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

830 {
831  Relation indexRelationDesc;
832  IndexScanDesc indexScanDesc;
833  Relation relation;
834 
835  /*
836  * extract information from the node
837  */
838  indexRelationDesc = node->iss_RelationDesc;
839  indexScanDesc = node->iss_ScanDesc;
840  relation = node->ss.ss_currentRelation;
841 
842  /*
843  * Free the exprcontext(s) ... now dead code, see ExecFreeExprContext
844  */
845 #ifdef NOT_USED
846  ExecFreeExprContext(&node->ss.ps);
847  if (node->iss_RuntimeContext)
848  FreeExprContext(node->iss_RuntimeContext, true);
849 #endif
850 
851  /*
852  * clear out tuple table slots
853  */
856 
857  /*
858  * close the index relation (no-op if we didn't open it)
859  */
860  if (indexScanDesc)
861  index_endscan(indexScanDesc);
862  if (indexRelationDesc)
863  index_close(indexRelationDesc, NoLock);
864 
865  /*
866  * close the heap relation.
867  */
868  ExecCloseScanRelation(relation);
869 }
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1101
Relation ss_currentRelation
Definition: execnodes.h:1099
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:521
PlanState ps
Definition: execnodes.h:1098
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:880
#define NoLock
Definition: lockdefs.h:34
void index_endscan(IndexScanDesc scan)
Definition: indexam.c:340
void FreeExprContext(ExprContext *econtext, bool isCommit)
Definition: execUtils.c:354
ScanState ss
Definition: execnodes.h:1182
void ExecCloseScanRelation(Relation scanrel)
Definition: execUtils.c:666
ExprContext * iss_RuntimeContext
Definition: execnodes.h:1192
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:176
IndexScanDesc iss_ScanDesc
Definition: execnodes.h:1194
Relation iss_RelationDesc
Definition: execnodes.h:1193
bool ExecIndexAdvanceArrayKeys ( IndexArrayKeyInfo arrayKeys,
int  numArrayKeys 
)

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

785 {
786  bool found = false;
787  int j;
788 
789  /*
790  * Note we advance the rightmost array key most quickly, since it will
791  * correspond to the lowest-order index column among the available
792  * qualifications. This is hypothesized to result in better locality of
793  * access in the index.
794  */
795  for (j = numArrayKeys - 1; j >= 0; j--)
796  {
797  ScanKey scan_key = arrayKeys[j].scan_key;
798  int next_elem = arrayKeys[j].next_elem;
799  int num_elems = arrayKeys[j].num_elems;
800  Datum *elem_values = arrayKeys[j].elem_values;
801  bool *elem_nulls = arrayKeys[j].elem_nulls;
802 
803  if (next_elem >= num_elems)
804  {
805  next_elem = 0;
806  found = false; /* need to advance next array key */
807  }
808  else
809  found = true;
810  scan_key->sk_argument = elem_values[next_elem];
811  if (elem_nulls[next_elem])
812  scan_key->sk_flags |= SK_ISNULL;
813  else
814  scan_key->sk_flags &= ~SK_ISNULL;
815  arrayKeys[j].next_elem = next_elem + 1;
816  if (found)
817  break;
818  }
819 
820  return found;
821 }
Datum * elem_values
Definition: execnodes.h:1150
#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 1163 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, RegProcedureIsValid, 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().

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

