PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
nodeIndexscan.h File Reference
#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)
 
TupleTableSlotExecIndexScan (IndexScanState *node)
 
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 ExecIndexScanInitializeWorker (IndexScanState *node, shm_toc *toc)
 
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

void ExecEndIndexScan ( IndexScanState node)

Definition at line 820 of file nodeIndexscan.c.

References ExecClearTuple(), ExecCloseScanRelation(), ExecFreeExprContext(), FreeExprContext(), index_close(), index_endscan(), IndexScanState::iss_RelationDesc, IndexScanState::iss_RuntimeContext, IndexScanState::iss_ScanDesc, NoLock, ScanState::ps, PlanState::ps_ResultTupleSlot, IndexScanState::ss, ScanState::ss_currentRelation, and ScanState::ss_ScanTupleSlot.

Referenced by ExecEndNode().

821 {
822  Relation indexRelationDesc;
823  IndexScanDesc indexScanDesc;
824  Relation relation;
825 
826  /*
827  * extract information from the node
828  */
829  indexRelationDesc = node->iss_RelationDesc;
830  indexScanDesc = node->iss_ScanDesc;
831  relation = node->ss.ss_currentRelation;
832 
833  /*
834  * Free the exprcontext(s) ... now dead code, see ExecFreeExprContext
835  */
836 #ifdef NOT_USED
837  ExecFreeExprContext(&node->ss.ps);
838  if (node->iss_RuntimeContext)
839  FreeExprContext(node->iss_RuntimeContext, true);
840 #endif
841 
842  /*
843  * clear out tuple table slots
844  */
847 
848  /*
849  * close the index relation (no-op if we didn't open it)
850  */
851  if (indexScanDesc)
852  index_endscan(indexScanDesc);
853  if (indexRelationDesc)
854  index_close(indexRelationDesc, NoLock);
855 
856  /*
857  * close the heap relation.
858  */
859  ExecCloseScanRelation(relation);
860 }
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1293
Relation ss_currentRelation
Definition: execnodes.h:1291
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:686
PlanState ps
Definition: execnodes.h:1290
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1079
#define NoLock
Definition: lockdefs.h:34
void index_endscan(IndexScanDesc scan)
Definition: indexam.c:340
void FreeExprContext(ExprContext *econtext, bool isCommit)
Definition: execUtils.c:340
ScanState ss
Definition: execnodes.h:1374
void ExecCloseScanRelation(Relation scanrel)
Definition: execUtils.c:831
ExprContext * iss_RuntimeContext
Definition: execnodes.h:1384
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:176
IndexScanDesc iss_ScanDesc
Definition: execnodes.h:1386
Relation iss_RelationDesc
Definition: execnodes.h:1385
bool ExecIndexAdvanceArrayKeys ( IndexArrayKeyInfo arrayKeys,
int  numArrayKeys 
)

Definition at line 775 of file nodeIndexscan.c.

References IndexArrayKeyInfo::elem_nulls, IndexArrayKeyInfo::elem_values, IndexArrayKeyInfo::next_elem, IndexArrayKeyInfo::num_elems, IndexArrayKeyInfo::scan_key, ScanKeyData::sk_argument, ScanKeyData::sk_flags, and SK_ISNULL.

Referenced by MultiExecBitmapIndexScan().

776 {
777  bool found = false;
778  int j;
779 
780  /*
781  * Note we advance the rightmost array key most quickly, since it will
782  * correspond to the lowest-order index column among the available
783  * qualifications. This is hypothesized to result in better locality of
784  * access in the index.
785  */
786  for (j = numArrayKeys - 1; j >= 0; j--)
787  {
788  ScanKey scan_key = arrayKeys[j].scan_key;
789  int next_elem = arrayKeys[j].next_elem;
790  int num_elems = arrayKeys[j].num_elems;
791  Datum *elem_values = arrayKeys[j].elem_values;
792  bool *elem_nulls = arrayKeys[j].elem_nulls;
793 
794  if (next_elem >= num_elems)
795  {
796  next_elem = 0;
797  found = false; /* need to advance next array key */
798  }
799  else
800  found = true;
801  scan_key->sk_argument = elem_values[next_elem];
802  if (elem_nulls[next_elem])
803  scan_key->sk_flags |= SK_ISNULL;
804  else
805  scan_key->sk_flags &= ~SK_ISNULL;
806  arrayKeys[j].next_elem = next_elem + 1;
807  if (found)
808  break;
809  }
810 
811  return found;
812 }
Datum * elem_values
Definition: execnodes.h:1342
#define SK_ISNULL
Definition: skey.h:115
uintptr_t Datum
Definition: postgres.h:372
int sk_flags
Definition: skey.h:66
Datum sk_argument
Definition: skey.h:72
void ExecIndexBuildScanKeys ( PlanState planstate,
Relation  index,
List quals,
bool  isorderby,
ScanKey scanKeys,
int *  numScanKeys,
IndexRuntimeKeyInfo **  runtimeKeys,
int *  numRuntimeKeys,
IndexArrayKeyInfo **  arrayKeys,
int *  numArrayKeys 
)

Definition at line 1159 of file nodeIndexscan.c.

References IndexAmRoutine::amsearcharray, arg, NullTest::arg, ScalarArrayOpExpr::args, IndexArrayKeyInfo::array_expr, Assert, BTORDER_PROC, BTREE_AM_OID, elog, ERROR, ExecInitExpr(), get_leftop(), get_op_opfamily_properties(), get_opfamily_proc(), get_rightop(), INDEX_VAR, ScalarArrayOpExpr::inputcollid, RowCompareExpr::inputcollids, InvalidOid, InvalidStrategy, IS_NOT_NULL, IS_NULL, IsA, IndexRuntimeKeyInfo::key_expr, IndexRuntimeKeyInfo::key_toastable, RowCompareExpr::largs, lfirst, lfirst_oid, linitial, list_head(), list_length(), lnext, lsecond, MemSet, nodeTag, NULL, NullTest::nulltesttype, ScalarArrayOpExpr::opfuncid, ScalarArrayOpExpr::opno, RowCompareExpr::opnos, palloc(), palloc0(), pfree(), PointerGetDatum, RowCompareExpr::rargs, RowCompareExpr::rctype, RelationData::rd_amroutine, RelationData::rd_index, RelationData::rd_opfamily, RelationData::rd_rel, repalloc(), IndexRuntimeKeyInfo::scan_key, IndexArrayKeyInfo::scan_key, ScanKeyEntryInitialize(), ScanKeyData::sk_argument, ScanKeyData::sk_attno, ScanKeyData::sk_flags, SK_ISNULL, SK_ORDER_BY, SK_ROW_END, SK_ROW_HEADER, SK_ROW_MEMBER, SK_SEARCHARRAY, SK_SEARCHNOTNULL, SK_SEARCHNULL, ScanKeyData::sk_strategy, TypeIsToastable, and ScalarArrayOpExpr::useOr.

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

