00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "postgres.h"
00026
00027 #include "access/nbtree.h"
00028 #include "access/relscan.h"
00029 #include "executor/execdebug.h"
00030 #include "executor/nodeIndexscan.h"
00031 #include "optimizer/clauses.h"
00032 #include "utils/array.h"
00033 #include "utils/lsyscache.h"
00034 #include "utils/memutils.h"
00035 #include "utils/rel.h"
00036
00037
00038 static TupleTableSlot *IndexNext(IndexScanState *node);
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 static TupleTableSlot *
00049 IndexNext(IndexScanState *node)
00050 {
00051 EState *estate;
00052 ExprContext *econtext;
00053 ScanDirection direction;
00054 IndexScanDesc scandesc;
00055 HeapTuple tuple;
00056 TupleTableSlot *slot;
00057
00058
00059
00060
00061 estate = node->ss.ps.state;
00062 direction = estate->es_direction;
00063
00064 if (ScanDirectionIsBackward(((IndexScan *) node->ss.ps.plan)->indexorderdir))
00065 {
00066 if (ScanDirectionIsForward(direction))
00067 direction = BackwardScanDirection;
00068 else if (ScanDirectionIsBackward(direction))
00069 direction = ForwardScanDirection;
00070 }
00071 scandesc = node->iss_ScanDesc;
00072 econtext = node->ss.ps.ps_ExprContext;
00073 slot = node->ss.ss_ScanTupleSlot;
00074
00075
00076
00077
00078 while ((tuple = index_getnext(scandesc, direction)) != NULL)
00079 {
00080
00081
00082
00083
00084
00085 ExecStoreTuple(tuple,
00086 slot,
00087 scandesc->xs_cbuf,
00088 false);
00089
00090
00091
00092
00093
00094 if (scandesc->xs_recheck)
00095 {
00096 econtext->ecxt_scantuple = slot;
00097 ResetExprContext(econtext);
00098 if (!ExecQual(node->indexqualorig, econtext, false))
00099 {
00100
00101 InstrCountFiltered2(node, 1);
00102 continue;
00103 }
00104 }
00105
00106 return slot;
00107 }
00108
00109
00110
00111
00112
00113 return ExecClearTuple(slot);
00114 }
00115
00116
00117
00118
00119 static bool
00120 IndexRecheck(IndexScanState *node, TupleTableSlot *slot)
00121 {
00122 ExprContext *econtext;
00123
00124
00125
00126
00127 econtext = node->ss.ps.ps_ExprContext;
00128
00129
00130 econtext->ecxt_scantuple = slot;
00131
00132 ResetExprContext(econtext);
00133
00134 return ExecQual(node->indexqualorig, econtext, false);
00135 }
00136
00137
00138
00139
00140
00141 TupleTableSlot *
00142 ExecIndexScan(IndexScanState *node)
00143 {
00144
00145
00146
00147 if (node->iss_NumRuntimeKeys != 0 && !node->iss_RuntimeKeysReady)
00148 ExecReScan((PlanState *) node);
00149
00150 return ExecScan(&node->ss,
00151 (ExecScanAccessMtd) IndexNext,
00152 (ExecScanRecheckMtd) IndexRecheck);
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 void
00167 ExecReScanIndexScan(IndexScanState *node)
00168 {
00169
00170
00171
00172
00173
00174
00175
00176 if (node->iss_NumRuntimeKeys != 0)
00177 {
00178 ExprContext *econtext = node->iss_RuntimeContext;
00179
00180 ResetExprContext(econtext);
00181 ExecIndexEvalRuntimeKeys(econtext,
00182 node->iss_RuntimeKeys,
00183 node->iss_NumRuntimeKeys);
00184 }
00185 node->iss_RuntimeKeysReady = true;
00186
00187
00188 index_rescan(node->iss_ScanDesc,
00189 node->iss_ScanKeys, node->iss_NumScanKeys,
00190 node->iss_OrderByKeys, node->iss_NumOrderByKeys);
00191
00192 ExecScanReScan(&node->ss);
00193 }
00194
00195
00196
00197
00198
00199
00200 void
00201 ExecIndexEvalRuntimeKeys(ExprContext *econtext,
00202 IndexRuntimeKeyInfo *runtimeKeys, int numRuntimeKeys)
00203 {
00204 int j;
00205 MemoryContext oldContext;
00206
00207
00208 oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
00209
00210 for (j = 0; j < numRuntimeKeys; j++)
00211 {
00212 ScanKey scan_key = runtimeKeys[j].scan_key;
00213 ExprState *key_expr = runtimeKeys[j].key_expr;
00214 Datum scanvalue;
00215 bool isNull;
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 scanvalue = ExecEvalExpr(key_expr,
00235 econtext,
00236 &isNull,
00237 NULL);
00238 if (isNull)
00239 {
00240 scan_key->sk_argument = scanvalue;
00241 scan_key->sk_flags |= SK_ISNULL;
00242 }
00243 else
00244 {
00245 if (runtimeKeys[j].key_toastable)
00246 scanvalue = PointerGetDatum(PG_DETOAST_DATUM(scanvalue));
00247 scan_key->sk_argument = scanvalue;
00248 scan_key->sk_flags &= ~SK_ISNULL;
00249 }
00250 }
00251
00252 MemoryContextSwitchTo(oldContext);
00253 }
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263 bool
00264 ExecIndexEvalArrayKeys(ExprContext *econtext,
00265 IndexArrayKeyInfo *arrayKeys, int numArrayKeys)
00266 {
00267 bool result = true;
00268 int j;
00269 MemoryContext oldContext;
00270
00271
00272 oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
00273
00274 for (j = 0; j < numArrayKeys; j++)
00275 {
00276 ScanKey scan_key = arrayKeys[j].scan_key;
00277 ExprState *array_expr = arrayKeys[j].array_expr;
00278 Datum arraydatum;
00279 bool isNull;
00280 ArrayType *arrayval;
00281 int16 elmlen;
00282 bool elmbyval;
00283 char elmalign;
00284 int num_elems;
00285 Datum *elem_values;
00286 bool *elem_nulls;
00287
00288
00289
00290
00291
00292 arraydatum = ExecEvalExpr(array_expr,
00293 econtext,
00294 &isNull,
00295 NULL);
00296 if (isNull)
00297 {
00298 result = false;
00299 break;
00300 }
00301 arrayval = DatumGetArrayTypeP(arraydatum);
00302
00303 get_typlenbyvalalign(ARR_ELEMTYPE(arrayval),
00304 &elmlen, &elmbyval, &elmalign);
00305 deconstruct_array(arrayval,
00306 ARR_ELEMTYPE(arrayval),
00307 elmlen, elmbyval, elmalign,
00308 &elem_values, &elem_nulls, &num_elems);
00309 if (num_elems <= 0)
00310 {
00311 result = false;
00312 break;
00313 }
00314
00315
00316
00317
00318
00319
00320 arrayKeys[j].elem_values = elem_values;
00321 arrayKeys[j].elem_nulls = elem_nulls;
00322 arrayKeys[j].num_elems = num_elems;
00323 scan_key->sk_argument = elem_values[0];
00324 if (elem_nulls[0])
00325 scan_key->sk_flags |= SK_ISNULL;
00326 else
00327 scan_key->sk_flags &= ~SK_ISNULL;
00328 arrayKeys[j].next_elem = 1;
00329 }
00330
00331 MemoryContextSwitchTo(oldContext);
00332
00333 return result;
00334 }
00335
00336
00337
00338
00339
00340
00341
00342
00343 bool
00344 ExecIndexAdvanceArrayKeys(IndexArrayKeyInfo *arrayKeys, int numArrayKeys)
00345 {
00346 bool found = false;
00347 int j;
00348
00349
00350
00351
00352
00353
00354
00355 for (j = numArrayKeys - 1; j >= 0; j--)
00356 {
00357 ScanKey scan_key = arrayKeys[j].scan_key;
00358 int next_elem = arrayKeys[j].next_elem;
00359 int num_elems = arrayKeys[j].num_elems;
00360 Datum *elem_values = arrayKeys[j].elem_values;
00361 bool *elem_nulls = arrayKeys[j].elem_nulls;
00362
00363 if (next_elem >= num_elems)
00364 {
00365 next_elem = 0;
00366 found = false;
00367 }
00368 else
00369 found = true;
00370 scan_key->sk_argument = elem_values[next_elem];
00371 if (elem_nulls[next_elem])
00372 scan_key->sk_flags |= SK_ISNULL;
00373 else
00374 scan_key->sk_flags &= ~SK_ISNULL;
00375 arrayKeys[j].next_elem = next_elem + 1;
00376 if (found)
00377 break;
00378 }
00379
00380 return found;
00381 }
00382
00383
00384
00385
00386
00387
00388 void
00389 ExecEndIndexScan(IndexScanState *node)
00390 {
00391 Relation indexRelationDesc;
00392 IndexScanDesc indexScanDesc;
00393 Relation relation;
00394
00395
00396
00397
00398 indexRelationDesc = node->iss_RelationDesc;
00399 indexScanDesc = node->iss_ScanDesc;
00400 relation = node->ss.ss_currentRelation;
00401
00402
00403
00404
00405 #ifdef NOT_USED
00406 ExecFreeExprContext(&node->ss.ps);
00407 if (node->iss_RuntimeContext)
00408 FreeExprContext(node->iss_RuntimeContext, true);
00409 #endif
00410
00411
00412
00413
00414 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
00415 ExecClearTuple(node->ss.ss_ScanTupleSlot);
00416
00417
00418
00419
00420 if (indexScanDesc)
00421 index_endscan(indexScanDesc);
00422 if (indexRelationDesc)
00423 index_close(indexRelationDesc, NoLock);
00424
00425
00426
00427
00428 ExecCloseScanRelation(relation);
00429 }
00430
00431
00432
00433
00434
00435 void
00436 ExecIndexMarkPos(IndexScanState *node)
00437 {
00438 index_markpos(node->iss_ScanDesc);
00439 }
00440
00441
00442
00443
00444
00445 void
00446 ExecIndexRestrPos(IndexScanState *node)
00447 {
00448 index_restrpos(node->iss_ScanDesc);
00449 }
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 IndexScanState *
00463 ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
00464 {
00465 IndexScanState *indexstate;
00466 Relation currentRelation;
00467 bool relistarget;
00468
00469
00470
00471
00472 indexstate = makeNode(IndexScanState);
00473 indexstate->ss.ps.plan = (Plan *) node;
00474 indexstate->ss.ps.state = estate;
00475
00476
00477
00478
00479
00480
00481 ExecAssignExprContext(estate, &indexstate->ss.ps);
00482
00483 indexstate->ss.ps.ps_TupFromTlist = false;
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 indexstate->ss.ps.targetlist = (List *)
00496 ExecInitExpr((Expr *) node->scan.plan.targetlist,
00497 (PlanState *) indexstate);
00498 indexstate->ss.ps.qual = (List *)
00499 ExecInitExpr((Expr *) node->scan.plan.qual,
00500 (PlanState *) indexstate);
00501 indexstate->indexqualorig = (List *)
00502 ExecInitExpr((Expr *) node->indexqualorig,
00503 (PlanState *) indexstate);
00504
00505
00506
00507
00508 ExecInitResultTupleSlot(estate, &indexstate->ss.ps);
00509 ExecInitScanTupleSlot(estate, &indexstate->ss);
00510
00511
00512
00513
00514 currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
00515
00516 indexstate->ss.ss_currentRelation = currentRelation;
00517 indexstate->ss.ss_currentScanDesc = NULL;
00518
00519
00520
00521
00522 ExecAssignScanType(&indexstate->ss, RelationGetDescr(currentRelation));
00523
00524
00525
00526
00527 ExecAssignResultTypeFromTL(&indexstate->ss.ps);
00528 ExecAssignScanProjectionInfo(&indexstate->ss);
00529
00530
00531
00532
00533
00534
00535 if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
00536 return indexstate;
00537
00538
00539
00540
00541
00542
00543
00544
00545 relistarget = ExecRelationIsTargetRelation(estate, node->scan.scanrelid);
00546 indexstate->iss_RelationDesc = index_open(node->indexid,
00547 relistarget ? NoLock : AccessShareLock);
00548
00549
00550
00551
00552 indexstate->iss_RuntimeKeysReady = false;
00553 indexstate->iss_RuntimeKeys = NULL;
00554 indexstate->iss_NumRuntimeKeys = 0;
00555
00556
00557
00558
00559 ExecIndexBuildScanKeys((PlanState *) indexstate,
00560 indexstate->iss_RelationDesc,
00561 node->indexqual,
00562 false,
00563 &indexstate->iss_ScanKeys,
00564 &indexstate->iss_NumScanKeys,
00565 &indexstate->iss_RuntimeKeys,
00566 &indexstate->iss_NumRuntimeKeys,
00567 NULL,
00568 NULL);
00569
00570
00571
00572
00573 ExecIndexBuildScanKeys((PlanState *) indexstate,
00574 indexstate->iss_RelationDesc,
00575 node->indexorderby,
00576 true,
00577 &indexstate->iss_OrderByKeys,
00578 &indexstate->iss_NumOrderByKeys,
00579 &indexstate->iss_RuntimeKeys,
00580 &indexstate->iss_NumRuntimeKeys,
00581 NULL,
00582 NULL);
00583
00584
00585
00586
00587
00588
00589
00590 if (indexstate->iss_NumRuntimeKeys != 0)
00591 {
00592 ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext;
00593
00594 ExecAssignExprContext(estate, &indexstate->ss.ps);
00595 indexstate->iss_RuntimeContext = indexstate->ss.ps.ps_ExprContext;
00596 indexstate->ss.ps.ps_ExprContext = stdecontext;
00597 }
00598 else
00599 {
00600 indexstate->iss_RuntimeContext = NULL;
00601 }
00602
00603
00604
00605
00606 indexstate->iss_ScanDesc = index_beginscan(currentRelation,
00607 indexstate->iss_RelationDesc,
00608 estate->es_snapshot,
00609 indexstate->iss_NumScanKeys,
00610 indexstate->iss_NumOrderByKeys);
00611
00612
00613
00614
00615
00616 if (indexstate->iss_NumRuntimeKeys == 0)
00617 index_rescan(indexstate->iss_ScanDesc,
00618 indexstate->iss_ScanKeys, indexstate->iss_NumScanKeys,
00619 indexstate->iss_OrderByKeys, indexstate->iss_NumOrderByKeys);
00620
00621
00622
00623
00624 return indexstate;
00625 }
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687 void
00688 ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
00689 List *quals, bool isorderby,
00690 ScanKey *scanKeys, int *numScanKeys,
00691 IndexRuntimeKeyInfo **runtimeKeys, int *numRuntimeKeys,
00692 IndexArrayKeyInfo **arrayKeys, int *numArrayKeys)
00693 {
00694 ListCell *qual_cell;
00695 ScanKey scan_keys;
00696 IndexRuntimeKeyInfo *runtime_keys;
00697 IndexArrayKeyInfo *array_keys;
00698 int n_scan_keys;
00699 int n_runtime_keys;
00700 int max_runtime_keys;
00701 int n_array_keys;
00702 int j;
00703
00704
00705 n_scan_keys = list_length(quals);
00706 scan_keys = (ScanKey) palloc(n_scan_keys * sizeof(ScanKeyData));
00707
00708
00709
00710
00711
00712
00713
00714
00715 runtime_keys = *runtimeKeys;
00716 n_runtime_keys = max_runtime_keys = *numRuntimeKeys;
00717
00718
00719 array_keys = (IndexArrayKeyInfo *)
00720 palloc0(n_scan_keys * sizeof(IndexArrayKeyInfo));
00721 n_array_keys = 0;
00722
00723
00724
00725
00726
00727 j = 0;
00728 foreach(qual_cell, quals)
00729 {
00730 Expr *clause = (Expr *) lfirst(qual_cell);
00731 ScanKey this_scan_key = &scan_keys[j++];
00732 Oid opno;
00733 RegProcedure opfuncid;
00734 Oid opfamily;
00735 int op_strategy;
00736 Oid op_lefttype;
00737 Oid op_righttype;
00738 Expr *leftop;
00739 Expr *rightop;
00740 AttrNumber varattno;
00741
00742 if (IsA(clause, OpExpr))
00743 {
00744
00745 int flags = 0;
00746 Datum scanvalue;
00747
00748 opno = ((OpExpr *) clause)->opno;
00749 opfuncid = ((OpExpr *) clause)->opfuncid;
00750
00751
00752
00753
00754 leftop = (Expr *) get_leftop(clause);
00755
00756 if (leftop && IsA(leftop, RelabelType))
00757 leftop = ((RelabelType *) leftop)->arg;
00758
00759 Assert(leftop != NULL);
00760
00761 if (!(IsA(leftop, Var) &&
00762 ((Var *) leftop)->varno == INDEX_VAR))
00763 elog(ERROR, "indexqual doesn't have key on left side");
00764
00765 varattno = ((Var *) leftop)->varattno;
00766 if (varattno < 1 || varattno > index->rd_index->indnatts)
00767 elog(ERROR, "bogus index qualification");
00768
00769
00770
00771
00772
00773 opfamily = index->rd_opfamily[varattno - 1];
00774
00775 get_op_opfamily_properties(opno, opfamily, isorderby,
00776 &op_strategy,
00777 &op_lefttype,
00778 &op_righttype);
00779
00780 if (isorderby)
00781 flags |= SK_ORDER_BY;
00782
00783
00784
00785
00786 rightop = (Expr *) get_rightop(clause);
00787
00788 if (rightop && IsA(rightop, RelabelType))
00789 rightop = ((RelabelType *) rightop)->arg;
00790
00791 Assert(rightop != NULL);
00792
00793 if (IsA(rightop, Const))
00794 {
00795
00796 scanvalue = ((Const *) rightop)->constvalue;
00797 if (((Const *) rightop)->constisnull)
00798 flags |= SK_ISNULL;
00799 }
00800 else
00801 {
00802
00803 if (n_runtime_keys >= max_runtime_keys)
00804 {
00805 if (max_runtime_keys == 0)
00806 {
00807 max_runtime_keys = 8;
00808 runtime_keys = (IndexRuntimeKeyInfo *)
00809 palloc(max_runtime_keys * sizeof(IndexRuntimeKeyInfo));
00810 }
00811 else
00812 {
00813 max_runtime_keys *= 2;
00814 runtime_keys = (IndexRuntimeKeyInfo *)
00815 repalloc(runtime_keys, max_runtime_keys * sizeof(IndexRuntimeKeyInfo));
00816 }
00817 }
00818 runtime_keys[n_runtime_keys].scan_key = this_scan_key;
00819 runtime_keys[n_runtime_keys].key_expr =
00820 ExecInitExpr(rightop, planstate);
00821 runtime_keys[n_runtime_keys].key_toastable =
00822 TypeIsToastable(op_righttype);
00823 n_runtime_keys++;
00824 scanvalue = (Datum) 0;
00825 }
00826
00827
00828
00829
00830 ScanKeyEntryInitialize(this_scan_key,
00831 flags,
00832 varattno,
00833 op_strategy,
00834 op_righttype,
00835 ((OpExpr *) clause)->inputcollid,
00836 opfuncid,
00837 scanvalue);
00838 }
00839 else if (IsA(clause, RowCompareExpr))
00840 {
00841
00842 RowCompareExpr *rc = (RowCompareExpr *) clause;
00843 ListCell *largs_cell = list_head(rc->largs);
00844 ListCell *rargs_cell = list_head(rc->rargs);
00845 ListCell *opnos_cell = list_head(rc->opnos);
00846 ListCell *collids_cell = list_head(rc->inputcollids);
00847 ScanKey first_sub_key;
00848 int n_sub_key;
00849
00850 Assert(!isorderby);
00851
00852 first_sub_key = (ScanKey)
00853 palloc(list_length(rc->opnos) * sizeof(ScanKeyData));
00854 n_sub_key = 0;
00855
00856
00857 while (opnos_cell != NULL)
00858 {
00859 ScanKey this_sub_key = &first_sub_key[n_sub_key];
00860 int flags = SK_ROW_MEMBER;
00861 Datum scanvalue;
00862 Oid inputcollation;
00863
00864
00865
00866
00867 leftop = (Expr *) lfirst(largs_cell);
00868 largs_cell = lnext(largs_cell);
00869
00870 if (leftop && IsA(leftop, RelabelType))
00871 leftop = ((RelabelType *) leftop)->arg;
00872
00873 Assert(leftop != NULL);
00874
00875 if (!(IsA(leftop, Var) &&
00876 ((Var *) leftop)->varno == INDEX_VAR))
00877 elog(ERROR, "indexqual doesn't have key on left side");
00878
00879 varattno = ((Var *) leftop)->varattno;
00880
00881
00882
00883
00884
00885 opno = lfirst_oid(opnos_cell);
00886 opnos_cell = lnext(opnos_cell);
00887
00888 if (index->rd_rel->relam != BTREE_AM_OID ||
00889 varattno < 1 || varattno > index->rd_index->indnatts)
00890 elog(ERROR, "bogus RowCompare index qualification");
00891 opfamily = index->rd_opfamily[varattno - 1];
00892
00893 get_op_opfamily_properties(opno, opfamily, isorderby,
00894 &op_strategy,
00895 &op_lefttype,
00896 &op_righttype);
00897
00898 if (op_strategy != rc->rctype)
00899 elog(ERROR, "RowCompare index qualification contains wrong operator");
00900
00901 opfuncid = get_opfamily_proc(opfamily,
00902 op_lefttype,
00903 op_righttype,
00904 BTORDER_PROC);
00905
00906 inputcollation = lfirst_oid(collids_cell);
00907 collids_cell = lnext(collids_cell);
00908
00909
00910
00911
00912 rightop = (Expr *) lfirst(rargs_cell);
00913 rargs_cell = lnext(rargs_cell);
00914
00915 if (rightop && IsA(rightop, RelabelType))
00916 rightop = ((RelabelType *) rightop)->arg;
00917
00918 Assert(rightop != NULL);
00919
00920 if (IsA(rightop, Const))
00921 {
00922
00923 scanvalue = ((Const *) rightop)->constvalue;
00924 if (((Const *) rightop)->constisnull)
00925 flags |= SK_ISNULL;
00926 }
00927 else
00928 {
00929
00930 if (n_runtime_keys >= max_runtime_keys)
00931 {
00932 if (max_runtime_keys == 0)
00933 {
00934 max_runtime_keys = 8;
00935 runtime_keys = (IndexRuntimeKeyInfo *)
00936 palloc(max_runtime_keys * sizeof(IndexRuntimeKeyInfo));
00937 }
00938 else
00939 {
00940 max_runtime_keys *= 2;
00941 runtime_keys = (IndexRuntimeKeyInfo *)
00942 repalloc(runtime_keys, max_runtime_keys * sizeof(IndexRuntimeKeyInfo));
00943 }
00944 }
00945 runtime_keys[n_runtime_keys].scan_key = this_sub_key;
00946 runtime_keys[n_runtime_keys].key_expr =
00947 ExecInitExpr(rightop, planstate);
00948 runtime_keys[n_runtime_keys].key_toastable =
00949 TypeIsToastable(op_righttype);
00950 n_runtime_keys++;
00951 scanvalue = (Datum) 0;
00952 }
00953
00954
00955
00956
00957 ScanKeyEntryInitialize(this_sub_key,
00958 flags,
00959 varattno,
00960 op_strategy,
00961 op_righttype,
00962 inputcollation,
00963 opfuncid,
00964 scanvalue);
00965 n_sub_key++;
00966 }
00967
00968
00969 first_sub_key[n_sub_key - 1].sk_flags |= SK_ROW_END;
00970
00971
00972
00973
00974
00975 MemSet(this_scan_key, 0, sizeof(ScanKeyData));
00976 this_scan_key->sk_flags = SK_ROW_HEADER;
00977 this_scan_key->sk_attno = first_sub_key->sk_attno;
00978 this_scan_key->sk_strategy = rc->rctype;
00979
00980 this_scan_key->sk_argument = PointerGetDatum(first_sub_key);
00981 }
00982 else if (IsA(clause, ScalarArrayOpExpr))
00983 {
00984
00985 ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
00986 int flags = 0;
00987 Datum scanvalue;
00988
00989 Assert(!isorderby);
00990
00991 Assert(saop->useOr);
00992 opno = saop->opno;
00993 opfuncid = saop->opfuncid;
00994
00995
00996
00997
00998 leftop = (Expr *) linitial(saop->args);
00999
01000 if (leftop && IsA(leftop, RelabelType))
01001 leftop = ((RelabelType *) leftop)->arg;
01002
01003 Assert(leftop != NULL);
01004
01005 if (!(IsA(leftop, Var) &&
01006 ((Var *) leftop)->varno == INDEX_VAR))
01007 elog(ERROR, "indexqual doesn't have key on left side");
01008
01009 varattno = ((Var *) leftop)->varattno;
01010 if (varattno < 1 || varattno > index->rd_index->indnatts)
01011 elog(ERROR, "bogus index qualification");
01012
01013
01014
01015
01016
01017 opfamily = index->rd_opfamily[varattno - 1];
01018
01019 get_op_opfamily_properties(opno, opfamily, isorderby,
01020 &op_strategy,
01021 &op_lefttype,
01022 &op_righttype);
01023
01024
01025
01026
01027 rightop = (Expr *) lsecond(saop->args);
01028
01029 if (rightop && IsA(rightop, RelabelType))
01030 rightop = ((RelabelType *) rightop)->arg;
01031
01032 Assert(rightop != NULL);
01033
01034 if (index->rd_am->amsearcharray)
01035 {
01036
01037 flags |= SK_SEARCHARRAY;
01038 if (IsA(rightop, Const))
01039 {
01040
01041 scanvalue = ((Const *) rightop)->constvalue;
01042 if (((Const *) rightop)->constisnull)
01043 flags |= SK_ISNULL;
01044 }
01045 else
01046 {
01047
01048 if (n_runtime_keys >= max_runtime_keys)
01049 {
01050 if (max_runtime_keys == 0)
01051 {
01052 max_runtime_keys = 8;
01053 runtime_keys = (IndexRuntimeKeyInfo *)
01054 palloc(max_runtime_keys * sizeof(IndexRuntimeKeyInfo));
01055 }
01056 else
01057 {
01058 max_runtime_keys *= 2;
01059 runtime_keys = (IndexRuntimeKeyInfo *)
01060 repalloc(runtime_keys, max_runtime_keys * sizeof(IndexRuntimeKeyInfo));
01061 }
01062 }
01063 runtime_keys[n_runtime_keys].scan_key = this_scan_key;
01064 runtime_keys[n_runtime_keys].key_expr =
01065 ExecInitExpr(rightop, planstate);
01066
01067
01068
01069
01070
01071
01072
01073 runtime_keys[n_runtime_keys].key_toastable = true;
01074 n_runtime_keys++;
01075 scanvalue = (Datum) 0;
01076 }
01077 }
01078 else
01079 {
01080
01081 array_keys[n_array_keys].scan_key = this_scan_key;
01082 array_keys[n_array_keys].array_expr =
01083 ExecInitExpr(rightop, planstate);
01084
01085 n_array_keys++;
01086 scanvalue = (Datum) 0;
01087 }
01088
01089
01090
01091
01092 ScanKeyEntryInitialize(this_scan_key,
01093 flags,
01094 varattno,
01095 op_strategy,
01096 op_righttype,
01097 saop->inputcollid,
01098 opfuncid,
01099 scanvalue);
01100 }
01101 else if (IsA(clause, NullTest))
01102 {
01103
01104 NullTest *ntest = (NullTest *) clause;
01105 int flags;
01106
01107 Assert(!isorderby);
01108
01109
01110
01111
01112 leftop = ntest->arg;
01113
01114 if (leftop && IsA(leftop, RelabelType))
01115 leftop = ((RelabelType *) leftop)->arg;
01116
01117 Assert(leftop != NULL);
01118
01119 if (!(IsA(leftop, Var) &&
01120 ((Var *) leftop)->varno == INDEX_VAR))
01121 elog(ERROR, "NullTest indexqual has wrong key");
01122
01123 varattno = ((Var *) leftop)->varattno;
01124
01125
01126
01127
01128 switch (ntest->nulltesttype)
01129 {
01130 case IS_NULL:
01131 flags = SK_ISNULL | SK_SEARCHNULL;
01132 break;
01133 case IS_NOT_NULL:
01134 flags = SK_ISNULL | SK_SEARCHNOTNULL;
01135 break;
01136 default:
01137 elog(ERROR, "unrecognized nulltesttype: %d",
01138 (int) ntest->nulltesttype);
01139 flags = 0;
01140 break;
01141 }
01142
01143 ScanKeyEntryInitialize(this_scan_key,
01144 flags,
01145 varattno,
01146 InvalidStrategy,
01147 InvalidOid,
01148 InvalidOid,
01149 InvalidOid,
01150 (Datum) 0);
01151 }
01152 else
01153 elog(ERROR, "unsupported indexqual type: %d",
01154 (int) nodeTag(clause));
01155 }
01156
01157 Assert(n_runtime_keys <= max_runtime_keys);
01158
01159
01160 if (n_array_keys == 0)
01161 {
01162 pfree(array_keys);
01163 array_keys = NULL;
01164 }
01165
01166
01167
01168
01169 *scanKeys = scan_keys;
01170 *numScanKeys = n_scan_keys;
01171 *runtimeKeys = runtime_keys;
01172 *numRuntimeKeys = n_runtime_keys;
01173 if (arrayKeys)
01174 {
01175 *arrayKeys = array_keys;
01176 *numArrayKeys = n_array_keys;
01177 }
01178 else if (n_array_keys != 0)
01179 elog(ERROR, "ScalarArrayOpExpr index qual found where not allowed");
01180 }