mirror of
https://github.com/postgres/postgres.git
synced 2025-05-09 18:21:05 +03:00
Code cleanup inspired by recent resname bug report (doesn't fix the bug
yet, though). Avoid using nth() to fetch tlist entries; provide a common routine get_tle_by_resno() to search a tlist for a particular resno. This replaces a couple uses of nth() and a dozen hand-coded search loops. Also, replace a few uses of nth(length-1, list) with llast().
This commit is contained in:
parent
cae912d05b
commit
88381ade63
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.104 2003/08/04 02:39:58 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.105 2003/08/11 20:46:46 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -371,7 +371,7 @@ check_sql_fn_retval(Oid rettype, char fn_typtype, List *queryTreeList)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* find the final query */
|
/* find the final query */
|
||||||
parse = (Query *) nth(length(queryTreeList) - 1, queryTreeList);
|
parse = (Query *) llast(queryTreeList);
|
||||||
|
|
||||||
cmd = parse->commandType;
|
cmd = parse->commandType;
|
||||||
tlist = parse->targetList;
|
tlist = parse->targetList;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
* Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.69 2003/08/04 23:59:37 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.70 2003/08/11 20:46:46 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -365,7 +365,7 @@ CommentAttribute(List *qualname, char *comment)
|
|||||||
if (nnames < 2) /* parser messed up */
|
if (nnames < 2) /* parser messed up */
|
||||||
elog(ERROR, "must specify relation and attribute");
|
elog(ERROR, "must specify relation and attribute");
|
||||||
relname = ltruncate(nnames - 1, listCopy(qualname));
|
relname = ltruncate(nnames - 1, listCopy(qualname));
|
||||||
attrname = strVal(nth(nnames - 1, qualname));
|
attrname = strVal(llast(qualname));
|
||||||
|
|
||||||
/* Open the containing relation to ensure it won't go away meanwhile */
|
/* Open the containing relation to ensure it won't go away meanwhile */
|
||||||
rel = makeRangeVarFromNameList(relname);
|
rel = makeRangeVarFromNameList(relname);
|
||||||
@ -583,7 +583,7 @@ CommentRule(List *qualname, char *comment)
|
|||||||
/* New-style: rule and relname both provided */
|
/* New-style: rule and relname both provided */
|
||||||
Assert(nnames >= 2);
|
Assert(nnames >= 2);
|
||||||
relname = ltruncate(nnames - 1, listCopy(qualname));
|
relname = ltruncate(nnames - 1, listCopy(qualname));
|
||||||
rulename = strVal(nth(nnames - 1, qualname));
|
rulename = strVal(llast(qualname));
|
||||||
|
|
||||||
/* Open the owning relation to ensure it won't go away meanwhile */
|
/* Open the owning relation to ensure it won't go away meanwhile */
|
||||||
rel = makeRangeVarFromNameList(relname);
|
rel = makeRangeVarFromNameList(relname);
|
||||||
@ -778,7 +778,7 @@ CommentTrigger(List *qualname, char *comment)
|
|||||||
if (nnames < 2) /* parser messed up */
|
if (nnames < 2) /* parser messed up */
|
||||||
elog(ERROR, "must specify relation and trigger");
|
elog(ERROR, "must specify relation and trigger");
|
||||||
relname = ltruncate(nnames - 1, listCopy(qualname));
|
relname = ltruncate(nnames - 1, listCopy(qualname));
|
||||||
trigname = strVal(nth(nnames - 1, qualname));
|
trigname = strVal(llast(qualname));
|
||||||
|
|
||||||
/* Open the owning relation to ensure it won't go away meanwhile */
|
/* Open the owning relation to ensure it won't go away meanwhile */
|
||||||
rel = makeRangeVarFromNameList(relname);
|
rel = makeRangeVarFromNameList(relname);
|
||||||
@ -856,7 +856,7 @@ CommentConstraint(List *qualname, char *comment)
|
|||||||
if (nnames < 2) /* parser messed up */
|
if (nnames < 2) /* parser messed up */
|
||||||
elog(ERROR, "must specify relation and constraint");
|
elog(ERROR, "must specify relation and constraint");
|
||||||
relName = ltruncate(nnames - 1, listCopy(qualname));
|
relName = ltruncate(nnames - 1, listCopy(qualname));
|
||||||
conName = strVal(nth(nnames - 1, qualname));
|
conName = strVal(llast(qualname));
|
||||||
|
|
||||||
/* Open the owning relation to ensure it won't go away meanwhile */
|
/* Open the owning relation to ensure it won't go away meanwhile */
|
||||||
rel = makeRangeVarFromNameList(relName);
|
rel = makeRangeVarFromNameList(relName);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1994-5, Regents of the University of California
|
* Portions Copyright (c) 1994-5, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.114 2003/08/08 21:41:30 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.115 2003/08/11 20:46:46 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -947,7 +947,6 @@ show_sort_keys(List *tlist, int nkeys, AttrNumber *keycols,
|
|||||||
List *context;
|
List *context;
|
||||||
bool useprefix;
|
bool useprefix;
|
||||||
int keyno;
|
int keyno;
|
||||||
List *tl;
|
|
||||||
char *exprstr;
|
char *exprstr;
|
||||||
Relids varnos;
|
Relids varnos;
|
||||||
int i;
|
int i;
|
||||||
@ -993,25 +992,17 @@ show_sort_keys(List *tlist, int nkeys, AttrNumber *keycols,
|
|||||||
{
|
{
|
||||||
/* find key expression in tlist */
|
/* find key expression in tlist */
|
||||||
AttrNumber keyresno = keycols[keyno];
|
AttrNumber keyresno = keycols[keyno];
|
||||||
|
TargetEntry *target = get_tle_by_resno(tlist, keyresno);
|
||||||
|
|
||||||
foreach(tl, tlist)
|
if (!target)
|
||||||
{
|
|
||||||
TargetEntry *target = (TargetEntry *) lfirst(tl);
|
|
||||||
|
|
||||||
if (target->resdom->resno == keyresno)
|
|
||||||
{
|
|
||||||
/* Deparse the expression, showing any top-level cast */
|
|
||||||
exprstr = deparse_expression((Node *) target->expr, context,
|
|
||||||
useprefix, true);
|
|
||||||
/* And add to str */
|
|
||||||
if (keyno > 0)
|
|
||||||
appendStringInfo(str, ", ");
|
|
||||||
appendStringInfo(str, "%s", exprstr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tl == NIL)
|
|
||||||
elog(ERROR, "no tlist entry for key %d", keyresno);
|
elog(ERROR, "no tlist entry for key %d", keyresno);
|
||||||
|
/* Deparse the expression, showing any top-level cast */
|
||||||
|
exprstr = deparse_expression((Node *) target->expr, context,
|
||||||
|
useprefix, true);
|
||||||
|
/* And add to str */
|
||||||
|
if (keyno > 0)
|
||||||
|
appendStringInfo(str, ", ");
|
||||||
|
appendStringInfo(str, "%s", exprstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
appendStringInfo(str, "\n");
|
appendStringInfo(str, "\n");
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/execJunk.c,v 1.35 2003/08/04 02:39:58 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/execJunk.c,v 1.36 2003/08/11 20:46:46 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -185,10 +185,7 @@ ExecGetJunkAttribute(JunkFilter *junkfilter,
|
|||||||
{
|
{
|
||||||
List *targetList;
|
List *targetList;
|
||||||
List *t;
|
List *t;
|
||||||
Resdom *resdom;
|
|
||||||
AttrNumber resno;
|
AttrNumber resno;
|
||||||
char *resname;
|
|
||||||
bool resjunk;
|
|
||||||
TupleDesc tupType;
|
TupleDesc tupType;
|
||||||
HeapTuple tuple;
|
HeapTuple tuple;
|
||||||
|
|
||||||
@ -202,11 +199,10 @@ ExecGetJunkAttribute(JunkFilter *junkfilter,
|
|||||||
foreach(t, targetList)
|
foreach(t, targetList)
|
||||||
{
|
{
|
||||||
TargetEntry *tle = lfirst(t);
|
TargetEntry *tle = lfirst(t);
|
||||||
|
Resdom *resdom = tle->resdom;
|
||||||
|
|
||||||
resdom = tle->resdom;
|
if (resdom->resjunk && resdom->resname &&
|
||||||
resname = resdom->resname;
|
(strcmp(resdom->resname, attrName) == 0))
|
||||||
resjunk = resdom->resjunk;
|
|
||||||
if (resjunk && (strcmp(resname, attrName) == 0))
|
|
||||||
{
|
{
|
||||||
/* We found it ! */
|
/* We found it ! */
|
||||||
resno = resdom->resno;
|
resno = resdom->resno;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.106 2003/08/04 02:40:00 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.107 2003/08/11 20:46:46 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -726,8 +726,7 @@ qual_is_pushdown_safe(Query *subquery, Index rti, Node *qual,
|
|||||||
foreach(vl, vars)
|
foreach(vl, vars)
|
||||||
{
|
{
|
||||||
Var *var = (Var *) lfirst(vl);
|
Var *var = (Var *) lfirst(vl);
|
||||||
List *tl;
|
TargetEntry *tle;
|
||||||
TargetEntry *tle = NULL;
|
|
||||||
|
|
||||||
Assert(var->varno == rti);
|
Assert(var->varno == rti);
|
||||||
|
|
||||||
@ -748,13 +747,8 @@ qual_is_pushdown_safe(Query *subquery, Index rti, Node *qual,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Must find the tlist element referenced by the Var */
|
/* Must find the tlist element referenced by the Var */
|
||||||
foreach(tl, subquery->targetList)
|
tle = get_tle_by_resno(subquery->targetList, var->varattno);
|
||||||
{
|
Assert(tle != NULL);
|
||||||
tle = (TargetEntry *) lfirst(tl);
|
|
||||||
if (tle->resdom->resno == var->varattno)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Assert(tl != NIL);
|
|
||||||
Assert(!tle->resdom->resjunk);
|
Assert(!tle->resdom->resjunk);
|
||||||
|
|
||||||
/* If subquery uses DISTINCT or DISTINCT ON, check point 3 */
|
/* If subquery uses DISTINCT or DISTINCT ON, check point 3 */
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.153 2003/08/08 21:41:48 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.154 2003/08/11 20:46:46 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -28,6 +28,7 @@
|
|||||||
#include "optimizer/restrictinfo.h"
|
#include "optimizer/restrictinfo.h"
|
||||||
#include "optimizer/tlist.h"
|
#include "optimizer/tlist.h"
|
||||||
#include "optimizer/var.h"
|
#include "optimizer/var.h"
|
||||||
|
#include "parser/parsetree.h"
|
||||||
#include "parser/parse_clause.h"
|
#include "parser/parse_clause.h"
|
||||||
#include "parser/parse_expr.h"
|
#include "parser/parse_expr.h"
|
||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
@ -626,8 +627,8 @@ create_unique_plan(Query *root, UniquePath *best_path)
|
|||||||
{
|
{
|
||||||
TargetEntry *tle;
|
TargetEntry *tle;
|
||||||
|
|
||||||
tle = nth(groupColIdx[groupColPos] - 1, my_tlist);
|
tle = get_tle_by_resno(my_tlist, groupColIdx[groupColPos]);
|
||||||
Assert(tle->resdom->resno == groupColIdx[groupColPos]);
|
Assert(tle != NULL);
|
||||||
sortList = addTargetToSortList(NULL, tle, sortList,
|
sortList = addTargetToSortList(NULL, tle, sortList,
|
||||||
my_tlist, NIL, false);
|
my_tlist, NIL, false);
|
||||||
}
|
}
|
||||||
@ -1975,7 +1976,7 @@ make_sort_from_groupcols(Query *root,
|
|||||||
foreach(i, groupcls)
|
foreach(i, groupcls)
|
||||||
{
|
{
|
||||||
GroupClause *grpcl = (GroupClause *) lfirst(i);
|
GroupClause *grpcl = (GroupClause *) lfirst(i);
|
||||||
TargetEntry *tle = nth(grpColIdx[grpno] - 1, sub_tlist);
|
TargetEntry *tle = get_tle_by_resno(sub_tlist, grpColIdx[grpno]);
|
||||||
Resdom *resdom = tle->resdom;
|
Resdom *resdom = tle->resdom;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.87 2003/08/04 02:40:02 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.88 2003/08/11 20:46:46 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1599,21 +1599,14 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
|
|||||||
case RTE_SUBQUERY:
|
case RTE_SUBQUERY:
|
||||||
{
|
{
|
||||||
/* Subselect RTE --- get type info from subselect's tlist */
|
/* Subselect RTE --- get type info from subselect's tlist */
|
||||||
List *tlistitem;
|
TargetEntry *te = get_tle_by_resno(rte->subquery->targetList,
|
||||||
|
attnum);
|
||||||
|
|
||||||
foreach(tlistitem, rte->subquery->targetList)
|
if (te == NULL || te->resdom->resjunk)
|
||||||
{
|
elog(ERROR, "subquery %s does not have attribute %d",
|
||||||
TargetEntry *te = (TargetEntry *) lfirst(tlistitem);
|
rte->eref->aliasname, attnum);
|
||||||
|
*vartype = te->resdom->restype;
|
||||||
if (te->resdom->resjunk || te->resdom->resno != attnum)
|
*vartypmod = te->resdom->restypmod;
|
||||||
continue;
|
|
||||||
*vartype = te->resdom->restype;
|
|
||||||
*vartypmod = te->resdom->restypmod;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* falling off end of list shouldn't happen... */
|
|
||||||
elog(ERROR, "subquery %s does not have attribute %d",
|
|
||||||
rte->eref->aliasname, attnum);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RTE_FUNCTION:
|
case RTE_FUNCTION:
|
||||||
@ -1777,6 +1770,29 @@ get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a targetlist and a resno, return the matching TargetEntry
|
||||||
|
*
|
||||||
|
* Returns NULL if resno is not present in list.
|
||||||
|
*
|
||||||
|
* Note: we need to search, rather than just indexing with nth(), because
|
||||||
|
* not all tlists are sorted by resno.
|
||||||
|
*/
|
||||||
|
TargetEntry *
|
||||||
|
get_tle_by_resno(List *tlist, AttrNumber resno)
|
||||||
|
{
|
||||||
|
List *i;
|
||||||
|
|
||||||
|
foreach(i, tlist)
|
||||||
|
{
|
||||||
|
TargetEntry *tle = (TargetEntry *) lfirst(i);
|
||||||
|
|
||||||
|
if (tle->resdom->resno == resno)
|
||||||
|
return tle;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* given relation and att name, return id of variable
|
* given relation and att name, return id of variable
|
||||||
*
|
*
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.110 2003/08/04 02:40:02 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.111 2003/08/11 20:46:46 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -100,49 +100,55 @@ transformTargetEntry(ParseState *pstate,
|
|||||||
List *
|
List *
|
||||||
transformTargetList(ParseState *pstate, List *targetlist)
|
transformTargetList(ParseState *pstate, List *targetlist)
|
||||||
{
|
{
|
||||||
List *p_target = NIL;
|
FastList p_target;
|
||||||
|
List *o_target;
|
||||||
|
|
||||||
while (targetlist != NIL)
|
FastListInit(&p_target);
|
||||||
|
|
||||||
|
foreach(o_target, targetlist)
|
||||||
{
|
{
|
||||||
ResTarget *res = (ResTarget *) lfirst(targetlist);
|
ResTarget *res = (ResTarget *) lfirst(o_target);
|
||||||
|
|
||||||
if (IsA(res->val, ColumnRef))
|
if (IsA(res->val, ColumnRef))
|
||||||
{
|
{
|
||||||
ColumnRef *cref = (ColumnRef *) res->val;
|
ColumnRef *cref = (ColumnRef *) res->val;
|
||||||
List *fields = cref->fields;
|
List *fields = cref->fields;
|
||||||
int numnames = length(fields);
|
|
||||||
|
|
||||||
if (numnames == 1 && strcmp(strVal(lfirst(fields)), "*") == 0)
|
if (strcmp(strVal(llast(fields)), "*") == 0)
|
||||||
{
|
{
|
||||||
/*
|
int numnames = length(fields);
|
||||||
* Target item is a single '*', expand all tables (eg.
|
|
||||||
* SELECT * FROM emp)
|
|
||||||
*/
|
|
||||||
p_target = nconc(p_target,
|
|
||||||
ExpandAllTables(pstate));
|
|
||||||
}
|
|
||||||
else if (strcmp(strVal(nth(numnames - 1, fields)), "*") == 0)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Target item is relation.*, expand that table (eg.
|
|
||||||
* SELECT emp.*, dname FROM emp, dept)
|
|
||||||
*/
|
|
||||||
char *schemaname;
|
|
||||||
char *relname;
|
|
||||||
RangeTblEntry *rte;
|
|
||||||
int sublevels_up;
|
|
||||||
|
|
||||||
switch (numnames)
|
if (numnames == 1)
|
||||||
{
|
{
|
||||||
case 2:
|
/*
|
||||||
schemaname = NULL;
|
* Target item is a single '*', expand all tables
|
||||||
relname = strVal(lfirst(fields));
|
* (e.g., SELECT * FROM emp)
|
||||||
break;
|
*/
|
||||||
case 3:
|
FastConc(&p_target,
|
||||||
schemaname = strVal(lfirst(fields));
|
ExpandAllTables(pstate));
|
||||||
relname = strVal(lsecond(fields));
|
}
|
||||||
break;
|
else
|
||||||
case 4:
|
{
|
||||||
|
/*
|
||||||
|
* Target item is relation.*, expand that table
|
||||||
|
* (e.g., SELECT emp.*, dname FROM emp, dept)
|
||||||
|
*/
|
||||||
|
char *schemaname;
|
||||||
|
char *relname;
|
||||||
|
RangeTblEntry *rte;
|
||||||
|
int sublevels_up;
|
||||||
|
|
||||||
|
switch (numnames)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
schemaname = NULL;
|
||||||
|
relname = strVal(lfirst(fields));
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
schemaname = strVal(lfirst(fields));
|
||||||
|
relname = strVal(lsecond(fields));
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
{
|
{
|
||||||
char *name1 = strVal(lfirst(fields));
|
char *name1 = strVal(lfirst(fields));
|
||||||
|
|
||||||
@ -152,57 +158,56 @@ transformTargetList(ParseState *pstate, List *targetlist)
|
|||||||
*/
|
*/
|
||||||
if (strcmp(name1, get_database_name(MyDatabaseId)) != 0)
|
if (strcmp(name1, get_database_name(MyDatabaseId)) != 0)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("cross-database references are not implemented")));
|
errmsg("cross-database references are not implemented")));
|
||||||
schemaname = strVal(lsecond(fields));
|
schemaname = strVal(lsecond(fields));
|
||||||
relname = strVal(lthird(fields));
|
relname = strVal(lthird(fields));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||||
errmsg("improper qualified name (too many dotted names): %s",
|
errmsg("improper qualified name (too many dotted names): %s",
|
||||||
NameListToString(fields))));
|
NameListToString(fields))));
|
||||||
schemaname = NULL; /* keep compiler quiet */
|
schemaname = NULL; /* keep compiler quiet */
|
||||||
relname = NULL;
|
relname = NULL;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rte = refnameRangeTblEntry(pstate, schemaname, relname,
|
||||||
|
&sublevels_up);
|
||||||
|
if (rte == NULL)
|
||||||
|
rte = addImplicitRTE(pstate, makeRangeVar(schemaname,
|
||||||
|
relname));
|
||||||
|
|
||||||
|
FastConc(&p_target,
|
||||||
|
expandRelAttrs(pstate, rte));
|
||||||
}
|
}
|
||||||
|
|
||||||
rte = refnameRangeTblEntry(pstate, schemaname, relname,
|
|
||||||
&sublevels_up);
|
|
||||||
if (rte == NULL)
|
|
||||||
rte = addImplicitRTE(pstate, makeRangeVar(schemaname,
|
|
||||||
relname));
|
|
||||||
|
|
||||||
p_target = nconc(p_target,
|
|
||||||
expandRelAttrs(pstate, rte));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Plain ColumnRef node, treat it as an expression */
|
/* Plain ColumnRef node, treat it as an expression */
|
||||||
p_target = lappend(p_target,
|
FastAppend(&p_target,
|
||||||
transformTargetEntry(pstate,
|
transformTargetEntry(pstate,
|
||||||
res->val,
|
res->val,
|
||||||
NULL,
|
NULL,
|
||||||
res->name,
|
res->name,
|
||||||
false));
|
false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Everything else but ColumnRef */
|
/* Everything else but ColumnRef */
|
||||||
p_target = lappend(p_target,
|
FastAppend(&p_target,
|
||||||
transformTargetEntry(pstate,
|
transformTargetEntry(pstate,
|
||||||
res->val,
|
res->val,
|
||||||
NULL,
|
NULL,
|
||||||
res->name,
|
res->name,
|
||||||
false));
|
false));
|
||||||
}
|
}
|
||||||
|
|
||||||
targetlist = lnext(targetlist);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return p_target;
|
return FastListValue(&p_target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -264,23 +269,14 @@ markTargetListOrigin(ParseState *pstate, Resdom *res, Var *var)
|
|||||||
case RTE_SUBQUERY:
|
case RTE_SUBQUERY:
|
||||||
{
|
{
|
||||||
/* Subselect-in-FROM: copy up from the subselect */
|
/* Subselect-in-FROM: copy up from the subselect */
|
||||||
List *subtl;
|
TargetEntry *te = get_tle_by_resno(rte->subquery->targetList,
|
||||||
|
attnum);
|
||||||
|
|
||||||
foreach(subtl, rte->subquery->targetList)
|
if (te == NULL || te->resdom->resjunk)
|
||||||
{
|
|
||||||
TargetEntry *subte = (TargetEntry *) lfirst(subtl);
|
|
||||||
|
|
||||||
if (subte->resdom->resjunk ||
|
|
||||||
subte->resdom->resno != attnum)
|
|
||||||
continue;
|
|
||||||
res->resorigtbl = subte->resdom->resorigtbl;
|
|
||||||
res->resorigcol = subte->resdom->resorigcol;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* falling off end of list shouldn't happen... */
|
|
||||||
if (subtl == NIL)
|
|
||||||
elog(ERROR, "subquery %s does not have attribute %d",
|
elog(ERROR, "subquery %s does not have attribute %d",
|
||||||
rte->eref->aliasname, attnum);
|
rte->eref->aliasname, attnum);
|
||||||
|
res->resorigtbl = te->resdom->resorigtbl;
|
||||||
|
res->resorigcol = te->resdom->resorigcol;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RTE_JOIN:
|
case RTE_JOIN:
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.77 2003/08/08 21:41:58 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.78 2003/08/11 20:46:46 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -838,44 +838,6 @@ AddInvertedQual(Query *parsetree, Node *qual)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Find a targetlist entry by resno */
|
|
||||||
static Node *
|
|
||||||
FindMatchingNew(List *tlist, int attno)
|
|
||||||
{
|
|
||||||
List *i;
|
|
||||||
|
|
||||||
foreach(i, tlist)
|
|
||||||
{
|
|
||||||
TargetEntry *tle = lfirst(i);
|
|
||||||
|
|
||||||
if (tle->resdom->resno == attno)
|
|
||||||
return (Node *) tle->expr;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef NOT_USED
|
|
||||||
|
|
||||||
/* Find a targetlist entry by resname */
|
|
||||||
static Node *
|
|
||||||
FindMatchingTLEntry(List *tlist, char *e_attname)
|
|
||||||
{
|
|
||||||
List *i;
|
|
||||||
|
|
||||||
foreach(i, tlist)
|
|
||||||
{
|
|
||||||
TargetEntry *tle = lfirst(i);
|
|
||||||
char *resname;
|
|
||||||
|
|
||||||
resname = tle->resdom->resname;
|
|
||||||
if (strcmp(e_attname, resname) == 0)
|
|
||||||
return tle->expr;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ResolveNew - replace Vars with corresponding items from a targetlist
|
* ResolveNew - replace Vars with corresponding items from a targetlist
|
||||||
*
|
*
|
||||||
@ -908,7 +870,7 @@ ResolveNew_mutator(Node *node, ResolveNew_context *context)
|
|||||||
if (this_varno == context->target_varno &&
|
if (this_varno == context->target_varno &&
|
||||||
this_varlevelsup == context->sublevels_up)
|
this_varlevelsup == context->sublevels_up)
|
||||||
{
|
{
|
||||||
Node *n;
|
TargetEntry *tle;
|
||||||
|
|
||||||
/* band-aid: don't do the wrong thing with a whole-tuple Var */
|
/* band-aid: don't do the wrong thing with a whole-tuple Var */
|
||||||
if (var->varattno == InvalidAttrNumber)
|
if (var->varattno == InvalidAttrNumber)
|
||||||
@ -916,9 +878,9 @@ ResolveNew_mutator(Node *node, ResolveNew_context *context)
|
|||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("cannot handle whole-tuple reference")));
|
errmsg("cannot handle whole-tuple reference")));
|
||||||
|
|
||||||
n = FindMatchingNew(context->targetlist, var->varattno);
|
tle = get_tle_by_resno(context->targetlist, var->varattno);
|
||||||
|
|
||||||
if (n == NULL)
|
if (tle == NULL)
|
||||||
{
|
{
|
||||||
if (context->event == CMD_UPDATE)
|
if (context->event == CMD_UPDATE)
|
||||||
{
|
{
|
||||||
@ -937,7 +899,8 @@ ResolveNew_mutator(Node *node, ResolveNew_context *context)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Make a copy of the tlist item to return */
|
/* Make a copy of the tlist item to return */
|
||||||
n = copyObject(n);
|
Node *n = copyObject(tle->expr);
|
||||||
|
|
||||||
/* Adjust varlevelsup if tlist item is from higher query */
|
/* Adjust varlevelsup if tlist item is from higher query */
|
||||||
if (this_varlevelsup > 0)
|
if (this_varlevelsup > 0)
|
||||||
IncrementVarSublevelsUp(n, this_varlevelsup, 0);
|
IncrementVarSublevelsUp(n, this_varlevelsup, 0);
|
||||||
@ -985,124 +948,3 @@ ResolveNew(Node *node, int target_varno, int sublevels_up,
|
|||||||
(void *) &context,
|
(void *) &context,
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef NOT_USED
|
|
||||||
|
|
||||||
/*
|
|
||||||
* HandleRIRAttributeRule
|
|
||||||
* Replace Vars matching a given RT index with copies of TL expressions.
|
|
||||||
*
|
|
||||||
* Handles 'on retrieve to relation.attribute
|
|
||||||
* do instead retrieve (attribute = expression) w/qual'
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
List *rtable;
|
|
||||||
List *targetlist;
|
|
||||||
int rt_index;
|
|
||||||
int attr_num;
|
|
||||||
int *modified;
|
|
||||||
int *badsql;
|
|
||||||
int sublevels_up;
|
|
||||||
} HandleRIRAttributeRule_context;
|
|
||||||
|
|
||||||
static Node *
|
|
||||||
HandleRIRAttributeRule_mutator(Node *node,
|
|
||||||
HandleRIRAttributeRule_context * context)
|
|
||||||
{
|
|
||||||
if (node == NULL)
|
|
||||||
return NULL;
|
|
||||||
if (IsA(node, Var))
|
|
||||||
{
|
|
||||||
Var *var = (Var *) node;
|
|
||||||
int this_varno = var->varno;
|
|
||||||
int this_varattno = var->varattno;
|
|
||||||
int this_varlevelsup = var->varlevelsup;
|
|
||||||
|
|
||||||
if (this_varno == context->rt_index &&
|
|
||||||
this_varattno == context->attr_num &&
|
|
||||||
this_varlevelsup == context->sublevels_up)
|
|
||||||
{
|
|
||||||
if (var->vartype == 32)
|
|
||||||
{ /* HACK: disallow SET variables */
|
|
||||||
*context->modified = TRUE;
|
|
||||||
*context->badsql = TRUE;
|
|
||||||
return (Node *) makeNullConst(var->vartype);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char *name_to_look_for;
|
|
||||||
|
|
||||||
name_to_look_for = get_attname(getrelid(this_varno,
|
|
||||||
context->rtable),
|
|
||||||
this_varattno);
|
|
||||||
if (name_to_look_for)
|
|
||||||
{
|
|
||||||
Node *n;
|
|
||||||
|
|
||||||
*context->modified = TRUE;
|
|
||||||
n = FindMatchingTLEntry(context->targetlist,
|
|
||||||
name_to_look_for);
|
|
||||||
if (n == NULL)
|
|
||||||
return (Node *) makeNullConst(var->vartype);
|
|
||||||
/* Make a copy of the tlist item to return */
|
|
||||||
n = copyObject(n);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Adjust varlevelsup if tlist item is from higher
|
|
||||||
* query
|
|
||||||
*/
|
|
||||||
if (this_varlevelsup > 0)
|
|
||||||
IncrementVarSublevelsUp(n, this_varlevelsup, 0);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* otherwise fall through to copy the var normally */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsA(node, Query))
|
|
||||||
{
|
|
||||||
/* Recurse into RTE subquery or not-yet-planned sublink subquery */
|
|
||||||
Query *newnode;
|
|
||||||
|
|
||||||
context->sublevels_up++;
|
|
||||||
newnode = query_tree_mutator((Query *) node,
|
|
||||||
HandleRIRAttributeRule_mutator,
|
|
||||||
(void *) context,
|
|
||||||
0);
|
|
||||||
context->sublevels_up--;
|
|
||||||
return (Node *) newnode;
|
|
||||||
}
|
|
||||||
return expression_tree_mutator(node, HandleRIRAttributeRule_mutator,
|
|
||||||
(void *) context);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
HandleRIRAttributeRule(Query *parsetree,
|
|
||||||
List *rtable,
|
|
||||||
List *targetlist,
|
|
||||||
int rt_index,
|
|
||||||
int attr_num,
|
|
||||||
int *modified,
|
|
||||||
int *badsql)
|
|
||||||
{
|
|
||||||
HandleRIRAttributeRule_context context;
|
|
||||||
|
|
||||||
context.rtable = rtable;
|
|
||||||
context.targetlist = targetlist;
|
|
||||||
context.rt_index = rt_index;
|
|
||||||
context.attr_num = attr_num;
|
|
||||||
context.modified = modified;
|
|
||||||
context.badsql = badsql;
|
|
||||||
context.sublevels_up = 0;
|
|
||||||
|
|
||||||
query_tree_mutator(parsetree,
|
|
||||||
HandleRIRAttributeRule_mutator,
|
|
||||||
(void *) &context,
|
|
||||||
QTW_DONT_COPY_QUERY);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* NOT_USED */
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/not_in.c,v 1.35 2003/08/04 02:40:05 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/not_in.c,v 1.36 2003/08/11 20:46:46 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -63,7 +63,7 @@ int4notin(PG_FUNCTION_ARGS)
|
|||||||
(errcode(ERRCODE_INVALID_NAME),
|
(errcode(ERRCODE_INVALID_NAME),
|
||||||
errmsg("invalid name syntax"),
|
errmsg("invalid name syntax"),
|
||||||
errhint("Must provide \"relationname.attributename\".")));
|
errhint("Must provide \"relationname.attributename\".")));
|
||||||
attribute = strVal(nth(nnames - 1, names));
|
attribute = strVal(llast(names));
|
||||||
names = ltruncate(nnames - 1, names);
|
names = ltruncate(nnames - 1, names);
|
||||||
relrv = makeRangeVarFromNameList(names);
|
relrv = makeRangeVarFromNameList(names);
|
||||||
|
|
||||||
|
@ -8,14 +8,13 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/tid.c,v 1.39 2003/08/04 02:40:05 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/tid.c,v 1.40 2003/08/11 20:46:46 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* input routine largely stolen from boxin().
|
* input routine largely stolen from boxin().
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -26,6 +25,7 @@
|
|||||||
#include "catalog/namespace.h"
|
#include "catalog/namespace.h"
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
#include "libpq/pqformat.h"
|
#include "libpq/pqformat.h"
|
||||||
|
#include "parser/parsetree.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
|
|
||||||
|
|
||||||
@ -223,6 +223,7 @@ currtid_for_view(Relation viewrel, ItemPointer tid)
|
|||||||
if (att->attrs[i]->atttypid != TIDOID)
|
if (att->attrs[i]->atttypid != TIDOID)
|
||||||
elog(ERROR, "ctid isn't of type TID");
|
elog(ERROR, "ctid isn't of type TID");
|
||||||
tididx = i;
|
tididx = i;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tididx < 0)
|
if (tididx < 0)
|
||||||
@ -241,7 +242,7 @@ currtid_for_view(Relation viewrel, ItemPointer tid)
|
|||||||
if (length(rewrite->actions) != 1)
|
if (length(rewrite->actions) != 1)
|
||||||
elog(ERROR, "only one select rule is allowed in views");
|
elog(ERROR, "only one select rule is allowed in views");
|
||||||
query = (Query *) lfirst(rewrite->actions);
|
query = (Query *) lfirst(rewrite->actions);
|
||||||
tle = (TargetEntry *) nth(tididx, query->targetList);
|
tle = get_tle_by_resno(query->targetList, tididx+1);
|
||||||
if (tle && tle->expr && IsA(tle->expr, Var))
|
if (tle && tle->expr && IsA(tle->expr, Var))
|
||||||
{
|
{
|
||||||
Var *var = (Var *) tle->expr;
|
Var *var = (Var *) tle->expr;
|
||||||
@ -250,7 +251,7 @@ currtid_for_view(Relation viewrel, ItemPointer tid)
|
|||||||
if (var->varno > 0 && var->varno < INNER &&
|
if (var->varno > 0 && var->varno < INNER &&
|
||||||
var->varattno == SelfItemPointerAttributeNumber)
|
var->varattno == SelfItemPointerAttributeNumber)
|
||||||
{
|
{
|
||||||
rte = (RangeTblEntry *) nth(var->varno - 1, query->rtable);
|
rte = rt_fetch(var->varno, query->rtable);
|
||||||
if (rte)
|
if (rte)
|
||||||
{
|
{
|
||||||
heap_close(viewrel, AccessShareLock);
|
heap_close(viewrel, AccessShareLock);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: parsetree.h,v 1.21 2003/08/04 02:40:14 momjian Exp $
|
* $Id: parsetree.h,v 1.22 2003/08/11 20:46:47 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* range table macros
|
* range table operations
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -55,4 +55,12 @@ extern char *get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum);
|
|||||||
extern void get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
|
extern void get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
|
||||||
Oid *vartype, int32 *vartypmod);
|
Oid *vartype, int32 *vartypmod);
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------------
|
||||||
|
* target list operations
|
||||||
|
* ----------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern TargetEntry *get_tle_by_resno(List *tlist, AttrNumber resno);
|
||||||
|
|
||||||
#endif /* PARSETREE_H */
|
#endif /* PARSETREE_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user