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 769 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().

770 {
771  Relation indexRelationDesc;
772  IndexScanDesc indexScanDesc;
773  Relation relation;
774 
775  /*
776  * extract information from the node
777  */
778  indexRelationDesc = node->iss_RelationDesc;
779  indexScanDesc = node->iss_ScanDesc;
780  relation = node->ss.ss_currentRelation;
781 
782  /*
783  * Free the exprcontext(s) ... now dead code, see ExecFreeExprContext
784  */
785 #ifdef NOT_USED
786  ExecFreeExprContext(&node->ss.ps);
787  if (node->iss_RuntimeContext)
788  FreeExprContext(node->iss_RuntimeContext, true);
789 #endif
790 
791  /*
792  * clear out tuple table slots
793  */
796 
797  /*
798  * close the index relation (no-op if we didn't open it)
799  */
800  if (indexScanDesc)
801  index_endscan(indexScanDesc);
802  if (indexRelationDesc)
803  index_close(indexRelationDesc, NoLock);
804 
805  /*
806  * close the heap relation.
807  */
808  ExecCloseScanRelation(relation);
809 }
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1290
Relation ss_currentRelation
Definition: execnodes.h:1288
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:684
PlanState ps
Definition: execnodes.h:1287
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1076
#define NoLock
Definition: lockdefs.h:34
void index_endscan(IndexScanDesc scan)
Definition: indexam.c:340
void FreeExprContext(ExprContext *econtext, bool isCommit)
Definition: execUtils.c:338
ScanState ss
Definition: execnodes.h:1371
void ExecCloseScanRelation(Relation scanrel)
Definition: execUtils.c:829
ExprContext * iss_RuntimeContext
Definition: execnodes.h:1381
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:176
IndexScanDesc iss_ScanDesc
Definition: execnodes.h:1383
Relation iss_RelationDesc
Definition: execnodes.h:1382
bool ExecIndexAdvanceArrayKeys ( IndexArrayKeyInfo arrayKeys,
int  numArrayKeys 
)

Definition at line 724 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().

725 {
726  bool found = false;
727  int j;
728 
729  /*
730  * Note we advance the rightmost array key most quickly, since it will
731  * correspond to the lowest-order index column among the available
732  * qualifications. This is hypothesized to result in better locality of
733  * access in the index.
734  */
735  for (j = numArrayKeys - 1; j >= 0; j--)
736  {
737  ScanKey scan_key = arrayKeys[j].scan_key;
738  int next_elem = arrayKeys[j].next_elem;
739  int num_elems = arrayKeys[j].num_elems;
740  Datum *elem_values = arrayKeys[j].elem_values;
741  bool *elem_nulls = arrayKeys[j].elem_nulls;
742 
743  if (next_elem >= num_elems)
744  {
745  next_elem = 0;
746  found = false; /* need to advance next array key */
747  }
748  else
749  found = true;
750  scan_key->sk_argument = elem_values[next_elem];
751  if (elem_nulls[next_elem])
752  scan_key->sk_flags |= SK_ISNULL;
753  else
754  scan_key->sk_flags &= ~SK_ISNULL;
755  arrayKeys[j].next_elem = next_elem + 1;
756  if (found)
757  break;
758  }
759 
760  return found;
761 }
Datum * elem_values
Definition: execnodes.h:1339
#define SK_ISNULL
Definition: skey.h:115
uintptr_t Datum
Definition: postgres.h:374
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 1133 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().

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

Referenced by ExecReScanBitmapIndexScan().

