PostgreSQL Source Code git master
Loading...
Searching...
No Matches
nodeIndexscan.h File Reference
#include "access/genam.h"
#include "access/parallel.h"
#include "nodes/execnodes.h"
Include dependency graph for nodeIndexscan.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

IndexScanStateExecInitIndexScan (IndexScan *node, EState *estate, int eflags)
 
void ExecEndIndexScan (IndexScanState *node)
 
void ExecIndexMarkPos (IndexScanState *node)
 
void ExecIndexRestrPos (IndexScanState *node)
 
void ExecReScanIndexScan (IndexScanState *node)
 
void ExecIndexScanEstimate (IndexScanState *node, ParallelContext *pcxt)
 
void ExecIndexScanInitializeDSM (IndexScanState *node, ParallelContext *pcxt)
 
void ExecIndexScanReInitializeDSM (IndexScanState *node, ParallelContext *pcxt)
 
void ExecIndexScanInitializeWorker (IndexScanState *node, ParallelWorkerContext *pwcxt)
 
void ExecIndexScanInstrumentEstimate (IndexScanState *node, ParallelContext *pcxt)
 
void ExecIndexScanInstrumentInitDSM (IndexScanState *node, ParallelContext *pcxt)
 
void ExecIndexScanInstrumentInitWorker (IndexScanState *node, ParallelWorkerContext *pwcxt)
 
void ExecIndexScanRetrieveInstrumentation (IndexScanState *node)
 
void ExecIndexBuildScanKeys (PlanState *planstate, Relation index, List *quals, bool isorderby, ScanKey *scanKeys, int *numScanKeys, IndexRuntimeKeyInfo **runtimeKeys, int *numRuntimeKeys, IndexArrayKeyInfo **arrayKeys, int *numArrayKeys)
 
void ExecIndexEvalRuntimeKeys (ExprContext *econtext, IndexRuntimeKeyInfo *runtimeKeys, int numRuntimeKeys)
 
bool ExecIndexEvalArrayKeys (ExprContext *econtext, IndexArrayKeyInfo *arrayKeys, int numArrayKeys)
 
bool ExecIndexAdvanceArrayKeys (IndexArrayKeyInfo *arrayKeys, int numArrayKeys)
 

Function Documentation

◆ ExecEndIndexScan()

void ExecEndIndexScan ( IndexScanState node)
extern

Definition at line 791 of file nodeIndexscan.c.

792{
795
796 /*
797 * extract information from the node
798 */
801
802 /*
803 * When ending a parallel worker, copy the statistics gathered by the
804 * worker back into shared memory so that it can be picked up by the main
805 * process to report in EXPLAIN ANALYZE
806 */
807 if (node->iss_SharedInfo != NULL && IsParallelWorker())
808 {
809 IndexScanInstrumentation *winstrument;
810
811 Assert(ParallelWorkerNumber < node->iss_SharedInfo->num_workers);
812 winstrument = &node->iss_SharedInfo->winstrument[ParallelWorkerNumber];
813
814 /*
815 * We have to accumulate the stats rather than performing a memcpy.
816 * When a Gather/GatherMerge node finishes it will perform planner
817 * shutdown on the workers. On rescan it will spin up new workers
818 * which will have a new IndexOnlyScanState and zeroed stats.
819 */
820 winstrument->nsearches += node->iss_Instrument->nsearches;
821 }
822
823 /*
824 * close the index relation (no-op if we didn't open it)
825 */
826 if (indexScanDesc)
830}
int ParallelWorkerNumber
Definition parallel.c:117
#define Assert(condition)
Definition c.h:943
#define IsParallelWorker()
Definition parallel.h:62
void index_close(Relation relation, LOCKMODE lockmode)
Definition indexam.c:178
void index_endscan(IndexScanDesc scan)
Definition indexam.c:394
#define NoLock
Definition lockdefs.h:34
static int fb(int x)
struct IndexScanDescData * iss_ScanDesc
Definition execnodes.h:1761
Relation iss_RelationDesc
Definition execnodes.h:1760
SharedIndexScanInstrumentation * iss_SharedInfo
Definition execnodes.h:1763
IndexScanInstrumentation * iss_Instrument
Definition execnodes.h:1762
IndexScanInstrumentation winstrument[FLEXIBLE_ARRAY_MEMBER]

References Assert, fb(), index_close(), index_endscan(), IsParallelWorker, IndexScanState::iss_Instrument, IndexScanState::iss_RelationDesc, IndexScanState::iss_ScanDesc, IndexScanState::iss_SharedInfo, NoLock, IndexScanInstrumentation::nsearches, ParallelWorkerNumber, and SharedIndexScanInstrumentation::winstrument.

Referenced by ExecEndNode().

◆ ExecIndexAdvanceArrayKeys()

bool ExecIndexAdvanceArrayKeys ( IndexArrayKeyInfo arrayKeys,
int  numArrayKeys 
)
extern

Definition at line 746 of file nodeIndexscan.c.

747{
748 bool found = false;
749 int j;
750
751 /*
752 * Note we advance the rightmost array key most quickly, since it will
753 * correspond to the lowest-order index column among the available
754 * qualifications. This is hypothesized to result in better locality of
755 * access in the index.
756 */
757 for (j = numArrayKeys - 1; j >= 0; j--)
758 {
759 ScanKey scan_key = arrayKeys[j].scan_key;
760 int next_elem = arrayKeys[j].next_elem;
761 int num_elems = arrayKeys[j].num_elems;
762 Datum *elem_values = arrayKeys[j].elem_values;
763 bool *elem_nulls = arrayKeys[j].elem_nulls;
764
765 if (next_elem >= num_elems)
766 {
767 next_elem = 0;
768 found = false; /* need to advance next array key */
769 }
770 else
771 found = true;
772 scan_key->sk_argument = elem_values[next_elem];
773 if (elem_nulls[next_elem])
774 scan_key->sk_flags |= SK_ISNULL;
775 else
776 scan_key->sk_flags &= ~SK_ISNULL;
777 arrayKeys[j].next_elem = next_elem + 1;
778 if (found)
779 break;
780 }
781
782 return found;
783}
int j
Definition isn.c:78
uint64_t Datum
Definition postgres.h:70
#define SK_ISNULL
Definition skey.h:115
ScanKeyData * scan_key
Definition execnodes.h:1711
int sk_flags
Definition skey.h:66
Datum sk_argument
Definition skey.h:72

References IndexArrayKeyInfo::elem_nulls, IndexArrayKeyInfo::elem_values, fb(), j, IndexArrayKeyInfo::next_elem, IndexArrayKeyInfo::num_elems, IndexArrayKeyInfo::scan_key, ScanKeyData::sk_argument, ScanKeyData::sk_flags, and SK_ISNULL.

Referenced by MultiExecBitmapIndexScan().

◆ ExecIndexBuildScanKeys()

void ExecIndexBuildScanKeys ( PlanState planstate,
Relation  index,
List quals,
bool  isorderby,
ScanKey scanKeys,
int numScanKeys,
IndexRuntimeKeyInfo **  runtimeKeys,
int numRuntimeKeys,
IndexArrayKeyInfo **  arrayKeys,
int numArrayKeys 
)
extern