707 {
708  bool result = true;
709  int j;
710  MemoryContext oldContext;
711 
712  /* We want to keep the arrays in per-tuple memory */
713  oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
714 
715  for (j = 0; j < numArrayKeys; j++)
716  {
717  ScanKey scan_key = arrayKeys[j].scan_key;
718  ExprState *array_expr = arrayKeys[j].array_expr;
719  Datum arraydatum;
720  bool isNull;
721  ArrayType *arrayval;
722  int16 elmlen;
723  bool elmbyval;
724  char elmalign;
725  int num_elems;
726  Datum *elem_values;
727  bool *elem_nulls;
728 
729  /*
730  * Compute and deconstruct the array expression. (Notes in
731  * ExecIndexEvalRuntimeKeys() apply here too.)
732  */
733  arraydatum = ExecEvalExpr(array_expr,
734  econtext,
735  &isNull);
736  if (isNull)
737  {
738  result = false;
739  break; /* no point in evaluating more */
740  }
741  arrayval = DatumGetArrayTypeP(arraydatum);
742  /* We could cache this data, but not clear it's worth it */
744  &elmlen, &elmbyval, &elmalign);
745  deconstruct_array(arrayval,
746  ARR_ELEMTYPE(arrayval),
747  elmlen, elmbyval, elmalign,
748  &elem_values, &elem_nulls, &num_elems);
749  if (num_elems <= 0)
750  {
751  result = false;
752  break; /* no point in evaluating more */
753  }
754 
755  /*
756  * Note: we expect the previous array data, if any, to be
757  * automatically freed by resetting the per-tuple context; hence no
758  * pfree's here.
759  */
760  arrayKeys[j].elem_values = elem_values;
761  arrayKeys[j].elem_nulls = elem_nulls;
762  arrayKeys[j].num_elems = num_elems;
763  scan_key->sk_argument = elem_values[0];
764  if (elem_nulls[0])
765  scan_key->sk_flags |= SK_ISNULL;
766  else
767  scan_key->sk_flags &= ~SK_ISNULL;
768  arrayKeys[j].next_elem = 1;
769  }
770 
771  MemoryContextSwitchTo(oldContext);
772 
773  return result;
774 }
Datum * elem_values
Definition: execnodes.h:1150
signed short int16
Definition: c.h:255
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2021
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:203
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
return result
Definition: formatting.c:1633
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:285
#define SK_ISNULL
Definition: skey.h:115
uintptr_t Datum
Definition: postgres.h:372
ExprState * array_expr
Definition: execnodes.h:1147
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 643 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().

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

Definition at line 876 of file nodeIndexscan.c.

References index_markpos(), and IndexScanState::iss_ScanDesc.

Referenced by ExecMarkPos().

877 {
879 }
void index_markpos(IndexScanDesc scan)
Definition: indexam.c:370
IndexScanDesc iss_ScanDesc
Definition: execnodes.h:1194
void ExecIndexRestrPos ( IndexScanState node)

Definition at line 886 of file nodeIndexscan.c.

References index_restrpos(), and IndexScanState::iss_ScanDesc.

Referenced by ExecRestrPos().

887 {
889 }
void index_restrpos(IndexScanDesc scan)
Definition: indexam.c:395
IndexScanDesc iss_ScanDesc
Definition: execnodes.h:1194
void ExecIndexScanEstimate ( IndexScanState node,
ParallelContext pcxt 
)

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

1674 {
1675  EState *estate = node->ss.ps.state;
1676 
1678  estate->es_snapshot);
1680  shm_toc_estimate_keys(&pcxt->estimator, 1);
1681 }
shm_toc_estimator estimator
Definition: parallel.h:41
Snapshot es_snapshot
Definition: execnodes.h:429
EState * state
Definition: execnodes.h:849
#define shm_toc_estimate_chunk(e, sz)
Definition: shm_toc.h:51
Size index_parallelscan_estimate(Relation indexRelation, Snapshot snapshot)
Definition: indexam.c:417
PlanState ps
Definition: execnodes.h:1098
ScanState ss
Definition: execnodes.h:1182
#define shm_toc_estimate_keys(e, cnt)
Definition: shm_toc.h:53
Relation iss_RelationDesc
Definition: execnodes.h:1193
void ExecIndexScanInitializeDSM ( IndexScanState node,
ParallelContext pcxt 
)

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

