PostgreSQL Source Code: src/backend/executor/nodeMergejoin.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
94
100
101
102
103
104
105#define EXEC_MJ_INITIALIZE_OUTER 1
106#define EXEC_MJ_INITIALIZE_INNER 2
107#define EXEC_MJ_JOINTUPLES 3
108#define EXEC_MJ_NEXTOUTER 4
109#define EXEC_MJ_TESTOUTER 5
110#define EXEC_MJ_NEXTINNER 6
111#define EXEC_MJ_SKIP_TEST 7
112#define EXEC_MJ_SKIPOUTER_ADVANCE 8
113#define EXEC_MJ_SKIPINNER_ADVANCE 9
114#define EXEC_MJ_ENDOUTER 10
115#define EXEC_MJ_ENDINNER 11
116
117
118
119
121{
122
125
126
127
128
129
134
135
136
137
138
141
142
143typedef enum
144{
149
150
151#define MarkInnerTuple(innerTupleSlot, mergestate) \
152 ExecCopySlot((mergestate)->mj_MarkedTupleSlot, (innerTupleSlot))
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
176 Oid *mergefamilies,
177 Oid *mergecollations,
178 bool *mergereversals,
179 bool *mergenullsfirst,
181{
183 int nClauses = list_length(mergeclauses);
184 int iClause;
186
188
189 iClause = 0;
190 foreach(cl, mergeclauses)
191 {
194 Oid opfamily = mergefamilies[iClause];
195 Oid collation = mergecollations[iClause];
196 bool reversed = mergereversals[iClause];
197 bool nulls_first = mergenullsfirst[iClause];
198 int op_strategy;
199 Oid op_lefttype;
200 Oid op_righttype;
201 Oid sortfunc;
202
204 elog(ERROR, "mergejoin clause is not an OpExpr");
205
206
207
208
211
212
217
218
220 &op_strategy,
221 &op_lefttype,
222 &op_righttype);
224 elog(ERROR, "cannot merge using non-equality operator %u",
226
227
228
229
230
231
232
234
235
238 op_lefttype,
239 op_righttype,
242 {
243
245 }
247 {
248
250 op_lefttype,
251 op_righttype,
253 if ((sortfunc))
254 elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
255 BTORDER_PROC, op_lefttype, op_righttype, opfamily);
256
258 }
259
260 iClause++;
261 }
262
263 return clauses;
264}
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
290{
293 int i;
295
296
299
301
303
305
307 {
309
313 {
314
320 }
321 }
322
324
325 return result;
326}
327
328
329
330
331
332
333
334
337{
340 int i;
342
343
346
348
350
352
354 {
356
360 {
361
367 }
368 }
369
371
372 return result;
373}
374
375
376
377
378
379
380
381
382
383
384
385static int
387{
388 int result = 0;
389 bool nulleqnull = false;
391 int i;
393
394
395
396
397
399
401
403 {
405
406
407
408
410 {
411 nulleqnull = true;
412 continue;
413 }
414
417 &clause->ssup);
418
419 if (result != 0)
420 break;
421 }
422
423
424
425
426
427
428
429
430
431
432 if (result == 0 &&
434 result = 1;
435
437
438 return result;
439}
440
441
442
443
444
445
448{
451
453
456
457 if (ExecQual(otherqual, econtext))
458 {
459
460
461
462
463 MJ_printf("ExecMergeJoin: returning outer fill tuple\n");
464
466 }
467 else
469
470 return NULL;
471}
472
473
474
475
476
479{
482
484
487
488 if (ExecQual(otherqual, econtext))
489 {
490
491
492
493
494 MJ_printf("ExecMergeJoin: returning inner fill tuple\n");
495
497 }
498 else
500
501 return NULL;
502}
503
504
505
506
507
508
509
510
511
512
513static bool
515{
517
518 foreach(lc, qual)
519 {
521
522 if (!con || (con, Const))
523 return false;
524 if (con->constisnull || (con->constvalue))
525 *is_const_false = true;
526 }
527 return true;
528}
529
530
531
532
533
534
535
536
537
538#ifdef EXEC_MERGEJOINDEBUG
539
540static void
542{
544
545 printf("==== outer tuple ====\n");
548 else
550}
551
552static void
554{
556
557 printf("==== inner tuple ====\n");
560 else
562}
563
564static void
566{
568
569 printf("==== marked tuple ====\n");
572 else
574}
575
576static void
578{
579 printf("******** ExecMergeTupleDump ********\n");
580
581 ExecMergeTupleDumpOuter(mergestate);
582 ExecMergeTupleDumpInner(mergestate);
583 ExecMergeTupleDumpMarked(mergestate);
584
585 printf("********\n");
586}
587#endif
588
589
590
591
592
595{
599 bool qualResult;
600 int compareResult;
606 bool doFillOuter;
607 bool doFillInner;
608
610
611
612
613
618 otherqual = node->js.ps.qual;
621
622
623
624
625
627
628
629
630
631 for (;;)
632 {
634
635
636
637
639 {
640
641
642
643
644
645
646
648 MJ_printf("ExecMergeJoin: EXEC_MJ_INITIALIZE_OUTER\n");
649
652
653
655 {
657
659 break;
661
662 if (doFillOuter)
663 {
664
665
666
667
668
670
672 if (result)
673 return result;
674 }
675 break;
677
678 MJ_printf("ExecMergeJoin: nothing in outer subplan\n");
679 if (doFillInner)
680 {
681
682
683
684
685
688 break;
689 }
690
691 return NULL;
692 }
693 break;
694
696 MJ_printf("ExecMergeJoin: EXEC_MJ_INITIALIZE_INNER\n");
697
700
701
703 {
705
706
707
708
709
711 break;
713
716
717 if (doFillInner)
718 {
719
720
721
722
723
725
727 if (result)
728 return result;
729 }
730 break;
732
733 MJ_printf("ExecMergeJoin: nothing in inner subplan\n");
734 if (doFillOuter)
735 {
736
737
738
739
740
741
742
745 break;
746 }
747
748 return NULL;
749 }
750 break;
751
752
753
754
755
756
758 MJ_printf("ExecMergeJoin: EXEC_MJ_JOINTUPLES\n");
759
760
761
762
763
764
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
785
786 qualResult = (joinqual == NULL ||
787 ExecQual(joinqual, econtext));
789
790 if (qualResult)
791 {
794
795
797 {
799 break;
800 }
801
802
803
804
805
806
809
810
811
812
813
814
815
817 break;
818
819 qualResult = (otherqual == NULL ||
820 ExecQual(otherqual, econtext));
822
823 if (qualResult)
824 {
825
826
827
828
829 MJ_printf("ExecMergeJoin: returning tuple\n");
830
832 }
833 else
835 }
836 else
838 break;
839
840
841
842
843
844
845
846
847
849 MJ_printf("ExecMergeJoin: EXEC_MJ_NEXTINNER\n");
850
852 {
853
854
855
856
858
860
862 if (result)
863 return result;
864 }
865
866
867
868
869
870
871
872
873
878
879
881 {
883
884
885
886
887
888
889
890
891
892
893
896
897 if (compareResult == 0)
899 else if (compareResult < 0)
901 else
902 elog(ERROR, "mergejoin input data is out of order");
903 break;
905
906
907
908
909
910
912 break;
914
915
916
917
918
919
920
921
922
925 break;
926 }
927 break;
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
950 MJ_printf("ExecMergeJoin: EXEC_MJ_NEXTOUTER\n");
951
953 {
954
955
956
957
959
961
963 if (result)
964 return result;
965 }
966
967
968
969
974
975
977 {
979
981 break;
983
985 break;
987
988 MJ_printf("ExecMergeJoin: end of outer subplan\n");
990 if (doFillInner && (innerTupleSlot))
991 {
992
993
994
995
997 break;
998 }
999
1000 return NULL;
1001 }
1002 break;
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1040 MJ_printf("ExecMergeJoin: EXEC_MJ_TESTOUTER\n");
1041
1042
1043
1044
1045
1046
1049
1050 compareResult = MJCompare(node);
1052
1053 if (compareResult == 0)
1054 {
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1077 {
1079
1080
1081
1082
1083
1084
1085
1087
1088 }
1089
1091 }
1092 else if (compareResult > 0)
1093 {
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1112
1113
1115 {
1117
1119 break;
1121
1122
1123
1124
1125
1126
1128 break;
1130
1131 if (doFillOuter)
1132 {
1133
1134
1135
1136
1138 break;
1139 }
1140
1141 return NULL;
1142 }
1143 }
1144 else
1145 elog(ERROR, "mergejoin input data is out of order");
1146 break;
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1178 MJ_printf("ExecMergeJoin: EXEC_MJ_SKIP_TEST\n");
1179
1180
1181
1182
1183
1184
1185 compareResult = MJCompare(node);
1187
1188 if (compareResult == 0)
1189 {
1192
1194
1196 }
1197 else if (compareResult < 0)
1199 else
1200
1202 break;
1203
1204
1205
1206
1207
1208
1209
1210
1212 MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPOUTER_ADVANCE\n");
1213
1215 {
1216
1217
1218
1219
1221
1223
1225 if (result)
1226 return result;
1227 }
1228
1229
1230
1231
1236
1237
1239 {
1241
1243 break;
1245
1247 break;
1249
1250 MJ_printf("ExecMergeJoin: end of outer subplan\n");
1252 if (doFillInner && (innerTupleSlot))
1253 {
1254
1255
1256
1257
1259 break;
1260 }
1261
1262 return NULL;
1263 }
1264 break;
1265
1266
1267
1268
1269
1270
1271
1272
1274 MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPINNER_ADVANCE\n");
1275
1277 {
1278
1279
1280
1281
1283
1285
1287 if (result)
1288 return result;
1289 }
1290
1291
1294
1295
1296
1297
1302
1303
1305 {
1307
1309 break;
1311
1312
1313
1314
1315
1317 break;
1319
1320 MJ_printf("ExecMergeJoin: end of inner subplan\n");
1322 if (doFillOuter && (outerTupleSlot))
1323 {
1324
1325
1326
1327
1329 break;
1330 }
1331
1332 return NULL;
1333 }
1334 break;
1335
1336
1337
1338
1339
1340
1342 MJ_printf("ExecMergeJoin: EXEC_MJ_ENDOUTER\n");
1343
1344 Assert(doFillInner);
1345
1347 {
1348
1349
1350
1351
1353
1355
1357 if (result)
1358 return result;
1359 }
1360
1361
1364
1365
1366
1367
1372
1374 {
1375 MJ_printf("ExecMergeJoin: end of inner subplan\n");
1376 return NULL;
1377 }
1378
1379
1380 break;
1381
1382
1383
1384
1385
1386
1388 MJ_printf("ExecMergeJoin: EXEC_MJ_ENDINNER\n");
1389
1390 Assert(doFillOuter);
1391
1393 {
1394
1395
1396
1397
1399
1401
1403 if (result)
1404 return result;
1405 }
1406
1407
1408
1409
1414
1416 {
1417 MJ_printf("ExecMergeJoin: end of outer subplan\n");
1418 return NULL;
1419 }
1420
1421
1422 break;
1423
1424
1425
1426
1427 default:
1428 elog(ERROR, "unrecognized mergejoin state: %d",
1430 }
1431 }
1432}
1433
1434
1435
1436
1437
1440{
1443 innerDesc;
1445
1446
1448
1449 MJ1_printf("ExecInitMergeJoin: %s\n",
1450 "initializing node");
1451
1452
1453
1454
1457 mergestate->js.ps.state = estate;
1461
1462
1463
1464
1465
1466
1468
1469
1470
1471
1472
1473
1476
1477
1478
1479
1480
1481
1482
1483
1486
1491 eflags :
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1513 else
1515
1516
1517
1518
1521
1522
1523
1524
1527 innerOps);
1528
1529
1530
1531
1536
1537
1538
1539
1540
1543
1544
1546 {
1551 break;
1558 break;
1565
1566
1567
1568
1569
1573 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1574 errmsg("RIGHT JOIN is only supported with merge-joinable join conditions")));
1575 break;
1583
1584
1585
1586
1587
1591 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1592 errmsg("FULL JOIN is only supported with merge-joinable join conditions")));
1593 break;
1594 default:
1595 elog(ERROR, "unrecognized join type: %d",
1597 }
1598
1599
1600
1601
1604 node->mergeFamilies,
1605 node->mergeCollations,
1606 node->mergeReversals,
1607 node->mergeNullsFirst,
1609
1610
1611
1612
1618
1619
1620
1621
1622 MJ1_printf("ExecInitMergeJoin: %s\n",
1623 "node initialized");
1624
1625 return mergestate;
1626}
1627
1628
1629
1630
1631
1632
1633
1634
1635void
1637{
1638 MJ1_printf("ExecEndMergeJoin: %s\n",
1639 "ending node processing");
1640
1641
1642
1643
1646
1647 MJ1_printf("ExecEndMergeJoin: %s\n",
1648 "node processing ended");
1649}
1650
1651void
1653{
1656
1658
1664
1665
1666
1667
1668
1669 if (outerPlan->chgParam == NULL)
1671 if (innerPlan->chgParam == NULL)
1673}
CompareType IndexAmTranslateStrategy(StrategyNumber strategy, Oid amoid, Oid opfamily, bool missing_ok)
#define OidIsValid(objectId)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
void ExecMarkPos(PlanState *node)
void ExecReScan(PlanState *node)
void ExecRestrPos(PlanState *node)
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
ExprState * ExecInitQual(List *qual, PlanState *parent)
void ExecEndNode(PlanState *node)
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
const TupleTableSlotOps TTSOpsVirtual
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
TupleTableSlot * ExecInitNullTupleSlot(EState *estate, TupleDesc tupType, const TupleTableSlotOps *tts_ops)
TupleDesc ExecGetResultType(PlanState *planstate)
ExprContext * CreateExprContext(EState *estate)
void ExecAssignExprContext(EState *estate, PlanState *planstate)
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
const TupleTableSlotOps * ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
#define MJ_DEBUG_COMPARE(res)
#define MJ_DEBUG_QUAL(clause, res)
#define MJ_DEBUG_PROC_NODE(slot)
#define MJ_debugtup(slot)
#define InstrCountFiltered1(node, delta)
#define outerPlanState(node)
#define InstrCountFiltered2(node, delta)
#define innerPlanState(node)
struct MergeJoinClauseData * MergeJoinClause
#define EXEC_FLAG_BACKWARD
static TupleTableSlot * ExecProject(ProjectionInfo *projInfo)
#define ResetExprContext(econtext)
static bool ExecQual(ExprState *state, ExprContext *econtext)
static TupleTableSlot * ExecProcNode(PlanState *node)
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
#define OidFunctionCall1(functionId, arg1)
Assert(PointerIsAligned(start, uint64))
void get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op, int *strategy, Oid *lefttype, Oid *righttype)
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Oid get_opfamily_method(Oid opfid)
void * palloc0(Size size)
MemoryContext CurrentMemoryContext
#define CHECK_FOR_INTERRUPTS()
#define BTSORTSUPPORT_PROC
static MergeJoinClause MJExamineQuals(List *mergeclauses, Oid *mergefamilies, Oid *mergecollations, bool *mergereversals, bool *mergenullsfirst, PlanState *parent)
static int MJCompare(MergeJoinState *mergestate)
struct MergeJoinClauseData MergeJoinClauseData
#define EXEC_MJ_SKIP_TEST
#define EXEC_MJ_JOINTUPLES
static TupleTableSlot * ExecMergeJoin(PlanState *pstate)
#define EXEC_MJ_SKIPOUTER_ADVANCE
#define MarkInnerTuple(innerTupleSlot, mergestate)
#define EXEC_MJ_TESTOUTER
static TupleTableSlot * MJFillOuter(MergeJoinState *node)
void ExecReScanMergeJoin(MergeJoinState *node)
static MJEvalResult MJEvalOuterValues(MergeJoinState *mergestate)
#define EXEC_MJ_INITIALIZE_OUTER
#define EXEC_MJ_SKIPINNER_ADVANCE
MergeJoinState * ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
#define EXEC_MJ_NEXTOUTER
void ExecEndMergeJoin(MergeJoinState *node)
#define EXEC_MJ_INITIALIZE_INNER
static MJEvalResult MJEvalInnerValues(MergeJoinState *mergestate, TupleTableSlot *innerslot)
#define EXEC_MJ_NEXTINNER
static TupleTableSlot * MJFillInner(MergeJoinState *node)
static bool check_constant_qual(List *qual, bool *is_const_false)
#define IsA(nodeptr, _type_)
#define castNode(_type_, nodeptr)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
static int list_length(const List *l)
static bool DatumGetBool(Datum X)
static Datum PointerGetDatum(const void *X)
void PrepareSortSupportComparisonShim(Oid cmpFunc, SortSupport ssup)
static int ApplySortComparator(Datum datum1, bool isNull1, Datum datum2, bool isNull2, SortSupport ssup)
MemoryContext ecxt_per_tuple_memory
TupleTableSlot * ecxt_innertuple
TupleTableSlot * ecxt_outertuple
TupleTableSlot * mj_MarkedTupleSlot
TupleTableSlot * mj_NullInnerTupleSlot
ExprContext * mj_InnerEContext
TupleTableSlot * mj_NullOuterTupleSlot
MergeJoinClause mj_Clauses
TupleTableSlot * mj_InnerTupleSlot
ExprContext * mj_OuterEContext
TupleTableSlot * mj_OuterTupleSlot
ExprContext * ps_ExprContext
ProjectionInfo * ps_ProjInfo
ExecProcNodeMtd ExecProcNode
int(* comparator)(Datum x, Datum y, SortSupport ssup)
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)