|
|
@ -7,7 +7,7 @@ |
|
|
|
* |
|
|
|
* |
|
|
|
* |
|
|
|
* |
|
|
|
* IDENTIFICATION |
|
|
|
* IDENTIFICATION |
|
|
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.52 1999/05/01 19:47:40 tgl Exp $ |
|
|
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.53 1999/05/06 01:30:58 tgl Exp $ |
|
|
|
* |
|
|
|
* |
|
|
|
*------------------------------------------------------------------------- |
|
|
|
*------------------------------------------------------------------------- |
|
|
|
*/ |
|
|
|
*/ |
|
|
@ -629,15 +629,23 @@ create_hashjoin_node(HashPath *best_path, |
|
|
|
* |
|
|
|
* |
|
|
|
*****************************************************************************/ |
|
|
|
*****************************************************************************/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* fix_indxqual_references |
|
|
|
|
|
|
|
* Adjust a qual clause to refer to an index instead of the original relation. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* Returns a modified copy of the given clause --- the original is not changed. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
static Node * |
|
|
|
static Node * |
|
|
|
fix_indxqual_references(Node *clause, Path *index_path) |
|
|
|
fix_indxqual_references(Node *clause, Path *index_path) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Node *newclause; |
|
|
|
if (clause == NULL) |
|
|
|
|
|
|
|
return NULL; |
|
|
|
if (IsA(clause, Var)) |
|
|
|
else if (IsA(clause, Var)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (lfirsti(index_path->parent->relids) == ((Var *) clause)->varno) |
|
|
|
if (lfirsti(index_path->parent->relids) == ((Var *) clause)->varno) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
Node *newclause; |
|
|
|
int pos = 0; |
|
|
|
int pos = 0; |
|
|
|
int varatt = ((Var *) clause)->varattno; |
|
|
|
int varatt = ((Var *) clause)->varattno; |
|
|
|
int *indexkeys = ((IndexPath *) index_path)->indexkeys; |
|
|
|
int *indexkeys = ((IndexPath *) index_path)->indexkeys; |
|
|
@ -655,20 +663,18 @@ fix_indxqual_references(Node *clause, Path *index_path) |
|
|
|
((Var *) newclause)->varattno = pos + 1; |
|
|
|
((Var *) newclause)->varattno = pos + 1; |
|
|
|
return newclause; |
|
|
|
return newclause; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
/* The Var is not part of the indexed relation, leave it alone */ |
|
|
|
return clause; |
|
|
|
return copyObject(clause); |
|
|
|
} |
|
|
|
|
|
|
|
else if (IsA(clause, Const)) |
|
|
|
|
|
|
|
return clause; |
|
|
|
|
|
|
|
else if (IsA(clause, Param)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
/* Function parameter used as index scan arg. DZ - 27-8-1996 */ |
|
|
|
|
|
|
|
return clause; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
else if (single_node(clause)) |
|
|
|
|
|
|
|
return copyObject(clause); |
|
|
|
else if (is_opclause(clause) && |
|
|
|
else if (is_opclause(clause) && |
|
|
|
is_funcclause((Node *) get_leftop((Expr *) clause)) && |
|
|
|
is_funcclause((Node *) get_leftop((Expr *) clause)) && |
|
|
|
((Func *) ((Expr *) get_leftop((Expr *) clause))->oper)->funcisindex) |
|
|
|
((Func *) ((Expr *) get_leftop((Expr *) clause))->oper)->funcisindex) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
/* This looks pretty seriously wrong to me, but I'm not sure what it's
|
|
|
|
|
|
|
|
* supposed to be doing ... tgl 5/99 |
|
|
|
|
|
|
|
*/ |
|
|
|
Var *newvar = makeVar((Index) lfirsti(index_path->parent->relids), |
|
|
|
Var *newvar = makeVar((Index) lfirsti(index_path->parent->relids), |
|
|
|
1, /* func indices have one key */ |
|
|
|
1, /* func indices have one key */ |
|
|
|
((Func *) ((Expr *) clause)->oper)->functype, |
|
|
|
((Func *) ((Expr *) clause)->oper)->functype, |
|
|
@ -686,61 +692,60 @@ fix_indxqual_references(Node *clause, Path *index_path) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Expr *expr = (Expr *) clause; |
|
|
|
Expr *expr = (Expr *) clause; |
|
|
|
List *new_subclauses = NIL; |
|
|
|
List *new_subclauses = NIL; |
|
|
|
Node *subclause = NULL; |
|
|
|
List *i; |
|
|
|
List *i = NIL; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach(i, expr->args) |
|
|
|
foreach(i, expr->args) |
|
|
|
{ |
|
|
|
{ |
|
|
|
subclause = lfirst(i); |
|
|
|
Node *subclause = lfirst(i); |
|
|
|
if (subclause) |
|
|
|
new_subclauses = lappend(new_subclauses, |
|
|
|
new_subclauses = lappend(new_subclauses, |
|
|
|
fix_indxqual_references(subclause, |
|
|
|
fix_indxqual_references(subclause, |
|
|
|
index_path)); |
|
|
|
index_path)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
return (Node *) make_clause(expr->opType, expr->oper, new_subclauses); |
|
|
|
* XXX new_subclauses should be a list of the form: ( (var var) |
|
|
|
|
|
|
|
* (var const) ...) ? |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
if (new_subclauses) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return (Node *) |
|
|
|
|
|
|
|
make_clause(expr->opType, expr->oper, new_subclauses); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
return clause; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if (IsA(clause, CaseExpr)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
elog(NOTICE,"optimizer: fix_indxqual_references sees CaseExpr"); |
|
|
|
|
|
|
|
return clause; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else if (IsA(clause, List)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
List *oldclauses = (List *) clause; |
|
|
|
|
|
|
|
List *new_subclauses = NIL; |
|
|
|
List *new_subclauses = NIL; |
|
|
|
Node *subclause = NULL; |
|
|
|
List *i; |
|
|
|
List *i = NIL; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach(i, oldclauses) |
|
|
|
foreach(i, (List *) clause) |
|
|
|
{ |
|
|
|
{ |
|
|
|
subclause = lfirst(i); |
|
|
|
Node *subclause = lfirst(i); |
|
|
|
if (subclause) |
|
|
|
new_subclauses = lappend(new_subclauses, |
|
|
|
new_subclauses = lappend(new_subclauses, |
|
|
|
fix_indxqual_references(subclause, |
|
|
|
fix_indxqual_references(subclause, |
|
|
|
index_path)); |
|
|
|
index_path)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
return (Node *) new_subclauses; |
|
|
|
* XXX new_subclauses should be a list of the form: ( (var var) |
|
|
|
} |
|
|
|
* (var const) ...) ? |
|
|
|
else if (IsA(clause, ArrayRef)) |
|
|
|
*/ |
|
|
|
{ |
|
|
|
if (new_subclauses) |
|
|
|
ArrayRef *oldnode = (ArrayRef *) clause; |
|
|
|
return (Node *) new_subclauses; |
|
|
|
ArrayRef *newnode = makeNode(ArrayRef); |
|
|
|
else |
|
|
|
|
|
|
|
return clause; |
|
|
|
newnode->refattrlength = oldnode->refattrlength; |
|
|
|
|
|
|
|
newnode->refelemlength = oldnode->refelemlength; |
|
|
|
|
|
|
|
newnode->refelemtype = oldnode->refelemtype; |
|
|
|
|
|
|
|
newnode->refelembyval = oldnode->refelembyval; |
|
|
|
|
|
|
|
newnode->refupperindexpr = (List *) |
|
|
|
|
|
|
|
fix_indxqual_references((Node *) oldnode->refupperindexpr, |
|
|
|
|
|
|
|
index_path); |
|
|
|
|
|
|
|
newnode->reflowerindexpr = (List *) |
|
|
|
|
|
|
|
fix_indxqual_references((Node *) oldnode->reflowerindexpr, |
|
|
|
|
|
|
|
index_path); |
|
|
|
|
|
|
|
newnode->refexpr = |
|
|
|
|
|
|
|
fix_indxqual_references(oldnode->refexpr, index_path); |
|
|
|
|
|
|
|
newnode->refassgnexpr = |
|
|
|
|
|
|
|
fix_indxqual_references(oldnode->refassgnexpr, index_path); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return (Node *) newnode; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
elog(ERROR, "fix_indxqual_references: Cannot handle node type %d", |
|
|
|
|
|
|
|
nodeTag(clause)); |
|
|
|
|
|
|
|
return NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|