1164 {
1165  ListCell *qual_cell;
1166  ScanKey scan_keys;
1167  IndexRuntimeKeyInfo *runtime_keys;
1168  IndexArrayKeyInfo *array_keys;
1169  int n_scan_keys;
1170  int n_runtime_keys;
1171  int max_runtime_keys;
1172  int n_array_keys;
1173  int j;
1174 
1175  /* Allocate array for ScanKey structs: one per qual */
1176  n_scan_keys = list_length(quals);
1177  scan_keys = (ScanKey) palloc(n_scan_keys * sizeof(ScanKeyData));
1178 
1179  /*
1180  * runtime_keys array is dynamically resized as needed. We handle it this
1181  * way so that the same runtime keys array can be shared between
1182  * indexquals and indexorderbys, which will be processed in separate calls
1183  * of this function. Caller must be sure to pass in NULL/0 for first
1184  * call.
1185  */
1186  runtime_keys = *runtimeKeys;
1187  n_runtime_keys = max_runtime_keys = *numRuntimeKeys;
1188 
1189  /* Allocate array_keys as large as it could possibly need to be */
1190  array_keys = (IndexArrayKeyInfo *)
1191  palloc0(n_scan_keys * sizeof(IndexArrayKeyInfo));
1192  n_array_keys = 0;
1193 
1194  /*
1195  * for each opclause in the given qual, convert the opclause into a single
1196  * scan key
1197  */
1198  j = 0;
1199  foreach(qual_cell, quals)
1200  {
1201  Expr *clause = (Expr *) lfirst(qual_cell);
1202  ScanKey this_scan_key = &scan_keys[j++];
1203  Oid opno; /* operator's OID */
1204  RegProcedure opfuncid; /* operator proc id used in scan */
1205  Oid opfamily; /* opfamily of index column */
1206  int op_strategy; /* operator's strategy number */
1207  Oid op_lefttype; /* operator's declared input types */
1208  Oid op_righttype;
1209  Expr *leftop; /* expr on lhs of operator */
1210  Expr *rightop; /* expr on rhs ... */
1211  AttrNumber varattno; /* att number used in scan */
1212 
1213  if (IsA(clause, OpExpr))
1214  {
1215  /* indexkey op const or indexkey op expression */
1216  int flags = 0;
1217  Datum scanvalue;
1218 
1219  opno = ((OpExpr *) clause)->opno;
1220  opfuncid = ((OpExpr *) clause)->opfuncid;
1221 
1222  /*
1223  * leftop should be the index key Var, possibly relabeled
1224  */
1225  leftop = (Expr *) get_leftop(clause);
1226 
1227  if (leftop && IsA(leftop, RelabelType))
1228  leftop = ((RelabelType *) leftop)->arg;
1229 
1230  Assert(leftop != NULL);
1231 
1232  if (!(IsA(leftop, Var) &&
1233  ((Var *) leftop)->varno == INDEX_VAR))
1234  elog(ERROR, "indexqual doesn't have key on left side");
1235 
1236  varattno = ((Var *) leftop)->varattno;
1237  if (varattno < 1 || varattno > index->rd_index->indnatts)
1238  elog(ERROR, "bogus index qualification");
1239 
1240  /*
1241  * We have to look up the operator's strategy number. This
1242  * provides a cross-check that the operator does match the index.
1243  */
1244  opfamily = index->rd_opfamily[varattno - 1];
1245 
1246  get_op_opfamily_properties(opno, opfamily, isorderby,
1247  &op_strategy,
1248  &op_lefttype,
1249  &op_righttype);
1250 
1251  if (isorderby)
1252  flags |= SK_ORDER_BY;
1253 
1254  /*
1255  * rightop is the constant or variable comparison value
1256  */
1257  rightop = (Expr *) get_rightop(clause);
1258 
1259  if (rightop && IsA(rightop, RelabelType))
1260  rightop = ((RelabelType *) rightop)->arg;
1261 
1262  Assert(rightop != NULL);
1263 
1264  if (IsA(rightop, Const))
1265  {
1266  /* OK, simple constant comparison value */
1267  scanvalue = ((Const *) rightop)->constvalue;
1268  if (((Const *) rightop)->constisnull)
1269  flags |= SK_ISNULL;
1270  }
1271  else
1272  {
1273  /* Need to treat this one as a runtime key */
1274  if (n_runtime_keys >= max_runtime_keys)
1275  {
1276  if (max_runtime_keys == 0)
1277  {
1278  max_runtime_keys = 8;
1279  runtime_keys = (IndexRuntimeKeyInfo *)
1280  palloc(max_runtime_keys * sizeof(IndexRuntimeKeyInfo));
1281  }
1282  else
1283  {
1284  max_runtime_keys *= 2;
1285  runtime_keys = (IndexRuntimeKeyInfo *)
1286  repalloc(runtime_keys, max_runtime_keys * sizeof(IndexRuntimeKeyInfo));
1287  }
1288  }
1289  runtime_keys[n_runtime_keys].scan_key = this_scan_key;
1290  runtime_keys[n_runtime_keys].key_expr =
1291  ExecInitExpr(rightop, planstate);
1292  runtime_keys[n_runtime_keys].key_toastable =
1293  TypeIsToastable(op_righttype);
1294  n_runtime_keys++;
1295  scanvalue = (Datum) 0;
1296  }
1297 
1298  /*
1299  * initialize the scan key's fields appropriately
1300  */
1301  ScanKeyEntryInitialize(this_scan_key,
1302  flags,
1303  varattno, /* attribute number to scan */
1304  op_strategy, /* op's strategy */
1305  op_righttype, /* strategy subtype */
1306  ((OpExpr *) clause)->inputcollid, /* collation */
1307  opfuncid, /* reg proc to use */
1308  scanvalue); /* constant */
1309  }
1310  else if (IsA(clause, RowCompareExpr))
1311  {
1312  /* (indexkey, indexkey, ...) op (expression, expression, ...) */
1313  RowCompareExpr *rc = (RowCompareExpr *) clause;
1314  ListCell *largs_cell = list_head(rc->largs);
1315  ListCell *rargs_cell = list_head(rc->rargs);
1316  ListCell *opnos_cell = list_head(rc->opnos);
1317  ListCell *collids_cell = list_head(rc->inputcollids);
1318  ScanKey first_sub_key;
1319  int n_sub_key;
1320 
1321  Assert(!isorderby);
1322 
1323  first_sub_key = (ScanKey)
1324  palloc(list_length(rc->opnos) * sizeof(ScanKeyData));
1325  n_sub_key = 0;
1326 
1327  /* Scan RowCompare columns and generate subsidiary ScanKey items */
1328  while (opnos_cell != NULL)
1329  {
1330  ScanKey this_sub_key = &first_sub_key[n_sub_key];
1331  int flags = SK_ROW_MEMBER;
1332  Datum scanvalue;
1333  Oid inputcollation;
1334 
1335  /*
1336  * leftop should be the index key Var, possibly relabeled
1337  */
1338  leftop = (Expr *) lfirst(largs_cell);
1339  largs_cell = lnext(largs_cell);
1340 
1341  if (leftop && IsA(leftop, RelabelType))
1342  leftop = ((RelabelType *) leftop)->arg;
1343 
1344  Assert(leftop != NULL);
1345 
1346  if (!(IsA(leftop, Var) &&
1347  ((Var *) leftop)->varno == INDEX_VAR))
1348  elog(ERROR, "indexqual doesn't have key on left side");
1349 
1350  varattno = ((Var *) leftop)->varattno;
1351 
1352  /*
1353  * We have to look up the operator's associated btree support
1354  * function
1355  */
1356  opno = lfirst_oid(opnos_cell);
1357  opnos_cell = lnext(opnos_cell);
1358 
1359  if (index->rd_rel->relam != BTREE_AM_OID ||
1360  varattno < 1 || varattno > index->rd_index->indnatts)
1361  elog(ERROR, "bogus RowCompare index qualification");
1362  opfamily = index->rd_opfamily[varattno - 1];
1363 
1364  get_op_opfamily_properties(opno, opfamily, isorderby,
1365  &op_strategy,
1366  &op_lefttype,
1367  &op_righttype);
1368 
1369  if (op_strategy != rc->rctype)
1370  elog(ERROR, "RowCompare index qualification contains wrong operator");
1371 
1372  opfuncid = get_opfamily_proc(opfamily,
1373  op_lefttype,
1374  op_righttype,
1375  BTORDER_PROC);
1376 
1377  inputcollation = lfirst_oid(collids_cell);
1378  collids_cell = lnext(collids_cell);
1379 
1380  /*
1381  * rightop is the constant or variable comparison value
1382  */
1383  rightop = (Expr *) lfirst(rargs_cell);
1384  rargs_cell = lnext(rargs_cell);
1385 
1386  if (rightop && IsA(rightop, RelabelType))
1387  rightop = ((RelabelType *) rightop)->arg;
1388 
1389  Assert(rightop != NULL);
1390 
1391  if (IsA(rightop, Const))
1392  {
1393  /* OK, simple constant comparison value */
1394  scanvalue = ((Const *) rightop)->constvalue;
1395  if (((Const *) rightop)->constisnull)
1396  flags |= SK_ISNULL;
1397  }
1398  else
1399  {
1400  /* Need to treat this one as a runtime key */
1401  if (n_runtime_keys >= max_runtime_keys)
1402  {
1403  if (max_runtime_keys == 0)
1404  {
1405  max_runtime_keys = 8;
1406  runtime_keys = (IndexRuntimeKeyInfo *)
1407  palloc(max_runtime_keys * sizeof(IndexRuntimeKeyInfo));
1408  }
1409  else
1410  {
1411  max_runtime_keys *= 2;
1412  runtime_keys = (IndexRuntimeKeyInfo *)
1413  repalloc(runtime_keys, max_runtime_keys * sizeof(IndexRuntimeKeyInfo));
1414  }
1415  }
1416  runtime_keys[n_runtime_keys].scan_key = this_sub_key;
1417  runtime_keys[n_runtime_keys].key_expr =
1418  ExecInitExpr(rightop, planstate);
1419  runtime_keys[n_runtime_keys].key_toastable =
1420  TypeIsToastable(op_righttype);
1421  n_runtime_keys++;
1422  scanvalue = (Datum) 0;
1423  }
1424 
1425  /*
1426  * initialize the subsidiary scan key's fields appropriately
1427  */
1428  ScanKeyEntryInitialize(this_sub_key,
1429  flags,
1430  varattno, /* attribute number */
1431  op_strategy, /* op's strategy */
1432  op_righttype, /* strategy subtype */
1433  inputcollation, /* collation */
1434  opfuncid, /* reg proc to use */
1435  scanvalue); /* constant */
1436  n_sub_key++;
1437  }
1438 
1439  /* Mark the last subsidiary scankey correctly */
1440  first_sub_key[n_sub_key - 1].sk_flags |= SK_ROW_END;
1441 
1442  /*
1443  * We don't use ScanKeyEntryInitialize for the header because it
1444  * isn't going to contain a valid sk_func pointer.
1445  */
1446  MemSet(this_scan_key, 0, sizeof(ScanKeyData));
1447  this_scan_key->sk_flags = SK_ROW_HEADER;
1448  this_scan_key->sk_attno = first_sub_key->sk_attno;
1449  this_scan_key->sk_strategy = rc->rctype;
1450  /* sk_subtype, sk_collation, sk_func not used in a header */
1451  this_scan_key->sk_argument = PointerGetDatum(first_sub_key);
1452  }
1453  else if (IsA(clause, ScalarArrayOpExpr))
1454  {
1455  /* indexkey op ANY (array-expression) */
1456  ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
1457  int flags = 0;
1458  Datum scanvalue;
1459 
1460  Assert(!isorderby);
1461 
1462  Assert(saop->useOr);
1463  opno = saop->opno;
1464  opfuncid = saop->opfuncid;
1465 
1466  /*
1467  * leftop should be the index key Var, possibly relabeled
1468  */
1469  leftop = (Expr *) linitial(saop->args);
1470 
1471  if (leftop && IsA(leftop, RelabelType))
1472  leftop = ((RelabelType *) leftop)->arg;
1473 
1474  Assert(leftop != NULL);
1475 
1476  if (!(IsA(leftop, Var) &&
1477  ((Var *) leftop)->varno == INDEX_VAR))
1478  elog(ERROR, "indexqual doesn't have key on left side");
1479 
1480  varattno = ((Var *) leftop)->varattno;
1481  if (varattno < 1 || varattno > index->rd_index->indnatts)
1482  elog(ERROR, "bogus index qualification");
1483 
1484  /*
1485  * We have to look up the operator's strategy number. This
1486  * provides a cross-check that the operator does match the index.
1487  */
1488  opfamily = index->rd_opfamily[varattno - 1];
1489 
1490  get_op_opfamily_properties(opno, opfamily, isorderby,
1491  &op_strategy,
1492  &op_lefttype,
1493  &op_righttype);
1494 
1495  /*
1496  * rightop is the constant or variable array value
1497  */
1498  rightop = (Expr *) lsecond(saop->args);
1499 
1500  if (rightop && IsA(rightop, RelabelType))
1501  rightop = ((RelabelType *) rightop)->arg;
1502 
1503  Assert(rightop != NULL);
1504 
1505  if (index->rd_amroutine->amsearcharray)
1506  {
1507  /* Index AM will handle this like a simple operator */
1508  flags |= SK_SEARCHARRAY;
1509  if (IsA(rightop, Const))
1510  {
1511  /* OK, simple constant comparison value */
1512  scanvalue = ((Const *) rightop)->constvalue;
1513  if (((Const *) rightop)->constisnull)
1514  flags |= SK_ISNULL;
1515  }
1516  else
1517  {
1518  /* Need to treat this one as a runtime key */
1519  if (n_runtime_keys >= max_runtime_keys)
1520  {
1521  if (max_runtime_keys == 0)
1522  {
1523  max_runtime_keys = 8;
1524  runtime_keys = (IndexRuntimeKeyInfo *)
1525  palloc(max_runtime_keys * sizeof(IndexRuntimeKeyInfo));
1526  }
1527  else
1528  {
1529  max_runtime_keys *= 2;
1530  runtime_keys = (IndexRuntimeKeyInfo *)
1531  repalloc(runtime_keys, max_runtime_keys * sizeof(IndexRuntimeKeyInfo));
1532  }
1533  }
1534  runtime_keys[n_runtime_keys].scan_key = this_scan_key;
1535  runtime_keys[n_runtime_keys].key_expr =
1536  ExecInitExpr(rightop, planstate);
1537 
1538  /*
1539  * Careful here: the runtime expression is not of
1540  * op_righttype, but rather is an array of same; so
1541  * TypeIsToastable() isn't helpful. However, we can
1542  * assume that all array types are toastable.
1543  */
1544  runtime_keys[n_runtime_keys].key_toastable = true;
1545  n_runtime_keys++;
1546  scanvalue = (Datum) 0;
1547  }
1548  }
1549  else
1550  {
1551  /* Executor has to expand the array value */
1552  array_keys[n_array_keys].scan_key = this_scan_key;
1553  array_keys[n_array_keys].array_expr =
1554  ExecInitExpr(rightop, planstate);
1555  /* the remaining fields were zeroed by palloc0 */
1556  n_array_keys++;
1557  scanvalue = (Datum) 0;
1558  }
1559 
1560  /*
1561  * initialize the scan key's fields appropriately
1562  */
1563  ScanKeyEntryInitialize(this_scan_key,
1564  flags,
1565  varattno, /* attribute number to scan */
1566  op_strategy, /* op's strategy */
1567  op_righttype, /* strategy subtype */
1568  saop->inputcollid, /* collation */
1569  opfuncid, /* reg proc to use */
1570  scanvalue); /* constant */
1571  }
1572  else if (IsA(clause, NullTest))
1573  {
1574  /* indexkey IS NULL or indexkey IS NOT NULL */
1575  NullTest *ntest = (NullTest *) clause;
1576  int flags;
1577 
1578  Assert(!isorderby);
1579 
1580  /*
1581  * argument should be the index key Var, possibly relabeled
1582  */
1583  leftop = ntest->arg;
1584 
1585  if (leftop && IsA(leftop, RelabelType))
1586  leftop = ((RelabelType *) leftop)->arg;
1587 
1588  Assert(leftop != NULL);
1589 
1590  if (!(IsA(leftop, Var) &&
1591  ((Var *) leftop)->varno == INDEX_VAR))
1592  elog(ERROR, "NullTest indexqual has wrong key");
1593 
1594  varattno = ((Var *) leftop)->varattno;
1595 
1596  /*
1597  * initialize the scan key's fields appropriately
1598  */
1599  switch (ntest->nulltesttype)
1600  {
1601  case IS_NULL:
1602  flags = SK_ISNULL | SK_SEARCHNULL;
1603  break;
1604  case IS_NOT_NULL:
1605  flags = SK_ISNULL | SK_SEARCHNOTNULL;
1606  break;
1607  default:
1608  elog(ERROR, "unrecognized nulltesttype: %d",
1609  (int) ntest->nulltesttype);
1610  flags = 0; /* keep compiler quiet */
1611  break;
1612  }
1613 
1614  ScanKeyEntryInitialize(this_scan_key,
1615  flags,
1616  varattno, /* attribute number to scan */
1617  InvalidStrategy, /* no strategy */
1618  InvalidOid, /* no strategy subtype */
1619  InvalidOid, /* no collation */
1620  InvalidOid, /* no reg proc for this */
1621  (Datum) 0); /* constant */
1622  }
1623  else
1624  elog(ERROR, "unsupported indexqual type: %d",
1625  (int) nodeTag(clause));
1626  }
1627 
1628  Assert(n_runtime_keys <= max_runtime_keys);
1629 
1630  /* Get rid of any unused arrays */
1631  if (n_array_keys == 0)
1632  {
1633  pfree(array_keys);
1634  array_keys = NULL;
1635  }
1636 
1637  /*
1638  * Return info to our caller.
1639  */
1640  *scanKeys = scan_keys;
1641  *numScanKeys = n_scan_keys;
1642  *runtimeKeys = runtime_keys;
1643  *numRuntimeKeys = n_runtime_keys;
1644  if (arrayKeys)
1645  {
1646  *arrayKeys = array_keys;
1647  *numArrayKeys = n_array_keys;
1648  }
1649  else if (n_array_keys != 0)
1650  elog(ERROR, "ScalarArrayOpExpr index qual found where not allowed");
1651 }
#define InvalidStrategy
Definition: stratnum.h:24
#define SK_ROW_MEMBER
Definition: skey.h:118
#define IsA(nodeptr, _type_)
Definition: nodes.h:571
#define BTORDER_PROC
Definition: nbtree.h:229
#define SK_ORDER_BY
Definition: skey.h:124
#define PointerGetDatum(X)
Definition: postgres.h:562
RowCompareType rctype
Definition: primnodes.h:1029
regproc RegProcedure
Definition: c.h:395
#define BTREE_AM_OID
Definition: pg_am.h:70
#define MemSet(start, val, len)
Definition: c.h:857
struct ScanKeyData ScanKeyData
Form_pg_class rd_rel
Definition: rel.h:113
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:163
#define SK_SEARCHARRAY
Definition: skey.h:120
struct IndexAmRoutine * rd_amroutine
Definition: rel.h:177
#define lsecond(l)
Definition: pg_list.h:114
#define SK_ROW_END
Definition: skey.h:119
Form_pg_index rd_index
Definition: rel.h:155
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execQual.c:4267
void pfree(void *pointer)
Definition: mcxt.c:950
#define linitial(l)
Definition: pg_list.h:110
#define ERROR
Definition: elog.h:43
Node * get_leftop(const Expr *clause)
Definition: clauses.c:198
StrategyNumber sk_strategy
Definition: skey.h:68
Expr * arg
Definition: primnodes.h:1178
ExprState * key_expr
Definition: execnodes.h:1332
void ScanKeyEntryInitialize(ScanKey entry, int flags, AttrNumber attributeNumber, StrategyNumber strategy, Oid subtype, Oid collation, RegProcedure procedure, Datum argument)
Definition: scankey.c:32
ScanKeyData * ScanKey
Definition: skey.h:75
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define SK_SEARCHNOTNULL
Definition: skey.h:122
Oid * rd_opfamily
Definition: rel.h:178
#define SK_ISNULL
Definition: skey.h:115
#define lnext(lc)
Definition: pg_list.h:105
#define SK_ROW_HEADER
Definition: skey.h:117
void * palloc0(Size size)
Definition: mcxt.c:878
uintptr_t Datum
Definition: postgres.h:372
NullTestType nulltesttype
Definition: primnodes.h:1179
bool amsearcharray
Definition: amapi.h:183
#define InvalidOid
Definition: postgres_ext.h:36
ExprState * array_expr
Definition: execnodes.h:1339
int sk_flags
Definition: skey.h:66
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition: lsyscache.c:744
static int list_length(const List *l)
Definition: pg_list.h:89
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:963
#define nodeTag(nodeptr)
Definition: nodes.h:525
Node * get_rightop(const Expr *clause)
Definition: clauses.c:215
void get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op, int *strategy, Oid *lefttype, Oid *righttype)
Definition: lsyscache.c:133
void * palloc(Size size)
Definition: mcxt.c:849
void * arg
#define elog
Definition: elog.h:219
List * inputcollids
Definition: primnodes.h:1032
#define INDEX_VAR
Definition: primnodes.h:155
#define TypeIsToastable(typid)
Definition: lsyscache.h:167
Datum sk_argument
Definition: skey.h:72
int16 AttrNumber
Definition: attnum.h:21
#define SK_SEARCHNULL
Definition: skey.h:121
AttrNumber sk_attno
Definition: skey.h:67
#define lfirst_oid(lc)
Definition: pg_list.h:108
bool ExecIndexEvalArrayKeys ( ExprContext econtext,
IndexArrayKeyInfo arrayKeys,
int  numArrayKeys 
)