647 {
648  bool result = true;
649  int j;
650  MemoryContext oldContext;
651 
652  /* We want to keep the arrays in per-tuple memory */
653  oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
654 
655  for (j = 0; j < numArrayKeys; j++)
656  {
657  ScanKey scan_key = arrayKeys[j].scan_key;
658  ExprState *array_expr = arrayKeys[j].array_expr;
659  Datum arraydatum;
660  bool isNull;
661  ArrayType *arrayval;
662  int16 elmlen;
663  bool elmbyval;
664  char elmalign;
665  int num_elems;
666  Datum *elem_values;
667  bool *elem_nulls;
668 
669  /*
670  * Compute and deconstruct the array expression. (Notes in
671  * ExecIndexEvalRuntimeKeys() apply here too.)
672  */
673  arraydatum = ExecEvalExpr(array_expr,
674  econtext,
675  &isNull);
676  if (isNull)
677  {
678  result = false;
679  break; /* no point in evaluating more */
680  }
681  arrayval = DatumGetArrayTypeP(arraydatum);
682  /* We could cache this data, but not clear it's worth it */
684  &elmlen, &elmbyval, &elmalign);
685  deconstruct_array(arrayval,
686  ARR_ELEMTYPE(arrayval),
687  elmlen, elmbyval, elmalign,
688  &elem_values, &elem_nulls, &num_elems);
689  if (num_elems <= 0)
690  {
691  result = false;
692  break; /* no point in evaluating more */
693  }
694 
695  /*
696  * Note: we expect the previous array data, if any, to be
697  * automatically freed by resetting the per-tuple context; hence no
698  * pfree's here.
699  */
700  arrayKeys[j].elem_values = elem_values;
701  arrayKeys[j].elem_nulls = elem_nulls;
702  arrayKeys[j].num_elems = num_elems;
703  scan_key->sk_argument = elem_values[0];
704  if (elem_nulls[0])
705  scan_key->sk_flags |= SK_ISNULL;
706  else
707  scan_key->sk_flags &= ~SK_ISNULL;
708  arrayKeys[j].next_elem = 1;
709  }
710 
711  MemoryContextSwitchTo(oldContext);
712 
713  return result;
714 }
Datum * elem_values
Definition: execnodes.h:1339
signed short int16
Definition: c.h:252
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:1989
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:134
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define ExecEvalExpr(expr, econtext, isNull)
Definition: executor.h:73
#define SK_ISNULL
Definition: skey.h:115
uintptr_t Datum
Definition: postgres.h:374
ExprState * array_expr
Definition: execnodes.h:1336
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 583 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().

585 {
586  int j;
587  MemoryContext oldContext;
588 
589  /* We want to keep the key values in per-tuple memory */
590  oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
591 
592  for (j = 0; j < numRuntimeKeys; j++)
593  {
594  ScanKey scan_key = runtimeKeys[j].scan_key;
595  ExprState *key_expr = runtimeKeys[j].key_expr;
596  Datum scanvalue;
597  bool isNull;
598 
599  /*
600  * For each run-time key, extract the run-time expression and evaluate
601  * it with respect to the current context. We then stick the result
602  * into the proper scan key.
603  *
604  * Note: the result of the eval could be a pass-by-ref value that's
605  * stored in some outer scan's tuple, not in
606  * econtext->ecxt_per_tuple_memory. We assume that the outer tuple
607  * will stay put throughout our scan. If this is wrong, we could copy
608  * the result into our context explicitly, but I think that's not
609  * necessary.
610  *
611  * It's also entirely possible that the result of the eval is a
612  * toasted value. In this case we should forcibly detoast it, to
613  * avoid repeat detoastings each time the value is examined by an
614  * index support function.
615  */
616  scanvalue = ExecEvalExpr(key_expr,
617  econtext,
618  &isNull);
619  if (isNull)
620  {
621  scan_key->sk_argument = scanvalue;
622  scan_key->sk_flags |= SK_ISNULL;
623  }
624  else
625  {
626  if (runtimeKeys[j].key_toastable)
627  scanvalue = PointerGetDatum(PG_DETOAST_DATUM(scanvalue));
628  scan_key->sk_argument = scanvalue;
629  scan_key->sk_flags &= ~SK_ISNULL;
630  }
631  }
632 
633  MemoryContextSwitchTo(oldContext);
634 }
#define PointerGetDatum(X)
Definition: postgres.h:564
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:134
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define ExecEvalExpr(expr, econtext, isNull)
Definition: executor.h:73
ExprState * key_expr
Definition: execnodes.h:1329
#define SK_ISNULL
Definition: skey.h:115
uintptr_t Datum
Definition: postgres.h:374
int sk_flags
Definition: skey.h:66
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:196
Datum sk_argument
Definition: skey.h:72
void ExecIndexMarkPos ( IndexScanState node)

