*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
}
/* find the final query */
- parse = (Query *) nth(length(queryTreeList) - 1, queryTreeList);
+ parse = (Query *) llast(queryTreeList);
cmd = parse->commandType;
tlist = parse->targetList;
* Copyright (c) 1996-2003, PostgreSQL Global Development Group
*
* 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 $
*
*-------------------------------------------------------------------------
*/
if (nnames < 2) /* parser messed up */
elog(ERROR, "must specify relation and attribute");
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 */
rel = makeRangeVarFromNameList(relname);
/* New-style: rule and relname both provided */
Assert(nnames >= 2);
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 */
rel = makeRangeVarFromNameList(relname);
if (nnames < 2) /* parser messed up */
elog(ERROR, "must specify relation and trigger");
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 */
rel = makeRangeVarFromNameList(relname);
if (nnames < 2) /* parser messed up */
elog(ERROR, "must specify relation and constraint");
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 */
rel = makeRangeVarFromNameList(relName);
* Portions Copyright (c) 1994-5, Regents of the University of California
*
* 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 $
*
*-------------------------------------------------------------------------
*/
List *context;
bool useprefix;
int keyno;
- List *tl;
char *exprstr;
Relids varnos;
int i;
{
/* find key expression in tlist */
AttrNumber keyresno = keycols[keyno];
+ TargetEntry *target = get_tle_by_resno(tlist, keyresno);
- foreach(tl, tlist)
- {
- 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)
+ if (!target)
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");
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
{
List *targetList;
List *t;
- Resdom *resdom;
AttrNumber resno;
- char *resname;
- bool resjunk;
TupleDesc tupType;
HeapTuple tuple;
foreach(t, targetList)
{
TargetEntry *tle = lfirst(t);
+ Resdom *resdom = tle->resdom;
- resdom = tle->resdom;
- resname = resdom->resname;
- resjunk = resdom->resjunk;
- if (resjunk && (strcmp(resname, attrName) == 0))
+ if (resdom->resjunk && resdom->resname &&
+ (strcmp(resdom->resname, attrName) == 0))
{
/* We found it ! */
resno = resdom->resno;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
foreach(vl, vars)
{
Var *var = (Var *) lfirst(vl);
- List *tl;
- TargetEntry *tle = NULL;
+ TargetEntry *tle;
Assert(var->varno == rti);
}
/* Must find the tlist element referenced by the Var */
- foreach(tl, subquery->targetList)
- {
- tle = (TargetEntry *) lfirst(tl);
- if (tle->resdom->resno == var->varattno)
- break;
- }
- Assert(tl != NIL);
+ tle = get_tle_by_resno(subquery->targetList, var->varattno);
+ Assert(tle != NULL);
Assert(!tle->resdom->resjunk);
/* If subquery uses DISTINCT or DISTINCT ON, check point 3 */
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#include "optimizer/restrictinfo.h"
#include "optimizer/tlist.h"
#include "optimizer/var.h"
+#include "parser/parsetree.h"
#include "parser/parse_clause.h"
#include "parser/parse_expr.h"
#include "utils/lsyscache.h"
{
TargetEntry *tle;
- tle = nth(groupColIdx[groupColPos] - 1, my_tlist);
- Assert(tle->resdom->resno == groupColIdx[groupColPos]);
+ tle = get_tle_by_resno(my_tlist, groupColIdx[groupColPos]);
+ Assert(tle != NULL);
sortList = addTargetToSortList(NULL, tle, sortList,
my_tlist, NIL, false);
}
foreach(i, groupcls)
{
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;
/*
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
case RTE_SUBQUERY:
{
/* Subselect RTE --- get type info from subselect's tlist */
- List *tlistitem;
-
- foreach(tlistitem, rte->subquery->targetList)
- {
- TargetEntry *te = (TargetEntry *) lfirst(tlistitem);
-
- if (te->resdom->resjunk || te->resdom->resno != attnum)
- 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);
+ TargetEntry *te = get_tle_by_resno(rte->subquery->targetList,
+ attnum);
+
+ if (te == NULL || te->resdom->resjunk)
+ elog(ERROR, "subquery %s does not have attribute %d",
+ rte->eref->aliasname, attnum);
+ *vartype = te->resdom->restype;
+ *vartypmod = te->resdom->restypmod;
}
break;
case RTE_FUNCTION:
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
*
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
List *
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))
{
ColumnRef *cref = (ColumnRef *) res->val;
List *fields = cref->fields;
- int numnames = length(fields);
- if (numnames == 1 && strcmp(strVal(lfirst(fields)), "*") == 0)
- {
- /*
- * 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)
+ if (strcmp(strVal(llast(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)
+ int numnames = length(fields);
+
+ if (numnames == 1)
{
- case 2:
- schemaname = NULL;
- relname = strVal(lfirst(fields));
- break;
- case 3:
- schemaname = strVal(lfirst(fields));
- relname = strVal(lsecond(fields));
- break;
- case 4:
+ /*
+ * Target item is a single '*', expand all tables
+ * (e.g., SELECT * FROM emp)
+ */
+ FastConc(&p_target,
+ ExpandAllTables(pstate));
+ }
+ else
+ {
+ /*
+ * 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));
*/
if (strcmp(name1, get_database_name(MyDatabaseId)) != 0)
ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("cross-database references are not implemented")));
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cross-database references are not implemented")));
schemaname = strVal(lsecond(fields));
relname = strVal(lthird(fields));
break;
}
- default:
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("improper qualified name (too many dotted names): %s",
- NameListToString(fields))));
- schemaname = NULL; /* keep compiler quiet */
- relname = NULL;
- break;
- }
+ default:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("improper qualified name (too many dotted names): %s",
+ NameListToString(fields))));
+ schemaname = NULL; /* keep compiler quiet */
+ relname = NULL;
+ break;
+ }
- rte = refnameRangeTblEntry(pstate, schemaname, relname,
- &sublevels_up);
- if (rte == NULL)
- rte = addImplicitRTE(pstate, makeRangeVar(schemaname,
- relname));
+ rte = refnameRangeTblEntry(pstate, schemaname, relname,
+ &sublevels_up);
+ if (rte == NULL)
+ rte = addImplicitRTE(pstate, makeRangeVar(schemaname,
+ relname));
- p_target = nconc(p_target,
- expandRelAttrs(pstate, rte));
+ FastConc(&p_target,
+ expandRelAttrs(pstate, rte));
+ }
}
else
{
/* Plain ColumnRef node, treat it as an expression */
- p_target = lappend(p_target,
- transformTargetEntry(pstate,
- res->val,
- NULL,
- res->name,
- false));
+ FastAppend(&p_target,
+ transformTargetEntry(pstate,
+ res->val,
+ NULL,
+ res->name,
+ false));
}
}
else
{
/* Everything else but ColumnRef */
- p_target = lappend(p_target,
- transformTargetEntry(pstate,
- res->val,
- NULL,
- res->name,
- false));
+ FastAppend(&p_target,
+ transformTargetEntry(pstate,
+ res->val,
+ NULL,
+ res->name,
+ false));
}
-
- targetlist = lnext(targetlist);
}
- return p_target;
+ return FastListValue(&p_target);
}
case RTE_SUBQUERY:
{
/* 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)
- {
- 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)
+ if (te == NULL || te->resdom->resjunk)
elog(ERROR, "subquery %s does not have attribute %d",
rte->eref->aliasname, attnum);
+ res->resorigtbl = te->resdom->resorigtbl;
+ res->resorigcol = te->resdom->resorigcol;
}
break;
case RTE_JOIN:
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
}
-/* 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
*
if (this_varno == context->target_varno &&
this_varlevelsup == context->sublevels_up)
{
- Node *n;
+ TargetEntry *tle;
/* band-aid: don't do the wrong thing with a whole-tuple Var */
if (var->varattno == InvalidAttrNumber)
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
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)
{
else
{
/* 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 */
if (this_varlevelsup > 0)
IncrementVarSublevelsUp(n, this_varlevelsup, 0);
(void *) &context,
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 */
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
(errcode(ERRCODE_INVALID_NAME),
errmsg("invalid name syntax"),
errhint("Must provide \"relationname.attributename\".")));
- attribute = strVal(nth(nnames - 1, names));
+ attribute = strVal(llast(names));
names = ltruncate(nnames - 1, names);
relrv = makeRangeVarFromNameList(names);
*
*
* 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
* input routine largely stolen from boxin().
*
*-------------------------------------------------------------------------
*/
-
#include "postgres.h"
#include <errno.h>
#include "catalog/namespace.h"
#include "catalog/pg_type.h"
#include "libpq/pqformat.h"
+#include "parser/parsetree.h"
#include "utils/builtins.h"
if (att->attrs[i]->atttypid != TIDOID)
elog(ERROR, "ctid isn't of type TID");
tididx = i;
+ break;
}
}
if (tididx < 0)
if (length(rewrite->actions) != 1)
elog(ERROR, "only one select rule is allowed in views");
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))
{
Var *var = (Var *) tle->expr;
if (var->varno > 0 && var->varno < INNER &&
var->varattno == SelfItemPointerAttributeNumber)
{
- rte = (RangeTblEntry *) nth(var->varno - 1, query->rtable);
+ rte = rt_fetch(var->varno, query->rtable);
if (rte)
{
heap_close(viewrel, AccessShareLock);
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* 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 $
*
*-------------------------------------------------------------------------
*/
/* ----------------
- * range table macros
+ * range table operations
* ----------------
*/
extern void get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
Oid *vartype, int32 *vartypmod);
+
+/* ----------------
+ * target list operations
+ * ----------------
+ */
+
+extern TargetEntry *get_tle_by_resno(List *tlist, AttrNumber resno);
+
#endif /* PARSETREE_H */