Definition at line 696 of file nodeIndexscan.c.

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

Referenced by ExecReScanBitmapIndexScan().

698 {
699  bool result = true;
700  int j;
701  MemoryContext oldContext;
702 
703  /* We want to keep the arrays in per-tuple memory */
704  oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
705 
706  for (j = 0; j < numArrayKeys; j++)
707  {
708  ScanKey scan_key = arrayKeys[j].scan_key;
709  ExprState *array_expr = arrayKeys[j].array_expr;
710  Datum arraydatum;
711  bool isNull;
712  ArrayType *arrayval;
713  int16 elmlen;
714  bool elmbyval;
715  char elmalign;
716  int num_elems;
717  Datum *elem_values;
718  bool *elem_nulls;
719 
720  /*
721  * Compute and deconstruct the array expression. (Notes in
722  * ExecIndexEvalRuntimeKeys() apply here too.)
723  */
724  arraydatum = ExecEvalExpr(array_expr,
725  econtext,
726  &isNull);
727  if (isNull)
728  {
729  result = false;
730  break; /* no point in evaluating more */
731  }
732  arrayval = DatumGetArrayTypeP(arraydatum);
733  /* We could cache this data, but not clear it's worth it */
735  &elmlen, &elmbyval, &elmalign);
736  deconstruct_array(arrayval,
737  ARR_ELEMTYPE(arrayval),
738  elmlen, elmbyval, elmalign,
739  &elem_values, &elem_nulls, &num_elems);
740  if (num_elems <= 0)
741  {
742  result = false;
743  break; /* no point in evaluating more */
744  }
745 
746  /*
747  * Note: we expect the previous array data, if any, to be
748  * automatically freed by resetting the per-tuple context; hence no
749  * pfree's here.
750  */
751  arrayKeys[j].elem_values = elem_values;
752  arrayKeys[j].elem_nulls = elem_nulls;
753  arrayKeys[j].num_elems = num_elems;
754  scan_key->sk_argument = elem_values[0];
755  if (elem_nulls[0])
756  scan_key->sk_flags |= SK_ISNULL;
757  else
758  scan_key->sk_flags &= ~SK_ISNULL;
759  arrayKeys[j].next_elem = 1;
760  }
761 
762  MemoryContextSwitchTo(oldContext);
763 
764  return result;
765 }
Datum * elem_values
Definition: execnodes.h:1342
signed short int16
Definition: c.h:255
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:1989
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:136
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
return result
Definition: formatting.c:1618
#define ExecEvalExpr(expr, econtext, isNull)
Definition: executor.h:73
#define SK_ISNULL
Definition: skey.h:115
uintptr_t Datum
Definition: postgres.h:372
ExprState * array_expr
Definition: execnodes.h:1339
int sk_flags
Definition: skey.h:66
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
Datum sk_argument
Definition: skey.h:72
#define ARR_ELEMTYPE(a)
Definition: array.h:273
#define DatumGetArrayTypeP(X)
Definition: array.h:242
void ExecIndexEvalRuntimeKeys ( ExprContext econtext,
IndexRuntimeKeyInfo runtimeKeys,
int  numRuntimeKeys 
)

