aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/nodeIndexscan.c75
1 files changed, 64 insertions, 11 deletions
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 6d073bf5fdb..e3be5a2cae3 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -647,11 +647,13 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
* as specified in access/skey.h. The elements of the row comparison
* can have either constant or non-constant comparison values.
*
- * 4. ScalarArrayOpExpr ("indexkey op ANY (array-expression)"). For these,
+ * 4. ScalarArrayOpExpr ("indexkey op ANY (array-expression)"). If the index
+ * has rd_am->amsearcharray, we handle these the same as simple operators,
+ * setting the SK_SEARCHARRAY flag to tell the AM to handle them. Otherwise,
* we create a ScanKey with everything filled in except the comparison value,
* and set up an IndexArrayKeyInfo struct to drive processing of the qual.
- * (Note that we treat all array-expressions as requiring runtime evaluation,
- * even if they happen to be constants.)
+ * (Note that if we use an IndexArrayKeyInfo struct, the array expression is
+ * always treated as requiring runtime evaluation, even if it's a constant.)
*
* 5. NullTest ("indexkey IS NULL/IS NOT NULL"). We just fill in the
* ScanKey properly.
@@ -680,7 +682,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
* *numArrayKeys: receives number of array keys
*
* Caller may pass NULL for arrayKeys and numArrayKeys to indicate that
- * ScalarArrayOpExpr quals are not supported.
+ * IndexArrayKeyInfos are not supported.
*/
void
ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
@@ -981,6 +983,8 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
{
/* indexkey op ANY (array-expression) */
ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
+ int flags = 0;
+ Datum scanvalue;
Assert(!isorderby);
@@ -1027,23 +1031,72 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
Assert(rightop != NULL);
- array_keys[n_array_keys].scan_key = this_scan_key;
- array_keys[n_array_keys].array_expr =
- ExecInitExpr(rightop, planstate);
- /* the remaining fields were zeroed by palloc0 */
- n_array_keys++;
+ if (index->rd_am->amsearcharray)
+ {
+ /* Index AM will handle this like a simple operator */
+ flags |= SK_SEARCHARRAY;
+ if (IsA(rightop, Const))
+ {
+ /* OK, simple constant comparison value */
+ scanvalue = ((Const *) rightop)->constvalue;
+ if (((Const *) rightop)->constisnull)
+ flags |= SK_ISNULL;
+ }
+ else
+ {
+ /* Need to treat this one as a runtime key */
+ if (n_runtime_keys >= max_runtime_keys)
+ {
+ if (max_runtime_keys == 0)
+ {
+ max_runtime_keys = 8;
+ runtime_keys = (IndexRuntimeKeyInfo *)
+ palloc(max_runtime_keys * sizeof(IndexRuntimeKeyInfo));
+ }
+ else
+ {
+ max_runtime_keys *= 2;
+ runtime_keys = (IndexRuntimeKeyInfo *)
+ repalloc(runtime_keys, max_runtime_keys * sizeof(IndexRuntimeKeyInfo));
+ }
+ }
+ runtime_keys[n_runtime_keys].scan_key = this_scan_key;
+ runtime_keys[n_runtime_keys].key_expr =
+ ExecInitExpr(rightop, planstate);
+
+ /*
+ * Careful here: the runtime expression is not of
+ * op_righttype, but rather is an array of same; so
+ * TypeIsToastable() isn't helpful. However, we can
+ * assume that all array types are toastable.
+ */
+ runtime_keys[n_runtime_keys].key_toastable = true;
+ n_runtime_keys++;
+ scanvalue = (Datum) 0;
+ }
+ }
+ else
+ {
+ /* Executor has to expand the array value */
+ array_keys[n_array_keys].scan_key = this_scan_key;
+ array_keys[n_array_keys].array_expr =
+ ExecInitExpr(rightop, planstate);
+ /* the remaining fields were zeroed by palloc0 */
+ n_array_keys++;
+ scanvalue = (Datum) 0;
+ }
/*
* initialize the scan key's fields appropriately
*/
ScanKeyEntryInitialize(this_scan_key,
- 0, /* flags */
+ flags,
varattno, /* attribute number to scan */
op_strategy, /* op's strategy */
op_righttype, /* strategy subtype */
saop->inputcollid, /* collation */
opfuncid, /* reg proc to use */
- (Datum) 0); /* constant */
+ scanvalue); /* constant */
}
else if (IsA(clause, NullTest))
{