aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r--src/backend/optimizer/path/indxpath.c26
-rw-r--r--src/backend/optimizer/plan/createplan.c46
-rw-r--r--src/backend/optimizer/util/plancat.c3
3 files changed, 60 insertions, 15 deletions
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 7197658ae9b..176f2a66387 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.218 2007/03/21 22:18:12 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.219 2007/04/06 22:33:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1050,6 +1050,7 @@ match_clause_to_indexcol(IndexOptInfo *index,
* Clause must be a binary opclause, or possibly a ScalarArrayOpExpr
* (which is always binary, by definition). Or it could be a
* RowCompareExpr, which we pass off to match_rowcompare_to_indexcol().
+ * Or, if the index supports it, we can handle IS NULL clauses.
*/
if (is_opclause(clause))
{
@@ -1083,6 +1084,15 @@ match_clause_to_indexcol(IndexOptInfo *index,
(RowCompareExpr *) clause,
outer_relids);
}
+ else if (index->amsearchnulls && IsA(clause, NullTest))
+ {
+ NullTest *nt = (NullTest *) clause;
+
+ if (nt->nulltesttype == IS_NULL &&
+ match_index_to_operand((Node *) nt->arg, indexcol, index))
+ return true;
+ return false;
+ }
else
return false;
@@ -2102,8 +2112,8 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups)
}
/*
- * Else it must be an opclause (usual case), ScalarArrayOp, or
- * RowCompare
+ * Else it must be an opclause (usual case), ScalarArrayOp,
+ * RowCompare, or NullTest
*/
if (is_opclause(clause))
{
@@ -2123,6 +2133,16 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups)
index,
indexcol));
}
+ else if (IsA(clause, NullTest))
+ {
+ Assert(index->amsearchnulls);
+ resultquals = lappend(resultquals,
+ make_restrictinfo(clause,
+ true,
+ false,
+ false,
+ NULL));
+ }
else
elog(ERROR, "unsupported indexqual type: %d",
(int) nodeTag(clause));
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 6c4bde14213..9b9645faf28 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.227 2007/02/25 17:44:01 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.228 2007/04/06 22:33:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -18,6 +18,7 @@
#include <limits.h>
+#include "access/skey.h"
#include "nodes/makefuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
@@ -1821,6 +1822,7 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path,
Oid stratlefttype;
Oid stratrighttype;
bool recheck;
+ bool is_null_op = false;
Assert(IsA(rinfo, RestrictInfo));
@@ -1907,6 +1909,17 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path,
&opfamily);
clause_op = saop->opno;
}
+ else if (IsA(clause, NullTest))
+ {
+ NullTest *nt = (NullTest *) clause;
+
+ Assert(nt->nulltesttype == IS_NULL);
+ nt->arg = (Expr *) fix_indexqual_operand((Node *) nt->arg,
+ index,
+ &opfamily);
+ is_null_op = true;
+ clause_op = InvalidOid; /* keep compiler quiet */
+ }
else
{
elog(ERROR, "unsupported indexqual type: %d",
@@ -1916,16 +1929,27 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path,
*fixed_indexquals = lappend(*fixed_indexquals, clause);
- /*
- * Look up the (possibly commuted) operator in the operator family to
- * get its strategy number and the recheck indicator. This also
- * double-checks that we found an operator matching the index.
- */
- get_op_opfamily_properties(clause_op, opfamily,
- &stratno,
- &stratlefttype,
- &stratrighttype,
- &recheck);
+ if (is_null_op)
+ {
+ /* IS NULL doesn't have a clause_op */
+ stratno = InvalidStrategy;
+ stratrighttype = InvalidOid;
+ /* We assume it's non-lossy ... might need more work someday */
+ recheck = false;
+ }
+ else
+ {
+ /*
+ * Look up the (possibly commuted) operator in the operator family
+ * to get its strategy number and the recheck indicator. This also
+ * double-checks that we found an operator matching the index.
+ */
+ get_op_opfamily_properties(clause_op, opfamily,
+ &stratno,
+ &stratlefttype,
+ &stratrighttype,
+ &recheck);
+ }
*indexstrategy = lappend_int(*indexstrategy, stratno);
*indexsubtype = lappend_oid(*indexsubtype, stratrighttype);
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index e52943a675e..33b081ffffd 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.132 2007/01/20 23:13:01 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.133 2007/04/06 22:33:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -187,6 +187,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
info->relam = indexRelation->rd_rel->relam;
info->amcostestimate = indexRelation->rd_am->amcostestimate;
info->amoptionalkey = indexRelation->rd_am->amoptionalkey;
+ info->amsearchnulls = indexRelation->rd_am->amsearchnulls;
/*
* Fetch the ordering operators associated with the index, if any.