mirror of
https://github.com/postgres/postgres.git
synced 2025-07-07 00:36:50 +03:00
Make 'col IS NULL' clauses be indexable conditions.
Teodor Sigaev, with some kibitzing from Tom Lane.
This commit is contained in:
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
Reference in New Issue
Block a user