Definition at line 634 of file nodeIndexscan.c.

References ExprContext::ecxt_per_tuple_memory, ExecEvalExpr, IndexRuntimeKeyInfo::key_expr, MemoryContextSwitchTo(), PG_DETOAST_DATUM, PointerGetDatum, IndexRuntimeKeyInfo::scan_key, ScanKeyData::sk_argument, ScanKeyData::sk_flags, and SK_ISNULL.

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

636 {
637  int j;
638  MemoryContext oldContext;
639 
640  /* We want to keep the key values in per-tuple memory */
641  oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
642 
643  for (j = 0; j < numRuntimeKeys; j++)
644  {
645  ScanKey scan_key = runtimeKeys[j].scan_key;
646  ExprState *key_expr = runtimeKeys[j].key_expr;
647  Datum scanvalue;
648  bool isNull;
649 
650  /*
651  * For each run-time key, extract the run-time expression and evaluate
652  * it with respect to the current context. We then stick the result
653  * into the proper scan key.
654  *
655  * Note: the result of the eval could be a pass-by-ref value that's
656  * stored in some outer scan's tuple, not in
657  * econtext->ecxt_per_tuple_memory. We assume that the outer tuple
658  * will stay put throughout our scan. If this is wrong, we could copy
659  * the result into our context explicitly, but I think that's not
660  * necessary.
661  *
662  * It's also entirely possible that the result of the eval is a
663  * toasted value. In this case we should forcibly detoast it, to
664  * avoid repeat detoastings each time the value is examined by an
665  * index support function.
666  */
667  scanvalue = ExecEvalExpr(key_expr,
668  econtext,
669  &isNull);
670  if (isNull)
671  {
672  scan_key->sk_argument = scanvalue;
673  scan_key->sk_flags |= SK_ISNULL;
674  }
675  else
676  {
677  if (runtimeKeys[j].key_toastable)
678  scanvalue = PointerGetDatum(PG_DETOAST_DATUM(scanvalue));
679  scan_key->sk_argument = scanvalue;
680  scan_key->sk_flags &= ~SK_ISNULL;
681  }
682  }
683 
684  MemoryContextSwitchTo(oldContext);
685 }
#define PointerGetDatum(X)
Definition: postgres.h:562
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:136
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define ExecEvalExpr(expr, econtext, isNull)
Definition: executor.h:73
ExprState * key_expr
Definition: execnodes.h:1332
#define SK_ISNULL
Definition: skey.h:115
uintptr_t Datum
Definition: postgres.h:372
int sk_flags
Definition: skey.h:66
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:197
Datum sk_argument
Definition: skey.h:72
void ExecIndexMarkPos ( IndexScanState node)

