PostgreSQL Source Code: src/backend/tcop/pquery.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
17
18#include <limits.h>
19
30
31
32
33
34
35
37
38
40 const char *sourceText,
51 bool isTopLevel, bool setHoldSnapshot,
54 bool isTopLevel, bool setHoldSnapshot,
59 long count,
62
63
64
65
66
69 const char *sourceText,
75 int instrument_options)
76{
78
81 qd->sourceText = sourceText;
83
86 qd->params = params;
88 qd->instrument_options = instrument_options;
89
90
95
96
98
99 return qd;
100}
101
102
103
104
105void
107{
108
110
111
114
115
117}
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136static void
138 const char *sourceText,
143{
145
146
147
148
151 dest, params, queryEnv, 0);
152
153
154
155
157
158
159
160
162
163
164
165
166 if (qc)
167 {
169
171 tag = CMDTAG_SELECT;
173 tag = CMDTAG_INSERT;
175 tag = CMDTAG_UPDATE;
177 tag = CMDTAG_DELETE;
179 tag = CMDTAG_MERGE;
180 else
181 tag = CMDTAG_UNKNOWN;
182
184 }
185
186
187
188
191
193}
194
195
196
197
198
199
200
201
202
203
206{
207 int nSetTag;
209
210
211
212
213
214
215
217 {
219
221 {
223
224 if (query->canSetTag)
225 {
227 {
228 if (query->hasModifyingCTE)
230 else
232 }
234 {
237
239 }
240 }
241 }
243 {
245
247 {
249 {
252 else
254 }
256 {
259
261 }
262 }
263 }
264 else
266 }
267
268
269
270
271
272
273 nSetTag = 0;
274 foreach(lc, stmts)
275 {
277
279 {
281
282 if (query->canSetTag)
283 {
284 if (++nSetTag > 1)
289 }
290 }
292 {
294
296 {
297 if (++nSetTag > 1)
302 }
303 }
304 else
306 }
307 if (nSetTag == 1)
309
310
312}
313
314
315
316
317
318
319
320
323{
324
326 return NIL;
327
329}
330
331
332
333
334
335
336
337
338
339
340
341
342
345{
346 if (stmt == NULL)
347 return NIL;
349 {
351
353 {
354
356 }
357 else
358 {
363 return NIL;
364 }
365 }
367 {
369
371 {
372
374 }
375 else
376 {
381 return NIL;
382 }
383 }
385 {
388
393 }
395 {
398
401 }
402 return NIL;
403}
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428void
430 int eflags, Snapshot snapshot)
431{
432 Portal saveActivePortal;
437 int myeflags;
438
441
442
443
444
449 {
454
456
457
459
460
461
462
464
465
466
467
469 {
471
472
473 if (snapshot)
475 else
477
478
479
480
481
482
483
484
485
486
487
488
489
490
496 params,
498 0);
499
500
501
502
503
504
507 else
508 myeflags = eflags;
509
510
511
512
514
515
516
517
519
520
521
522
524
525
526
527
529 portal->atEnd = false;
531
533 break;
534
537
538
539
540
541
542 {
544
548 }
549
550
551
552
554 portal->atEnd = false;
556 break;
557
559
560
561
562
563
564 {
566
569 }
570
571
572
573
575 portal->atEnd = false;
577 break;
578
580
582 break;
583 }
584 }
586 {
587
589
590
594
596 }
598
600
604
606}
607
608
609
610
611
612
613
614
615
616
617
618void
620{
621 int natts;
622 int i;
623
624
625 if (portal->tupDesc == NULL)
626 return;
630 natts * sizeof(int16));
631 if (nFormats > 1)
632 {
633
634 if (nFormats != natts)
636 (errcode(ERRCODE_PROTOCOL_VIOLATION),
637 errmsg("bind message has %d result formats but query has %d columns",
638 nFormats, natts)));
639 memcpy(portal->formats, formats, natts * sizeof(int16));
640 }
641 else if (nFormats > 0)
642 {
643
644 int16 format1 = formats[0];
645
646 for (i = 0; i < natts; i++)
647 portal->formats[i] = format1;
648 }
649 else
650 {
651
652 for (i = 0; i < natts; i++)
654 }
655}
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679bool
683{
684 bool result;
688 Portal saveActivePortal;
692
694
695 TRACE_POSTGRESQL_QUERY_EXECUTE_START();
696
697
698 if (qc)
700
702 {
704
706 }
707
708
709
710
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
734 {
739
741
743 {
748
749
750
751
752
753
756
757
758
759
761
762
763
764
765
766
767 if (qc && portal->qc.commandTag != CMDTAG_UNKNOWN)
768 {
771 }
772
773
775
776
777
778
779 result = portal->atEnd;
780 break;
781
784 dest, altdest, qc);
785
786
788
789
790 result = true;
791 break;
792
793 default:
794 elog(ERROR, "unrecognized portal strategy: %d",
796 result = false;
797 break;
798 }
799 }
801 {
802
804
805
806 if (saveMemoryContext == saveTopTransactionContext)
808 else
811 if (saveResourceOwner == saveTopTransactionResourceOwner)
813 else
816
818 }
820
821 if (saveMemoryContext == saveTopTransactionContext)
823 else
826 if (saveResourceOwner == saveTopTransactionResourceOwner)
828 else
831
833 ShowUsage("EXECUTOR STATISTICS");
834
835 TRACE_POSTGRESQL_QUERY_EXECUTE_DONE();
836
837 return result;
838}
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
860 bool forward,
861 long count,
863{
867
868
869
870
871
873
874
876
877
878
879
880
881
882
883 if (queryDesc)
885
886
887
888
889
890
891
892
893
894
895
896
897 if (forward)
898 {
899 if (portal->atEnd || count <= 0)
900 {
902 count = 0;
903 }
904 else
906
907
909 count = 0;
910
913 else
914 {
919 }
920
922 {
923 if (nprocessed > 0)
924 portal->atStart = false;
925 if (count == 0 || nprocessed < (uint64) count)
926 portal->atEnd = true;
928 }
929 }
930 else
931 {
934 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
935 errmsg("cursor can only scan forward"),
936 errhint("Declare it with SCROLL option to enable backward scan.")));
937
938 if (portal->atStart || count <= 0)
939 {
941 count = 0;
942 }
943 else
945
946
948 count = 0;
949
952 else
953 {
958 }
959
961 {
962 if (nprocessed > 0 && portal->atEnd)
963 {
964 portal->atEnd = false;
965 portal->portalPos++;
966 }
967 if (count == 0 || nprocessed < (uint64) count)
968 {
969 portal->atStart = true;
971 }
972 else
973 {
975 }
976 }
977 }
978
979 return nprocessed;
980}
981
982
983
984
985
986
987
988
989static void
991{
994
1001 false,
1002 NULL,
1003 NULL);
1004
1006 {
1009
1010
1011
1012
1013
1014
1015
1018 break;
1019
1022 isTopLevel, true, treceiver, &qc);
1023 break;
1024
1025 default:
1026 elog(ERROR, "unsupported portal strategy: %d",
1028 break;
1029 }
1030
1031
1032 if (qc.commandTag != CMDTAG_UNKNOWN)
1034
1035 treceiver->rDestroy(treceiver);
1036}
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1053{
1054 uint64 current_tuple_count = 0;
1056
1058
1060
1062 {
1063
1064 }
1065 else
1066 {
1068
1069 for (;;)
1070 {
1072 bool ok;
1073
1075
1077 slot);
1078
1080
1081 if (!ok)
1082 break;
1083
1084
1085
1086
1087
1088
1089 if (->receiveSlot(slot, dest))
1090 break;
1091
1093
1094
1095
1096
1097
1098
1099 current_tuple_count++;
1100 if (count && count == current_tuple_count)
1101 break;
1102 }
1103 }
1104
1106
1108
1109 return current_tuple_count;
1110}
1111
1112
1113
1114
1115
1116static void
1118 bool isTopLevel, bool setHoldSnapshot,
1120{
1121
1122
1123
1125 {
1127
1128
1129 if (setHoldSnapshot)
1130 {
1133 }
1134
1135
1136
1137
1138
1139
1140
1142
1144 }
1145 else
1147
1150 (portal->cplan != NULL),
1155 qc);
1156
1157
1159
1160
1161
1162
1163
1164
1165
1166
1168 {
1171 }
1173}
1174
1175
1176
1177
1178
1179
1180static void
1182 bool isTopLevel, bool setHoldSnapshot,
1185{
1186 bool active_snapshot_set = false;
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1203
1204
1205
1206
1207
1208 foreach(stmtlist_item, portal->stmts)
1209 {
1211
1212
1213
1214
1216
1218 {
1219
1220
1221
1222 TRACE_POSTGRESQL_QUERY_EXECUTE_START();
1223
1226
1227
1228
1229
1230
1231
1232
1233 if (!active_snapshot_set)
1234 {
1236
1237
1238 if (setHoldSnapshot)
1239 {
1242 }
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1254
1255
1256
1257
1258
1259
1260 active_snapshot_set = true;
1261 }
1262 else
1264
1266 {
1267
1273 }
1274 else
1275 {
1276
1281 altdest, NULL);
1282 }
1283
1285 ShowUsage("EXECUTOR STATISTICS");
1286
1287 TRACE_POSTGRESQL_QUERY_EXECUTE_DONE();
1288 }
1289 else
1290 {
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1303 {
1304 Assert(!active_snapshot_set);
1305
1308 }
1309 else
1310 {
1312
1314 altdest, NULL);
1315 }
1316 }
1317
1318
1319
1320
1322
1324
1325
1326
1327
1328
1329
1330
1331
1332
1334 break;
1335
1336
1337
1338
1339
1340 if (lnext(portal->stmts, stmtlist_item) != NULL)
1342 }
1343
1344
1345 if (active_snapshot_set)
1347
1348
1349
1350
1351
1352
1353
1354 if (qc &&
1358}
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1375 long count,
1377{
1379 Portal saveActivePortal;
1383
1385
1386
1387
1388
1390
1391
1392
1393
1398 {
1403
1405
1407 {
1410 break;
1411
1415
1416
1417
1418
1419
1422
1423
1424
1425
1427 break;
1428
1429 default:
1430 elog(ERROR, "unsupported portal strategy");
1431 result = 0;
1432 break;
1433 }
1434 }
1436 {
1437
1439
1440
1444
1446 }
1448
1450
1451
1453
1457
1458 return result;
1459}
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1473 long count,
1475{
1476 bool forward;
1477
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492 switch (fdirection)
1493 {
1495 if (count < 0)
1496 {
1498 count = -count;
1499 }
1500
1501 break;
1503 if (count < 0)
1504 {
1506 count = -count;
1507 }
1508
1509 break;
1511 if (count > 0)
1512 {
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1530 {
1532 if (count > 1)
1535 }
1536 else
1537 {
1538 long pos = (long) portal->portalPos;
1539
1541 pos++;
1542 if (count <= pos)
1545 else if (count > pos + 1)
1548 }
1550 }
1551 else if (count < 0)
1552 {
1553
1554
1555
1556
1557
1558
1559
1561 if (count < -1)
1564 }
1565 else
1566 {
1567
1568
1571 }
1572 break;
1574 if (count > 0)
1575 {
1576
1577
1578
1579 if (count > 1)
1582 }
1583 else if (count < 0)
1584 {
1585
1586
1587
1588
1589 if (count < -1)
1592 }
1593 else
1594 {
1595
1596
1598 }
1599 break;
1600 default:
1602 break;
1603 }
1604
1605
1606
1607
1608
1610
1611
1612
1613
1614 if (count == 0)
1615 {
1616 bool on_row;
1617
1618
1619 on_row = (!portal->atStart && !portal->atEnd);
1620
1622 {
1623
1624 return on_row ? 1 : 0;
1625 }
1626 else
1627 {
1628
1629
1630
1631
1632
1633
1634
1635 if (on_row)
1636 {
1638
1639 count = 1;
1640 forward = true;
1641 }
1642 }
1643 }
1644
1645
1646
1647
1649 {
1651
1652 if (result > 0 && !portal->atEnd)
1653 result--;
1655 return result;
1656 }
1657
1659}
1660
1661
1662
1663
1664static void
1666{
1668
1669
1670
1671
1672
1674 return;
1675
1676
1679 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1680 errmsg("cursor can only scan forward"),
1681 errhint("Declare it with SCROLL option to enable backward scan.")));
1682
1683
1685 {
1687
1691 }
1692
1693
1695 if (queryDesc)
1696 {
1700 }
1701
1703 portal->atEnd = false;
1705}
1706
1707
1708
1709
1710bool
1712{
1714
1715
1716 if (utilityStmt == NULL)
1717 return true;
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1737
1744 return false;
1745
1746 return true;
1747}
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759void
1761{
1763
1764
1765
1766
1767
1768
1770 return;
1771
1772
1774 if (unlikely(portal == NULL))
1775 elog(ERROR, "cannot execute SQL without an outer snapshot or portal");
1777
1778
1779
1780
1781
1782
1783
1785
1787}
PreparedStatement * FetchPreparedStatement(const char *stmt_name, bool throwError)
List * FetchPreparedStatementTargetList(PreparedStatement *stmt)
void InitializeQueryCompletion(QueryCompletion *qc)
static void SetQueryCompletion(QueryCompletion *qc, CommandTag commandTag, uint64 nprocessed)
static void CopyQueryCompletion(QueryCompletion *dst, const QueryCompletion *src)
DestReceiver * CreateDestReceiver(CommandDest dest)
DestReceiver * None_Receiver
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
void ExecutorEnd(QueryDesc *queryDesc)
void ExecutorFinish(QueryDesc *queryDesc)
void ExecutorRewind(QueryDesc *queryDesc)
void ExecutorStart(QueryDesc *queryDesc, int eflags)
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
TupleDesc ExecCleanTypeFromTL(List *targetList)
const TupleTableSlotOps TTSOpsMinimalTuple
#define EXEC_FLAG_BACKWARD
#define palloc_object(type)
Assert(PointerIsAligned(start, uint64))
if(TABLE==NULL||TABLE_index==NULL)
void * MemoryContextAlloc(MemoryContext context, Size size)
MemoryContext TopTransactionContext
void pfree(void *pointer)
void MemoryContextDeleteChildren(MemoryContext context)
MemoryContext CurrentMemoryContext
MemoryContext PortalContext
#define CHECK_FOR_INTERRUPTS()
#define IsA(nodeptr, _type_)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
#define CURSOR_OPT_SCROLL
#define CURSOR_OPT_NO_SCROLL
#define lfirst_node(type, lc)
static int list_length(const List *l)
#define linitial_node(type, l)
static ListCell * lnext(const List *l, const ListCell *c)
void MarkPortalDone(Portal portal)
void MarkPortalFailed(Portal portal)
PlannedStmt * PortalGetPrimaryStmt(Portal portal)
void MarkPortalActive(Portal portal)
Portal GetPortalByName(const char *name)
void PortalCreateHoldStore(Portal portal)
void ShowUsage(const char *title)
void FreeQueryDesc(QueryDesc *qdesc)
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)
PortalStrategy ChoosePortalStrategy(List *stmts)
static void PortalRunMulti(Portal portal, bool isTopLevel, bool setHoldSnapshot, DestReceiver *dest, DestReceiver *altdest, QueryCompletion *qc)
static void FillPortalStore(Portal portal, bool isTopLevel)
bool PlannedStmtRequiresSnapshot(PlannedStmt *pstmt)
void EnsurePortalSnapshotExists(void)
void PortalSetResultFormat(Portal portal, int nFormats, int16 *formats)
void PortalStart(Portal portal, ParamListInfo params, int eflags, Snapshot snapshot)
static uint64 PortalRunSelect(Portal portal, bool forward, long count, DestReceiver *dest)
static uint64 RunFromStore(Portal portal, ScanDirection direction, uint64 count, DestReceiver *dest)
List * FetchStatementTargetList(Node *stmt)
uint64 PortalRunFetch(Portal portal, FetchDirection fdirection, long count, DestReceiver *dest)
static void ProcessQuery(PlannedStmt *plan, const char *sourceText, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
List * FetchPortalTargetList(Portal portal)
bool PortalRun(Portal portal, long count, bool isTopLevel, DestReceiver *dest, DestReceiver *altdest, QueryCompletion *qc)
static uint64 DoPortalRunFetch(Portal portal, FetchDirection fdirection, long count, DestReceiver *dest)
static void DoPortalRewind(Portal portal)
static void PortalRunUtility(Portal portal, PlannedStmt *pstmt, bool isTopLevel, bool setHoldSnapshot, DestReceiver *dest, QueryCompletion *qc)
ResourceOwner TopTransactionResourceOwner
ResourceOwner CurrentResourceOwner
#define ScanDirectionIsForward(direction)
#define ScanDirectionIsNoMovement(direction)
@ NoMovementScanDirection
Snapshot GetTransactionSnapshot(void)
void UnregisterSnapshot(Snapshot snapshot)
void PushActiveSnapshot(Snapshot snapshot)
void UpdateActiveSnapshotCommandId(void)
bool ActiveSnapshotSet(void)
Snapshot RegisterSnapshot(Snapshot snapshot)
void PopActiveSnapshot(void)
void PushCopiedSnapshot(Snapshot snapshot)
void PushActiveSnapshotWithLevel(Snapshot snapshot, int snap_level)
Snapshot GetActiveSnapshot(void)
MemoryContext holdContext
QueryEnvironment * queryEnv
MemoryContext portalContext
ParamListInfo portalParams
Tuplestorestate * holdStore
PlannedStmt * plannedstmt
struct Instrumentation * totaltime
QueryEnvironment * queryEnv
Snapshot crosscheck_snapshot
void(* rDestroy)(DestReceiver *self)
void SetTuplestoreDestReceiverParams(DestReceiver *self, Tuplestorestate *tStore, MemoryContext tContext, bool detoast, TupleDesc target_tupdesc, const char *map_failure_msg)
bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, bool copy, TupleTableSlot *slot)
void tuplestore_rescan(Tuplestorestate *state)
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
void ProcessUtility(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
bool UtilityReturnsTuples(Node *parsetree)
TupleDesc UtilityTupleDescriptor(Node *parsetree)
@ PROCESS_UTILITY_TOPLEVEL
void CommandCounterIncrement(void)