From: Dan McGuirk <mcguirk@indirect.com>

Subject: [HACKERS] equal column and table name patch

This fixes a bug where selects fail when there is a column with the same
name as the table it's a part of.
This commit is contained in:
Marc G. Fournier 1997-03-12 20:51:33 +00:00
parent e4949f9fe5
commit 127826978a
1 changed files with 78 additions and 44 deletions

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.22 1997/03/02 01:02:48 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.23 1997/03/12 20:51:33 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@ -52,7 +52,10 @@ static Query *transformUpdateStmt(ParseState *pstate, ReplaceStmt *stmt);
static Query *transformCursorStmt(ParseState *pstate, CursorStmt *stmt);
static Node *handleNestedDots(ParseState *pstate, Attr *attr, int *curr_resno);
static Node *transformExpr(ParseState *pstate, Node *expr);
#define EXPR_COLUMN_FIRST 1
#define EXPR_RELATION_FIRST 2
static Node *transformExpr(ParseState *pstate, Node *expr, int precedence);
static Node *transformIdent(ParseState *pstate, Node *expr, int precedence);
static void makeRangeTable(ParseState *pstate, char *relname, List *frmList);
static List *expandAllTables(ParseState *pstate);
@ -534,7 +537,7 @@ transformCursorStmt(ParseState *pstate, CursorStmt *stmt)
* here.
*/
static Node *
transformExpr(ParseState *pstate, Node *expr)
transformExpr(ParseState *pstate, Node *expr, int precedence)
{
Node *result = NULL;
@ -553,11 +556,11 @@ transformExpr(ParseState *pstate, Node *expr)
while(idx!=NIL) {
A_Indices *ai = (A_Indices *)lfirst(idx);
Node *lexpr=NULL, *uexpr;
uexpr = transformExpr(pstate, ai->uidx); /* must exists */
uexpr = transformExpr(pstate, ai->uidx, precedence); /* must exists */
if (exprType(uexpr) != INT4OID)
elog(WARN, "array index expressions must be int4's");
if (ai->lidx != NULL) {
lexpr = transformExpr(pstate, ai->lidx);
lexpr = transformExpr(pstate, ai->lidx, precedence);
if (exprType(lexpr) != INT4OID)
elog(WARN, "array index expressions must be int4's");
}
@ -615,14 +618,14 @@ transformExpr(ParseState *pstate, Node *expr)
switch(a->oper) {
case OP:
{
Node *lexpr = transformExpr(pstate, a->lexpr);
Node *rexpr = transformExpr(pstate, a->rexpr);
Node *lexpr = transformExpr(pstate, a->lexpr, precedence);
Node *rexpr = transformExpr(pstate, a->rexpr, precedence);
result = (Node *)make_op(a->opname, lexpr, rexpr);
}
break;
case ISNULL:
{
Node *lexpr = transformExpr(pstate, a->lexpr);
Node *lexpr = transformExpr(pstate, a->lexpr, precedence);
result = ParseFunc(pstate,
"NullValue", lcons(lexpr, NIL),
&pstate->p_last_resno);
@ -630,7 +633,7 @@ transformExpr(ParseState *pstate, Node *expr)
break;
case NOTNULL:
{
Node *lexpr = transformExpr(pstate, a->lexpr);
Node *lexpr = transformExpr(pstate, a->lexpr, precedence);
result = ParseFunc(pstate,
"NonNullValue", lcons(lexpr, NIL),
&pstate->p_last_resno);
@ -639,8 +642,8 @@ transformExpr(ParseState *pstate, Node *expr)
case AND:
{
Expr *expr = makeNode(Expr);
Node *lexpr = transformExpr(pstate, a->lexpr);
Node *rexpr = transformExpr(pstate, a->rexpr);
Node *lexpr = transformExpr(pstate, a->lexpr, precedence);
Node *rexpr = transformExpr(pstate, a->rexpr, precedence);
if (exprType(lexpr) != BOOLOID)
elog(WARN,
"left-hand side of AND is type '%s', not bool",
@ -658,8 +661,8 @@ transformExpr(ParseState *pstate, Node *expr)
case OR:
{
Expr *expr = makeNode(Expr);
Node *lexpr = transformExpr(pstate, a->lexpr);
Node *rexpr = transformExpr(pstate, a->rexpr);
Node *lexpr = transformExpr(pstate, a->lexpr, precedence);
Node *rexpr = transformExpr(pstate, a->rexpr, precedence);
if (exprType(lexpr) != BOOLOID)
elog(WARN,
"left-hand side of OR is type '%s', not bool",
@ -677,7 +680,7 @@ transformExpr(ParseState *pstate, Node *expr)
case NOT:
{
Expr *expr = makeNode(Expr);
Node *rexpr = transformExpr(pstate, a->rexpr);
Node *rexpr = transformExpr(pstate, a->rexpr, precedence);
if (exprType(rexpr) != BOOLOID)
elog(WARN,
"argument to NOT is type '%s', not bool",
@ -692,24 +695,8 @@ transformExpr(ParseState *pstate, Node *expr)
break;
}
case T_Ident: {
Ident *ident = (Ident*)expr;
RangeTblEntry *rte;
/* could be a column name or a relation_name */
if (refnameRangeTableEntry(pstate->p_rtable, ident->name) != NULL) {
ident->isRel = TRUE;
result = (Node*)ident;
}
else if ((rte = colnameRangeTableEntry(pstate, ident->name)) != NULL)
{
Attr *att = makeNode(Attr);
att->relname = rte->refname;
att->attrs = lcons(makeString(ident->name), NIL);
result =
(Node*)handleNestedDots(pstate, att, &pstate->p_last_resno);
} else
elog(WARN, "attribute \"%s\" not found", ident->name);
/* look for a column name or a relation name (the default behavior) */
result = transformIdent(pstate, expr, precedence);
break;
}
case T_FuncCall: {
@ -718,7 +705,7 @@ transformExpr(ParseState *pstate, Node *expr)
/* transform the list of arguments */
foreach(args, fn->args)
lfirst(args) = transformExpr(pstate, (Node*)lfirst(args));
lfirst(args) = transformExpr(pstate, (Node*)lfirst(args), precedence);
result = ParseFunc(pstate,
fn->funcname, fn->args, &pstate->p_last_resno);
break;
@ -733,6 +720,49 @@ transformExpr(ParseState *pstate, Node *expr)
return result;
}
static Node *
transformIdent(ParseState *pstate, Node *expr, int precedence)
{
Ident *ident = (Ident*)expr;
RangeTblEntry *rte;
Node *column_result, *relation_result, *result;
column_result = relation_result = result = 0;
/* try to find the ident as a column */
if ((rte = colnameRangeTableEntry(pstate, ident->name)) != NULL) {
Attr *att = makeNode(Attr);
att->relname = rte->refname;
att->attrs = lcons(makeString(ident->name), NIL);
column_result =
(Node*)handleNestedDots(pstate, att, &pstate->p_last_resno);
}
/* try to find the ident as a relation */
if (refnameRangeTableEntry(pstate->p_rtable, ident->name) != NULL) {
ident->isRel = TRUE;
relation_result = (Node*)ident;
}
/* choose the right result based on the precedence */
if(precedence == EXPR_COLUMN_FIRST) {
if(column_result)
result = column_result;
else
result = relation_result;
} else {
if(relation_result)
result = relation_result;
else
result = column_result;
}
if(result == NULL)
elog(WARN, "attribute \"%s\" not found", ident->name);
return result;
}
/*****************************************************************************
*
* From Clause
@ -1011,7 +1041,11 @@ transformTargetList(ParseState *pstate, List *targetlist)
identname = ((Ident*)res->val)->name;
handleTargetColname(pstate, &res->name, NULL, res->name);
expr = transformExpr(pstate, (Node*)res->val);
/* here we want to look for column names only, not relation */
/* names (even though they can be stored in Ident nodes, */
/* too) */
expr = transformIdent(pstate, (Node*)res->val, EXPR_COLUMN_FIRST);
type_id = exprType(expr);
type_len = tlen(get_id_type(type_id));
resname = (res->name) ? res->name : identname;
@ -1030,7 +1064,7 @@ transformTargetList(ParseState *pstate, List *targetlist)
case T_FuncCall:
case T_A_Const:
case T_A_Expr: {
Node *expr = transformExpr(pstate, (Node *)res->val);
Node *expr = transformExpr(pstate, (Node *)res->val, EXPR_COLUMN_FIRST);
handleTargetColname(pstate, &res->name, NULL, NULL);
/* note indirection has not been transformed */
@ -1054,13 +1088,13 @@ transformTargetList(ParseState *pstate, List *targetlist)
str = save_str = (char*)palloc(strlen(val) + MAXDIM * 25 + 2);
foreach(elt, res->indirection) {
A_Indices *aind = (A_Indices *)lfirst(elt);
aind->uidx = transformExpr(pstate, aind->uidx);
aind->uidx = transformExpr(pstate, aind->uidx, EXPR_COLUMN_FIRST);
if (!IsA(aind->uidx,Const))
elog(WARN,
"Array Index for Append should be a constant");
uindx[i] = ((Const *)aind->uidx)->constvalue;
if (aind->lidx!=NULL) {
aind->lidx = transformExpr(pstate, aind->lidx);
aind->lidx = transformExpr(pstate, aind->lidx, EXPR_COLUMN_FIRST);
if (!IsA(aind->lidx,Const))
elog(WARN,
"Array Index for Append should be a constant");
@ -1101,8 +1135,8 @@ transformTargetList(ParseState *pstate, List *targetlist)
List *ilist = res->indirection;
while (ilist!=NIL) {
A_Indices *ind = lfirst(ilist);
ind->lidx = transformExpr(pstate, ind->lidx);
ind->uidx = transformExpr(pstate, ind->uidx);
ind->lidx = transformExpr(pstate, ind->lidx, EXPR_COLUMN_FIRST);
ind->uidx = transformExpr(pstate, ind->uidx, EXPR_COLUMN_FIRST);
ilist = lnext(ilist);
}
}
@ -1178,8 +1212,8 @@ transformTargetList(ParseState *pstate, List *targetlist)
List *ilist = att->indirection;
while (ilist!=NIL) {
A_Indices *ind = lfirst(ilist);
ind->lidx = transformExpr(pstate, ind->lidx);
ind->uidx = transformExpr(pstate, ind->uidx);
ind->lidx = transformExpr(pstate, ind->lidx, EXPR_COLUMN_FIRST);
ind->uidx = transformExpr(pstate, ind->uidx, EXPR_COLUMN_FIRST);
ilist = lnext(ilist);
}
result = (Node*)make_array_ref(result, att->indirection);
@ -1390,7 +1424,7 @@ make_targetlist_expr(ParseState *pstate,
tent->expr = expr;
return tent;
}
}
/*****************************************************************************
@ -1412,7 +1446,7 @@ transformWhereClause(ParseState *pstate, Node *a_expr)
if (a_expr == NULL)
return (Node *)NULL; /* no qualifiers */
qual = transformExpr(pstate, a_expr);
qual = transformExpr(pstate, a_expr, EXPR_COLUMN_FIRST);
if (exprType(qual) != BOOLOID) {
elog(WARN,
"where clause must return type bool, not %s",
@ -1633,7 +1667,7 @@ handleNestedDots(ParseState *pstate, Attr *attr, int *curr_resno)
Node *retval = NULL;
if (attr->paramNo != NULL) {
Param *param = (Param *)transformExpr(pstate, (Node*)attr->paramNo);
Param *param = (Param *)transformExpr(pstate, (Node*)attr->paramNo, EXPR_RELATION_FIRST);
retval =
ParseFunc(pstate, strVal(lfirst(attr->attrs)),