Definition at line 867 of file nodeIndexscan.c.

References index_markpos(), and IndexScanState::iss_ScanDesc.

Referenced by ExecMarkPos().

868 {
870 }
void index_markpos(IndexScanDesc scan)
Definition: indexam.c:370
IndexScanDesc iss_ScanDesc
Definition: execnodes.h:1386
void ExecIndexRestrPos ( IndexScanState node)

Definition at line 877 of file nodeIndexscan.c.

References index_restrpos(), and IndexScanState::iss_ScanDesc.

Referenced by ExecRestrPos().

878 {
880 }
void index_restrpos(IndexScanDesc scan)
Definition: indexam.c:395
IndexScanDesc iss_ScanDesc
Definition: execnodes.h:1386
TupleTableSlot* ExecIndexScan ( IndexScanState node)

Definition at line 539 of file nodeIndexscan.c.

References ExecReScan(), ExecScan(), IndexNext(), IndexNextWithReorder(), IndexRecheck(), IndexScanState::iss_NumOrderByKeys, IndexScanState::iss_NumRuntimeKeys, IndexScanState::iss_RuntimeKeysReady, and IndexScanState::ss.

Referenced by ExecProcNode().

540 {
541  /*
542  * If we have runtime keys and they've not already been set up, do it now.
543  */
544  if (node->iss_NumRuntimeKeys != 0 && !node->iss_RuntimeKeysReady)
545  ExecReScan((PlanState *) node);
546 
547  if (node->iss_NumOrderByKeys > 0)
548  return ExecScan(&node->ss,
551  else
552  return ExecScan(&node->ss,
555 }
static bool IndexRecheck(IndexScanState *node, TupleTableSlot *slot)
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition: execScan.c:121
void ExecReScan(PlanState *node)
Definition: execAmi.c:74
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition: executor.h:272
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:273
int iss_NumRuntimeKeys
Definition: execnodes.h:1382
bool iss_RuntimeKeysReady
Definition: execnodes.h:1383
static TupleTableSlot * IndexNext(IndexScanState *node)
Definition: nodeIndexscan.c:79
static TupleTableSlot * IndexNextWithReorder(IndexScanState *node)
ScanState ss
Definition: execnodes.h:1374
int iss_NumOrderByKeys
Definition: execnodes.h:1380
void ExecIndexScanEstimate ( IndexScanState node,
ParallelContext pcxt 
)

Definition at line 1665 of file nodeIndexscan.c.

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

Referenced by ExecParallelEstimate().

1667 {
1668  EState *estate = node->ss.ps.state;
1669 
1671  estate->es_snapshot);
1673  shm_toc_estimate_keys(&pcxt->estimator, 1);
1674 }
shm_toc_estimator estimator
Definition: parallel.h:42
Snapshot es_snapshot
Definition: execnodes.h:372
EState * state
Definition: execnodes.h:1051
#define shm_toc_estimate_chunk(e, sz)
Definition: shm_toc.h:49
Size index_parallelscan_estimate(Relation indexRelation, Snapshot snapshot)
Definition: indexam.c:417
PlanState ps
Definition: execnodes.h:1290
ScanState ss
Definition: execnodes.h:1374
#define shm_toc_estimate_keys(e, cnt)
Definition: shm_toc.h:52
Relation iss_RelationDesc
Definition: execnodes.h:1385
void ExecIndexScanInitializeDSM ( IndexScanState node,
ParallelContext pcxt 
)

Definition at line 1683 of file nodeIndexscan.c.

References EState::es_snapshot, index_beginscan_parallel(), index_parallelscan_initialize(), index_rescan(), 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, shm_toc_allocate(), shm_toc_insert(), IndexScanState::ss, ScanState::ss_currentRelation, PlanState::state, and ParallelContext::toc.

Referenced by ExecParallelInitializeDSM().

1685 {
1686  EState *estate = node->ss.ps.state;
1687  ParallelIndexScanDesc piscan;
1688 
1689  piscan = shm_toc_allocate(pcxt->toc, node->iss_PscanLen);
1691  node->iss_RelationDesc,
1692  estate->es_snapshot,
1693  piscan);
1694  shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, piscan);
1695  node->iss_ScanDesc =
1697  node->iss_RelationDesc,
1698  node->iss_NumScanKeys,
1699  node->iss_NumOrderByKeys,
1700  piscan);
1701 
1702  /*
1703  * If no run-time keys to calculate or they are ready, go ahead and pass
1704  * the scankeys to the index AM.
1705  */
1706  if (node->iss_NumRuntimeKeys == 0 || node->iss_RuntimeKeysReady)
1707  index_rescan(node->iss_ScanDesc,
1708  node->iss_ScanKeys, node->iss_NumScanKeys,
1709  node->iss_OrderByKeys, node->iss_NumOrderByKeys);
1710 }
IndexScanDesc index_beginscan_parallel(Relation heaprel, Relation indexrel, int nkeys, int norderbys, ParallelIndexScanDesc pscan)
Definition: indexam.c:496
int plan_node_id
Definition: plannodes.h:131
void index_rescan(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int norderbys)
Definition: indexam.c:310
Snapshot es_snapshot
Definition: execnodes.h:372
Relation ss_currentRelation
Definition: execnodes.h:1291
EState * state
Definition: execnodes.h:1051
ScanKey iss_ScanKeys
Definition: execnodes.h:1377
PlanState ps
Definition: execnodes.h:1290
int iss_NumRuntimeKeys
Definition: execnodes.h:1382
bool iss_RuntimeKeysReady
Definition: execnodes.h:1383
Plan * plan
Definition: execnodes.h:1049
ScanState ss
Definition: execnodes.h:1374
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
Definition: shm_toc.c:83
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
Definition: shm_toc.c:161
void index_parallelscan_initialize(Relation heapRelation, Relation indexRelation, Snapshot snapshot, ParallelIndexScanDesc target)
Definition: indexam.c:450
int iss_NumOrderByKeys
Definition: execnodes.h:1380
IndexScanDesc iss_ScanDesc
Definition: execnodes.h:1386
shm_toc * toc
Definition: parallel.h:45
Relation iss_RelationDesc
Definition: execnodes.h:1385
ScanKey iss_OrderByKeys
Definition: execnodes.h:1379
void ExecIndexScanInitializeWorker ( IndexScanState node,
shm_toc toc 
)