Definition at line 1167 of file nodeIndexscan.c.

1172{
1177 int n_scan_keys;
1178 int n_runtime_keys;
1179 int max_runtime_keys;
1180 int n_array_keys;
1181 int j;
1182
1183 /* Allocate array for ScanKey structs: one per qual */
1184 n_scan_keys = list_length(quals);
1186
1187 /*
1188 * runtime_keys array is dynamically resized as needed. We handle it this
1189 * way so that the same runtime keys array can be shared between
1190 * indexquals and indexorderbys, which will be processed in separate calls
1191 * of this function. Caller must be sure to pass in NULL/0 for first
1192 * call.
1193 */
1196
1197 /* Allocate array_keys as large as it could possibly need to be */
1200 n_array_keys = 0;
1201
1202 /*
1203 * for each opclause in the given qual, convert the opclause into a single
1204 * scan key
1205 */
1206 j = 0;
1207 foreach(qual_cell, quals)
1208 {
1209 Expr *clause = (Expr *) lfirst(qual_cell);
1211 Oid opno; /* operator's OID */
1212 RegProcedure opfuncid; /* operator proc id used in scan */
1213 Oid opfamily; /* opfamily of index column */
1214 int op_strategy; /* operator's strategy number */
1215 Oid op_lefttype; /* operator's declared input types */
1217 Expr *leftop; /* expr on lhs of operator */
1218 Expr *rightop; /* expr on rhs ... */
1219 AttrNumber varattno; /* att number used in scan */
1220 int indnkeyatts;
1221
1223 if (IsA(clause, OpExpr))
1224 {
1225 /* indexkey op const or indexkey op expression */
1226 int flags = 0;
1228
1229 opno = ((OpExpr *) clause)->opno;
1230 opfuncid = ((OpExpr *) clause)->opfuncid;
1231
1232 /*
1233 * leftop should be the index key Var, possibly relabeled
1234 */
1235 leftop = (Expr *) get_leftop(clause);
1236
1237 if (leftop && IsA(leftop, RelabelType))
1238 leftop = ((RelabelType *) leftop)->arg;
1239
1240 Assert(leftop != NULL);
1241
1242 if (!(IsA(leftop, Var) &&
1243 ((Var *) leftop)->varno == INDEX_VAR))
1244 elog(ERROR, "indexqual doesn't have key on left side");
1245
1246 varattno = ((Var *) leftop)->varattno;
1248 elog(ERROR, "bogus index qualification");
1249
1250 /*
1251 * We have to look up the operator's strategy number. This
1252 * provides a cross-check that the operator does match the index.
1253 */
1254 opfamily = index->rd_opfamily[varattno - 1];
1255
1256 get_op_opfamily_properties(opno, opfamily, isorderby,
1257 &op_strategy,
1258 &op_lefttype,
1259 &op_righttype);
1260
1261 if (isorderby)
1262 flags |= SK_ORDER_BY;
1263
1264 /*
1265 * rightop is the constant or variable comparison value
1266 */
1267 rightop = (Expr *) get_rightop(clause);
1268
1269 if (rightop && IsA(rightop, RelabelType))
1270 rightop = ((RelabelType *) rightop)->arg;
1271
1272 Assert(rightop != NULL);
1273
1274 if (IsA(rightop, Const))
1275 {
1276 /* OK, simple constant comparison value */
1277 scanvalue = ((Const *) rightop)->constvalue;
1278 if (((Const *) rightop)->constisnull)
1279 flags |= SK_ISNULL;
1280 }
1281 else
1282 {
1283 /* Need to treat this one as a runtime key */
1285 {
1286 if (max_runtime_keys == 0)
1287 {
1288 max_runtime_keys = 8;
1291 }
1292 else
1293 {
1294 max_runtime_keys *= 2;
1297 }
1298 }
1300 runtime_keys[n_runtime_keys].key_expr =
1301 ExecInitExpr(rightop, planstate);
1302 runtime_keys[n_runtime_keys].key_toastable =
1305 scanvalue = (Datum) 0;
1306 }
1307
1308 /*
1309 * initialize the scan key's fields appropriately
1310 */
1312 flags,
1313 varattno, /* attribute number to scan */
1314 op_strategy, /* op's strategy */
1315 op_righttype, /* strategy subtype */
1316 ((OpExpr *) clause)->inputcollid, /* collation */
1317 opfuncid, /* reg proc to use */
1318 scanvalue); /* constant */
1319 }
1320 else if (IsA(clause, RowCompareExpr))
1321 {
1322 /* (indexkey, indexkey, ...) op (expression, expression, ...) */
1323 RowCompareExpr *rc = (RowCompareExpr *) clause;
1325 int n_sub_key;
1330
1331 Assert(!isorderby);
1332
1334 palloc(list_length(rc->opnos) * sizeof(ScanKeyData));
1335 n_sub_key = 0;
1336
1337 /* Scan RowCompare columns and generate subsidiary ScanKey items */
1339 opnos_cell, rc->opnos, collids_cell, rc->inputcollids)
1340 {
1342 int flags = SK_ROW_MEMBER;
1345
1348 opno = lfirst_oid(opnos_cell);
1350
1351 /*
1352 * leftop should be the index key Var, possibly relabeled
1353 */
1354 if (leftop && IsA(leftop, RelabelType))
1355 leftop = ((RelabelType *) leftop)->arg;
1356
1357 Assert(leftop != NULL);
1358
1359 if (!(IsA(leftop, Var) &&
1360 ((Var *) leftop)->varno == INDEX_VAR))
1361 elog(ERROR, "indexqual doesn't have key on left side");
1362
1363 varattno = ((Var *) leftop)->varattno;
1364
1365 /*
1366 * We have to look up the operator's associated support
1367 * function
1368 */
1369 if (!index->rd_indam->amcanorder ||
1371 elog(ERROR, "bogus RowCompare index qualification");
1372 opfamily = index->rd_opfamily[varattno - 1];
1373
1374 get_op_opfamily_properties(opno, opfamily, isorderby,
1375 &op_strategy,
1376 &op_lefttype,
1377 &op_righttype);
1378
1379 if (op_strategy != rc->cmptype)
1380 elog(ERROR, "RowCompare index qualification contains wrong operator");
1381
1382 opfuncid = get_opfamily_proc(opfamily,
1385 BTORDER_PROC);
1387 elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
1389
1390 /*
1391 * rightop is the constant or variable comparison value
1392 */
1393 if (rightop && IsA(rightop, RelabelType))
1394 rightop = ((RelabelType *) rightop)->arg;
1395
1396 Assert(rightop != NULL);
1397
1398 if (IsA(rightop, Const))
1399 {
1400 /* OK, simple constant comparison value */
1401 scanvalue = ((Const *) rightop)->constvalue;
1402 if (((Const *) rightop)->constisnull)
1403 flags |= SK_ISNULL;
1404 }
1405 else
1406 {
1407 /* Need to treat this one as a runtime key */
1409 {
1410 if (max_runtime_keys == 0)
1411 {
1412 max_runtime_keys = 8;
1415 }
1416 else
1417 {
1418 max_runtime_keys *= 2;
1421 }
1422 }
1424 runtime_keys[n_runtime_keys].key_expr =
1425 ExecInitExpr(rightop, planstate);
1426 runtime_keys[n_runtime_keys].key_toastable =
1429 scanvalue = (Datum) 0;
1430 }
1431
1432 /*
1433 * initialize the subsidiary scan key's fields appropriately
1434 */
1436 flags,
1437 varattno, /* attribute number */
1438 op_strategy, /* op's strategy */
1439 op_righttype, /* strategy subtype */
1440 inputcollation, /* collation */
1441 opfuncid, /* reg proc to use */
1442 scanvalue); /* constant */
1443 n_sub_key++;
1444 }
1445
1446 /* Mark the last subsidiary scankey correctly */
1447 first_sub_key[n_sub_key - 1].sk_flags |= SK_ROW_END;
1448
1449 /*
1450 * We don't use ScanKeyEntryInitialize for the header because it
1451 * isn't going to contain a valid sk_func pointer.
1452 */
1453 MemSet(this_scan_key, 0, sizeof(ScanKeyData));
1454 this_scan_key->sk_flags = SK_ROW_HEADER;
1455 this_scan_key->sk_attno = first_sub_key->sk_attno;
1456 this_scan_key->sk_strategy = rc->cmptype;
1457 /* sk_subtype, sk_collation, sk_func not used in a header */
1459 }
1460 else if (IsA(clause, ScalarArrayOpExpr))
1461 {
1462 /* indexkey op ANY (array-expression) */
1463 ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
1464 int flags = 0;
1466
1467 Assert(!isorderby);
1468
1469 Assert(saop->useOr);
1470 opno = saop->opno;
1471 opfuncid = saop->opfuncid;
1472
1473 /*
1474 * leftop should be the index key Var, possibly relabeled
1475 */
1476 leftop = (Expr *) linitial(saop->args);
1477
1478 if (leftop && IsA(leftop, RelabelType))
1479 leftop = ((RelabelType *) leftop)->arg;
1480
1481 Assert(leftop != NULL);
1482
1483 if (!(IsA(leftop, Var) &&
1484 ((Var *) leftop)->varno == INDEX_VAR))
1485 elog(ERROR, "indexqual doesn't have key on left side");
1486
1487 varattno = ((Var *) leftop)->varattno;
1489 elog(ERROR, "bogus index qualification");
1490
1491 /*
1492 * We have to look up the operator's strategy number. This
1493 * provides a cross-check that the operator does match the index.
1494 */
1495 opfamily = index->rd_opfamily[varattno - 1];
1496
1497 get_op_opfamily_properties(opno, opfamily, isorderby,
1498 &op_strategy,
1499 &op_lefttype,
1500 &op_righttype);
1501
1502 /*
1503 * rightop is the constant or variable array value
1504 */
1505 rightop = (Expr *) lsecond(saop->args);
1506
1507 if (rightop && IsA(rightop, RelabelType))
1508 rightop = ((RelabelType *) rightop)->arg;
1509
1510 Assert(rightop != NULL);
1511
1512 if (index->rd_indam->amsearcharray)
1513 {
1514 /* Index AM will handle this like a simple operator */
1515 flags |= SK_SEARCHARRAY;
1516 if (IsA(rightop, Const))
1517 {
1518 /* OK, simple constant comparison value */
1519 scanvalue = ((Const *) rightop)->constvalue;
1520 if (((Const *) rightop)->constisnull)
1521 flags |= SK_ISNULL;
1522 }
1523 else
1524 {
1525 /* Need to treat this one as a runtime key */
1527 {
1528 if (max_runtime_keys == 0)
1529 {
1530 max_runtime_keys = 8;
1533 }
1534 else
1535 {
1536 max_runtime_keys *= 2;
1539 }
1540 }
1542 runtime_keys[n_runtime_keys].key_expr =
1543 ExecInitExpr(rightop, planstate);
1544
1545 /*
1546 * Careful here: the runtime expression is not of
1547 * op_righttype, but rather is an array of same; so
1548 * TypeIsToastable() isn't helpful. However, we can
1549 * assume that all array types are toastable.
1550 */
1551 runtime_keys[n_runtime_keys].key_toastable = true;
1553 scanvalue = (Datum) 0;
1554 }
1555 }
1556 else
1557 {
1558 /* Executor has to expand the array value */
1560 array_keys[n_array_keys].array_expr =
1561 ExecInitExpr(rightop, planstate);
1562 /* the remaining fields were zeroed by palloc0 */
1563 n_array_keys++;
1564 scanvalue = (Datum) 0;
1565 }
1566
1567 /*
1568 * initialize the scan key's fields appropriately
1569 */
1571 flags,
1572 varattno, /* attribute number to scan */
1573 op_strategy, /* op's strategy */
1574 op_righttype, /* strategy subtype */
1575 saop->inputcollid, /* collation */
1576 opfuncid, /* reg proc to use */
1577 scanvalue); /* constant */
1578 }
1579 else if (IsA(clause, NullTest))
1580 {
1581 /* indexkey IS NULL or indexkey IS NOT NULL */
1582 NullTest *ntest = (NullTest *) clause;
1583 int flags;
1584
1585 Assert(!isorderby);
1586
1587 /*
1588 * argument should be the index key Var, possibly relabeled
1589 */
1590 leftop = ntest->arg;
1591
1592 if (leftop && IsA(leftop, RelabelType))
1593 leftop = ((RelabelType *) leftop)->arg;
1594
1595 Assert(leftop != NULL);
1596
1597 if (!(IsA(leftop, Var) &&
1598 ((Var *) leftop)->varno == INDEX_VAR))
1599 elog(ERROR, "NullTest indexqual has wrong key");
1600
1601 varattno = ((Var *) leftop)->varattno;
1602
1603 /*
1604 * initialize the scan key's fields appropriately
1605 */
1606 switch (ntest->nulltesttype)
1607 {
1608 case IS_NULL:
1609 flags = SK_ISNULL | SK_SEARCHNULL;
1610 break;
1611 case IS_NOT_NULL:
1612 flags = SK_ISNULL | SK_SEARCHNOTNULL;
1613 break;
1614 default:
1615 elog(ERROR, "unrecognized nulltesttype: %d",
1616 (int) ntest->nulltesttype);
1617 flags = 0; /* keep compiler quiet */
1618 break;
1619 }
1620
1622 flags,
1623 varattno, /* attribute number to scan */
1624 InvalidStrategy, /* no strategy */
1625 InvalidOid, /* no strategy subtype */
1626 InvalidOid, /* no collation */
1627 InvalidOid, /* no reg proc for this */
1628 (Datum) 0); /* constant */
1629 }
1630 else
1631 elog(ERROR, "unsupported indexqual type: %d",
1632 (int) nodeTag(clause));
1633 }
1634
1636
1637 /* Get rid of any unused arrays */
1638 if (n_array_keys == 0)
1639 {
1641 array_keys = NULL;
1642 }
1643
1644 /*
1645 * Return info to our caller.
1646 */
1651 if (arrayKeys)
1652 {
1653 *arrayKeys = array_keys;
1654 *numArrayKeys = n_array_keys;
1655 }
1656 else if (n_array_keys != 0)
1657 elog(ERROR, "ScalarArrayOpExpr index qual found where not allowed");
1658}
int16 AttrNumber
Definition attnum.h:21
#define RegProcedureIsValid(p)
Definition c.h:862
regproc RegProcedure
Definition c.h:734
#define MemSet(start, val, len)
Definition c.h:1107
Datum arg
Definition elog.c:1322
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition execExpr.c:143
void get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op, int *strategy, Oid *lefttype, Oid *righttype)
Definition lsyscache.c:140
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition lsyscache.c:915
#define TypeIsToastable(typid)
Definition lsyscache.h:224
void * repalloc(void *pointer, Size size)
Definition mcxt.c:1632
void pfree(void *pointer)
Definition mcxt.c:1616
void * palloc0(Size size)
Definition mcxt.c:1417
void * palloc(Size size)
Definition mcxt.c:1387
#define BTORDER_PROC
Definition nbtree.h:717
static Node * get_rightop(const void *clause)
Definition nodeFuncs.h:95
static Node * get_leftop(const void *clause)
Definition nodeFuncs.h:83
#define IsA(nodeptr, _type_)
Definition nodes.h:164
#define nodeTag(nodeptr)
Definition nodes.h:139
#define lfirst(lc)
Definition pg_list.h:172
static int list_length(const List *l)
Definition pg_list.h:152
#define linitial(l)
Definition pg_list.h:178
#define lsecond(l)
Definition pg_list.h:183
#define forfour(cell1, list1, cell2, list2, cell3, list3, cell4, list4)
Definition pg_list.h:607
#define lfirst_oid(lc)
Definition pg_list.h:174
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
#define InvalidOid
unsigned int Oid
@ IS_NULL
Definition primnodes.h:1980
@ IS_NOT_NULL
Definition primnodes.h:1980
#define INDEX_VAR
Definition primnodes.h:245
#define IndexRelationGetNumberOfKeyAttributes(relation)
Definition rel.h:535
void ScanKeyEntryInitialize(ScanKey entry, int flags, AttrNumber attributeNumber, StrategyNumber strategy, Oid subtype, Oid collation, RegProcedure procedure, Datum argument)
Definition scankey.c:32
#define SK_ORDER_BY
Definition skey.h:123
#define SK_ROW_HEADER
Definition skey.h:117
#define SK_SEARCHARRAY
Definition skey.h:120
#define SK_ROW_MEMBER
Definition skey.h:118
#define SK_SEARCHNOTNULL
Definition skey.h:122
#define SK_SEARCHNULL
Definition skey.h:121
#define SK_ROW_END
Definition skey.h:119
ScanKeyData * ScanKey
Definition skey.h:75
#define InvalidStrategy
Definition stratnum.h:24
CompareType cmptype
Definition primnodes.h:1495
Definition type.h:96

