Commit 0fc13f58 authored by Bruce Momjian's avatar Bruce Momjian

Make sure resdomno for update/insert match attribute number for

rewrite system.  Restructure parse_target to make it easier to
understand.
parent a06ba33c
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.23 1998/08/05 04:49:09 scrappy Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.24 1998/08/25 03:17:26 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -272,14 +272,14 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause) ...@@ -272,14 +272,14 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause)
switch(nodeTag(node)) switch(nodeTag(node))
{ {
case T_Attr: case T_Attr:
target_result = transformTargetIdent(pstate, node, makeNode(TargetEntry), target_result = MakeTargetEntryIdent(pstate, node,
&((Attr*)node)->relname, NULL, &((Attr*)node)->relname, NULL,
((Attr*)node)->relname, TRUE); ((Attr*)node)->relname, TRUE);
lappend(tlist, target_result); lappend(tlist, target_result);
break; break;
case T_Ident: case T_Ident:
target_result = transformTargetIdent(pstate, node, makeNode(TargetEntry), target_result = MakeTargetEntryIdent(pstate, node,
&((Ident*)node)->name, NULL, &((Ident*)node)->name, NULL,
((Ident*)node)->name, TRUE); ((Ident*)node)->name, TRUE);
lappend(tlist, target_result); lappend(tlist, target_result);
...@@ -294,7 +294,7 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause) ...@@ -294,7 +294,7 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause)
case T_FuncCall: case T_FuncCall:
case T_A_Expr: case T_A_Expr:
target_result = MakeTargetlistExpr(pstate, "resjunk", expr, FALSE, TRUE); target_result = MakeTargetEntryExpr(pstate, "resjunk", expr, FALSE, TRUE);
lappend(tlist, target_result); lappend(tlist, target_result);
break; break;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.22 1998/08/23 14:43:46 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.23 1998/08/25 03:17:28 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -40,7 +40,7 @@ SizeTargetExpr(ParseState *pstate, ...@@ -40,7 +40,7 @@ SizeTargetExpr(ParseState *pstate,
int32 attrtypmod); int32 attrtypmod);
/* transformTargetIdent() /* MakeTargetEntryIdent()
* Transforms an Ident Node to a Target Entry * Transforms an Ident Node to a Target Entry
* Created this function to allow the ORDER/GROUP BY clause to be able * Created this function to allow the ORDER/GROUP BY clause to be able
* to construct a TargetEntry from an Ident. * to construct a TargetEntry from an Ident.
...@@ -52,13 +52,12 @@ SizeTargetExpr(ParseState *pstate, ...@@ -52,13 +52,12 @@ SizeTargetExpr(ParseState *pstate,
* - thomas 1998-06-02 * - thomas 1998-06-02
*/ */
TargetEntry * TargetEntry *
transformTargetIdent(ParseState *pstate, MakeTargetEntryIdent(ParseState *pstate,
#if FALSE #if FALSE
Ident *ident, Ident *ident,
#else #else
Node *node, Node *node,
#endif #endif
TargetEntry *tent,
char **resname, char **resname,
char *refname, char *refname,
char *colname, char *colname,
...@@ -66,7 +65,7 @@ transformTargetIdent(ParseState *pstate, ...@@ -66,7 +65,7 @@ transformTargetIdent(ParseState *pstate,
{ {
Node *expr = NULL; Node *expr = NULL;
Oid attrtype_target; Oid attrtype_target;
TargetEntry *tent = makeNode(TargetEntry);
if (pstate->p_is_insert) if (pstate->p_is_insert)
{ {
...@@ -93,6 +92,7 @@ transformTargetIdent(ParseState *pstate, ...@@ -93,6 +92,7 @@ transformTargetIdent(ParseState *pstate,
target_colname = *resname; target_colname = *resname;
/* this looks strange to me, returning an empty TargetEntry bjm 1998/08/24 */
if (target_colname == NULL || colname == NULL) if (target_colname == NULL || colname == NULL)
return (tent); return (tent);
...@@ -115,7 +115,7 @@ transformTargetIdent(ParseState *pstate, ...@@ -115,7 +115,7 @@ transformTargetIdent(ParseState *pstate,
attrtypmod_target = get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target); attrtypmod_target = get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target);
#ifdef PARSEDEBUG #ifdef PARSEDEBUG
printf("transformTargetIdent- transform type %d to %d\n", printf("MakeTargetEntryIdent- transform type %d to %d\n",
attrtype_id, attrtype_target); attrtype_id, attrtype_target);
#endif #endif
if ((attrtype_id != attrtype_target) if ((attrtype_id != attrtype_target)
...@@ -125,7 +125,7 @@ printf("transformTargetIdent- transform type %d to %d\n", ...@@ -125,7 +125,7 @@ printf("transformTargetIdent- transform type %d to %d\n",
{ {
expr = coerce_type(pstate, node, attrtype_id, attrtype_target); expr = coerce_type(pstate, node, attrtype_id, attrtype_target);
expr = transformExpr(pstate, expr, EXPR_COLUMN_FIRST); expr = transformExpr(pstate, expr, EXPR_COLUMN_FIRST);
tent = MakeTargetlistExpr(pstate, *resname, expr, FALSE, FALSE); tent = MakeTargetEntryExpr(pstate, *resname, expr, FALSE, FALSE);
expr = tent->expr; expr = tent->expr;
} }
else else
...@@ -155,7 +155,7 @@ printf("transformTargetIdent- transform type %d to %d\n", ...@@ -155,7 +155,7 @@ printf("transformTargetIdent- transform type %d to %d\n",
name = ((*resname != NULL)? *resname: colname); name = ((*resname != NULL)? *resname: colname);
#ifdef PARSEDEBUG #ifdef PARSEDEBUG
printf("transformTargetIdent- call transformIdent()\n"); printf("MakeTargetEntryIdent- call transformIdent()\n");
#endif #endif
#if FALSE #if FALSE
expr = transformIdent(pstate, (Node *) ident, EXPR_COLUMN_FIRST); expr = transformIdent(pstate, (Node *) ident, EXPR_COLUMN_FIRST);
...@@ -170,7 +170,7 @@ printf("transformTargetIdent- call transformIdent()\n"); ...@@ -170,7 +170,7 @@ printf("transformTargetIdent- call transformIdent()\n");
type_mod = -1; type_mod = -1;
#ifdef PARSEDEBUG #ifdef PARSEDEBUG
printf("transformTargetIdent- attrtype_target = %d; type_mod = %d\n", attrtype_target, type_mod); printf("MakeTargetEntryIdent- attrtype_target = %d; type_mod = %d\n", attrtype_target, type_mod);
#endif #endif
tent->resdom = makeResdom((AttrNumber) pstate->p_last_resno++, tent->resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
...@@ -184,10 +184,10 @@ printf("transformTargetIdent- attrtype_target = %d; type_mod = %d\n", attrtype_t ...@@ -184,10 +184,10 @@ printf("transformTargetIdent- attrtype_target = %d; type_mod = %d\n", attrtype_t
} }
return (tent); return (tent);
} /* transformTargetIdent() */ } /* MakeTargetEntryIdent() */
/* MakeTargetlistExpr() /* MakeTargetEntryExpr()
* Make a TargetEntry from an expression. * Make a TargetEntry from an expression.
* arrayRef is a list of transformed A_Indices. * arrayRef is a list of transformed A_Indices.
* *
...@@ -200,7 +200,7 @@ printf("transformTargetIdent- attrtype_target = %d; type_mod = %d\n", attrtype_t ...@@ -200,7 +200,7 @@ printf("transformTargetIdent- attrtype_target = %d; type_mod = %d\n", attrtype_t
* - daveh@insightdist.com 1998-07-31 * - daveh@insightdist.com 1998-07-31
*/ */
TargetEntry * TargetEntry *
MakeTargetlistExpr(ParseState *pstate, MakeTargetEntryExpr(ParseState *pstate,
char *colname, char *colname,
Node *expr, Node *expr,
List *arrayRef, List *arrayRef,
...@@ -213,11 +213,10 @@ MakeTargetlistExpr(ParseState *pstate, ...@@ -213,11 +213,10 @@ MakeTargetlistExpr(ParseState *pstate,
int resdomno; int resdomno;
Relation rd; Relation rd;
bool attrisset; bool attrisset;
TargetEntry *tent;
Resdom *resnode; Resdom *resnode;
if (expr == NULL) if (expr == NULL)
elog(ERROR, "MakeTargetlistExpr: invalid use of NULL expression"); elog(ERROR, "MakeTargetEntryExpr: invalid use of NULL expression");
type_id = exprType(expr); type_id = exprType(expr);
if (nodeTag(expr) == T_Var) if (nodeTag(expr) == T_Var)
...@@ -225,7 +224,7 @@ MakeTargetlistExpr(ParseState *pstate, ...@@ -225,7 +224,7 @@ MakeTargetlistExpr(ParseState *pstate,
else else
type_mod = -1; type_mod = -1;
/* Processes target columns that will be receiving results */ /* Process target columns that will be receiving results */
if (pstate->p_is_insert || pstate->p_is_update) if (pstate->p_is_insert || pstate->p_is_update)
{ {
/* /*
...@@ -266,7 +265,7 @@ MakeTargetlistExpr(ParseState *pstate, ...@@ -266,7 +265,7 @@ MakeTargetlistExpr(ParseState *pstate,
} }
#ifdef PARSEDEBUG #ifdef PARSEDEBUG
printf("MakeTargetlistExpr: attrtypmod is %d\n", (int4) attrtypmod); printf("MakeTargetEntryExpr: attrtypmod is %d\n", (int4) attrtypmod);
#endif #endif
/* Apparently going to a fixed-length string? /* Apparently going to a fixed-length string?
...@@ -329,52 +328,23 @@ printf("MakeTargetlistExpr: attrtypmod is %d\n", (int4) attrtypmod); ...@@ -329,52 +328,23 @@ printf("MakeTargetlistExpr: attrtypmod is %d\n", (int4) attrtypmod);
(Oid) 0, (Oid) 0,
resjunk); resjunk);
tent = makeTargetEntry(resnode, expr); return makeTargetEntry(resnode, expr);
} /* MakeTargetEntryExpr() */
return tent; /*
} /* MakeTargetlistExpr() */ * MakeTargetlistComplex()
* pMake a TargetEntry from an complex node.
/* transformTargetList()
* Turns a list of ResTarget's into a list of TargetEntry's.
*/ */
List * static TargetEntry *
transformTargetList(ParseState *pstate, List *targetlist) MakeTargetEntryComplex(ParseState *pstate,
ResTarget *res)
{ {
List *p_target = NIL;
List *tail_p_target = NIL;
while (targetlist != NIL)
{
ResTarget *res = (ResTarget *) lfirst(targetlist);
TargetEntry *tent = makeNode(TargetEntry);
switch (nodeTag(res->val))
{
case T_Ident:
{
char *identname;
#if FALSE
char *resname;
#endif
#ifdef PARSEDEBUG
printf("transformTargetList: decode T_Ident\n");
#endif
identname = ((Ident *) res->val)->name;
tent = transformTargetIdent(pstate, (Node *)res->val, tent, &res->name, NULL, identname, FALSE);
break;
}
case T_ParamNo:
case T_FuncCall:
case T_A_Const:
case T_A_Expr:
{
Node *expr = transformExpr(pstate, (Node *) res->val, EXPR_COLUMN_FIRST); Node *expr = transformExpr(pstate, (Node *) res->val, EXPR_COLUMN_FIRST);
#ifdef PARSEDEBUG #ifdef PARSEDEBUG
printf("transformTargetList: decode T_Expr\n"); printf("transformTargetList: decode T_Expr\n");
#endif #endif
handleTargetColname(pstate, &res->name, NULL, NULL); handleTargetColname(pstate, &res->name, NULL, NULL);
/* note indirection has not been transformed */ /* note indirection has not been transformed */
if (pstate->p_is_insert && res->indirection != NIL) if (pstate->p_is_insert && res->indirection != NIL)
...@@ -435,7 +405,7 @@ printf("transformTargetList: decode T_Expr\n"); ...@@ -435,7 +405,7 @@ printf("transformTargetList: decode T_Expr\n");
constval = makeNode(Value); constval = makeNode(Value);
constval->type = T_String; constval->type = T_String;
constval->val.str = save_str; constval->val.str = save_str;
tent = MakeTargetlistExpr(pstate, res->name, return MakeTargetEntryExpr(pstate, res->name,
(Node *) make_const(constval), (Node *) make_const(constval),
NULL, FALSE); NULL, FALSE);
pfree(save_str); pfree(save_str);
...@@ -468,13 +438,19 @@ printf("transformTargetList: decode T_Expr\n"); ...@@ -468,13 +438,19 @@ printf("transformTargetList: decode T_Expr\n");
} }
} }
res->name = colname; res->name = colname;
tent = MakeTargetlistExpr(pstate, res->name, expr, return MakeTargetEntryExpr(pstate, res->name, expr,
res->indirection, FALSE); res->indirection, FALSE);
} }
break; }
}
case T_Attr: /*
{ * MakeTargetlistComplex()
* pMake a TargetEntry from an complex node.
*/
static TargetEntry *
MakeTargetEntryAttr(ParseState *pstate,
ResTarget *res)
{
Oid type_id; Oid type_id;
int32 type_mod; int32 type_mod;
Attr *att = (Attr *) res->val; Attr *att = (Attr *) res->val;
...@@ -482,62 +458,12 @@ printf("transformTargetList: decode T_Expr\n"); ...@@ -482,62 +458,12 @@ printf("transformTargetList: decode T_Expr\n");
char *attrname; char *attrname;
char *resname; char *resname;
Resdom *resnode; Resdom *resnode;
int resdomno;
List *attrs = att->attrs; List *attrs = att->attrs;
TargetEntry *tent;
Oid relid;
/*
* Target item is a single '*', expand all tables (eg.
* SELECT * FROM emp)
*/
if (att->relname != NULL && !strcmp(att->relname, "*"))
{
if (tail_p_target == NIL)
p_target = tail_p_target = ExpandAllTables(pstate);
else
lnext(tail_p_target) = ExpandAllTables(pstate);
while (lnext(tail_p_target) != NIL)
/* make sure we point to the last target entry */
tail_p_target = lnext(tail_p_target);
/*
* skip rest of while loop
*/
targetlist = lnext(targetlist);
continue;
}
/*
* Target item is relation.*, expand the table (eg.
* SELECT emp.*, dname FROM emp, dept)
*/
attrname = strVal(lfirst(att->attrs)); attrname = strVal(lfirst(att->attrs));
if (att->attrs != NIL && !strcmp(attrname, "*"))
{
/*
* tail_p_target is the target list we're building
* in the while loop. Make sure we fix it after
* appending more nodes.
*/
if (tail_p_target == NIL)
p_target = tail_p_target = expandAll(pstate, att->relname,
att->relname, &pstate->p_last_resno);
else
lnext(tail_p_target) =
expandAll(pstate, att->relname, att->relname,
&pstate->p_last_resno);
while (lnext(tail_p_target) != NIL)
/* make sure we point to the last target entry */
tail_p_target = lnext(tail_p_target);
/*
* skip the rest of the while loop
*/
targetlist = lnext(targetlist);
continue;
}
/* /*
* Target item is fully specified: ie. * Target item is fully specified: ie.
* relation.attribute * relation.attribute
...@@ -570,17 +496,123 @@ printf("transformTargetList: decode T_Attr\n"); ...@@ -570,17 +496,123 @@ printf("transformTargetList: decode T_Attr\n");
while (lnext(attrs) != NIL) while (lnext(attrs) != NIL)
attrs = lnext(attrs); attrs = lnext(attrs);
resname = (res->name) ? res->name : strVal(lfirst(attrs)); resname = (res->name) ? res->name : strVal(lfirst(attrs));
resnode = makeResdom((AttrNumber) pstate->p_last_resno++, if (pstate->p_is_insert || pstate->p_is_update)
{
/*
* insert or update query -- insert, update work only on one
* relation, so multiple occurence of same resdomno is bogus
*/
relid = refnameRangeTableEntry(pstate, att->relname)->relid;
resdomno = get_attnum(relid, attrname);
}
else
resdomno = pstate->p_last_resno++;
resnode = makeResdom((AttrNumber) resdomno,
(Oid) type_id, (Oid) type_id,
type_mod, type_mod,
resname, resname,
(Index) 0, (Index) 0,
(Oid) 0, (Oid) 0,
0); 0);
tent = makeNode(TargetEntry);
tent->resdom = resnode; tent->resdom = resnode;
tent->expr = result; tent->expr = result;
return tent;
}
/* transformTargetList()
* Turns a list of ResTarget's into a list of TargetEntry's.
*/
List *
transformTargetList(ParseState *pstate, List *targetlist)
{
List *p_target = NIL;
List *tail_p_target = NIL;
while (targetlist != NIL)
{
ResTarget *res = (ResTarget *) lfirst(targetlist);
TargetEntry *tent = NULL;
switch (nodeTag(res->val))
{
case T_Ident:
{
char *identname;
#ifdef PARSEDEBUG
printf("transformTargetList: decode T_Ident\n");
#endif
identname = ((Ident *) res->val)->name;
tent = MakeTargetEntryIdent(pstate, (Node *)res->val, &res->name, NULL, identname, FALSE);
break;
}
case T_ParamNo:
case T_FuncCall:
case T_A_Const:
case T_A_Expr:
{
tent = MakeTargetEntryComplex(pstate, res);
break; break;
} }
case T_Attr:
{
bool expand_star = false;
char *attrname;
Attr *att = (Attr *) res->val;
/*
* Target item is a single '*', expand all tables (eg.
* SELECT * FROM emp)
*/
if (att->relname != NULL && !strcmp(att->relname, "*"))
{
if (tail_p_target == NIL)
p_target = tail_p_target = ExpandAllTables(pstate);
else
lnext(tail_p_target) = ExpandAllTables(pstate);
expand_star = true;
}
/*
* Target item is relation.*, expand the table (eg.
* SELECT emp.*, dname FROM emp, dept)
*/
attrname = strVal(lfirst(att->attrs));
if (att->attrs != NIL && !strcmp(attrname, "*"))
{
/*
* tail_p_target is the target list we're building
* in the while loop. Make sure we fix it after
* appending more nodes.
*/
if (tail_p_target == NIL)
p_target = tail_p_target = expandAll(pstate, att->relname,
att->relname, &pstate->p_last_resno);
else
lnext(tail_p_target) =
expandAll(pstate, att->relname, att->relname,
&pstate->p_last_resno);
expand_star = true;
}
if (expand_star)
{
while (lnext(tail_p_target) != NIL)
/* make sure we point to the last target entry */
tail_p_target = lnext(tail_p_target);
/*
* skip rest of while loop
*/
targetlist = lnext(targetlist);
continue;
}
else
{
tent = MakeTargetEntryAttr(pstate, res);
break;
}
}
default: default:
/* internal error */ /* internal error */
elog(ERROR, "internal error: do not know how to transform targetlist"); elog(ERROR, "internal error: do not know how to transform targetlist");
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: parse_target.h,v 1.9 1998/08/05 04:49:15 scrappy Exp $ * $Id: parse_target.h,v 1.10 1998/08/25 03:17:29 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -25,9 +25,8 @@ ...@@ -25,9 +25,8 @@
extern List *transformTargetList(ParseState *pstate, List *targetlist); extern List *transformTargetList(ParseState *pstate, List *targetlist);
extern List *makeTargetNames(ParseState *pstate, List *cols); extern List *makeTargetNames(ParseState *pstate, List *cols);
extern TargetEntry * extern TargetEntry *
transformTargetIdent(ParseState *pstate, MakeTargetEntryIdent(ParseState *pstate,
Node *node, Node *node,
TargetEntry *tent,
char **resname, char **resname,
char *refname, char *refname,
char *colname, char *colname,
...@@ -35,7 +34,7 @@ transformTargetIdent(ParseState *pstate, ...@@ -35,7 +34,7 @@ transformTargetIdent(ParseState *pstate,
extern Node * extern Node *
CoerceTargetExpr(ParseState *pstate, Node *expr, CoerceTargetExpr(ParseState *pstate, Node *expr,
Oid type_id, Oid attrtype); Oid type_id, Oid attrtype);
TargetEntry * MakeTargetlistExpr(ParseState *pstate, TargetEntry * MakeTargetEntryExpr(ParseState *pstate,
char *colname, char *colname,
Node *expr, Node *expr,
List *arrayRef, List *arrayRef,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment