OSDN Git Service

Break parser functions into smaller files, group together.
authorBruce Momjian <bruce@momjian.us>
Tue, 25 Nov 1997 22:07:18 +0000 (22:07 +0000)
committerBruce Momjian <bruce@momjian.us>
Tue, 25 Nov 1997 22:07:18 +0000 (22:07 +0000)
62 files changed:
src/backend/access/common/tupdesc.c
src/backend/catalog/heap.c
src/backend/catalog/index.c
src/backend/catalog/pg_operator.c
src/backend/catalog/pg_proc.c
src/backend/catalog/pg_type.c
src/backend/commands/_deadcode/version.c
src/backend/commands/explain.c
src/backend/commands/recipe.c
src/backend/commands/remove.c
src/backend/commands/vacuum.c
src/backend/commands/view.c
src/backend/executor/execTuples.c
src/backend/executor/functions.c
src/backend/executor/nodeAgg.c
src/backend/executor/spi.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/print.c
src/backend/optimizer/path/xfunc.c
src/backend/optimizer/plan/createplan.c
src/backend/optimizer/plan/planner.c
src/backend/optimizer/prep/preptlist.c
src/backend/optimizer/prep/prepunion.c
src/backend/optimizer/util/tlist.c
src/backend/parser/Makefile
src/backend/parser/analyze.c
src/backend/parser/catalog_utils.c [deleted file]
src/backend/parser/gram.y
src/backend/parser/keywords.c
src/backend/parser/parse_agg.c [new file with mode: 0644]
src/backend/parser/parse_clause.c [new file with mode: 0644]
src/backend/parser/parse_expr.c [new file with mode: 0644]
src/backend/parser/parse_func.c [new file with mode: 0644]
src/backend/parser/parse_node.c [moved from src/backend/parser/parse_query.c with 56% similarity]
src/backend/parser/parse_oper.c [new file with mode: 0644]
src/backend/parser/parse_relation.c [new file with mode: 0644]
src/backend/parser/parse_target.c [new file with mode: 0644]
src/backend/parser/parse_type.c [new file with mode: 0644]
src/backend/parser/parser.c
src/backend/parser/scansup.c
src/backend/rewrite/rewriteDefine.c
src/backend/tcop/aclchk.c
src/backend/tcop/postgres.c
src/include/executor/spi.h
src/include/nodes/nodeFuncs.h
src/include/optimizer/planner.h
src/include/parser/analyze.h [new file with mode: 0644]
src/include/parser/catalog_utils.h [deleted file]
src/include/parser/parse_agg.h [new file with mode: 0644]
src/include/parser/parse_clause.h [new file with mode: 0644]
src/include/parser/parse_expr.h [new file with mode: 0644]
src/include/parser/parse_func.h [new file with mode: 0644]
src/include/parser/parse_node.h [new file with mode: 0644]
src/include/parser/parse_oper.h [new file with mode: 0644]
src/include/parser/parse_query.h [deleted file]
src/include/parser/parse_relation.h [new file with mode: 0644]
src/include/parser/parse_state.h [deleted file]
src/include/parser/parse_target.h [new file with mode: 0644]
src/include/parser/parse_type.h [new file with mode: 0644]
src/include/parser/parser.h [new file with mode: 0644]
src/include/tcop/tcopprot.h
src/test/regress/checkresults

index 04622a1..1a8d297 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.28 1997/11/24 05:07:42 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.29 1997/11/25 21:58:35 momjian Exp $
  *
  * NOTES
  *       some of the executor utility code such as "ExecTypeFromTL" should be
@@ -20,8 +20,9 @@
 
 #include <postgres.h>
 
-#include <parser/catalog_utils.h>
+#include <catalog/pg_type.h>
 #include <nodes/parsenodes.h>
+#include <parser/parse_type.h>
 #include <utils/builtins.h>
 #include <utils/fcache.h>
 #include <utils/syscache.h>
@@ -377,10 +378,10 @@ TupleDescInitEntry(TupleDesc desc,
           */
        if (attisset)
        {
-               Type            t = type("oid");
+               Type            t = typeidType(OIDOID);
 
-               att->attlen = tlen(t);
-               att->attbyval = tbyval(t);
+               att->attlen = typeLen(t);
+               att->attbyval = typeByVal(t);
        }
        else
        {
@@ -410,12 +411,12 @@ TupleDescMakeSelfReference(TupleDesc desc,
                                                   char *relname)
 {
        AttributeTupleForm att;
-       Type            t = type("oid");
+       Type            t = typeidType(OIDOID);
 
        att = desc->attrs[attnum - 1];
        att->atttypid = TypeShellMake(relname);
-       att->attlen = tlen(t);
-       att->attbyval = tbyval(t);
+       att->attlen = typeLen(t);
+       att->attbyval = typeByVal(t);
        att->attnelems = 0;
 }
 
index 6a150a0..512e2a0 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.33 1997/11/24 05:08:07 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.34 1997/11/25 21:58:40 momjian Exp $
  *
  * INTERFACE ROUTINES
  *             heap_creatr()                   - Create an uncataloged heap relation
 #include <catalog/pg_attrdef.h>
 #include <catalog/pg_relcheck.h>
 #include <commands/trigger.h>
+#include <parser/parse_expr.h>
+#include <parser/parse_node.h>
+#include <parser/parse_type.h>
 #include <storage/bufmgr.h>
 #include <storage/lmgr.h>
 #include <storage/smgr.h>
-#include <parser/catalog_utils.h>
-#include <parser/parse_query.h>
 #include <rewrite/rewriteRemove.h>
 #include <utils/builtins.h>
 #include <utils/mcxt.h>
@@ -722,8 +723,8 @@ addNewRelationType(char *typeName, Oid new_rel_oid)
         */
        new_type_oid = TypeCreate(typeName, /* type name */
                                                          new_rel_oid,          /* relation oid */
-                                                         tlen(type("oid")),            /* internal size */
-                                                         tlen(type("oid")),            /* external size */
+                                                         typeLen(typeidType(OIDOID)),  /* internal size */
+                                                         typeLen(typeidType(OIDOID)),  /* external size */
                                                          'c',          /* type-type (catalog) */
                                                          ',',          /* default array delimiter */
                                                          "int4in", /* input procedure */
index 418123a..deb908e 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.29 1997/11/24 05:08:11 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.30 1997/11/25 21:58:43 momjian Exp $
  *
  *
  * INTERFACE ROUTINES
 #include <fmgr.h>
 #include <access/genam.h>
 #include <access/heapam.h>
-#include <storage/lmgr.h>
-#include <miscadmin.h>
+#include <access/istrat.h>
 #include <access/xact.h>
-#include <parser/catalog_utils.h>
-#include <storage/smgr.h>
-#include <utils/builtins.h>
-#include <utils/mcxt.h>
-#include <utils/relcache.h>
-#include <utils/syscache.h>
-#include <utils/tqual.h>
 #include <bootstrap/bootstrap.h>
 #include <catalog/catname.h>
 #include <catalog/catalog.h>
 #include <catalog/indexing.h>
 #include <catalog/heap.h>
 #include <catalog/index.h>
+#include <catalog/pg_type.h>
 #include <executor/executor.h>
+#include <miscadmin.h>
 #include <optimizer/clauses.h>
 #include <optimizer/prep.h>
-#include <access/istrat.h>
+#include <parser/parse_func.h>
+#include <storage/lmgr.h>
+#include <storage/smgr.h>
+#include <utils/builtins.h>
+#include <utils/mcxt.h>
+#include <utils/relcache.h>
+#include <utils/syscache.h>
+#include <utils/tqual.h>
 
 #ifndef HAVE_MEMMOVE
 #include <regex/utils.h>
index a4b4919..bbdd237 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.16 1997/11/24 05:08:15 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.17 1997/11/25 21:58:46 momjian Exp $
  *
  * NOTES
  *       these routines moved here from commands/define.c and somewhat cleaned up.
 #include <utils/syscache.h>
 #include <utils/tqual.h>
 #include <access/heapam.h>
-#include <parser/catalog_utils.h>
 #include <catalog/catname.h>
 #include <catalog/pg_operator.h>
+#include <catalog/pg_type.h>
+#include <parser/parse_oper.h>
 #include <storage/bufmgr.h>
 #include <fmgr.h>
 #include <miscadmin.h>
index 9cbf4e3..e08bb54 100644 (file)
@@ -7,28 +7,28 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.9 1997/09/18 20:20:18 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.10 1997/11/25 21:58:48 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include <postgres.h>
 
+#include <fmgr.h>
+#include <miscadmin.h>
 #include <utils/syscache.h>
 #include <catalog/pg_proc.h>
 #include <access/heapam.h>
 #include <access/relscan.h>
-#include <fmgr.h>
-#include <utils/builtins.h>
-#include <utils/sets.h>
 #include <catalog/catname.h>
 #include <catalog/indexing.h>
-#include <parser/parse_query.h>
+#include <catalog/pg_type.h>
+#include <parser/parse_node.h>
 #include <tcop/tcopprot.h>
-#include <parser/catalog_utils.h>
+#include <utils/builtins.h>
+#include <utils/sets.h>
+#include <utils/lsyscache.h>
 #include <optimizer/internal.h>
 #include <optimizer/planner.h>
-#include <utils/lsyscache.h>
-#include <miscadmin.h>
 #ifndef HAVE_MEMMOVE
 #include <regex/utils.h>
 #else
@@ -200,7 +200,7 @@ ProcedureCreate(char *procedureName,
        if (parameterCount == 1 &&
                (toid = TypeGet(strVal(lfirst(argList)), &defined)) &&
                defined &&
-               (relid = typeid_get_relid(toid)) != 0 &&
+               (relid = typeidTypeRelid(toid)) != 0 &&
                get_attnum(relid, procedureName) != InvalidAttrNumber)
                elog(WARN, "method %s already an attribute of type %s",
                         procedureName, strVal(lfirst(argList)));
index 2dc80bb..1cd0fa9 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.13 1997/11/24 05:08:17 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.14 1997/11/25 21:58:50 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include <utils/builtins.h>
 #include <utils/tqual.h>
 #include <fmgr.h>
-#include <parser/catalog_utils.h>
 #include <catalog/catname.h>
 #include <catalog/indexing.h>
+#include <catalog/pg_type.h>
+#include <parser/parse_func.h>
 #include <storage/lmgr.h>
 #include <miscadmin.h>
 #ifndef HAVE_MEMMOVE
index 0059405..829f924 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/_deadcode/Attic/version.c,v 1.7 1997/09/08 02:22:18 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/_deadcode/Attic/version.c,v 1.8 1997/11/25 21:59:11 momjian Exp $
  *
  * NOTES
  *       At the point the version is defined, 2 physical relations are created
@@ -30,6 +30,7 @@
 #include <utils/builtins.h>
 #include <commands/version.h>
 #include <access/xact.h>               /* for GetCurrentXactStartTime */
+#include <parser/parse_node.h>
 #include <tcop/tcopprot.h>
 
 #define MAX_QUERY_LEN 1024
index c0a7412..5c2c1a2 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.14 1997/09/18 20:20:22 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.15 1997/11/25 21:58:53 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include <postgres.h>
 
-#include <parser/catalog_utils.h>
-#include <parser/parse_query.h> /* for MakeTimeRange() */
 #include <nodes/plannodes.h>
 #include <tcop/tcopprot.h>
 #include <lib/stringinfo.h>
 #include <commands/explain.h>
+#include <parser/parse_node.h>
 #include <optimizer/planner.h>
 #include <access/xact.h>
 
index 9e5d281..5b77b73 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/recipe.c,v 1.12 1997/11/21 18:09:51 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/recipe.c,v 1.13 1997/11/25 21:59:00 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,9 +20,9 @@
 #include <catalog/pg_type.h>
 #include <commands/recipe.h>
 #include <libpq/libpq-be.h>
+#include <parser/parse_node.h>
 #include <utils/builtins.h>
 #include <utils/relcache.h>            /* for RelationNameGetRelation */
-#include <parser/parse_query.h>
 #include <rewrite/rewriteHandler.h>
 #include <rewrite/rewriteManip.h>
 #include <tcop/pquery.h>
@@ -488,7 +488,7 @@ tg_replaceNumberedParam(Node *expression,
                                                 * "result" attribute from the tee relation
                                                 */
 
-                                               isRel = (typeid_get_relid(p->paramtype) != 0);
+                                               isRel = (typeidTypeRelid(p->paramtype) != 0);
                                                if (isRel)
                                                {
                                                        newVar = makeVar(rt_ind,
index aaf2127..3bfdfb0 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.16 1997/11/20 23:21:13 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.17 1997/11/25 21:59:03 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -24,7 +24,8 @@
 #include <catalog/pg_language.h>
 #include <catalog/pg_operator.h>
 #include <catalog/pg_proc.h>
-#include <parser/catalog_utils.h>
+#include <catalog/pg_type.h>
+#include <parser/parse_func.h>
 #include <storage/bufmgr.h>
 #include <fmgr.h>
 #ifndef HAVE_MEMMOVE
index 7ae8fa1..2de5360 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.52 1997/11/21 19:59:34 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.53 1997/11/25 21:59:09 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,6 +36,7 @@
 #include <catalog/pg_statistic.h>
 #include <catalog/pg_type.h>
 #include <catalog/pg_operator.h>
+#include <parser/parse_oper.h>
 #include <storage/smgr.h>
 #include <storage/lmgr.h>
 #include <utils/inval.h>
@@ -44,7 +45,6 @@
 #include <utils/syscache.h>
 #include <utils/builtins.h>
 #include <commands/vacuum.h>
-#include <parser/catalog_utils.h>
 #include <storage/bufpage.h>
 #include "storage/shmem.h"
 #ifndef HAVE_GETRUSAGE
index 64b4de2..a752e30 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/view.c,v 1.15 1997/11/21 18:09:58 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/view.c,v 1.16 1997/11/25 21:59:12 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,8 +21,8 @@
 #include <access/xact.h>
 #include <utils/builtins.h>
 #include <nodes/relation.h>
-#include <parser/catalog_utils.h>
-#include <parser/parse_query.h>
+#include <parser/parse_relation.h>
+#include <parser/parse_type.h>
 #include <rewrite/rewriteDefine.h>
 #include <rewrite/rewriteHandler.h>
 #include <rewrite/rewriteManip.h>
@@ -72,7 +72,7 @@ DefineVirtualRelation(char *relname, List *tlist)
                        entry = lfirst(t);
                        res = entry->resdom;
                        resname = res->resname;
-                       restypename = tname(get_id_type(res->restype));
+                       restypename = typeidTypeName(res->restype);
 
                        typename = makeNode(TypeName);
 
index f513354..d541f29 100644 (file)
@@ -14,7 +14,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.10 1997/09/18 20:20:32 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.11 1997/11/25 21:59:16 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #undef ExecStoreTuple
 
 #include "access/tupdesc.h"
+#include "catalog/pg_type.h"
+#include "parser/parse_type.h"
+#include "storage/bufmgr.h"
 #include "utils/palloc.h"
 #include "utils/lsyscache.h"
-#include "storage/bufmgr.h"
-#include "parser/catalog_utils.h"
-#include "catalog/pg_type.h"
 
 static TupleTableSlot *NodeGetResultTupleSlot(Plan *node);
 
index a2f143d..2f0e0b9 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.12 1997/09/18 20:20:37 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.13 1997/11/25 21:59:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,7 +21,6 @@
 #include "nodes/plannodes.h"
 
 #include "catalog/pg_proc.h"
-#include "parser/parse_query.h"
 #include "tcop/pquery.h"
 #include "tcop/tcopprot.h"
 #include "tcop/utility.h"
index b9d7999..accc7b1 100644 (file)
 #include "access/heapam.h"
 #include "catalog/pg_aggregate.h"
 #include "catalog/catalog.h"
+#include "parser/parse_type.h"
 #include "executor/executor.h"
 #include "executor/nodeAgg.h"
 #include "storage/bufmgr.h"
 #include "utils/palloc.h"
 #include "utils/syscache.h"
-#include "parser/catalog_utils.h"
 
 /*
  * AggFuncInfo -
@@ -172,7 +172,7 @@ ExecAgg(Agg *node)
                if (!HeapTupleIsValid(aggTuple))
                        elog(WARN, "ExecAgg: cache lookup failed for aggregate \"%s\"(%s)",
                                 aggname,
-                                tname(get_id_type(agg->basetype)));
+                                typeidTypeName(agg->basetype));
                aggp = (Form_pg_aggregate) GETSTRUCT(aggTuple);
 
                xfn1_oid = aggp->aggtransfn1;
index 16a8ee3..f954dbe 100644 (file)
@@ -6,6 +6,7 @@
  *-------------------------------------------------------------------------
  */
 #include "executor/spi.h"
+#include "catalog/pg_type.h"
 #include "access/printtup.h"
 #include "fmgr.h"
 
index 62b72ab..5d848df 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.15 1997/11/20 23:21:40 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.16 1997/11/25 21:59:40 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,7 +22,6 @@
 #include "nodes/parsenodes.h"
 #include "nodes/primnodes.h"
 #include "nodes/relation.h"
-#include "parser/parse_query.h"
 
 #include "utils/syscache.h"
 #include "utils/builtins.h"            /* for namecpy */
index d674263..6b62064 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.10 1997/10/25 01:09:28 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.11 1997/11/25 21:59:44 momjian Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
 #include "nodes/parsenodes.h"
 #include "nodes/print.h"
 #include "parser/parsetree.h"
-#include "parser/catalog_utils.h"
 #include "access/heapam.h"
 #include "utils/lsyscache.h"
 #include "nodes/nodes.h"
 #include "nodes/plannodes.h"
+#include "parser/parse_relation.h"
 #include "optimizer/clauses.h"
 
 static char *plannode_type(Plan *p);
@@ -194,7 +194,7 @@ print_expr(Node *expr, List *rtable)
                                        r = heap_openr(relname);
                                        if (rt->refname)
                                                relname = rt->refname;  /* table renamed */
-                                       attname = getAttrName(r, var->varattno);
+                                       attname = attnumAttName(r, var->varattno);
                                        heap_close(r);
                                }
                                break;
index 39d4131..0f6894e 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/xfunc.c,v 1.6 1997/09/08 21:45:10 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/xfunc.c,v 1.7 1997/11/25 21:59:50 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -641,10 +641,10 @@ xfunc_width(LispValue clause)
        }
        else if (IsA(clause, Param))
        {
-               if (typeid_get_relid(get_paramtype((Param) clause)))
+               if (typeidTypeRelid(get_paramtype((Param) clause)))
                {
                        /* Param node returns a tuple.  Find its width */
-                       rd = heap_open(typeid_get_relid(get_paramtype((Param) clause)));
+                       rd = heap_open(typeidTypeRelid(get_paramtype((Param) clause)));
                        retval = xfunc_tuple_width(rd);
                        heap_close(rd);
                }
@@ -659,7 +659,7 @@ xfunc_width(LispValue clause)
                else
                {
                        /* Param node returns a base type */
-                       retval = tlen(get_id_type(get_paramtype((Param) clause)));
+                       retval = typeLen(typeidType(get_paramtype((Param) clause)));
                }
                goto exit;
        }
@@ -1324,9 +1324,9 @@ xfunc_func_width(RegProcedure funcid, LispValue args)
        proc = (Form_pg_proc) GETSTRUCT(tupl);
 
        /* if function returns a tuple, get the width of that */
-       if (typeid_get_relid(proc->prorettype))
+       if (typeidTypeRelid(proc->prorettype))
        {
-               rd = heap_open(typeid_get_relid(proc->prorettype));
+               rd = heap_open(typeidTypeRelid(proc->prorettype));
                retval = xfunc_tuple_width(rd);
                heap_close(rd);
                goto exit;
index 11d777e..00898de 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.15 1997/09/08 21:45:13 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.16 1997/11/25 21:59:56 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -31,7 +31,6 @@
 #include "utils/palloc.h"
 #include "utils/builtins.h"
 
-#include "parser/parse_query.h"
 #include "optimizer/clauseinfo.h"
 #include "optimizer/clauses.h"
 #include "optimizer/planmain.h"
index e10e36b..ceddbbe 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.10 1997/11/21 18:10:26 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.11 1997/11/25 21:59:59 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,9 +19,8 @@
 #include "nodes/plannodes.h"
 #include "nodes/parsenodes.h"
 #include "nodes/relation.h"
+#include "parser/parse_expr.h"
 
-#include "parser/catalog_utils.h"
-#include "parser/parse_query.h"
 #include "utils/elog.h"
 #include "utils/lsyscache.h"
 #include "access/heapam.h"
@@ -310,7 +309,7 @@ pg_checkretval(Oid rettype, QueryTreeList *queryTreeList)
        }
 
        /* by here, the function is declared to return some type */
-       if ((typ = (Type) get_id_type(rettype)) == NULL)
+       if ((typ = typeidType(rettype)) == NULL)
                elog(WARN, "can't find return type %d for function\n", rettype);
 
        /*
@@ -318,21 +317,21 @@ pg_checkretval(Oid rettype, QueryTreeList *queryTreeList)
         * final query had better be a retrieve.
         */
        if (cmd != CMD_SELECT)
-               elog(WARN, "function declared to return type %s, but final query is not a retrieve", tname(typ));
+               elog(WARN, "function declared to return type %s, but final query is not a retrieve", typeTypeName(typ));
 
        /*
         * test 4:      for base type returns, the target list should have exactly
         * one entry, and its type should agree with what the user declared.
         */
 
-       if (get_typrelid(typ) == InvalidOid)
+       if (typeTypeRelid(typ) == InvalidOid)
        {
                if (exec_tlist_length(tlist) > 1)
-                       elog(WARN, "function declared to return %s returns multiple values in final retrieve", tname(typ));
+                       elog(WARN, "function declared to return %s returns multiple values in final retrieve", typeTypeName(typ));
 
                resnode = (Resdom *) ((TargetEntry *) lfirst(tlist))->resdom;
                if (resnode->restype != rettype)
-                       elog(WARN, "return type mismatch in function: declared to return %s, returns %s", tname(typ), tname(get_id_type(resnode->restype)));
+                       elog(WARN, "return type mismatch in function: declared to return %s, returns %s", typeTypeName(typ), typeidTypeName(resnode->restype));
 
                /* by here, base return types match */
                return;
@@ -358,16 +357,16 @@ pg_checkretval(Oid rettype, QueryTreeList *queryTreeList)
         * declared return type, and be sure that attributes 1 .. n in the
         * target list match the declared types.
         */
-       reln = heap_open(get_typrelid(typ));
+       reln = heap_open(typeTypeRelid(typ));
 
        if (!RelationIsValid(reln))
-               elog(WARN, "cannot open relation relid %d", get_typrelid(typ));
+               elog(WARN, "cannot open relation relid %d", typeTypeRelid(typ));
 
        relid = reln->rd_id;
        relnatts = reln->rd_rel->relnatts;
 
        if (exec_tlist_length(tlist) != relnatts)
-               elog(WARN, "function declared to return type %s does not retrieve (%s.*)", tname(typ), tname(typ));
+               elog(WARN, "function declared to return type %s does not retrieve (%s.*)", typeTypeName(typ), typeTypeName(typ));
 
        /* expect attributes 1 .. n in order */
        for (i = 1; i <= relnatts; i++)
@@ -397,14 +396,14 @@ pg_checkretval(Oid rettype, QueryTreeList *queryTreeList)
                        else if (IsA(thenode, Func))
                                tletype = (Oid) get_functype((Func *) thenode);
                        else
-                               elog(WARN, "function declared to return type %s does not retrieve (%s.all)", tname(typ), tname(typ));
+                               elog(WARN, "function declared to return type %s does not retrieve (%s.all)", typeTypeName(typ), typeTypeName(typ));
                }
                else
-                       elog(WARN, "function declared to return type %s does not retrieve (%s.all)", tname(typ), tname(typ));
+                       elog(WARN, "function declared to return type %s does not retrieve (%s.all)", typeTypeName(typ), typeTypeName(typ));
 #endif
                /* reach right in there, why don't you? */
                if (tletype != reln->rd_att->attrs[i - 1]->atttypid)
-                       elog(WARN, "function declared to return type %s does not retrieve (%s.all)", tname(typ), tname(typ));
+                       elog(WARN, "function declared to return type %s does not retrieve (%s.all)", typeTypeName(typ), typeTypeName(typ));
        }
 
        heap_close(reln);
index 0010c69..faf2819 100644 (file)
@@ -7,13 +7,14 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.5 1997/09/08 21:45:36 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.6 1997/11/25 22:00:06 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include <string.h>
 #include "postgres.h"
 
+#include "catalog/pg_type.h"
 #include "nodes/pg_list.h"
 #include "nodes/relation.h"
 #include "nodes/primnodes.h"
@@ -24,9 +25,9 @@
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
 #include "utils/palloc.h"
+#include "parser/parse_type.h"
 
 #include "parser/parsetree.h"  /* for getrelid() */
-#include "parser/catalog_utils.h"
 
 #include "optimizer/internal.h"
 #include "optimizer/prep.h"
@@ -278,7 +279,7 @@ new_relation_targetlist(Oid relid, Index rt_index, NodeTag node_type)
                attisset = get_attisset( /* type_id, */ relid, attname);
                if (attisset)
                {
-                       typlen = tlen(type("oid"));
+                       typlen = typeLen(typeidType(OIDOID));
                }
                else
                {
index a686f94..00dd407 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.8 1997/11/21 18:10:44 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.9 1997/11/25 22:00:10 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,7 +22,6 @@
 #include "nodes/plannodes.h"
 #include "nodes/relation.h"
 
-#include "parser/parse_query.h"
 #include "parser/parsetree.h"
 
 #include "utils/elog.h"
index 0896330..aa867f4 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.7 1997/09/08 21:45:55 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.8 1997/11/25 22:00:16 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,7 +26,6 @@
 #include "optimizer/clauses.h"
 
 #include "nodes/makefuncs.h"
-#include "parser/catalog_utils.h"
 
 static Node *flatten_tlistentry(Node *tlistentry, List *flat_tlist);
 
index 8559100..7ab45e4 100644 (file)
@@ -4,7 +4,7 @@
 #    Makefile for parser
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/parser/Makefile,v 1.11 1997/11/24 05:20:57 momjian Exp $
+#    $Header: /cvsroot/pgsql/src/backend/parser/Makefile,v 1.12 1997/11/25 22:00:21 momjian Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -22,8 +22,9 @@ CFLAGS+= -Wno-error
 endif
 
 
-OBJS= analyze.o catalog_utils.o gram.o \
-      keywords.o parser.o parse_query.o scan.o scansup.o
+OBJS= analyze.o gram.o keywords.o parser.o parse_agg.o parse_clause.o \
+      parse_expr.o parse_func.o parse_node.o parse_oper.o parse_relation.o \
+      parse_type.o parse_target.o scan.o scansup.o
 
 all: SUBSYS.o
 
index bee5132..4a3800a 100644 (file)
@@ -7,46 +7,30 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.49 1997/11/20 23:22:11 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.50 1997/11/25 22:00:27 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "postgres.h"
-#include "nodes/nodes.h"
-#include "nodes/params.h"
-#include "nodes/primnodes.h"
-#include "nodes/parsenodes.h"
-#include "nodes/relation.h"
-#include "parse.h"                             /* for AND, OR, etc. */
-#include "catalog/pg_aggregate.h"
-#include "catalog/pg_type.h"   /* for INT4OID, etc. */
-#include "catalog/pg_proc.h"
-#include "utils/elog.h"
-#include "utils/builtins.h"            /* namecmp(), textout() */
-#include "utils/lsyscache.h"
-#include "utils/palloc.h"
-#include "utils/mcxt.h"
-#include "utils/syscache.h"
-#include "utils/acl.h"
-#include "parser/parse_query.h"
-#include "parser/parse_state.h"
-#include "nodes/makefuncs.h"   /* for makeResdom(), etc. */
-#include "nodes/nodeFuncs.h"
-#include "commands/sequence.h"
-
-#include "optimizer/clauses.h"
-#include "access/heapam.h"
-
-#include "miscadmin.h"
 
-#include "port-protos.h"               /* strdup() */
+#include "access/heapam.h"
+#include "nodes/makefuncs.h"
+#include "nodes/memnodes.h"
+#include "nodes/pg_list.h"
+#include "parser/analyze.h"
+#include "parser/parse_agg.h"
+#include "parser/parse_node.h"
+#include "parser/parse_relation.h"
+#include "parser/parse_target.h"
+#include "parser/parse_clause.h"
+#include "utils/builtins.h"
+#include "utils/mcxt.h"
 
-/* convert the parse tree into a query tree */
 static Query *transformStmt(ParseState *pstate, Node *stmt);
-
 static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
 static Query *transformInsertStmt(ParseState *pstate, AppendStmt *stmt);
 static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt);
@@ -55,74 +39,7 @@ static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt);
 static Query *transformSelectStmt(ParseState *pstate, RetrieveStmt *stmt);
 static Query *transformUpdateStmt(ParseState *pstate, ReplaceStmt *stmt);
 static Query *transformCursorStmt(ParseState *pstate, CursorStmt *stmt);
-static Node *handleNestedDots(ParseState *pstate, Attr *attr, int *curr_resno);
-
-#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);
-static char *figureColname(Node *expr, Node *resval);
-static List *makeTargetNames(ParseState *pstate, List *cols);
-static List *transformTargetList(ParseState *pstate, List *targetlist);
-static TargetEntry *make_targetlist_expr(ParseState *pstate,
-                                        char *colname, Node *expr,
-                                        List *arrayRef);
-static bool inWhereClause = false;
-static Node *transformWhereClause(ParseState *pstate, Node *a_expr);
-static List *transformGroupClause(ParseState *pstate, List *grouplist,
-                                        List *targetlist);
-static List *transformSortClause(ParseState *pstate,
-                                       List *orderlist, List *targetlist,
-                                       char *uniqueFlag);
-
-static void parseFromClause(ParseState *pstate, List *frmList);
-static Node *ParseFunc(ParseState *pstate, char *funcname,
-                 List *fargs, int *curr_resno);
-static List *setup_tlist(char *attname, Oid relid);
-static List *setup_base_tlist(Oid typeid);
-static void make_arguments(int nargs, List *fargs, Oid *input_typeids,
-                          Oid *function_typeids);
-static void AddAggToParseState(ParseState *pstate, Aggreg *aggreg);
-static void finalizeAggregates(ParseState *pstate, Query *qry);
-static void parseCheckAggregates(ParseState *pstate, Query *qry);
-static ParseState *makeParseState(void);
-static Node *parser_typecast(Value *expr, TypeName *typename, int typlen);
-static Node *parser_typecast2(Node *expr, Oid exprType, Type tp, int typlen);
-static Aggreg *ParseAgg(char *aggname, Oid basetype, Node *target);
-
-/*****************************************************************************
- *
- *****************************************************************************/
 
-/*
- * makeParseState() --
- *       allocate and initialize a new ParseState.
- *     the CALLERS is responsible for freeing the ParseState* returned
- *
- */
-
-static ParseState *
-makeParseState(void)
-{
-       ParseState *pstate;
-
-       pstate = malloc(sizeof(ParseState));
-       pstate->p_last_resno = 1;
-       pstate->p_rtable = NIL;
-       pstate->p_numAgg = 0;
-       pstate->p_aggs = NIL;
-       pstate->p_is_insert = false;
-       pstate->p_insert_columns = NIL;
-       pstate->p_is_update = false;
-       pstate->p_is_rule = false;
-       pstate->p_target_relation = NULL;
-       pstate->p_target_rangetblentry = NULL;
-
-       return (pstate);
-}
 
 /*
  * parse_analyze -
@@ -144,11 +61,9 @@ parse_analyze(List *pl)
        result->len = length(pl);
        result->qtrees = (Query **) malloc(result->len * sizeof(Query *));
 
-       inWhereClause = false;          /* to avoid nextval(sequence) in WHERE */
-
        while (pl != NIL)
        {
-               pstate = makeParseState();
+               pstate = make_parsestate();
                result->qtrees[i++] = transformStmt(pstate, lfirst(pl));
                pl = lnext(pl);
                if (pstate->p_target_relation != NULL)
@@ -620,2580 +535,3 @@ transformCursorStmt(ParseState *pstate, CursorStmt *stmt)
 
        return (Query *) qry;
 }
-
-/*****************************************************************************
- *
- * Transform Exprs, Aggs, etc.
- *
- *****************************************************************************/
-
-/*
- * transformExpr -
- *       analyze and transform expressions. Type checking and type casting is
- *       done here. The optimizer and the executor cannot handle the original
- *       (raw) expressions collected by the parse tree. Hence the transformation
- *       here.
- */
-static Node *
-transformExpr(ParseState *pstate, Node *expr, int precedence)
-{
-       Node       *result = NULL;
-
-       if (expr == NULL)
-               return NULL;
-
-       switch (nodeTag(expr))
-       {
-               case T_Attr:
-                       {
-                               Attr       *att = (Attr *) expr;
-                               Node       *temp;
-
-                               /* what if att.attrs == "*"?? */
-                               temp = handleNestedDots(pstate, att, &pstate->p_last_resno);
-                               if (att->indirection != NIL)
-                               {
-                                       List       *idx = att->indirection;
-
-                                       while (idx != NIL)
-                                       {
-                                               A_Indices  *ai = (A_Indices *) lfirst(idx);
-                                               Node       *lexpr = NULL,
-                                                                  *uexpr;
-
-                                               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, precedence);
-                                                       if (exprType(lexpr) != INT4OID)
-                                                               elog(WARN, "array index expressions must be int4's");
-                                               }
-#if 0
-                                               pfree(ai->uidx);
-                                               if (ai->lidx != NULL)
-                                                       pfree(ai->lidx);
-#endif
-                                               ai->lidx = lexpr;
-                                               ai->uidx = uexpr;
-
-                                               /*
-                                                * note we reuse the list of indices, make sure we
-                                                * don't free them! Otherwise, make a new list
-                                                * here
-                                                */
-                                               idx = lnext(idx);
-                                       }
-                                       result = (Node *) make_array_ref(temp, att->indirection);
-                               }
-                               else
-                               {
-                                       result = temp;
-                               }
-                               break;
-                       }
-               case T_A_Const:
-                       {
-                               A_Const    *con = (A_Const *) expr;
-                               Value      *val = &con->val;
-
-                               if (con->typename != NULL)
-                               {
-                                       result = parser_typecast(val, con->typename, -1);
-                               }
-                               else
-                               {
-                                       result = (Node *) make_const(val);
-                               }
-                               break;
-                       }
-               case T_ParamNo:
-                       {
-                               ParamNo    *pno = (ParamNo *) expr;
-                               Oid                     toid;
-                               int                     paramno;
-                               Param      *param;
-
-                               paramno = pno->number;
-                               toid = param_type(paramno);
-                               if (!OidIsValid(toid))
-                               {
-                                       elog(WARN, "Parameter '$%d' is out of range",
-                                                paramno);
-                               }
-                               param = makeNode(Param);
-                               param->paramkind = PARAM_NUM;
-                               param->paramid = (AttrNumber) paramno;
-                               param->paramname = "<unnamed>";
-                               param->paramtype = (Oid) toid;
-                               param->param_tlist = (List *) NULL;
-
-                               result = (Node *) param;
-                               break;
-                       }
-               case T_A_Expr:
-                       {
-                               A_Expr     *a = (A_Expr *) expr;
-
-                               switch (a->oper)
-                               {
-                                       case OP:
-                                               {
-                                                       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, precedence);
-
-                                                       result = ParseFunc(pstate,
-                                                                                 "nullvalue", lcons(lexpr, NIL),
-                                                                                          &pstate->p_last_resno);
-                                               }
-                                               break;
-                                       case NOTNULL:
-                                               {
-                                                       Node       *lexpr = transformExpr(pstate, a->lexpr, precedence);
-
-                                                       result = ParseFunc(pstate,
-                                                                          "nonnullvalue", lcons(lexpr, NIL),
-                                                                                          &pstate->p_last_resno);
-                                               }
-                                               break;
-                                       case AND:
-                                               {
-                                                       Expr       *expr = makeNode(Expr);
-                                                       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",
-                                                                        tname(get_id_type(exprType(lexpr))));
-                                                       if (exprType(rexpr) != BOOLOID)
-                                                               elog(WARN,
-                                                                        "right-hand side of AND is type '%s', not bool",
-                                                                        tname(get_id_type(exprType(rexpr))));
-                                                       expr->typeOid = BOOLOID;
-                                                       expr->opType = AND_EXPR;
-                                                       expr->args = makeList(lexpr, rexpr, -1);
-                                                       result = (Node *) expr;
-                                               }
-                                               break;
-                                       case OR:
-                                               {
-                                                       Expr       *expr = makeNode(Expr);
-                                                       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",
-                                                                        tname(get_id_type(exprType(lexpr))));
-                                                       if (exprType(rexpr) != BOOLOID)
-                                                               elog(WARN,
-                                                                        "right-hand side of OR is type '%s', not bool",
-                                                                        tname(get_id_type(exprType(rexpr))));
-                                                       expr->typeOid = BOOLOID;
-                                                       expr->opType = OR_EXPR;
-                                                       expr->args = makeList(lexpr, rexpr, -1);
-                                                       result = (Node *) expr;
-                                               }
-                                               break;
-                                       case NOT:
-                                               {
-                                                       Expr       *expr = makeNode(Expr);
-                                                       Node       *rexpr = transformExpr(pstate, a->rexpr, precedence);
-
-                                                       if (exprType(rexpr) != BOOLOID)
-                                                               elog(WARN,
-                                                               "argument to NOT is type '%s', not bool",
-                                                                        tname(get_id_type(exprType(rexpr))));
-                                                       expr->typeOid = BOOLOID;
-                                                       expr->opType = NOT_EXPR;
-                                                       expr->args = makeList(rexpr, -1);
-                                                       result = (Node *) expr;
-                                               }
-                                               break;
-                               }
-                               break;
-                       }
-               case T_Ident:
-                       {
-
-                               /*
-                                * look for a column name or a relation name (the default
-                                * behavior)
-                                */
-                               result = transformIdent(pstate, expr, precedence);
-                               break;
-                       }
-               case T_FuncCall:
-                       {
-                               FuncCall   *fn = (FuncCall *) expr;
-                               List       *args;
-
-                               /* transform the list of arguments */
-                               foreach(args, fn->args)
-                                       lfirst(args) = transformExpr(pstate, (Node *) lfirst(args), precedence);
-                               result = ParseFunc(pstate,
-                                                 fn->funcname, fn->args, &pstate->p_last_resno);
-                               break;
-                       }
-               default:
-                       /* should not reach here */
-                       elog(WARN, "transformExpr: does not know how to transform %d\n",
-                                nodeTag(expr));
-                       break;
-       }
-
-       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
- *
- *****************************************************************************/
-
-/*
- * parseFromClause -
- *       turns the table references specified in the from-clause into a
- *       range table. The range table may grow as we transform the expressions
- *       in the target list. (Note that this happens because in POSTQUEL, we
- *       allow references to relations not specified in the from-clause. We
- *       also allow that in our POST-SQL)
- *
- */
-static void
-parseFromClause(ParseState *pstate, List *frmList)
-{
-       List       *fl;
-
-       foreach(fl, frmList)
-       {
-               RangeVar   *r = lfirst(fl);
-               RelExpr    *baserel = r->relExpr;
-               char       *relname = baserel->relname;
-               char       *refname = r->name;
-               RangeTblEntry *rte;
-
-               if (refname == NULL)
-                       refname = relname;
-
-               /*
-                * marks this entry to indicate it comes from the FROM clause. In
-                * SQL, the target list can only refer to range variables
-                * specified in the from clause but we follow the more powerful
-                * POSTQUEL semantics and automatically generate the range
-                * variable if not specified. However there are times we need to
-                * know whether the entries are legitimate.
-                *
-                * eg. select * from foo f where f.x = 1; will generate wrong answer
-                * if we expand * to foo.x.
-                */
-               rte = addRangeTableEntry(pstate, relname, refname, baserel->inh, TRUE);
-       }
-}
-
-/*
- * makeRangeTable -
- *       make a range table with the specified relation (optional) and the
- *       from-clause.
- */
-static void
-makeRangeTable(ParseState *pstate, char *relname, List *frmList)
-{
-       RangeTblEntry *rte;
-
-       parseFromClause(pstate, frmList);
-
-       if (relname == NULL)
-               return;
-
-       if (refnameRangeTablePosn(pstate->p_rtable, relname) < 1)
-               rte = addRangeTableEntry(pstate, relname, relname, FALSE, FALSE);
-       else
-               rte = refnameRangeTableEntry(pstate->p_rtable, relname);
-
-       pstate->p_target_rangetblentry = rte;
-       Assert(pstate->p_target_relation == NULL);
-       pstate->p_target_relation = heap_open(rte->relid);
-       Assert(pstate->p_target_relation != NULL);
-       /* will close relation later */
-}
-
-/*
- *     exprType -
- *       returns the Oid of the type of the expression. (Used for typechecking.)
- */
-Oid
-exprType(Node *expr)
-{
-       Oid                     type = (Oid) 0;
-
-       switch (nodeTag(expr))
-       {
-               case T_Func:
-                       type = ((Func *) expr)->functype;
-                       break;
-               case T_Iter:
-                       type = ((Iter *) expr)->itertype;
-                       break;
-               case T_Var:
-                       type = ((Var *) expr)->vartype;
-                       break;
-               case T_Expr:
-                       type = ((Expr *) expr)->typeOid;
-                       break;
-               case T_Const:
-                       type = ((Const *) expr)->consttype;
-                       break;
-               case T_ArrayRef:
-                       type = ((ArrayRef *) expr)->refelemtype;
-                       break;
-               case T_Aggreg:
-                       type = ((Aggreg *) expr)->aggtype;
-                       break;
-               case T_Param:
-                       type = ((Param *) expr)->paramtype;
-                       break;
-               case T_Ident:
-                       /* is this right? */
-                       type = UNKNOWNOID;
-                       break;
-               default:
-                       elog(WARN, "exprType: don't know how to get type for %d node",
-                                nodeTag(expr));
-                       break;
-       }
-       return type;
-}
-
-/*
- * expandAllTables -
- *       turns '*' (in the target list) into a list of attributes
- *        (of all relations in the range table)
- */
-static List *
-expandAllTables(ParseState *pstate)
-{
-       List       *target = NIL;
-       List       *legit_rtable = NIL;
-       List       *rt,
-                          *rtable;
-
-       rtable = pstate->p_rtable;
-       if (pstate->p_is_rule)
-       {
-
-               /*
-                * skip first two entries, "*new*" and "*current*"
-                */
-               rtable = lnext(lnext(pstate->p_rtable));
-       }
-
-       /* this should not happen */
-       if (rtable == NULL)
-               elog(WARN, "cannot expand: null p_rtable");
-
-       /*
-        * go through the range table and make a list of range table entries
-        * which we will expand.
-        */
-       foreach(rt, rtable)
-       {
-               RangeTblEntry *rte = lfirst(rt);
-
-               /*
-                * we only expand those specify in the from clause. (This will
-                * also prevent us from using the wrong table in inserts: eg.
-                * tenk2 in "insert into tenk2 select * from tenk1;")
-                */
-               if (!rte->inFromCl)
-                       continue;
-               legit_rtable = lappend(legit_rtable, rte);
-       }
-
-       foreach(rt, legit_rtable)
-       {
-               RangeTblEntry *rte = lfirst(rt);
-               List       *temp = target;
-
-               if (temp == NIL)
-                       target = expandAll(pstate, rte->relname, rte->refname,
-                                                          &pstate->p_last_resno);
-               else
-               {
-                       while (temp != NIL && lnext(temp) != NIL)
-                               temp = lnext(temp);
-                       lnext(temp) = expandAll(pstate, rte->relname, rte->refname,
-                                                                       &pstate->p_last_resno);
-               }
-       }
-       return target;
-}
-
-
-/*
- * figureColname -
- *       if the name of the resulting column is not specified in the target
- *       list, we have to guess.
- *
- */
-static char *
-figureColname(Node *expr, Node *resval)
-{
-       switch (nodeTag(expr))
-       {
-                       case T_Aggreg:
-                       return (char *)         /* XXX */
-                       ((Aggreg *) expr)->aggname;
-               case T_Expr:
-                       if (((Expr *) expr)->opType == FUNC_EXPR)
-                       {
-                               if (nodeTag(resval) == T_FuncCall)
-                                       return ((FuncCall *) resval)->funcname;
-                       }
-                       break;
-               default:
-                       break;
-       }
-
-       return "?column?";
-}
-
-/*****************************************************************************
- *
- * Target list
- *
- *****************************************************************************/
-
-/*
- * makeTargetNames -
- *       generate a list of column names if not supplied or
- *       test supplied column names to make sure they are in target table
- *       (used exclusively for inserts)
- */
-static List *
-makeTargetNames(ParseState *pstate, List *cols)
-{
-       List       *tl = NULL;
-
-       /* Generate ResTarget if not supplied */
-
-       if (cols == NIL)
-       {
-               int                     numcol;
-               int                     i;
-               AttributeTupleForm *attr = pstate->p_target_relation->rd_att->attrs;
-
-               numcol = pstate->p_target_relation->rd_rel->relnatts;
-               for (i = 0; i < numcol; i++)
-               {
-                       Ident      *id = makeNode(Ident);
-
-                       id->name = palloc(NAMEDATALEN);
-                       StrNCpy(id->name, attr[i]->attname.data, NAMEDATALEN);
-                       id->indirection = NIL;
-                       id->isRel = false;
-                       if (tl == NIL)
-                               cols = tl = lcons(id, NIL);
-                       else
-                       {
-                               lnext(tl) = lcons(id, NIL);
-                               tl = lnext(tl);
-                       }
-               }
-       }
-       else
-       {
-               foreach(tl, cols)
-               {
-                       List       *nxt;
-                       char       *name = ((Ident *) lfirst(tl))->name;
-               
-                       /* elog on failure */
-                       varattno(pstate->p_target_relation, name);
-                       foreach(nxt, lnext(tl))
-                               if (!strcmp(name, ((Ident *) lfirst(nxt))->name))
-                                       elog (WARN, "Attribute '%s' should be specified only once", name);
-               }
-       }
-       
-       return cols;
-}
-
-/*
- * transformTargetList -
- *       turns a list of ResTarget's into a list of TargetEntry's
- */
-static 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 = makeNode(TargetEntry);
-
-               switch (nodeTag(res->val))
-               {
-                       case T_Ident:
-                               {
-                                       Node       *expr;
-                                       Oid                     type_id;
-                                       int                     type_len;
-                                       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);
-                                       type_len = tlen(get_id_type(type_id));
-                                       resname = (res->name) ? res->name : identname;
-                                       tent->resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
-                                                                                         (Oid) type_id,
-                                                                                         (Size) type_len,
-                                                                                         resname,
-                                                                                         (Index) 0,
-                                                                                         (Oid) 0,
-                                                                                         0);
-
-                                       tent->expr = expr;
-                                       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);
-
-                                       handleTargetColname(pstate, &res->name, NULL, NULL);
-                                       /* note indirection has not been transformed */
-                                       if (pstate->p_is_insert && res->indirection != NIL)
-                                       {
-                                               /* this is an array assignment */
-                                               char       *val;
-                                               char       *str,
-                                                                  *save_str;
-                                               List       *elt;
-                                               int                     i = 0,
-                                                                       ndims;
-                                               int                     lindx[MAXDIM],
-                                                                       uindx[MAXDIM];
-                                               int                     resdomno;
-                                               Relation        rd;
-                                               Value      *constval;
-
-                                               if (exprType(expr) != UNKNOWNOID ||
-                                                       !IsA(expr, Const))
-                                                       elog(WARN, "yyparse: string constant expected");
-
-                                               val = (char *) textout((struct varlena *)
-                                                                                  ((Const *) expr)->constvalue);
-                                               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, 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, EXPR_COLUMN_FIRST);
-                                                               if (!IsA(aind->lidx, Const))
-                                                                       elog(WARN,
-                                                                                "Array Index for Append should be a constant");
-                                                               lindx[i] = ((Const *) aind->lidx)->constvalue;
-                                                       }
-                                                       else
-                                                       {
-                                                               lindx[i] = 1;
-                                                       }
-                                                       if (lindx[i] > uindx[i])
-                                                               elog(WARN, "yyparse: lower index cannot be greater than upper index");
-                                                       sprintf(str, "[%d:%d]", lindx[i], uindx[i]);
-                                                       str += strlen(str);
-                                                       i++;
-                                               }
-                                               sprintf(str, "=%s", val);
-                                               rd = pstate->p_target_relation;
-                                               Assert(rd != NULL);
-                                               resdomno = varattno(rd, res->name);
-                                               ndims = att_attnelems(rd, resdomno);
-                                               if (i != ndims)
-                                                       elog(WARN, "yyparse: array dimensions do not match");
-                                               constval = makeNode(Value);
-                                               constval->type = T_String;
-                                               constval->val.str = save_str;
-                                               tent = make_targetlist_expr(pstate, res->name,
-                                                                                  (Node *) make_const(constval),
-                                                                                                       NULL);
-                                               pfree(save_str);
-                                       }
-                                       else
-                                       {
-                                               char       *colname = res->name;
-
-                                               /* this is not an array assignment */
-                                               if (colname == NULL)
-                                               {
-
-                                                       /*
-                                                        * if you're wondering why this is here, look
-                                                        * at the yacc grammar for why a name can be
-                                                        * missing. -ay
-                                                        */
-                                                       colname = figureColname(expr, res->val);
-                                               }
-                                               if (res->indirection)
-                                               {
-                                                       List       *ilist = res->indirection;
-
-                                                       while (ilist != NIL)
-                                                       {
-                                                               A_Indices  *ind = lfirst(ilist);
-
-                                                               ind->lidx = transformExpr(pstate, ind->lidx, EXPR_COLUMN_FIRST);
-                                                               ind->uidx = transformExpr(pstate, ind->uidx, EXPR_COLUMN_FIRST);
-                                                               ilist = lnext(ilist);
-                                                       }
-                                               }
-                                               res->name = colname;
-                                               tent = make_targetlist_expr(pstate, res->name, expr,
-                                                                                                       res->indirection);
-                                       }
-                                       break;
-                               }
-                       case T_Attr:
-                               {
-                                       Oid                     type_id;
-                                       int                     type_len;
-                                       Attr       *att = (Attr *) res->val;
-                                       Node       *result;
-                                       char       *attrname;
-                                       char       *resname;
-                                       Resdom     *resnode;
-                                       List       *attrs = att->attrs;
-
-                                       /*
-                                        * 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));
-                                       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.
-                                        * relation.attribute
-                                        */
-                                       result = handleNestedDots(pstate, att, &pstate->p_last_resno);
-                                       handleTargetColname(pstate, &res->name, att->relname, attrname);
-                                       if (att->indirection != NIL)
-                                       {
-                                               List       *ilist = att->indirection;
-
-                                               while (ilist != NIL)
-                                               {
-                                                       A_Indices  *ind = lfirst(ilist);
-
-                                                       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);
-                                       }
-                                       type_id = exprType(result);
-                                       type_len = tlen(get_id_type(type_id));
-                                       /* move to last entry */
-                                       while (lnext(attrs) != NIL)
-                                               attrs = lnext(attrs);
-                                       resname = (res->name) ? res->name : strVal(lfirst(attrs));
-                                       resnode = makeResdom((AttrNumber) pstate->p_last_resno++,
-                                                                                (Oid) type_id,
-                                                                                (Size) type_len,
-                                                                                resname,
-                                                                                (Index) 0,
-                                                                                (Oid) 0,
-                                                                                0);
-                                       tent->resdom = resnode;
-                                       tent->expr = result;
-                                       break;
-                               }
-                       default:
-                               /* internal error */
-                               elog(WARN,
-                                        "internal error: do not know how to transform targetlist");
-                               break;
-               }
-
-               if (p_target == NIL)
-               {
-                       p_target = tail_p_target = lcons(tent, NIL);
-               }
-               else
-               {
-                       lnext(tail_p_target) = lcons(tent, NIL);
-                       tail_p_target = lnext(tail_p_target);
-               }
-               targetlist = lnext(targetlist);
-       }
-
-       return p_target;
-}
-
-
-/*
- * make_targetlist_expr -
- *       make a TargetEntry from an expression
- *
- * arrayRef is a list of transformed A_Indices
- */
-static TargetEntry *
-make_targetlist_expr(ParseState *pstate,
-                                        char *colname,
-                                        Node *expr,
-                                        List *arrayRef)
-{
-       Oid                     type_id,
-                               attrtype;
-       int                     type_len,
-                               attrlen;
-       int                     resdomno;
-       Relation        rd;
-       bool            attrisset;
-       TargetEntry *tent;
-       Resdom     *resnode;
-
-       if (expr == NULL)
-               elog(WARN, "make_targetlist_expr: invalid use of NULL expression");
-
-       type_id = exprType(expr);
-       if (type_id == InvalidOid)
-       {
-               type_len = 0;
-       }
-       else
-               type_len = tlen(get_id_type(type_id));
-
-       /* I have no idea what the following does! */
-       /* It appears to process target columns that will be receiving results */
-       if (pstate->p_is_insert || pstate->p_is_update)
-       {
-
-               /*
-                * append or replace query -- append, replace work only on one
-                * relation, so multiple occurence of same resdomno is bogus
-                */
-               rd = pstate->p_target_relation;
-               Assert(rd != NULL);
-               resdomno = varattno(rd, colname);
-               attrisset = varisset(rd, colname);
-               attrtype = att_typeid(rd, resdomno);
-               if ((arrayRef != NIL) && (lfirst(arrayRef) == NIL))
-                       attrtype = GetArrayElementType(attrtype);
-               if (attrtype == BPCHAROID || attrtype == VARCHAROID)
-               {
-                       attrlen = rd->rd_att->attrs[resdomno - 1]->attlen;
-               }
-               else
-               {
-                       attrlen = tlen(get_id_type(attrtype));
-               }
-#if 0
-               if (Input_is_string && Typecast_ok)
-               {
-                       Datum           val;
-
-                       if (type_id == typeid(type("unknown")))
-                       {
-                               val = (Datum) textout((struct varlena *)
-                                                                         ((Const) lnext(expr))->constvalue);
-                       }
-                       else
-                       {
-                               val = ((Const) lnext(expr))->constvalue;
-                       }
-                       if (attrisset)
-                       {
-                               lnext(expr) = makeConst(attrtype,
-                                                                               attrlen,
-                                                                               val,
-                                                                               false,
-                                                                               true,
-                                                                               true,   /* is set */
-                                                                               false);
-                       }
-                       else
-                       {
-                               lnext(expr) =
-                                       makeConst(attrtype,
-                                                         attrlen,
-                                                         (Datum) fmgr(typeid_get_retinfunc(attrtype),
-                                                                                val, get_typelem(attrtype), -1),
-                                                         false,
-                                                         true /* Maybe correct-- 80% chance */ ,
-                                                         false,        /* is not a set */
-                                                         false);
-                       }
-               }
-               else if ((Typecast_ok) && (attrtype != type_id))
-               {
-                       lnext(expr) =
-                               parser_typecast2(expr, get_id_type(attrtype));
-               }
-               else if (attrtype != type_id)
-               {
-                       if ((attrtype == INT2OID) && (type_id == INT4OID))
-                               lfirst(expr) = lispInteger(INT2OID);    /* handle CASHOID too */
-                       else if ((attrtype == FLOAT4OID) && (type_id == FLOAT8OID))
-                               lfirst(expr) = lispInteger(FLOAT4OID);
-                       else
-                               elog(WARN, "unequal type in tlist : %s \n", colname);
-               }
-
-               Input_is_string = false;
-               Input_is_integer = false;
-               Typecast_ok = true;
-#endif
-
-               if (attrtype != type_id)
-               {
-                       if (IsA(expr, Const))
-                       {
-                               /* try to cast the constant */
-                               if (arrayRef && !(((A_Indices *) lfirst(arrayRef))->lidx))
-                               {
-                                       /* updating a single item */
-                                       Oid                     typelem = get_typelem(attrtype);
-
-                                       expr = (Node *) parser_typecast2(expr,
-                                                                                                        type_id,
-                                                                                                        get_id_type(typelem),
-                                                                                                        attrlen);
-                               }
-                               else
-                                       expr = (Node *) parser_typecast2(expr,
-                                                                                                        type_id,
-                                                                                                  get_id_type(attrtype),
-                                                                                                        attrlen);
-                       }
-                       else
-                       {
-                               /* currently, we can't handle casting of expressions */
-                               elog(WARN, "parser: attribute '%s' is of type '%s' but expression is of type '%s'",
-                                        colname,
-                                        get_id_typname(attrtype),
-                                        get_id_typname(type_id));
-                       }
-               }
-
-               if (arrayRef != NIL)
-               {
-                       Expr       *target_expr;
-                       Attr       *att = makeNode(Attr);
-                       List       *ar = arrayRef;
-                       List       *upperIndexpr = NIL;
-                       List       *lowerIndexpr = NIL;
-
-                       att->relname = pstrdup(RelationGetRelationName(rd)->data);
-                       att->attrs = lcons(makeString(colname), NIL);
-                       target_expr = (Expr *) handleNestedDots(pstate, att,
-                                                                                                 &pstate->p_last_resno);
-                       while (ar != NIL)
-                       {
-                               A_Indices  *ind = lfirst(ar);
-
-                               if (lowerIndexpr || (!upperIndexpr && ind->lidx))
-                               {
-
-                                       /*
-                                        * XXX assume all lowerIndexpr is non-null in this
-                                        * case
-                                        */
-                                       lowerIndexpr = lappend(lowerIndexpr, ind->lidx);
-                               }
-                               upperIndexpr = lappend(upperIndexpr, ind->uidx);
-                               ar = lnext(ar);
-                       }
-
-                       expr = (Node *) make_array_set(target_expr,
-                                                                                  upperIndexpr,
-                                                                                  lowerIndexpr,
-                                                                                  (Expr *) expr);
-                       attrtype = att_typeid(rd, resdomno);
-                       attrlen = tlen(get_id_type(attrtype));
-               }
-       }
-       else
-       {
-               resdomno = pstate->p_last_resno++;
-               attrtype = type_id;
-               attrlen = type_len;
-       }
-       tent = makeNode(TargetEntry);
-
-       resnode = makeResdom((AttrNumber) resdomno,
-                                                (Oid) attrtype,
-                                                (Size) attrlen,
-                                                colname,
-                                                (Index) 0,
-                                                (Oid) 0,
-                                                0);
-
-       tent->resdom = resnode;
-       tent->expr = expr;
-
-       return tent;
-}
-
-
-/*****************************************************************************
- *
- * Where Clause
- *
- *****************************************************************************/
-
-/*
- * transformWhereClause -
- *       transforms the qualification and make sure it is of type Boolean
- *
- */
-static Node *
-transformWhereClause(ParseState *pstate, Node *a_expr)
-{
-       Node       *qual;
-
-       if (a_expr == NULL)
-               return (Node *) NULL;   /* no qualifiers */
-
-       inWhereClause = true;
-       qual = transformExpr(pstate, a_expr, EXPR_COLUMN_FIRST);
-       inWhereClause = false;
-       if (exprType(qual) != BOOLOID)
-       {
-               elog(WARN,
-                        "where clause must return type bool, not %s",
-                        tname(get_id_type(exprType(qual))));
-       }
-       return qual;
-}
-
-/*****************************************************************************
- *
- * Sort Clause
- *
- *****************************************************************************/
-
-/*
- *     find_targetlist_entry -
- *       returns the Resdom in the target list matching the specified varname
- *       and range
- *
- */
-static TargetEntry *
-find_targetlist_entry(ParseState *pstate, SortGroupBy *sortgroupby, List *tlist)
-{
-       List       *i;
-       int                     real_rtable_pos = 0,
-                               target_pos = 0;
-       TargetEntry *target_result = NULL;
-
-       if (sortgroupby->range)
-               real_rtable_pos = refnameRangeTablePosn(pstate->p_rtable,
-                                                                                               sortgroupby->range);
-
-       foreach(i, tlist)
-       {
-               TargetEntry *target = (TargetEntry *) lfirst(i);
-               Resdom     *resnode = target->resdom;
-               Var                *var = (Var *) target->expr;
-               char       *resname = resnode->resname;
-               int                     test_rtable_pos = var->varno;
-
-#ifdef PARSEDEBUG
-               printf("find_targetlist_entry- target name is %s, position %d, resno %d\n",
-                          (sortgroupby->name ? sortgroupby->name : "(null)"), target_pos + 1, sortgroupby->resno);
-#endif
-
-               if (!sortgroupby->name)
-               {
-                       if (sortgroupby->resno == ++target_pos)
-                       {
-                               target_result = target;
-                               break;
-                       }
-               }
-               else
-               {
-                       if (!strcmp(resname, sortgroupby->name))
-                       {
-                               if (sortgroupby->range)
-                               {
-                                       if (real_rtable_pos == test_rtable_pos)
-                                       {
-                                               if (target_result != NULL)
-                                                       elog(WARN, "Order/Group By '%s' is ambiguous", sortgroupby->name);
-                                               else
-                                                       target_result = target;
-                                       }
-                               }
-                               else
-                               {
-                                       if (target_result != NULL)
-                                               elog(WARN, "Order/Group By '%s' is ambiguous", sortgroupby->name);
-                                       else
-                                               target_result = target;
-                               }
-                       }
-               }
-       }
-       return target_result;
-}
-
-static Oid
-any_ordering_op(int restype)
-{
-       Operator        order_op;
-       Oid                     order_opid;
-
-       order_op = oper("<", restype, restype, false);
-       order_opid = oprid(order_op);
-
-       return order_opid;
-}
-
-/*
- * transformGroupClause -
- *       transform a Group By clause
- *
- */
-static List *
-transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist)
-{
-       List       *glist = NIL,
-                          *gl = NIL;
-
-       while (grouplist != NIL)
-       {
-               GroupClause *grpcl = makeNode(GroupClause);
-               TargetEntry *restarget;
-               Resdom     *resdom;
-
-               restarget = find_targetlist_entry(pstate, lfirst(grouplist), targetlist);
-
-               if (restarget == NULL)
-                       elog(WARN, "The field being grouped by must appear in the target list");
-
-               grpcl->entry = restarget;
-               resdom = restarget->resdom;
-               grpcl->grpOpoid = oprid(oper("<",
-                                                                        resdom->restype,
-                                                                        resdom->restype, false));
-               if (glist == NIL)
-                       gl = glist = lcons(grpcl, NIL);
-               else
-               {
-                       List       *i;
-                       
-                       foreach (i, glist)
-                       {
-                               GroupClause *gcl = (GroupClause *) lfirst (i);
-                               
-                               if ( gcl->entry == grpcl->entry )
-                                       break;
-                       }
-                       if ( i == NIL )                 /* not in grouplist already */
-                       {
-                               lnext(gl) = lcons(grpcl, NIL);
-                               gl = lnext(gl);
-                       }
-                       else
-                               pfree (grpcl);          /* get rid of this */
-               }
-               grouplist = lnext(grouplist);
-       }
-
-       return glist;
-}
-
-/*
- * transformSortClause -
- *       transform an Order By clause
- *
- */
-static List *
-transformSortClause(ParseState *pstate,
-                                       List *orderlist, List *targetlist,
-                                       char *uniqueFlag)
-{
-       List       *sortlist = NIL;
-       List       *s = NIL;
-
-       while (orderlist != NIL)
-       {
-               SortGroupBy *sortby = lfirst(orderlist);
-               SortClause *sortcl = makeNode(SortClause);
-               TargetEntry *restarget;
-               Resdom     *resdom;
-
-               restarget = find_targetlist_entry(pstate, sortby, targetlist);
-               if (restarget == NULL)
-                       elog(WARN, "The field being ordered by must appear in the target list");
-
-               sortcl->resdom = resdom = restarget->resdom;
-               sortcl->opoid = oprid(oper(sortby->useOp,
-                                                                  resdom->restype,
-                                                                  resdom->restype, false));
-               if (sortlist == NIL)
-               {
-                       s = sortlist = lcons(sortcl, NIL);
-               }
-               else
-               {
-                       List       *i;
-                       
-                       foreach (i, sortlist)
-                       {
-                               SortClause *scl = (SortClause *) lfirst (i);
-                               
-                               if ( scl->resdom == sortcl->resdom )
-                                       break;
-                       }
-                       if ( i == NIL )                 /* not in sortlist already */
-                       {
-                               lnext(s) = lcons(sortcl, NIL);
-                               s = lnext(s);
-                       }
-                       else
-                               pfree (sortcl);         /* get rid of this */
-               }
-               orderlist = lnext(orderlist);
-       }
-
-       if (uniqueFlag)
-       {
-               List       *i;
-               
-               if (uniqueFlag[0] == '*')
-               {
-
-                       /*
-                        * concatenate all elements from target list that are not
-                        * already in the sortby list
-                        */
-                       foreach(i, targetlist)
-                       {
-                               TargetEntry *tlelt = (TargetEntry *) lfirst(i);
-
-                               s = sortlist;
-                               while (s != NIL)
-                               {
-                                       SortClause *sortcl = lfirst(s);
-
-                                       if (sortcl->resdom == tlelt->resdom)
-                                               break;
-                                       s = lnext(s);
-                               }
-                               if (s == NIL)
-                               {
-                                       /* not a member of the sortclauses yet */
-                                       SortClause *sortcl = makeNode(SortClause);
-
-                                       sortcl->resdom = tlelt->resdom;
-                                       sortcl->opoid = any_ordering_op(tlelt->resdom->restype);
-
-                                       sortlist = lappend(sortlist, sortcl);
-                               }
-                       }
-               }
-               else
-               {
-                       TargetEntry *tlelt = NULL;
-                       char       *uniqueAttrName = uniqueFlag;
-
-                       /* only create sort clause with the specified unique attribute */
-                       foreach(i, targetlist)
-                       {
-                               tlelt = (TargetEntry *) lfirst(i);
-                               if (strcmp(tlelt->resdom->resname, uniqueAttrName) == 0)
-                                       break;
-                       }
-                       if (i == NIL)
-                       {
-                               elog(WARN, "The field specified in the UNIQUE ON clause is not in the targetlist");
-                       }
-                       s = sortlist;
-                       foreach(s, sortlist)
-                       {
-                               SortClause *sortcl = lfirst(s);
-
-                               if (sortcl->resdom == tlelt->resdom)
-                                       break;
-                       }
-                       if (s == NIL)
-                       {
-                               /* not a member of the sortclauses yet */
-                               SortClause *sortcl = makeNode(SortClause);
-
-                               sortcl->resdom = tlelt->resdom;
-                               sortcl->opoid = any_ordering_op(tlelt->resdom->restype);
-
-                               sortlist = lappend(sortlist, sortcl);
-                       }
-               }
-
-       }
-
-       return sortlist;
-}
-
-/*
- ** HandleNestedDots --
- **    Given a nested dot expression (i.e. (relation func ... attr), build up
- ** a tree with of Iter and Func nodes.
- */
-static Node *
-handleNestedDots(ParseState *pstate, Attr *attr, int *curr_resno)
-{
-       List       *mutator_iter;
-       Node       *retval = NULL;
-
-       if (attr->paramNo != NULL)
-       {
-               Param      *param = (Param *) transformExpr(pstate, (Node *) attr->paramNo, EXPR_RELATION_FIRST);
-
-               retval =
-                       ParseFunc(pstate, strVal(lfirst(attr->attrs)),
-                                         lcons(param, NIL),
-                                         curr_resno);
-       }
-       else
-       {
-               Ident      *ident = makeNode(Ident);
-
-               ident->name = attr->relname;
-               ident->isRel = TRUE;
-               retval =
-                       ParseFunc(pstate, strVal(lfirst(attr->attrs)),
-                                         lcons(ident, NIL),
-                                         curr_resno);
-       }
-
-       foreach(mutator_iter, lnext(attr->attrs))
-       {
-               retval = ParseFunc(pstate, strVal(lfirst(mutator_iter)),
-                                                  lcons(retval, NIL),
-                                                  curr_resno);
-       }
-
-       return (retval);
-}
-
-/*
- ** make_arguments --
- **   Given the number and types of arguments to a function, and the
- **   actual arguments and argument types, do the necessary typecasting.
- */
-static void
-make_arguments(int nargs,
-                          List *fargs,
-                          Oid *input_typeids,
-                          Oid *function_typeids)
-{
-
-       /*
-        * there are two ways an input typeid can differ from a function
-        * typeid : either the input type inherits the function type, so no
-        * typecasting is necessary, or the input type can be typecast into
-        * the function type. right now, we only typecast unknowns, and that
-        * is all we check for.
-        */
-
-       List       *current_fargs;
-       int                     i;
-
-       for (i = 0, current_fargs = fargs;
-                i < nargs;
-                i++, current_fargs = lnext(current_fargs))
-       {
-
-               if (input_typeids[i] == UNKNOWNOID && function_typeids[i] != InvalidOid)
-               {
-                       lfirst(current_fargs) =
-                               parser_typecast2(lfirst(current_fargs),
-                                                                input_typeids[i],
-                                                                get_id_type(function_typeids[i]),
-                                                                -1);
-               }
-       }
-}
-
-/*
- ** setup_tlist --
- **            Build a tlist that says which attribute to project to.
- **            This routine is called by ParseFunc() to set up a target list
- **            on a tuple parameter or return value.  Due to a bug in 4.0,
- **            it's not possible to refer to system attributes in this case.
- */
-static List *
-setup_tlist(char *attname, Oid relid)
-{
-       TargetEntry *tle;
-       Resdom     *resnode;
-       Var                *varnode;
-       Oid                     typeid;
-       int                     attno;
-
-       attno = get_attnum(relid, attname);
-       if (attno < 0)
-               elog(WARN, "cannot reference attribute '%s' of tuple params/return values for functions", attname);
-
-       typeid = find_atttype(relid, attname);
-       resnode = makeResdom(1,
-                                                typeid,
-                                                tlen(get_id_type(typeid)),
-                                                get_attname(relid, attno),
-                                                0,
-                                                (Oid) 0,
-                                                0);
-       varnode = makeVar(-1, attno, typeid, -1, attno);
-
-       tle = makeNode(TargetEntry);
-       tle->resdom = resnode;
-       tle->expr = (Node *) varnode;
-       return (lcons(tle, NIL));
-}
-
-/*
- ** setup_base_tlist --
- **            Build a tlist that extracts a base type from the tuple
- **            returned by the executor.
- */
-static List *
-setup_base_tlist(Oid typeid)
-{
-       TargetEntry *tle;
-       Resdom     *resnode;
-       Var                *varnode;
-
-       resnode = makeResdom(1,
-                                                typeid,
-                                                tlen(get_id_type(typeid)),
-                                                "<noname>",
-                                                0,
-                                                (Oid) 0,
-                                                0);
-       varnode = makeVar(-1, 1, typeid, -1, 1);
-       tle = makeNode(TargetEntry);
-       tle->resdom = resnode;
-       tle->expr = (Node *) varnode;
-
-       return (lcons(tle, NIL));
-}
-
-/*
- * ParseComplexProjection -
- *       handles function calls with a single argument that is of complex type.
- *       This routine returns NULL if it can't handle the projection (eg. sets).
- */
-static Node *
-ParseComplexProjection(ParseState *pstate,
-                                          char *funcname,
-                                          Node *first_arg,
-                                          bool *attisset)
-{
-       Oid                     argtype;
-       Oid                     argrelid;
-       Name            relname;
-       Relation        rd;
-       Oid                     relid;
-       int                     attnum;
-
-       switch (nodeTag(first_arg))
-       {
-               case T_Iter:
-                       {
-                               Func       *func;
-                               Iter       *iter;
-
-                               iter = (Iter *) first_arg;
-                               func = (Func *) ((Expr *) iter->iterexpr)->oper;
-                               argtype = funcid_get_rettype(func->funcid);
-                               argrelid = typeid_get_relid(argtype);
-                               if (argrelid &&
-                                       ((attnum = get_attnum(argrelid, funcname))
-                                        != InvalidAttrNumber))
-                               {
-
-                                       /*
-                                        * the argument is a function returning a tuple, so
-                                        * funcname may be a projection
-                                        */
-
-                                       /* add a tlist to the func node and return the Iter */
-                                       rd = heap_openr(tname(get_id_type(argtype)));
-                                       if (RelationIsValid(rd))
-                                       {
-                                               relid = RelationGetRelationId(rd);
-                                               relname = RelationGetRelationName(rd);
-                                               heap_close(rd);
-                                       }
-                                       if (RelationIsValid(rd))
-                                       {
-                                               func->func_tlist =
-                                                       setup_tlist(funcname, argrelid);
-                                               iter->itertype = att_typeid(rd, attnum);
-                                               return ((Node *) iter);
-                                       }
-                                       else
-                                       {
-                                               elog(WARN,
-                                                        "Function '%s' has bad returntype %d",
-                                                        funcname, argtype);
-                                       }
-                               }
-                               else
-                               {
-                                       /* drop through */
-                                       ;
-                               }
-                               break;
-                       }
-               case T_Var:
-                       {
-
-                               /*
-                                * The argument is a set, so this is either a projection
-                                * or a function call on this set.
-                                */
-                               *attisset = true;
-                               break;
-                       }
-               case T_Expr:
-                       {
-                               Expr       *expr = (Expr *) first_arg;
-                               Func       *funcnode;
-
-                               if (expr->opType != FUNC_EXPR)
-                                       break;
-
-                               funcnode = (Func *) expr->oper;
-                               argtype = funcid_get_rettype(funcnode->funcid);
-                               argrelid = typeid_get_relid(argtype);
-
-                               /*
-                                * the argument is a function returning a tuple, so
-                                * funcname may be a projection
-                                */
-                               if (argrelid &&
-                                       (attnum = get_attnum(argrelid, funcname))
-                                       != InvalidAttrNumber)
-                               {
-
-                                       /* add a tlist to the func node */
-                                       rd = heap_openr(tname(get_id_type(argtype)));
-                                       if (RelationIsValid(rd))
-                                       {
-                                               relid = RelationGetRelationId(rd);
-                                               relname = RelationGetRelationName(rd);
-                                               heap_close(rd);
-                                       }
-                                       if (RelationIsValid(rd))
-                                       {
-                                               Expr       *newexpr;
-
-                                               funcnode->func_tlist =
-                                                       setup_tlist(funcname, argrelid);
-                                               funcnode->functype = att_typeid(rd, attnum);
-
-                                               newexpr = makeNode(Expr);
-                                               newexpr->typeOid = funcnode->functype;
-                                               newexpr->opType = FUNC_EXPR;
-                                               newexpr->oper = (Node *) funcnode;
-                                               newexpr->args = lcons(first_arg, NIL);
-
-                                               return ((Node *) newexpr);
-                                       }
-
-                               }
-
-                               elog(WARN, "Function '%s' has bad returntype %d",
-                                        funcname, argtype);
-                               break;
-                       }
-               case T_Param:
-                       {
-                               Param      *param = (Param *) first_arg;
-
-                               /*
-                                * If the Param is a complex type, this could be a
-                                * projection
-                                */
-                               rd = heap_openr(tname(get_id_type(param->paramtype)));
-                               if (RelationIsValid(rd))
-                               {
-                                       relid = RelationGetRelationId(rd);
-                                       relname = RelationGetRelationName(rd);
-                                       heap_close(rd);
-                               }
-                               if (RelationIsValid(rd) &&
-                                       (attnum = get_attnum(relid, funcname))
-                                       != InvalidAttrNumber)
-                               {
-
-                                       param->paramtype = att_typeid(rd, attnum);
-                                       param->param_tlist = setup_tlist(funcname, relid);
-                                       return ((Node *) param);
-                               }
-                               break;
-                       }
-               default:
-                       break;
-       }
-
-       return NULL;
-}
-
-static Node *
-ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
-{
-       Oid                     rettype = (Oid) 0;
-       Oid                     argrelid = (Oid) 0;
-       Oid                     funcid = (Oid) 0;
-       List       *i = NIL;
-       Node       *first_arg = NULL;
-       char       *relname = NULL;
-       char       *refname = NULL;
-       Relation        rd;
-       Oid                     relid;
-       int                     nargs;
-       Func       *funcnode;
-       Oid                     oid_array[8];
-       Oid                *true_oid_array;
-       Node       *retval;
-       bool            retset;
-       bool            exists;
-       bool            attisset = false;
-       Oid                     toid = (Oid) 0;
-       Expr       *expr;
-
-       if (fargs)
-       {
-               first_arg = lfirst(fargs);
-               if (first_arg == NULL)
-                       elog(WARN, "function '%s' does not allow NULL input", funcname);
-       }
-
-       /*
-        * * check for projection methods: if function takes one argument, and *
-        * that argument is a relation, param, or PQ function returning a
-        * complex * type, then the function could be a projection.
-        */
-       if (length(fargs) == 1)
-       {
-
-               if (nodeTag(first_arg) == T_Ident && ((Ident *) first_arg)->isRel)
-               {
-                       RangeTblEntry *rte;
-                       Ident      *ident = (Ident *) first_arg;
-
-                       /*
-                        * first arg is a relation. This could be a projection.
-                        */
-                       refname = ident->name;
-
-                       rte = refnameRangeTableEntry(pstate->p_rtable, refname);
-                       if (rte == NULL)
-                               rte = addRangeTableEntry(pstate, refname, refname, FALSE, FALSE);
-
-                       relname = rte->relname;
-                       relid = rte->relid;
-
-                       /*
-                        * If the attr isn't a set, just make a var for it.  If it is
-                        * a set, treat it like a function and drop through.
-                        */
-                       if (get_attnum(relid, funcname) != InvalidAttrNumber)
-                       {
-                               Oid                     dummyTypeId;
-
-                               return
-                                       ((Node *) make_var(pstate,
-                                                                          refname,
-                                                                          funcname,
-                                                                          &dummyTypeId));
-                       }
-                       else
-                       {
-                               /* drop through - attr is a set */
-                               ;
-                       }
-               }
-               else if (ISCOMPLEX(exprType(first_arg)))
-               {
-
-                       /*
-                        * Attempt to handle projection of a complex argument. If
-                        * ParseComplexProjection can't handle the projection, we have
-                        * to keep going.
-                        */
-                       retval = ParseComplexProjection(pstate,
-                                                                                       funcname,
-                                                                                       first_arg,
-                                                                                       &attisset);
-                       if (attisset)
-                       {
-                               toid = exprType(first_arg);
-                               rd = heap_openr(tname(get_id_type(toid)));
-                               if (RelationIsValid(rd))
-                               {
-                                       relname = RelationGetRelationName(rd)->data;
-                                       heap_close(rd);
-                               }
-                               else
-                                       elog(WARN,
-                                                "Type '%s' is not a relation type",
-                                                tname(get_id_type(toid)));
-                               argrelid = typeid_get_relid(toid);
-
-                               /*
-                                * A projection contains either an attribute name or the
-                                * "*".
-                                */
-                               if ((get_attnum(argrelid, funcname) == InvalidAttrNumber)
-                                       && strcmp(funcname, "*"))
-                               {
-                                       elog(WARN, "Functions on sets are not yet supported");
-                               }
-                       }
-
-                       if (retval)
-                               return retval;
-               }
-               else
-               {
-
-                       /*
-                        * Parsing aggregates.
-                        */
-                       Oid                     basetype;
-
-                       /*
-                        * the aggregate count is a special case, ignore its base
-                        * type.  Treat it as zero
-                        */
-                       if (strcmp(funcname, "count") == 0)
-                               basetype = 0;
-                       else
-                               basetype = exprType(lfirst(fargs));
-                       if (SearchSysCacheTuple(AGGNAME,
-                                                                       PointerGetDatum(funcname),
-                                                                       ObjectIdGetDatum(basetype),
-                                                                       0, 0))
-                       {
-                               Aggreg     *aggreg = ParseAgg(funcname, basetype, lfirst(fargs));
-
-                               AddAggToParseState(pstate, aggreg);
-                               return (Node *) aggreg;
-                       }
-               }
-       }
-
-
-       /*
-        * * If we dropped through to here it's really a function (or a set,
-        * which * is implemented as a function.) * extract arg type info and
-        * transform relation name arguments into * varnodes of the
-        * appropriate form.
-        */
-       MemSet(&oid_array[0], 0, 8 * sizeof(Oid));
-
-       nargs = 0;
-       foreach(i, fargs)
-       {
-               int                     vnum;
-               RangeTblEntry *rte;
-               Node       *pair = lfirst(i);
-
-               if (nodeTag(pair) == T_Ident && ((Ident *) pair)->isRel)
-               {
-
-                       /*
-                        * a relation
-                        */
-                       refname = ((Ident *) pair)->name;
-
-                       rte = refnameRangeTableEntry(pstate->p_rtable, refname);
-                       if (rte == NULL)
-                               rte = addRangeTableEntry(pstate, refname, refname,
-                                                                                FALSE, FALSE);
-                       relname = rte->relname;
-
-                       vnum = refnameRangeTablePosn(pstate->p_rtable, rte->refname);
-
-                       /*
-                        * for func(relname), the param to the function is the tuple
-                        * under consideration.  we build a special VarNode to reflect
-                        * this -- it has varno set to the correct range table entry,
-                        * but has varattno == 0 to signal that the whole tuple is the
-                        * argument.
-                        */
-                       toid = typeid(type(relname));
-                       /* replace it in the arg list */
-                       lfirst(fargs) =
-                               makeVar(vnum, 0, toid, vnum, 0);
-               }
-               else if (!attisset)
-               {                                               /* set functions don't have parameters */
-
-                       /*
-                        * any functiona args which are typed "unknown", but aren't
-                        * constants, we don't know what to do with, because we can't
-                        * cast them    - jolly
-                        */
-                       if (exprType(pair) == UNKNOWNOID &&
-                               !IsA(pair, Const))
-                       {
-                               elog(WARN, "ParseFunc: no function named '%s' that takes in an unknown type as argument #%d", funcname, nargs);
-                       }
-                       else
-                               toid = exprType(pair);
-               }
-
-               oid_array[nargs++] = toid;
-       }
-
-       /*
-        * func_get_detail looks up the function in the catalogs, does
-        * disambiguation for polymorphic functions, handles inheritance, and
-        * returns the funcid and type and set or singleton status of the
-        * function's return value.  it also returns the true argument types
-        * to the function.  if func_get_detail returns true, the function
-        * exists.      otherwise, there was an error.
-        */
-       if (attisset)
-       {                                                       /* we know all of these fields already */
-
-               /*
-                * We create a funcnode with a placeholder function SetEval.
-                * SetEval() never actually gets executed.      When the function
-                * evaluation routines see it, they use the funcid projected out
-                * from the relation as the actual function to call. Example:
-                * retrieve (emp.mgr.name) The plan for this will scan the emp
-                * relation, projecting out the mgr attribute, which is a funcid.
-                * This function is then called (instead of SetEval) and "name" is
-                * projected from its result.
-                */
-               funcid = SetEvalRegProcedure;
-               rettype = toid;
-               retset = true;
-               true_oid_array = oid_array;
-               exists = true;
-       }
-       else
-       {
-               exists = func_get_detail(funcname, nargs, oid_array, &funcid,
-                                                                &rettype, &retset, &true_oid_array);
-       }
-
-       if (!exists)
-               elog(WARN, "no such attribute or function '%s'", funcname);
-
-       /* got it */
-       funcnode = makeNode(Func);
-       funcnode->funcid = funcid;
-       funcnode->functype = rettype;
-       funcnode->funcisindex = false;
-       funcnode->funcsize = 0;
-       funcnode->func_fcache = NULL;
-       funcnode->func_tlist = NIL;
-       funcnode->func_planlist = NIL;
-
-       /* perform the necessary typecasting */
-       make_arguments(nargs, fargs, oid_array, true_oid_array);
-
-       /*
-        * for functions returning base types, we want to project out the
-        * return value.  set up a target list to do that.      the executor will
-        * ignore these for c functions, and do the right thing for postquel
-        * functions.
-        */
-
-       if (typeid_get_relid(rettype) == InvalidOid)
-               funcnode->func_tlist = setup_base_tlist(rettype);
-
-       /*
-        * For sets, we want to make a targetlist to project out this
-        * attribute of the set tuples.
-        */
-       if (attisset)
-       {
-               if (!strcmp(funcname, "*"))
-               {
-                       funcnode->func_tlist =
-                               expandAll(pstate, relname, refname, curr_resno);
-               }
-               else
-               {
-                       funcnode->func_tlist = setup_tlist(funcname, argrelid);
-                       rettype = find_atttype(argrelid, funcname);
-               }
-       }
-
-       /*
-        * Sequence handling.
-        */
-       if (funcid == SeqNextValueRegProcedure ||
-               funcid == SeqCurrValueRegProcedure)
-       {
-               Const      *seq;
-               char       *seqrel;
-               text       *seqname;
-               int32           aclcheck_result = -1;
-               extern text *lower (text *string);
-
-               Assert(length(fargs) == 1);
-               seq = (Const *) lfirst(fargs);
-               if (!IsA((Node *) seq, Const))
-                       elog(WARN, "%s: only constant sequence names are acceptable", funcname);
-               seqname = lower ((text*)DatumGetPointer(seq->constvalue));
-               pfree (DatumGetPointer(seq->constvalue));
-               seq->constvalue = PointerGetDatum (seqname);
-               seqrel = textout(seqname);
-
-               if ((aclcheck_result = pg_aclcheck(seqrel, GetPgUserName(),
-                          ((funcid == SeqNextValueRegProcedure) ? ACL_WR : ACL_RD)))
-                       != ACLCHECK_OK)
-                       elog(WARN, "%s.%s: %s",
-                         seqrel, funcname, aclcheck_error_strings[aclcheck_result]);
-
-               pfree(seqrel);
-
-               if (funcid == SeqNextValueRegProcedure && inWhereClause)
-                       elog(WARN, "nextval of a sequence in WHERE disallowed");
-       }
-
-       expr = makeNode(Expr);
-       expr->typeOid = rettype;
-       expr->opType = FUNC_EXPR;
-       expr->oper = (Node *) funcnode;
-       expr->args = fargs;
-       retval = (Node *) expr;
-
-       /*
-        * if the function returns a set of values, then we need to iterate
-        * over all the returned values in the executor, so we stick an iter
-        * node here.  if it returns a singleton, then we don't need the iter
-        * node.
-        */
-
-       if (retset)
-       {
-               Iter       *iter = makeNode(Iter);
-
-               iter->itertype = rettype;
-               iter->iterexpr = retval;
-               retval = (Node *) iter;
-       }
-
-       return (retval);
-}
-
-/*****************************************************************************
- *
- *****************************************************************************/
-
-/*
- * AddAggToParseState -
- *       add the aggregate to the list of unique aggregates in pstate.
- *
- * SIDE EFFECT: aggno in target list entry will be modified
- */
-static void
-AddAggToParseState(ParseState *pstate, Aggreg *aggreg)
-{
-       List       *ag;
-       int                     i;
-
-       /*
-        * see if we have the aggregate already (we only need to record the
-        * aggregate once)
-        */
-       i = 0;
-       foreach(ag, pstate->p_aggs)
-       {
-               Aggreg     *a = lfirst(ag);
-
-               if (!strcmp(a->aggname, aggreg->aggname) &&
-                       equal(a->target, aggreg->target))
-               {
-
-                       /* fill in the aggno and we're done */
-                       aggreg->aggno = i;
-                       return;
-               }
-               i++;
-       }
-
-       /* not found, new aggregate */
-       aggreg->aggno = i;
-       pstate->p_numAgg++;
-       pstate->p_aggs = lappend(pstate->p_aggs, aggreg);
-       return;
-}
-
-/*
- * finalizeAggregates -
- *       fill in qry_aggs from pstate. Also checks to make sure that aggregates
- *       are used in the proper place.
- */
-static void
-finalizeAggregates(ParseState *pstate, Query *qry)
-{
-       List       *l;
-       int                     i;
-
-       parseCheckAggregates(pstate, qry);
-
-       qry->qry_numAgg = pstate->p_numAgg;
-       qry->qry_aggs =
-               (Aggreg **) palloc(sizeof(Aggreg *) * qry->qry_numAgg);
-       i = 0;
-       foreach(l, pstate->p_aggs)
-               qry->qry_aggs[i++] = (Aggreg *) lfirst(l);
-}
-
-/*
- * contain_agg_clause--
- *       Recursively find aggreg nodes from a clause.
- *
- *       Returns true if any aggregate found.
- */
-static bool
-contain_agg_clause(Node *clause)
-{
-       if (clause == NULL)
-               return FALSE;
-       else if (IsA(clause, Aggreg))
-               return TRUE;
-       else if (IsA(clause, Iter))
-               return contain_agg_clause(((Iter *) clause)->iterexpr);
-       else if (single_node(clause))
-               return FALSE;
-       else if (or_clause(clause))
-       {
-               List       *temp;
-
-               foreach(temp, ((Expr *) clause)->args)
-                       if (contain_agg_clause(lfirst(temp)))
-                       return TRUE;
-               return FALSE;
-       }
-       else if (is_funcclause(clause))
-       {
-               List       *temp;
-
-               foreach(temp, ((Expr *) clause)->args)
-                       if (contain_agg_clause(lfirst(temp)))
-                       return TRUE;
-               return FALSE;
-       }
-       else if (IsA(clause, ArrayRef))
-       {
-               List       *temp;
-
-               foreach(temp, ((ArrayRef *) clause)->refupperindexpr)
-                       if (contain_agg_clause(lfirst(temp)))
-                       return TRUE;
-               foreach(temp, ((ArrayRef *) clause)->reflowerindexpr)
-                       if (contain_agg_clause(lfirst(temp)))
-                       return TRUE;
-               if (contain_agg_clause(((ArrayRef *) clause)->refexpr))
-                       return TRUE;
-               if (contain_agg_clause(((ArrayRef *) clause)->refassgnexpr))
-                       return TRUE;
-               return FALSE;
-       }
-       else if (not_clause(clause))
-               return contain_agg_clause((Node *) get_notclausearg((Expr *) clause));
-       else if (is_opclause(clause))
-               return (contain_agg_clause((Node *) get_leftop((Expr *) clause)) ||
-                         contain_agg_clause((Node *) get_rightop((Expr *) clause)));
-
-       return FALSE;
-}
-
-/*
- * exprIsAggOrGroupCol -
- *       returns true if the expression does not contain non-group columns.
- */
-static bool
-exprIsAggOrGroupCol(Node *expr, List *groupClause)
-{
-       List       *gl;
-
-       if (expr == NULL || IsA(expr, Const) ||
-               IsA(expr, Param) ||IsA(expr, Aggreg))
-               return TRUE;
-
-       foreach(gl, groupClause)
-       {
-               GroupClause *grpcl = lfirst(gl);
-
-               if (equal(expr, grpcl->entry->expr))
-                       return TRUE;
-       }
-
-       if (IsA(expr, Expr))
-       {
-               List       *temp;
-
-               foreach(temp, ((Expr *) expr)->args)
-                       if (!exprIsAggOrGroupCol(lfirst(temp), groupClause))
-                       return FALSE;
-               return TRUE;
-       }
-
-       return FALSE;
-}
-
-/*
- * tleIsAggOrGroupCol -
- *       returns true if the TargetEntry is Agg or GroupCol.
- */
-static bool
-tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause)
-{
-       Node       *expr = tle->expr;
-       List       *gl;
-
-       if (expr == NULL || IsA(expr, Const) ||IsA(expr, Param))
-               return TRUE;
-
-       foreach(gl, groupClause)
-       {
-               GroupClause *grpcl = lfirst(gl);
-
-               if (tle->resdom->resno == grpcl->entry->resdom->resno)
-               {
-                       if (contain_agg_clause((Node *) expr))
-                               elog(WARN, "parser: aggregates not allowed in GROUP BY clause");
-                       return TRUE;
-               }
-       }
-
-       if (IsA(expr, Aggreg))
-               return TRUE;
-
-       if (IsA(expr, Expr))
-       {
-               List       *temp;
-
-               foreach(temp, ((Expr *) expr)->args)
-                       if (!exprIsAggOrGroupCol(lfirst(temp), groupClause))
-                       return FALSE;
-               return TRUE;
-       }
-
-       return FALSE;
-}
-
-/*
- * parseCheckAggregates -
- *       this should really be done earlier but the current grammar
- *       cannot differentiate functions from aggregates. So we have do check
- *       here when the target list and the qualifications are finalized.
- */
-static void
-parseCheckAggregates(ParseState *pstate, Query *qry)
-{
-       List       *tl;
-
-       Assert(pstate->p_numAgg > 0);
-
-       /*
-        * aggregates never appear in WHERE clauses. (we have to check where
-        * clause first because if there is an aggregate, the check for
-        * non-group column in target list may fail.)
-        */
-       if (contain_agg_clause(qry->qual))
-               elog(WARN, "parser: aggregates not allowed in WHERE clause");
-
-       /*
-        * the target list can only contain aggregates, group columns and
-        * functions thereof.
-        */
-       foreach(tl, qry->targetList)
-       {
-               TargetEntry *tle = lfirst(tl);
-
-               if (!tleIsAggOrGroupCol(tle, qry->groupClause))
-                       elog(WARN,
-                                "parser: illegal use of aggregates or non-group column in target list");
-       }
-
-       /*
-        * the expression specified in the HAVING clause has the same
-        * restriction as those in the target list.
-        */
-/*
- * Need to change here when we get HAVING works. Currently
- * qry->havingQual is NULL.            - vadim 04/05/97
-       if (!exprIsAggOrGroupCol(qry->havingQual, qry->groupClause))
-               elog(WARN,
-                        "parser: illegal use of aggregates or non-group column in HAVING clause");
- */
-       return;
-}
-
-/* not used
-#define    PSIZE(PTR)     (*((int32 *)(PTR) - 1))
-*/
-
-static Node       *
-parser_typecast(Value *expr, TypeName *typename, int typlen)
-{
-       /* check for passing non-ints */
-       Const      *adt;
-       Datum           lcp;
-       Type            tp;
-       char            type_string[NAMEDATALEN];
-       int32           len;
-       char       *cp = NULL;
-       char       *const_string = NULL;
-       bool            string_palloced = false;
-
-       switch (nodeTag(expr))
-       {
-               case T_String:
-                       const_string = DatumGetPointer(expr->val.str);
-                       break;
-               case T_Integer:
-                       const_string = (char *) palloc(256);
-                       string_palloced = true;
-                       sprintf(const_string, "%ld", expr->val.ival);
-                       break;
-               default:
-                       elog(WARN,
-                       "parser_typecast: cannot cast this expression to type \"%s\"",
-                                typename->name);
-       }
-
-       if (typename->arrayBounds != NIL)
-       {
-               sprintf(type_string, "_%s", typename->name);
-               tp = (Type) type(type_string);
-       }
-       else
-       {
-               tp = (Type) type(typename->name);
-       }
-
-       len = tlen(tp);
-
-#if 0                                                  /* fix me */
-       switch (CInteger(lfirst(expr)))
-       {
-               case INT4OID:                   /* int4 */
-                       const_string = (char *) palloc(256);
-                       string_palloced = true;
-                       sprintf(const_string, "%d", ((Const *) lnext(expr))->constvalue);
-                       break;
-
-               case NAMEOID:                   /* char16 */
-                       const_string = (char *) palloc(256);
-                       string_palloced = true;
-                       sprintf(const_string, "%s", ((Const *) lnext(expr))->constvalue);
-                       break;
-
-               case CHAROID:                   /* char */
-                       const_string = (char *) palloc(256);
-                       string_palloced = true;
-                       sprintf(const_string, "%c", ((Const) lnext(expr))->constvalue);
-                       break;
-
-               case FLOAT8OID: /* float8 */
-                       const_string = (char *) palloc(256);
-                       string_palloced = true;
-                       sprintf(const_string, "%f", ((Const) lnext(expr))->constvalue);
-                       break;
-
-               case CASHOID:                   /* money */
-                       const_string = (char *) palloc(256);
-                       string_palloced = true;
-                       sprintf(const_string, "%d",
-                                       (int) ((Const *) expr)->constvalue);
-                       break;
-
-               case TEXTOID:                   /* text */
-                       const_string = DatumGetPointer(((Const) lnext(expr))->constvalue);
-                       const_string = (char *) textout((struct varlena *) const_string);
-                       break;
-
-               case UNKNOWNOID:                /* unknown */
-                       const_string = DatumGetPointer(((Const) lnext(expr))->constvalue);
-                       const_string = (char *) textout((struct varlena *) const_string);
-                       break;
-
-               default:
-                       elog(WARN, "unknown type %d", CInteger(lfirst(expr)));
-       }
-#endif
-
-       cp = instr2(tp, const_string, typlen);
-
-       if (!tbyvalue(tp))
-       {
-/*
-               if (len >= 0 && len != PSIZE(cp)) {
-                       char *pp;
-                       pp = (char *) palloc(len);
-                       memmove(pp, cp, len);
-                       cp = pp;
-               }
-*/
-               lcp = PointerGetDatum(cp);
-       }
-       else
-       {
-               switch (len)
-               {
-                       case 1:
-                               lcp = Int8GetDatum(cp);
-                               break;
-                       case 2:
-                               lcp = Int16GetDatum(cp);
-                               break;
-                       case 4:
-                               lcp = Int32GetDatum(cp);
-                               break;
-                       default:
-                               lcp = PointerGetDatum(cp);
-                               break;
-               }
-       }
-
-       adt = makeConst(typeid(tp),
-                                       len,
-                                       (Datum) lcp,
-                                       false,
-                                       tbyvalue(tp),
-                                       false,          /* not a set */
-                                       true /* is cast */ );
-
-       if (string_palloced)
-               pfree(const_string);
-
-       return (Node *) adt;
-}
-
-static Node       *
-parser_typecast2(Node *expr, Oid exprType, Type tp, int typlen)
-{
-       /* check for passing non-ints */
-       Const      *adt;
-       Datum           lcp;
-       int32           len = tlen(tp);
-       char       *cp = NULL;
-
-       char       *const_string = NULL;
-       bool            string_palloced = false;
-
-       Assert(IsA(expr, Const));
-
-       switch (exprType)
-       {
-               case 0:                 /* NULL */
-                       break;
-               case INT4OID:                   /* int4 */
-                       const_string = (char *) palloc(256);
-                       string_palloced = true;
-                       sprintf(const_string, "%d",
-                                       (int) ((Const *) expr)->constvalue);
-                       break;
-               case NAMEOID:                   /* char16 */
-                       const_string = (char *) palloc(256);
-                       string_palloced = true;
-                       sprintf(const_string, "%s",
-                                       (char *) ((Const *) expr)->constvalue);
-                       break;
-               case CHAROID:                   /* char */
-                       const_string = (char *) palloc(256);
-                       string_palloced = true;
-                       sprintf(const_string, "%c",
-                                       (char) ((Const *) expr)->constvalue);
-                       break;
-               case FLOAT4OID: /* float4 */
-                       {
-                               float32         floatVal =
-                               DatumGetFloat32(((Const *) expr)->constvalue);
-
-                               const_string = (char *) palloc(256);
-                               string_palloced = true;
-                               sprintf(const_string, "%f", *floatVal);
-                               break;
-                       }
-               case FLOAT8OID: /* float8 */
-                       {
-                               float64         floatVal =
-                               DatumGetFloat64(((Const *) expr)->constvalue);
-
-                               const_string = (char *) palloc(256);
-                               string_palloced = true;
-                               sprintf(const_string, "%f", *floatVal);
-                               break;
-                       }
-               case CASHOID:                   /* money */
-                       const_string = (char *) palloc(256);
-                       string_palloced = true;
-                       sprintf(const_string, "%ld",
-                                       (long) ((Const *) expr)->constvalue);
-                       break;
-               case TEXTOID:                   /* text */
-                       const_string =
-                               DatumGetPointer(((Const *) expr)->constvalue);
-                       const_string = (char *) textout((struct varlena *) const_string);
-                       break;
-               case UNKNOWNOID:                /* unknown */
-                       const_string =
-                               DatumGetPointer(((Const *) expr)->constvalue);
-                       const_string = (char *) textout((struct varlena *) const_string);
-                       break;
-               default:
-                       elog(WARN, "unknown type %u ", exprType);
-       }
-
-       if (!exprType)
-       {
-               adt = makeConst(typeid(tp),
-                                               (Size) 0,
-                                               (Datum) NULL,
-                                               true,   /* isnull */
-                                               false,  /* was omitted */
-                                               false,  /* not a set */
-                                               true /* is cast */ );
-               return ((Node *) adt);
-       }
-
-       cp = instr2(tp, const_string, typlen);
-
-
-       if (!tbyvalue(tp))
-       {
-/*
-               if (len >= 0 && len != PSIZE(cp)) {
-                       char *pp;
-                       pp = (char *) palloc(len);
-                       memmove(pp, cp, len);
-                       cp = pp;
-               }
-*/
-               lcp = PointerGetDatum(cp);
-       }
-       else
-       {
-               switch (len)
-               {
-                       case 1:
-                               lcp = Int8GetDatum(cp);
-                               break;
-                       case 2:
-                               lcp = Int16GetDatum(cp);
-                               break;
-                       case 4:
-                               lcp = Int32GetDatum(cp);
-                               break;
-                       default:
-                               lcp = PointerGetDatum(cp);
-                               break;
-               }
-       }
-
-       adt = makeConst(typeid(tp),
-                                       (Size) len,
-                                       (Datum) lcp,
-                                       false,
-                                       false,          /* was omitted */
-                                       false,          /* not a set */
-                                       true /* is cast */ );
-
-       /*
-        * printf("adt %s : %u %d %d\n",CString(expr),typeid(tp) , len,cp);
-        */
-       if (string_palloced)
-               pfree(const_string);
-
-       return ((Node *) adt);
-}
-
-static Aggreg     *
-ParseAgg(char *aggname, Oid basetype, Node *target)
-{
-       Oid                     fintype;
-       Oid                     vartype;
-       Oid                     xfn1;
-       Form_pg_aggregate aggform;
-       Aggreg     *aggreg;
-       HeapTuple       theAggTuple;
-
-       theAggTuple = SearchSysCacheTuple(AGGNAME, PointerGetDatum(aggname),
-                                                                         ObjectIdGetDatum(basetype),
-                                                                         0, 0);
-       if (!HeapTupleIsValid(theAggTuple))
-       {
-               elog(WARN, "aggregate %s does not exist", aggname);
-       }
-
-       aggform = (Form_pg_aggregate) GETSTRUCT(theAggTuple);
-       fintype = aggform->aggfinaltype;
-       xfn1 = aggform->aggtransfn1;
-
-       if (nodeTag(target) != T_Var && nodeTag(target) != T_Expr)
-               elog(WARN, "parser: aggregate can only be applied on an attribute or expression");
-
-       /* only aggregates with transfn1 need a base type */
-       if (OidIsValid(xfn1))
-       {
-               basetype = aggform->aggbasetype;
-               if (nodeTag(target) == T_Var)
-                       vartype = ((Var *) target)->vartype;
-               else
-                       vartype = ((Expr *) target)->typeOid;
-
-               if (basetype != vartype)
-               {
-                       Type            tp1,
-                                               tp2;
-
-                       tp1 = get_id_type(basetype);
-                       tp2 = get_id_type(vartype);
-                       elog(NOTICE, "Aggregate type mismatch:");
-                       elog(WARN, "%s works on %s, not %s", aggname,
-                                tname(tp1), tname(tp2));
-               }
-       }
-
-       aggreg = makeNode(Aggreg);
-       aggreg->aggname = pstrdup(aggname);
-       aggreg->basetype = aggform->aggbasetype;
-       aggreg->aggtype = fintype;
-
-       aggreg->target = target;
-
-       return aggreg;
-}
diff --git a/src/backend/parser/catalog_utils.c b/src/backend/parser/catalog_utils.c
deleted file mode 100644 (file)
index b119c7d..0000000
+++ /dev/null
@@ -1,1686 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * catalog_utils.c--
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/Attic/catalog_utils.c,v 1.30 1997/11/20 23:22:14 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-#include <string.h>
-#include "postgres.h"
-
-#include "lib/dllist.h"
-#include "utils/datum.h"
-
-#include "utils/builtins.h"
-#include "utils/elog.h"
-#include "utils/palloc.h"
-#include "fmgr.h"
-
-#include "nodes/pg_list.h"
-#include "nodes/parsenodes.h"
-#include "utils/syscache.h"
-#include "catalog/catname.h"
-
-#include "parser/catalog_utils.h"
-#include "catalog/pg_inherits.h"
-#include "catalog/pg_operator.h"
-#include "catalog/pg_type.h"
-#include "catalog/pg_proc.h"
-#include "catalog/indexing.h"
-#include "catalog/catname.h"
-
-#include "access/skey.h"
-#include "access/relscan.h"
-#include "access/tupdesc.h"
-#include "access/htup.h"
-#include "access/heapam.h"
-#include "access/genam.h"
-#include "access/itup.h"
-#include "access/tupmacs.h"
-
-#include "storage/buf.h"
-#include "storage/bufmgr.h"
-#include "utils/lsyscache.h"
-#include "storage/lmgr.h"
-
-#include "port-protos.h"               /* strdup() */
-
-struct
-{
-       char       *field;
-       int                     code;
-}                      special_attr[] =
-
-{
-       {
-               "ctid", SelfItemPointerAttributeNumber
-       },
-       {
-               "oid", ObjectIdAttributeNumber
-       },
-       {
-               "xmin", MinTransactionIdAttributeNumber
-       },
-       {
-               "cmin", MinCommandIdAttributeNumber
-       },
-       {
-               "xmax", MaxTransactionIdAttributeNumber
-       },
-       {
-               "cmax", MaxCommandIdAttributeNumber
-       },
-};
-
-#define SPECIALS (sizeof(special_attr)/sizeof(*special_attr))
-
-static char *attnum_type[SPECIALS] = {
-       "tid",
-       "oid",
-       "xid",
-       "cid",
-       "xid",
-       "cid",
-};
-
-#define MAXFARGS 8                             /* max # args to a c or postquel function */
-
-/*
- *     This structure is used to explore the inheritance hierarchy above
- *     nodes in the type tree in order to disambiguate among polymorphic
- *     functions.
- */
-
-typedef struct _InhPaths
-{
-       int                     nsupers;                /* number of superclasses */
-       Oid                     self;                   /* this class */
-       Oid                *supervec;           /* vector of superclasses */
-} InhPaths;
-
-/*
- *     This structure holds a list of possible functions or operators that
- *     agree with the known name and argument types of the function/operator.
- */
-typedef struct _CandidateList
-{
-       Oid                *args;
-       struct _CandidateList *next;
-}                 *CandidateList;
-
-static Oid **argtype_inherit(int nargs, Oid *oid_array);
-static Oid **genxprod(InhPaths *arginh, int nargs);
-static int     findsupers(Oid relid, Oid **supervec);
-static bool check_typeid(Oid id);
-static char *instr1(TypeTupleForm tp, char *string, int typlen);
-static void op_error(char *op, Oid arg1, Oid arg2);
-
-/* check to see if a type id is valid,
- * returns true if it is. By using this call before calling
- * get_id_type or get_id_typname, more meaningful error messages
- * can be produced because the caller typically has more context of
- *     what's going on                 - jolly
- */
-static bool
-check_typeid(Oid id)
-{
-       return (SearchSysCacheTuple(TYPOID,
-                                                               ObjectIdGetDatum(id),
-                                                               0, 0, 0) != NULL);
-}
-
-
-/* return a Type structure, given an typid */
-Type
-get_id_type(Oid id)
-{
-       HeapTuple       tup;
-
-       if (!(tup = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(id),
-                                                                       0, 0, 0)))
-       {
-               elog(WARN, "type id lookup of %ud failed", id);
-               return (NULL);
-       }
-       return ((Type) tup);
-}
-
-/* return a type name, given a typeid */
-char      *
-get_id_typname(Oid id)
-{
-       HeapTuple       tup;
-       TypeTupleForm typetuple;
-
-       if (!(tup = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(id),
-                                                                       0, 0, 0)))
-       {
-               elog(WARN, "type id lookup of %ud failed", id);
-               return (NULL);
-       }
-       typetuple = (TypeTupleForm) GETSTRUCT(tup);
-       return (typetuple->typname).data;
-}
-
-/* return a Type structure, given type name */
-Type
-type(char *s)
-{
-       HeapTuple       tup;
-
-       if (s == NULL)
-       {
-               elog(WARN, "type(): Null type");
-       }
-
-       if (!(tup = SearchSysCacheTuple(TYPNAME, PointerGetDatum(s), 0, 0, 0)))
-       {
-               elog(WARN, "type name lookup of %s failed", s);
-       }
-       return ((Type) tup);
-}
-
-/* given attribute id, return type of that attribute */
-/* XXX Special case for pseudo-attributes is a hack */
-Oid
-att_typeid(Relation rd, int attid)
-{
-
-       if (attid < 0)
-       {
-               return (typeid(type(attnum_type[-attid - 1])));
-       }
-
-       /*
-        * -1 because varattno (where attid comes from) returns one more than
-        * index
-        */
-       return (rd->rd_att->attrs[attid - 1]->atttypid);
-}
-
-
-int
-att_attnelems(Relation rd, int attid)
-{
-       return (rd->rd_att->attrs[attid - 1]->attnelems);
-}
-
-/* given type, return the type OID */
-Oid
-typeid(Type tp)
-{
-       if (tp == NULL)
-       {
-               elog(WARN, "typeid() called with NULL type struct");
-       }
-       return (tp->t_oid);
-}
-
-/* given type (as type struct), return the length of type */
-int16
-tlen(Type t)
-{
-       TypeTupleForm typ;
-
-       typ = (TypeTupleForm) GETSTRUCT(t);
-       return (typ->typlen);
-}
-
-/* given type (as type struct), return the value of its 'byval' attribute.*/
-bool
-tbyval(Type t)
-{
-       TypeTupleForm typ;
-
-       typ = (TypeTupleForm) GETSTRUCT(t);
-       return (typ->typbyval);
-}
-
-/* given type (as type struct), return the name of type */
-char      *
-tname(Type t)
-{
-       TypeTupleForm typ;
-
-       typ = (TypeTupleForm) GETSTRUCT(t);
-       return (typ->typname).data;
-}
-
-/* given type (as type struct), return wether type is passed by value */
-int
-tbyvalue(Type t)
-{
-       TypeTupleForm typ;
-
-       typ = (TypeTupleForm) GETSTRUCT(t);
-       return (typ->typbyval);
-}
-
-/* given a type, return its typetype ('c' for 'c'atalog types) */
-static char
-typetypetype(Type t)
-{
-       TypeTupleForm typ;
-
-       typ = (TypeTupleForm) GETSTRUCT(t);
-       return (typ->typtype);
-}
-
-/* given operator, return the operator OID */
-Oid
-oprid(Operator op)
-{
-       return (op->t_oid);
-}
-
-/*
- *     given opname, leftTypeId and rightTypeId,
- *     find all possible (arg1, arg2) pairs for which an operator named
- *     opname exists, such that leftTypeId can be coerced to arg1 and
- *     rightTypeId can be coerced to arg2
- */
-static int
-binary_oper_get_candidates(char *opname,
-                                                  Oid leftTypeId,
-                                                  Oid rightTypeId,
-                                                  CandidateList *candidates)
-{
-       CandidateList current_candidate;
-       Relation        pg_operator_desc;
-       HeapScanDesc pg_operator_scan;
-       HeapTuple       tup;
-       OperatorTupleForm oper;
-       Buffer          buffer;
-       int                     nkeys;
-       int                     ncandidates = 0;
-       ScanKeyData opKey[3];
-
-       *candidates = NULL;
-
-       ScanKeyEntryInitialize(&opKey[0], 0,
-                                                  Anum_pg_operator_oprname,
-                                                  NameEqualRegProcedure,
-                                                  NameGetDatum(opname));
-
-       ScanKeyEntryInitialize(&opKey[1], 0,
-                                                  Anum_pg_operator_oprkind,
-                                                  CharacterEqualRegProcedure,
-                                                  CharGetDatum('b'));
-
-
-       if (leftTypeId == UNKNOWNOID)
-       {
-               if (rightTypeId == UNKNOWNOID)
-               {
-                       nkeys = 2;
-               }
-               else
-               {
-                       nkeys = 3;
-
-                       ScanKeyEntryInitialize(&opKey[2], 0,
-                                                                  Anum_pg_operator_oprright,
-                                                                  ObjectIdEqualRegProcedure,
-                                                                  ObjectIdGetDatum(rightTypeId));
-               }
-       }
-       else if (rightTypeId == UNKNOWNOID)
-       {
-               nkeys = 3;
-
-               ScanKeyEntryInitialize(&opKey[2], 0,
-                                                          Anum_pg_operator_oprleft,
-                                                          ObjectIdEqualRegProcedure,
-                                                          ObjectIdGetDatum(leftTypeId));
-       }
-       else
-       {
-               /* currently only "unknown" can be coerced */
-               return 0;
-       }
-
-       pg_operator_desc = heap_openr(OperatorRelationName);
-       pg_operator_scan = heap_beginscan(pg_operator_desc,
-                                                                         0,
-                                                                         true,
-                                                                         nkeys,
-                                                                         opKey);
-
-       do
-       {
-               tup = heap_getnext(pg_operator_scan, 0, &buffer);
-               if (HeapTupleIsValid(tup))
-               {
-                       current_candidate = (CandidateList) palloc(sizeof(struct _CandidateList));
-                       current_candidate->args = (Oid *) palloc(2 * sizeof(Oid));
-
-                       oper = (OperatorTupleForm) GETSTRUCT(tup);
-                       current_candidate->args[0] = oper->oprleft;
-                       current_candidate->args[1] = oper->oprright;
-                       current_candidate->next = *candidates;
-                       *candidates = current_candidate;
-                       ncandidates++;
-                       ReleaseBuffer(buffer);
-               }
-       } while (HeapTupleIsValid(tup));
-
-       heap_endscan(pg_operator_scan);
-       heap_close(pg_operator_desc);
-
-       return ncandidates;
-}
-
-/*
- * equivalentOpersAfterPromotion -
- *       checks if a list of candidate operators obtained from
- *       binary_oper_get_candidates() contain equivalent operators. If
- *       this routine is called, we have more than 1 candidate and need to
- *       decided whether to pick one of them. This routine returns true if
- *       the all the candidates operate on the same data types after
- *       promotion (int2, int4, float4 -> float8).
- */
-static bool
-equivalentOpersAfterPromotion(CandidateList candidates)
-{
-       CandidateList result;
-       CandidateList promotedCandidates = NULL;
-       Oid                     leftarg,
-                               rightarg;
-
-       for (result = candidates; result != NULL; result = result->next)
-       {
-               CandidateList c;
-
-               c = (CandidateList) palloc(sizeof(*c));
-               c->args = (Oid *) palloc(2 * sizeof(Oid));
-               switch (result->args[0])
-               {
-                       case FLOAT4OID:
-                       case INT4OID:
-                       case INT2OID:
-                       case CASHOID:
-                               c->args[0] = FLOAT8OID;
-                               break;
-                       default:
-                               c->args[0] = result->args[0];
-                               break;
-               }
-               switch (result->args[1])
-               {
-                       case FLOAT4OID:
-                       case INT4OID:
-                       case INT2OID:
-                       case CASHOID:
-                               c->args[1] = FLOAT8OID;
-                               break;
-                       default:
-                               c->args[1] = result->args[1];
-                               break;
-               }
-               c->next = promotedCandidates;
-               promotedCandidates = c;
-       }
-
-       /*
-        * if we get called, we have more than 1 candidates so we can do the
-        * following safely
-        */
-       leftarg = promotedCandidates->args[0];
-       rightarg = promotedCandidates->args[1];
-
-       for (result = promotedCandidates->next; result != NULL; result = result->next)
-       {
-               if (result->args[0] != leftarg || result->args[1] != rightarg)
-
-                       /*
-                        * this list contains operators that operate on different data
-                        * types even after promotion. Hence we can't decide on which
-                        * one to pick. The user must do explicit type casting.
-                        */
-                       return FALSE;
-       }
-
-       /*
-        * all the candidates are equivalent in the following sense: they
-        * operate on equivalent data types and picking any one of them is as
-        * good.
-        */
-       return TRUE;
-}
-
-
-/*
- *     given a choice of argument type pairs for a binary operator,
- *     try to choose a default pair
- */
-static CandidateList
-binary_oper_select_candidate(Oid arg1,
-                                                        Oid arg2,
-                                                        CandidateList candidates)
-{
-       CandidateList result;
-
-       /*
-        * if both are "unknown", there is no way to select a candidate
-        *
-        * current wisdom holds that the default operator should be one in which
-        * both operands have the same type (there will only be one such
-        * operator)
-        *
-        * 7.27.93 - I have decided not to do this; it's too hard to justify, and
-        * it's easy enough to typecast explicitly -avi [the rest of this
-        * routine were commented out since then -ay]
-        */
-
-       if (arg1 == UNKNOWNOID && arg2 == UNKNOWNOID)
-               return (NULL);
-
-       /*
-        * 6/23/95 - I don't complete agree with avi. In particular, casting
-        * floats is a pain for users. Whatever the rationale behind not doing
-        * this is, I need the following special case to work.
-        *
-        * In the WHERE clause of a query, if a float is specified without
-        * quotes, we treat it as float8. I added the float48* operators so
-        * that we can operate on float4 and float8. But now we have more than
-        * one matching operator if the right arg is unknown (eg. float
-        * specified with quotes). This break some stuff in the regression
-        * test where there are floats in quotes not properly casted. Below is
-        * the solution. In addition to requiring the operator operates on the
-        * same type for both operands [as in the code Avi originally
-        * commented out], we also require that the operators be equivalent in
-        * some sense. (see equivalentOpersAfterPromotion for details.) - ay
-        * 6/95
-        */
-       if (!equivalentOpersAfterPromotion(candidates))
-               return NULL;
-
-       /*
-        * if we get here, any one will do but we're more picky and require
-        * both operands be the same.
-        */
-       for (result = candidates; result != NULL; result = result->next)
-       {
-               if (result->args[0] == result->args[1])
-                       return result;
-       }
-
-       return (NULL);
-}
-
-/* Given operator, types of arg1, and arg2, return oper struct */
-/* arg1, arg2 --typeids */
-Operator
-oper(char *op, Oid arg1, Oid arg2, bool noWarnings)
-{
-       HeapTuple       tup;
-       CandidateList candidates;
-       int                     ncandidates;
-
-       if (!arg2)
-               arg2 = arg1;
-       if (!arg1)
-               arg1 = arg2;
-
-       if (!(tup = SearchSysCacheTuple(OPRNAME,
-                                                                       PointerGetDatum(op),
-                                                                       ObjectIdGetDatum(arg1),
-                                                                       ObjectIdGetDatum(arg2),
-                                                                       Int8GetDatum('b'))))
-       {
-               ncandidates = binary_oper_get_candidates(op, arg1, arg2, &candidates);
-               if (ncandidates == 0)
-               {
-
-                       /*
-                        * no operators of the desired types found
-                        */
-                       if (!noWarnings)
-                               op_error(op, arg1, arg2);
-                       return (NULL);
-               }
-               else if (ncandidates == 1)
-               {
-
-                       /*
-                        * exactly one operator of the desired types found
-                        */
-                       tup = SearchSysCacheTuple(OPRNAME,
-                                                                         PointerGetDatum(op),
-                                                                  ObjectIdGetDatum(candidates->args[0]),
-                                                                  ObjectIdGetDatum(candidates->args[1]),
-                                                                         Int8GetDatum('b'));
-                       Assert(HeapTupleIsValid(tup));
-               }
-               else
-               {
-
-                       /*
-                        * multiple operators of the desired types found
-                        */
-                       candidates = binary_oper_select_candidate(arg1, arg2, candidates);
-                       if (candidates != NULL)
-                       {
-                               /* we chose one of them */
-                               tup = SearchSysCacheTuple(OPRNAME,
-                                                                                 PointerGetDatum(op),
-                                                                  ObjectIdGetDatum(candidates->args[0]),
-                                                                  ObjectIdGetDatum(candidates->args[1]),
-                                                                                 Int8GetDatum('b'));
-                               Assert(HeapTupleIsValid(tup));
-                       }
-                       else
-                       {
-                               Type            tp1,
-                                                       tp2;
-
-                               /* we chose none of them */
-                               tp1 = get_id_type(arg1);
-                               tp2 = get_id_type(arg2);
-                               if (!noWarnings)
-                               {
-                                       elog(NOTICE, "there is more than one operator %s for types", op);
-                                       elog(NOTICE, "%s and %s. You will have to retype this query",
-                                                tname(tp1), tname(tp2));
-                                       elog(WARN, "using an explicit cast");
-                               }
-                               return (NULL);
-                       }
-               }
-       }
-       return ((Operator) tup);
-}
-
-/*
- *     given opname and typeId, find all possible types for which
- *     a right/left unary operator named opname exists,
- *     such that typeId can be coerced to it
- */
-static int
-unary_oper_get_candidates(char *op,
-                                                 Oid typeId,
-                                                 CandidateList *candidates,
-                                                 char rightleft)
-{
-       CandidateList current_candidate;
-       Relation        pg_operator_desc;
-       HeapScanDesc pg_operator_scan;
-       HeapTuple       tup;
-       OperatorTupleForm oper;
-       Buffer          buffer;
-       int                     ncandidates = 0;
-
-       static ScanKeyData opKey[2] = {
-               {0, Anum_pg_operator_oprname, NameEqualRegProcedure},
-       {0, Anum_pg_operator_oprkind, CharacterEqualRegProcedure}};
-
-       *candidates = NULL;
-
-       fmgr_info(NameEqualRegProcedure, (func_ptr *) &opKey[0].sk_func,
-                         &opKey[0].sk_nargs);
-       opKey[0].sk_argument = NameGetDatum(op);
-       fmgr_info(CharacterEqualRegProcedure, (func_ptr *) &opKey[1].sk_func,
-                         &opKey[1].sk_nargs);
-       opKey[1].sk_argument = CharGetDatum(rightleft);
-
-       /* currently, only "unknown" can be coerced */
-
-       /*
-        * but we should allow types that are internally the same to be
-        * "coerced"
-        */
-       if (typeId != UNKNOWNOID)
-       {
-               return 0;
-       }
-
-       pg_operator_desc = heap_openr(OperatorRelationName);
-       pg_operator_scan = heap_beginscan(pg_operator_desc,
-                                                                         0,
-                                                                         true,
-                                                                         2,
-                                                                         opKey);
-
-       do
-       {
-               tup = heap_getnext(pg_operator_scan, 0, &buffer);
-               if (HeapTupleIsValid(tup))
-               {
-                       current_candidate = (CandidateList) palloc(sizeof(struct _CandidateList));
-                       current_candidate->args = (Oid *) palloc(sizeof(Oid));
-
-                       oper = (OperatorTupleForm) GETSTRUCT(tup);
-                       if (rightleft == 'r')
-                               current_candidate->args[0] = oper->oprleft;
-                       else
-                               current_candidate->args[0] = oper->oprright;
-                       current_candidate->next = *candidates;
-                       *candidates = current_candidate;
-                       ncandidates++;
-                       ReleaseBuffer(buffer);
-               }
-       } while (HeapTupleIsValid(tup));
-
-       heap_endscan(pg_operator_scan);
-       heap_close(pg_operator_desc);
-
-       return ncandidates;
-}
-
-/* Given unary right-side operator (operator on right), return oper struct */
-/* arg-- type id */
-Operator
-right_oper(char *op, Oid arg)
-{
-       HeapTuple       tup;
-       CandidateList candidates;
-       int                     ncandidates;
-
-       /*
-        * if (!OpCache) { init_op_cache(); }
-        */
-       if (!(tup = SearchSysCacheTuple(OPRNAME,
-                                                                       PointerGetDatum(op),
-                                                                       ObjectIdGetDatum(arg),
-                                                                       ObjectIdGetDatum(InvalidOid),
-                                                                       Int8GetDatum('r'))))
-       {
-               ncandidates = unary_oper_get_candidates(op, arg, &candidates, 'r');
-               if (ncandidates == 0)
-               {
-                       elog(WARN,
-                                "Can't find right op: %s for type %d", op, arg);
-                       return (NULL);
-               }
-               else if (ncandidates == 1)
-               {
-                       tup = SearchSysCacheTuple(OPRNAME,
-                                                                         PointerGetDatum(op),
-                                                                  ObjectIdGetDatum(candidates->args[0]),
-                                                                         ObjectIdGetDatum(InvalidOid),
-                                                                         Int8GetDatum('r'));
-                       Assert(HeapTupleIsValid(tup));
-               }
-               else
-               {
-                       elog(NOTICE, "there is more than one right operator %s", op);
-                       elog(NOTICE, "you will have to retype this query");
-                       elog(WARN, "using an explicit cast");
-                       return (NULL);
-               }
-       }
-       return ((Operator) tup);
-}
-
-/* Given unary left-side operator (operator on left), return oper struct */
-/* arg--type id */
-Operator
-left_oper(char *op, Oid arg)
-{
-       HeapTuple       tup;
-       CandidateList candidates;
-       int                     ncandidates;
-
-       /*
-        * if (!OpCache) { init_op_cache(); }
-        */
-       if (!(tup = SearchSysCacheTuple(OPRNAME,
-                                                                       PointerGetDatum(op),
-                                                                       ObjectIdGetDatum(InvalidOid),
-                                                                       ObjectIdGetDatum(arg),
-                                                                       Int8GetDatum('l'))))
-       {
-               ncandidates = unary_oper_get_candidates(op, arg, &candidates, 'l');
-               if (ncandidates == 0)
-               {
-                       elog(WARN,
-                                "Can't find left op: %s for type %d", op, arg);
-                       return (NULL);
-               }
-               else if (ncandidates == 1)
-               {
-                       tup = SearchSysCacheTuple(OPRNAME,
-                                                                         PointerGetDatum(op),
-                                                                         ObjectIdGetDatum(InvalidOid),
-                                                                  ObjectIdGetDatum(candidates->args[0]),
-                                                                         Int8GetDatum('l'));
-                       Assert(HeapTupleIsValid(tup));
-               }
-               else
-               {
-                       elog(NOTICE, "there is more than one left operator %s", op);
-                       elog(NOTICE, "you will have to retype this query");
-                       elog(WARN, "using an explicit cast");
-                       return (NULL);
-               }
-       }
-       return ((Operator) tup);
-}
-
-/* given range variable, return id of variable */
-
-int
-varattno(Relation rd, char *a)
-{
-       int                     i;
-
-       for (i = 0; i < rd->rd_rel->relnatts; i++)
-       {
-               if (!namestrcmp(&(rd->rd_att->attrs[i]->attname), a))
-               {
-                       return (i + 1);
-               }
-       }
-       for (i = 0; i < SPECIALS; i++)
-       {
-               if (!strcmp(special_attr[i].field, a))
-               {
-                       return (special_attr[i].code);
-               }
-       }
-
-       elog(WARN, "Relation %s does not have attribute %s",
-                RelationGetRelationName(rd), a);
-       return (-1);
-}
-
-/* Given range variable, return whether attribute of this name
- * is a set.
- * NOTE the ASSUMPTION here that no system attributes are, or ever
- * will be, sets.
- */
-bool
-varisset(Relation rd, char *name)
-{
-       int                     i;
-
-       /* First check if this is a system attribute */
-       for (i = 0; i < SPECIALS; i++)
-       {
-               if (!strcmp(special_attr[i].field, name))
-               {
-                       return (false);         /* no sys attr is a set */
-               }
-       }
-       return (get_attisset(rd->rd_id, name));
-}
-
-/* given range variable, return id of variable */
-int
-nf_varattno(Relation rd, char *a)
-{
-       int                     i;
-
-       for (i = 0; i < rd->rd_rel->relnatts; i++)
-       {
-               if (!namestrcmp(&(rd->rd_att->attrs[i]->attname), a))
-               {
-                       return (i + 1);
-               }
-       }
-       for (i = 0; i < SPECIALS; i++)
-       {
-               if (!strcmp(special_attr[i].field, a))
-               {
-                       return (special_attr[i].code);
-               }
-       }
-       return InvalidAttrNumber;
-}
-
-/*-------------
- * given an attribute number and a relation, return its relation name
- */
-char      *
-getAttrName(Relation rd, int attrno)
-{
-       char       *name;
-       int                     i;
-
-       if (attrno < 0)
-       {
-               for (i = 0; i < SPECIALS; i++)
-               {
-                       if (special_attr[i].code == attrno)
-                       {
-                               name = special_attr[i].field;
-                               return (name);
-                       }
-               }
-               elog(WARN, "Illegal attr no %d for relation %s",
-                        attrno, RelationGetRelationName(rd));
-       }
-       else if (attrno >= 1 && attrno <= RelationGetNumberOfAttributes(rd))
-       {
-               name = (rd->rd_att->attrs[attrno - 1]->attname).data;
-               return (name);
-       }
-       else
-       {
-               elog(WARN, "Illegal attr no %d for relation %s",
-                        attrno, RelationGetRelationName(rd));
-       }
-
-       /*
-        * Shouldn't get here, but we want lint to be happy...
-        */
-
-       return (NULL);
-}
-
-/* Given a typename and value, returns the ascii form of the value */
-
-#ifdef NOT_USED
-char      *
-outstr(char *typename,                 /* Name of type of value */
-          char *value)                         /* Could be of any type */
-{
-       TypeTupleForm tp;
-       Oid                     op;
-
-       tp = (TypeTupleForm) GETSTRUCT(type(typename));
-       op = tp->typoutput;
-       return ((char *) fmgr(op, value));
-}
-
-#endif
-
-/* Given a Type and a string, return the internal form of that string */
-char      *
-instr2(Type tp, char *string, int typlen)
-{
-       return (instr1((TypeTupleForm) GETSTRUCT(tp), string, typlen));
-}
-
-/* Given a type structure and a string, returns the internal form of
-   that string */
-static char *
-instr1(TypeTupleForm tp, char *string, int typlen)
-{
-       Oid                     op;
-       Oid                     typelem;
-
-       op = tp->typinput;
-       typelem = tp->typelem;          /* XXX - used for array_in */
-       /* typlen is for bpcharin() and varcharin() */
-       return ((char *) fmgr(op, string, typelem, typlen));
-}
-
-/* Given the attribute type of an array return the arrtribute type of
-   an element of the array */
-
-Oid
-GetArrayElementType(Oid typearray)
-{
-       HeapTuple       type_tuple;
-       TypeTupleForm type_struct_array;
-
-       type_tuple = SearchSysCacheTuple(TYPOID,
-                                                                        ObjectIdGetDatum(typearray),
-                                                                        0, 0, 0);
-
-       if (!HeapTupleIsValid(type_tuple))
-               elog(WARN, "GetArrayElementType: Cache lookup failed for type %d",
-                        typearray);
-
-       /* get the array type struct from the type tuple */
-       type_struct_array = (TypeTupleForm) GETSTRUCT(type_tuple);
-
-       if (type_struct_array->typelem == InvalidOid)
-       {
-               elog(WARN, "GetArrayElementType: type %s is not an array",
-                        (Name) &(type_struct_array->typname.data[0]));
-       }
-
-       return (type_struct_array->typelem);
-}
-
-Oid
-funcid_get_rettype(Oid funcid)
-{
-       HeapTuple       func_tuple = NULL;
-       Oid                     funcrettype = (Oid) 0;
-
-       func_tuple = SearchSysCacheTuple(PROOID, ObjectIdGetDatum(funcid),
-                                                                        0, 0, 0);
-
-       if (!HeapTupleIsValid(func_tuple))
-               elog(WARN, "function  %d does not exist", funcid);
-
-       funcrettype = (Oid)
-               ((Form_pg_proc) GETSTRUCT(func_tuple))->prorettype;
-
-       return (funcrettype);
-}
-
-/*
- * get a list of all argument type vectors for which a function named
- * funcname taking nargs arguments exists
- */
-static CandidateList
-func_get_candidates(char *funcname, int nargs)
-{
-       Relation        heapRelation;
-       Relation        idesc;
-       ScanKeyData skey;
-       HeapTuple       tuple;
-       IndexScanDesc sd;
-       RetrieveIndexResult indexRes;
-       Buffer          buffer;
-       Form_pg_proc pgProcP;
-       bool            bufferUsed = FALSE;
-       CandidateList candidates = NULL;
-       CandidateList current_candidate;
-       int                     i;
-
-       heapRelation = heap_openr(ProcedureRelationName);
-       ScanKeyEntryInitialize(&skey,
-                                                  (bits16) 0x0,
-                                                  (AttrNumber) 1,
-                                                  (RegProcedure) NameEqualRegProcedure,
-                                                  (Datum) funcname);
-
-       idesc = index_openr(ProcedureNameIndex);
-
-       sd = index_beginscan(idesc, false, 1, &skey);
-
-       do
-       {
-               tuple = (HeapTuple) NULL;
-               if (bufferUsed)
-               {
-                       ReleaseBuffer(buffer);
-                       bufferUsed = FALSE;
-               }
-
-               indexRes = index_getnext(sd, ForwardScanDirection);
-               if (indexRes)
-               {
-                       ItemPointer iptr;
-
-                       iptr = &indexRes->heap_iptr;
-                       tuple = heap_fetch(heapRelation, false, iptr, &buffer);
-                       pfree(indexRes);
-                       if (HeapTupleIsValid(tuple))
-                       {
-                               pgProcP = (Form_pg_proc) GETSTRUCT(tuple);
-                               bufferUsed = TRUE;
-                               if (pgProcP->pronargs == nargs)
-                               {
-                                       current_candidate = (CandidateList)
-                                               palloc(sizeof(struct _CandidateList));
-                                       current_candidate->args = (Oid *)
-                                               palloc(8 * sizeof(Oid));
-                                       MemSet(current_candidate->args, 0, 8 * sizeof(Oid));
-                                       for (i = 0; i < nargs; i++)
-                                       {
-                                               current_candidate->args[i] =
-                                                       pgProcP->proargtypes[i];
-                                       }
-
-                                       current_candidate->next = candidates;
-                                       candidates = current_candidate;
-                               }
-                       }
-               }
-       } while (indexRes);
-
-       index_endscan(sd);
-       index_close(idesc);
-       heap_close(heapRelation);
-
-       return candidates;
-}
-
-/*
- * can input_typeids be coerced to func_typeids?
- */
-static bool
-can_coerce(int nargs, Oid *input_typeids, Oid *func_typeids)
-{
-       int                     i;
-       Type            tp;
-
-       /*
-        * right now, we only coerce "unknown", and we cannot coerce it to a
-        * relation type
-        */
-       for (i = 0; i < nargs; i++)
-       {
-               if (input_typeids[i] != func_typeids[i])
-               {
-                       if ((input_typeids[i] == BPCHAROID && func_typeids[i] == TEXTOID) ||
-                               (input_typeids[i] == BPCHAROID && func_typeids[i] == VARCHAROID) ||
-                               (input_typeids[i] == VARCHAROID && func_typeids[i] == TEXTOID) ||
-                               (input_typeids[i] == VARCHAROID && func_typeids[i] == BPCHAROID) ||
-                       (input_typeids[i] == CASHOID && func_typeids[i] == INT4OID) ||
-                        (input_typeids[i] == INT4OID && func_typeids[i] == CASHOID))
-                               ;                               /* these are OK */
-                       else if (input_typeids[i] != UNKNOWNOID || func_typeids[i] == 0)
-                               return false;
-
-                       tp = get_id_type(input_typeids[i]);
-                       if (typetypetype(tp) == 'c')
-                               return false;
-               }
-       }
-
-       return true;
-}
-
-/*
- * given a list of possible typeid arrays to a function and an array of
- * input typeids, produce a shortlist of those function typeid arrays
- * that match the input typeids (either exactly or by coercion), and
- * return the number of such arrays
- */
-static int
-match_argtypes(int nargs,
-                          Oid *input_typeids,
-                          CandidateList function_typeids,
-                          CandidateList *candidates)           /* return value */
-{
-       CandidateList current_candidate;
-       CandidateList matching_candidate;
-       Oid                *current_typeids;
-       int                     ncandidates = 0;
-
-       *candidates = NULL;
-
-       for (current_candidate = function_typeids;
-                current_candidate != NULL;
-                current_candidate = current_candidate->next)
-       {
-               current_typeids = current_candidate->args;
-               if (can_coerce(nargs, input_typeids, current_typeids))
-               {
-                       matching_candidate = (CandidateList)
-                               palloc(sizeof(struct _CandidateList));
-                       matching_candidate->args = current_typeids;
-                       matching_candidate->next = *candidates;
-                       *candidates = matching_candidate;
-                       ncandidates++;
-               }
-       }
-
-       return ncandidates;
-}
-
-/*
- * given the input argtype array and more than one candidate
- * for the function argtype array, attempt to resolve the conflict.
- * returns the selected argtype array if the conflict can be resolved,
- * otherwise returns NULL
- */
-static Oid *
-func_select_candidate(int nargs,
-                                         Oid *input_typeids,
-                                         CandidateList candidates)
-{
-       /* XXX no conflict resolution implemeneted yet */
-       return (NULL);
-}
-
-bool
-func_get_detail(char *funcname,
-                               int nargs,
-                               Oid *oid_array,
-                               Oid *funcid,    /* return value */
-                               Oid *rettype,   /* return value */
-                               bool *retset,   /* return value */
-                               Oid **true_typeids)             /* return value */
-{
-       Oid               **input_typeid_vector;
-       Oid                *current_input_typeids;
-       CandidateList function_typeids;
-       CandidateList current_function_typeids;
-       HeapTuple       ftup;
-       Form_pg_proc pform;
-
-       /*
-        * attempt to find named function in the system catalogs with
-        * arguments exactly as specified - so that the normal case is just as
-        * quick as before
-        */
-       ftup = SearchSysCacheTuple(PRONAME,
-                                                          PointerGetDatum(funcname),
-                                                          Int32GetDatum(nargs),
-                                                          PointerGetDatum(oid_array),
-                                                          0);
-       *true_typeids = oid_array;
-
-       /*
-        * If an exact match isn't found : 1) get a vector of all possible
-        * input arg type arrays constructed from the superclasses of the
-        * original input arg types 2) get a list of all possible argument
-        * type arrays to the function with given name and number of arguments
-        * 3) for each input arg type array from vector #1 : a) find how many
-        * of the function arg type arrays from list #2 it can be coerced to
-        * b) - if the answer is one, we have our function - if the answer is
-        * more than one, attempt to resolve the conflict - if the answer is
-        * zero, try the next array from vector #1
-        */
-       if (!HeapTupleIsValid(ftup))
-       {
-               function_typeids = func_get_candidates(funcname, nargs);
-
-               if (function_typeids != NULL)
-               {
-                       int                     ncandidates = 0;
-
-                       input_typeid_vector = argtype_inherit(nargs, oid_array);
-                       current_input_typeids = oid_array;
-
-                       do
-                       {
-                               ncandidates = match_argtypes(nargs, current_input_typeids,
-                                                                                        function_typeids,
-                                                                                        &current_function_typeids);
-                               if (ncandidates == 1)
-                               {
-                                       *true_typeids = current_function_typeids->args;
-                                       ftup = SearchSysCacheTuple(PRONAME,
-                                                                                          PointerGetDatum(funcname),
-                                                                                          Int32GetDatum(nargs),
-                                                                                 PointerGetDatum(*true_typeids),
-                                                                                          0);
-                                       Assert(HeapTupleIsValid(ftup));
-                               }
-                               else if (ncandidates > 1)
-                               {
-                                       *true_typeids =
-                                               func_select_candidate(nargs,
-                                                                                         current_input_typeids,
-                                                                                         current_function_typeids);
-                                       if (*true_typeids == NULL)
-                                       {
-                                               elog(NOTICE, "there is more than one function named \"%s\"",
-                                                        funcname);
-                                               elog(NOTICE, "that satisfies the given argument types. you will have to");
-                                               elog(NOTICE, "retype your query using explicit typecasts.");
-                                               func_error("func_get_detail", funcname, nargs, oid_array);
-                                       }
-                                       else
-                                       {
-                                               ftup = SearchSysCacheTuple(PRONAME,
-                                                                                          PointerGetDatum(funcname),
-                                                                                                  Int32GetDatum(nargs),
-                                                                                 PointerGetDatum(*true_typeids),
-                                                                                                  0);
-                                               Assert(HeapTupleIsValid(ftup));
-                                       }
-                               }
-                               current_input_typeids = *input_typeid_vector++;
-                       }
-                       while (current_input_typeids !=
-                                  InvalidOid && ncandidates == 0);
-               }
-       }
-
-       if (!HeapTupleIsValid(ftup))
-       {
-               Type            tp;
-
-               if (nargs == 1)
-               {
-                       tp = get_id_type(oid_array[0]);
-                       if (typetypetype(tp) == 'c')
-                               elog(WARN, "no such attribute or function \"%s\"",
-                                        funcname);
-               }
-               func_error("func_get_detail", funcname, nargs, oid_array);
-       }
-       else
-       {
-               pform = (Form_pg_proc) GETSTRUCT(ftup);
-               *funcid = ftup->t_oid;
-               *rettype = pform->prorettype;
-               *retset = pform->proretset;
-
-               return (true);
-       }
-/* shouldn't reach here */
-       return (false);
-
-}
-
-/*
- *     argtype_inherit() -- Construct an argtype vector reflecting the
- *                                              inheritance properties of the supplied argv.
- *
- *             This function is used to disambiguate among functions with the
- *             same name but different signatures.  It takes an array of eight
- *             type ids.  For each type id in the array that's a complex type
- *             (a class), it walks up the inheritance tree, finding all
- *             superclasses of that type.      A vector of new Oid type arrays
- *             is returned to the caller, reflecting the structure of the
- *             inheritance tree above the supplied arguments.
- *
- *             The order of this vector is as follows:  all superclasses of the
- *             rightmost complex class are explored first.  The exploration
- *             continues from right to left.  This policy means that we favor
- *             keeping the leftmost argument type as low in the inheritance tree
- *             as possible.  This is intentional; it is exactly what we need to
- *             do for method dispatch.  The last type array we return is all
- *             zeroes.  This will match any functions for which return types are
- *             not defined.  There are lots of these (mostly builtins) in the
- *             catalogs.
- */
-static Oid **
-argtype_inherit(int nargs, Oid *oid_array)
-{
-       Oid                     relid;
-       int                     i;
-       InhPaths        arginh[MAXFARGS];
-
-       for (i = 0; i < MAXFARGS; i++)
-       {
-               if (i < nargs)
-               {
-                       arginh[i].self = oid_array[i];
-                       if ((relid = typeid_get_relid(oid_array[i])) != InvalidOid)
-                       {
-                               arginh[i].nsupers = findsupers(relid, &(arginh[i].supervec));
-                       }
-                       else
-                       {
-                               arginh[i].nsupers = 0;
-                               arginh[i].supervec = (Oid *) NULL;
-                       }
-               }
-               else
-               {
-                       arginh[i].self = InvalidOid;
-                       arginh[i].nsupers = 0;
-                       arginh[i].supervec = (Oid *) NULL;
-               }
-       }
-
-       /* return an ordered cross-product of the classes involved */
-       return (genxprod(arginh, nargs));
-}
-
-typedef struct _SuperQE
-{
-       Oid                     sqe_relid;
-} SuperQE;
-
-static int
-findsupers(Oid relid, Oid **supervec)
-{
-       Oid                *relidvec;
-       Relation        inhrel;
-       HeapScanDesc inhscan;
-       ScanKeyData skey;
-       HeapTuple       inhtup;
-       TupleDesc       inhtupdesc;
-       int                     nvisited;
-       SuperQE    *qentry,
-                          *vnode;
-       Dllist     *visited,
-                          *queue;
-       Dlelem     *qe,
-                          *elt;
-
-       Relation        rd;
-       Buffer          buf;
-       Datum           d;
-       bool            newrelid;
-       char            isNull;
-
-       nvisited = 0;
-       queue = DLNewList();
-       visited = DLNewList();
-
-
-       inhrel = heap_openr(InheritsRelationName);
-       RelationSetLockForRead(inhrel);
-       inhtupdesc = RelationGetTupleDescriptor(inhrel);
-
-       /*
-        * Use queue to do a breadth-first traversal of the inheritance graph
-        * from the relid supplied up to the root.
-        */
-       do
-       {
-               ScanKeyEntryInitialize(&skey, 0x0, Anum_pg_inherits_inhrel,
-                                                          ObjectIdEqualRegProcedure,
-                                                          ObjectIdGetDatum(relid));
-
-               inhscan = heap_beginscan(inhrel, 0, false, 1, &skey);
-
-               while (HeapTupleIsValid(inhtup = heap_getnext(inhscan, 0, &buf)))
-               {
-                       qentry = (SuperQE *) palloc(sizeof(SuperQE));
-
-                       d = fastgetattr(inhtup, Anum_pg_inherits_inhparent,
-                                                       inhtupdesc, &isNull);
-                       qentry->sqe_relid = DatumGetObjectId(d);
-
-                       /* put this one on the queue */
-                       DLAddTail(queue, DLNewElem(qentry));
-
-                       ReleaseBuffer(buf);
-               }
-
-               heap_endscan(inhscan);
-
-               /* pull next unvisited relid off the queue */
-               do
-               {
-                       qe = DLRemHead(queue);
-                       qentry = qe ? (SuperQE *) DLE_VAL(qe) : NULL;
-
-                       if (qentry == (SuperQE *) NULL)
-                               break;
-
-                       relid = qentry->sqe_relid;
-                       newrelid = true;
-
-                       for (elt = DLGetHead(visited); elt; elt = DLGetSucc(elt))
-                       {
-                               vnode = (SuperQE *) DLE_VAL(elt);
-                               if (vnode && (qentry->sqe_relid == vnode->sqe_relid))
-                               {
-                                       newrelid = false;
-                                       break;
-                               }
-                       }
-               } while (!newrelid);
-
-               if (qentry != (SuperQE *) NULL)
-               {
-
-                       /* save the type id, rather than the relation id */
-                       if ((rd = heap_open(qentry->sqe_relid)) == (Relation) NULL)
-                               elog(WARN, "relid %d does not exist", qentry->sqe_relid);
-                       qentry->sqe_relid = typeid(type(RelationGetRelationName(rd)->data));
-                       heap_close(rd);
-
-                       DLAddTail(visited, qe);
-
-                       nvisited++;
-               }
-       } while (qentry != (SuperQE *) NULL);
-
-       RelationUnsetLockForRead(inhrel);
-       heap_close(inhrel);
-
-       if (nvisited > 0)
-       {
-               relidvec = (Oid *) palloc(nvisited * sizeof(Oid));
-               *supervec = relidvec;
-
-               for (elt = DLGetHead(visited); elt; elt = DLGetSucc(elt))
-               {
-                       vnode = (SuperQE *) DLE_VAL(elt);
-                       *relidvec++ = vnode->sqe_relid;
-               }
-
-       }
-       else
-       {
-               *supervec = (Oid *) NULL;
-       }
-
-       return (nvisited);
-}
-
-static Oid **
-genxprod(InhPaths *arginh, int nargs)
-{
-       int                     nanswers;
-       Oid               **result,
-                         **iter;
-       Oid                *oneres;
-       int                     i,
-                               j;
-       int                     cur[MAXFARGS];
-
-       nanswers = 1;
-       for (i = 0; i < nargs; i++)
-       {
-               nanswers *= (arginh[i].nsupers + 2);
-               cur[i] = 0;
-       }
-
-       iter = result = (Oid **) palloc(sizeof(Oid *) * nanswers);
-
-       /* compute the cross product from right to left */
-       for (;;)
-       {
-               oneres = (Oid *) palloc(MAXFARGS * sizeof(Oid));
-               MemSet(oneres, 0, MAXFARGS * sizeof(Oid));
-
-               for (i = nargs - 1; i >= 0 && cur[i] > arginh[i].nsupers; i--)
-                       continue;
-
-               /* if we're done, terminate with NULL pointer */
-               if (i < 0)
-               {
-                       *iter = NULL;
-                       return (result);
-               }
-
-               /* no, increment this column and zero the ones after it */
-               cur[i] = cur[i] + 1;
-               for (j = nargs - 1; j > i; j--)
-                       cur[j] = 0;
-
-               for (i = 0; i < nargs; i++)
-               {
-                       if (cur[i] == 0)
-                               oneres[i] = arginh[i].self;
-                       else if (cur[i] > arginh[i].nsupers)
-                               oneres[i] = 0;  /* wild card */
-                       else
-                               oneres[i] = arginh[i].supervec[cur[i] - 1];
-               }
-
-               *iter++ = oneres;
-       }
-}
-
-/* Given a type id, returns the in-conversion function of the type */
-Oid
-typeid_get_retinfunc(Oid type_id)
-{
-       HeapTuple       typeTuple;
-       TypeTupleForm type;
-       Oid                     infunc;
-
-       typeTuple = SearchSysCacheTuple(TYPOID,
-                                                                       ObjectIdGetDatum(type_id),
-                                                                       0, 0, 0);
-       if (!HeapTupleIsValid(typeTuple))
-               elog(WARN, "typeid_get_retinfunc: Invalid type - oid = %u", type_id);
-
-       type = (TypeTupleForm) GETSTRUCT(typeTuple);
-       infunc = type->typinput;
-       return (infunc);
-}
-
-/* Given a type id, returns the out-conversion function of the type */
-Oid
-typeid_get_retoutfunc(Oid type_id)
-{
-       HeapTuple       typeTuple;
-       TypeTupleForm type;
-       Oid                     outfunc;
-
-       typeTuple = SearchSysCacheTuple(TYPOID,
-                                                                       ObjectIdGetDatum(type_id),
-                                                                       0, 0, 0);
-       if (!HeapTupleIsValid(typeTuple))
-               elog(WARN, "typeid_get_retoutfunc: Invalid type - oid = %u", type_id);
-
-       type = (TypeTupleForm) GETSTRUCT(typeTuple);
-       outfunc = type->typoutput;
-       return (outfunc);
-}
-
-Oid
-typeid_get_relid(Oid type_id)
-{
-       HeapTuple       typeTuple;
-       TypeTupleForm type;
-       Oid                     infunc;
-
-       typeTuple = SearchSysCacheTuple(TYPOID,
-                                                                       ObjectIdGetDatum(type_id),
-                                                                       0, 0, 0);
-       if (!HeapTupleIsValid(typeTuple))
-               elog(WARN, "typeid_get_relid: Invalid type - oid = %u", type_id);
-
-       type = (TypeTupleForm) GETSTRUCT(typeTuple);
-       infunc = type->typrelid;
-       return (infunc);
-}
-
-Oid
-get_typrelid(Type typ)
-{
-       TypeTupleForm typtup;
-
-       typtup = (TypeTupleForm) GETSTRUCT(typ);
-
-       return (typtup->typrelid);
-}
-
-Oid
-get_typelem(Oid type_id)
-{
-       HeapTuple       typeTuple;
-       TypeTupleForm type;
-
-       if (!(typeTuple = SearchSysCacheTuple(TYPOID,
-                                                                                 ObjectIdGetDatum(type_id),
-                                                                                 0, 0, 0)))
-       {
-               elog(WARN, "type id lookup of %u failed", type_id);
-       }
-       type = (TypeTupleForm) GETSTRUCT(typeTuple);
-
-       return (type->typelem);
-}
-
-#ifdef NOT_USED
-char
-FindDelimiter(char *typename)
-{
-       char            delim;
-       HeapTuple       typeTuple;
-       TypeTupleForm type;
-
-
-       if (!(typeTuple = SearchSysCacheTuple(TYPNAME,
-                                                                                 PointerGetDatum(typename),
-                                                                                 0, 0, 0)))
-       {
-               elog(WARN, "type name lookup of %s failed", typename);
-       }
-       type = (TypeTupleForm) GETSTRUCT(typeTuple);
-
-       delim = type->typdelim;
-       return (delim);
-}
-
-#endif
-
-/*
- * Give a somewhat useful error message when the operator for two types
- * is not found.
- */
-static void
-op_error(char *op, Oid arg1, Oid arg2)
-{
-       Type            tp1 = NULL,
-                               tp2 = NULL;
-
-       if (check_typeid(arg1))
-       {
-               tp1 = get_id_type(arg1);
-       }
-       else
-       {
-               elog(WARN, "left hand side of operator %s has an unknown type, probably a bad attribute name", op);
-       }
-
-       if (check_typeid(arg2))
-       {
-               tp2 = get_id_type(arg2);
-       }
-       else
-       {
-               elog(WARN, "right hand side of operator %s has an unknown type, probably a bad attribute name", op);
-       }
-
-       elog(NOTICE, "there is no operator %s for types %s and %s",
-                op, tname(tp1), tname(tp2));
-       elog(NOTICE, "You will either have to retype this query using an");
-       elog(NOTICE, "explicit cast, or you will have to define the operator");
-       elog(WARN, "%s for %s and %s using CREATE OPERATOR",
-                op, tname(tp1), tname(tp2));
-}
-
-/*
- * Error message when function lookup fails that gives details of the
- * argument types
- */
-void
-func_error(char *caller, char *funcname, int nargs, Oid *argtypes)
-{
-       char            p[(NAMEDATALEN + 2) * MAXFMGRARGS],
-                          *ptr;
-       int                     i;
-
-       ptr = p;
-       *ptr = '\0';
-       for (i = 0; i < nargs; i++)
-       {
-               if (i)
-               {
-                       *ptr++ = ',';
-                       *ptr++ = ' ';
-               }
-               if (argtypes[i] != 0)
-               {
-                       strcpy(ptr, tname(get_id_type(argtypes[i])));
-                       *(ptr + NAMEDATALEN) = '\0';
-               }
-               else
-                       strcpy(ptr, "opaque");
-               ptr += strlen(ptr);
-       }
-
-       elog(WARN, "%s: function %s(%s) does not exist", caller, funcname, p);
-}
-
-/*
- * Error message when aggregate lookup fails that gives details of the
- * basetype
- */
-void
-agg_error(char *caller, char *aggname, Oid basetypeID)
-{
-
-       /*
-        * basetypeID that is Invalid (zero) means aggregate over all types.
-        * (count)
-        */
-
-       if (basetypeID == InvalidOid)
-       {
-               elog(WARN, "%s: aggregate '%s' for all types does not exist", caller, aggname);
-       }
-       else
-       {
-               elog(WARN, "%s: aggregate '%s' for '%s' does not exist", caller, aggname,
-                        tname(get_id_type(basetypeID)));
-       }
-}
index abaedbb..d146b6e 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.71 1997/11/24 16:55:22 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.72 1997/11/25 22:05:29 momjian Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -39,8 +39,6 @@
 #include "nodes/parsenodes.h"
 #include "nodes/print.h"
 #include "parser/gramparse.h"
-#include "parser/catalog_utils.h"
-#include "parser/parse_query.h"
 #include "utils/acl.h"
 #include "catalog/catname.h"
 #include "utils/elog.h"
 static char saved_relname[NAMEDATALEN];  /* need this for complex attributes */
 static bool QueryIsRule = FALSE;
 static Node *saved_In_Expr;
+static Oid     *param_type_info;
+static int     pfunc_num_args;
 extern List *parsetree;
 
+
 /*
  * If you need access to certain yacc-generated variables and find that
  * they're static by default, uncomment the next line.  (this is not a
@@ -64,6 +65,9 @@ static List *makeConstantList( A_Const *node);
 static char *FlattenStringList(List *list);
 static char *fmtId(char *rawid);
 static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr);
+static void param_type_init(Oid *typev, int nargs);
+
+Oid    param_type(int t); /* used in parse_expr.c */
 
 /* old versions of flex define this as a macro */
 #if defined(yywrap)
@@ -2324,7 +2328,7 @@ Typename:  Array opt_array_bounds
                                                 * emp(name=text,mgr=emp)
                                                 */
                                                $$->setof = TRUE;
-                                       else if (get_typrelid((Type)type($$->name)) != InvalidOid)
+                                       else if (typeTypeRelid(typenameType($$->name)) != InvalidOid)
                                                 /* (Eventually add in here that the set can only
                                                  * contain one element.)
                                                  */
@@ -3690,4 +3694,24 @@ printf("fmtId- %sconvert %s to %s\n", ((cp == rawid)? "do not ": ""), rawid, cp)
 #endif
 
        return(cp);
-} /* fmtId() */
+}
+
+/*
+ * param_type_init()
+ *
+ * keep enough information around fill out the type of param nodes
+ * used in postquel functions
+ */
+static void
+param_type_init(Oid *typev, int nargs)
+{
+       pfunc_num_args = nargs;
+       param_type_info = typev;
+}
+
+Oid param_type(int t)
+{
+       if ((t > pfunc_num_args) || (t == 0))
+               return InvalidOid;
+       return param_type_info[t - 1];
+}
index 0312e02..1c4b63c 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.24 1997/11/24 05:32:28 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.25 1997/11/25 22:05:32 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,8 +18,8 @@
 #include "nodes/pg_list.h"
 #include "nodes/parsenodes.h"
 #include "parse.h"
-#include "utils/elog.h"
 #include "parser/keywords.h"
+#include "utils/elog.h"
 
 /*
  * List of (keyword-name, keyword-token-value) pairs.
diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c
new file mode 100644 (file)
index 0000000..b64b920
--- /dev/null
@@ -0,0 +1,371 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_agg.c--
+ *       handle aggregates in parser
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.1 1997/11/25 22:05:34 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "postgres.h"
+#include "access/heapam.h"
+#include "catalog/pg_aggregate.h"
+#include "nodes/nodeFuncs.h"
+#include "nodes/primnodes.h"
+#include "nodes/relation.h"
+#include "optimizer/clauses.h"
+#include "parser/parse_agg.h"
+#include "parser/parse_node.h"
+#include "parser/parse_target.h"
+#include "utils/syscache.h"
+
+#ifdef 0
+#include "nodes/nodes.h"
+#include "nodes/params.h"
+#include "parse.h"                             /* for AND, OR, etc. */
+#include "catalog/pg_type.h"   /* for INT4OID, etc. */
+#include "catalog/pg_proc.h"
+#include "utils/elog.h"
+#include "utils/builtins.h"            /* namecmp(), textout() */
+#include "utils/lsyscache.h"
+#include "utils/palloc.h"
+#include "utils/mcxt.h"
+#include "utils/acl.h"
+#include "nodes/makefuncs.h"   /* for makeResdom(), etc. */
+#include "commands/sequence.h"
+
+#endif
+
+/*
+ * AddAggToParseState -
+ *       add the aggregate to the list of unique aggregates in pstate.
+ *
+ * SIDE EFFECT: aggno in target list entry will be modified
+ */
+void
+AddAggToParseState(ParseState *pstate, Aggreg *aggreg)
+{
+       List       *ag;
+       int                     i;
+
+       /*
+        * see if we have the aggregate already (we only need to record the
+        * aggregate once)
+        */
+       i = 0;
+       foreach(ag, pstate->p_aggs)
+       {
+               Aggreg     *a = lfirst(ag);
+
+               if (!strcmp(a->aggname, aggreg->aggname) &&
+                       equal(a->target, aggreg->target))
+               {
+
+                       /* fill in the aggno and we're done */
+                       aggreg->aggno = i;
+                       return;
+               }
+               i++;
+       }
+
+       /* not found, new aggregate */
+       aggreg->aggno = i;
+       pstate->p_numAgg++;
+       pstate->p_aggs = lappend(pstate->p_aggs, aggreg);
+       return;
+}
+
+/*
+ * finalizeAggregates -
+ *       fill in qry_aggs from pstate. Also checks to make sure that aggregates
+ *       are used in the proper place.
+ */
+void
+finalizeAggregates(ParseState *pstate, Query *qry)
+{
+       List       *l;
+       int                     i;
+
+       parseCheckAggregates(pstate, qry);
+
+       qry->qry_numAgg = pstate->p_numAgg;
+       qry->qry_aggs =
+               (Aggreg **) palloc(sizeof(Aggreg *) * qry->qry_numAgg);
+       i = 0;
+       foreach(l, pstate->p_aggs)
+               qry->qry_aggs[i++] = (Aggreg *) lfirst(l);
+}
+
+/*
+ * contain_agg_clause--
+ *       Recursively find aggreg nodes from a clause.
+ *
+ *       Returns true if any aggregate found.
+ */
+bool
+contain_agg_clause(Node *clause)
+{
+       if (clause == NULL)
+               return FALSE;
+       else if (IsA(clause, Aggreg))
+               return TRUE;
+       else if (IsA(clause, Iter))
+               return contain_agg_clause(((Iter *) clause)->iterexpr);
+       else if (single_node(clause))
+               return FALSE;
+       else if (or_clause(clause))
+       {
+               List       *temp;
+
+               foreach(temp, ((Expr *) clause)->args)
+                       if (contain_agg_clause(lfirst(temp)))
+                       return TRUE;
+               return FALSE;
+       }
+       else if (is_funcclause(clause))
+       {
+               List       *temp;
+
+               foreach(temp, ((Expr *) clause)->args)
+                       if (contain_agg_clause(lfirst(temp)))
+                       return TRUE;
+               return FALSE;
+       }
+       else if (IsA(clause, ArrayRef))
+       {
+               List       *temp;
+
+               foreach(temp, ((ArrayRef *) clause)->refupperindexpr)
+                       if (contain_agg_clause(lfirst(temp)))
+                       return TRUE;
+               foreach(temp, ((ArrayRef *) clause)->reflowerindexpr)
+                       if (contain_agg_clause(lfirst(temp)))
+                       return TRUE;
+               if (contain_agg_clause(((ArrayRef *) clause)->refexpr))
+                       return TRUE;
+               if (contain_agg_clause(((ArrayRef *) clause)->refassgnexpr))
+                       return TRUE;
+               return FALSE;
+       }
+       else if (not_clause(clause))
+               return contain_agg_clause((Node *) get_notclausearg((Expr *) clause));
+       else if (is_opclause(clause))
+               return (contain_agg_clause((Node *) get_leftop((Expr *) clause)) ||
+                         contain_agg_clause((Node *) get_rightop((Expr *) clause)));
+
+       return FALSE;
+}
+
+/*
+ * exprIsAggOrGroupCol -
+ *       returns true if the expression does not contain non-group columns.
+ */
+bool
+exprIsAggOrGroupCol(Node *expr, List *groupClause)
+{
+       List       *gl;
+
+       if (expr == NULL || IsA(expr, Const) ||
+               IsA(expr, Param) ||IsA(expr, Aggreg))
+               return TRUE;
+
+       foreach(gl, groupClause)
+       {
+               GroupClause *grpcl = lfirst(gl);
+
+               if (equal(expr, grpcl->entry->expr))
+                       return TRUE;
+       }
+
+       if (IsA(expr, Expr))
+       {
+               List       *temp;
+
+               foreach(temp, ((Expr *) expr)->args)
+                       if (!exprIsAggOrGroupCol(lfirst(temp), groupClause))
+                       return FALSE;
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+/*
+ * tleIsAggOrGroupCol -
+ *       returns true if the TargetEntry is Agg or GroupCol.
+ */
+bool
+tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause)
+{
+       Node       *expr = tle->expr;
+       List       *gl;
+
+       if (expr == NULL || IsA(expr, Const) ||IsA(expr, Param))
+               return TRUE;
+
+       foreach(gl, groupClause)
+       {
+               GroupClause *grpcl = lfirst(gl);
+
+               if (tle->resdom->resno == grpcl->entry->resdom->resno)
+               {
+                       if (contain_agg_clause((Node *) expr))
+                               elog(WARN, "parser: aggregates not allowed in GROUP BY clause");
+                       return TRUE;
+               }
+       }
+
+       if (IsA(expr, Aggreg))
+               return TRUE;
+
+       if (IsA(expr, Expr))
+       {
+               List       *temp;
+
+               foreach(temp, ((Expr *) expr)->args)
+                       if (!exprIsAggOrGroupCol(lfirst(temp), groupClause))
+                       return FALSE;
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+/*
+ * parseCheckAggregates -
+ *       this should really be done earlier but the current grammar
+ *       cannot differentiate functions from aggregates. So we have do check
+ *       here when the target list and the qualifications are finalized.
+ */
+void
+parseCheckAggregates(ParseState *pstate, Query *qry)
+{
+       List       *tl;
+
+       Assert(pstate->p_numAgg > 0);
+
+       /*
+        * aggregates never appear in WHERE clauses. (we have to check where
+        * clause first because if there is an aggregate, the check for
+        * non-group column in target list may fail.)
+        */
+       if (contain_agg_clause(qry->qual))
+               elog(WARN, "parser: aggregates not allowed in WHERE clause");
+
+       /*
+        * the target list can only contain aggregates, group columns and
+        * functions thereof.
+        */
+       foreach(tl, qry->targetList)
+       {
+               TargetEntry *tle = lfirst(tl);
+
+               if (!tleIsAggOrGroupCol(tle, qry->groupClause))
+                       elog(WARN,
+                                "parser: illegal use of aggregates or non-group column in target list");
+       }
+
+       /*
+        * the expression specified in the HAVING clause has the same
+        * restriction as those in the target list.
+        */
+/*
+ * Need to change here when we get HAVING works. Currently
+ * qry->havingQual is NULL.            - vadim 04/05/97
+       if (!exprIsAggOrGroupCol(qry->havingQual, qry->groupClause))
+               elog(WARN,
+                        "parser: illegal use of aggregates or non-group column in HAVING clause");
+ */
+       return;
+}
+
+
+Aggreg    *
+ParseAgg(char *aggname, Oid basetype, Node *target)
+{
+       Oid                     fintype;
+       Oid                     vartype;
+       Oid                     xfn1;
+       Form_pg_aggregate aggform;
+       Aggreg     *aggreg;
+       HeapTuple       theAggTuple;
+
+       theAggTuple = SearchSysCacheTuple(AGGNAME, PointerGetDatum(aggname),
+                                                                         ObjectIdGetDatum(basetype),
+                                                                         0, 0);
+       if (!HeapTupleIsValid(theAggTuple))
+       {
+               elog(WARN, "aggregate %s does not exist", aggname);
+       }
+
+       aggform = (Form_pg_aggregate) GETSTRUCT(theAggTuple);
+       fintype = aggform->aggfinaltype;
+       xfn1 = aggform->aggtransfn1;
+
+       if (nodeTag(target) != T_Var && nodeTag(target) != T_Expr)
+               elog(WARN, "parser: aggregate can only be applied on an attribute or expression");
+
+       /* only aggregates with transfn1 need a base type */
+       if (OidIsValid(xfn1))
+       {
+               basetype = aggform->aggbasetype;
+               if (nodeTag(target) == T_Var)
+                       vartype = ((Var *) target)->vartype;
+               else
+                       vartype = ((Expr *) target)->typeOid;
+
+               if (basetype != vartype)
+               {
+                       Type            tp1,
+                                               tp2;
+
+                       tp1 = typeidType(basetype);
+                       tp2 = typeidType(vartype);
+                       elog(NOTICE, "Aggregate type mismatch:");
+                       elog(WARN, "%s works on %s, not %s", aggname,
+                                typeTypeName(tp1), typeTypeName(tp2));
+               }
+       }
+
+       aggreg = makeNode(Aggreg);
+       aggreg->aggname = pstrdup(aggname);
+       aggreg->basetype = aggform->aggbasetype;
+       aggreg->aggtype = fintype;
+
+       aggreg->target = target;
+
+       return aggreg;
+}
+
+/*
+ * Error message when aggregate lookup fails that gives details of the
+ * basetype
+ */
+void
+agg_error(char *caller, char *aggname, Oid basetypeID)
+{
+
+       /*
+        * basetypeID that is Invalid (zero) means aggregate over all types.
+        * (count)
+        */
+
+       if (basetypeID == InvalidOid)
+       {
+               elog(WARN, "%s: aggregate '%s' for all types does not exist", caller, aggname);
+       }
+       else
+       {
+               elog(WARN, "%s: aggregate '%s' for '%s' does not exist", caller, aggname,
+                        typeidTypeName(basetypeID));
+       }
+}
+
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
new file mode 100644 (file)
index 0000000..8e08e00
--- /dev/null
@@ -0,0 +1,407 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_clause.c--
+ *       handle clauses in parser
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.1 1997/11/25 22:05:35 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "postgres.h"
+#include "access/heapam.h"
+#include "parser/parse_clause.h"
+#include "parser/parse_expr.h"
+#include "parser/parse_node.h"
+#include "parser/parse_oper.h"
+#include "parser/parse_relation.h"
+#include "parser/parse_target.h"
+#include "catalog/pg_type.h"
+
+#ifdef 0
+#include "nodes/nodes.h"
+#include "nodes/params.h"
+#include "nodes/primnodes.h"
+#include "nodes/parsenodes.h"
+#include "nodes/relation.h"
+#include "parse.h"                             /* for AND, OR, etc. */
+#include "catalog/pg_aggregate.h"
+#include "catalog/pg_proc.h"
+#include "utils/elog.h"
+#include "utils/builtins.h"            /* namecmp(), textout() */
+#include "utils/lsyscache.h"
+#include "utils/palloc.h"
+#include "utils/mcxt.h"
+#include "utils/syscache.h"
+#include "utils/acl.h"
+#include "nodes/makefuncs.h"   /* for makeResdom(), etc. */
+#include "nodes/nodeFuncs.h"
+#include "commands/sequence.h"
+
+#include "optimizer/clauses.h"
+
+#include "miscadmin.h"
+
+#include "port-protos.h"               /* strdup() */
+#endif
+
+/*
+ * parseFromClause -
+ *       turns the table references specified in the from-clause into a
+ *       range table. The range table may grow as we transform the expressions
+ *       in the target list. (Note that this happens because in POSTQUEL, we
+ *       allow references to relations not specified in the from-clause. We
+ *       also allow that in our POST-SQL)
+ *
+ */
+void
+parseFromClause(ParseState *pstate, List *frmList)
+{
+       List       *fl;
+
+       foreach(fl, frmList)
+       {
+               RangeVar   *r = lfirst(fl);
+               RelExpr    *baserel = r->relExpr;
+               char       *relname = baserel->relname;
+               char       *refname = r->name;
+               RangeTblEntry *rte;
+
+               if (refname == NULL)
+                       refname = relname;
+
+               /*
+                * marks this entry to indicate it comes from the FROM clause. In
+                * SQL, the target list can only refer to range variables
+                * specified in the from clause but we follow the more powerful
+                * POSTQUEL semantics and automatically generate the range
+                * variable if not specified. However there are times we need to
+                * know whether the entries are legitimate.
+                *
+                * eg. select * from foo f where f.x = 1; will generate wrong answer
+                * if we expand * to foo.x.
+                */
+               rte = addRangeTableEntry(pstate, relname, refname, baserel->inh, TRUE);
+       }
+}
+
+/*
+ * makeRangeTable -
+ *       make a range table with the specified relation (optional) and the
+ *       from-clause.
+ */
+void
+makeRangeTable(ParseState *pstate, char *relname, List *frmList)
+{
+       RangeTblEntry *rte;
+
+       parseFromClause(pstate, frmList);
+
+       if (relname == NULL)
+               return;
+
+       if (refnameRangeTablePosn(pstate->p_rtable, relname) < 1)
+               rte = addRangeTableEntry(pstate, relname, relname, FALSE, FALSE);
+       else
+               rte = refnameRangeTableEntry(pstate->p_rtable, relname);
+
+       pstate->p_target_rangetblentry = rte;
+       Assert(pstate->p_target_relation == NULL);
+       pstate->p_target_relation = heap_open(rte->relid);
+       Assert(pstate->p_target_relation != NULL);
+       /* will close relation later */
+}
+
+/*****************************************************************************
+ *
+ * Where Clause
+ *
+ *****************************************************************************/
+
+/*
+ * transformWhereClause -
+ *       transforms the qualification and make sure it is of type Boolean
+ *
+ */
+Node *
+transformWhereClause(ParseState *pstate, Node *a_expr)
+{
+       Node       *qual;
+
+       if (a_expr == NULL)
+               return (Node *) NULL;   /* no qualifiers */
+
+       pstate->p_in_where_clause = true;
+       qual = transformExpr(pstate, a_expr, EXPR_COLUMN_FIRST);
+       pstate->p_in_where_clause = false;
+       if (exprType(qual) != BOOLOID)
+       {
+               elog(WARN,
+                        "where clause must return type bool, not %s",
+                        typeidTypeName(exprType(qual)));
+       }
+       return qual;
+}
+
+/*****************************************************************************
+ *
+ * Sort Clause
+ *
+ *****************************************************************************/
+
+/*
+ *     find_targetlist_entry -
+ *       returns the Resdom in the target list matching the specified varname
+ *       and range
+ *
+ */
+TargetEntry *
+find_targetlist_entry(ParseState *pstate, SortGroupBy *sortgroupby, List *tlist)
+{
+       List       *i;
+       int                     real_rtable_pos = 0,
+                               target_pos = 0;
+       TargetEntry *target_result = NULL;
+
+       if (sortgroupby->range)
+               real_rtable_pos = refnameRangeTablePosn(pstate->p_rtable,
+                                                                                               sortgroupby->range);
+
+       foreach(i, tlist)
+       {
+               TargetEntry *target = (TargetEntry *) lfirst(i);
+               Resdom     *resnode = target->resdom;
+               Var                *var = (Var *) target->expr;
+               char       *resname = resnode->resname;
+               int                     test_rtable_pos = var->varno;
+
+#ifdef PARSEDEBUG
+               printf("find_targetlist_entry- target name is %s, position %d, resno %d\n",
+                          (sortgroupby->name ? sortgroupby->name : "(null)"), target_pos + 1, sortgroupby->resno);
+#endif
+
+               if (!sortgroupby->name)
+               {
+                       if (sortgroupby->resno == ++target_pos)
+                       {
+                               target_result = target;
+                               break;
+                       }
+               }
+               else
+               {
+                       if (!strcmp(resname, sortgroupby->name))
+                       {
+                               if (sortgroupby->range)
+                               {
+                                       if (real_rtable_pos == test_rtable_pos)
+                                       {
+                                               if (target_result != NULL)
+                                                       elog(WARN, "Order/Group By '%s' is ambiguous", sortgroupby->name);
+                                               else
+                                                       target_result = target;
+                                       }
+                               }
+                               else
+                               {
+                                       if (target_result != NULL)
+                                               elog(WARN, "Order/Group By '%s' is ambiguous", sortgroupby->name);
+                                       else
+                                               target_result = target;
+                               }
+                       }
+               }
+       }
+       return target_result;
+}
+
+/*
+ * transformGroupClause -
+ *       transform a Group By clause
+ *
+ */
+List *
+transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist)
+{
+       List       *glist = NIL,
+                          *gl = NIL;
+
+       while (grouplist != NIL)
+       {
+               GroupClause *grpcl = makeNode(GroupClause);
+               TargetEntry *restarget;
+               Resdom     *resdom;
+
+               restarget = find_targetlist_entry(pstate, lfirst(grouplist), targetlist);
+
+               if (restarget == NULL)
+                       elog(WARN, "The field being grouped by must appear in the target list");
+
+               grpcl->entry = restarget;
+               resdom = restarget->resdom;
+               grpcl->grpOpoid = oprid(oper("<",
+                                                                        resdom->restype,
+                                                                        resdom->restype, false));
+               if (glist == NIL)
+                       gl = glist = lcons(grpcl, NIL);
+               else
+               {
+                       List       *i;
+                       
+                       foreach (i, glist)
+                       {
+                               GroupClause *gcl = (GroupClause *) lfirst (i);
+                               
+                               if ( gcl->entry == grpcl->entry )
+                                       break;
+                       }
+                       if ( i == NIL )                 /* not in grouplist already */
+                       {
+                               lnext(gl) = lcons(grpcl, NIL);
+                               gl = lnext(gl);
+                       }
+                       else
+                               pfree (grpcl);          /* get rid of this */
+               }
+               grouplist = lnext(grouplist);
+       }
+
+       return glist;
+}
+
+/*
+ * transformSortClause -
+ *       transform an Order By clause
+ *
+ */
+List *
+transformSortClause(ParseState *pstate,
+                                       List *orderlist, List *targetlist,
+                                       char *uniqueFlag)
+{
+       List       *sortlist = NIL;
+       List       *s = NIL;
+
+       while (orderlist != NIL)
+       {
+               SortGroupBy *sortby = lfirst(orderlist);
+               SortClause *sortcl = makeNode(SortClause);
+               TargetEntry *restarget;
+               Resdom     *resdom;
+
+               restarget = find_targetlist_entry(pstate, sortby, targetlist);
+               if (restarget == NULL)
+                       elog(WARN, "The field being ordered by must appear in the target list");
+
+               sortcl->resdom = resdom = restarget->resdom;
+               sortcl->opoid = oprid(oper(sortby->useOp,
+                                                                  resdom->restype,
+                                                                  resdom->restype, false));
+               if (sortlist == NIL)
+               {
+                       s = sortlist = lcons(sortcl, NIL);
+               }
+               else
+               {
+                       List       *i;
+                       
+                       foreach (i, sortlist)
+                       {
+                               SortClause *scl = (SortClause *) lfirst (i);
+                               
+                               if ( scl->resdom == sortcl->resdom )
+                                       break;
+                       }
+                       if ( i == NIL )                 /* not in sortlist already */
+                       {
+                               lnext(s) = lcons(sortcl, NIL);
+                               s = lnext(s);
+                       }
+                       else
+                               pfree (sortcl);         /* get rid of this */
+               }
+               orderlist = lnext(orderlist);
+       }
+
+       if (uniqueFlag)
+       {
+               List       *i;
+               
+               if (uniqueFlag[0] == '*')
+               {
+
+                       /*
+                        * concatenate all elements from target list that are not
+                        * already in the sortby list
+                        */
+                       foreach(i, targetlist)
+                       {
+                               TargetEntry *tlelt = (TargetEntry *) lfirst(i);
+
+                               s = sortlist;
+                               while (s != NIL)
+                               {
+                                       SortClause *sortcl = lfirst(s);
+
+                                       if (sortcl->resdom == tlelt->resdom)
+                                               break;
+                                       s = lnext(s);
+                               }
+                               if (s == NIL)
+                               {
+                                       /* not a member of the sortclauses yet */
+                                       SortClause *sortcl = makeNode(SortClause);
+
+                                       sortcl->resdom = tlelt->resdom;
+                                       sortcl->opoid = any_ordering_op(tlelt->resdom->restype);
+
+                                       sortlist = lappend(sortlist, sortcl);
+                               }
+                       }
+               }
+               else
+               {
+                       TargetEntry *tlelt = NULL;
+                       char       *uniqueAttrName = uniqueFlag;
+
+                       /* only create sort clause with the specified unique attribute */
+                       foreach(i, targetlist)
+                       {
+                               tlelt = (TargetEntry *) lfirst(i);
+                               if (strcmp(tlelt->resdom->resname, uniqueAttrName) == 0)
+                                       break;
+                       }
+                       if (i == NIL)
+                       {
+                               elog(WARN, "The field specified in the UNIQUE ON clause is not in the targetlist");
+                       }
+                       s = sortlist;
+                       foreach(s, sortlist)
+                       {
+                               SortClause *sortcl = lfirst(s);
+
+                               if (sortcl->resdom == tlelt->resdom)
+                                       break;
+                       }
+                       if (s == NIL)
+                       {
+                               /* not a member of the sortclauses yet */
+                               SortClause *sortcl = makeNode(SortClause);
+
+                               sortcl->resdom = tlelt->resdom;
+                               sortcl->opoid = any_ordering_op(tlelt->resdom->restype);
+
+                               sortlist = lappend(sortlist, sortcl);
+                       }
+               }
+
+       }
+
+       return sortlist;
+}
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
new file mode 100644 (file)
index 0000000..fe00b2b
--- /dev/null
@@ -0,0 +1,694 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_expr.c
+ *       handle expressions in parser
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.1 1997/11/25 22:05:39 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "postgres.h"
+#include "catalog/pg_type.h"
+#include "nodes/makefuncs.h"
+#include "nodes/nodes.h"
+#include "nodes/params.h"
+#include "nodes/relation.h"
+#include "parser/parse_expr.h"
+#include "parser/parse_func.h"
+#include "parser/parse_node.h"
+#include "parser/parse_relation.h"
+#include "parser/parse_target.h"
+#include "parse.h"
+#include "utils/builtins.h"
+
+#ifdef 0
+#include "nodes/primnodes.h"
+#include "nodes/parsenodes.h"
+#include "catalog/pg_aggregate.h"
+#include "catalog/pg_proc.h"
+#include "utils/elog.h"
+#include "utils/lsyscache.h"
+#include "utils/palloc.h"
+#include "utils/mcxt.h"
+#include "utils/syscache.h"
+#include "utils/acl.h"
+#include "nodes/nodeFuncs.h"
+#include "commands/sequence.h"
+
+#include "optimizer/clauses.h"
+#include "access/heapam.h"
+
+#include "miscadmin.h"
+#endif
+
+Oid param_type(int t); /* from gram.y */
+
+/*
+ * transformExpr -
+ *       analyze and transform expressions. Type checking and type casting is
+ *       done here. The optimizer and the executor cannot handle the original
+ *       (raw) expressions collected by the parse tree. Hence the transformation
+ *       here.
+ */
+Node *
+transformExpr(ParseState *pstate, Node *expr, int precedence)
+{
+       Node       *result = NULL;
+
+       if (expr == NULL)
+               return NULL;
+
+       switch (nodeTag(expr))
+       {
+               case T_Attr:
+                       {
+                               Attr       *att = (Attr *) expr;
+                               Node       *temp;
+
+                               /* what if att.attrs == "*"?? */
+                               temp = handleNestedDots(pstate, att, &pstate->p_last_resno);
+                               if (att->indirection != NIL)
+                               {
+                                       List       *idx = att->indirection;
+
+                                       while (idx != NIL)
+                                       {
+                                               A_Indices  *ai = (A_Indices *) lfirst(idx);
+                                               Node       *lexpr = NULL,
+                                                                  *uexpr;
+
+                                               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, precedence);
+                                                       if (exprType(lexpr) != INT4OID)
+                                                               elog(WARN, "array index expressions must be int4's");
+                                               }
+#if 0
+                                               pfree(ai->uidx);
+                                               if (ai->lidx != NULL)
+                                                       pfree(ai->lidx);
+#endif
+                                               ai->lidx = lexpr;
+                                               ai->uidx = uexpr;
+
+                                               /*
+                                                * note we reuse the list of indices, make sure we
+                                                * don't free them! Otherwise, make a new list
+                                                * here
+                                                */
+                                               idx = lnext(idx);
+                                       }
+                                       result = (Node *) make_array_ref(temp, att->indirection);
+                               }
+                               else
+                               {
+                                       result = temp;
+                               }
+                               break;
+                       }
+               case T_A_Const:
+                       {
+                               A_Const    *con = (A_Const *) expr;
+                               Value      *val = &con->val;
+
+                               if (con->typename != NULL)
+                               {
+                                       result = parser_typecast(val, con->typename, -1);
+                               }
+                               else
+                               {
+                                       result = (Node *) make_const(val);
+                               }
+                               break;
+                       }
+               case T_ParamNo:
+                       {
+                               ParamNo    *pno = (ParamNo *) expr;
+                               Oid                     toid;
+                               int                     paramno;
+                               Param      *param;
+
+                               paramno = pno->number;
+                               toid = param_type(paramno);
+                               if (!OidIsValid(toid))
+                               {
+                                       elog(WARN, "Parameter '$%d' is out of range",
+                                                paramno);
+                               }
+                               param = makeNode(Param);
+                               param->paramkind = PARAM_NUM;
+                               param->paramid = (AttrNumber) paramno;
+                               param->paramname = "<unnamed>";
+                               param->paramtype = (Oid) toid;
+                               param->param_tlist = (List *) NULL;
+
+                               result = (Node *) param;
+                               break;
+                       }
+               case T_A_Expr:
+                       {
+                               A_Expr     *a = (A_Expr *) expr;
+
+                               switch (a->oper)
+                               {
+                                       case OP:
+                                               {
+                                                       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, precedence);
+
+                                                       result = ParseFunc(pstate,
+                                                                                 "nullvalue", lcons(lexpr, NIL),
+                                                                                          &pstate->p_last_resno);
+                                               }
+                                               break;
+                                       case NOTNULL:
+                                               {
+                                                       Node       *lexpr = transformExpr(pstate, a->lexpr, precedence);
+
+                                                       result = ParseFunc(pstate,
+                                                                          "nonnullvalue", lcons(lexpr, NIL),
+                                                                                          &pstate->p_last_resno);
+                                               }
+                                               break;
+                                       case AND:
+                                               {
+                                                       Expr       *expr = makeNode(Expr);
+                                                       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",
+                                                                        typeidTypeName(exprType(lexpr)));
+                                                       if (exprType(rexpr) != BOOLOID)
+                                                               elog(WARN,
+                                                                        "right-hand side of AND is type '%s', not bool",
+                                                                        typeidTypeName(exprType(rexpr)));
+                                                       expr->typeOid = BOOLOID;
+                                                       expr->opType = AND_EXPR;
+                                                       expr->args = makeList(lexpr, rexpr, -1);
+                                                       result = (Node *) expr;
+                                               }
+                                               break;
+                                       case OR:
+                                               {
+                                                       Expr       *expr = makeNode(Expr);
+                                                       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",
+                                                                        typeidTypeName(exprType(lexpr)));
+                                                       if (exprType(rexpr) != BOOLOID)
+                                                               elog(WARN,
+                                                                        "right-hand side of OR is type '%s', not bool",
+                                                                        typeidTypeName(exprType(rexpr)));
+                                                       expr->typeOid = BOOLOID;
+                                                       expr->opType = OR_EXPR;
+                                                       expr->args = makeList(lexpr, rexpr, -1);
+                                                       result = (Node *) expr;
+                                               }
+                                               break;
+                                       case NOT:
+                                               {
+                                                       Expr       *expr = makeNode(Expr);
+                                                       Node       *rexpr = transformExpr(pstate, a->rexpr, precedence);
+
+                                                       if (exprType(rexpr) != BOOLOID)
+                                                               elog(WARN,
+                                                               "argument to NOT is type '%s', not bool",
+                                                                        typeidTypeName(exprType(rexpr)));
+                                                       expr->typeOid = BOOLOID;
+                                                       expr->opType = NOT_EXPR;
+                                                       expr->args = makeList(rexpr, -1);
+                                                       result = (Node *) expr;
+                                               }
+                                               break;
+                               }
+                               break;
+                       }
+               case T_Ident:
+                       {
+
+                               /*
+                                * look for a column name or a relation name (the default
+                                * behavior)
+                                */
+                               result = transformIdent(pstate, expr, precedence);
+                               break;
+                       }
+               case T_FuncCall:
+                       {
+                               FuncCall   *fn = (FuncCall *) expr;
+                               List       *args;
+
+                               /* transform the list of arguments */
+                               foreach(args, fn->args)
+                                       lfirst(args) = transformExpr(pstate, (Node *) lfirst(args), precedence);
+                               result = ParseFunc(pstate,
+                                                 fn->funcname, fn->args, &pstate->p_last_resno);
+                               break;
+                       }
+               default:
+                       /* should not reach here */
+                       elog(WARN, "transformExpr: does not know how to transform %d\n",
+                                nodeTag(expr));
+                       break;
+       }
+
+       return result;
+}
+
+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;
+}
+
+/*
+ *     exprType -
+ *       returns the Oid of the type of the expression. (Used for typechecking.)
+ */
+Oid
+exprType(Node *expr)
+{
+       Oid                     type = (Oid) 0;
+
+       switch (nodeTag(expr))
+       {
+               case T_Func:
+                       type = ((Func *) expr)->functype;
+                       break;
+               case T_Iter:
+                       type = ((Iter *) expr)->itertype;
+                       break;
+               case T_Var:
+                       type = ((Var *) expr)->vartype;
+                       break;
+               case T_Expr:
+                       type = ((Expr *) expr)->typeOid;
+                       break;
+               case T_Const:
+                       type = ((Const *) expr)->consttype;
+                       break;
+               case T_ArrayRef:
+                       type = ((ArrayRef *) expr)->refelemtype;
+                       break;
+               case T_Aggreg:
+                       type = ((Aggreg *) expr)->aggtype;
+                       break;
+               case T_Param:
+                       type = ((Param *) expr)->paramtype;
+                       break;
+               case T_Ident:
+                       /* is this right? */
+                       type = UNKNOWNOID;
+                       break;
+               default:
+                       elog(WARN, "exprType: don't know how to get type for %d node",
+                                nodeTag(expr));
+                       break;
+       }
+       return type;
+}
+
+/*
+ ** HandleNestedDots --
+ **    Given a nested dot expression (i.e. (relation func ... attr), build up
+ ** a tree with of Iter and Func nodes.
+ */
+Node *
+handleNestedDots(ParseState *pstate, Attr *attr, int *curr_resno)
+{
+       List       *mutator_iter;
+       Node       *retval = NULL;
+
+       if (attr->paramNo != NULL)
+       {
+               Param      *param = (Param *) transformExpr(pstate, (Node *) attr->paramNo, EXPR_RELATION_FIRST);
+
+               retval =
+                       ParseFunc(pstate, strVal(lfirst(attr->attrs)),
+                                         lcons(param, NIL),
+                                         curr_resno);
+       }
+       else
+       {
+               Ident      *ident = makeNode(Ident);
+
+               ident->name = attr->relname;
+               ident->isRel = TRUE;
+               retval =
+                       ParseFunc(pstate, strVal(lfirst(attr->attrs)),
+                                         lcons(ident, NIL),
+                                         curr_resno);
+       }
+
+       foreach(mutator_iter, lnext(attr->attrs))
+       {
+               retval = ParseFunc(pstate, strVal(lfirst(mutator_iter)),
+                                                  lcons(retval, NIL),
+                                                  curr_resno);
+       }
+
+       return (retval);
+}
+
+Node      *
+parser_typecast(Value *expr, TypeName *typename, int typlen)
+{
+       /* check for passing non-ints */
+       Const      *adt;
+       Datum           lcp;
+       Type            tp;
+       char            type_string[NAMEDATALEN];
+       int32           len;
+       char       *cp = NULL;
+       char       *const_string = NULL;
+       bool            string_palloced = false;
+
+       switch (nodeTag(expr))
+       {
+               case T_String:
+                       const_string = DatumGetPointer(expr->val.str);
+                       break;
+               case T_Integer:
+                       const_string = (char *) palloc(256);
+                       string_palloced = true;
+                       sprintf(const_string, "%ld", expr->val.ival);
+                       break;
+               default:
+                       elog(WARN,
+                       "parser_typecast: cannot cast this expression to type \"%s\"",
+                                typename->name);
+       }
+
+       if (typename->arrayBounds != NIL)
+       {
+               sprintf(type_string, "_%s", typename->name);
+               tp = (Type) typenameType(type_string);
+       }
+       else
+       {
+               tp = (Type) typenameType(typename->name);
+       }
+
+       len = typeLen(tp);
+
+#if 0                                                  /* fix me */
+       switch (CInteger(lfirst(expr)))
+       {
+               case INT4OID:                   /* int4 */
+                       const_string = (char *) palloc(256);
+                       string_palloced = true;
+                       sprintf(const_string, "%d", ((Const *) lnext(expr))->constvalue);
+                       break;
+
+               case NAMEOID:                   /* char16 */
+                       const_string = (char *) palloc(256);
+                       string_palloced = true;
+                       sprintf(const_string, "%s", ((Const *) lnext(expr))->constvalue);
+                       break;
+
+               case CHAROID:                   /* char */
+                       const_string = (char *) palloc(256);
+                       string_palloced = true;
+                       sprintf(const_string, "%c", ((Const) lnext(expr))->constvalue);
+                       break;
+
+               case FLOAT8OID: /* float8 */
+                       const_string = (char *) palloc(256);
+                       string_palloced = true;
+                       sprintf(const_string, "%f", ((Const) lnext(expr))->constvalue);
+                       break;
+
+               case CASHOID:                   /* money */
+                       const_string = (char *) palloc(256);
+                       string_palloced = true;
+                       sprintf(const_string, "%d",
+                                       (int) ((Const *) expr)->constvalue);
+                       break;
+
+               case TEXTOID:                   /* text */
+                       const_string = DatumGetPointer(((Const) lnext(expr))->constvalue);
+                       const_string = (char *) textout((struct varlena *) const_string);
+                       break;
+
+               case UNKNOWNOID:                /* unknown */
+                       const_string = DatumGetPointer(((Const) lnext(expr))->constvalue);
+                       const_string = (char *) textout((struct varlena *) const_string);
+                       break;
+
+               default:
+                       elog(WARN, "unknown type %d", CInteger(lfirst(expr)));
+       }
+#endif
+
+       cp = stringTypeString(tp, const_string, typlen);
+
+       if (!typeByVal(tp))
+       {
+/*
+               if (len >= 0 && len != PSIZE(cp)) {
+                       char *pp;
+                       pp = (char *) palloc(len);
+                       memmove(pp, cp, len);
+                       cp = pp;
+               }
+*/
+               lcp = PointerGetDatum(cp);
+       }
+       else
+       {
+               switch (len)
+               {
+                       case 1:
+                               lcp = Int8GetDatum(cp);
+                               break;
+                       case 2:
+                               lcp = Int16GetDatum(cp);
+                               break;
+                       case 4:
+                               lcp = Int32GetDatum(cp);
+                               break;
+                       default:
+                               lcp = PointerGetDatum(cp);
+                               break;
+               }
+       }
+
+       adt = makeConst(typeTypeId(tp),
+                                       len,
+                                       (Datum) lcp,
+                                       false,
+                                       typeByVal(tp),
+                                       false,          /* not a set */
+                                       true /* is cast */ );
+
+       if (string_palloced)
+               pfree(const_string);
+
+       return (Node *) adt;
+}
+
+Node      *
+parser_typecast2(Node *expr, Oid exprType, Type tp, int typlen)
+{
+       /* check for passing non-ints */
+       Const      *adt;
+       Datum           lcp;
+       int32           len = typeLen(tp);
+       char       *cp = NULL;
+
+       char       *const_string = NULL;
+       bool            string_palloced = false;
+
+       Assert(IsA(expr, Const));
+
+       switch (exprType)
+       {
+               case 0:                 /* NULL */
+                       break;
+               case INT4OID:                   /* int4 */
+                       const_string = (char *) palloc(256);
+                       string_palloced = true;
+                       sprintf(const_string, "%d",
+                                       (int) ((Const *) expr)->constvalue);
+                       break;
+               case NAMEOID:                   /* char16 */
+                       const_string = (char *) palloc(256);
+                       string_palloced = true;
+                       sprintf(const_string, "%s",
+                                       (char *) ((Const *) expr)->constvalue);
+                       break;
+               case CHAROID:                   /* char */
+                       const_string = (char *) palloc(256);
+                       string_palloced = true;
+                       sprintf(const_string, "%c",
+                                       (char) ((Const *) expr)->constvalue);
+                       break;
+               case FLOAT4OID: /* float4 */
+                       {
+                               float32         floatVal =
+                               DatumGetFloat32(((Const *) expr)->constvalue);
+
+                               const_string = (char *) palloc(256);
+                               string_palloced = true;
+                               sprintf(const_string, "%f", *floatVal);
+                               break;
+                       }
+               case FLOAT8OID: /* float8 */
+                       {
+                               float64         floatVal =
+                               DatumGetFloat64(((Const *) expr)->constvalue);
+
+                               const_string = (char *) palloc(256);
+                               string_palloced = true;
+                               sprintf(const_string, "%f", *floatVal);
+                               break;
+                       }
+               case CASHOID:                   /* money */
+                       const_string = (char *) palloc(256);
+                       string_palloced = true;
+                       sprintf(const_string, "%ld",
+                                       (long) ((Const *) expr)->constvalue);
+                       break;
+               case TEXTOID:                   /* text */
+                       const_string =
+                               DatumGetPointer(((Const *) expr)->constvalue);
+                       const_string = (char *) textout((struct varlena *) const_string);
+                       break;
+               case UNKNOWNOID:                /* unknown */
+                       const_string =
+                               DatumGetPointer(((Const *) expr)->constvalue);
+                       const_string = (char *) textout((struct varlena *) const_string);
+                       break;
+               default:
+                       elog(WARN, "unknown type %u ", exprType);
+       }
+
+       if (!exprType)
+       {
+               adt = makeConst(typeTypeId(tp),
+                                               (Size) 0,
+                                               (Datum) NULL,
+                                               true,   /* isnull */
+                                               false,  /* was omitted */
+                                               false,  /* not a set */
+                                               true /* is cast */ );
+               return ((Node *) adt);
+       }
+
+       cp = stringTypeString(tp, const_string, typlen);
+
+
+       if (!typeByVal(tp))
+       {
+/*
+               if (len >= 0 && len != PSIZE(cp)) {
+                       char *pp;
+                       pp = (char *) palloc(len);
+                       memmove(pp, cp, len);
+                       cp = pp;
+               }
+*/
+               lcp = PointerGetDatum(cp);
+       }
+       else
+       {
+               switch (len)
+               {
+                       case 1:
+                               lcp = Int8GetDatum(cp);
+                               break;
+                       case 2:
+                               lcp = Int16GetDatum(cp);
+                               break;
+                       case 4:
+                               lcp = Int32GetDatum(cp);
+                               break;
+                       default:
+                               lcp = PointerGetDatum(cp);
+                               break;
+               }
+       }
+
+       adt = makeConst(typeTypeId(tp),
+                                       (Size) len,
+                                       (Datum) lcp,
+                                       false,
+                                       false,          /* was omitted */
+                                       false,          /* not a set */
+                                       true /* is cast */ );
+
+       /*
+        * printf("adt %s : %u %d %d\n",CString(expr),typeTypeId(tp) , len,cp);
+        */
+       if (string_palloced)
+               pfree(const_string);
+
+       return ((Node *) adt);
+} 
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
new file mode 100644 (file)
index 0000000..bb2a777
--- /dev/null
@@ -0,0 +1,1264 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_func.c
+ *             handle function calls in parser
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.1 1997/11/25 22:05:41 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <string.h>
+#include "postgres.h"
+#include "fmgr.h"
+#include "miscadmin.h"
+#include "access/genam.h"
+#include "access/heapam.h"
+#include "access/itup.h"
+#include "access/relscan.h"
+#include "access/sdir.h"
+#include "catalog/catname.h"
+#include "catalog/indexing.h"
+#include "catalog/pg_inherits.h"
+#include "catalog/pg_proc.h"
+#include "catalog/pg_type.h"
+#include "lib/dllist.h"
+#include "nodes/makefuncs.h"
+#include "nodes/relation.h"
+#include "parser/parse_agg.h"
+#include "parser/parse_expr.h"
+#include "parser/parse_func.h"
+#include "parser/parse_node.h"
+#include "parser/parse_relation.h"
+#include "parser/parse_type.h"
+#include "storage/bufmgr.h"
+#include "storage/lmgr.h"
+#include "utils/acl.h"
+#include "utils/builtins.h"
+#include "utils/lsyscache.h"
+#include "utils/syscache.h"
+
+#ifdef 0
+#include "utils/datum.h"
+
+#include "utils/elog.h"
+#include "utils/palloc.h"
+
+#include "nodes/pg_list.h"
+#include "nodes/parsenodes.h"
+
+#include "catalog/pg_operator.h"
+#include "catalog/catname.h"
+
+#include "access/skey.h"
+#include "access/tupdesc.h"
+#include "access/htup.h"
+#include "access/genam.h"
+#include "access/itup.h"
+#include "access/tupmacs.h"
+
+#include "storage/buf.h"
+#endif
+
+#define ISCOMPLEX(type) (typeidTypeRelid(type) ? true : false)
+
+#define MAXFARGS 8                             /* max # args to a c or postquel function */
+
+typedef struct _SuperQE
+{
+       Oid                     sqe_relid;
+} SuperQE;
+
+/*
+ * parse function
+ */
+
+Node *
+ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
+{
+       Oid                     rettype = (Oid) 0;
+       Oid                     argrelid = (Oid) 0;
+       Oid                     funcid = (Oid) 0;
+       List       *i = NIL;
+       Node       *first_arg = NULL;
+       char       *relname = NULL;
+       char       *refname = NULL;
+       Relation        rd;
+       Oid                     relid;
+       int                     nargs;
+       Func       *funcnode;
+       Oid                     oid_array[8];
+       Oid                *true_oid_array;
+       Node       *retval;
+       bool            retset;
+       bool            exists;
+       bool            attisset = false;
+       Oid                     toid = (Oid) 0;
+       Expr       *expr;
+
+       if (fargs)
+       {
+               first_arg = lfirst(fargs);
+               if (first_arg == NULL)
+                       elog(WARN, "function '%s' does not allow NULL input", funcname);
+       }
+
+       /*
+        * check for projection methods: if function takes one argument, and
+        * that argument is a relation, param, or PQ function returning a
+        * complex * type, then the function could be a projection.
+        */
+       if (length(fargs) == 1)
+       {
+
+               if (nodeTag(first_arg) == T_Ident && ((Ident *) first_arg)->isRel)
+               {
+                       RangeTblEntry *rte;
+                       Ident      *ident = (Ident *) first_arg;
+
+                       /*
+                        * first arg is a relation. This could be a projection.
+                        */
+                       refname = ident->name;
+
+                       rte = refnameRangeTableEntry(pstate->p_rtable, refname);
+                       if (rte == NULL)
+                               rte = addRangeTableEntry(pstate, refname, refname, FALSE, FALSE);
+
+                       relname = rte->relname;
+                       relid = rte->relid;
+
+                       /*
+                        * If the attr isn't a set, just make a var for it.  If it is
+                        * a set, treat it like a function and drop through.
+                        */
+                       if (get_attnum(relid, funcname) != InvalidAttrNumber)
+                       {
+                               Oid                     dummyTypeId;
+
+                               return
+                                       ((Node *) make_var(pstate,
+                                                                          refname,
+                                                                          funcname,
+                                                                          &dummyTypeId));
+                       }
+                       else
+                       {
+                               /* drop through - attr is a set */
+                               ;
+                       }
+               }
+               else if (ISCOMPLEX(exprType(first_arg)))
+               {
+
+                       /*
+                        * Attempt to handle projection of a complex argument. If
+                        * ParseComplexProjection can't handle the projection, we have
+                        * to keep going.
+                        */
+                       retval = ParseComplexProjection(pstate,
+                                                                                       funcname,
+                                                                                       first_arg,
+                                                                                       &attisset);
+                       if (attisset)
+                       {
+                               toid = exprType(first_arg);
+                               rd = heap_openr(typeidTypeName(toid));
+                               if (RelationIsValid(rd))
+                               {
+                                       relname = RelationGetRelationName(rd)->data;
+                                       heap_close(rd);
+                               }
+                               else
+                                       elog(WARN,
+                                                "Type '%s' is not a relation type",
+                                                typeidTypeName(toid));
+                               argrelid = typeidTypeRelid(toid);
+
+                               /*
+                                * A projection contains either an attribute name or the
+                                * "*".
+                                */
+                               if ((get_attnum(argrelid, funcname) == InvalidAttrNumber)
+                                       && strcmp(funcname, "*"))
+                               {
+                                       elog(WARN, "Functions on sets are not yet supported");
+                               }
+                       }
+
+                       if (retval)
+                               return retval;
+               }
+               else
+               {
+
+                       /*
+                        * Parsing aggregates.
+                        */
+                       Oid                     basetype;
+
+                       /*
+                        * the aggregate count is a special case, ignore its base
+                        * type.  Treat it as zero
+                        */
+                       if (strcmp(funcname, "count") == 0)
+                               basetype = 0;
+                       else
+                               basetype = exprType(lfirst(fargs));
+                       if (SearchSysCacheTuple(AGGNAME,
+                                                                       PointerGetDatum(funcname),
+                                                                       ObjectIdGetDatum(basetype),
+                                                                       0, 0))
+                       {
+                               Aggreg     *aggreg = ParseAgg(funcname, basetype, lfirst(fargs));
+
+                               AddAggToParseState(pstate, aggreg);
+                               return (Node *) aggreg;
+                       }
+               }
+       }
+
+
+       /*
+        * * If we dropped through to here it's really a function (or a set,
+        * which * is implemented as a function.) * extract arg type info and
+        * transform relation name arguments into * varnodes of the
+        * appropriate form.
+        */
+       MemSet(&oid_array[0], 0, 8 * sizeof(Oid));
+
+       nargs = 0;
+       foreach(i, fargs)
+       {
+               int                     vnum;
+               RangeTblEntry *rte;
+               Node       *pair = lfirst(i);
+
+               if (nodeTag(pair) == T_Ident && ((Ident *) pair)->isRel)
+               {
+
+                       /*
+                        * a relation
+                        */
+                       refname = ((Ident *) pair)->name;
+
+                       rte = refnameRangeTableEntry(pstate->p_rtable, refname);
+                       if (rte == NULL)
+                               rte = addRangeTableEntry(pstate, refname, refname,
+                                                                                FALSE, FALSE);
+                       relname = rte->relname;
+
+                       vnum = refnameRangeTablePosn(pstate->p_rtable, rte->refname);
+
+                       /*
+                        * for func(relname), the param to the function is the tuple
+                        * under consideration.  we build a special VarNode to reflect
+                        * this -- it has varno set to the correct range table entry,
+                        * but has varattno == 0 to signal that the whole tuple is the
+                        * argument.
+                        */
+                       toid = typeTypeId(typenameType(relname));
+                       /* replace it in the arg list */
+                       lfirst(fargs) =
+                               makeVar(vnum, 0, toid, vnum, 0);
+               }
+               else if (!attisset)
+               {                                               /* set functions don't have parameters */
+
+                       /*
+                        * any functiona args which are typed "unknown", but aren't
+                        * constants, we don't know what to do with, because we can't
+                        * cast them    - jolly
+                        */
+                       if (exprType(pair) == UNKNOWNOID &&
+                               !IsA(pair, Const))
+                       {
+                               elog(WARN, "ParseFunc: no function named '%s' that takes in an unknown type as argument #%d", funcname, nargs);
+                       }
+                       else
+                               toid = exprType(pair);
+               }
+
+               oid_array[nargs++] = toid;
+       }
+
+       /*
+        * func_get_detail looks up the function in the catalogs, does
+        * disambiguation for polymorphic functions, handles inheritance, and
+        * returns the funcid and type and set or singleton status of the
+        * function's return value.  it also returns the true argument types
+        * to the function.  if func_get_detail returns true, the function
+        * exists.      otherwise, there was an error.
+        */
+       if (attisset)
+       {                                                       /* we know all of these fields already */
+
+               /*
+                * We create a funcnode with a placeholder function SetEval.
+                * SetEval() never actually gets executed.      When the function
+                * evaluation routines see it, they use the funcid projected out
+                * from the relation as the actual function to call. Example:
+                * retrieve (emp.mgr.name) The plan for this will scan the emp
+                * relation, projecting out the mgr attribute, which is a funcid.
+                * This function is then called (instead of SetEval) and "name" is
+                * projected from its result.
+                */
+               funcid = SetEvalRegProcedure;
+               rettype = toid;
+               retset = true;
+               true_oid_array = oid_array;
+               exists = true;
+       }
+       else
+       {
+               exists = func_get_detail(funcname, nargs, oid_array, &funcid,
+                                                                &rettype, &retset, &true_oid_array);
+       }
+
+       if (!exists)
+               elog(WARN, "no such attribute or function '%s'", funcname);
+
+       /* got it */
+       funcnode = makeNode(Func);
+       funcnode->funcid = funcid;
+       funcnode->functype = rettype;
+       funcnode->funcisindex = false;
+       funcnode->funcsize = 0;
+       funcnode->func_fcache = NULL;
+       funcnode->func_tlist = NIL;
+       funcnode->func_planlist = NIL;
+
+       /* perform the necessary typecasting */
+       make_arguments(nargs, fargs, oid_array, true_oid_array);
+
+       /*
+        * for functions returning base types, we want to project out the
+        * return value.  set up a target list to do that.      the executor will
+        * ignore these for c functions, and do the right thing for postquel
+        * functions.
+        */
+
+       if (typeidTypeRelid(rettype) == InvalidOid)
+               funcnode->func_tlist = setup_base_tlist(rettype);
+
+       /*
+        * For sets, we want to make a targetlist to project out this
+        * attribute of the set tuples.
+        */
+       if (attisset)
+       {
+               if (!strcmp(funcname, "*"))
+               {
+                       funcnode->func_tlist =
+                               expandAll(pstate, relname, refname, curr_resno);
+               }
+               else
+               {
+                       funcnode->func_tlist = setup_tlist(funcname, argrelid);
+                       rettype = attnameTypeId(argrelid, funcname);
+               }
+       }
+
+       /*
+        * Sequence handling.
+        */
+       if (funcid == SeqNextValueRegProcedure ||
+               funcid == SeqCurrValueRegProcedure)
+       {
+               Const      *seq;
+               char       *seqrel;
+               text       *seqname;
+               int32           aclcheck_result = -1;
+               extern text *lower (text *string);
+
+               Assert(length(fargs) == 1);
+               seq = (Const *) lfirst(fargs);
+               if (!IsA((Node *) seq, Const))
+                       elog(WARN, "%s: only constant sequence names are acceptable", funcname);
+               seqname = lower ((text*)DatumGetPointer(seq->constvalue));
+               pfree (DatumGetPointer(seq->constvalue));
+               seq->constvalue = PointerGetDatum (seqname);
+               seqrel = textout(seqname);
+
+               if ((aclcheck_result = pg_aclcheck(seqrel, GetPgUserName(),
+                          ((funcid == SeqNextValueRegProcedure) ? ACL_WR : ACL_RD)))
+                       != ACLCHECK_OK)
+                       elog(WARN, "%s.%s: %s",
+                         seqrel, funcname, aclcheck_error_strings[aclcheck_result]);
+
+               pfree(seqrel);
+
+               if (funcid == SeqNextValueRegProcedure && pstate->p_in_where_clause)
+                       elog(WARN, "nextval of a sequence in WHERE disallowed");
+       }
+
+       expr = makeNode(Expr);
+       expr->typeOid = rettype;
+       expr->opType = FUNC_EXPR;
+       expr->oper = (Node *) funcnode;
+       expr->args = fargs;
+       retval = (Node *) expr;
+
+       /*
+        * if the function returns a set of values, then we need to iterate
+        * over all the returned values in the executor, so we stick an iter
+        * node here.  if it returns a singleton, then we don't need the iter
+        * node.
+        */
+
+       if (retset)
+       {
+               Iter       *iter = makeNode(Iter);
+
+               iter->itertype = rettype;
+               iter->iterexpr = retval;
+               retval = (Node *) iter;
+       }
+
+       return (retval);
+}
+
+Oid
+funcid_get_rettype(Oid funcid)
+{
+       HeapTuple       func_tuple = NULL;
+       Oid                     funcrettype = (Oid) 0;
+
+       func_tuple = SearchSysCacheTuple(PROOID, ObjectIdGetDatum(funcid),
+                                                                        0, 0, 0);
+
+       if (!HeapTupleIsValid(func_tuple))
+               elog(WARN, "function  %d does not exist", funcid);
+
+       funcrettype = (Oid)
+               ((Form_pg_proc) GETSTRUCT(func_tuple))->prorettype;
+
+       return (funcrettype);
+}
+
+/*
+ * get a list of all argument type vectors for which a function named
+ * funcname taking nargs arguments exists
+ */
+CandidateList
+func_get_candidates(char *funcname, int nargs)
+{
+       Relation        heapRelation;
+       Relation        idesc;
+       ScanKeyData skey;
+       HeapTuple       tuple;
+       IndexScanDesc sd;
+       RetrieveIndexResult indexRes;
+       Buffer          buffer;
+       Form_pg_proc pgProcP;
+       bool            bufferUsed = FALSE;
+       CandidateList candidates = NULL;
+       CandidateList current_candidate;
+       int                     i;
+
+       heapRelation = heap_openr(ProcedureRelationName);
+       ScanKeyEntryInitialize(&skey,
+                                                  (bits16) 0x0,
+                                                  (AttrNumber) 1,
+                                                  (RegProcedure) NameEqualRegProcedure,
+                                                  (Datum) funcname);
+
+       idesc = index_openr(ProcedureNameIndex);
+
+       sd = index_beginscan(idesc, false, 1, &skey);
+
+       do
+       {
+               tuple = (HeapTuple) NULL;
+               if (bufferUsed)
+               {
+                       ReleaseBuffer(buffer);
+                       bufferUsed = FALSE;
+               }
+
+               indexRes = index_getnext(sd, ForwardScanDirection);
+               if (indexRes)
+               {
+                       ItemPointer iptr;
+
+                       iptr = &indexRes->heap_iptr;
+                       tuple = heap_fetch(heapRelation, false, iptr, &buffer);
+                       pfree(indexRes);
+                       if (HeapTupleIsValid(tuple))
+                       {
+                               pgProcP = (Form_pg_proc) GETSTRUCT(tuple);
+                               bufferUsed = TRUE;
+                               if (pgProcP->pronargs == nargs)
+                               {
+                                       current_candidate = (CandidateList)
+                                               palloc(sizeof(struct _CandidateList));
+                                       current_candidate->args = (Oid *)
+                                               palloc(8 * sizeof(Oid));
+                                       MemSet(current_candidate->args, 0, 8 * sizeof(Oid));
+                                       for (i = 0; i < nargs; i++)
+                                       {
+                                               current_candidate->args[i] =
+                                                       pgProcP->proargtypes[i];
+                                       }
+
+                                       current_candidate->next = candidates;
+                                       candidates = current_candidate;
+                               }
+                       }
+               }
+       } while (indexRes);
+
+       index_endscan(sd);
+       index_close(idesc);
+       heap_close(heapRelation);
+
+       return candidates;
+}
+
+/*
+ * can input_typeids be coerced to func_typeids?
+ */
+bool
+can_coerce(int nargs, Oid *input_typeids, Oid *func_typeids)
+{
+       int                     i;
+       Type            tp;
+
+       /*
+        * right now, we only coerce "unknown", and we cannot coerce it to a
+        * relation type
+        */
+       for (i = 0; i < nargs; i++)
+       {
+               if (input_typeids[i] != func_typeids[i])
+               {
+                       if ((input_typeids[i] == BPCHAROID && func_typeids[i] == TEXTOID) ||
+                               (input_typeids[i] == BPCHAROID && func_typeids[i] == VARCHAROID) ||
+                               (input_typeids[i] == VARCHAROID && func_typeids[i] == TEXTOID) ||
+                               (input_typeids[i] == VARCHAROID && func_typeids[i] == BPCHAROID) ||
+                       (input_typeids[i] == CASHOID && func_typeids[i] == INT4OID) ||
+                        (input_typeids[i] == INT4OID && func_typeids[i] == CASHOID))
+                               ;                               /* these are OK */
+                       else if (input_typeids[i] != UNKNOWNOID || func_typeids[i] == 0)
+                               return false;
+
+                       tp = typeidType(input_typeids[i]);
+                       if (typeTypeFlag(tp) == 'c')
+                               return false;
+               }
+       }
+
+       return true;
+}
+
+/*
+ * given a list of possible typeid arrays to a function and an array of
+ * input typeids, produce a shortlist of those function typeid arrays
+ * that match the input typeids (either exactly or by coercion), and
+ * return the number of such arrays
+ */
+int
+match_argtypes(int nargs,
+                          Oid *input_typeids,
+                          CandidateList function_typeids,
+                          CandidateList *candidates)           /* return value */
+{
+       CandidateList current_candidate;
+       CandidateList matching_candidate;
+       Oid                *current_typeids;
+       int                     ncandidates = 0;
+
+       *candidates = NULL;
+
+       for (current_candidate = function_typeids;
+                current_candidate != NULL;
+                current_candidate = current_candidate->next)
+       {
+               current_typeids = current_candidate->args;
+               if (can_coerce(nargs, input_typeids, current_typeids))
+               {
+                       matching_candidate = (CandidateList)
+                               palloc(sizeof(struct _CandidateList));
+                       matching_candidate->args = current_typeids;
+                       matching_candidate->next = *candidates;
+                       *candidates = matching_candidate;
+                       ncandidates++;
+               }
+       }
+
+       return ncandidates;
+}
+
+/*
+ * given the input argtype array and more than one candidate
+ * for the function argtype array, attempt to resolve the conflict.
+ * returns the selected argtype array if the conflict can be resolved,
+ * otherwise returns NULL
+ */
+Oid *
+func_select_candidate(int nargs,
+                                         Oid *input_typeids,
+                                         CandidateList candidates)
+{
+       /* XXX no conflict resolution implemeneted yet */
+       return (NULL);
+}
+
+bool
+func_get_detail(char *funcname,
+                               int nargs,
+                               Oid *oid_array,
+                               Oid *funcid,    /* return value */
+                               Oid *rettype,   /* return value */
+                               bool *retset,   /* return value */
+                               Oid **true_typeids)             /* return value */
+{
+       Oid               **input_typeid_vector;
+       Oid                *current_input_typeids;
+       CandidateList function_typeids;
+       CandidateList current_function_typeids;
+       HeapTuple       ftup;
+       Form_pg_proc pform;
+
+       /*
+        * attempt to find named function in the system catalogs with
+        * arguments exactly as specified - so that the normal case is just as
+        * quick as before
+        */
+       ftup = SearchSysCacheTuple(PRONAME,
+                                                          PointerGetDatum(funcname),
+                                                          Int32GetDatum(nargs),
+                                                          PointerGetDatum(oid_array),
+                                                          0);
+       *true_typeids = oid_array;
+
+       /*
+        * If an exact match isn't found : 1) get a vector of all possible
+        * input arg type arrays constructed from the superclasses of the
+        * original input arg types 2) get a list of all possible argument
+        * type arrays to the function with given name and number of arguments
+        * 3) for each input arg type array from vector #1 : a) find how many
+        * of the function arg type arrays from list #2 it can be coerced to
+        * b) - if the answer is one, we have our function - if the answer is
+        * more than one, attempt to resolve the conflict - if the answer is
+        * zero, try the next array from vector #1
+        */
+       if (!HeapTupleIsValid(ftup))
+       {
+               function_typeids = func_get_candidates(funcname, nargs);
+
+               if (function_typeids != NULL)
+               {
+                       int                     ncandidates = 0;
+
+                       input_typeid_vector = argtype_inherit(nargs, oid_array);
+                       current_input_typeids = oid_array;
+
+                       do
+                       {
+                               ncandidates = match_argtypes(nargs, current_input_typeids,
+                                                                                        function_typeids,
+                                                                                        &current_function_typeids);
+                               if (ncandidates == 1)
+                               {
+                                       *true_typeids = current_function_typeids->args;
+                                       ftup = SearchSysCacheTuple(PRONAME,
+                                                                                          PointerGetDatum(funcname),
+                                                                                          Int32GetDatum(nargs),
+                                                                                 PointerGetDatum(*true_typeids),
+                                                                                          0);
+                                       Assert(HeapTupleIsValid(ftup));
+                               }
+                               else if (ncandidates > 1)
+                               {
+                                       *true_typeids =
+                                               func_select_candidate(nargs,
+                                                                                         current_input_typeids,
+                                                                                         current_function_typeids);
+                                       if (*true_typeids == NULL)
+                                       {
+                                               elog(NOTICE, "there is more than one function named \"%s\"",
+                                                        funcname);
+                                               elog(NOTICE, "that satisfies the given argument types. you will have to");
+                                               elog(NOTICE, "retype your query using explicit typecasts.");
+                                               func_error("func_get_detail", funcname, nargs, oid_array);
+                                       }
+                                       else
+                                       {
+                                               ftup = SearchSysCacheTuple(PRONAME,
+                                                                                          PointerGetDatum(funcname),
+                                                                                                  Int32GetDatum(nargs),
+                                                                                 PointerGetDatum(*true_typeids),
+                                                                                                  0);
+                                               Assert(HeapTupleIsValid(ftup));
+                                       }
+                               }
+                               current_input_typeids = *input_typeid_vector++;
+                       }
+                       while (current_input_typeids !=
+                                  InvalidOid && ncandidates == 0);
+               }
+       }
+
+       if (!HeapTupleIsValid(ftup))
+       {
+               Type            tp;
+
+               if (nargs == 1)
+               {
+                       tp = typeidType(oid_array[0]);
+                       if (typeTypeFlag(tp) == 'c')
+                               elog(WARN, "no such attribute or function \"%s\"",
+                                        funcname);
+               }
+               func_error("func_get_detail", funcname, nargs, oid_array);
+       }
+       else
+       {
+               pform = (Form_pg_proc) GETSTRUCT(ftup);
+               *funcid = ftup->t_oid;
+               *rettype = pform->prorettype;
+               *retset = pform->proretset;
+
+               return (true);
+       }
+/* shouldn't reach here */
+       return (false);
+
+}
+
+/*
+ *     argtype_inherit() -- Construct an argtype vector reflecting the
+ *                                              inheritance properties of the supplied argv.
+ *
+ *             This function is used to disambiguate among functions with the
+ *             same name but different signatures.  It takes an array of eight
+ *             type ids.  For each type id in the array that's a complex type
+ *             (a class), it walks up the inheritance tree, finding all
+ *             superclasses of that type.      A vector of new Oid type arrays
+ *             is returned to the caller, reflecting the structure of the
+ *             inheritance tree above the supplied arguments.
+ *
+ *             The order of this vector is as follows:  all superclasses of the
+ *             rightmost complex class are explored first.  The exploration
+ *             continues from right to left.  This policy means that we favor
+ *             keeping the leftmost argument type as low in the inheritance tree
+ *             as possible.  This is intentional; it is exactly what we need to
+ *             do for method dispatch.  The last type array we return is all
+ *             zeroes.  This will match any functions for which return types are
+ *             not defined.  There are lots of these (mostly builtins) in the
+ *             catalogs.
+ */
+Oid **
+argtype_inherit(int nargs, Oid *oid_array)
+{
+       Oid                     relid;
+       int                     i;
+       InhPaths        arginh[MAXFARGS];
+
+       for (i = 0; i < MAXFARGS; i++)
+       {
+               if (i < nargs)
+               {
+                       arginh[i].self = oid_array[i];
+                       if ((relid = typeidTypeRelid(oid_array[i])) != InvalidOid)
+                       {
+                               arginh[i].nsupers = findsupers(relid, &(arginh[i].supervec));
+                       }
+                       else
+                       {
+                               arginh[i].nsupers = 0;
+                               arginh[i].supervec = (Oid *) NULL;
+                       }
+               }
+               else
+               {
+                       arginh[i].self = InvalidOid;
+                       arginh[i].nsupers = 0;
+                       arginh[i].supervec = (Oid *) NULL;
+               }
+       }
+
+       /* return an ordered cross-product of the classes involved */
+       return (genxprod(arginh, nargs));
+}
+
+int findsupers(Oid relid, Oid **supervec)
+{
+       Oid                *relidvec;
+       Relation        inhrel;
+       HeapScanDesc inhscan;
+       ScanKeyData skey;
+       HeapTuple       inhtup;
+       TupleDesc       inhtupdesc;
+       int                     nvisited;
+       SuperQE    *qentry,
+                          *vnode;
+       Dllist     *visited,
+                          *queue;
+       Dlelem     *qe,
+                          *elt;
+
+       Relation        rd;
+       Buffer          buf;
+       Datum           d;
+       bool            newrelid;
+       char            isNull;
+
+       nvisited = 0;
+       queue = DLNewList();
+       visited = DLNewList();
+
+
+       inhrel = heap_openr(InheritsRelationName);
+       RelationSetLockForRead(inhrel);
+       inhtupdesc = RelationGetTupleDescriptor(inhrel);
+
+       /*
+        * Use queue to do a breadth-first traversal of the inheritance graph
+        * from the relid supplied up to the root.
+        */
+       do
+       {
+               ScanKeyEntryInitialize(&skey, 0x0, Anum_pg_inherits_inhrel,
+                                                          ObjectIdEqualRegProcedure,
+                                                          ObjectIdGetDatum(relid));
+
+               inhscan = heap_beginscan(inhrel, 0, false, 1, &skey);
+
+               while (HeapTupleIsValid(inhtup = heap_getnext(inhscan, 0, &buf)))
+               {
+                       qentry = (SuperQE *) palloc(sizeof(SuperQE));
+
+                       d = fastgetattr(inhtup, Anum_pg_inherits_inhparent,
+                                                       inhtupdesc, &isNull);
+                       qentry->sqe_relid = DatumGetObjectId(d);
+
+                       /* put this one on the queue */
+                       DLAddTail(queue, DLNewElem(qentry));
+
+                       ReleaseBuffer(buf);
+               }
+
+               heap_endscan(inhscan);
+
+               /* pull next unvisited relid off the queue */
+               do
+               {
+                       qe = DLRemHead(queue);
+                       qentry = qe ? (SuperQE *) DLE_VAL(qe) : NULL;
+
+                       if (qentry == (SuperQE *) NULL)
+                               break;
+
+                       relid = qentry->sqe_relid;
+                       newrelid = true;
+
+                       for (elt = DLGetHead(visited); elt; elt = DLGetSucc(elt))
+                       {
+                               vnode = (SuperQE *) DLE_VAL(elt);
+                               if (vnode && (qentry->sqe_relid == vnode->sqe_relid))
+                               {
+                                       newrelid = false;
+                                       break;
+                               }
+                       }
+               } while (!newrelid);
+
+               if (qentry != (SuperQE *) NULL)
+               {
+
+                       /* save the type id, rather than the relation id */
+                       if ((rd = heap_open(qentry->sqe_relid)) == (Relation) NULL)
+                               elog(WARN, "relid %d does not exist", qentry->sqe_relid);
+                       qentry->sqe_relid = typeTypeId(typenameType(RelationGetRelationName(rd)->data));
+                       heap_close(rd);
+
+                       DLAddTail(visited, qe);
+
+                       nvisited++;
+               }
+       } while (qentry != (SuperQE *) NULL);
+
+       RelationUnsetLockForRead(inhrel);
+       heap_close(inhrel);
+
+       if (nvisited > 0)
+       {
+               relidvec = (Oid *) palloc(nvisited * sizeof(Oid));
+               *supervec = relidvec;
+
+               for (elt = DLGetHead(visited); elt; elt = DLGetSucc(elt))
+               {
+                       vnode = (SuperQE *) DLE_VAL(elt);
+                       *relidvec++ = vnode->sqe_relid;
+               }
+
+       }
+       else
+       {
+               *supervec = (Oid *) NULL;
+       }
+
+       return (nvisited);
+}
+
+Oid **
+genxprod(InhPaths *arginh, int nargs)
+{
+       int                     nanswers;
+       Oid               **result,
+                         **iter;
+       Oid                *oneres;
+       int                     i,
+                               j;
+       int                     cur[MAXFARGS];
+
+       nanswers = 1;
+       for (i = 0; i < nargs; i++)
+       {
+               nanswers *= (arginh[i].nsupers + 2);
+               cur[i] = 0;
+       }
+
+       iter = result = (Oid **) palloc(sizeof(Oid *) * nanswers);
+
+       /* compute the cross product from right to left */
+       for (;;)
+       {
+               oneres = (Oid *) palloc(MAXFARGS * sizeof(Oid));
+               MemSet(oneres, 0, MAXFARGS * sizeof(Oid));
+
+               for (i = nargs - 1; i >= 0 && cur[i] > arginh[i].nsupers; i--)
+                       continue;
+
+               /* if we're done, terminate with NULL pointer */
+               if (i < 0)
+               {
+                       *iter = NULL;
+                       return (result);
+               }
+
+               /* no, increment this column and zero the ones after it */
+               cur[i] = cur[i] + 1;
+               for (j = nargs - 1; j > i; j--)
+                       cur[j] = 0;
+
+               for (i = 0; i < nargs; i++)
+               {
+                       if (cur[i] == 0)
+                               oneres[i] = arginh[i].self;
+                       else if (cur[i] > arginh[i].nsupers)
+                               oneres[i] = 0;  /* wild card */
+                       else
+                               oneres[i] = arginh[i].supervec[cur[i] - 1];
+               }
+
+               *iter++ = oneres;
+       }
+}
+
+
+/*
+ ** make_arguments --
+ **   Given the number and types of arguments to a function, and the
+ **   actual arguments and argument types, do the necessary typecasting.
+ */
+void
+make_arguments(int nargs,
+                          List *fargs,
+                          Oid *input_typeids,
+                          Oid *function_typeids)
+{
+
+       /*
+        * there are two ways an input typeid can differ from a function
+        * typeid : either the input type inherits the function type, so no
+        * typecasting is necessary, or the input type can be typecast into
+        * the function type. right now, we only typecast unknowns, and that
+        * is all we check for.
+        */
+
+       List       *current_fargs;
+       int                     i;
+
+       for (i = 0, current_fargs = fargs;
+                i < nargs;
+                i++, current_fargs = lnext(current_fargs))
+       {
+
+               if (input_typeids[i] == UNKNOWNOID && function_typeids[i] != InvalidOid)
+               {
+                       lfirst(current_fargs) =
+                               parser_typecast2(lfirst(current_fargs),
+                                                                input_typeids[i],
+                                                                typeidType(function_typeids[i]),
+                                                                -1);
+               }
+       }
+}
+
+/*
+ ** setup_tlist --
+ **            Build a tlist that says which attribute to project to.
+ **            This routine is called by ParseFunc() to set up a target list
+ **            on a tuple parameter or return value.  Due to a bug in 4.0,
+ **            it's not possible to refer to system attributes in this case.
+ */
+List *
+setup_tlist(char *attname, Oid relid)
+{
+       TargetEntry *tle;
+       Resdom     *resnode;
+       Var                *varnode;
+       Oid                     typeid;
+       int                     attno;
+
+       attno = get_attnum(relid, attname);
+       if (attno < 0)
+               elog(WARN, "cannot reference attribute '%s' of tuple params/return values for functions", attname);
+
+       typeid = attnameTypeId(relid, attname);
+       resnode = makeResdom(1,
+                                                typeid,
+                                                typeLen(typeidType(typeid)),
+                                                get_attname(relid, attno),
+                                                0,
+                                                (Oid) 0,
+                                                0);
+       varnode = makeVar(-1, attno, typeid, -1, attno);
+
+       tle = makeNode(TargetEntry);
+       tle->resdom = resnode;
+       tle->expr = (Node *) varnode;
+       return (lcons(tle, NIL));
+}
+
+/*
+ ** setup_base_tlist --
+ **            Build a tlist that extracts a base type from the tuple
+ **            returned by the executor.
+ */
+List *
+setup_base_tlist(Oid typeid)
+{
+       TargetEntry *tle;
+       Resdom     *resnode;
+       Var                *varnode;
+
+       resnode = makeResdom(1,
+                                                typeid,
+                                                typeLen(typeidType(typeid)),
+                                                "<noname>",
+                                                0,
+                                                (Oid) 0,
+                                                0);
+       varnode = makeVar(-1, 1, typeid, -1, 1);
+       tle = makeNode(TargetEntry);
+       tle->resdom = resnode;
+       tle->expr = (Node *) varnode;
+
+       return (lcons(tle, NIL));
+}
+
+/*
+ * ParseComplexProjection -
+ *       handles function calls with a single argument that is of complex type.
+ *       This routine returns NULL if it can't handle the projection (eg. sets).
+ */
+Node *
+ParseComplexProjection(ParseState *pstate,
+                                          char *funcname,
+                                          Node *first_arg,
+                                          bool *attisset)
+{
+       Oid                     argtype;
+       Oid                     argrelid;
+       Name            relname;
+       Relation        rd;
+       Oid                     relid;
+       int                     attnum;
+
+       switch (nodeTag(first_arg))
+       {
+               case T_Iter:
+                       {
+                               Func       *func;
+                               Iter       *iter;
+
+                               iter = (Iter *) first_arg;
+                               func = (Func *) ((Expr *) iter->iterexpr)->oper;
+                               argtype = funcid_get_rettype(func->funcid);
+                               argrelid = typeidTypeRelid(argtype);
+                               if (argrelid &&
+                                       ((attnum = get_attnum(argrelid, funcname))
+                                        != InvalidAttrNumber))
+                               {
+
+                                       /*
+                                        * the argument is a function returning a tuple, so
+                                        * funcname may be a projection
+                                        */
+
+                                       /* add a tlist to the func node and return the Iter */
+                                       rd = heap_openr(typeidTypeName(argtype));
+                                       if (RelationIsValid(rd))
+                                       {
+                                               relid = RelationGetRelationId(rd);
+                                               relname = RelationGetRelationName(rd);
+                                               heap_close(rd);
+                                       }
+                                       if (RelationIsValid(rd))
+                                       {
+                                               func->func_tlist =
+                                                       setup_tlist(funcname, argrelid);
+                                               iter->itertype = attnumTypeId(rd, attnum);
+                                               return ((Node *) iter);
+                                       }
+                                       else
+                                       {
+                                               elog(WARN,
+                                                        "Function '%s' has bad returntype %d",
+                                                        funcname, argtype);
+                                       }
+                               }
+                               else
+                               {
+                                       /* drop through */
+                                       ;
+                               }
+                               break;
+                       }
+               case T_Var:
+                       {
+
+                               /*
+                                * The argument is a set, so this is either a projection
+                                * or a function call on this set.
+                                */
+                               *attisset = true;
+                               break;
+                       }
+               case T_Expr:
+                       {
+                               Expr       *expr = (Expr *) first_arg;
+                               Func       *funcnode;
+
+                               if (expr->opType != FUNC_EXPR)
+                                       break;
+
+                               funcnode = (Func *) expr->oper;
+                               argtype = funcid_get_rettype(funcnode->funcid);
+                               argrelid = typeidTypeRelid(argtype);
+
+                               /*
+                                * the argument is a function returning a tuple, so
+                                * funcname may be a projection
+                                */
+                               if (argrelid &&
+                                       (attnum = get_attnum(argrelid, funcname))
+                                       != InvalidAttrNumber)
+                               {
+
+                                       /* add a tlist to the func node */
+                                       rd = heap_openr(typeidTypeName(argtype));
+                                       if (RelationIsValid(rd))
+                                       {
+                                               relid = RelationGetRelationId(rd);
+                                               relname = RelationGetRelationName(rd);
+                                               heap_close(rd);
+                                       }
+                                       if (RelationIsValid(rd))
+                                       {
+                                               Expr       *newexpr;
+
+                                               funcnode->func_tlist =
+                                                       setup_tlist(funcname, argrelid);
+                                               funcnode->functype = attnumTypeId(rd, attnum);
+
+                                               newexpr = makeNode(Expr);
+                                               newexpr->typeOid = funcnode->functype;
+                                               newexpr->opType = FUNC_EXPR;
+                                               newexpr->oper = (Node *) funcnode;
+                                               newexpr->args = lcons(first_arg, NIL);
+
+                                               return ((Node *) newexpr);
+                                       }
+
+                               }
+
+                               elog(WARN, "Function '%s' has bad returntype %d",
+                                        funcname, argtype);
+                               break;
+                       }
+               case T_Param:
+                       {
+                               Param      *param = (Param *) first_arg;
+
+                               /*
+                                * If the Param is a complex type, this could be a
+                                * projection
+                                */
+                               rd = heap_openr(typeidTypeName(param->paramtype));
+                               if (RelationIsValid(rd))
+                               {
+                                       relid = RelationGetRelationId(rd);
+                                       relname = RelationGetRelationName(rd);
+                                       heap_close(rd);
+                               }
+                               if (RelationIsValid(rd) &&
+                                       (attnum = get_attnum(relid, funcname))
+                                       != InvalidAttrNumber)
+                               {
+
+                                       param->paramtype = attnumTypeId(rd, attnum);
+                                       param->param_tlist = setup_tlist(funcname, relid);
+                                       return ((Node *) param);
+                               }
+                               break;
+                       }
+               default:
+                       break;
+       }
+
+       return NULL;
+}
+
+/*
+ * Error message when function lookup fails that gives details of the
+ * argument types
+ */
+void
+func_error(char *caller, char *funcname, int nargs, Oid *argtypes)
+{
+       char            p[(NAMEDATALEN + 2) * MAXFMGRARGS],
+                          *ptr;
+       int                     i;
+
+       ptr = p;
+       *ptr = '\0';
+       for (i = 0; i < nargs; i++)
+       {
+               if (i)
+               {
+                       *ptr++ = ',';
+                       *ptr++ = ' ';
+               }
+               if (argtypes[i] != 0)
+               {
+                       strcpy(ptr, typeidTypeName(argtypes[i]));
+                       *(ptr + NAMEDATALEN) = '\0';
+               }
+               else
+                       strcpy(ptr, "opaque");
+               ptr += strlen(ptr);
+       }
+
+       elog(WARN, "%s: function %s(%s) does not exist", caller, funcname, p);
+}
+
+
+
similarity index 56%
rename from src/backend/parser/parse_query.c
rename to src/backend/parser/parse_node.c
index c47feea..c06e008 100644 (file)
 /*-------------------------------------------------------------------------
  *
- * parse_query.c--
- *       take an "optimizable" stmt and make the query tree that
- *        the planner requires.
+ * parse_node.c--
+ *       various routines that make nodes for query plans
  *
  * Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/Attic/parse_query.c,v 1.25 1997/11/24 05:08:27 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.1 1997/11/25 22:05:42 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include <ctype.h>
 #include <string.h>
-#include "postgres.h"
 
+#include "postgres.h"
 #include "fmgr.h"
 #include "access/heapam.h"
-#include "access/tupmacs.h"
+#include "catalog/pg_operator.h"
+#include "catalog/pg_type.h"
+#include "nodes/makefuncs.h"
+#include "parser/parse_expr.h"
+#include "parser/parse_oper.h"
+#include "parser/parse_node.h"
+#include "parser/parse_relation.h"
+#include "parser/parse_type.h"
 #include "utils/builtins.h"
+#include "utils/syscache.h"
+
+#ifdef 0
+#include "access/tupmacs.h"
 #include "utils/elog.h"
 #include "utils/palloc.h"
 #include "utils/acl.h"                 /* for ACL_NO_PRIV_WARNING */
 #include "utils/rel.h"                 /* Relation stuff */
 
 #include "utils/syscache.h"
-#include "catalog/pg_type.h"
-#include "catalog/pg_operator.h"
-#include "parser/catalog_utils.h"
-#include "parser/parse_query.h"
-#include "utils/lsyscache.h"
 
 #include "nodes/pg_list.h"
 #include "nodes/primnodes.h"
 #include "nodes/parsenodes.h"
-#include "nodes/makefuncs.h"
-
-static void
-checkTargetTypes(ParseState *pstate, char *target_colname,
-                                char *refname, char *colname);
-
-Oid               *param_type_info;
-int                    pfunc_num_args;
-
-/* given refname, return a pointer to the range table entry */
-RangeTblEntry *
-refnameRangeTableEntry(List *rtable, char *refname)
-{
-       List       *temp;
-
-       foreach(temp, rtable)
-       {
-               RangeTblEntry *rte = lfirst(temp);
-
-               if (!strcmp(rte->refname, refname))
-                       return rte;
-       }
-       return NULL;
-}
-
-/* given refname, return id of variable; position starts with 1 */
-int
-refnameRangeTablePosn(List *rtable, char *refname)
-{
-       int                     index;
-       List       *temp;
-
-       index = 1;
-       foreach(temp, rtable)
-       {
-               RangeTblEntry *rte = lfirst(temp);
-
-               if (!strcmp(rte->refname, refname))
-                       return index;
-               index++;
-       }
-       return (0);
-}
+#endif
 
 /*
- * returns range entry if found, else NULL
+ * make_parsestate() --
+ *       allocate and initialize a new ParseState.
+ *     the CALLERS is responsible for freeing the ParseState* returned
+ *
  */
-RangeTblEntry *
-colnameRangeTableEntry(ParseState *pstate, char *colname)
-{
-       List       *et;
-       List       *rtable;
-       RangeTblEntry *rte_result;
-
-       if (pstate->p_is_rule)
-               rtable = lnext(lnext(pstate->p_rtable));
-       else
-               rtable = pstate->p_rtable;
-
-       rte_result = NULL;
-       foreach(et, rtable)
-       {
-               RangeTblEntry *rte = lfirst(et);
-
-               /* only entries on outer(non-function?) scope */
-               if (!rte->inFromCl && rte != pstate->p_target_rangetblentry)
-                       continue;
-
-               if (get_attnum(rte->relid, colname) != InvalidAttrNumber)
-               {
-                       if (rte_result != NULL)
-                       {
-                               if (!pstate->p_is_insert ||
-                                       rte != pstate->p_target_rangetblentry)
-                                       elog(WARN, "Column %s is ambiguous", colname);
-                       }
-                       else
-                               rte_result = rte;
-               }
-       }
-       return rte_result;
-}
 
-/*
- * put new entry in pstate p_rtable structure, or return pointer
- * if pstate null
-*/
-RangeTblEntry *
-addRangeTableEntry(ParseState *pstate,
-                                  char *relname,
-                                  char *refname,
-                                  bool inh,
-                                  bool inFromCl)
-{
-       Relation        relation;
-       RangeTblEntry *rte = makeNode(RangeTblEntry);
-
-       if (pstate != NULL &&
-               refnameRangeTableEntry(pstate->p_rtable, refname) != NULL)
-               elog(WARN, "Table name %s specified more than once", refname);
-
-       rte->relname = pstrdup(relname);
-       rte->refname = pstrdup(refname);
-
-       relation = heap_openr(relname);
-       if (relation == NULL)
-       {
-               elog(WARN, "%s: %s",
-                        relname, aclcheck_error_strings[ACLCHECK_NO_CLASS]);
-       }
-
-       /*
-        * Flags - zero or more from inheritance,union,version or
-        * recursive (transitive closure) [we don't support them all -- ay
-        * 9/94 ]
-        */
-       rte->inh = inh;
-
-       /* RelOID */
-       rte->relid = RelationGetRelationId(relation);
-
-       rte->inFromCl = inFromCl;
-
-       /*
-        * close the relation we're done with it for now.
-        */
-       if (pstate != NULL)
-               pstate->p_rtable = lappend(pstate->p_rtable, rte);
-
-       heap_close(relation);
-
-       return rte;
-}
-
-/*
- * expandAll -
- *       makes a list of attributes
- *       assumes reldesc caching works
- */
-List      *
-expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
+ParseState *
+make_parsestate(void)
 {
-       Relation        rdesc;
-       List       *te_tail = NIL,
-                          *te_head = NIL;
-       Var                *varnode;
-       int                     varattno,
-                               maxattrs;
-       Oid                     type_id;
-       int                     type_len;
-       RangeTblEntry *rte;
-
-       rte = refnameRangeTableEntry(pstate->p_rtable, refname);
-       if (rte == NULL)
-               rte = addRangeTableEntry(pstate, relname, refname, FALSE, FALSE);
-
-       rdesc = heap_open(rte->relid);
-
-       if (rdesc == NULL)
-       {
-               elog(WARN, "Unable to expand all -- heap_open failed on %s",
-                        rte->refname);
-               return NIL;
-       }
-       maxattrs = RelationGetNumberOfAttributes(rdesc);
-
-       for (varattno = 0; varattno <= maxattrs - 1; varattno++)
-       {
-               char       *attrname;
-               char       *resname = NULL;
-               TargetEntry *te = makeNode(TargetEntry);
-
-               attrname = pstrdup((rdesc->rd_att->attrs[varattno]->attname).data);
-               varnode = (Var *) make_var(pstate, refname, attrname, &type_id);
-               type_len = (int) tlen(get_id_type(type_id));
-
-               handleTargetColname(pstate, &resname, refname, attrname);
-               if (resname != NULL)
-                       attrname = resname;
-
-               /*
-                * Even if the elements making up a set are complex, the set
-                * itself is not.
-                */
-
-               te->resdom = makeResdom((AttrNumber) (*this_resno)++,
-                                                               type_id,
-                                                               (Size) type_len,
-                                                               attrname,
-                                                               (Index) 0,
-                                                               (Oid) 0,
-                                                               0);
-               te->expr = (Node *) varnode;
-               if (te_head == NIL)
-                       te_head = te_tail = lcons(te, NIL);
-               else
-                       te_tail = lappend(te_tail, te);
-       }
-
-       heap_close(rdesc);
-       return (te_head);
+       ParseState *pstate;
+
+       pstate = malloc(sizeof(ParseState));
+       pstate->p_last_resno = 1;
+       pstate->p_rtable = NIL;
+       pstate->p_numAgg = 0;
+       pstate->p_aggs = NIL;
+       pstate->p_is_insert = false;
+       pstate->p_insert_columns = NIL;
+       pstate->p_is_update = false;
+       pstate->p_is_rule = false;
+       pstate->p_in_where_clause = false;
+       pstate->p_target_relation = NULL;
+       pstate->p_target_rangetblentry = NULL;
+
+       return (pstate);
 }
 
-static void
-disallow_setop(char *op, Type optype, Node *operand)
-{
-       if (operand == NULL)
-               return;
-
-       if (nodeTag(operand) == T_Iter)
-       {
-               elog(NOTICE, "An operand to the '%s' operator returns a set of %s,",
-                        op, tname(optype));
-               elog(WARN, "but '%s' takes single values, not sets.",
-                        op);
-       }
-}
-
-static Node *
+Node *
 make_operand(char *opname,
                         Node *tree,
                         Oid orig_typeId,
@@ -267,7 +84,7 @@ make_operand(char *opname,
        if (tree != NULL)
        {
                result = tree;
-               true_type = get_id_type(true_typeId);
+               true_type = typeidType(true_typeId);
                disallow_setop(opname, true_type, result);
                if (true_typeId != orig_typeId)
                {                                               /* must coerce */
@@ -276,13 +93,13 @@ make_operand(char *opname,
                        Assert(nodeTag(result) == T_Const);
                        val = (Datum) textout((struct varlena *)
                                                                  con->constvalue);
-                       infunc = typeid_get_retinfunc(true_typeId);
+                       infunc = typeidRetinfunc(true_typeId);
                        con = makeNode(Const);
                        con->consttype = true_typeId;
-                       con->constlen = tlen(true_type);
+                       con->constlen = typeLen(true_type);
                        con->constvalue = (Datum) fmgr(infunc,
                                                                                   val,
-                                                                                  get_typelem(true_typeId),
+                                                                                  typeidTypElem(true_typeId),
                                                                                   -1 /* for varchar() type */ );
                        con->constisnull = false;
                        con->constbyval = true;
@@ -307,6 +124,21 @@ make_operand(char *opname,
 }
 
 
+void
+disallow_setop(char *op, Type optype, Node *operand)
+{
+       if (operand == NULL)
+               return;
+
+       if (nodeTag(operand) == T_Iter)
+       {
+               elog(NOTICE, "An operand to the '%s' operator returns a set of %s,",
+                        op, typeTypeName(optype));
+               elog(WARN, "but '%s' takes single values, not sets.",
+                        op);
+       }
+}
+
 Expr      *
 make_op(char *opname, Node *ltree, Node *rtree)
 {
@@ -367,30 +199,30 @@ make_op(char *opname, Node *ltree, Node *rtree)
                        CONVERTABLE_TYPE(rtypeId) && nodeTag(rtree) == T_Const &&
                        !((Const *) rtree)->constiscast)
                {
-                       outfunc = typeid_get_retoutfunc(rtypeId);
-                       infunc = typeid_get_retinfunc(ltypeId);
+                       outfunc = typeidRetoutfunc(rtypeId);
+                       infunc = typeidRetinfunc(ltypeId);
                        outstr = (char *) fmgr(outfunc, ((Const *) rtree)->constvalue);
                        ((Const *) rtree)->constvalue = (Datum) fmgr(infunc, outstr);
                        pfree(outstr);
                        ((Const *) rtree)->consttype = rtypeId = ltypeId;
-                       newtype = get_id_type(rtypeId);
-                       ((Const *) rtree)->constlen = tlen(newtype);
-                       ((Const *) rtree)->constbyval = tbyval(newtype);
+                       newtype = typeidType(rtypeId);
+                       ((Const *) rtree)->constlen = typeLen(newtype);
+                       ((Const *) rtree)->constbyval = typeByVal(newtype);
                }
 
                if (CONVERTABLE_TYPE(rtypeId) && nodeTag(rtree) != T_Const &&
                        CONVERTABLE_TYPE(ltypeId) && nodeTag(ltree) == T_Const &&
                        !((Const *) ltree)->constiscast)
                {
-                       outfunc = typeid_get_retoutfunc(ltypeId);
-                       infunc = typeid_get_retinfunc(rtypeId);
+                       outfunc = typeidRetoutfunc(ltypeId);
+                       infunc = typeidRetinfunc(rtypeId);
                        outstr = (char *) fmgr(outfunc, ((Const *) ltree)->constvalue);
                        ((Const *) ltree)->constvalue = (Datum) fmgr(infunc, outstr);
                        pfree(outstr);
                        ((Const *) ltree)->consttype = ltypeId = rtypeId;
-                       newtype = get_id_type(ltypeId);
-                       ((Const *) ltree)->constlen = tlen(newtype);
-                       ((Const *) ltree)->constbyval = tbyval(newtype);
+                       newtype = typeidType(ltypeId);
+                       ((Const *) ltree)->constlen = typeLen(newtype);
+                       ((Const *) ltree)->constbyval = typeByVal(newtype);
                }
 
                temp = oper(opname, ltypeId, rtypeId, false);
@@ -426,38 +258,6 @@ make_op(char *opname, Node *ltree, Node *rtree)
        return result;
 }
 
-Oid
-find_atttype(Oid relid, char *attrname)
-{
-       int                     attid;
-       Oid                     vartype;
-       Relation        rd;
-
-       rd = heap_open(relid);
-       if (!RelationIsValid(rd))
-       {
-               rd = heap_openr(tname(get_id_type(relid)));
-               if (!RelationIsValid(rd))
-                       elog(WARN, "cannot compute type of att %s for relid %d",
-                                attrname, relid);
-       }
-
-       attid = nf_varattno(rd, attrname);
-
-       if (attid == InvalidAttrNumber)
-               elog(WARN, "Invalid attribute %s\n", attrname);
-
-       vartype = att_typeid(rd, attid);
-
-       /*
-        * close relation we're done with it now
-        */
-       heap_close(rd);
-
-       return (vartype);
-}
-
-
 Var               *
 make_var(ParseState *pstate, char *refname, char *attrname, Oid *type_id)
 {
@@ -476,10 +276,8 @@ make_var(ParseState *pstate, char *refname, char *attrname, Oid *type_id)
 
        rd = heap_open(rte->relid);
 
-       attid = nf_varattno(rd, attrname);
-       if (attid == InvalidAttrNumber)
-               elog(WARN, "Invalid attribute %s\n", attrname);
-       vartypeid = att_typeid(rd, attid);
+       attid = attnameAttNum(rd, attrname); /* could elog(WARN) */
+       vartypeid = attnumTypeId(rd, attid);
 
        varnode = makeVar(vnum, attid, vartypeid, vnum, attid);
 
@@ -667,7 +465,7 @@ make_const(Value *value)
        switch (nodeTag(value))
        {
                case T_Integer:
-                       tp = type("int4");
+                       tp = typeidType(INT4OID);
                        val = Int32GetDatum(intVal(value));
                        break;
 
@@ -675,7 +473,7 @@ make_const(Value *value)
                        {
                                float64         dummy;
 
-                               tp = type("float8");
+                               tp = typeidType(FLOAT8OID);
 
                                dummy = (float64) palloc(sizeof(float64data));
                                *dummy = floatVal(value);
@@ -685,7 +483,7 @@ make_const(Value *value)
                        break;
 
                case T_String:
-                       tp = type("unknown");           /* unknown for now, will be type
+                       tp = typeidType(UNKNOWNOID);    /* unknown for now, will be type
                                                                                 * coerced */
                        val = PointerGetDatum(textin(strVal(value)));
                        break;
@@ -702,111 +500,14 @@ make_const(Value *value)
                        }
        }
 
-       con = makeConst(typeid(tp),
-                                       tlen(tp),
+       con = makeConst(typeTypeId(tp),
+                                       typeLen(tp),
                                        val,
                                        false,
-                                       tbyval(tp),
+                                       typeByVal(tp),
                                        false,          /* not a set */
                                        false);
 
        return (con);
 }
 
-/*
- * param_type_init()
- *
- * keep enough information around fill out the type of param nodes
- * used in postquel functions
- */
-void
-param_type_init(Oid *typev, int nargs)
-{
-       pfunc_num_args = nargs;
-       param_type_info = typev;
-}
-
-Oid
-param_type(int t)
-{
-       if ((t > pfunc_num_args) || (t == 0))
-               return InvalidOid;
-       return param_type_info[t - 1];
-}
-
-/*
- * handleTargetColname -
- *       use column names from insert
- */
-void
-handleTargetColname(ParseState *pstate, char **resname,
-                                       char *refname, char *colname)
-{
-       if (pstate->p_is_insert)
-       {
-               if (pstate->p_insert_columns != NIL)
-               {
-                       Ident      *id = lfirst(pstate->p_insert_columns);
-
-                       *resname = id->name;
-                       pstate->p_insert_columns = lnext(pstate->p_insert_columns);
-               }
-               else
-                       elog(WARN, "insert: more expressions than target columns");
-       }
-       if (pstate->p_is_insert || pstate->p_is_update)
-               checkTargetTypes(pstate, *resname, refname, colname);
-}
-
-/*
- * checkTargetTypes -
- *       checks value and target column types
- */
-static void
-checkTargetTypes(ParseState *pstate, char *target_colname,
-                                char *refname, char *colname)
-{
-       Oid                     attrtype_id,
-                               attrtype_target;
-       int                     resdomno_id,
-                               resdomno_target;
-       Relation        rd;
-       RangeTblEntry *rte;
-
-       if (target_colname == NULL || colname == NULL)
-               return;
-
-       if (refname != NULL)
-               rte = refnameRangeTableEntry(pstate->p_rtable, refname);
-       else
-       {
-               rte = colnameRangeTableEntry(pstate, colname);
-               if (rte == (RangeTblEntry *) NULL)
-                       elog(WARN, "attribute %s not found", colname);
-               refname = rte->refname;
-       }
-
-/*
-       if (pstate->p_is_insert && rte == pstate->p_target_rangetblentry)
-               elog(WARN, "%s not available in this context", colname);
-*/
-       rd = heap_open(rte->relid);
-
-       resdomno_id = varattno(rd, colname);
-       attrtype_id = att_typeid(rd, resdomno_id);
-
-       resdomno_target = varattno(pstate->p_target_relation, target_colname);
-       attrtype_target = att_typeid(pstate->p_target_relation, resdomno_target);
-
-       if (attrtype_id != attrtype_target)
-               elog(WARN, "Type of %s does not match target column %s",
-                        colname, target_colname);
-
-       if ((attrtype_id == BPCHAROID || attrtype_id == VARCHAROID) &&
-               rd->rd_att->attrs[resdomno_id - 1]->attlen !=
-       pstate->p_target_relation->rd_att->attrs[resdomno_target - 1]->attlen)
-               elog(WARN, "Length of %s does not match length of target column %s",
-                        colname, target_colname);
-
-       heap_close(rd);
-}
diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c
new file mode 100644 (file)
index 0000000..d82a46b
--- /dev/null
@@ -0,0 +1,613 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_oper.h
+ *             handle operator things for parser
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.1 1997/11/25 22:05:43 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <string.h>
+#include "postgres.h"
+#include <fmgr.h>
+
+#include <access/heapam.h>
+#include <access/relscan.h>
+#include <catalog/catname.h>
+#include <catalog/pg_operator.h>
+#include <catalog/pg_proc.h>
+#include <catalog/pg_type.h>
+#include <parser/parse_oper.h>
+#include <parser/parse_type.h>
+#include <storage/bufmgr.h>
+#include <utils/syscache.h>
+
+#ifdef 0
+#include "lib/dllist.h"
+#include "utils/datum.h"
+
+#include "utils/builtins.h"
+#include "utils/elog.h"
+#include "utils/palloc.h"
+
+#include "nodes/pg_list.h"
+#include "nodes/parsenodes.h"
+
+#include "catalog/pg_inherits.h"
+#include "catalog/pg_operator.h"
+#include "catalog/pg_proc.h"
+#include "catalog/indexing.h"
+#include "catalog/catname.h"
+
+#include "access/skey.h"
+#include "access/relscan.h"
+#include "access/tupdesc.h"
+#include "access/htup.h"
+#include "access/genam.h"
+#include "access/itup.h"
+#include "access/tupmacs.h"
+#include "storage/buf.h"
+#include "utils/lsyscache.h"
+#include "storage/lmgr.h"
+
+#include "port-protos.h"               /* strdup() */
+#endif
+
+Oid
+any_ordering_op(int restype)
+{
+       Operator        order_op;
+       Oid                     order_opid;
+
+       order_op = oper("<", restype, restype, false);
+       order_opid = oprid(order_op);
+
+       return order_opid;
+}
+
+/* given operator, return the operator OID */
+Oid
+oprid(Operator op)
+{
+       return (op->t_oid);
+}
+
+/*
+ *     given opname, leftTypeId and rightTypeId,
+ *     find all possible (arg1, arg2) pairs for which an operator named
+ *     opname exists, such that leftTypeId can be coerced to arg1 and
+ *     rightTypeId can be coerced to arg2
+ */
+int
+binary_oper_get_candidates(char *opname,
+                                                  Oid leftTypeId,
+                                                  Oid rightTypeId,
+                                                  CandidateList *candidates)
+{
+       CandidateList current_candidate;
+       Relation        pg_operator_desc;
+       HeapScanDesc pg_operator_scan;
+       HeapTuple       tup;
+       OperatorTupleForm oper;
+       Buffer          buffer;
+       int                     nkeys;
+       int                     ncandidates = 0;
+       ScanKeyData opKey[3];
+
+       *candidates = NULL;
+
+       ScanKeyEntryInitialize(&opKey[0], 0,
+                                                  Anum_pg_operator_oprname,
+                                                  NameEqualRegProcedure,
+                                                  NameGetDatum(opname));
+
+       ScanKeyEntryInitialize(&opKey[1], 0,
+                                                  Anum_pg_operator_oprkind,
+                                                  CharacterEqualRegProcedure,
+                                                  CharGetDatum('b'));
+
+
+       if (leftTypeId == UNKNOWNOID)
+       {
+               if (rightTypeId == UNKNOWNOID)
+               {
+                       nkeys = 2;
+               }
+               else
+               {
+                       nkeys = 3;
+
+                       ScanKeyEntryInitialize(&opKey[2], 0,
+                                                                  Anum_pg_operator_oprright,
+                                                                  ObjectIdEqualRegProcedure,
+                                                                  ObjectIdGetDatum(rightTypeId));
+               }
+       }
+       else if (rightTypeId == UNKNOWNOID)
+       {
+               nkeys = 3;
+
+               ScanKeyEntryInitialize(&opKey[2], 0,
+                                                          Anum_pg_operator_oprleft,
+                                                          ObjectIdEqualRegProcedure,
+                                                          ObjectIdGetDatum(leftTypeId));
+       }
+       else
+               /* currently only "unknown" can be coerced */
+               return 0;
+
+       pg_operator_desc = heap_openr(OperatorRelationName);
+       pg_operator_scan = heap_beginscan(pg_operator_desc,
+                                                                         0,
+                                                                         true,
+                                                                         nkeys,
+                                                                         opKey);
+
+       do
+       {
+               tup = heap_getnext(pg_operator_scan, 0, &buffer);
+               if (HeapTupleIsValid(tup))
+               {
+                       current_candidate = (CandidateList) palloc(sizeof(struct _CandidateList));
+                       current_candidate->args = (Oid *) palloc(2 * sizeof(Oid));
+
+                       oper = (OperatorTupleForm) GETSTRUCT(tup);
+                       current_candidate->args[0] = oper->oprleft;
+                       current_candidate->args[1] = oper->oprright;
+                       current_candidate->next = *candidates;
+                       *candidates = current_candidate;
+                       ncandidates++;
+                       ReleaseBuffer(buffer);
+               }
+       } while (HeapTupleIsValid(tup));
+
+       heap_endscan(pg_operator_scan);
+       heap_close(pg_operator_desc);
+
+       return ncandidates;
+}
+
+/*
+ * equivalentOpersAfterPromotion -
+ *       checks if a list of candidate operators obtained from
+ *       binary_oper_get_candidates() contain equivalent operators. If
+ *       this routine is called, we have more than 1 candidate and need to
+ *       decided whether to pick one of them. This routine returns true if
+ *       the all the candidates operate on the same data types after
+ *       promotion (int2, int4, float4 -> float8).
+ */
+bool
+equivalentOpersAfterPromotion(CandidateList candidates)
+{
+       CandidateList result;
+       CandidateList promotedCandidates = NULL;
+       Oid                     leftarg,
+                               rightarg;
+
+       for (result = candidates; result != NULL; result = result->next)
+       {
+               CandidateList c;
+
+               c = (CandidateList) palloc(sizeof(*c));
+               c->args = (Oid *) palloc(2 * sizeof(Oid));
+               switch (result->args[0])
+               {
+                       case FLOAT4OID:
+                       case INT4OID:
+                       case INT2OID:
+                       case CASHOID:
+                               c->args[0] = FLOAT8OID;
+                               break;
+                       default:
+                               c->args[0] = result->args[0];
+                               break;
+               }
+               switch (result->args[1])
+               {
+                       case FLOAT4OID:
+                       case INT4OID:
+                       case INT2OID:
+                       case CASHOID:
+                               c->args[1] = FLOAT8OID;
+                               break;
+                       default:
+                               c->args[1] = result->args[1];
+                               break;
+               }
+               c->next = promotedCandidates;
+               promotedCandidates = c;
+       }
+
+       /*
+        * if we get called, we have more than 1 candidates so we can do the
+        * following safely
+        */
+       leftarg = promotedCandidates->args[0];
+       rightarg = promotedCandidates->args[1];
+
+       for (result = promotedCandidates->next; result != NULL; result = result->next)
+       {
+               if (result->args[0] != leftarg || result->args[1] != rightarg)
+
+                       /*
+                        * this list contains operators that operate on different data
+                        * types even after promotion. Hence we can't decide on which
+                        * one to pick. The user must do explicit type casting.
+                        */
+                       return FALSE;
+       }
+
+       /*
+        * all the candidates are equivalent in the following sense: they
+        * operate on equivalent data types and picking any one of them is as
+        * good.
+        */
+       return TRUE;
+}
+
+
+/*
+ *     given a choice of argument type pairs for a binary operator,
+ *     try to choose a default pair
+ */
+CandidateList
+binary_oper_select_candidate(Oid arg1,
+                                                        Oid arg2,
+                                                        CandidateList candidates)
+{
+       CandidateList result;
+
+       /*
+        * if both are "unknown", there is no way to select a candidate
+        *
+        * current wisdom holds that the default operator should be one in which
+        * both operands have the same type (there will only be one such
+        * operator)
+        *
+        * 7.27.93 - I have decided not to do this; it's too hard to justify, and
+        * it's easy enough to typecast explicitly -avi [the rest of this
+        * routine were commented out since then -ay]
+        */
+
+       if (arg1 == UNKNOWNOID && arg2 == UNKNOWNOID)
+               return (NULL);
+
+       /*
+        * 6/23/95 - I don't complete agree with avi. In particular, casting
+        * floats is a pain for users. Whatever the rationale behind not doing
+        * this is, I need the following special case to work.
+        *
+        * In the WHERE clause of a query, if a float is specified without
+        * quotes, we treat it as float8. I added the float48* operators so
+        * that we can operate on float4 and float8. But now we have more than
+        * one matching operator if the right arg is unknown (eg. float
+        * specified with quotes). This break some stuff in the regression
+        * test where there are floats in quotes not properly casted. Below is
+        * the solution. In addition to requiring the operator operates on the
+        * same type for both operands [as in the code Avi originally
+        * commented out], we also require that the operators be equivalent in
+        * some sense. (see equivalentOpersAfterPromotion for details.) - ay
+        * 6/95
+        */
+       if (!equivalentOpersAfterPromotion(candidates))
+               return NULL;
+
+       /*
+        * if we get here, any one will do but we're more picky and require
+        * both operands be the same.
+        */
+       for (result = candidates; result != NULL; result = result->next)
+       {
+               if (result->args[0] == result->args[1])
+                       return result;
+       }
+
+       return (NULL);
+}
+
+/* Given operator, types of arg1, and arg2, return oper struct */
+/* arg1, arg2 --typeids */
+Operator
+oper(char *op, Oid arg1, Oid arg2, bool noWarnings)
+{
+       HeapTuple       tup;
+       CandidateList candidates;
+       int                     ncandidates;
+
+       if (!arg2)
+               arg2 = arg1;
+       if (!arg1)
+               arg1 = arg2;
+
+       if (!(tup = SearchSysCacheTuple(OPRNAME,
+                                                                       PointerGetDatum(op),
+                                                                       ObjectIdGetDatum(arg1),
+                                                                       ObjectIdGetDatum(arg2),
+                                                                       Int8GetDatum('b'))))
+       {
+               ncandidates = binary_oper_get_candidates(op, arg1, arg2, &candidates);
+               if (ncandidates == 0)
+               {
+
+                       /*
+                        * no operators of the desired types found
+                        */
+                       if (!noWarnings)
+                               op_error(op, arg1, arg2);
+                       return (NULL);
+               }
+               else if (ncandidates == 1)
+               {
+
+                       /*
+                        * exactly one operator of the desired types found
+                        */
+                       tup = SearchSysCacheTuple(OPRNAME,
+                                                                         PointerGetDatum(op),
+                                                                  ObjectIdGetDatum(candidates->args[0]),
+                                                                  ObjectIdGetDatum(candidates->args[1]),
+                                                                         Int8GetDatum('b'));
+                       Assert(HeapTupleIsValid(tup));
+               }
+               else
+               {
+
+                       /*
+                        * multiple operators of the desired types found
+                        */
+                       candidates = binary_oper_select_candidate(arg1, arg2, candidates);
+                       if (candidates != NULL)
+                       {
+                               /* we chose one of them */
+                               tup = SearchSysCacheTuple(OPRNAME,
+                                                                                 PointerGetDatum(op),
+                                                                  ObjectIdGetDatum(candidates->args[0]),
+                                                                  ObjectIdGetDatum(candidates->args[1]),
+                                                                                 Int8GetDatum('b'));
+                               Assert(HeapTupleIsValid(tup));
+                       }
+                       else
+                       {
+                               Type            tp1,
+                                                       tp2;
+
+                               /* we chose none of them */
+                               tp1 = typeidType(arg1);
+                               tp2 = typeidType(arg2);
+                               if (!noWarnings)
+                               {
+                                       elog(NOTICE, "there is more than one operator %s for types", op);
+                                       elog(NOTICE, "%s and %s. You will have to retype this query",
+                                                typeTypeName(tp1), typeTypeName(tp2));
+                                       elog(WARN, "using an explicit cast");
+                               }
+                               return (NULL);
+                       }
+               }
+       }
+       return ((Operator) tup);
+}
+
+/*
+ *     given opname and typeId, find all possible types for which
+ *     a right/left unary operator named opname exists,
+ *     such that typeId can be coerced to it
+ */
+int
+unary_oper_get_candidates(char *op,
+                                                 Oid typeId,
+                                                 CandidateList *candidates,
+                                                 char rightleft)
+{
+       CandidateList current_candidate;
+       Relation        pg_operator_desc;
+       HeapScanDesc pg_operator_scan;
+       HeapTuple       tup;
+       OperatorTupleForm oper;
+       Buffer          buffer;
+       int                     ncandidates = 0;
+
+       static ScanKeyData opKey[2] = {
+               {0, Anum_pg_operator_oprname, NameEqualRegProcedure},
+       {0, Anum_pg_operator_oprkind, CharacterEqualRegProcedure}};
+
+       *candidates = NULL;
+
+       fmgr_info(NameEqualRegProcedure, (func_ptr *) &opKey[0].sk_func,
+                         &opKey[0].sk_nargs);
+       opKey[0].sk_argument = NameGetDatum(op);
+       fmgr_info(CharacterEqualRegProcedure, (func_ptr *) &opKey[1].sk_func,
+                         &opKey[1].sk_nargs);
+       opKey[1].sk_argument = CharGetDatum(rightleft);
+
+       /* currently, only "unknown" can be coerced */
+
+       /*
+        * but we should allow types that are internally the same to be
+        * "coerced"
+        */
+       if (typeId != UNKNOWNOID)
+       {
+               return 0;
+       }
+
+       pg_operator_desc = heap_openr(OperatorRelationName);
+       pg_operator_scan = heap_beginscan(pg_operator_desc,
+                                                                         0,
+                                                                         true,
+                                                                         2,
+                                                                         opKey);
+
+       do
+       {
+               tup = heap_getnext(pg_operator_scan, 0, &buffer);
+               if (HeapTupleIsValid(tup))
+               {
+                       current_candidate = (CandidateList) palloc(sizeof(struct _CandidateList));
+                       current_candidate->args = (Oid *) palloc(sizeof(Oid));
+
+                       oper = (OperatorTupleForm) GETSTRUCT(tup);
+                       if (rightleft == 'r')
+                               current_candidate->args[0] = oper->oprleft;
+                       else
+                               current_candidate->args[0] = oper->oprright;
+                       current_candidate->next = *candidates;
+                       *candidates = current_candidate;
+                       ncandidates++;
+                       ReleaseBuffer(buffer);
+               }
+       } while (HeapTupleIsValid(tup));
+
+       heap_endscan(pg_operator_scan);
+       heap_close(pg_operator_desc);
+
+       return ncandidates;
+}
+
+/* Given unary right-side operator (operator on right), return oper struct */
+/* arg-- type id */
+Operator
+right_oper(char *op, Oid arg)
+{
+       HeapTuple       tup;
+       CandidateList candidates;
+       int                     ncandidates;
+
+       /*
+        * if (!OpCache) { init_op_cache(); }
+        */
+       if (!(tup = SearchSysCacheTuple(OPRNAME,
+                                                                       PointerGetDatum(op),
+                                                                       ObjectIdGetDatum(arg),
+                                                                       ObjectIdGetDatum(InvalidOid),
+                                                                       Int8GetDatum('r'))))
+       {
+               ncandidates = unary_oper_get_candidates(op, arg, &candidates, 'r');
+               if (ncandidates == 0)
+               {
+                       elog(WARN,
+                                "Can't find right op: %s for type %d", op, arg);
+                       return (NULL);
+               }
+               else if (ncandidates == 1)
+               {
+                       tup = SearchSysCacheTuple(OPRNAME,
+                                                                         PointerGetDatum(op),
+                                                                  ObjectIdGetDatum(candidates->args[0]),
+                                                                         ObjectIdGetDatum(InvalidOid),
+                                                                         Int8GetDatum('r'));
+                       Assert(HeapTupleIsValid(tup));
+               }
+               else
+               {
+                       elog(NOTICE, "there is more than one right operator %s", op);
+                       elog(NOTICE, "you will have to retype this query");
+                       elog(WARN, "using an explicit cast");
+                       return (NULL);
+               }
+       }
+       return ((Operator) tup);
+}
+
+/* Given unary left-side operator (operator on left), return oper struct */
+/* arg--type id */
+Operator
+left_oper(char *op, Oid arg)
+{
+       HeapTuple       tup;
+       CandidateList candidates;
+       int                     ncandidates;
+
+       /*
+        * if (!OpCache) { init_op_cache(); }
+        */
+       if (!(tup = SearchSysCacheTuple(OPRNAME,
+                                                                       PointerGetDatum(op),
+                                                                       ObjectIdGetDatum(InvalidOid),
+                                                                       ObjectIdGetDatum(arg),
+                                                                       Int8GetDatum('l'))))
+       {
+               ncandidates = unary_oper_get_candidates(op, arg, &candidates, 'l');
+               if (ncandidates == 0)
+               {
+                       elog(WARN,
+                                "Can't find left op: %s for type %d", op, arg);
+                       return (NULL);
+               }
+               else if (ncandidates == 1)
+               {
+                       tup = SearchSysCacheTuple(OPRNAME,
+                                                                         PointerGetDatum(op),
+                                                                         ObjectIdGetDatum(InvalidOid),
+                                                                  ObjectIdGetDatum(candidates->args[0]),
+                                                                         Int8GetDatum('l'));
+                       Assert(HeapTupleIsValid(tup));
+               }
+               else
+               {
+                       elog(NOTICE, "there is more than one left operator %s", op);
+                       elog(NOTICE, "you will have to retype this query");
+                       elog(WARN, "using an explicit cast");
+                       return (NULL);
+               }
+       }
+       return ((Operator) tup);
+}
+
+/* Given a typename and value, returns the ascii form of the value */
+
+#ifdef NOT_USED
+char      *
+outstr(char *typename,                 /* Name of type of value */
+          char *value)                         /* Could be of any type */
+{
+       TypeTupleForm tp;
+       Oid                     op;
+
+       tp = (TypeTupleForm) GETSTRUCT(type(typename));
+       op = tp->typoutput;
+       return ((char *) fmgr(op, value));
+}
+
+#endif
+
+/*
+ * Give a somewhat useful error message when the operator for two types
+ * is not found.
+ */
+void
+op_error(char *op, Oid arg1, Oid arg2)
+{
+       Type            tp1 = NULL,
+                               tp2 = NULL;
+
+       if (typeidIsValid(arg1))
+       {
+               tp1 = typeidType(arg1);
+       }
+       else
+       {
+               elog(WARN, "left hand side of operator %s has an unknown type, probably a bad attribute name", op);
+       }
+
+       if (typeidIsValid(arg2))
+       {
+               tp2 = typeidType(arg2);
+       }
+       else
+       {
+               elog(WARN, "right hand side of operator %s has an unknown type, probably a bad attribute name", op);
+       }
+
+       elog(NOTICE, "there is no operator %s for types %s and %s",
+                op, typeTypeName(tp1), typeTypeName(tp2));
+       elog(NOTICE, "You will either have to retype this query using an");
+       elog(NOTICE, "explicit cast, or you will have to define the operator");
+       elog(WARN, "%s for %s and %s using CREATE OPERATOR",
+                op, typeTypeName(tp1), typeTypeName(tp2));
+}
+
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
new file mode 100644 (file)
index 0000000..dd3fa27
--- /dev/null
@@ -0,0 +1,480 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_relation.c--
+ *       parser support routines dealing with relations
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.1 1997/11/25 22:05:45 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <ctype.h>
+#include <string.h>
+
+#include "postgres.h"
+#include "access/heapam.h"
+#include <access/htup.h>
+#include <catalog/pg_type.h>
+#include "nodes/makefuncs.h"
+#include <parser/parse_relation.h>
+#include <utils/acl.h>
+#include "utils/builtins.h"
+#include <utils/lsyscache.h>
+
+#ifdef 0
+#include "fmgr.h"
+#include "access/tupmacs.h"
+#include "utils/elog.h"
+#include "utils/palloc.h"
+#include "utils/acl.h"                 /* for ACL_NO_PRIV_WARNING */
+
+#include "utils/syscache.h"
+#include "catalog/pg_operator.h"
+
+#include "nodes/pg_list.h"
+#include "nodes/primnodes.h"
+#include "nodes/parsenodes.h"
+#endif
+
+struct
+{
+       char       *field;
+       int                     code;
+}                      special_attr[] =
+
+{
+       {
+               "ctid", SelfItemPointerAttributeNumber
+       },
+       {
+               "oid", ObjectIdAttributeNumber
+       },
+       {
+               "xmin", MinTransactionIdAttributeNumber
+       },
+       {
+               "cmin", MinCommandIdAttributeNumber
+       },
+       {
+               "xmax", MaxTransactionIdAttributeNumber
+       },
+       {
+               "cmax", MaxCommandIdAttributeNumber
+       },
+};
+
+#define SPECIALS (sizeof(special_attr)/sizeof(*special_attr))
+
+static char *attnum_type[SPECIALS] = {
+       "tid",
+       "oid",
+       "xid",
+       "cid",
+       "xid",
+       "cid",
+};
+
+/* given refname, return a pointer to the range table entry */
+RangeTblEntry *
+refnameRangeTableEntry(List *rtable, char *refname)
+{
+       List       *temp;
+
+       foreach(temp, rtable)
+       {
+               RangeTblEntry *rte = lfirst(temp);
+
+               if (!strcmp(rte->refname, refname))
+                       return rte;
+       }
+       return NULL;
+}
+
+/* given refname, return id of variable; position starts with 1 */
+int
+refnameRangeTablePosn(List *rtable, char *refname)
+{
+       int                     index;
+       List       *temp;
+
+       index = 1;
+       foreach(temp, rtable)
+       {
+               RangeTblEntry *rte = lfirst(temp);
+
+               if (!strcmp(rte->refname, refname))
+                       return index;
+               index++;
+       }
+       return (0);
+}
+
+/*
+ * returns range entry if found, else NULL
+ */
+RangeTblEntry *
+colnameRangeTableEntry(ParseState *pstate, char *colname)
+{
+       List       *et;
+       List       *rtable;
+       RangeTblEntry *rte_result;
+
+       if (pstate->p_is_rule)
+               rtable = lnext(lnext(pstate->p_rtable));
+       else
+               rtable = pstate->p_rtable;
+
+       rte_result = NULL;
+       foreach(et, rtable)
+       {
+               RangeTblEntry *rte = lfirst(et);
+
+               /* only entries on outer(non-function?) scope */
+               if (!rte->inFromCl && rte != pstate->p_target_rangetblentry)
+                       continue;
+
+               if (get_attnum(rte->relid, colname) != InvalidAttrNumber)
+               {
+                       if (rte_result != NULL)
+                       {
+                               if (!pstate->p_is_insert ||
+                                       rte != pstate->p_target_rangetblentry)
+                                       elog(WARN, "Column %s is ambiguous", colname);
+                       }
+                       else
+                               rte_result = rte;
+               }
+       }
+       return rte_result;
+}
+
+/*
+ * put new entry in pstate p_rtable structure, or return pointer
+ * if pstate null
+*/
+RangeTblEntry *
+addRangeTableEntry(ParseState *pstate,
+                                  char *relname,
+                                  char *refname,
+                                  bool inh,
+                                  bool inFromCl)
+{
+       Relation        relation;
+       RangeTblEntry *rte = makeNode(RangeTblEntry);
+
+       if (pstate != NULL &&
+               refnameRangeTableEntry(pstate->p_rtable, refname) != NULL)
+               elog(WARN, "Table name %s specified more than once", refname);
+
+       rte->relname = pstrdup(relname);
+       rte->refname = pstrdup(refname);
+
+       relation = heap_openr(relname);
+       if (relation == NULL)
+       {
+               elog(WARN, "%s: %s",
+                        relname, aclcheck_error_strings[ACLCHECK_NO_CLASS]);
+       }
+
+       /*
+        * Flags - zero or more from inheritance,union,version or
+        * recursive (transitive closure) [we don't support them all -- ay
+        * 9/94 ]
+        */
+       rte->inh = inh;
+
+       /* RelOID */
+       rte->relid = RelationGetRelationId(relation);
+
+       rte->inFromCl = inFromCl;
+
+       /*
+        * close the relation we're done with it for now.
+        */
+       if (pstate != NULL)
+               pstate->p_rtable = lappend(pstate->p_rtable, rte);
+
+       heap_close(relation);
+
+       return rte;
+}
+
+/*
+ * expandAll -
+ *       makes a list of attributes
+ *       assumes reldesc caching works
+ */
+List      *
+expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
+{
+       Relation        rdesc;
+       List       *te_tail = NIL,
+                          *te_head = NIL;
+       Var                *varnode;
+       int                     varattno,
+                               maxattrs;
+       Oid                     type_id;
+       int                     type_len;
+       RangeTblEntry *rte;
+
+       rte = refnameRangeTableEntry(pstate->p_rtable, refname);
+       if (rte == NULL)
+               rte = addRangeTableEntry(pstate, relname, refname, FALSE, FALSE);
+
+       rdesc = heap_open(rte->relid);
+
+       if (rdesc == NULL)
+       {
+               elog(WARN, "Unable to expand all -- heap_open failed on %s",
+                        rte->refname);
+               return NIL;
+       }
+       maxattrs = RelationGetNumberOfAttributes(rdesc);
+
+       for (varattno = 0; varattno <= maxattrs - 1; varattno++)
+       {
+               char       *attrname;
+               char       *resname = NULL;
+               TargetEntry *te = makeNode(TargetEntry);
+
+               attrname = pstrdup((rdesc->rd_att->attrs[varattno]->attname).data);
+               varnode = (Var *) make_var(pstate, refname, attrname, &type_id);
+               type_len = (int) typeLen(typeidType(type_id));
+
+               handleTargetColname(pstate, &resname, refname, attrname);
+               if (resname != NULL)
+                       attrname = resname;
+
+               /*
+                * Even if the elements making up a set are complex, the set
+                * itself is not.
+                */
+
+               te->resdom = makeResdom((AttrNumber) (*this_resno)++,
+                                                               type_id,
+                                                               (Size) type_len,
+                                                               attrname,
+                                                               (Index) 0,
+                                                               (Oid) 0,
+                                                               0);
+               te->expr = (Node *) varnode;
+               if (te_head == NIL)
+                       te_head = te_tail = lcons(te, NIL);
+               else
+                       te_tail = lappend(te_tail, te);
+       }
+
+       heap_close(rdesc);
+       return (te_head);
+}
+
+/* given relation and att name, return id of variable */
+int
+attnameAttNum(Relation rd, char *a)
+{
+       int                     i;
+
+       for (i = 0; i < rd->rd_rel->relnatts; i++)
+               if (!namestrcmp(&(rd->rd_att->attrs[i]->attname), a))
+                       return (i + 1);
+
+       for (i = 0; i < SPECIALS; i++)
+               if (!strcmp(special_attr[i].field, a))
+                       return (special_attr[i].code);
+
+       /* on failure */
+       elog(WARN, "Relation %s does not have attribute %s",
+                RelationGetRelationName(rd), a);
+       return 0;  /* lint */
+}
+
+/* Given range variable, return whether attribute of this name
+ * is a set.
+ * NOTE the ASSUMPTION here that no system attributes are, or ever
+ * will be, sets.
+ */
+bool
+attnameIsSet(Relation rd, char *name)
+{
+       int                     i;
+
+       /* First check if this is a system attribute */
+       for (i = 0; i < SPECIALS; i++)
+       {
+               if (!strcmp(special_attr[i].field, name))
+               {
+                       return (false);         /* no sys attr is a set */
+               }
+       }
+       return (get_attisset(rd->rd_id, name));
+}
+
+/*-------------
+ * given an attribute number and a relation, return its relation name
+ */
+char      *
+attnumAttName(Relation rd, int attrno)
+{
+       char       *name;
+       int                     i;
+
+       if (attrno < 0)
+       {
+               for (i = 0; i < SPECIALS; i++)
+               {
+                       if (special_attr[i].code == attrno)
+                       {
+                               name = special_attr[i].field;
+                               return (name);
+                       }
+               }
+               elog(WARN, "Illegal attr no %d for relation %s",
+                        attrno, RelationGetRelationName(rd));
+       }
+       else if (attrno >= 1 && attrno <= RelationGetNumberOfAttributes(rd))
+       {
+               name = (rd->rd_att->attrs[attrno - 1]->attname).data;
+               return (name);
+       }
+       else
+       {
+               elog(WARN, "Illegal attr no %d for relation %s",
+                        attrno, RelationGetRelationName(rd));
+       }
+
+       /*
+        * Shouldn't get here, but we want lint to be happy...
+        */
+
+       return (NULL);
+}
+
+int
+attnumAttNelems(Relation rd, int attid)
+{
+       return (rd->rd_att->attrs[attid - 1]->attnelems);
+}
+
+Oid
+attnameTypeId(Oid relid, char *attrname)
+{
+       int                     attid;
+       Oid                     vartype;
+       Relation        rd;
+
+       rd = heap_open(relid);
+       if (!RelationIsValid(rd))
+       {
+               rd = heap_openr(typeidTypeName(relid));
+               if (!RelationIsValid(rd))
+                       elog(WARN, "cannot compute type of att %s for relid %d",
+                                attrname, relid);
+       }
+
+       attid = attnameAttNum(rd, attrname); /* could elog(WARN) and never return */
+
+       vartype = attnumTypeId(rd, attid);
+
+       /*
+        * close relation we're done with it now
+        */
+       heap_close(rd);
+
+       return (vartype);
+}
+
+/* given attribute id, return type of that attribute */
+/* XXX Special case for pseudo-attributes is a hack */
+Oid
+attnumTypeId(Relation rd, int attid)
+{
+
+       if (attid < 0)
+               return (typeTypeId(typenameType(attnum_type[-attid - 1])));
+
+       /*
+        * -1 because varattno (where attid comes from) returns one more than
+        * index
+        */
+       return (rd->rd_att->attrs[attid - 1]->atttypid);
+}
+
+/*
+ * handleTargetColname -
+ *       use column names from insert
+ */
+void
+handleTargetColname(ParseState *pstate, char **resname,
+                                       char *refname, char *colname)
+{
+       if (pstate->p_is_insert)
+       {
+               if (pstate->p_insert_columns != NIL)
+               {
+                       Ident      *id = lfirst(pstate->p_insert_columns);
+
+                       *resname = id->name;
+                       pstate->p_insert_columns = lnext(pstate->p_insert_columns);
+               }
+               else
+                       elog(WARN, "insert: more expressions than target columns");
+       }
+       if (pstate->p_is_insert || pstate->p_is_update)
+               checkTargetTypes(pstate, *resname, refname, colname);
+}
+
+/*
+ * checkTargetTypes -
+ *       checks value and target column types
+ */
+void
+checkTargetTypes(ParseState *pstate, char *target_colname,
+                                char *refname, char *colname)
+{
+       Oid                     attrtype_id,
+                               attrtype_target;
+       int                     resdomno_id,
+                               resdomno_target;
+       Relation        rd;
+       RangeTblEntry *rte;
+
+       if (target_colname == NULL || colname == NULL)
+               return;
+
+       if (refname != NULL)
+               rte = refnameRangeTableEntry(pstate->p_rtable, refname);
+       else
+       {
+               rte = colnameRangeTableEntry(pstate, colname);
+               if (rte == (RangeTblEntry *) NULL)
+                       elog(WARN, "attribute %s not found", colname);
+               refname = rte->refname;
+       }
+
+/*
+       if (pstate->p_is_insert && rte == pstate->p_target_rangetblentry)
+               elog(WARN, "%s not available in this context", colname);
+*/
+       rd = heap_open(rte->relid);
+
+       resdomno_id = attnameAttNum(rd, colname);
+       attrtype_id = attnumTypeId(rd, resdomno_id);
+
+       resdomno_target = attnameAttNum(pstate->p_target_relation, target_colname);
+       attrtype_target = attnumTypeId(pstate->p_target_relation, resdomno_target);
+
+       if (attrtype_id != attrtype_target)
+               elog(WARN, "Type of %s does not match target column %s",
+                        colname, target_colname);
+
+       if ((attrtype_id == BPCHAROID || attrtype_id == VARCHAROID) &&
+               rd->rd_att->attrs[resdomno_id - 1]->attlen !=
+       pstate->p_target_relation->rd_att->attrs[resdomno_target - 1]->attlen)
+               elog(WARN, "Length of %s does not match length of target column %s",
+                        colname, target_colname);
+
+       heap_close(rd);
+}
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
new file mode 100644 (file)
index 0000000..f29aa49
--- /dev/null
@@ -0,0 +1,679 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_target.c
+ *       handle target lists
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.1 1997/11/25 22:05:47 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "postgres.h"
+#include "catalog/pg_type.h"
+#include "nodes/makefuncs.h"
+#include "nodes/primnodes.h"
+#include "parser/parse_expr.h"
+#include "parser/parse_relation.h"
+#include "parser/parse_target.h"
+#include "parser/parse_node.h"
+#include "utils/builtins.h"
+
+#ifdef 0
+#include "nodes/nodes.h"
+#include "nodes/params.h"
+#include "nodes/parsenodes.h"
+#include "nodes/relation.h"
+#include "parse.h"                             /* for AND, OR, etc. */
+#include "catalog/pg_aggregate.h"
+#include "catalog/pg_proc.h"
+#include "utils/elog.h"
+#include "utils/palloc.h"
+#include "utils/mcxt.h"
+#include "utils/syscache.h"
+#include "utils/acl.h"
+#include "nodes/nodeFuncs.h"
+#include "commands/sequence.h"
+
+#include "optimizer/clauses.h"
+#include "access/heapam.h"
+
+#include "miscadmin.h"
+
+#include "port-protos.h"               /* strdup() */
+#endif
+
+/*
+ * 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 = makeNode(TargetEntry);
+
+               switch (nodeTag(res->val))
+               {
+                       case T_Ident:
+                               {
+                                       Node       *expr;
+                                       Oid                     type_id;
+                                       int                     type_len;
+                                       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);
+                                       type_len = typeLen(typeidType(type_id));
+                                       resname = (res->name) ? res->name : identname;
+                                       tent->resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
+                                                                                         (Oid) type_id,
+                                                                                         (Size) type_len,
+                                                                                         resname,
+                                                                                         (Index) 0,
+                                                                                         (Oid) 0,
+                                                                                         0);
+
+                                       tent->expr = expr;
+                                       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);
+
+                                       handleTargetColname(pstate, &res->name, NULL, NULL);
+                                       /* note indirection has not been transformed */
+                                       if (pstate->p_is_insert && res->indirection != NIL)
+                                       {
+                                               /* this is an array assignment */
+                                               char       *val;
+                                               char       *str,
+                                                                  *save_str;
+                                               List       *elt;
+                                               int                     i = 0,
+                                                                       ndims;
+                                               int                     lindx[MAXDIM],
+                                                                       uindx[MAXDIM];
+                                               int                     resdomno;
+                                               Relation        rd;
+                                               Value      *constval;
+
+                                               if (exprType(expr) != UNKNOWNOID ||
+                                                       !IsA(expr, Const))
+                                                       elog(WARN, "yyparse: string constant expected");
+
+                                               val = (char *) textout((struct varlena *)
+                                                                                  ((Const *) expr)->constvalue);
+                                               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, 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, EXPR_COLUMN_FIRST);
+                                                               if (!IsA(aind->lidx, Const))
+                                                                       elog(WARN,
+                                                                                "Array Index for Append should be a constant");
+                                                               lindx[i] = ((Const *) aind->lidx)->constvalue;
+                                                       }
+                                                       else
+                                                       {
+                                                               lindx[i] = 1;
+                                                       }
+                                                       if (lindx[i] > uindx[i])
+                                                               elog(WARN, "yyparse: lower index cannot be greater than upper index");
+                                                       sprintf(str, "[%d:%d]", lindx[i], uindx[i]);
+                                                       str += strlen(str);
+                                                       i++;
+                                               }
+                                               sprintf(str, "=%s", val);
+                                               rd = pstate->p_target_relation;
+                                               Assert(rd != NULL);
+                                               resdomno = attnameAttNum(rd, res->name);
+                                               ndims = attnumAttNelems(rd, resdomno);
+                                               if (i != ndims)
+                                                       elog(WARN, "yyparse: array dimensions do not match");
+                                               constval = makeNode(Value);
+                                               constval->type = T_String;
+                                               constval->val.str = save_str;
+                                               tent = make_targetlist_expr(pstate, res->name,
+                                                                                  (Node *) make_const(constval),
+                                                                                                       NULL);
+                                               pfree(save_str);
+                                       }
+                                       else
+                                       {
+                                               char       *colname = res->name;
+
+                                               /* this is not an array assignment */
+                                               if (colname == NULL)
+                                               {
+
+                                                       /*
+                                                        * if you're wondering why this is here, look
+                                                        * at the yacc grammar for why a name can be
+                                                        * missing. -ay
+                                                        */
+                                                       colname = figureColname(expr, res->val);
+                                               }
+                                               if (res->indirection)
+                                               {
+                                                       List       *ilist = res->indirection;
+
+                                                       while (ilist != NIL)
+                                                       {
+                                                               A_Indices  *ind = lfirst(ilist);
+
+                                                               ind->lidx = transformExpr(pstate, ind->lidx, EXPR_COLUMN_FIRST);
+                                                               ind->uidx = transformExpr(pstate, ind->uidx, EXPR_COLUMN_FIRST);
+                                                               ilist = lnext(ilist);
+                                                       }
+                                               }
+                                               res->name = colname;
+                                               tent = make_targetlist_expr(pstate, res->name, expr,
+                                                                                                       res->indirection);
+                                       }
+                                       break;
+                               }
+                       case T_Attr:
+                               {
+                                       Oid                     type_id;
+                                       int                     type_len;
+                                       Attr       *att = (Attr *) res->val;
+                                       Node       *result;
+                                       char       *attrname;
+                                       char       *resname;
+                                       Resdom     *resnode;
+                                       List       *attrs = att->attrs;
+
+                                       /*
+                                        * 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));
+                                       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.
+                                        * relation.attribute
+                                        */
+                                       result = handleNestedDots(pstate, att, &pstate->p_last_resno);
+                                       handleTargetColname(pstate, &res->name, att->relname, attrname);
+                                       if (att->indirection != NIL)
+                                       {
+                                               List       *ilist = att->indirection;
+
+                                               while (ilist != NIL)
+                                               {
+                                                       A_Indices  *ind = lfirst(ilist);
+
+                                                       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);
+                                       }
+                                       type_id = exprType(result);
+                                       type_len = typeLen(typeidType(type_id));
+                                       /* move to last entry */
+                                       while (lnext(attrs) != NIL)
+                                               attrs = lnext(attrs);
+                                       resname = (res->name) ? res->name : strVal(lfirst(attrs));
+                                       resnode = makeResdom((AttrNumber) pstate->p_last_resno++,
+                                                                                (Oid) type_id,
+                                                                                (Size) type_len,
+                                                                                resname,
+                                                                                (Index) 0,
+                                                                                (Oid) 0,
+                                                                                0);
+                                       tent->resdom = resnode;
+                                       tent->expr = result;
+                                       break;
+                               }
+                       default:
+                               /* internal error */
+                               elog(WARN,
+                                        "internal error: do not know how to transform targetlist");
+                               break;
+               }
+
+               if (p_target == NIL)
+               {
+                       p_target = tail_p_target = lcons(tent, NIL);
+               }
+               else
+               {
+                       lnext(tail_p_target) = lcons(tent, NIL);
+                       tail_p_target = lnext(tail_p_target);
+               }
+               targetlist = lnext(targetlist);
+       }
+
+       return p_target;
+}
+
+
+/*
+ * make_targetlist_expr -
+ *       make a TargetEntry from an expression
+ *
+ * arrayRef is a list of transformed A_Indices
+ */
+TargetEntry *
+make_targetlist_expr(ParseState *pstate,
+                                        char *colname,
+                                        Node *expr,
+                                        List *arrayRef)
+{
+       Oid                     type_id,
+                               attrtype;
+       int                     type_len,
+                               attrlen;
+       int                     resdomno;
+       Relation        rd;
+       bool            attrisset;
+       TargetEntry *tent;
+       Resdom     *resnode;
+
+       if (expr == NULL)
+               elog(WARN, "make_targetlist_expr: invalid use of NULL expression");
+
+       type_id = exprType(expr);
+       if (type_id == InvalidOid)
+       {
+               type_len = 0;
+       }
+       else
+               type_len = typeLen(typeidType(type_id));
+
+       /* I have no idea what the following does! */
+       /* It appears to process target columns that will be receiving results */
+       if (pstate->p_is_insert || pstate->p_is_update)
+       {
+
+               /*
+                * append or replace query -- append, replace work only on one
+                * relation, so multiple occurence of same resdomno is bogus
+                */
+               rd = pstate->p_target_relation;
+               Assert(rd != NULL);
+               resdomno = attnameAttNum(rd, colname);
+               attrisset = attnameIsSet(rd, colname);
+               attrtype = attnumTypeId(rd, resdomno);
+               if ((arrayRef != NIL) && (lfirst(arrayRef) == NIL))
+                       attrtype = GetArrayElementType(attrtype);
+               if (attrtype == BPCHAROID || attrtype == VARCHAROID)
+               {
+                       attrlen = rd->rd_att->attrs[resdomno - 1]->attlen;
+               }
+               else
+               {
+                       attrlen = typeLen(typeidType(attrtype));
+               }
+#if 0
+               if (Input_is_string && Typecast_ok)
+               {
+                       Datum           val;
+
+                       if (type_id == typeTypeId(type("unknown")))
+                       {
+                               val = (Datum) textout((struct varlena *)
+                                                                         ((Const) lnext(expr))->constvalue);
+                       }
+                       else
+                       {
+                               val = ((Const) lnext(expr))->constvalue;
+                       }
+                       if (attrisset)
+                       {
+                               lnext(expr) = makeConst(attrtype,
+                                                                               attrlen,
+                                                                               val,
+                                                                               false,
+                                                                               true,
+                                                                               true,   /* is set */
+                                                                               false);
+                       }
+                       else
+                       {
+                               lnext(expr) =
+                                       makeConst(attrtype,
+                                                         attrlen,
+                                                         (Datum) fmgr(typeidRetinfunc(attrtype),
+                                                                                val, typeidTypElem(attrtype), -1),
+                                                         false,
+                                                         true /* Maybe correct-- 80% chance */ ,
+                                                         false,        /* is not a set */
+                                                         false);
+                       }
+               }
+               else if ((Typecast_ok) && (attrtype != type_id))
+               {
+                       lnext(expr) =
+                               parser_typecast2(expr, typeidType(attrtype));
+               }
+               else if (attrtype != type_id)
+               {
+                       if ((attrtype == INT2OID) && (type_id == INT4OID))
+                               lfirst(expr) = lispInteger(INT2OID);    /* handle CASHOID too */
+                       else if ((attrtype == FLOAT4OID) && (type_id == FLOAT8OID))
+                               lfirst(expr) = lispInteger(FLOAT4OID);
+                       else
+                               elog(WARN, "unequal type in tlist : %s \n", colname);
+               }
+
+               Input_is_string = false;
+               Input_is_integer = false;
+               Typecast_ok = true;
+#endif
+
+               if (attrtype != type_id)
+               {
+                       if (IsA(expr, Const))
+                       {
+                               /* try to cast the constant */
+                               if (arrayRef && !(((A_Indices *) lfirst(arrayRef))->lidx))
+                               {
+                                       /* updating a single item */
+                                       Oid                     typelem = typeidTypElem(attrtype);
+
+                                       expr = (Node *) parser_typecast2(expr,
+                                                                                                        type_id,
+                                                                                                        typeidType(typelem),
+                                                                                                        attrlen);
+                               }
+                               else
+                                       expr = (Node *) parser_typecast2(expr,
+                                                                                                        type_id,
+                                                                                                  typeidType(attrtype),
+                                                                                                        attrlen);
+                       }
+                       else
+                       {
+                               /* currently, we can't handle casting of expressions */
+                               elog(WARN, "parser: attribute '%s' is of type '%s' but expression is of type '%s'",
+                                        colname,
+                                        typeidTypeName(attrtype),
+                                        typeidTypeName(type_id));
+                       }
+               }
+
+               if (arrayRef != NIL)
+               {
+                       Expr       *target_expr;
+                       Attr       *att = makeNode(Attr);
+                       List       *ar = arrayRef;
+                       List       *upperIndexpr = NIL;
+                       List       *lowerIndexpr = NIL;
+
+                       att->relname = pstrdup(RelationGetRelationName(rd)->data);
+                       att->attrs = lcons(makeString(colname), NIL);
+                       target_expr = (Expr *) handleNestedDots(pstate, att,
+                                                                                                 &pstate->p_last_resno);
+                       while (ar != NIL)
+                       {
+                               A_Indices  *ind = lfirst(ar);
+
+                               if (lowerIndexpr || (!upperIndexpr && ind->lidx))
+                               {
+
+                                       /*
+                                        * XXX assume all lowerIndexpr is non-null in this
+                                        * case
+                                        */
+                                       lowerIndexpr = lappend(lowerIndexpr, ind->lidx);
+                               }
+                               upperIndexpr = lappend(upperIndexpr, ind->uidx);
+                               ar = lnext(ar);
+                       }
+
+                       expr = (Node *) make_array_set(target_expr,
+                                                                                  upperIndexpr,
+                                                                                  lowerIndexpr,
+                                                                                  (Expr *) expr);
+                       attrtype = attnumTypeId(rd, resdomno);
+                       attrlen = typeLen(typeidType(attrtype));
+               }
+       }
+       else
+       {
+               resdomno = pstate->p_last_resno++;
+               attrtype = type_id;
+               attrlen = type_len;
+       }
+       tent = makeNode(TargetEntry);
+
+       resnode = makeResdom((AttrNumber) resdomno,
+                                                (Oid) attrtype,
+                                                (Size) attrlen,
+                                                colname,
+                                                (Index) 0,
+                                                (Oid) 0,
+                                                0);
+
+       tent->resdom = resnode;
+       tent->expr = expr;
+
+       return tent;
+}
+
+/*
+ * makeTargetNames -
+ *       generate a list of column names if not supplied or
+ *       test supplied column names to make sure they are in target table
+ *       (used exclusively for inserts)
+ */
+List *
+makeTargetNames(ParseState *pstate, List *cols)
+{
+       List       *tl = NULL;
+
+       /* Generate ResTarget if not supplied */
+
+       if (cols == NIL)
+       {
+               int                     numcol;
+               int                     i;
+               AttributeTupleForm *attr = pstate->p_target_relation->rd_att->attrs;
+
+               numcol = pstate->p_target_relation->rd_rel->relnatts;
+               for (i = 0; i < numcol; i++)
+               {
+                       Ident      *id = makeNode(Ident);
+
+                       id->name = palloc(NAMEDATALEN);
+                       StrNCpy(id->name, attr[i]->attname.data, NAMEDATALEN);
+                       id->indirection = NIL;
+                       id->isRel = false;
+                       if (tl == NIL)
+                               cols = tl = lcons(id, NIL);
+                       else
+                       {
+                               lnext(tl) = lcons(id, NIL);
+                               tl = lnext(tl);
+                       }
+               }
+       }
+       else
+       {
+               foreach(tl, cols)
+               {
+                       List       *nxt;
+                       char       *name = ((Ident *) lfirst(tl))->name;
+               
+                       /* elog on failure */
+                       attnameAttNum(pstate->p_target_relation, name);
+                       foreach(nxt, lnext(tl))
+                               if (!strcmp(name, ((Ident *) lfirst(nxt))->name))
+                                       elog (WARN, "Attribute '%s' should be specified only once", name);
+               }
+       }
+       
+       return cols;
+}
+
+/*
+ * expandAllTables -
+ *       turns '*' (in the target list) into a list of attributes
+ *        (of all relations in the range table)
+ */
+List *
+expandAllTables(ParseState *pstate)
+{
+       List       *target = NIL;
+       List       *legit_rtable = NIL;
+       List       *rt,
+                          *rtable;
+
+       rtable = pstate->p_rtable;
+       if (pstate->p_is_rule)
+       {
+
+               /*
+                * skip first two entries, "*new*" and "*current*"
+                */
+               rtable = lnext(lnext(pstate->p_rtable));
+       }
+
+       /* this should not happen */
+       if (rtable == NULL)
+               elog(WARN, "cannot expand: null p_rtable");
+
+       /*
+        * go through the range table and make a list of range table entries
+        * which we will expand.
+        */
+       foreach(rt, rtable)
+       {
+               RangeTblEntry *rte = lfirst(rt);
+
+               /*
+                * we only expand those specify in the from clause. (This will
+                * also prevent us from using the wrong table in inserts: eg.
+                * tenk2 in "insert into tenk2 select * from tenk1;")
+                */
+               if (!rte->inFromCl)
+                       continue;
+               legit_rtable = lappend(legit_rtable, rte);
+       }
+
+       foreach(rt, legit_rtable)
+       {
+               RangeTblEntry *rte = lfirst(rt);
+               List       *temp = target;
+
+               if (temp == NIL)
+                       target = expandAll(pstate, rte->relname, rte->refname,
+                                                          &pstate->p_last_resno);
+               else
+               {
+                       while (temp != NIL && lnext(temp) != NIL)
+                               temp = lnext(temp);
+                       lnext(temp) = expandAll(pstate, rte->relname, rte->refname,
+                                                                       &pstate->p_last_resno);
+               }
+       }
+       return target;
+}
+
+/*
+ * figureColname -
+ *       if the name of the resulting column is not specified in the target
+ *       list, we have to guess.
+ *
+ */
+char *
+figureColname(Node *expr, Node *resval)
+{
+       switch (nodeTag(expr))
+       {
+                       case T_Aggreg:
+                       return (char *)         /* XXX */
+                       ((Aggreg *) expr)->aggname;
+               case T_Expr:
+                       if (((Expr *) expr)->opType == FUNC_EXPR)
+                       {
+                               if (nodeTag(resval) == T_FuncCall)
+                                       return ((FuncCall *) resval)->funcname;
+                       }
+                       break;
+               default:
+                       break;
+       }
+
+       return "?column?";
+}
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
new file mode 100644 (file)
index 0000000..67632cd
--- /dev/null
@@ -0,0 +1,319 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_type.h
+ *             handle type operations for parser
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.1 1997/11/25 22:05:51 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <string.h>
+#include "postgres.h"
+#include "fmgr.h"
+
+#include <catalog/pg_type.h>
+#include <parser/parse_target.h>
+#include <parser/parse_type.h>
+#include "utils/syscache.h"
+
+#ifdef 0
+#include "lib/dllist.h"
+#include "utils/datum.h"
+
+#include "utils/builtins.h"
+#include "utils/elog.h"
+#include "utils/palloc.h"
+
+#include "nodes/pg_list.h"
+#include "nodes/parsenodes.h"
+#include "catalog/catname.h"
+
+#include "catalog/pg_inherits.h"
+#include "catalog/pg_operator.h"
+#include "catalog/pg_proc.h"
+#include "catalog/indexing.h"
+#include "catalog/catname.h"
+
+#include "access/skey.h"
+#include "access/relscan.h"
+#include "access/tupdesc.h"
+#include "access/htup.h"
+#include "access/heapam.h"
+#include "access/genam.h"
+#include "access/itup.h"
+#include "access/tupmacs.h"
+
+#include "storage/buf.h"
+#include "storage/bufmgr.h"
+#include "utils/lsyscache.h"
+#include "storage/lmgr.h"
+
+#include "port-protos.h"               /* strdup() */
+#endif
+
+/* check to see if a type id is valid,
+ * returns true if it is. By using this call before calling
+ * typeidType or typeidTypeName, more meaningful error messages
+ * can be produced because the caller typically has more context of
+ *     what's going on                 - jolly
+ */
+bool
+typeidIsValid(Oid id)
+{
+       return (SearchSysCacheTuple(TYPOID,
+                                                               ObjectIdGetDatum(id),
+                                                               0, 0, 0) != NULL);
+}
+
+/* return a type name, given a typeid */
+char      *
+typeidTypeName(Oid id)
+{
+       HeapTuple       tup;
+       TypeTupleForm typetuple;
+
+       if (!(tup = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(id),
+                                                                       0, 0, 0)))
+       {
+               elog(WARN, "type id lookup of %ud failed", id);
+               return (NULL);
+       }
+       typetuple = (TypeTupleForm) GETSTRUCT(tup);
+       return (typetuple->typname).data;
+}
+
+/* return a Type structure, given an typid */
+Type
+typeidType(Oid id)
+{
+       HeapTuple       tup;
+
+       if (!(tup = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(id),
+                                                                       0, 0, 0)))
+       {
+               elog(WARN, "type id lookup of %ud failed", id);
+               return (NULL);
+       }
+       return ((Type) tup);
+}
+
+/* return a Type structure, given type name */
+Type
+typenameType(char *s)
+{
+       HeapTuple       tup;
+
+       if (s == NULL)
+       {
+               elog(WARN, "type(): Null type");
+       }
+
+       if (!(tup = SearchSysCacheTuple(TYPNAME, PointerGetDatum(s), 0, 0, 0)))
+       {
+               elog(WARN, "type name lookup of %s failed", s);
+       }
+       return ((Type) tup);
+}
+
+/* given type, return the type OID */
+Oid
+typeTypeId(Type tp)
+{
+       if (tp == NULL)
+               elog(WARN, "typeTypeId() called with NULL type struct");
+       return (tp->t_oid);
+}
+
+/* given type (as type struct), return the length of type */
+int16
+typeLen(Type t)
+{
+       TypeTupleForm typ;
+
+       typ = (TypeTupleForm) GETSTRUCT(t);
+       return (typ->typlen);
+}
+
+/* given type (as type struct), return the value of its 'byval' attribute.*/
+bool
+typeByVal(Type t)
+{
+       TypeTupleForm typ;
+
+       typ = (TypeTupleForm) GETSTRUCT(t);
+       return (typ->typbyval);
+}
+
+/* given type (as type struct), return the name of type */
+char      *
+typeTypeName(Type t)
+{
+       TypeTupleForm typ;
+
+       typ = (TypeTupleForm) GETSTRUCT(t);
+       return (typ->typname).data;
+}
+
+/* given a type, return its typetype ('c' for 'c'atalog types) */
+char
+typeTypeFlag(Type t)
+{
+       TypeTupleForm typ;
+
+       typ = (TypeTupleForm) GETSTRUCT(t);
+       return (typ->typtype);
+}
+
+/* Given a type structure and a string, returns the internal form of
+   that string */
+char *
+stringTypeString(Type tp, char *string, int typlen)
+{
+       Oid                     op;
+       Oid                     typelem;
+
+       op = ((TypeTupleForm) GETSTRUCT(tp))->typinput;
+       typelem = ((TypeTupleForm) GETSTRUCT(tp))->typelem;     /* XXX - used for array_in */
+       /* typlen is for bpcharin() and varcharin() */
+       return ((char *) fmgr(op, string, typelem, typlen));
+}
+
+/* Given a type id, returns the out-conversion function of the type */
+Oid
+typeidRetoutfunc(Oid type_id)
+{
+       HeapTuple       typeTuple;
+       TypeTupleForm type;
+       Oid                     outfunc;
+
+       typeTuple = SearchSysCacheTuple(TYPOID,
+                                                                       ObjectIdGetDatum(type_id),
+                                                                       0, 0, 0);
+       if (!HeapTupleIsValid(typeTuple))
+               elog(WARN, "typeidRetoutfunc: Invalid type - oid = %u", type_id);
+
+       type = (TypeTupleForm) GETSTRUCT(typeTuple);
+       outfunc = type->typoutput;
+       return (outfunc);
+}
+
+Oid
+typeidTypeRelid(Oid type_id)
+{
+       HeapTuple       typeTuple;
+       TypeTupleForm type;
+       Oid                     infunc;
+
+       typeTuple = SearchSysCacheTuple(TYPOID,
+                                                                       ObjectIdGetDatum(type_id),
+                                                                       0, 0, 0);
+       if (!HeapTupleIsValid(typeTuple))
+               elog(WARN, "typeidTypeRelid: Invalid type - oid = %u", type_id);
+
+       type = (TypeTupleForm) GETSTRUCT(typeTuple);
+       infunc = type->typrelid;
+       return (infunc);
+}
+
+Oid
+typeTypeRelid(Type typ)
+{
+       TypeTupleForm typtup;
+
+       typtup = (TypeTupleForm) GETSTRUCT(typ);
+
+       return (typtup->typrelid);
+}
+
+Oid
+typeidTypElem(Oid type_id)
+{
+       HeapTuple       typeTuple;
+       TypeTupleForm type;
+
+       if (!(typeTuple = SearchSysCacheTuple(TYPOID,
+                                                                                 ObjectIdGetDatum(type_id),
+                                                                                 0, 0, 0)))
+       {
+               elog(WARN, "type id lookup of %u failed", type_id);
+       }
+       type = (TypeTupleForm) GETSTRUCT(typeTuple);
+
+       return (type->typelem);
+}
+
+/* Given the attribute type of an array return the arrtribute type of
+   an element of the array */
+
+Oid
+GetArrayElementType(Oid typearray)
+{
+       HeapTuple       type_tuple;
+       TypeTupleForm type_struct_array;
+
+       type_tuple = SearchSysCacheTuple(TYPOID,
+                                                                        ObjectIdGetDatum(typearray),
+                                                                        0, 0, 0);
+
+       if (!HeapTupleIsValid(type_tuple))
+               elog(WARN, "GetArrayElementType: Cache lookup failed for type %d",
+                        typearray);
+
+       /* get the array type struct from the type tuple */
+       type_struct_array = (TypeTupleForm) GETSTRUCT(type_tuple);
+
+       if (type_struct_array->typelem == InvalidOid)
+       {
+               elog(WARN, "GetArrayElementType: type %s is not an array",
+                        (Name) &(type_struct_array->typname.data[0]));
+       }
+
+       return (type_struct_array->typelem);
+}
+
+/* Given a type id, returns the in-conversion function of the type */
+Oid
+typeidRetinfunc(Oid type_id)
+{
+       HeapTuple       typeTuple;
+       TypeTupleForm type;
+       Oid                     infunc;
+
+       typeTuple = SearchSysCacheTuple(TYPOID,
+                                                                       ObjectIdGetDatum(type_id),
+                                                                       0, 0, 0);
+       if (!HeapTupleIsValid(typeTuple))
+               elog(WARN, "typeidRetinfunc: Invalid type - oid = %u", type_id);
+
+       type = (TypeTupleForm) GETSTRUCT(typeTuple);
+       infunc = type->typinput;
+       return (infunc);
+}
+
+
+#ifdef NOT_USED
+char
+FindDelimiter(char *typename)
+{
+       char            delim;
+       HeapTuple       typeTuple;
+       TypeTupleForm type;
+
+
+       if (!(typeTuple = SearchSysCacheTuple(TYPNAME,
+                                                                                 PointerGetDatum(typename),
+                                                                                 0, 0, 0)))
+       {
+               elog(WARN, "type name lookup of %s failed", typename);
+       }
+       type = (TypeTupleForm) GETSTRUCT(typeTuple);
+
+       delim = type->typdelim;
+       return (delim);
+}
+
+#endif
index d658c30..ea309c3 100644 (file)
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.28 1997/11/20 23:22:24 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.29 1997/11/25 22:05:52 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include <stdio.h>
 
 #include "postgres.h"
+#include "nodes/pg_list.h"
+#include "parser/parser.h"
+#include "parser/analyze.h"
+#include "parser/parse_node.h"
+
+void   init_io();              /* from scan.l */
+void   parser_init(Oid *typev, int nargs); /* from gram.y */
+int    yyparse();              /* from gram.c */
+
+#ifdef 0
+#include "parser/parse.h"
 #include "parser/gramparse.h"
-#include "parser/parse_query.h"
 #include "utils/palloc.h"
+#endif
 
 char      *parseString;                /* the char* which holds the string to be
                                                                 * parsed */
@@ -103,10 +114,10 @@ static void
 define_sets(Node *clause)
 {
        Oid                     setoid;
-       Type            t = type("oid");
-       Oid                     typeoid = typeid(t);
-       Size            oidsize = tlen(t);
-       bool            oidbyval = tbyval(t);
+       Type            t = typeidType(OIDOID);
+       Oid                     typeoid = typeTypeId(t);
+       Size            oidsize = typeLen(t);
+       bool            oidbyval = typeByVal(t);
 
        if (clause == NULL)
        {
@@ -125,11 +136,11 @@ define_sets(Node *clause)
                        return;
                }
                setoid = SetDefine(((Const *) clause)->constvalue,
-                                                  get_id_typname(((Const *) clause)->consttype));
+                                                  typeidTypeName(((Const *) clause)->consttype));
                set_constvalue((Const) clause, setoid);
                set_consttype((Const) clause, typeoid);
                set_constlen((Const) clause, oidsize);
-               set_constbyval((Const) clause, oidbyval);
+               set_constypeByVal((Const) clause, oidbyval);
        }
        else if (IsA(clause, Iter))
        {
@@ -173,6 +184,5 @@ define_sets(Node *clause)
                define_sets(get_rightop(clause));
        }
 }
-
 #endif
 
index dcc6614..e507579 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/scansup.c,v 1.7 1997/09/08 02:25:22 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/scansup.c,v 1.8 1997/11/25 22:05:55 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,7 +17,6 @@
 
 #include <ctype.h>
 #include <string.h>
-#include "c.h"
 #include "postgres.h"
 #include "miscadmin.h"
 #include "utils/elog.h"
index 37d1e1c..c6f4719 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.7 1997/10/25 05:37:07 thomas Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.8 1997/11/25 22:06:04 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -23,7 +23,8 @@
 #include "utils/lsyscache.h"   /* for get_typlen */
 #include "nodes/pg_list.h"             /* for Lisp support */
 #include "nodes/parsenodes.h"
-#include "parser/catalog_utils.h"
+#include "parser/parse_relation.h"
+
 #include "rewrite/locks.h"
 #include "rewrite/rewriteDefine.h"
 #include "rewrite/rewriteRemove.h"
@@ -107,7 +108,7 @@ InsertRule(char *rulname,
        if (evslot == NULL)
                evslot_index = -1;
        else
-               evslot_index = varattno(eventrel, (char *) evslot);
+               evslot_index = attnameAttNum(eventrel, (char *) evslot);
        heap_close(eventrel);
 
        if (evinstead)
@@ -221,8 +222,8 @@ DefineQueryRewrite(RuleStmt *stmt)
        }
        else
        {
-               event_attno = varattno(event_relation, eslot_string);
-               event_attype = att_typeid(event_relation, event_attno);
+               event_attno = attnameAttNum(event_relation, eslot_string);
+               event_attype = attnumTypeId(event_relation, event_attno);
        }
        heap_close(event_relation);
 
index 0b8a49f..0021213 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/tcop/Attic/aclchk.c,v 1.19 1997/11/24 05:08:47 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/tcop/Attic/aclchk.c,v 1.20 1997/11/25 22:06:08 momjian Exp $
  *
  * NOTES
  *       See acl.h.
 #include "catalog/pg_operator.h"
 #include "catalog/pg_aggregate.h"
 #include "catalog/pg_proc.h"
+#include "catalog/pg_type.h"
 #include "catalog/pg_user.h"
+#include "parser/parse_agg.h"
+#include "parser/parse_func.h"
 #include "utils/syscache.h"
 #include "utils/tqual.h"
-#include "parser/catalog_utils.h"
 #include "fmgr.h"
 
 static int32 aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode);
index 7659d90..d0d134e 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.54 1997/11/10 15:24:55 thomas Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.55 1997/11/25 22:06:14 momjian Exp $
  *
  * NOTES
  *       this is the "main" module of the postgres backend and
 
 #include "lib/dllist.h"
 
-#include "parser/catalog_utils.h"
-#include "parser/parse_query.h" /* for MakeTimeRange() */
 #include "commands/async.h"
 #include "tcop/tcopprot.h"             /* where declarations for this file go */
 #include "optimizer/planner.h"
+#include "parser/parser.h"
 
 #include "tcop/tcopprot.h"
 #include "tcop/tcopdebug.h"
@@ -1341,7 +1340,7 @@ PostgresMain(int argc, char *argv[])
        if (IsUnderPostmaster == false)
        {
                puts("\nPOSTGRES backend interactive interface");
-               puts("$Revision: 1.54 $ $Date: 1997/11/10 15:24:55 $");
+               puts("$Revision: 1.55 $ $Date: 1997/11/25 22:06:14 $");
        }
 
        /* ----------------
index 4a38e20..7a02f6a 100644 (file)
@@ -15,7 +15,6 @@
 #include "nodes/execnodes.h"
 #include "nodes/plannodes.h"
 #include "catalog/pg_proc.h"
-#include "parser/parse_query.h"
 #include "tcop/pquery.h"
 #include "tcop/tcopprot.h"
 #include "tcop/utility.h"
index de5ad32..696f5f7 100644 (file)
@@ -6,13 +6,16 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodeFuncs.h,v 1.5 1997/09/08 21:52:45 momjian Exp $
+ * $Id: nodeFuncs.h,v 1.6 1997/11/25 22:06:30 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef NODEFUNCS_H
 #define NODEFUNCS_H
 
+#include <nodes/nodes.h>
+#include <nodes/primnodes.h>
+
 extern bool single_node(Node *node);
 extern bool var_is_outer(Var *var);
 extern bool var_is_rel(Var *var);
index da90b76..59bd873 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: planner.h,v 1.5 1997/09/08 21:53:29 momjian Exp $
+ * $Id: planner.h,v 1.6 1997/11/25 22:06:37 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,8 @@
 /*
 */
 
+#include <parser/parse_node.h>
+
 extern Plan *planner(Query *parse);
 extern void pg_checkretval(Oid rettype, QueryTreeList *querytree_list);
 
diff --git a/src/include/parser/analyze.h b/src/include/parser/analyze.h
new file mode 100644 (file)
index 0000000..a85e207
--- /dev/null
@@ -0,0 +1,19 @@
+/*-------------------------------------------------------------------------
+ *
+ * analyze.h
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: analyze.h,v 1.1 1997/11/25 22:06:47 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ANALYZE_H
+#define ANALYZE_H
+
+#include <parser/parse_node.h>
+
+QueryTreeList *parse_analyze(List *pl);
+
+#endif                                                 /* ANALYZE_H */
diff --git a/src/include/parser/catalog_utils.h b/src/include/parser/catalog_utils.h
deleted file mode 100644 (file)
index 707ca3a..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * catalog_utils.h--
- *
- *
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- * $Id: catalog_utils.h,v 1.13 1997/09/08 21:53:35 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-#ifndef CATALOG_UTILS_H
-#define CATALOG_UTILS_H
-
-#include <catalog/pg_type.h>
-#include <access/htup.h>
-
-typedef HeapTuple Type;
-typedef HeapTuple Operator;
-
-extern Type get_id_type(Oid id);
-extern char *get_id_typname(Oid id);
-extern Type type(char *);
-extern Oid     att_typeid(Relation rd, int attid);
-extern int     att_attnelems(Relation rd, int attid);
-extern Oid     typeid(Type tp);
-extern int16 tlen(Type t);
-extern bool tbyval(Type t);
-extern char *tname(Type t);
-extern int     tbyvalue(Type t);
-extern Oid     oprid(Operator op);
-extern Operator oper(char *op, Oid arg1, Oid arg2, bool noWarnings);
-extern Operator right_oper(char *op, Oid arg);
-extern Operator left_oper(char *op, Oid arg);
-extern int     varattno(Relation rd, char *a);
-extern bool varisset(Relation rd, char *name);
-extern int     nf_varattno(Relation rd, char *a);
-extern char *getAttrName(Relation rd, int attrno);
-extern char *instr2(Type tp, char *string, int typlen);
-extern Oid     GetArrayElementType(Oid typearray);
-extern Oid     funcid_get_rettype(Oid funcid);
-extern bool
-func_get_detail(char *funcname, int nargs, Oid *oid_array,
-                       Oid *funcid, Oid *rettype, bool *retset, Oid **true_typeids);
-extern Oid     typeid_get_retinfunc(Oid type_id);
-extern Oid     typeid_get_retoutfunc(Oid type_id);
-extern Oid     typeid_get_relid(Oid type_id);
-extern Oid     get_typrelid(Type typ);
-extern Oid     get_typelem(Oid type_id);
-extern void func_error(char *caller, char *funcname, int nargs, Oid *argtypes);
-extern void agg_error(char *caller, char *aggname, Oid basetypeID);
-
-#endif                                                 /* CATALOG_UTILS_H */
diff --git a/src/include/parser/parse_agg.h b/src/include/parser/parse_agg.h
new file mode 100644 (file)
index 0000000..21ef362
--- /dev/null
@@ -0,0 +1,38 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_agg.h
+ *
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: parse_agg.h,v 1.1 1997/11/25 22:06:53 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_AGG_H
+#define PARSE_AGG_H
+
+#include <nodes/nodes.h>
+#include <nodes/parsenodes.h>
+#include <nodes/primnodes.h>
+#include <parser/parse_node.h>
+
+void AddAggToParseState(ParseState *pstate, Aggreg *aggreg);
+
+void finalizeAggregates(ParseState *pstate, Query *qry);
+
+bool contain_agg_clause(Node *clause);
+
+bool exprIsAggOrGroupCol(Node *expr, List *groupClause);
+
+bool tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause);
+
+void parseCheckAggregates(ParseState *pstate, Query *qry);
+
+Aggreg *ParseAgg(char *aggname, Oid basetype, Node *target);
+
+void agg_error(char *caller, char *aggname, Oid basetypeID);
+
+#endif                                                 /* PARSE_AGG_H */
+
diff --git a/src/include/parser/parse_clause.h b/src/include/parser/parse_clause.h
new file mode 100644 (file)
index 0000000..2c0a527
--- /dev/null
@@ -0,0 +1,39 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_clause.h
+ *
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: parse_clause.h,v 1.1 1997/11/25 22:06:54 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_CLAUSE_H
+#define PARSE_CLAUSE_H
+
+#include <nodes/pg_list.h>
+#include <nodes/nodes.h>
+#include <nodes/parsenodes.h>
+#include <nodes/primnodes.h>
+#include <parser/parse_node.h>
+
+void parseFromClause(ParseState *pstate, List *frmList);
+
+void makeRangeTable(ParseState *pstate, char *relname, List *frmList);
+
+Node *transformWhereClause(ParseState *pstate, Node *a_expr);
+
+TargetEntry *find_targetlist_entry(ParseState *pstate,
+                       SortGroupBy *sortgroupby, List *tlist);
+
+List *transformGroupClause(ParseState *pstate, List *grouplist,
+                       List *targetlist);
+
+List *transformSortClause(ParseState *pstate,
+                                       List *orderlist, List *targetlist,
+                                       char *uniqueFlag);
+
+#endif                                                 /* PARSE_CLAUSE_H */
+
diff --git a/src/include/parser/parse_expr.h b/src/include/parser/parse_expr.h
new file mode 100644 (file)
index 0000000..e7c4a04
--- /dev/null
@@ -0,0 +1,34 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_exer.h
+ *
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: parse_expr.h,v 1.1 1997/11/25 22:06:55 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_EXPR_H
+#define PARSE_EXPR_H
+
+#include <nodes/nodes.h>
+#include <nodes/parsenodes.h>
+#include <nodes/primnodes.h>
+#include <parser/parse_node.h>
+
+Node *transformExpr(ParseState *pstate, Node *expr, int precedence);
+
+Node *transformIdent(ParseState *pstate, Node *expr, int precedence);
+
+Oid exprType(Node *expr);
+
+Node *handleNestedDots(ParseState *pstate, Attr *attr, int *curr_resno);
+
+Node *parser_typecast(Value *expr, TypeName *typename, int typlen);
+
+Node *parser_typecast2(Node *expr, Oid exprType, Type tp, int typlen);
+
+#endif                                                 /* PARSE_EXPR_H */
+
diff --git a/src/include/parser/parse_func.h b/src/include/parser/parse_func.h
new file mode 100644 (file)
index 0000000..de8fc66
--- /dev/null
@@ -0,0 +1,97 @@
+/*-------------------------------------------------------------------------
+ *
+ * catalog_utils.h--
+ *
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: parse_func.h,v 1.1 1997/11/25 22:06:56 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSER_FUNC_H
+#define PARSER_FUNC_H
+
+#include <nodes/nodes.h>
+#include <nodes/pg_list.h>
+#include <nodes/parsenodes.h>
+#include <nodes/primnodes.h>
+#include <parser/parse_func.h>
+#include <parser/parse_node.h>
+
+/*
+ *     This structure is used to explore the inheritance hierarchy above
+ *     nodes in the type tree in order to disambiguate among polymorphic
+ *     functions.
+ */
+typedef struct _InhPaths
+{
+       int                     nsupers;                /* number of superclasses */
+       Oid                     self;                   /* this class */
+       Oid                *supervec;           /* vector of superclasses */
+} InhPaths;
+
+/*
+ *     This structure holds a list of possible functions or operators that
+ *     agree with the known name and argument types of the function/operator.
+ */
+typedef struct _CandidateList
+{
+       Oid                *args;
+       struct _CandidateList *next;
+}                 *CandidateList;
+
+Node *ParseFunc(ParseState *pstate, char *funcname, List *fargs,
+       int *curr_resno);
+
+Oid funcid_get_rettype(Oid funcid);
+
+CandidateList func_get_candidates(char *funcname, int nargs);
+
+bool can_coerce(int nargs, Oid *input_typeids, Oid *func_typeids);
+
+int match_argtypes(int nargs,
+                                  Oid *input_typeids,
+                                  CandidateList function_typeids,
+                                  CandidateList *candidates);
+
+Oid * func_select_candidate(int nargs,
+                                                 Oid *input_typeids,
+                                                 CandidateList candidates);
+
+bool func_get_detail(char *funcname,
+                                       int nargs,
+                                       Oid *oid_array,
+                                       Oid *funcid,    /* return value */
+                                       Oid *rettype,   /* return value */
+                                       bool *retset,   /* return value */
+                                       Oid **true_typeids);
+
+Oid ** argtype_inherit(int nargs, Oid *oid_array);
+
+int findsupers(Oid relid, Oid **supervec);
+
+Oid **genxprod(InhPaths *arginh, int nargs);
+
+void make_arguments(int nargs,
+                                  List *fargs,
+                                  Oid *input_typeids,
+                                  Oid *function_typeids);
+
+List *setup_tlist(char *attname, Oid relid);
+
+List *setup_base_tlist(Oid typeid);
+
+Node *ParseComplexProjection(ParseState *pstate,
+                                                  char *funcname,
+                                                  Node *first_arg,
+                                                  bool *attisset);
+       
+void func_error(char *caller, char *funcname, int nargs, Oid *argtypes);
+
+                                  
+
+
+#endif                                                 /* PARSE_FUNC_H */
+
diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h
new file mode 100644 (file)
index 0000000..bac05cb
--- /dev/null
@@ -0,0 +1,67 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_node.h
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: parse_node.h,v 1.1 1997/11/25 22:06:57 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_NODE_H
+#define PARSE_NODE_H
+
+#include <nodes/nodes.h>
+#include <nodes/pg_list.h>
+#include <nodes/primnodes.h>
+#include <nodes/parsenodes.h>
+#include <parser/parse_type.h>
+#include <utils/rel.h>
+
+typedef struct QueryTreeList
+{
+       int                     len;                    /* number of queries */
+       Query     **qtrees;
+} QueryTreeList;
+
+/* state information used during parse analysis */
+typedef struct ParseState
+{
+       int                     p_last_resno;
+       List       *p_rtable;
+       int                     p_numAgg;
+       List       *p_aggs;
+       bool            p_is_insert;
+       List       *p_insert_columns;
+       bool            p_is_update;
+       bool            p_is_rule;
+       bool            p_in_where_clause;
+       Relation        p_target_relation;
+       RangeTblEntry *p_target_rangetblentry;
+} ParseState;
+
+ParseState *make_parsestate(void);
+
+Node *make_operand(char *opname,
+                        Node *tree,
+                        Oid orig_typeId,
+                        Oid true_typeId);
+
+void disallow_setop(char *op, Type optype, Node *operand);
+
+Expr *make_op(char *opname, Node *ltree, Node *rtree);
+
+Var *make_var(ParseState *pstate, char *refname, char *attrname, Oid *type_id);
+
+ArrayRef   *make_array_ref(Node *expr,
+                          List *indirection);
+
+ArrayRef   *make_array_set(Expr *target_expr,
+                                                  List *upperIndexpr,
+                                                  List *lowerIndexpr,
+                                                  Expr *expr);
+
+Const *make_const(Value *value);
+                          
+#endif                                                 /* PARSE_NODE_H */
diff --git a/src/include/parser/parse_oper.h b/src/include/parser/parse_oper.h
new file mode 100644 (file)
index 0000000..c013af6
--- /dev/null
@@ -0,0 +1,50 @@
+/*-------------------------------------------------------------------------
+ *
+ * catalog_utils.h--
+ *
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: parse_oper.h,v 1.1 1997/11/25 22:06:59 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_OPER_H
+#define PARSE_OPER_H
+
+#include <parser/parse_func.h>
+#include <parser/parse_node.h>
+
+typedef HeapTuple Operator;
+
+Oid any_ordering_op(int restype);
+
+Oid oprid(Operator op);
+
+int binary_oper_get_candidates(char *opname,
+                                                  Oid leftTypeId,
+                                                  Oid rightTypeId,
+                                                  CandidateList *candidates);
+
+bool equivalentOpersAfterPromotion(CandidateList candidates);
+
+CandidateList binary_oper_select_candidate(Oid arg1,
+                                                        Oid arg2,
+                                                        CandidateList candidates);
+
+Operator oper(char *op, Oid arg1, Oid arg2, bool noWarnings);
+
+int
+unary_oper_get_candidates(char *op,
+                                                 Oid typeId,
+                                                 CandidateList *candidates,
+                                                 char rightleft);
+
+Operator right_oper(char *op, Oid arg);
+                                                 
+Operator left_oper(char *op, Oid arg);
+
+void op_error(char *op, Oid arg1, Oid arg2);
+
+#endif                                                 /* PARSE_OPER_H */
diff --git a/src/include/parser/parse_query.h b/src/include/parser/parse_query.h
deleted file mode 100644 (file)
index 0a7d534..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
- /*-------------------------------------------------------------------------
- *
- * parse_query.h--
- *       prototypes for parse_query.c.
- *
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- * $Id: parse_query.h,v 1.14 1997/11/20 23:23:53 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-#ifndef PARSE_QUERY_H
-#define PARSE_QUERY_H
-
-#include <parser/catalog_utils.h>
-#include <parser/parse_state.h>
-#include <nodes/parsenodes.h>
-
-typedef struct QueryTreeList
-{
-       int                     len;                    /* number of queries */
-       Query     **qtrees;
-} QueryTreeList;
-
-extern RangeTblEntry *refnameRangeTableEntry(List *rtable, char *refname);
-extern RangeTblEntry *colnameRangeTableEntry(ParseState *pstate, char *colname);
-extern int     refnameRangeTablePosn(List *rtable, char *refname);
-extern RangeTblEntry *
-addRangeTableEntry(ParseState *pstate,
-                                  char *relname, char *refname,
-                                  bool inh, bool inFromCl);
-extern List *
-expandAll(ParseState *pstate, char *relname, char *refname,
-                 int *this_resno);
-extern Expr *make_op(char *opname, Node *ltree, Node *rtree);
-
-extern Oid     find_atttype(Oid relid, char *attrname);
-extern Var *
-make_var(ParseState *pstate,
-                char *relname, char *attrname, Oid *type_id);
-extern ArrayRef *make_array_ref(Node *array, List *indirection);
-extern ArrayRef *
-make_array_set(Expr *target_expr, List *upperIndexpr,
-                          List *lowerIndexpr, Expr *expr);
-extern Const *make_const(Value *value);
-
-extern void param_type_init(Oid *typev, int nargs);
-extern Oid     param_type(int t);
-
-extern QueryTreeList *parser(char *str, Oid *typev, int nargs);
-
-extern void handleTargetColname(ParseState *pstate, char **resname,
-                                       char *refname, char *colname);
-
-/*
- * analyze.c
- */
-
-Oid                    exprType(Node *expr);
-QueryTreeList *parse_analyze(List *querytree_list);
-
-/* define in parse_query.c, used in gram.y */
-extern Oid *param_type_info;
-extern int     pfunc_num_args;
-
-/* useful macros */
-#define ISCOMPLEX(type) (typeid_get_relid(type) ? true : false)
-
-#endif                                                 /* PARSE_QUERY_H */
diff --git a/src/include/parser/parse_relation.h b/src/include/parser/parse_relation.h
new file mode 100644 (file)
index 0000000..ed47082
--- /dev/null
@@ -0,0 +1,56 @@
+ /*-------------------------------------------------------------------------
+ *
+ * parse_query.h--
+ *       prototypes for parse_query.c.
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: parse_relation.h,v 1.1 1997/11/25 22:07:02 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_QUERY_H
+#define PARSE_RANGE_H
+
+#include <nodes/nodes.h>
+#include <nodes/parsenodes.h>
+#include <nodes/pg_list.h>
+#include <nodes/primnodes.h>
+#include <parser/parse_node.h>
+#include <utils/rel.h>
+
+RangeTblEntry *refnameRangeTableEntry(List *rtable, char *refname);
+
+int refnameRangeTablePosn(List *rtable, char *refname);
+
+RangeTblEntry *colnameRangeTableEntry(ParseState *pstate, char *colname);
+
+RangeTblEntry *addRangeTableEntry(ParseState *pstate,
+                                                                  char *relname,
+                                                                  char *refname,
+                                                                  bool inh,
+                                                                  bool inFromCl);
+
+List *expandAll(ParseState *pstate, char *relname, char *refname,
+                                               int *this_resno);
+
+int attnameAttNum(Relation rd, char *a);
+
+bool attnameIsSet(Relation rd, char *name);
+
+char *attnumAttName(Relation rd, int attrno);
+
+int attnumAttNelems(Relation rd, int attid);
+
+Oid attnameTypeId(Oid relid, char *attrname);
+
+Oid attnumTypeId(Relation rd, int attid);
+
+void handleTargetColname(ParseState *pstate, char **resname,
+                                       char *refname, char *colname);
+
+void checkTargetTypes(ParseState *pstate, char *target_colname,
+                                char *refname, char *colname);
+
+#endif                                                 /* PARSE_RANGE_H */
diff --git a/src/include/parser/parse_state.h b/src/include/parser/parse_state.h
deleted file mode 100644 (file)
index abda19b..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * parse_state.h--
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- * $Id: parse_state.h,v 1.8 1997/09/08 21:53:40 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef PARSE_STATE_H
-#define PARSE_STATE_H
-
-#include <nodes/parsenodes.h>
-#include <utils/rel.h>
-
-/* state information used during parse analysis */
-typedef struct ParseState
-{
-       int                     p_last_resno;
-       List       *p_rtable;
-       int                     p_numAgg;
-       List       *p_aggs;
-       bool            p_is_insert;
-       List       *p_insert_columns;
-       bool            p_is_update;
-       bool            p_is_rule;
-       Relation        p_target_relation;
-       RangeTblEntry *p_target_rangetblentry;
-} ParseState;
-
-
-#endif                                                 /* PARSE_QUERY_H */
diff --git a/src/include/parser/parse_target.h b/src/include/parser/parse_target.h
new file mode 100644 (file)
index 0000000..c7faa6b
--- /dev/null
@@ -0,0 +1,39 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_target.h
+ *
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: parse_target.h,v 1.1 1997/11/25 22:07:06 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_TARGET_H
+#define PARSE_TARGET_H
+
+#include <nodes/pg_list.h>
+#include <nodes/nodes.h>
+#include <nodes/parsenodes.h>
+#include <nodes/primnodes.h>
+#include <parser/parse_node.h>
+
+#define EXPR_COLUMN_FIRST      1
+#define EXPR_RELATION_FIRST    2
+
+List *transformTargetList(ParseState *pstate, List *targetlist);
+
+TargetEntry *make_targetlist_expr(ParseState *pstate,
+                                        char *colname,
+                                        Node *expr,
+                                        List *arrayRef);
+
+List *expandAllTables(ParseState *pstate);
+
+char *figureColname(Node *expr, Node *resval);
+
+List *makeTargetNames(ParseState *pstate, List *cols);
+
+#endif                                                 /* PARSE_TARGET_H */
+
diff --git a/src/include/parser/parse_type.h b/src/include/parser/parse_type.h
new file mode 100644 (file)
index 0000000..63c38ab
--- /dev/null
@@ -0,0 +1,37 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_type.h
+ *
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: parse_type.h,v 1.1 1997/11/25 22:07:07 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_TYPE_H
+#define PARSE_TYPE_H
+
+#include "access/htup.h"
+
+typedef HeapTuple Type;
+
+bool typeidIsValid(Oid id);
+Type typeidType(Oid id);
+Type typenameType(char *s);
+char *typeidTypeName(Oid id);
+Oid typeTypeId(Type tp);
+int16 typeLen(Type t);
+bool typeByVal(Type t);
+char *typeTypeName(Type t);
+char typeTypeFlag(Type t);
+char *stringTypeString(Type tp, char *string, int typlen);
+Oid typeidRetoutfunc(Oid type_id);
+Oid typeidTypeRelid(Oid type_id);
+Oid typeTypeRelid(Type typ);
+Oid typeidTypElem(Oid type_id);
+Oid GetArrayElementType(Oid typearray);
+Oid typeidRetinfunc(Oid type_id);
+
+#endif                                                 /* PARSE_TYPE_H */
diff --git a/src/include/parser/parser.h b/src/include/parser/parser.h
new file mode 100644 (file)
index 0000000..4362ebb
--- /dev/null
@@ -0,0 +1,21 @@
+/*-------------------------------------------------------------------------
+ *
+ * parser.h
+ *
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: parser.h,v 1.1 1997/11/25 22:07:08 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSER_H
+#define PARSER_H
+
+#include <parser/parse_node.h>
+
+QueryTreeList *parser(char *str, Oid *typev, int nargs);
+
+#endif                                                 /* PARSER_H */
+
index 6142f24..eeb21b9 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: tcopprot.h,v 1.7 1997/09/08 21:54:42 momjian Exp $
+ * $Id: tcopprot.h,v 1.8 1997/11/25 22:07:10 momjian Exp $
  *
  * OLD COMMENTS
  *       This file was created so that other c files could get the two
@@ -19,7 +19,7 @@
 #define TCOPPROT_H
 
 #include <executor/execdesc.h>
-#include <parser/parse_query.h>
+#include <parser/parse_node.h>
 
 #ifndef BOOTSTRAP_INCLUDE
 extern List *
index 1536dc2..39783cf 100755 (executable)
@@ -1,6 +1,8 @@
 #!/bin/sh
 # check regression tests
-# usage:  checkresults < results.out
+# usage:  checkresults [ regress.out ]
+
+[ "$#" -eq 0 ] && set regress.out
 
 for file in `cat "$@" | grep 'failed$' | cut -d " " -f 1`
 do