References arg, ScalarArrayOpExpr::args, Assert, BTORDER_PROC, RowCompareExpr::cmptype, elog, ERROR, ExecInitExpr(), fb(), forfour, get_leftop(), get_op_opfamily_properties(), get_opfamily_proc(), get_rightop(), INDEX_VAR, IndexRelationGetNumberOfKeyAttributes, InvalidOid, InvalidStrategy, IS_NOT_NULL, IS_NULL, IsA, j, RowCompareExpr::largs, lfirst, lfirst_oid, linitial, list_length(), lsecond, MemSet, nodeTag, ScalarArrayOpExpr::opno, palloc(), palloc0(), pfree(), PointerGetDatum(), RowCompareExpr::rargs, RegProcedureIsValid, repalloc(), ScanKeyEntryInitialize(), SK_ISNULL, SK_ORDER_BY, SK_ROW_END, SK_ROW_HEADER, SK_ROW_MEMBER, SK_SEARCHARRAY, SK_SEARCHNOTNULL, SK_SEARCHNULL, TypeIsToastable, and ScalarArrayOpExpr::useOr.

Referenced by ExecInitBitmapIndexScan(), ExecInitIndexOnlyScan(), and ExecInitIndexScan().

◆ ExecIndexEvalArrayKeys()

bool ExecIndexEvalArrayKeys ( ExprContext econtext,
IndexArrayKeyInfo arrayKeys,
int  numArrayKeys 
)
extern