1692 {
1693  EState *estate = node->ss.ps.state;
1694  ParallelIndexScanDesc piscan;
1695 
1696  piscan = shm_toc_allocate(pcxt->toc, node->iss_PscanLen);
1698  node->iss_RelationDesc,
1699  estate->es_snapshot,
1700  piscan);
1701  shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, piscan);
1702  node->iss_ScanDesc =
1704  node->iss_RelationDesc,
1705  node->iss_NumScanKeys,
1706  node->iss_NumOrderByKeys,
1707  piscan);
1708 
1709  /*
1710  * If no run-time keys to calculate or they are ready, go ahead and pass
1711  * the scankeys to the index AM.
1712  */
1713  if (node->iss_NumRuntimeKeys == 0 || node->iss_RuntimeKeysReady)
1714  index_rescan(node->iss_ScanDesc,
1715  node->iss_ScanKeys, node->iss_NumScanKeys,
1716  node->iss_OrderByKeys, node->iss_NumOrderByKeys);
1717 }
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:143
void index_rescan(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int norderbys)
Definition: indexam.c:310
Snapshot es_snapshot
Definition: execnodes.h:429
Relation ss_currentRelation
Definition: execnodes.h:1099
EState * state
Definition: execnodes.h:849
ScanKey iss_ScanKeys
Definition: execnodes.h:1185
PlanState ps
Definition: execnodes.h:1098
int iss_NumRuntimeKeys
Definition: execnodes.h:1190
bool iss_RuntimeKeysReady
Definition: execnodes.h:1191
Plan * plan
Definition: execnodes.h:847
ScanState ss
Definition: execnodes.h:1182
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
Definition: shm_toc.c:88
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
Definition: shm_toc.c:171
void index_parallelscan_initialize(Relation heapRelation, Relation indexRelation, Snapshot snapshot, ParallelIndexScanDesc target)
Definition: indexam.c:450
int iss_NumOrderByKeys
Definition: execnodes.h:1188
IndexScanDesc iss_ScanDesc
Definition: execnodes.h:1194
shm_toc * toc
Definition: parallel.h:44
Relation iss_RelationDesc
Definition: execnodes.h:1193
ScanKey iss_OrderByKeys
Definition: execnodes.h:1187
void ExecIndexScanInitializeWorker ( IndexScanState node,
shm_toc toc 
)

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

1727 {
1728  ParallelIndexScanDesc piscan;
1729 
1730  piscan = shm_toc_lookup(toc, node->ss.ps.plan->plan_node_id, false);
1731  node->iss_ScanDesc =
1733  node->iss_RelationDesc,
1734  node->iss_NumScanKeys,
1735  node->iss_NumOrderByKeys,
1736  piscan);
1737 
1738  /*
1739  * If no run-time keys to calculate or they are ready, go ahead and pass
1740  * the scankeys to the index AM.
1741  */
1742  if (node->iss_NumRuntimeKeys == 0 || node->iss_RuntimeKeysReady)
1743  index_rescan(node->iss_ScanDesc,
1744  node->iss_ScanKeys, node->iss_NumScanKeys,
1745  node->iss_OrderByKeys, node->iss_NumOrderByKeys);
1746 }
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:143
void index_rescan(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int norderbys)
Definition: indexam.c:310
Relation ss_currentRelation
Definition: execnodes.h:1099
ScanKey iss_ScanKeys
Definition: execnodes.h:1185
PlanState ps
Definition: execnodes.h:1098
int iss_NumRuntimeKeys
Definition: execnodes.h:1190
bool iss_RuntimeKeysReady
Definition: execnodes.h:1191
Plan * plan
Definition: execnodes.h:847
ScanState ss
Definition: execnodes.h:1182
int iss_NumOrderByKeys
Definition: execnodes.h:1188
IndexScanDesc iss_ScanDesc
Definition: execnodes.h:1194
void * shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
Definition: shm_toc.c:232
Relation iss_RelationDesc
Definition: execnodes.h:1193
ScanKey iss_OrderByKeys
Definition: execnodes.h:1187
IndexScanState* ExecInitIndexScan ( IndexScan node,
EState estate,
int  eflags 
)