Definition at line 1719 of file nodeIndexscan.c.

References index_beginscan_parallel(), index_rescan(), 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, shm_toc_lookup(), IndexScanState::ss, and ScanState::ss_currentRelation.

Referenced by ExecParallelInitializeWorker().

1720 {
1721  ParallelIndexScanDesc piscan;
1722 
1723  piscan = shm_toc_lookup(toc, node->ss.ps.plan->plan_node_id);
1724  node->iss_ScanDesc =
1726  node->iss_RelationDesc,
1727  node->iss_NumScanKeys,
1728  node->iss_NumOrderByKeys,
1729  piscan);
1730 
1731  /*
1732  * If no run-time keys to calculate or they are ready, go ahead and pass
1733  * the scankeys to the index AM.
1734  */
1735  if (node->iss_NumRuntimeKeys == 0 || node->iss_RuntimeKeysReady)
1736  index_rescan(node->iss_ScanDesc,
1737  node->iss_ScanKeys, node->iss_NumScanKeys,
1738  node->iss_OrderByKeys, node->iss_NumOrderByKeys);
1739 }
IndexScanDesc index_beginscan_parallel(Relation heaprel, Relation indexrel, int nkeys, int norderbys, ParallelIndexScanDesc pscan)
Definition: indexam.c:496
int plan_node_id
Definition: plannodes.h:131
void index_rescan(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int norderbys)
Definition: indexam.c:310
Relation ss_currentRelation
Definition: execnodes.h:1291
ScanKey iss_ScanKeys
Definition: execnodes.h:1377
PlanState ps
Definition: execnodes.h:1290
void * shm_toc_lookup(shm_toc *toc, uint64 key)
Definition: shm_toc.c:218
int iss_NumRuntimeKeys
Definition: execnodes.h:1382
bool iss_RuntimeKeysReady
Definition: execnodes.h:1383
Plan * plan
Definition: execnodes.h:1049
ScanState ss
Definition: execnodes.h:1374
int iss_NumOrderByKeys
Definition: execnodes.h:1380
IndexScanDesc iss_ScanDesc
Definition: execnodes.h:1386
Relation iss_RelationDesc
Definition: execnodes.h:1385
ScanKey iss_OrderByKeys
Definition: execnodes.h:1379
IndexScanState* ExecInitIndexScan ( IndexScan node,
EState estate,
int  eflags 
)

Definition at line 894 of file nodeIndexscan.c.

References SortSupportData::abbreviate, AccessShareLock, Assert, CurrentMemoryContext, EXEC_FLAG_EXPLAIN_ONLY, ExecAssignExprContext(), ExecAssignResultTypeFromTL(), ExecAssignScanProjectionInfo(), ExecAssignScanType(), ExecIndexBuildScanKeys(), ExecInitExpr(), ExecInitResultTupleSlot(), ExecInitScanTupleSlot(), ExecOpenScanRelation(), ExecRelationIsTargetRelation(), exprCollation(), exprType(), forboth, get_typlenbyval(), i, index_open(), IndexScan::indexid, IndexScan::indexorderby, IndexScan::indexorderbyops, IndexScan::indexorderbyorig, IndexScanState::indexorderbyorig, IndexScan::indexqual, IndexScan::indexqualorig, IndexScanState::indexqualorig, IndexScanState::iss_NumOrderByKeys, IndexScanState::iss_NumRuntimeKeys, IndexScanState::iss_NumScanKeys, IndexScanState::iss_OrderByKeys, IndexScanState::iss_OrderByNulls, IndexScanState::iss_OrderByTypByVals, IndexScanState::iss_OrderByTypLens, IndexScanState::iss_OrderByValues, IndexScanState::iss_RelationDesc, IndexScanState::iss_ReorderQueue, IndexScanState::iss_RuntimeContext, IndexScanState::iss_RuntimeKeys, IndexScanState::iss_RuntimeKeysReady, IndexScanState::iss_ScanKeys, IndexScanState::iss_SortSupport, lfirst, lfirst_oid, list_length(), makeNode, NoLock, NULL, pairingheap_allocate(), palloc(), palloc0(), Scan::plan, PlanState::plan, PrepareSortSupportFromOrderingOp(), ScanState::ps, PlanState::ps_ExprContext, Plan::qual, PlanState::qual, RelationGetDescr, reorderqueue_cmp(), IndexScan::scan, Scan::scanrelid, IndexScanState::ss, ScanState::ss_currentRelation, ScanState::ss_currentScanDesc, SortSupportData::ssup_attno, SortSupportData::ssup_collation, SortSupportData::ssup_cxt, SortSupportData::ssup_nulls_first, PlanState::state, Plan::targetlist, and PlanState::targetlist.

Referenced by ExecInitNode().

