*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.49 2000/04/12 17:15:09 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.50 2000/05/23 16:56:37 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
for (j = 0; j < n_keys; j++)
{
- Expr *clause; /* one part of index qual */
- Oper *op; /* operator used in scan.. */
+ Expr *clause; /* one clause of index qual */
+ Oper *op; /* operator used in clause */
Node *leftop; /* expr on lhs of operator */
Node *rightop;/* expr on rhs ... */
bits16 flags = 0;
*/
scanvar = NO_OP;
+ run_keys[j] = NO_OP;
/* ----------------
* determine information in leftop
Assert(leftop != NULL);
- if (IsA(leftop, Var) &&var_is_rel((Var *) leftop))
+ if (IsA(leftop, Var) && var_is_rel((Var *) leftop))
{
/* ----------------
* if the leftop is a "rel-var", then it means
varattno = ((Var *) leftop)->varattno;
scanvar = LEFT_OP;
}
- else if (is_funcclause(leftop) &&
- var_is_rel(lfirst(((Expr *) leftop)->args)))
- {
- /* ----------------
- * if the leftop is a func node then it means
- * it identifies the value to place in our scan key.
- * Since functional indices have only one attribute
- * the attno must always be set to 1.
- * ----------------
- */
- varattno = 1;
- scanvar = LEFT_OP;
- }
else if (IsA(leftop, Const))
{
/* ----------------
* it identifies the value to place in our scan key.
* ----------------
*/
- run_keys[j] = NO_OP;
scanvalue = ((Const *) leftop)->constvalue;
+ if (((Const *) leftop)->constisnull)
+ flags |= SK_ISNULL;
}
else if (IsA(leftop, Param))
{
/* Life was so easy before ... subselects */
if (((Param *) leftop)->paramkind == PARAM_EXEC)
{
+ /* treat Param as runtime key */
have_runtime_keys = true;
run_keys[j] = LEFT_OP;
execParam = lappendi(execParam, ((Param *) leftop)->paramid);
}
else
{
+ /* treat Param like a constant */
scanvalue = ExecEvalParam((Param *) leftop,
scanstate->cstate.cs_ExprContext,
&isnull);
if (isnull)
flags |= SK_ISNULL;
-
- run_keys[j] = NO_OP;
}
}
else
{
/* ----------------
- * otherwise, the leftop contains information usable
+ * otherwise, the leftop contains an expression evaluable
* at runtime to figure out the value to place in our
* scan key.
* ----------------
*/
have_runtime_keys = true;
run_keys[j] = LEFT_OP;
- scanvalue = Int32GetDatum((int32) true);
}
/* ----------------
Assert(rightop != NULL);
- if (IsA(rightop, Var) &&var_is_rel((Var *) rightop))
+ if (IsA(rightop, Var) && var_is_rel((Var *) rightop))
{
/* ----------------
* here we make sure only one op identifies the
varattno = ((Var *) rightop)->varattno;
scanvar = RIGHT_OP;
}
- else if (is_funcclause(rightop) &&
- var_is_rel(lfirst(((Expr *) rightop)->args)))
- {
- /* ----------------
- * if the rightop is a func node then it means
- * it identifies the value to place in our scan key.
- * Since functional indices have only one attribute
- * the attno must always be set to 1.
- * ----------------
- */
- if (scanvar == LEFT_OP)
- elog(ERROR, "ExecInitIndexScan: %s",
- "both left and right ops are rel-vars");
-
- varattno = 1;
- scanvar = RIGHT_OP;
- }
else if (IsA(rightop, Const))
{
/* ----------------
* it identifies the value to place in our scan key.
* ----------------
*/
- run_keys[j] = NO_OP;
scanvalue = ((Const *) rightop)->constvalue;
+ if (((Const *) rightop)->constisnull)
+ flags |= SK_ISNULL;
}
else if (IsA(rightop, Param))
{
/* Life was so easy before ... subselects */
if (((Param *) rightop)->paramkind == PARAM_EXEC)
{
+ /* treat Param as runtime key */
have_runtime_keys = true;
run_keys[j] = RIGHT_OP;
execParam = lappendi(execParam, ((Param *) rightop)->paramid);
}
else
{
+ /* treat Param like a constant */
scanvalue = ExecEvalParam((Param *) rightop,
scanstate->cstate.cs_ExprContext,
&isnull);
if (isnull)
flags |= SK_ISNULL;
-
- run_keys[j] = NO_OP;
}
}
else
{
/* ----------------
- * otherwise, the rightop contains information usable
+ * otherwise, the rightop contains an expression evaluable
* at runtime to figure out the value to place in our
* scan key.
* ----------------
*/
have_runtime_keys = true;
run_keys[j] = RIGHT_OP;
- scanvalue = Int32GetDatum((int32) true);
}
/* ----------------
varattno, /* attribute number to
* scan */
(RegProcedure) opid, /* reg proc to use */
- (Datum) scanvalue); /* constant */
+ scanvalue); /* constant */
}
/* ----------------
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.89 2000/04/12 17:15:21 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.90 2000/05/23 16:56:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "optimizer/planmain.h"
#include "optimizer/restrictinfo.h"
#include "optimizer/tlist.h"
+#include "parser/parse_expr.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
* machinery needs.
*
* We have three tasks here:
- * * Var nodes representing index keys must have varattno equal to the
+ * * Index keys must be represented by Var nodes with varattno set to the
* index's attribute number, not the attribute number in the original rel.
* * indxpath.c may have selected an index that is binary-compatible with
* the actual expression operator, but not exactly the same datatype.
* Fix the sublist of indexquals to be used in a particular scan.
*
* For each qual clause, commute if needed to put the indexkey operand on the
- * left, and then change its varno. (We do not need to change the other side
+ * left, and then fix its varattno. (We do not need to change the other side
* of the clause.) Also change the operator if necessary.
*/
static List *
fix_indxqual_operand(Node *node, int baserelid, Form_pg_index index,
Oid *opclass)
{
+ /*
+ * We represent index keys by Var nodes having the varno of the base
+ * table but varattno equal to the index's attribute number (index
+ * column position). This is a bit hokey ... would be cleaner to use
+ * a special-purpose node type that could not be mistaken for a regular
+ * Var. But it will do for now.
+ */
if (IsA(node, Var))
{
+ /* If it's a var, find which index key position it occupies */
if (((Var *) node)->varno == baserelid)
{
int varatt = ((Var *) node)->varattno;
Node *newnode = copyObject(node);
((Var *) newnode)->varattno = pos + 1;
+ /* return the correct opclass, too */
*opclass = index->indclass[pos];
return newnode;
}
}
/*
- * Else, it must be a func expression representing a functional index.
- *
- * Currently, there is no need for us to do anything here for functional
- * indexes. If nodeIndexscan.c sees a func clause as the left or
- * right-hand toplevel operand of an indexqual, it assumes that that
- * is a reference to the functional index's value and makes the
- * appropriate substitution. (It would be cleaner to make the
- * substitution here, I think --- suspect this issue if a join clause
- * involving a function call misbehaves...)
+ * Else, it must be a func expression matching a functional index.
+ * Since we currently only support single-column functional indexes,
+ * the returned varattno must be 1.
*/
+ Assert(is_funcclause(node)); /* not a very thorough check, but easy */
+
/* indclass[0] is the only class of a functional index */
*opclass = index->indclass[0];
- /* return the unmodified node */
- return node;
+ return (Node *) makeVar(baserelid, 1, exprType(node), -1, 0);
}
/*