Definition at line 903 of file nodeIndexscan.c.

References SortSupportData::abbreviate, AccessShareLock, Assert, CurrentMemoryContext, EXEC_FLAG_EXPLAIN_ONLY, ExecAssignExprContext(), ExecAssignResultTypeFromTL(), ExecAssignScanProjectionInfo(), ExecAssignScanType(), ExecIndexBuildScanKeys(), ExecIndexScan(), ExecInitExprList(), ExecInitQual(), ExecInitResultTupleSlot(), ExecInitScanTupleSlot(), ExecOpenScanRelation(), PlanState::ExecProcNode, 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, and PlanState::state.

Referenced by ExecInitNode().

904 {
905  IndexScanState *indexstate;
906  Relation currentRelation;
907  bool relistarget;
908 
909  /*
910  * create state structure
911  */
912  indexstate = makeNode(IndexScanState);
913  indexstate->ss.ps.plan = (Plan *) node;
914  indexstate->ss.ps.state = estate;
915  indexstate->ss.ps.ExecProcNode = ExecIndexScan;
916 
917  /*
918  * Miscellaneous initialization
919  *
920  * create expression context for node
921  */
922  ExecAssignExprContext(estate, &indexstate->ss.ps);
923 
924  /*
925  * initialize child expressions
926  *
927  * Note: we don't initialize all of the indexqual expression, only the
928  * sub-parts corresponding to runtime keys (see below). Likewise for
929  * indexorderby, if any. But the indexqualorig expression is always
930  * initialized even though it will only be used in some uncommon cases ---
931  * would be nice to improve that. (Problem is that any SubPlans present
932  * in the expression must be found now...)
933  */
934  indexstate->ss.ps.qual =
935  ExecInitQual(node->scan.plan.qual, (PlanState *) indexstate);
936  indexstate->indexqualorig =
937  ExecInitQual(node->indexqualorig, (PlanState *) indexstate);
938  indexstate->indexorderbyorig =
939  ExecInitExprList(node->indexorderbyorig, (PlanState *) indexstate);
940 
941  /*
942  * tuple table initialization
943  */
944  ExecInitResultTupleSlot(estate, &indexstate->ss.ps);
945  ExecInitScanTupleSlot(estate, &indexstate->ss);
946 
947  /*
948  * open the base relation and acquire appropriate lock on it.
949  */
950  currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
951 
952  indexstate->ss.ss_currentRelation = currentRelation;
953  indexstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */
954 
955  /*
956  * get the scan type from the relation descriptor.
957  */
958  ExecAssignScanType(&indexstate->ss, RelationGetDescr(currentRelation));
959 
960  /*
961  * Initialize result tuple type and projection info.
962  */
963  ExecAssignResultTypeFromTL(&indexstate->ss.ps);
964  ExecAssignScanProjectionInfo(&indexstate->ss);
965 
966  /*
967  * If we are just doing EXPLAIN (ie, aren't going to run the plan), stop
968  * here. This allows an index-advisor plugin to EXPLAIN a plan containing
969  * references to nonexistent indexes.
970  */
971  if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
972  return indexstate;
973 
974  /*
975  * Open the index relation.
976  *
977  * If the parent table is one of the target relations of the query, then
978  * InitPlan already opened and write-locked the index, so we can avoid
979  * taking another lock here. Otherwise we need a normal reader's lock.
980  */
981  relistarget = ExecRelationIsTargetRelation(estate, node->scan.scanrelid);
982  indexstate->iss_RelationDesc = index_open(node->indexid,
983  relistarget ? NoLock : AccessShareLock);
984 
985  /*
986  * Initialize index-specific scan state
987  */
988  indexstate->iss_RuntimeKeysReady = false;
989  indexstate->iss_RuntimeKeys = NULL;
990  indexstate->iss_NumRuntimeKeys = 0;
991 
992  /*
993  * build the index scan keys from the index qualification
994  */
995  ExecIndexBuildScanKeys((PlanState *) indexstate,
996  indexstate->iss_RelationDesc,
997  node->indexqual,
998  false,
999  &indexstate->iss_ScanKeys,
1000  &indexstate->iss_NumScanKeys,
1001  &indexstate->iss_RuntimeKeys,
1002  &indexstate->iss_NumRuntimeKeys,
1003  NULL, /* no ArrayKeys */
1004  NULL);
1005 
1006  /*
1007  * any ORDER BY exprs have to be turned into scankeys in the same way
1008  */
1009  ExecIndexBuildScanKeys((PlanState *) indexstate,
1010  indexstate->iss_RelationDesc,
1011  node->indexorderby,
1012  true,
1013  &indexstate->iss_OrderByKeys,
1014  &indexstate->iss_NumOrderByKeys,
1015  &indexstate->iss_RuntimeKeys,
1016  &indexstate->iss_NumRuntimeKeys,
1017  NULL, /* no ArrayKeys */
1018  NULL);
1019 
1020  /* Initialize sort support, if we need to re-check ORDER BY exprs */
1021  if (indexstate->iss_NumOrderByKeys > 0)
1022  {
1023  int numOrderByKeys = indexstate->iss_NumOrderByKeys;
1024  int i;
1025  ListCell *lco;
1026  ListCell *lcx;
1027 
1028  /*
1029  * Prepare sort support, and look up the data type for each ORDER BY
1030  * expression.
1031  */
1032  Assert(numOrderByKeys == list_length(node->indexorderbyops));
1033  Assert(numOrderByKeys == list_length(node->indexorderbyorig));
1034  indexstate->iss_SortSupport = (SortSupportData *)
1035  palloc0(numOrderByKeys * sizeof(SortSupportData));
1036  indexstate->iss_OrderByTypByVals = (bool *)
1037  palloc(numOrderByKeys * sizeof(bool));
1038  indexstate->iss_OrderByTypLens = (int16 *)
1039  palloc(numOrderByKeys * sizeof(int16));
1040  i = 0;
1041  forboth(lco, node->indexorderbyops, lcx, node->indexorderbyorig)
1042  {
1043  Oid orderbyop = lfirst_oid(lco);
1044  Node *orderbyexpr = (Node *) lfirst(lcx);
1045  Oid orderbyType = exprType(orderbyexpr);
1046  Oid orderbyColl = exprCollation(orderbyexpr);
1047  SortSupport orderbysort = &indexstate->iss_SortSupport[i];
1048 
1049  /* Initialize sort support */
1050  orderbysort->ssup_cxt = CurrentMemoryContext;
1051  orderbysort->ssup_collation = orderbyColl;
1052  /* See cmp_orderbyvals() comments on NULLS LAST */
1053  orderbysort->ssup_nulls_first = false;
1054  /* ssup_attno is unused here and elsewhere */
1055  orderbysort->ssup_attno = 0;
1056  /* No abbreviation */
1057  orderbysort->abbreviate = false;
1058  PrepareSortSupportFromOrderingOp(orderbyop, orderbysort);
1059 
1060  get_typlenbyval(orderbyType,
1061  &indexstate->iss_OrderByTypLens[i],
1062  &indexstate->iss_OrderByTypByVals[i]);
1063  i++;
1064  }
1065 
1066  /* allocate arrays to hold the re-calculated distances */
1067  indexstate->iss_OrderByValues = (Datum *)
1068  palloc(numOrderByKeys * sizeof(Datum));
1069  indexstate->iss_OrderByNulls = (bool *)
1070  palloc(numOrderByKeys * sizeof(bool));
1071 
1072  /* and initialize the reorder queue */
1074  indexstate);
1075  }
1076 
1077  /*
1078  * If we have runtime keys, we need an ExprContext to evaluate them. The
1079  * node's standard context won't do because we want to reset that context
1080  * for every tuple. So, build another context just like the other one...
1081  * -tgl 7/11/00
1082  */
1083  if (indexstate->iss_NumRuntimeKeys != 0)
1084  {
1085  ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext;
1086 
1087  ExecAssignExprContext(estate, &indexstate->ss.ps);
1088  indexstate->iss_RuntimeContext = indexstate->ss.ps.ps_ExprContext;
1089  indexstate->ss.ps.ps_ExprContext = stdecontext;
1090  }
1091  else
1092  {
1093  indexstate->iss_RuntimeContext = NULL;
1094  }
1095 
1096  /*
1097  * all done.
1098  */
1099  return indexstate;
1100 }
signed short int16
Definition: c.h:255
bool ssup_nulls_first
Definition: sortsupport.h:75
List * qual
Definition: plannodes.h:145
Plan plan
Definition: plannodes.h:328
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:180
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate)
Definition: execTuples.c:842
Index scanrelid
Definition: plannodes.h:329
#define RelationGetDescr(relation)
Definition: rel.h:428
IndexRuntimeKeyInfo * iss_RuntimeKeys
Definition: execnodes.h:1189
int16 * iss_OrderByTypLens
Definition: execnodes.h:1203
ExprContext * ps_ExprContext
Definition: execnodes.h:881
SortSupport iss_SortSupport
Definition: execnodes.h:1201
void PrepareSortSupportFromOrderingOp(Oid orderingOp, SortSupport ssup)
Definition: sortsupport.c:133
List * indexqualorig
Definition: plannodes.h:391
#define AccessShareLock
Definition: lockdefs.h:36
static TupleTableSlot * ExecIndexScan(PlanState *pstate)
Definition: nodes.h:509
pairingheap * pairingheap_allocate(pairingheap_comparator compare, void *arg)
Definition: pairingheap.c:42
Relation ss_currentRelation
Definition: execnodes.h:1099
EState * state
Definition: execnodes.h:849
unsigned int Oid
Definition: postgres_ext.h:31
ExprState * indexqualorig
Definition: execnodes.h:1183
ScanKey iss_ScanKeys
Definition: execnodes.h:1185
Oid indexid
Definition: plannodes.h:389
List * indexorderbyorig
Definition: execnodes.h:1184
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:160
void ExecAssignResultTypeFromTL(PlanState *planstate)
Definition: execUtils.c:445
bool * iss_OrderByNulls
Definition: execnodes.h:1200
PlanState ps
Definition: execnodes.h:1098
List * indexorderbyorig
Definition: plannodes.h:393
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:608
MemoryContext ssup_cxt
Definition: sortsupport.h:66
Scan scan
Definition: plannodes.h:388
#define NoLock
Definition: lockdefs.h:34
int iss_NumRuntimeKeys
Definition: execnodes.h:1190
bool * iss_OrderByTypByVals
Definition: execnodes.h:1202
static int reorderqueue_cmp(const pairingheap_node *a, const pairingheap_node *b, void *arg)
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:266
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
bool iss_RuntimeKeysReady
Definition: execnodes.h:1191
List * indexqual
Definition: plannodes.h:390
void * palloc0(Size size)
Definition: mcxt.c:878
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:853
uintptr_t Datum
Definition: postgres.h:372
AttrNumber ssup_attno
Definition: sortsupport.h:81
Plan * plan
Definition: execnodes.h:847
ScanState ss
Definition: execnodes.h:1182
#define makeNode(_type_)
Definition: nodes.h:557
List * indexorderby
Definition: plannodes.h:392
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
#define lfirst(lc)
Definition: pg_list.h:106
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:423
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:720
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:2001
ExprContext * iss_RuntimeContext
Definition: execnodes.h:1192
List * indexorderbyops
Definition: plannodes.h:394
ExprState * qual
Definition: execnodes.h:865
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1100
void * palloc(Size size)
Definition: mcxt.c:849
int i
void ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
Definition: execUtils.c:545
Datum * iss_OrderByValues
Definition: execnodes.h:1199
int iss_NumOrderByKeys
Definition: execnodes.h:1188
#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:582
#define lfirst_oid(lc)
Definition: pg_list.h:108
Relation iss_RelationDesc
Definition: execnodes.h:1193
pairingheap * iss_ReorderQueue
Definition: execnodes.h:1197
ScanKey iss_OrderByKeys
Definition: execnodes.h:1187
void ExecReScanIndexScan ( IndexScanState node)

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