895 {
896  IndexScanState *indexstate;
897  Relation currentRelation;
898  bool relistarget;
899 
900  /*
901  * create state structure
902  */
903  indexstate = makeNode(IndexScanState);
904  indexstate->ss.ps.plan = (Plan *) node;
905  indexstate->ss.ps.state = estate;
906 
907  /*
908  * Miscellaneous initialization
909  *
910  * create expression context for node
911  */
912  ExecAssignExprContext(estate, &indexstate->ss.ps);
913 
914  /*
915  * initialize child expressions
916  *
917  * Note: we don't initialize all of the indexqual expression, only the
918  * sub-parts corresponding to runtime keys (see below). Likewise for
919  * indexorderby, if any. But the indexqualorig expression is always
920  * initialized even though it will only be used in some uncommon cases ---
921  * would be nice to improve that. (Problem is that any SubPlans present
922  * in the expression must be found now...)
923  */
924  indexstate->ss.ps.targetlist = (List *)
926  (PlanState *) indexstate);
927  indexstate->ss.ps.qual = (List *)
928  ExecInitExpr((Expr *) node->scan.plan.qual,
929  (PlanState *) indexstate);
930  indexstate->indexqualorig = (List *)
931  ExecInitExpr((Expr *) node->indexqualorig,
932  (PlanState *) indexstate);
933  indexstate->indexorderbyorig = (List *)
935  (PlanState *) indexstate);
936 
937  /*
938  * tuple table initialization
939  */
940  ExecInitResultTupleSlot(estate, &indexstate->ss.ps);
941  ExecInitScanTupleSlot(estate, &indexstate->ss);
942 
943  /*
944  * open the base relation and acquire appropriate lock on it.
945  */
946  currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
947 
948  indexstate->ss.ss_currentRelation = currentRelation;
949  indexstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */
950 
951  /*
952  * get the scan type from the relation descriptor.
953  */
954  ExecAssignScanType(&indexstate->ss, RelationGetDescr(currentRelation));
955 
956  /*
957  * Initialize result tuple type and projection info.
958  */
959  ExecAssignResultTypeFromTL(&indexstate->ss.ps);
960  ExecAssignScanProjectionInfo(&indexstate->ss);
961 
962  /*
963  * If we are just doing EXPLAIN (ie, aren't going to run the plan), stop
964  * here. This allows an index-advisor plugin to EXPLAIN a plan containing
965  * references to nonexistent indexes.
966  */
967  if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
968  return indexstate;
969 
970  /*
971  * Open the index relation.
972  *
973  * If the parent table is one of the target relations of the query, then
974  * InitPlan already opened and write-locked the index, so we can avoid
975  * taking another lock here. Otherwise we need a normal reader's lock.
976  */
977  relistarget = ExecRelationIsTargetRelation(estate, node->scan.scanrelid);
978  indexstate->iss_RelationDesc = index_open(node->indexid,
979  relistarget ? NoLock : AccessShareLock);
980 
981  /*
982  * Initialize index-specific scan state
983  */
984  indexstate->iss_RuntimeKeysReady = false;
985  indexstate->iss_RuntimeKeys = NULL;
986  indexstate->iss_NumRuntimeKeys = 0;
987 
988  /*
989  * build the index scan keys from the index qualification
990  */
991  ExecIndexBuildScanKeys((PlanState *) indexstate,
992  indexstate->iss_RelationDesc,
993  node->indexqual,
994  false,
995  &indexstate->iss_ScanKeys,
996  &indexstate->iss_NumScanKeys,
997  &indexstate->iss_RuntimeKeys,
998  &indexstate->iss_NumRuntimeKeys,
999  NULL, /* no ArrayKeys */
1000  NULL);
1001 
1002  /*
1003  * any ORDER BY exprs have to be turned into scankeys in the same way
1004  */
1005  ExecIndexBuildScanKeys((PlanState *) indexstate,
1006  indexstate->iss_RelationDesc,
1007  node->indexorderby,
1008  true,
1009  &indexstate->iss_OrderByKeys,
1010  &indexstate->iss_NumOrderByKeys,
1011  &indexstate->iss_RuntimeKeys,
1012  &indexstate->iss_NumRuntimeKeys,
1013  NULL, /* no ArrayKeys */
1014  NULL);
1015 
1016  /* Initialize sort support, if we need to re-check ORDER BY exprs */
1017  if (indexstate->iss_NumOrderByKeys > 0)
1018  {
1019  int numOrderByKeys = indexstate->iss_NumOrderByKeys;
1020  int i;
1021  ListCell *lco;
1022  ListCell *lcx;
1023 
1024  /*
1025  * Prepare sort support, and look up the data type for each ORDER BY
1026  * expression.
1027  */
1028  Assert(numOrderByKeys == list_length(node->indexorderbyops));
1029  Assert(numOrderByKeys == list_length(node->indexorderbyorig));
1030  indexstate->iss_SortSupport = (SortSupportData *)
1031  palloc0(numOrderByKeys * sizeof(SortSupportData));
1032  indexstate->iss_OrderByTypByVals = (bool *)
1033  palloc(numOrderByKeys * sizeof(bool));
1034  indexstate->iss_OrderByTypLens = (int16 *)
1035  palloc(numOrderByKeys * sizeof(int16));
1036  i = 0;
1037  forboth(lco, node->indexorderbyops, lcx, node->indexorderbyorig)
1038  {
1039  Oid orderbyop = lfirst_oid(lco);
1040  Node *orderbyexpr = (Node *) lfirst(lcx);
1041  Oid orderbyType = exprType(orderbyexpr);
1042  Oid orderbyColl = exprCollation(orderbyexpr);
1043  SortSupport orderbysort = &indexstate->iss_SortSupport[i];
1044 
1045  /* Initialize sort support */
1046  orderbysort->ssup_cxt = CurrentMemoryContext;
1047  orderbysort->ssup_collation = orderbyColl;
1048  /* See cmp_orderbyvals() comments on NULLS LAST */
1049  orderbysort->ssup_nulls_first = false;
1050  /* ssup_attno is unused here and elsewhere */
1051  orderbysort->ssup_attno = 0;
1052  /* No abbreviation */
1053  orderbysort->abbreviate = false;
1054  PrepareSortSupportFromOrderingOp(orderbyop, orderbysort);
1055 
1056  get_typlenbyval(orderbyType,
1057  &indexstate->iss_OrderByTypLens[i],
1058  &indexstate->iss_OrderByTypByVals[i]);
1059  i++;
1060  }
1061 
1062  /* allocate arrays to hold the re-calculated distances */
1063  indexstate->iss_OrderByValues = (Datum *)
1064  palloc(numOrderByKeys * sizeof(Datum));
1065  indexstate->iss_OrderByNulls = (bool *)
1066  palloc(numOrderByKeys * sizeof(bool));
1067 
1068  /* and initialize the reorder queue */
1070  indexstate);
1071  }
1072 
1073  /*
1074  * If we have runtime keys, we need an ExprContext to evaluate them. The
1075  * node's standard context won't do because we want to reset that context
1076  * for every tuple. So, build another context just like the other one...
1077  * -tgl 7/11/00
1078  */
1079  if (indexstate->iss_NumRuntimeKeys != 0)
1080  {
1081  ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext;
1082 
1083  ExecAssignExprContext(estate, &indexstate->ss.ps);
1084  indexstate->iss_RuntimeContext = indexstate->ss.ps.ps_ExprContext;
1085  indexstate->ss.ps.ps_ExprContext = stdecontext;
1086  }
1087  else
1088  {
1089  indexstate->iss_RuntimeContext = NULL;
1090  }
1091 
1092  /*
1093  * all done.
1094  */
1095  return indexstate;
1096 }
signed short int16
Definition: c.h:255
bool ssup_nulls_first
Definition: sortsupport.h:75
List * qual
Definition: plannodes.h:133
Plan plan
Definition: plannodes.h:315
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:174
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate)
Definition: execTuples.c:842
Index scanrelid
Definition: plannodes.h:316
#define RelationGetDescr(relation)
Definition: rel.h:425
IndexRuntimeKeyInfo * iss_RuntimeKeys
Definition: execnodes.h:1381
int16 * iss_OrderByTypLens
Definition: execnodes.h:1395
ExprContext * ps_ExprContext
Definition: execnodes.h:1080
SortSupport iss_SortSupport
Definition: execnodes.h:1393
void PrepareSortSupportFromOrderingOp(Oid orderingOp, SortSupport ssup)
Definition: sortsupport.c:133
List * indexqualorig
Definition: plannodes.h:378
#define AccessShareLock
Definition: lockdefs.h:36
List * qual
Definition: execnodes.h:1064
Definition: nodes.h:520
pairingheap * pairingheap_allocate(pairingheap_comparator compare, void *arg)
Definition: pairingheap.c:42
List * targetlist
Definition: execnodes.h:1063
Relation ss_currentRelation
Definition: execnodes.h:1291
EState * state
Definition: execnodes.h:1051
unsigned int Oid
Definition: postgres_ext.h:31
ScanKey iss_ScanKeys
Definition: execnodes.h:1377
Oid indexid
Definition: plannodes.h:376
List * indexorderbyorig
Definition: execnodes.h:1376
void ExecAssignResultTypeFromTL(PlanState *planstate)
Definition: execUtils.c:431
bool * iss_OrderByNulls
Definition: execnodes.h:1392
PlanState ps
Definition: execnodes.h:1290
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execQual.c:4267
List * indexorderbyorig
Definition: plannodes.h:380
void ExecAssignScanProjectionInfo(ScanState *node)
Definition: execScan.c:235
void ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
Definition: execTuples.c:832
Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
Definition: execUtils.c:773
MemoryContext ssup_cxt
Definition: sortsupport.h:66
Scan scan
Definition: plannodes.h:375
#define NoLock
Definition: lockdefs.h:34
int iss_NumRuntimeKeys
Definition: execnodes.h:1382
bool * iss_OrderByTypByVals
Definition: execnodes.h:1394
static int reorderqueue_cmp(const pairingheap_node *a, const pairingheap_node *b, void *arg)
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
bool iss_RuntimeKeysReady
Definition: execnodes.h:1383
List * indexqual
Definition: plannodes.h:377
void * palloc0(Size size)
Definition: mcxt.c:878
uintptr_t Datum
Definition: postgres.h:372
AttrNumber ssup_attno
Definition: sortsupport.h:81
Plan * plan
Definition: execnodes.h:1049
ScanState ss
Definition: execnodes.h:1374
#define makeNode(_type_)
Definition: nodes.h:568
List * indexorderby
Definition: plannodes.h:379
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:409
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
void ExecIndexBuildScanKeys(PlanState *planstate, Relation index, List *quals, bool isorderby, ScanKey *scanKeys, int *numScanKeys, IndexRuntimeKeyInfo **runtimeKeys, int *numRuntimeKeys, IndexArrayKeyInfo **arrayKeys, int *numArrayKeys)
static int list_length(const List *l)
Definition: pg_list.h:89
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:745
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:1969
List * indexqualorig
Definition: execnodes.h:1375
ExprContext * iss_RuntimeContext
Definition: execnodes.h:1384
List * indexorderbyops
Definition: plannodes.h:381
List * targetlist
Definition: plannodes.h:132
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1292
void * palloc(Size size)
Definition: mcxt.c:849
int i
void ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
Definition: execUtils.c:710
Datum * iss_OrderByValues
Definition: execnodes.h:1391
int iss_NumOrderByKeys
Definition: execnodes.h:1380
Definition: pg_list.h:45
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:58
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:151
bool ExecRelationIsTargetRelation(EState *estate, Index scanrelid)
Definition: execUtils.c:747
#define lfirst_oid(lc)
Definition: pg_list.h:108
Relation iss_RelationDesc
Definition: execnodes.h:1385
pairingheap * iss_ReorderQueue
Definition: execnodes.h:1389
ScanKey iss_OrderByKeys
Definition: execnodes.h:1379
void ExecReScanIndexScan ( IndexScanState node)