Definition at line 816 of file nodeIndexscan.c.

References index_markpos(), and IndexScanState::iss_ScanDesc.

Referenced by ExecMarkPos().

817 {
819 }
void index_markpos(IndexScanDesc scan)
Definition: indexam.c:370
IndexScanDesc iss_ScanDesc
Definition: execnodes.h:1383
void ExecIndexRestrPos ( IndexScanState node)

Definition at line 826 of file nodeIndexscan.c.

References index_restrpos(), and IndexScanState::iss_ScanDesc.

Referenced by ExecRestrPos().

827 {
829 }
void index_restrpos(IndexScanDesc scan)
Definition: indexam.c:395
IndexScanDesc iss_ScanDesc
Definition: execnodes.h:1383
TupleTableSlot* ExecIndexScan ( IndexScanState node)

Definition at line 488 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().

489 {
490  /*
491  * If we have runtime keys and they've not already been set up, do it now.
492  */
493  if (node->iss_NumRuntimeKeys != 0 && !node->iss_RuntimeKeysReady)
494  ExecReScan((PlanState *) node);
495 
496  if (node->iss_NumOrderByKeys > 0)
497  return ExecScan(&node->ss,
500  else
501  return ExecScan(&node->ss,
504 }
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:73
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition: executor.h:271
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:272
int iss_NumRuntimeKeys
Definition: execnodes.h:1379
bool iss_RuntimeKeysReady
Definition: execnodes.h:1380
static TupleTableSlot * IndexNext(IndexScanState *node)
Definition: nodeIndexscan.c:79
static TupleTableSlot * IndexNextWithReorder(IndexScanState *node)
ScanState ss
Definition: execnodes.h:1371
int iss_NumOrderByKeys
Definition: execnodes.h:1377
void ExecIndexScanEstimate ( IndexScanState node,
ParallelContext pcxt 
)

Definition at line 1639 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().

1641 {
1642  EState *estate = node->ss.ps.state;
1643 
1645  estate->es_snapshot);
1647  shm_toc_estimate_keys(&pcxt->estimator, 1);
1648 }
shm_toc_estimator estimator
Definition: parallel.h:42
Snapshot es_snapshot
Definition: execnodes.h:370
EState * state
Definition: execnodes.h:1048
#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:1287
ScanState ss
Definition: execnodes.h:1371
#define shm_toc_estimate_keys(e, cnt)
Definition: shm_toc.h:52
Relation iss_RelationDesc
Definition: execnodes.h:1382
void ExecIndexScanInitializeDSM ( IndexScanState node,
ParallelContext pcxt 
)

Definition at line 1657 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_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().

1659 {
1660  EState *estate = node->ss.ps.state;
1661  ParallelIndexScanDesc piscan;
1662 
1663  piscan = shm_toc_allocate(pcxt->toc, node->iss_PscanLen);
1665  node->iss_RelationDesc,
1666  estate->es_snapshot,
1667  piscan);
1668  shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, piscan);
1669  node->iss_ScanDesc =
1671  node->iss_RelationDesc,
1672  node->iss_NumScanKeys,
1673  node->iss_NumOrderByKeys,
1674  piscan);
1675 
1676  /*
1677  * If no run-time keys to calculate, go ahead and pass the scankeys to the
1678  * index AM.
1679  */
1680  if (node->iss_NumRuntimeKeys == 0)
1681  index_rescan(node->iss_ScanDesc,
1682  node->iss_ScanKeys, node->iss_NumScanKeys,
1683  node->iss_OrderByKeys, node->iss_NumOrderByKeys);
1684 }
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:128
void index_rescan(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int norderbys)
Definition: indexam.c:310
Snapshot es_snapshot
Definition: execnodes.h:370
Relation ss_currentRelation
Definition: execnodes.h:1288
EState * state
Definition: execnodes.h:1048
ScanKey iss_ScanKeys
Definition: execnodes.h:1374
PlanState ps
Definition: execnodes.h:1287
int iss_NumRuntimeKeys
Definition: execnodes.h:1379
Plan * plan
Definition: execnodes.h:1046
ScanState ss
Definition: execnodes.h:1371
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:1377
IndexScanDesc iss_ScanDesc
Definition: execnodes.h:1383
shm_toc * toc
Definition: parallel.h:45
Relation iss_RelationDesc
Definition: execnodes.h:1382
ScanKey iss_OrderByKeys
Definition: execnodes.h:1376
void ExecIndexScanInitializeWorker ( IndexScanState node,
shm_toc toc 
)