Definition at line 667 of file nodeIndexscan.c.

669{
670 bool result = true;
671 int j;
673
674 /* We want to keep the arrays in per-tuple memory */
676
677 for (j = 0; j < numArrayKeys; j++)
678 {
679 ScanKey scan_key = arrayKeys[j].scan_key;
680 ExprState *array_expr = arrayKeys[j].array_expr;
682 bool isNull;
684 int16 elmlen;
685 bool elmbyval;
686 char elmalign;
687 int num_elems;
688 Datum *elem_values;
689 bool *elem_nulls;
690
691 /*
692 * Compute and deconstruct the array expression. (Notes in
693 * ExecIndexEvalRuntimeKeys() apply here too.)
694 */
695 arraydatum = ExecEvalExpr(array_expr,
696 econtext,
697 &isNull);
698 if (isNull)
699 {
700 result = false;
701 break; /* no point in evaluating more */
702 }
704 /* We could cache this data, but not clear it's worth it */
706 &elmlen, &elmbyval, &elmalign);
709 elmlen, elmbyval, elmalign,
710 &elem_values, &elem_nulls, &num_elems);
711 if (num_elems <= 0)
712 {
713 result = false;
714 break; /* no point in evaluating more */
715 }
716
717 /*
718 * Note: we expect the previous array data, if any, to be
719 * automatically freed by resetting the per-tuple context; hence no
720 * pfree's here.
721 */
722 arrayKeys[j].elem_values = elem_values;
723 arrayKeys[j].elem_nulls = elem_nulls;
724 arrayKeys[j].num_elems = num_elems;
725 scan_key->sk_argument = elem_values[0];
726 if (elem_nulls[0])
727 scan_key->sk_flags |= SK_ISNULL;
728 else
729 scan_key->sk_flags &= ~SK_ISNULL;
730 arrayKeys[j].next_elem = 1;
731 }
732
734
735 return result;
736}
#define DatumGetArrayTypeP(X)
Definition array.h:261
#define ARR_ELEMTYPE(a)
Definition array.h:292
void deconstruct_array(const ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
int16_t int16
Definition c.h:619
uint32 result
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition executor.h:403
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition lsyscache.c:2491
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
MemoryContext ecxt_per_tuple_memory
Definition execnodes.h:295
ExprState * array_expr
Definition execnodes.h:1712

References ARR_ELEMTYPE, IndexArrayKeyInfo::array_expr, DatumGetArrayTypeP, deconstruct_array(), ExprContext::ecxt_per_tuple_memory, IndexArrayKeyInfo::elem_nulls, IndexArrayKeyInfo::elem_values, ExecEvalExpr(), fb(), get_typlenbyvalalign(), j, MemoryContextSwitchTo(), IndexArrayKeyInfo::next_elem, IndexArrayKeyInfo::num_elems, result, IndexArrayKeyInfo::scan_key, ScanKeyData::sk_argument, ScanKeyData::sk_flags, and SK_ISNULL.

Referenced by ExecReScanBitmapIndexScan().

◆ ExecIndexEvalRuntimeKeys()

void ExecIndexEvalRuntimeKeys ( ExprContext econtext,
IndexRuntimeKeyInfo runtimeKeys,
int  numRuntimeKeys 
)
extern

Definition at line 605 of file nodeIndexscan.c.

607{
608 int j;
610
611 /* We want to keep the key values in per-tuple memory */
613
614 for (j = 0; j < numRuntimeKeys; j++)
615 {
616 ScanKey scan_key = runtimeKeys[j].scan_key;
617 ExprState *key_expr = runtimeKeys[j].key_expr;
619 bool isNull;
620
621 /*
622 * For each run-time key, extract the run-time expression and evaluate
623 * it with respect to the current context. We then stick the result
624 * into the proper scan key.
625 *
626 * Note: the result of the eval could be a pass-by-ref value that's
627 * stored in some outer scan's tuple, not in
628 * econtext->ecxt_per_tuple_memory. We assume that the outer tuple
629 * will stay put throughout our scan. If this is wrong, we could copy
630 * the result into our context explicitly, but I think that's not
631 * necessary.
632 *
633 * It's also entirely possible that the result of the eval is a
634 * toasted value. In this case we should forcibly detoast it, to
635 * avoid repeat detoastings each time the value is examined by an
636 * index support function.
637 */
638 scanvalue = ExecEvalExpr(key_expr,
639 econtext,
640 &isNull);
641 if (isNull)
642 {
643 scan_key->sk_argument = scanvalue;
644 scan_key->sk_flags |= SK_ISNULL;
645 }
646 else
647 {
648 if (runtimeKeys[j].key_toastable)
650 scan_key->sk_argument = scanvalue;
651 scan_key->sk_flags &= ~SK_ISNULL;
652 }
653 }
654
656}
#define PG_DETOAST_DATUM(datum)
Definition fmgr.h:240

References ExprContext::ecxt_per_tuple_memory, ExecEvalExpr(), fb(), j, MemoryContextSwitchTo(), PG_DETOAST_DATUM, PointerGetDatum(), ScanKeyData::sk_argument, ScanKeyData::sk_flags, and SK_ISNULL.

Referenced by ExecReScanBitmapIndexScan(), ExecReScanIndexOnlyScan(), and ExecReScanIndexScan().

◆ ExecIndexMarkPos()

void ExecIndexMarkPos ( IndexScanState node)
extern

Definition at line 840 of file nodeIndexscan.c.

841{
842 EState *estate = node->ss.ps.state;
843 EPQState *epqstate = estate->es_epq_active;
844
845 if (epqstate != NULL)
846 {
847 /*
848 * We are inside an EvalPlanQual recheck. If a test tuple exists for
849 * this relation, then we shouldn't access the index at all. We would
850 * instead need to save, and later restore, the state of the
851 * relsubs_done flag, so that re-fetching the test tuple is possible.
852 * However, given the assumption that no caller sets a mark at the
853 * start of the scan, we can only get here with relsubs_done[i]
854 * already set, and so no state need be saved.
855 */
856 Index scanrelid = ((Scan *) node->ss.ps.plan)->scanrelid;
857
858 Assert(scanrelid > 0);
859 if (epqstate->relsubs_slot[scanrelid - 1] != NULL ||
860 epqstate->relsubs_rowmark[scanrelid - 1] != NULL)
861 {
862 /* Verify the claim above */
863 if (!epqstate->relsubs_done[scanrelid - 1])
864 elog(ERROR, "unexpected ExecIndexMarkPos call in EPQ recheck");
865 return;
866 }
867 }
868
870}
unsigned int Index
Definition c.h:698
void index_markpos(IndexScanDesc scan)
Definition indexam.c:424
ExecAuxRowMark ** relsubs_rowmark
Definition execnodes.h:1378
TupleTableSlot ** relsubs_slot
Definition execnodes.h:1350
bool * relsubs_done
Definition execnodes.h:1385
struct EPQState * es_epq_active
Definition execnodes.h:778
ScanState ss
Definition execnodes.h:1749
Plan * plan
Definition execnodes.h:1201
EState * state
Definition execnodes.h:1203
PlanState ps
Definition execnodes.h:1659

References Assert, elog, ERROR, EState::es_epq_active, fb(), index_markpos(), IndexScanState::iss_ScanDesc, PlanState::plan, ScanState::ps, EPQState::relsubs_done, EPQState::relsubs_rowmark, EPQState::relsubs_slot, IndexScanState::ss, and PlanState::state.

Referenced by ExecMarkPos().

◆ ExecIndexRestrPos()

void ExecIndexRestrPos ( IndexScanState node)
extern

Definition at line 877 of file nodeIndexscan.c.

878{
879 EState *estate = node->ss.ps.state;
880 EPQState *epqstate = estate->es_epq_active;
881
882 if (estate->es_epq_active != NULL)
883 {
884 /* See comments in ExecIndexMarkPos */
885 Index scanrelid = ((Scan *) node->ss.ps.plan)->scanrelid;
886
887 Assert(scanrelid > 0);
888 if (epqstate->relsubs_slot[scanrelid - 1] != NULL ||
889 epqstate->relsubs_rowmark[scanrelid - 1] != NULL)
890 {
891 /* Verify the claim above */
892 if (!epqstate->relsubs_done[scanrelid - 1])
893 elog(ERROR, "unexpected ExecIndexRestrPos call in EPQ recheck");
894 return;
895 }
896 }
897
899}
void index_restrpos(IndexScanDesc scan)
Definition indexam.c:448

References Assert, elog, ERROR, EState::es_epq_active, fb(), index_restrpos(), IndexScanState::iss_ScanDesc, PlanState::plan, ScanState::ps, EPQState::relsubs_done, EPQState::relsubs_rowmark, EPQState::relsubs_slot, IndexScanState::ss, and PlanState::state.

Referenced by ExecRestrPos().

◆ ExecIndexScanEstimate()

void ExecIndexScanEstimate ( IndexScanState node,
ParallelContext pcxt 
)
extern

Definition at line 1673 of file nodeIndexscan.c.

1675{
1676 EState *estate = node->ss.ps.state;
1677
1679 node->iss_NumScanKeys,
1680 node->iss_NumOrderByKeys,
1681 estate->es_snapshot);
1684}
Size index_parallelscan_estimate(Relation indexRelation, int nkeys, int norderbys, Snapshot snapshot)
Definition indexam.c:470
#define shm_toc_estimate_chunk(e, sz)
Definition shm_toc.h:51
#define shm_toc_estimate_keys(e, cnt)
Definition shm_toc.h:53
Snapshot es_snapshot
Definition execnodes.h:696
shm_toc_estimator estimator
Definition parallel.h:43