Definition at line 569 of file nodeIndexscan.c.

References ExecIndexEvalRuntimeKeys(), ExecScanReScan(), index_parallelrescan(), 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, IndexScanDescData::parallel_scan, reorderqueue_pop(), ResetExprContext, and IndexScanState::ss.

Referenced by ExecReScan().

570 {
571  bool reset_parallel_scan = true;
572 
573  /*
574  * If we are here to just update the scan keys, then don't reset parallel
575  * scan. We don't want each of the participating process in the parallel
576  * scan to update the shared parallel scan state at the start of the scan.
577  * It is quite possible that one of the participants has already begun
578  * scanning the index when another has yet to start it.
579  */
580  if (node->iss_NumRuntimeKeys != 0 && !node->iss_RuntimeKeysReady)
581  reset_parallel_scan = false;
582 
583  /*
584  * If we are doing runtime key calculations (ie, any of the index key
585  * values weren't simple Consts), compute the new key values. But first,
586  * reset the context so we don't leak memory as each outer tuple is
587  * scanned. Note this assumes that we will recalculate *all* runtime keys
588  * on each call.
589  */
590  if (node->iss_NumRuntimeKeys != 0)
591  {
592  ExprContext *econtext = node->iss_RuntimeContext;
593 
594  ResetExprContext(econtext);
595  ExecIndexEvalRuntimeKeys(econtext,
596  node->iss_RuntimeKeys,
597  node->iss_NumRuntimeKeys);
598  }
599  node->iss_RuntimeKeysReady = true;
600 
601  /* flush the reorder queue */
602  if (node->iss_ReorderQueue)
603  {
604  while (!pairingheap_is_empty(node->iss_ReorderQueue))
605  reorderqueue_pop(node);
606  }
607 
608  /*
609  * Reset (parallel) index scan. For parallel-aware nodes, the scan
610  * descriptor is initialized during actual execution of node and we can
611  * reach here before that (ex. during execution of nest loop join). So,
612  * avoid updating the scan descriptor at that time.
613  */
614  if (node->iss_ScanDesc)
615  {
617  node->iss_ScanKeys, node->iss_NumScanKeys,
618  node->iss_OrderByKeys, node->iss_NumOrderByKeys);
619 
620  if (reset_parallel_scan && node->iss_ScanDesc->parallel_scan)
622  }
623  node->iss_ReachedEnd = false;
624 
625  ExecScanReScan(&node->ss);
626 }
ParallelIndexScanDesc parallel_scan
Definition: relscan.h:139
IndexRuntimeKeyInfo * iss_RuntimeKeys
Definition: execnodes.h:1381
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
void index_rescan(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int norderbys)
Definition: indexam.c:310
ScanKey iss_ScanKeys
Definition: execnodes.h:1377
void index_parallelrescan(IndexScanDesc scan)
Definition: indexam.c:481
bool iss_ReachedEnd
Definition: execnodes.h:1390
int iss_NumRuntimeKeys
Definition: execnodes.h:1382
bool iss_RuntimeKeysReady
Definition: execnodes.h:1383
ScanState ss
Definition: execnodes.h:1374
static HeapTuple reorderqueue_pop(IndexScanState *node)
ExprContext * iss_RuntimeContext
Definition: execnodes.h:1384
void ExecIndexEvalRuntimeKeys(ExprContext *econtext, IndexRuntimeKeyInfo *runtimeKeys, int numRuntimeKeys)
void ExecScanReScan(ScanState *node)
Definition: execScan.c:327
int iss_NumOrderByKeys
Definition: execnodes.h:1380
IndexScanDesc iss_ScanDesc
Definition: execnodes.h:1386
#define ResetExprContext(econtext)
Definition: executor.h:333
pairingheap * iss_ReorderQueue
Definition: execnodes.h:1389
ScanKey iss_OrderByKeys
Definition: execnodes.h:1379