mirror of
https://github.com/postgres/postgres.git
synced 2025-04-21 12:05:57 +03:00
Make sure resdomno for update/insert match attribute number for
rewrite system. Restructure parse_target to make it easier to understand.
This commit is contained in:
parent
a06ba33cfd
commit
0fc13f582a
@ -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)
|
|||||||
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)
|
|||||||
|
|
||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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,
|
|||||||
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,
|
|||||||
* - 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,
|
|||||||
{
|
{
|
||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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",
|
|||||||
{
|
{
|
||||||
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",
|
|||||||
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");
|
|||||||
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
|
|||||||
}
|
}
|
||||||
|
|
||||||
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
|
|||||||
* - 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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#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);
|
|||||||
(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");
|
|||||||
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,12 +438,18 @@ 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;
|
||||||
@ -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");
|
|||||||
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;
|
break;
|
||||||
}
|
}
|
||||||
|
case T_ParamNo:
|
||||||
|
case T_FuncCall:
|
||||||
|
case T_A_Const:
|
||||||
|
case T_A_Expr:
|
||||||
|
{
|
||||||
|
tent = MakeTargetEntryComplex(pstate, res);
|
||||||
|
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 @@
|
|||||||
*
|
*
|
||||||
* 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 @@
|
|||||||
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,
|
|||||||
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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user