References EState::es_snapshot, ParallelContext::estimator, index_parallelscan_estimate(), IndexScanState::iss_NumOrderByKeys, IndexScanState::iss_NumScanKeys, IndexScanState::iss_PscanLen, IndexScanState::iss_RelationDesc, ScanState::ps, shm_toc_estimate_chunk, shm_toc_estimate_keys, IndexScanState::ss, and PlanState::state.

Referenced by ExecParallelEstimate().

◆ ExecIndexScanInitializeDSM()

void ExecIndexScanInitializeDSM ( IndexScanState node,
ParallelContext pcxt 
)
extern

Definition at line 1693 of file nodeIndexscan.c.

1695{
1696 EState *estate = node->ss.ps.state;
1698
1699 piscan = shm_toc_allocate(pcxt->toc, node->iss_PscanLen);
1701 node->iss_RelationDesc,
1702 estate->es_snapshot,
1703 piscan);
1704 shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, piscan);
1705
1706 node->iss_ScanDesc =
1708 node->iss_RelationDesc,
1709 node->iss_Instrument,
1710 node->iss_NumScanKeys,
1711 node->iss_NumOrderByKeys,
1712 piscan,
1713 ScanRelIsReadOnly(&node->ss) ?
1715
1716 /*
1717 * If no run-time keys to calculate or they are ready, go ahead and pass
1718 * the scankeys to the index AM.
1719 */
1720 if (node->iss_NumRuntimeKeys == 0 || node->iss_RuntimeKeysReady)
1722 node->iss_ScanKeys, node->iss_NumScanKeys,
1723 node->iss_OrderByKeys, node->iss_NumOrderByKeys);
1724}
bool ScanRelIsReadOnly(ScanState *ss)
Definition execUtils.c:751
IndexScanDesc index_beginscan_parallel(Relation heaprel, Relation indexrel, IndexScanInstrumentation *instrument, int nkeys, int norderbys, ParallelIndexScanDesc pscan, uint32 flags)
Definition indexam.c:560
void index_parallelscan_initialize(Relation heapRelation, Relation indexRelation, Snapshot snapshot, ParallelIndexScanDesc target)
Definition indexam.c:505
void index_rescan(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int norderbys)
Definition indexam.c:368
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
Definition shm_toc.c:88
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
Definition shm_toc.c:171
bool iss_RuntimeKeysReady
Definition execnodes.h:1758
ScanKeyData * iss_ScanKeys
Definition execnodes.h:1752
ScanKeyData * iss_OrderByKeys
Definition execnodes.h:1754
shm_toc * toc
Definition parallel.h:46
int plan_node_id
Definition plannodes.h:233
Relation ss_currentRelation
Definition execnodes.h:1660
@ SO_HINT_REL_READ_ONLY
Definition tableam.h:71
@ SO_NONE
Definition tableam.h:49

