]> granicus.if.org Git - postgresql/commitdiff
From: David Hartwig <daveh@insightdist.com>
authorMarc G. Fournier <scrappy@hub.org>
Thu, 21 May 1998 03:53:51 +0000 (03:53 +0000)
committerMarc G. Fournier <scrappy@hub.org>
Thu, 21 May 1998 03:53:51 +0000 (03:53 +0000)
Here is a patch to remove the requirement that ORDER/GROUP BY clause
identifiers be included in the target list.

src/backend/executor/execMain.c
src/backend/parser/parse_clause.c
src/backend/parser/parse_target.c
src/include/parser/parse_target.h

index 35107c8af20e08c5acfcb08e8d72c4f01e0de204..1437c2e8c9c4d12561485f3f554bfc94660fa7be 100644 (file)
@@ -26,7 +26,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.45 1998/02/27 08:43:52 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.46 1998/05/21 03:53:50 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -521,14 +521,16 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
         *        NOTE: in the future we might want to initialize the junk
         *        filter for all queries.
         * ----------------
+        *        SELECT added by daveh@insightdist.com  5/20/98 to allow 
+        *        ORDER/GROUP BY have an identifier missing from the target.
         */
        if (operation == CMD_UPDATE || operation == CMD_DELETE ||
-               operation == CMD_INSERT)
+               operation == CMD_INSERT || operation == CMD_SELECT)
        {
-
                JunkFilter *j = (JunkFilter *) ExecInitJunkFilter(targetList);
-
                estate->es_junkFilter = j;
+
+               tupType = j->jf_cleanTupType;       /*  Added by daveh@insightdist.com  5/20/98   */
        }
        else
                estate->es_junkFilter = NULL;
index 30be8335351c217dbe1b3e8272c72ec493f98697..06c7cdee5f284af25107c6a2d0ef81ec1d88b6c1 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.15 1998/03/31 04:43:53 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.16 1998/05/21 03:53:50 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -182,6 +182,37 @@ find_targetlist_entry(ParseState *pstate, SortGroupBy *sortgroupby, List *tlist)
                        }
                }
        }
+
+       /*    BEGIN add missing target entry hack.
+        *
+        *    Prior to this hack, this function returned NIL if no target_result.
+        *    Thus, ORDER/GROUP BY required the attributes be in the target list.
+        *    Now it constructs a new target entry which is appended to the end of
+        *    the target list.   This target is set to be  resjunk = TRUE so that
+        *    it will not be projected into the final tuple.
+        *          daveh@insightdist.com    5/20/98
+        */  
+       if ( ! target_result)  {  
+               List   *p_target = tlist;
+               Ident *missingTargetId = (Ident *)makeNode(Ident);
+               TargetEntry *tent = makeNode(TargetEntry);
+               
+               /*   Fill in the constructed Ident node   */
+               missingTargetId->type = T_Ident;
+               missingTargetId->name = palloc(strlen(sortgroupby->name) + 1);
+               strcpy(missingTargetId->name, sortgroupby->name);
+
+               transformTargetId(pstate, missingTargetId, tent, missingTargetId->name, TRUE);
+
+               /* Add to the end of the target list */
+               while (lnext(p_target) != NIL)  {
+                       p_target = lnext(p_target);
+               }
+               lnext(p_target) = lcons(tent, NIL);
+               target_result = tent;
+       }
+       /*    END add missing target entry hack.   */
+
        return target_result;
 }
 
@@ -203,10 +234,6 @@ transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist)
                Resdom     *resdom;
 
                restarget = find_targetlist_entry(pstate, lfirst(grouplist), targetlist);
-
-               if (restarget == NULL)
-                       elog(ERROR, "The field being grouped by must appear in the target list");
-
                grpcl->entry = restarget;
                resdom = restarget->resdom;
                grpcl->grpOpoid = oprid(oper("<",
@@ -262,9 +289,6 @@ transformSortClause(ParseState *pstate,
 
 
                restarget = find_targetlist_entry(pstate, sortby, targetlist);
-               if (restarget == NULL)
-                       elog(ERROR, "The field being ordered by must appear in the target list");
-
                sortcl->resdom = resdom = restarget->resdom;
                sortcl->opoid = oprid(oper(sortby->useOp,
                                                                   resdom->restype,
index e3d5654ec4a9ac28dd4907facbefbbb2b24c5455..e76fa1829e32437af2e5ce1d263233a2ccfd57c5 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.12 1998/05/09 23:29:54 thomas Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.13 1998/05/21 03:53:51 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -52,6 +52,51 @@ coerce_target_expr(ParseState *pstate,
                                   Oid type_id,
                                   Oid attrtype);
 
+
+/*
+ *   transformTargetId - transforms an Ident Node to a Target Entry
+ *   Created this a function to allow the ORDER/GROUP BY clause be able 
+ *   to construct a TargetEntry from an Ident.
+ *
+ *   resjunk = TRUE will hide the target entry in the final result tuple.
+ *        daveh@insightdist.com     5/20/98
+ */
+void
+transformTargetId(ParseState *pstate,
+                               Ident *ident,
+                               TargetEntry *tent,
+                               char *resname,
+                               int16 resjunk)
+{
+       Node   *expr;
+       Oid     type_id;
+       int16   type_mod;
+
+       /*
+        * 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 *) ident, EXPR_COLUMN_FIRST);
+       type_id = exprType(expr);
+       if (nodeTag(expr) == T_Var)
+               type_mod = ((Var *) expr)->vartypmod;
+       else
+               type_mod = -1;
+       tent->resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
+                                                         (Oid) type_id,
+                                                         type_mod,
+                                                         resname,
+                                                         (Index) 0,
+                                                         (Oid) 0,
+                                                         resjunk);
+
+       tent->expr = expr;
+       return;
+}
+
+
+
 /*
  * transformTargetList -
  *       turns a list of ResTarget's into a list of TargetEntry's
@@ -71,36 +116,13 @@ transformTargetList(ParseState *pstate, List *targetlist)
                {
                        case T_Ident:
                                {
-                                       Node       *expr;
-                                       Oid                     type_id;
-                                       int16           type_mod;
                                        char       *identname;
                                        char       *resname;
 
                                        identname = ((Ident *) res->val)->name;
                                        handleTargetColname(pstate, &res->name, NULL, identname);
-
-                                       /*
-                                        * 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);
-                                       if (nodeTag(expr) == T_Var)
-                                               type_mod = ((Var *) expr)->vartypmod;
-                                       else
-                                               type_mod = -1;
                                        resname = (res->name) ? res->name : identname;
-                                       tent->resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
-                                                                                         (Oid) type_id,
-                                                                                         type_mod,
-                                                                                         resname,
-                                                                                         (Index) 0,
-                                                                                         (Oid) 0,
-                                                                                         0);
-
-                                       tent->expr = expr;
+                                       transformTargetId(pstate, (Ident*)res->val, tent, resname, FALSE);
                                        break;
                                }
                        case T_ParamNo:
index 98dd31f68c30f3a4514d456a8d29806e42107df6..cb75d61615e37e4326fb525476aae0575bccb907 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_target.h,v 1.4 1998/02/26 04:42:49 momjian Exp $
+ * $Id: parse_target.h,v 1.5 1998/05/21 03:53:51 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -24,5 +24,7 @@
 
 extern List *transformTargetList(ParseState *pstate, List *targetlist);
 extern List *makeTargetNames(ParseState *pstate, List *cols);
+extern void transformTargetId(ParseState *pstate, Ident *ident,
+       TargetEntry *tent, char *resname, int16 resjunk);
 
 #endif                                                 /* PARSE_TARGET_H */