Definition at line 1693 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_ScanDesc, IndexScanState::iss_ScanKeys, PlanState::plan, Plan::plan_node_id, ScanState::ps, shm_toc_lookup(), IndexScanState::ss, and ScanState::ss_currentRelation.

Referenced by ExecParallelInitializeWorker().

1694 {
1695  ParallelIndexScanDesc piscan;
1696 
1697  piscan = shm_toc_lookup(toc, node->ss.ps.plan->plan_node_id);
1698  node->iss_ScanDesc =
1700  node->iss_RelationDesc,
1701  node->iss_NumScanKeys,
1702  node->iss_NumOrderByKeys,
1703  piscan);
1704 
1705  /*
1706  * If no run-time keys to calculate, go ahead and pass the scankeys to the
1707  * index AM.
1708  */
1709  if (node->iss_NumRuntimeKeys == 0)
1710  index_rescan(node->iss_ScanDesc,
1711  node->iss_ScanKeys, node->iss_NumScanKeys,
1712  node->iss_OrderByKeys, node->iss_NumOrderByKeys);
1713 }
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:128
void index_rescan(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int norderbys)
Definition: indexam.c:310
Relation ss_currentRelation
Definition: execnodes.h:1288
ScanKey iss_ScanKeys
Definition: execnodes.h:1374
PlanState ps
Definition: execnodes.h:1287
void * shm_toc_lookup(shm_toc *toc, uint64 key)
Definition: shm_toc.c:218
int iss_NumRuntimeKeys
Definition: execnodes.h:1379
Plan * plan
Definition: execnodes.h:1046
ScanState ss
Definition: execnodes.h:1371
int iss_NumOrderByKeys
Definition: execnodes.h:1377
IndexScanDesc iss_ScanDesc
Definition: execnodes.h:1383
Relation iss_RelationDesc
Definition: execnodes.h:1382
ScanKey iss_OrderByKeys
Definition: execnodes.h:1376
IndexScanState* ExecInitIndexScan ( IndexScan node,
EState estate,
int  eflags 
)

Definition at line 843 of file nodeIndexscan.c.

References SortSupportData::abbreviate, AccessShareLock, Assert, CurrentMemoryContext, EState::es_snapshot, EXEC_FLAG_EXPLAIN_ONLY, ExecAssignExprContext(), ExecAssignResultTypeFromTL(), ExecAssignScanProjectionInfo(), ExecAssignScanType(), ExecIndexBuildScanKeys(), ExecInitExpr(), ExecInitResultTupleSlot(), ExecInitScanTupleSlot(), ExecOpenScanRelation(), ExecRelationIsTargetRelation(), exprCollation(), exprType(), forboth, get_typlenbyval(), i, index_beginscan(), index_open(), index_rescan(), 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_ScanDesc, IndexScanState::iss_ScanKeys, IndexScanState::iss_SortSupport, lfirst, lfirst_oid, list_length(), makeNode, NoLock, NULL, pairingheap_allocate(), palloc(), palloc0(), Plan::parallel_aware, 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().