References EState::es_snapshot, fb(), index_beginscan_parallel(), index_parallelscan_initialize(), index_rescan(), IndexScanState::iss_Instrument, IndexScanState::iss_NumOrderByKeys, IndexScanState::iss_NumRuntimeKeys, IndexScanState::iss_NumScanKeys, IndexScanState::iss_OrderByKeys, IndexScanState::iss_PscanLen, IndexScanState::iss_RelationDesc, IndexScanState::iss_RuntimeKeysReady, IndexScanState::iss_ScanDesc, IndexScanState::iss_ScanKeys, PlanState::plan, Plan::plan_node_id, ScanState::ps, ScanRelIsReadOnly(), shm_toc_allocate(), shm_toc_insert(), SO_HINT_REL_READ_ONLY, SO_NONE, IndexScanState::ss, ScanState::ss_currentRelation, PlanState::state, and ParallelContext::toc.

Referenced by ExecParallelInitializeDSM().

◆ ExecIndexScanInitializeWorker()

void ExecIndexScanInitializeWorker ( IndexScanState node,
ParallelWorkerContext pwcxt 
)
extern

Definition at line 1747 of file nodeIndexscan.c.

1749{
1751
1752 piscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
1753
1754 node->iss_ScanDesc =
1756 node->iss_RelationDesc,
1757 node->iss_Instrument,
1758 node->iss_NumScanKeys,
1759 node->iss_NumOrderByKeys,
1760 piscan,
1761 ScanRelIsReadOnly(&node->ss) ?
1763
1764 /*
1765 * If no run-time keys to calculate or they are ready, go ahead and pass
1766 * the scankeys to the index AM.
1767 */
1768 if (node->iss_NumRuntimeKeys == 0 || node->iss_RuntimeKeysReady)
1770 node->iss_ScanKeys, node->iss_NumScanKeys,
1771 node->iss_OrderByKeys, node->iss_NumOrderByKeys);
1772}
void * shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
Definition shm_toc.c:239

References fb(), index_beginscan_parallel(), index_rescan(), IndexScanState::iss_Instrument, IndexScanState::iss_NumOrderByKeys, IndexScanState::iss_NumRuntimeKeys, IndexScanState::iss_NumScanKeys, IndexScanState::iss_OrderByKeys, IndexScanState::iss_RelationDesc, IndexScanState::iss_RuntimeKeysReady, IndexScanState::iss_ScanDesc, IndexScanState::iss_ScanKeys, PlanState::plan, Plan::plan_node_id, ScanState::ps, ScanRelIsReadOnly(), shm_toc_lookup(), SO_HINT_REL_READ_ONLY, SO_NONE, IndexScanState::ss, and ScanState::ss_currentRelation.

Referenced by ExecParallelInitializeWorker().

◆ ExecIndexScanInstrumentEstimate()

void ExecIndexScanInstrumentEstimate ( IndexScanState node,
ParallelContext pcxt 
)
extern

Definition at line 1779 of file nodeIndexscan.c.

1781{
1782 Size size;
1783
1784 if (!node->ss.ps.instrument || pcxt->nworkers == 0)
1785 return;
1786
1787 /*
1788 * This size calculation is trivial enough that we don't bother saving it
1789 * in the IndexScanState. We'll recalculate the needed size in
1790 * ExecIndexScanInstrumentInitDSM().
1791 */
1794 shm_toc_estimate_chunk(&pcxt->estimator, size);
1796}
size_t Size
Definition c.h:689
Size add_size(Size s1, Size s2)
Definition shmem.c:1048
Size mul_size(Size s1, Size s2)
Definition shmem.c:1063
NodeInstrumentation * instrument
Definition execnodes.h:1211

References add_size(), ParallelContext::estimator, fb(), PlanState::instrument, mul_size(), ParallelContext::nworkers, ScanState::ps, shm_toc_estimate_chunk, shm_toc_estimate_keys, and IndexScanState::ss.

Referenced by ExecParallelEstimate().

◆ ExecIndexScanInstrumentInitDSM()

void ExecIndexScanInstrumentInitDSM ( IndexScanState node,
ParallelContext pcxt 
)
extern

