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

132 bool lisnull;

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 (OidIsValid(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 || IsA(con, Const))

523 return false;

524 if (con->constisnull || DatumGetBool(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 && TupIsNull(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 && TupIsNull(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 && TupIsNull(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)