844 {
845  IndexScanState *indexstate;
846  Relation currentRelation;
847  bool relistarget;
848 
849  /*
850  * create state structure
851  */
852  indexstate = makeNode(IndexScanState);
853  indexstate->ss.ps.plan = (Plan *) node;
854  indexstate->ss.ps.state = estate;
855 
856  /*
857  * Miscellaneous initialization
858  *
859  * create expression context for node
860  */
861  ExecAssignExprContext(estate, &indexstate->ss.ps);
862 
863  /*
864  * initialize child expressions
865  *
866  * Note: we don't initialize all of the indexqual expression, only the
867  * sub-parts corresponding to runtime keys (see below). Likewise for
868  * indexorderby, if any. But the indexqualorig expression is always
869  * initialized even though it will only be used in some uncommon cases ---
870  * would be nice to improve that. (Problem is that any SubPlans present
871  * in the expression must be found now...)
872  */
873  indexstate->ss.ps.targetlist = (List *)
875  (PlanState *) indexstate);
876  indexstate->ss.ps.qual = (List *)
877  ExecInitExpr((Expr *) node->scan.plan.qual,
878  (PlanState *) indexstate);
879  indexstate->indexqualorig = (List *)
880  ExecInitExpr((Expr *) node->indexqualorig,
881  (PlanState *) indexstate);
882  indexstate->indexorderbyorig = (List *)
884  (PlanState *) indexstate);
885 
886  /*
887  * tuple table initialization
888  */
889  ExecInitResultTupleSlot(estate, &indexstate->ss.ps);
890  ExecInitScanTupleSlot(estate, &indexstate->ss);
891 
892  /*
893  * open the base relation and acquire appropriate lock on it.
894  */
895  currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
896 
897  indexstate->ss.ss_currentRelation = currentRelation;
898  indexstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */
899 
900  /*
901  * get the scan type from the relation descriptor.
902  */
903  ExecAssignScanType(&indexstate->ss, RelationGetDescr(currentRelation));
904 
905  /*
906  * Initialize result tuple type and projection info.
907  */
908  ExecAssignResultTypeFromTL(&indexstate->ss.ps);
909  ExecAssignScanProjectionInfo(&indexstate->ss);
910 
911  /*
912  * If we are just doing EXPLAIN (ie, aren't going to run the plan), stop
913  * here. This allows an index-advisor plugin to EXPLAIN a plan containing
914  * references to nonexistent indexes.
915  */
916  if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
917  return indexstate;
918 
919  /*
920  * Open the index relation.
921  *
922  * If the parent table is one of the target relations of the query, then
923  * InitPlan already opened and write-locked the index, so we can avoid
924  * taking another lock here. Otherwise we need a normal reader's lock.
925  */
926  relistarget = ExecRelationIsTargetRelation(estate, node->scan.scanrelid);
927  indexstate->iss_RelationDesc = index_open(node->indexid,
928  relistarget ? NoLock : AccessShareLock);
929 
930  /*
931  * Initialize index-specific scan state
932  */
933  indexstate->iss_RuntimeKeysReady = false;
934  indexstate->iss_RuntimeKeys = NULL;
935  indexstate->iss_NumRuntimeKeys = 0;
936 
937  /*
938  * build the index scan keys from the index qualification
939  */
940  ExecIndexBuildScanKeys((PlanState *) indexstate,
941  indexstate->iss_RelationDesc,
942  node->indexqual,
943  false,
944  &indexstate->iss_ScanKeys,
945  &indexstate->iss_NumScanKeys,
946  &indexstate->iss_RuntimeKeys,
947  &indexstate->iss_NumRuntimeKeys,
948  NULL, /* no ArrayKeys */
949  NULL);
950 
951  /*
952  * any ORDER BY exprs have to be turned into scankeys in the same way
953  */
954  ExecIndexBuildScanKeys((PlanState *) indexstate,
955  indexstate->iss_RelationDesc,
956  node->indexorderby,
957  true,
958  &indexstate->iss_OrderByKeys,
959  &indexstate->iss_NumOrderByKeys,
960  &indexstate->iss_RuntimeKeys,
961  &indexstate->iss_NumRuntimeKeys,
962  NULL, /* no ArrayKeys */
963  NULL);
964 
965  /* Initialize sort support, if we need to re-check ORDER BY exprs */
966  if (indexstate->iss_NumOrderByKeys > 0)
967  {
968  int numOrderByKeys = indexstate->iss_NumOrderByKeys;
969  int i;
970  ListCell *lco;
971  ListCell *lcx;
972 
973  /*
974  * Prepare sort support, and look up the data type for each ORDER BY
975  * expression.
976  */
977  Assert(numOrderByKeys == list_length(node->indexorderbyops));
978  Assert(numOrderByKeys == list_length(node->indexorderbyorig));
979  indexstate->iss_SortSupport = (SortSupportData *)
980  palloc0(numOrderByKeys * sizeof(SortSupportData));
981  indexstate->iss_OrderByTypByVals = (bool *)
982  palloc(numOrderByKeys * sizeof(bool));
983  indexstate->iss_OrderByTypLens = (int16 *)
984  palloc(numOrderByKeys * sizeof(int16));
985  i = 0;
986  forboth(lco, node->indexorderbyops, lcx, node->indexorderbyorig)
987  {
988  Oid orderbyop = lfirst_oid(lco);
989  Node *orderbyexpr = (Node *) lfirst(lcx);
990  Oid orderbyType = exprType(orderbyexpr);
991  Oid orderbyColl = exprCollation(orderbyexpr);
992  SortSupport orderbysort = &indexstate->iss_SortSupport[i];
993 
994  /* Initialize sort support */
995  orderbysort->ssup_cxt = CurrentMemoryContext;
996  orderbysort->ssup_collation = orderbyColl;
997  /* See cmp_orderbyvals() comments on NULLS LAST */
998  orderbysort->ssup_nulls_first = false;
999  /* ssup_attno is unused here and elsewhere */
1000  orderbysort->ssup_attno = 0;
1001  /* No abbreviation */
1002  orderbysort->abbreviate = false;
1003  PrepareSortSupportFromOrderingOp(orderbyop, orderbysort);
1004 
1005  get_typlenbyval(orderbyType,
1006  &indexstate->iss_OrderByTypLens[i],
1007  &indexstate->iss_OrderByTypByVals[i]);
1008  i++;
1009  }
1010 
1011  /* allocate arrays to hold the re-calculated distances */
1012  indexstate->iss_OrderByValues = (Datum *)
1013  palloc(numOrderByKeys * sizeof(Datum));
1014  indexstate->iss_OrderByNulls = (bool *)
1015  palloc(numOrderByKeys * sizeof(bool));
1016 
1017  /* and initialize the reorder queue */
1019  indexstate);
1020  }
1021 
1022  /*
1023  * If we have runtime keys, we need an ExprContext to evaluate them. The
1024  * node's standard context won't do because we want to reset that context
1025  * for every tuple. So, build another context just like the other one...
1026  * -tgl 7/11/00
1027  */
1028  if (indexstate->iss_NumRuntimeKeys != 0)
1029  {
1030  ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext;
1031 
1032  ExecAssignExprContext(estate, &indexstate->ss.ps);
1033  indexstate->iss_RuntimeContext = indexstate->ss.ps.ps_ExprContext;
1034  indexstate->ss.ps.ps_ExprContext = stdecontext;
1035  }
1036  else
1037  {
1038  indexstate->iss_RuntimeContext = NULL;
1039  }
1040 
1041  /*
1042  * for parallel-aware node, we initialize the scan descriptor after
1043  * initializing the shared memory for parallel execution.
1044  */
1045  if (!node->scan.plan.parallel_aware)
1046  {
1047  /*
1048  * Initialize scan descriptor.
1049  */
1050  indexstate->iss_ScanDesc = index_beginscan(currentRelation,
1051  indexstate->iss_RelationDesc,
1052  estate->es_snapshot,
1053  indexstate->iss_NumScanKeys,
1054  indexstate->iss_NumOrderByKeys);
1055 
1056  /*
1057  * If no run-time keys to calculate, go ahead and pass the scankeys to
1058  * the index AM.
1059  */
1060  if (indexstate->iss_NumRuntimeKeys == 0)
1061  index_rescan(indexstate->iss_ScanDesc,
1062  indexstate->iss_ScanKeys, indexstate->iss_NumScanKeys,
1063  indexstate->iss_OrderByKeys, indexstate->iss_NumOrderByKeys);
1064  }
1065 
1066  /*
1067  * all done.
1068  */
1069  return indexstate;
1070 }
signed short int16
Definition: c.h:252
bool ssup_nulls_first
Definition: sortsupport.h:75
List * qual
Definition: plannodes.h:130
Plan plan
Definition: plannodes.h:305
#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:306
#define RelationGetDescr(relation)
Definition: rel.h:425
IndexRuntimeKeyInfo * iss_RuntimeKeys
Definition: execnodes.h:1378
int16 * iss_OrderByTypLens
Definition: execnodes.h:1392
ExprContext * ps_ExprContext
Definition: execnodes.h:1077
SortSupport iss_SortSupport
Definition: execnodes.h:1390
void PrepareSortSupportFromOrderingOp(Oid orderingOp, SortSupport ssup)
Definition: sortsupport.c:133
List * indexqualorig
Definition: plannodes.h:368
#define AccessShareLock
Definition: lockdefs.h:36
List * qual
Definition: execnodes.h:1061
void index_rescan(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int norderbys)
Definition: indexam.c:310
Definition: nodes.h:508
pairingheap * pairingheap_allocate(pairingheap_comparator compare, void *arg)
Definition: pairingheap.c:42
List * targetlist
Definition: execnodes.h:1060
Snapshot es_snapshot
Definition: execnodes.h:370
Relation ss_currentRelation
Definition: execnodes.h:1288
EState * state
Definition: execnodes.h:1048
unsigned int Oid
Definition: postgres_ext.h:31
ScanKey iss_ScanKeys
Definition: execnodes.h:1374
Oid indexid
Definition: plannodes.h:366
List * indexorderbyorig
Definition: execnodes.h:1373
void ExecAssignResultTypeFromTL(PlanState *planstate)
Definition: execUtils.c:429
bool * iss_OrderByNulls
Definition: execnodes.h:1389
PlanState ps
Definition: execnodes.h:1287
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execQual.c:4266
List * indexorderbyorig
Definition: plannodes.h:370
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:771
MemoryContext ssup_cxt
Definition: sortsupport.h:66
Scan scan
Definition: plannodes.h:365
#define NoLock
Definition: lockdefs.h:34
int iss_NumRuntimeKeys
Definition: execnodes.h:1379
bool * iss_OrderByTypByVals
Definition: execnodes.h:1391
static int reorderqueue_cmp(const pairingheap_node *a, const pairingheap_node *b, void *arg)
bool parallel_aware
Definition: plannodes.h:123
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
bool iss_RuntimeKeysReady
Definition: execnodes.h:1380
List * indexqual
Definition: plannodes.h:367
void * palloc0(Size size)
Definition: mcxt.c:920
uintptr_t Datum
Definition: postgres.h:374
AttrNumber ssup_attno
Definition: sortsupport.h:81
Plan * plan
Definition: execnodes.h:1046
ScanState ss
Definition: execnodes.h:1371
#define makeNode(_type_)
Definition: nodes.h:556
List * indexorderby
Definition: plannodes.h:369
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:407
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:748
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:1969
List * indexqualorig
Definition: execnodes.h:1372
ExprContext * iss_RuntimeContext
Definition: execnodes.h:1381
List * indexorderbyops
Definition: plannodes.h:371
List * targetlist
Definition: plannodes.h:129
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1289
void * palloc(Size size)
Definition: mcxt.c:891
int i
void ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
Definition: execUtils.c:708
Datum * iss_OrderByValues
Definition: execnodes.h:1388
int iss_NumOrderByKeys
Definition: execnodes.h:1377
IndexScanDesc iss_ScanDesc
Definition: execnodes.h:1383
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:745
#define lfirst_oid(lc)
Definition: pg_list.h:108
Relation iss_RelationDesc
Definition: execnodes.h:1382
IndexScanDesc index_beginscan(Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, int norderbys)
Definition: indexam.c:221
pairingheap * iss_ReorderQueue
Definition: execnodes.h:1386
ScanKey iss_OrderByKeys
Definition: execnodes.h:1376
void ExecReScanIndexScan ( IndexScanState node)