◆ ExecIndexScanInstrumentInitWorker()

void ExecIndexScanInstrumentInitWorker ( IndexScanState node,
ParallelWorkerContext pwcxt 
)
extern

◆ ExecIndexScanReInitializeDSM()

void ExecIndexScanReInitializeDSM ( IndexScanState node,
ParallelContext pcxt 
)
extern

Definition at line 1733 of file nodeIndexscan.c.

1735{
1736 Assert(node->ss.ps.plan->parallel_aware);
1738}
void index_parallelrescan(IndexScanDesc scan)
Definition indexam.c:538
bool parallel_aware
Definition plannodes.h:219

References Assert, index_parallelrescan(), IndexScanState::iss_ScanDesc, Plan::parallel_aware, PlanState::plan, ScanState::ps, and IndexScanState::ss.

Referenced by ExecParallelReInitializeDSM().

◆ ExecIndexScanRetrieveInstrumentation()

void ExecIndexScanRetrieveInstrumentation ( IndexScanState node)
extern

Definition at line 1848 of file nodeIndexscan.c.

1849{
1851 size_t size;
1852
1853 if (SharedInfo == NULL)
1854 return;
1855
1856 /* Create a copy of SharedInfo in backend-local memory */
1857 size = offsetof(SharedIndexScanInstrumentation, winstrument) +
1859 node->iss_SharedInfo = palloc(size);
1860 memcpy(node->iss_SharedInfo, SharedInfo, size);
1861}
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))

References fb(), IndexScanState::iss_SharedInfo, memcpy(), SharedIndexScanInstrumentation::num_workers, and palloc().

Referenced by ExecParallelRetrieveInstrumentation().

◆ ExecInitIndexScan()

IndexScanState * ExecInitIndexScan ( IndexScan node,
EState estate,
int  eflags 
)
extern

Definition at line 913 of file nodeIndexscan.c.

914{
917 LOCKMODE lockmode;
918
919 /*
920 * create state structure
921 */
923 indexstate->ss.ps.plan = (Plan *) node;
924 indexstate->ss.ps.state = estate;
925 indexstate->ss.ps.ExecProcNode = ExecIndexScan;
926
927 /*
928 * Miscellaneous initialization
929 *
930 * create expression context for node
931 */
932 ExecAssignExprContext(estate, &indexstate->ss.ps);
933
934 /*
935 * open the scan relation
936 */
937 currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
938
939 indexstate->ss.ss_currentRelation = currentRelation;
940 indexstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */
941
942 /*
943 * get the scan type from the relation descriptor.
944 */
949
950 /*
951 * Initialize result type and projection.
952 */
955
956 /*
957 * initialize child expressions
958 *
959 * Note: we don't initialize all of the indexqual expression, only the
960 * sub-parts corresponding to runtime keys (see below). Likewise for
961 * indexorderby, if any. But the indexqualorig expression is always
962 * initialized even though it will only be used in some uncommon cases ---
963 * would be nice to improve that. (Problem is that any SubPlans present
964 * in the expression must be found now...)
965 */
966 indexstate->ss.ps.qual =
967 ExecInitQual(node->scan.plan.qual, (PlanState *) indexstate);
968 indexstate->indexqualorig =
970 indexstate->indexorderbyorig =
972
973 /*
974 * If we are just doing EXPLAIN (ie, aren't going to run the plan), stop
975 * here. This allows an index-advisor plugin to EXPLAIN a plan containing
976 * references to nonexistent indexes.
977 */
978 if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
979 return indexstate;
980
981 /* Set up instrumentation of index scans if requested */
982 if (estate->es_instrument)
984
985 /* Open the index relation. */
986 lockmode = exec_rt_fetch(node->scan.scanrelid, estate)->rellockmode;
987 indexstate->iss_RelationDesc = index_open(node->indexid, lockmode);
988
989 /*
990 * Initialize index-specific scan state
991 */
992 indexstate->iss_RuntimeKeysReady = false;
993 indexstate->iss_RuntimeKeys = NULL;
994 indexstate->iss_NumRuntimeKeys = 0;
995
996 /*
997 * build the index scan keys from the index qualification
998 */
1000 indexstate->iss_RelationDesc,
1001 node->indexqual,
1002 false,
1003 &indexstate->iss_ScanKeys,
1004 &indexstate->iss_NumScanKeys,
1005 &indexstate->iss_RuntimeKeys,
1006 &indexstate->iss_NumRuntimeKeys,
1007 NULL, /* no ArrayKeys */
1008 NULL);
1009
1010 /*
1011 * any ORDER BY exprs have to be turned into scankeys in the same way
1012 */
1014 indexstate->iss_RelationDesc,
1015 node->indexorderby,
1016 true,
1017 &indexstate->iss_OrderByKeys,
1018 &indexstate->iss_NumOrderByKeys,
1019 &indexstate->iss_RuntimeKeys,
1020 &indexstate->iss_NumRuntimeKeys,
1021 NULL, /* no ArrayKeys */
1022 NULL);
1023
1024 /* Initialize sort support, if we need to re-check ORDER BY exprs */
1025 if (indexstate->iss_NumOrderByKeys > 0)
1026 {
1027 int numOrderByKeys = indexstate->iss_NumOrderByKeys;
1028 int i;
1029 ListCell *lco;
1030 ListCell *lcx;
1031
1032 /*
1033 * Prepare sort support, and look up the data type for each ORDER BY
1034 * expression.
1035 */
1038 indexstate->iss_SortSupport = (SortSupportData *)
1040 indexstate->iss_OrderByTypByVals = (bool *)
1041 palloc(numOrderByKeys * sizeof(bool));
1042 indexstate->iss_OrderByTypLens = (int16 *)
1043 palloc(numOrderByKeys * sizeof(int16));
1044 i = 0;
1046 {
1048 Node *orderbyexpr = (Node *) lfirst(lcx);
1051 SortSupport orderbysort = &indexstate->iss_SortSupport[i];
1052
1053 /* Initialize sort support */
1055 orderbysort->ssup_collation = orderbyColl;
1056 /* See cmp_orderbyvals() comments on NULLS LAST */
1057 orderbysort->ssup_nulls_first = false;
1058 /* ssup_attno is unused here and elsewhere */
1059 orderbysort->ssup_attno = 0;
1060 /* No abbreviation */
1061 orderbysort->abbreviate = false;
1063
1065 &indexstate->iss_OrderByTypLens[i],
1066 &indexstate->iss_OrderByTypByVals[i]);
1067 i++;
1068 }
1069
1070 /* allocate arrays to hold the re-calculated distances */
1071 indexstate->iss_OrderByValues = (Datum *)
1072 palloc(numOrderByKeys * sizeof(Datum));
1073 indexstate->iss_OrderByNulls = (bool *)
1074 palloc(numOrderByKeys * sizeof(bool));
1075
1076 /* and initialize the reorder queue */
1078 indexstate);
1079 }
1080
1081 /*
1082 * If we have runtime keys, we need an ExprContext to evaluate them. The
1083 * node's standard context won't do because we want to reset that context
1084 * for every tuple. So, build another context just like the other one...
1085 * -tgl 7/11/00
1086 */
1087 if (indexstate->iss_NumRuntimeKeys != 0)
1088 {
1089 ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext;
1090
1091 ExecAssignExprContext(estate, &indexstate->ss.ps);
1092 indexstate->iss_RuntimeContext = indexstate->ss.ps.ps_ExprContext;
1093 indexstate->ss.ps.ps_ExprContext = stdecontext;
1094 }
1095 else
1096 {
1097 indexstate->iss_RuntimeContext = NULL;
1098 }
1099
1100 /*
1101 * all done.
1102 */
1103 return indexstate;
1104}
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition execExpr.c:250
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition execExpr.c:356
void ExecAssignScanProjectionInfo(ScanState *node)
Definition execScan.c:81
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops, uint16 flags)
void ExecInitResultTypeTL(PlanState *planstate)
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition execUtils.c:490
Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
Definition execUtils.c:768
static RangeTblEntry * exec_rt_fetch(Index rti, EState *estate)
Definition executor.h:710
#define EXEC_FLAG_EXPLAIN_ONLY
Definition executor.h:67
#define palloc0_object(type)
Definition fe_memutils.h:75
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition indexam.c:134
int i
Definition isn.c:77
int LOCKMODE
Definition lockdefs.h:26
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition lsyscache.c:2471
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
Oid exprCollation(const Node *expr)
Definition nodeFuncs.c:826
void ExecIndexBuildScanKeys(PlanState *planstate, Relation index, List *quals, bool isorderby, ScanKey *scanKeys, int *numScanKeys, IndexRuntimeKeyInfo **runtimeKeys, int *numRuntimeKeys, IndexArrayKeyInfo **arrayKeys, int *numArrayKeys)
static TupleTableSlot * ExecIndexScan(PlanState *pstate)
static int reorderqueue_cmp(const pairingheap_node *a, const pairingheap_node *b, void *arg)
#define makeNode(_type_)
Definition nodes.h:161
pairingheap * pairingheap_allocate(pairingheap_comparator compare, void *arg)
Definition pairingheap.c:42
#define forboth(cell1, list1, cell2, list2)
Definition pg_list.h:550
#define RelationGetDescr(relation)
Definition rel.h:542
void PrepareSortSupportFromOrderingOp(Oid orderingOp, SortSupport ssup)
int es_instrument
Definition execnodes.h:756
List * indexorderby
Definition plannodes.h:614
List * indexorderbyops
Definition plannodes.h:618
Scan scan
Definition plannodes.h:606
List * indexqualorig
Definition plannodes.h:612
Oid indexid
Definition plannodes.h:608
List * indexqual
Definition plannodes.h:610
List * indexorderbyorig
Definition plannodes.h:616
Definition nodes.h:135
Index scanrelid
Definition plannodes.h:544
MemoryContext ssup_cxt
Definition sortsupport.h:66
const TupleTableSlotOps * table_slot_callbacks(Relation relation)
Definition tableam.c:59
#define TTS_FLAG_OBEYS_NOT_NULL_CONSTRAINTS
Definition tuptable.h:102

