]> granicus.if.org Git - postgresql/commitdiff
From: Dan McGuirk <mcguirk@indirect.com>
authorMarc G. Fournier <scrappy@hub.org>
Wed, 12 Mar 1997 20:51:33 +0000 (20:51 +0000)
committerMarc G. Fournier <scrappy@hub.org>
Wed, 12 Mar 1997 20:51:33 +0000 (20:51 +0000)
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.

src/backend/parser/analyze.c

index 760ca8066aa8bb97355a26d32ec61fccd495234f..2cbe2c4a66d29b2c4f9570d1d0f36dea20067085 100644 (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)),