579 {
580  bool reset_parallel_scan = true;
581 
582  /*
583  * If we are here to just update the scan keys, then don't reset parallel
584  * scan. We don't want each of the participating process in the parallel
585  * scan to update the shared parallel scan state at the start of the scan.
586  * It is quite possible that one of the participants has already begun
587  * scanning the index when another has yet to start it.
588  */
589  if (node->iss_NumRuntimeKeys != 0 && !node->iss_RuntimeKeysReady)
590  reset_parallel_scan = false;
591 
592  /*
593  * If we are doing runtime key calculations (ie, any of the index key
594  * values weren't simple Consts), compute the new key values. But first,
595  * reset the context so we don't leak memory as each outer tuple is
596  * scanned. Note this assumes that we will recalculate *all* runtime keys
597  * on each call.
598  */
599  if (node->iss_NumRuntimeKeys != 0)
600  {
601  ExprContext *econtext = node->iss_RuntimeContext;
602 
603  ResetExprContext(econtext);
604  ExecIndexEvalRuntimeKeys(econtext,
605  node->iss_RuntimeKeys,
606  node->iss_NumRuntimeKeys);
607  }
608  node->iss_RuntimeKeysReady = true;
609 
610  /* flush the reorder queue */
611  if (node->iss_ReorderQueue)
612  {
613  while (!pairingheap_is_empty(node->iss_ReorderQueue))
614  reorderqueue_pop(node);
615  }
616 
617  /*
618  * Reset (parallel) index scan. For parallel-aware nodes, the scan
619  * descriptor is initialized during actual execution of node and we can
620  * reach here before that (ex. during execution of nest loop join). So,
621  * avoid updating the scan descriptor at that time.
622  */
623  if (node->iss_ScanDesc)
624  {
626  node->iss_ScanKeys, node->iss_NumScanKeys,
627  node->iss_OrderByKeys, node->iss_NumOrderByKeys);
628 
629  if (reset_parallel_scan && node->iss_ScanDesc->parallel_scan)
631  }
632  node->iss_ReachedEnd = false;
633 
634  ExecScanReScan(&node->ss);
635 }
ParallelIndexScanDesc parallel_scan
Definition: relscan.h:140
IndexRuntimeKeyInfo * iss_RuntimeKeys
Definition: execnodes.h:1189
#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:1185
void index_parallelrescan(IndexScanDesc scan)
Definition: indexam.c:481
bool iss_ReachedEnd
Definition: execnodes.h:1198
int iss_NumRuntimeKeys
Definition: execnodes.h:1190
bool iss_RuntimeKeysReady
Definition: execnodes.h:1191
ScanState ss
Definition: execnodes.h:1182
static HeapTuple reorderqueue_pop(IndexScanState *node)
ExprContext * iss_RuntimeContext
Definition: execnodes.h:1192
void ExecIndexEvalRuntimeKeys(ExprContext *econtext, IndexRuntimeKeyInfo *runtimeKeys, int numRuntimeKeys)
void ExecScanReScan(ScanState *node)
Definition: execScan.c:327
int iss_NumOrderByKeys
Definition: execnodes.h:1188
IndexScanDesc iss_ScanDesc
Definition: execnodes.h:1194
#define ResetExprContext(econtext)
Definition: executor.h:469
pairingheap * iss_ReorderQueue
Definition: execnodes.h:1197
ScanKey iss_OrderByKeys
Definition: execnodes.h:1187