References Assert, CurrentMemoryContext, EState::es_instrument, EXEC_FLAG_EXPLAIN_ONLY, exec_rt_fetch(), ExecAssignExprContext(), ExecAssignScanProjectionInfo(), ExecIndexBuildScanKeys(), ExecIndexScan(), ExecInitExprList(), ExecInitQual(), ExecInitResultTypeTL(), ExecInitScanTupleSlot(), ExecOpenScanRelation(), exprCollation(), exprType(), fb(), forboth, get_typlenbyval(), i, index_open(), IndexScan::indexid, IndexScan::indexorderby, IndexScan::indexorderbyops, IndexScan::indexorderbyorig, IndexScan::indexqual, IndexScan::indexqualorig, lfirst, lfirst_oid, list_length(), makeNode, pairingheap_allocate(), palloc(), palloc0(), palloc0_object, PrepareSortSupportFromOrderingOp(), RelationGetDescr, reorderqueue_cmp(), IndexScan::scan, Scan::scanrelid, SortSupportData::ssup_cxt, table_slot_callbacks(), and TTS_FLAG_OBEYS_NOT_NULL_CONSTRAINTS.

Referenced by ExecInitNode().

◆ ExecReScanIndexScan()

void ExecReScanIndexScan ( IndexScanState node)
extern

Definition at line 557 of file nodeIndexscan.c.

558{
559 /*
560 * If we are doing runtime key calculations (ie, any of the index key
561 * values weren't simple Consts), compute the new key values. But first,
562 * reset the context so we don't leak memory as each outer tuple is
563 * scanned. Note this assumes that we will recalculate *all* runtime keys
564 * on each call.
565 */
566 if (node->iss_NumRuntimeKeys != 0)
567 {
568 ExprContext *econtext = node->iss_RuntimeContext;
569
570 ResetExprContext(econtext);
572 node->iss_RuntimeKeys,
573 node->iss_NumRuntimeKeys);
574 }
575 node->iss_RuntimeKeysReady = true;
576
577 /* flush the reorder queue */
578 if (node->iss_ReorderQueue)
579 {
580 HeapTuple tuple;
581
583 {
584 tuple = reorderqueue_pop(node);
585 heap_freetuple(tuple);
586 }
587 }
588
589 /* reset index scan */
590 if (node->iss_ScanDesc)
592 node->iss_ScanKeys, node->iss_NumScanKeys,
594 node->iss_ReachedEnd = false;
595
596 ExecScanReScan(&node->ss);
597}
void ExecScanReScan(ScanState *node)
Definition execScan.c:108
#define ResetExprContext(econtext)
Definition executor.h:661
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1372
void ExecIndexEvalRuntimeKeys(ExprContext *econtext, IndexRuntimeKeyInfo *runtimeKeys, int numRuntimeKeys)
static HeapTuple reorderqueue_pop(IndexScanState *node)
#define pairingheap_is_empty(h)
Definition pairingheap.h:99
pairingheap * iss_ReorderQueue
Definition execnodes.h:1766
ExprContext * iss_RuntimeContext
Definition execnodes.h:1759
IndexRuntimeKeyInfo * iss_RuntimeKeys
Definition execnodes.h:1756

References ExecIndexEvalRuntimeKeys(), ExecScanReScan(), heap_freetuple(), index_rescan(), IndexScanState::iss_NumOrderByKeys, IndexScanState::iss_NumRuntimeKeys, IndexScanState::iss_NumScanKeys, IndexScanState::iss_OrderByKeys, IndexScanState::iss_ReachedEnd, IndexScanState::iss_ReorderQueue, IndexScanState::iss_RuntimeContext, IndexScanState::iss_RuntimeKeys, IndexScanState::iss_RuntimeKeysReady, IndexScanState::iss_ScanDesc, IndexScanState::iss_ScanKeys, pairingheap_is_empty, reorderqueue_pop(), ResetExprContext, and IndexScanState::ss.

Referenced by ExecReScan().