Definition at line 518 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().

519 {
520  bool reset_parallel_scan = true;
521 
522  /*
523  * If we are here to just update the scan keys, then don't reset parallel
524  * scan. We don't want each of the participating process in the parallel
525  * scan to update the shared parallel scan state at the start of the scan.
526  * It is quite possible that one of the participants has already begun
527  * scanning the index when another has yet to start it.
528  */
529  if (node->iss_NumRuntimeKeys != 0 && !node->iss_RuntimeKeysReady)
530  reset_parallel_scan = false;
531 
532  /*
533  * If we are doing runtime key calculations (ie, any of the index key
534  * values weren't simple Consts), compute the new key values. But first,
535  * reset the context so we don't leak memory as each outer tuple is
536  * scanned. Note this assumes that we will recalculate *all* runtime keys
537  * on each call.
538  */
539  if (node->iss_NumRuntimeKeys != 0)
540  {
541  ExprContext *econtext = node->iss_RuntimeContext;
542 
543  ResetExprContext(econtext);
544  ExecIndexEvalRuntimeKeys(econtext,
545  node->iss_RuntimeKeys,
546  node->iss_NumRuntimeKeys);
547  }
548  node->iss_RuntimeKeysReady = true;
549 
550  /* flush the reorder queue */
551  if (node->iss_ReorderQueue)
552  {
553  while (!pairingheap_is_empty(node->iss_ReorderQueue))
554  reorderqueue_pop(node);
555  }
556 
557  /*
558  * Reset (parallel) index scan. For parallel-aware nodes, the scan
559  * descriptor is initialized during actual execution of node and we can
560  * reach here before that (ex. during execution of nest loop join). So,
561  * avoid updating the scan descriptor at that time.
562  */
563  if (node->iss_ScanDesc)
564  {
566  node->iss_ScanKeys, node->iss_NumScanKeys,
567  node->iss_OrderByKeys, node->iss_NumOrderByKeys);
568 
569  if (reset_parallel_scan && node->iss_ScanDesc->parallel_scan)
571  }
572  node->iss_ReachedEnd = false;
573 
574  ExecScanReScan(&node->ss);
575 }
ParallelIndexScanDesc parallel_scan
Definition: relscan.h:132
IndexRuntimeKeyInfo * iss_RuntimeKeys
Definition: execnodes.h:1378
#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:1374
void index_parallelrescan(IndexScanDesc scan)
Definition: indexam.c:481
bool iss_ReachedEnd
Definition: execnodes.h:1387
int iss_NumRuntimeKeys
Definition: execnodes.h:1379
bool iss_RuntimeKeysReady
Definition: execnodes.h:1380
ScanState ss
Definition: execnodes.h:1371
static HeapTuple reorderqueue_pop(IndexScanState *node)
ExprContext * iss_RuntimeContext
Definition: execnodes.h:1381
void ExecIndexEvalRuntimeKeys(ExprContext *econtext, IndexRuntimeKeyInfo *runtimeKeys, int numRuntimeKeys)
void ExecScanReScan(ScanState *node)
Definition: execScan.c:327
int iss_NumOrderByKeys
Definition: execnodes.h:1377
IndexScanDesc iss_ScanDesc
Definition: execnodes.h:1383
#define ResetExprContext(econtext)
Definition: executor.h:332
pairingheap * iss_ReorderQueue
Definition: execnodes.h:1386
ScanKey iss_OrderByKeys
Definition: execnodes.h:1376