Infrastructure for deducing Param types from context, in the same way
authorTom Lane
Tue, 29 Apr 2003 22:13:11 +0000 (22:13 +0000)
committerTom Lane
Tue, 29 Apr 2003 22:13:11 +0000 (22:13 +0000)
that the types of untyped string-literal constants are deduced (ie,
when coerce_type is applied to 'em, that's what the type must be).
Remove the ancient hack of storing the input Param-types array as a
global variable, and put the info into ParseState instead.  This touches
a lot of files because of adjustment of routine parameter lists, but
it's really not a large patch.  Note: PREPARE statement still insists on
exact specification of parameter types, but that could easily be relaxed
now, if we wanted to do so.

29 files changed:
src/backend/catalog/heap.c
src/backend/commands/schemacmds.c
src/backend/commands/tablecmds.c
src/backend/commands/typecmds.c
src/backend/executor/spi.c
src/backend/optimizer/plan/subselect.c
src/backend/optimizer/prep/prepunion.c
src/backend/optimizer/util/clauses.c
src/backend/parser/analyze.c
src/backend/parser/parse_clause.c
src/backend/parser/parse_coerce.c
src/backend/parser/parse_expr.c
src/backend/parser/parse_func.c
src/backend/parser/parse_node.c
src/backend/parser/parse_oper.c
src/backend/parser/parse_relation.c
src/backend/parser/parse_target.c
src/backend/parser/parse_type.c
src/backend/parser/parser.c
src/backend/rewrite/rewriteHandler.c
src/backend/tcop/postgres.c
src/include/parser/analyze.h
src/include/parser/gramparse.h
src/include/parser/parse_coerce.h
src/include/parser/parse_func.h
src/include/parser/parse_node.h
src/include/parser/parse_oper.h
src/include/parser/parser.h
src/include/tcop/tcopprot.h

index 802f5932f7375b6ea907af719ea7372f50c7783d..5a6ec98e1b8a02207f9688893529a06d70b5c0f0 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.241 2003/03/23 05:14:36 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.242 2003/04/29 22:13:08 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -1592,7 +1592,7 @@ AddRelationRawConstraints(Relation rel,
        /*
         * Make sure it yields a boolean result.
         */
-       expr = coerce_to_boolean(expr, "CHECK");
+       expr = coerce_to_boolean(pstate, expr, "CHECK");
 
        /*
         * Make sure no outside relations are referred to.
@@ -1743,7 +1743,7 @@ cookDefault(ParseState *pstate,
    {
        Oid         type_id = exprType(expr);
 
-       if (coerce_to_target_type(expr, type_id,
+       if (coerce_to_target_type(pstate, expr, type_id,
                                  atttypid, atttypmod,
                                  COERCION_ASSIGNMENT,
                                  COERCE_IMPLICIT_CAST) == NULL)
index ba37c24987315b541e3d09402a5f6289f23ef800..4e2224e189bb6d9de2f0ef3c00f0cb6651ed7b17 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/schemacmds.c,v 1.7 2002/12/05 04:04:42 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/schemacmds.c,v 1.8 2003/04/29 22:13:08 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -124,7 +124,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt)
        List       *querytree_list,
                   *querytree_item;
 
-       querytree_list = parse_analyze(parsetree, NULL);
+       querytree_list = parse_analyze(parsetree, NULL, 0);
 
        foreach(querytree_item, querytree_list)
        {
index b4576893c660626757bdaf5528152761dc97da69..5f60ab9cf016d9daefa63b412d6eab0773eb3d88 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.71 2003/04/21 15:19:55 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.72 2003/04/29 22:13:08 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2852,7 +2852,7 @@ AlterTableAddCheckConstraint(Relation rel, Constraint *constr)
    /*
     * Make sure it yields a boolean result.
     */
-   expr = coerce_to_boolean(expr, "CHECK");
+   expr = coerce_to_boolean(pstate, expr, "CHECK");
 
    /*
     * Make sure no outside relations are referred to.
index 3cc11ed81a5970e91343e043ec9664cfe8f4d311..0523878f2a717578f31a955b614d37a5e08544e6 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.33 2003/04/08 16:57:45 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.34 2003/04/29 22:13:08 tgl Exp $
  *
  * DESCRIPTION
  *   The "DefineFoo" routines take the parse tree and pick out the
@@ -1601,7 +1601,7 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid,
    /*
     * Make sure it yields a boolean result.
     */
-   expr = coerce_to_boolean(expr, "CHECK");
+   expr = coerce_to_boolean(pstate, expr, "CHECK");
 
    /*
     * Make sure no outside relations are
index 218b56a601315088f8d339fa44118c5fedca6f15..aca27d0aebf3597900e057dbe046e6be9c53777c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.92 2003/04/29 03:21:29 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.93 2003/04/29 22:13:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -993,7 +993,7 @@ _SPI_execute(const char *src, int tcount, _SPI_plan *plan)
    /*
     * Parse the request string into a list of raw parse trees.
     */
-   raw_parsetree_list = pg_parse_query(src, argtypes, nargs);
+   raw_parsetree_list = pg_parse_query(src);
 
    /*
     * Do parse analysis and rule rewrite for each raw parsetree.
@@ -1036,7 +1036,7 @@ _SPI_execute(const char *src, int tcount, _SPI_plan *plan)
        if (plan)
            plan->origCmdType = origCmdType;
 
-       query_list = pg_analyze_and_rewrite(parsetree);
+       query_list = pg_analyze_and_rewrite(parsetree, argtypes, nargs);
 
        query_list_list = lappend(query_list_list, query_list);
 
index 15d16d002211746f4867a4338693514533ece315..4be69d77cfdf95d7e663cd17e59fdef2e5fa5fec 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.74 2003/04/08 23:20:01 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.75 2003/04/29 22:13:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -495,10 +495,13 @@ convert_sublink_opers(List *lefthand, List *operOids,
         * Make the expression node.
         *
         * Note: we use make_op_expr in case runtime type conversion
-        * function calls must be inserted for this operator!
+        * function calls must be inserted for this operator!  (But we
+        * are not expecting to have to resolve unknown Params, so
+        * it's okay to pass a null pstate.)
         */
        result = lappend(result,
-                        make_op_expr(tup,
+                        make_op_expr(NULL,
+                                     tup,
                                      leftop,
                                      rightop,
                                      exprType(leftop),
index fb7bf9e70700ad084a93eb474bb524271d290095..d2b91c2ec6d23510c92c9e6c6fca594ad830e57b 100644 (file)
@@ -14,7 +14,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.93 2003/04/24 23:43:09 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.94 2003/04/29 22:13:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -418,7 +418,8 @@ generate_setop_tlist(List *colTypes, int flag,
        }
        else
        {
-           expr = coerce_to_common_type(expr,
+           expr = coerce_to_common_type(NULL, /* no UNKNOWNs here */
+                                        expr,
                                         colType,
                                         "UNION/INTERSECT/EXCEPT");
            colTypmod = -1;
index 778fc3a2bb9054c679bdb3eefdd96f83ba01ec20..c0ffd939cbe520f9a50e0f9b7c93c5b857df3a7b 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.135 2003/04/27 20:09:44 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.136 2003/04/29 22:13:09 tgl Exp $
  *
  * HISTORY
  *   AUTHOR            DATE            MAJOR EVENT
@@ -1747,17 +1747,17 @@ inline_function(Oid funcid, Oid result_type, List *args,
 
    /*
     * We just do parsing and parse analysis, not rewriting, because
-    * rewriting will not affect SELECT-only queries, which is all that
-    * we care about.  Also, we can punt as soon as we detect more than
+    * rewriting will not affect table-free-SELECT-only queries, which is all
+    * that we care about.  Also, we can punt as soon as we detect more than
     * one command in the function body.
     */
-   raw_parsetree_list = pg_parse_query(src,
-                                       funcform->proargtypes,
-                                       funcform->pronargs);
+   raw_parsetree_list = pg_parse_query(src);
    if (length(raw_parsetree_list) != 1)
        goto fail;
 
-   querytree_list = parse_analyze(lfirst(raw_parsetree_list), NULL);
+   querytree_list = parse_analyze(lfirst(raw_parsetree_list),
+                                  funcform->proargtypes,
+                                  funcform->pronargs);
 
    if (length(querytree_list) != 1)
        goto fail;
index 5dc3d82bea8f695dfb01818356f02d0355854024..c2159a70e0e78f1e550030cc239f2f7c215e1cde 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.267 2003/04/29 03:21:29 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.268 2003/04/29 22:13:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -84,6 +84,7 @@ typedef struct
 } CreateStmtContext;
 
 
+static List *do_parse_analyze(Node *parseTree, ParseState *pstate);
 static Query *transformStmt(ParseState *pstate, Node *stmt,
              List **extras_before, List **extras_after);
 static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
@@ -125,10 +126,12 @@ static void release_pstate_resources(ParseState *pstate);
 static FromExpr *makeFromExpr(List *fromlist, Node *quals);
 
 
-
 /*
- * parse_analyze -
- *   analyze a raw parse tree and transform it to Query form.
+ * parse_analyze
+ *     Analyze a raw parse tree and transform it to Query form.
+ *
+ * Optionally, information about $n parameter types can be supplied.
+ * References to $n indexes not defined by paramTypes[] are disallowed.
  *
  * The result is a List of Query nodes (we need a list since some commands
  * produce multiple Queries).  Optimizable statements require considerable
@@ -136,11 +139,74 @@ static FromExpr *makeFromExpr(List *fromlist, Node *quals);
  * a dummy CMD_UTILITY Query node.
  */
 List *
-parse_analyze(Node *parseTree, ParseState *parentParseState)
+parse_analyze(Node *parseTree, Oid *paramTypes, int numParams)
+{
+   ParseState *pstate = make_parsestate(NULL);
+   List       *result;
+
+   pstate->p_paramtypes = paramTypes;
+   pstate->p_numparams = numParams;
+   pstate->p_variableparams = false;
+
+   result = do_parse_analyze(parseTree, pstate);
+
+   pfree(pstate);
+
+   return result;
+}
+
+/*
+ * parse_analyze_varparams
+ *
+ * This variant is used when it's okay to deduce information about $n
+ * symbol datatypes from context.  The passed-in paramTypes[] array can
+ * be modified or enlarged (via repalloc).
+ */
+List *
+parse_analyze_varparams(Node *parseTree, Oid **paramTypes, int *numParams)
+{
+   ParseState *pstate = make_parsestate(NULL);
+   List       *result;
+
+   pstate->p_paramtypes = *paramTypes;
+   pstate->p_numparams = *numParams;
+   pstate->p_variableparams = true;
+
+   result = do_parse_analyze(parseTree, pstate);
+
+   *paramTypes = pstate->p_paramtypes;
+   *numParams = pstate->p_numparams;
+
+   pfree(pstate);
+
+   return result;
+}
+
+/*
+ * parse_sub_analyze
+ *     Entry point for recursively analyzing a sub-statement.
+ */
+List *
+parse_sub_analyze(Node *parseTree, ParseState *parentParseState)
 {
-   List       *result = NIL;
    ParseState *pstate = make_parsestate(parentParseState);
+   List       *result;
+
+   result = do_parse_analyze(parseTree, pstate);
+
+   pfree(pstate);
 
+   return result;
+}
+
+/*
+ * do_parse_analyze
+ *     Workhorse code shared by the above variants of parse_analyze.
+ */
+static List *
+do_parse_analyze(Node *parseTree, ParseState *pstate)
+{
+   List       *result = NIL;
    /* Lists to return extra commands from transformation */
    List       *extras_before = NIL;
    List       *extras_after = NIL;
@@ -148,11 +214,14 @@ parse_analyze(Node *parseTree, ParseState *parentParseState)
    List       *listscan;
 
    query = transformStmt(pstate, parseTree, &extras_before, &extras_after);
+
+   /* don't need to access result relation any more */
    release_pstate_resources(pstate);
 
    while (extras_before != NIL)
    {
-       result = nconc(result, parse_analyze(lfirst(extras_before), pstate));
+       result = nconc(result,
+                      parse_sub_analyze(lfirst(extras_before), pstate));
        extras_before = lnext(extras_before);
    }
 
@@ -160,13 +229,14 @@ parse_analyze(Node *parseTree, ParseState *parentParseState)
 
    while (extras_after != NIL)
    {
-       result = nconc(result, parse_analyze(lfirst(extras_after), pstate));
+       result = nconc(result,
+                      parse_sub_analyze(lfirst(extras_after), pstate));
        extras_after = lnext(extras_after);
    }
 
    /*
     * Make sure that only the original query is marked original. We have
-    * to do this explicitly since recursive calls of parse_analyze will
+    * to do this explicitly since recursive calls of do_parse_analyze will
     * have marked some of the added-on queries as "original".
     */
    foreach(listscan, result)
@@ -176,8 +246,6 @@ parse_analyze(Node *parseTree, ParseState *parentParseState)
        q->querySource = (q == query ? QSRC_ORIGINAL : QSRC_PARSER);
    }
 
-   pfree(pstate);
-
    return result;
 }
 
@@ -423,7 +491,14 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
     */
    if (stmt->selectStmt)
    {
-       ParseState *sub_pstate = make_parsestate(pstate->parentParseState);
+       /*
+        * We make the sub-pstate a child of the outer pstate so that it
+        * can see any Param definitions supplied from above.  Since the
+        * outer pstate's rtable and namespace are presently empty, there
+        * are no side-effects of exposing names the sub-SELECT shouldn't
+        * be able to see.
+        */
+       ParseState *sub_pstate = make_parsestate(pstate);
        Query      *selectQuery;
        RangeTblEntry *rte;
        RangeTblRef *rtr;
@@ -475,12 +550,12 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
         * separate from the subquery's tlist because we may add columns,
         * insert datatype coercions, etc.)
         *
-        * HACK: constants in the INSERT's targetlist are copied up as-is
-        * rather than being referenced as subquery outputs.  This is
-        * mainly to ensure that when we try to coerce them to the target
-        * column's datatype, the right things happen for UNKNOWN
-        * constants. Otherwise this fails: INSERT INTO foo SELECT 'bar',
-        * ... FROM baz
+        * HACK: unknown-type constants and params in the INSERT's targetlist
+        * are copied up as-is rather than being referenced as subquery
+        * outputs.  This is to ensure that when we try to coerce them
+        * to the target column's datatype, the right things happen (see
+        * special cases in coerce_type).  Otherwise, this fails:
+        *      INSERT INTO foo SELECT 'bar', ... FROM baz
         */
        qry->targetList = NIL;
        foreach(tl, selectQuery->targetList)
@@ -491,7 +566,9 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
 
            if (resnode->resjunk)
                continue;
-           if (tle->expr && IsA(tle->expr, Const))
+           if (tle->expr &&
+               (IsA(tle->expr, Const) || IsA(tle->expr, Param)) &&
+               exprType((Node *) tle->expr) == UNKNOWNOID)
                expr = tle->expr;
            else
                expr = (Expr *) makeVar(rtr->rtindex,
@@ -500,7 +577,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
                                        resnode->restypmod,
                                        0);
            resnode = copyObject(resnode);
-           resnode->resno = (AttrNumber) pstate->p_last_resno++;
+           resnode->resno = (AttrNumber) pstate->p_next_resno++;
            qry->targetList = lappend(qry->targetList,
                                      makeTargetEntry(resnode, expr));
        }
@@ -520,8 +597,8 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
     */
 
    /* Prepare to assign non-conflicting resnos to resjunk attributes */
-   if (pstate->p_last_resno <= pstate->p_target_relation->rd_rel->relnatts)
-       pstate->p_last_resno = pstate->p_target_relation->rd_rel->relnatts + 1;
+   if (pstate->p_next_resno <= pstate->p_target_relation->rd_rel->relnatts)
+       pstate->p_next_resno = pstate->p_target_relation->rd_rel->relnatts + 1;
 
    /* Validate stmt->cols list, or build default list if no list given */
    icolumns = checkInsertTargets(pstate, stmt->cols, &attrnos);
@@ -1484,7 +1561,7 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
        List       *newactions = NIL;
 
        /*
-        * transform each statement, like parse_analyze()
+        * transform each statement, like parse_sub_analyze()
         */
        foreach(oldactions, stmt->actions)
        {
@@ -1789,7 +1866,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
        Resdom     *resdom;
        Expr       *expr;
 
-       resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
+       resdom = makeResdom((AttrNumber) pstate->p_next_resno++,
                            colType,
                            -1,
                            colName,
@@ -1938,7 +2015,7 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt)
         * of this sub-query, because they are not in the toplevel
         * pstate's namespace list.
         */
-       selectList = parse_analyze((Node *) stmt, pstate);
+       selectList = parse_sub_analyze((Node *) stmt, pstate);
 
        Assert(length(selectList) == 1);
        selectQuery = (Query *) lfirst(selectList);
@@ -2132,8 +2209,8 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
     */
 
    /* Prepare to assign non-conflicting resnos to resjunk attributes */
-   if (pstate->p_last_resno <= pstate->p_target_relation->rd_rel->relnatts)
-       pstate->p_last_resno = pstate->p_target_relation->rd_rel->relnatts + 1;
+   if (pstate->p_next_resno <= pstate->p_target_relation->rd_rel->relnatts)
+       pstate->p_next_resno = pstate->p_target_relation->rd_rel->relnatts + 1;
 
    /* Prepare non-junk columns for assignment to target table */
    origTargetList = stmt->targetList;
@@ -2151,7 +2228,7 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
             * columns; else rewriter or planner might get confused.
             */
            resnode->resname = "?resjunk?";
-           resnode->resno = (AttrNumber) pstate->p_last_resno++;
+           resnode->resno = (AttrNumber) pstate->p_next_resno++;
            continue;
        }
        if (origTargetList == NIL)
@@ -2316,11 +2393,10 @@ static Query *
 transformPrepareStmt(ParseState *pstate, PrepareStmt *stmt)
 {
    Query      *result = makeNode(Query);
-   List       *extras_before = NIL,
-              *extras_after = NIL;
    List       *argtype_oids = NIL;     /* argtype OIDs in a list */
-   Oid        *argtoids = NULL;    /* as an array for parser_param_set */
+   Oid        *argtoids = NULL;        /* and as an array */
    int         nargs;
+   List       *queries;
 
    result->commandType = CMD_UTILITY;
    result->utilityStmt = (Node *) stmt;
@@ -2348,24 +2424,19 @@ transformPrepareStmt(ParseState *pstate, PrepareStmt *stmt)
    stmt->argtype_oids = argtype_oids;
 
    /*
-    * We need to adjust the parameters expected by the rest of the
-    * system, so that $1, ... $n are parsed properly.
-    *
-    * This is somewhat of a hack; however, the main parser interface only
-    * allows parameters to be specified when working with a raw query
-    * string, which is not helpful here.
+    * Analyze the statement using these parameter types (any parameters
+    * passed in from above us will not be visible to it).
     */
-   parser_param_set(argtoids, nargs);
-
-   stmt->query = transformStmt(pstate, (Node *) stmt->query,
-                               &extras_before, &extras_after);
+   queries = parse_analyze((Node *) stmt->query, argtoids, nargs);
 
-   /* Shouldn't get any extras, since grammar only allows OptimizableStmt */
-   if (extras_before || extras_after)
+   /*
+    * Shouldn't get any extra statements, since grammar only allows
+    * OptimizableStmt
+    */
+   if (length(queries) != 1)
        elog(ERROR, "transformPrepareStmt: internal error");
 
-   /* Remove links to our local parameters */
-   parser_param_set(NULL, 0);
+   stmt->query = lfirst(queries);
 
    return result;
 }
@@ -2409,7 +2480,7 @@ transformExecuteStmt(ParseState *pstate, ExecuteStmt *stmt)
            given_type_id = exprType(expr);
            expected_type_id = lfirsto(paramtypes);
 
-           expr = coerce_to_target_type(expr, given_type_id,
+           expr = coerce_to_target_type(pstate, expr, given_type_id,
                                         expected_type_id, -1,
                                         COERCION_ASSIGNMENT,
                                         COERCE_IMPLICIT_CAST);
index 2fd5811000a07ac0bf1152936ab848ae7b4932a3..1c8cb8bc0e3721603011004c87aa0714b5ff8607 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.112 2003/03/22 01:49:38 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.113 2003/04/29 22:13:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -54,7 +54,7 @@ static RangeTblRef *transformRangeFunction(ParseState *pstate,
                       RangeFunction *r);
 static Node *transformFromClauseItem(ParseState *pstate, Node *n,
                        List **containedRels);
-static Node *buildMergedJoinVar(JoinType jointype,
+static Node *buildMergedJoinVar(ParseState *pstate, JoinType jointype,
                   Var *l_colvar, Var *r_colvar);
 static TargetEntry *findTargetlistEntry(ParseState *pstate, Node *node,
                    List *tlist, int clause);
@@ -284,7 +284,7 @@ transformJoinUsingClause(ParseState *pstate, List *leftVars, List *rightVars)
     */
    result = transformExpr(pstate, result);
 
-   result = coerce_to_boolean(result, "JOIN/USING");
+   result = coerce_to_boolean(pstate, result, "JOIN/USING");
 
    return result;
 }  /* transformJoinUsingClause() */
@@ -318,7 +318,7 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j,
    /* This part is just like transformWhereClause() */
    result = transformExpr(pstate, j->quals);
 
-   result = coerce_to_boolean(result, "JOIN/ON");
+   result = coerce_to_boolean(pstate, result, "JOIN/ON");
 
    pstate->p_namespace = save_namespace;
 
@@ -398,7 +398,7 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
    /*
     * Analyze and transform the subquery.
     */
-   parsetrees = parse_analyze(r->subquery, pstate);
+   parsetrees = parse_sub_analyze(r->subquery, pstate);
 
    /*
     * Check that we got something reasonable.  Some of these conditions
@@ -759,7 +759,8 @@ transformFromClauseItem(ParseState *pstate, Node *n, List **containedRels)
 
                res_colnames = lappend(res_colnames, lfirst(ucol));
                res_colvars = lappend(res_colvars,
-                                     buildMergedJoinVar(j->jointype,
+                                     buildMergedJoinVar(pstate,
+                                                        j->jointype,
                                                         l_colvar,
                                                         r_colvar));
            }
@@ -836,7 +837,8 @@ transformFromClauseItem(ParseState *pstate, Node *n, List **containedRels)
  *   generate a suitable replacement expression for a merged join column
  */
 static Node *
-buildMergedJoinVar(JoinType jointype, Var *l_colvar, Var *r_colvar)
+buildMergedJoinVar(ParseState *pstate, JoinType jointype,
+                  Var *l_colvar, Var *r_colvar)
 {
    Oid         outcoltype;
    int32       outcoltypmod;
@@ -869,7 +871,7 @@ buildMergedJoinVar(JoinType jointype, Var *l_colvar, Var *r_colvar)
     * typmod is not same as input.
     */
    if (l_colvar->vartype != outcoltype)
-       l_node = coerce_type((Node *) l_colvar, l_colvar->vartype,
+       l_node = coerce_type(pstate, (Node *) l_colvar, l_colvar->vartype,
                             outcoltype,
                             COERCION_IMPLICIT, COERCE_IMPLICIT_CAST);
    else if (l_colvar->vartypmod != outcoltypmod)
@@ -880,7 +882,7 @@ buildMergedJoinVar(JoinType jointype, Var *l_colvar, Var *r_colvar)
        l_node = (Node *) l_colvar;
 
    if (r_colvar->vartype != outcoltype)
-       r_node = coerce_type((Node *) r_colvar, r_colvar->vartype,
+       r_node = coerce_type(pstate, (Node *) r_colvar, r_colvar->vartype,
                             outcoltype,
                             COERCION_IMPLICIT, COERCE_IMPLICIT_CAST);
    else if (r_colvar->vartypmod != outcoltypmod)
@@ -953,7 +955,7 @@ transformWhereClause(ParseState *pstate, Node *clause)
 
    qual = transformExpr(pstate, clause);
 
-   qual = coerce_to_boolean(qual, "WHERE");
+   qual = coerce_to_boolean(pstate, qual, "WHERE");
 
    return qual;
 }
index a4b739b0f7e8a77db2ac1da07fd6982d30832742..9dc0c7f1c19ba4f0b66a952676e09ed567dd0dde 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.95 2003/04/10 02:47:46 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.96 2003/04/29 22:13:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,6 +17,7 @@
 #include "catalog/pg_cast.h"
 #include "catalog/pg_proc.h"
 #include "nodes/makefuncs.h"
+#include "nodes/params.h"
 #include "optimizer/clauses.h"
 #include "parser/parse_coerce.h"
 #include "parser/parse_expr.h"
@@ -49,6 +50,7 @@ static Node *build_func_call(Oid funcid, Oid rettype, List *args,
  * conversion is not possible.  (We do this, rather than elog'ing directly,
  * so that callers can generate custom error messages indicating context.)
  *
+ * pstate - parse state (can be NULL, see coerce_type)
  * expr - input expression tree (already transformed by transformExpr)
  * exprtype - result type of expr
  * targettype - desired result type
@@ -56,13 +58,13 @@ static Node *build_func_call(Oid funcid, Oid rettype, List *args,
  * ccontext, cformat - context indicators to control coercions
  */
 Node *
-coerce_to_target_type(Node *expr, Oid exprtype,
+coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype,
                      Oid targettype, int32 targettypmod,
                      CoercionContext ccontext,
                      CoercionForm cformat)
 {
    if (can_coerce_type(1, &exprtype, &targettype, ccontext))
-       expr = coerce_type(expr, exprtype, targettype,
+       expr = coerce_type(pstate, expr, exprtype, targettype,
                           ccontext, cformat);
    /*
     * String hacks to get transparent conversions for char and varchar:
@@ -79,7 +81,7 @@ coerce_to_target_type(Node *expr, Oid exprtype,
 
        if (can_coerce_type(1, &exprtype, &text_id, ccontext))
        {
-           expr = coerce_type(expr, exprtype, text_id,
+           expr = coerce_type(pstate, expr, exprtype, text_id,
                               ccontext, cformat);
            /* Need a RelabelType if no typmod coercion is performed */
            if (targettypmod < 0)
@@ -117,9 +119,14 @@ coerce_to_target_type(Node *expr, Oid exprtype,
  * call coerce_type_typmod as well, if a typmod constraint is wanted.
  * (But if the target type is a domain, it may internally contain a
  * typmod constraint, which will be applied inside coerce_to_domain.)
+ *
+ * pstate is only used in the case that we are able to resolve the type of
+ * a previously UNKNOWN Param.  It is okay to pass pstate = NULL if the
+ * caller does not want type information updated for Params.
  */
 Node *
-coerce_type(Node *node, Oid inputTypeId, Oid targetTypeId,
+coerce_type(ParseState *pstate, Node *node,
+           Oid inputTypeId, Oid targetTypeId,
            CoercionContext ccontext, CoercionForm cformat)
 {
    Node       *result;
@@ -129,9 +136,9 @@ coerce_type(Node *node, Oid inputTypeId, Oid targetTypeId,
        node == NULL)
    {
        /* no conversion needed */
-       result = node;
+       return node;
    }
-   else if (inputTypeId == UNKNOWNOID && IsA(node, Const))
+   if (inputTypeId == UNKNOWNOID && IsA(node, Const))
    {
        /*
         * Input is a string constant with previously undetermined type.
@@ -187,17 +194,62 @@ coerce_type(Node *node, Oid inputTypeId, Oid targetTypeId,
                                      cformat);
 
        ReleaseSysCache(targetType);
+
+       return result;
    }
-   else if (targetTypeId == ANYOID ||
-            targetTypeId == ANYARRAYOID ||
-            targetTypeId == ANYELEMENTOID)
+   if (inputTypeId == UNKNOWNOID && IsA(node, Param) &&
+       ((Param *) node)->paramkind == PARAM_NUM &&
+       pstate != NULL && pstate->p_variableparams)
+   {
+       /*
+        * Input is a Param of previously undetermined type, and we want
+        * to update our knowledge of the Param's type.  Find the topmost
+        * ParseState and update the state.
+        */
+       Param      *param = (Param *) node;
+       int         paramno = param->paramid;
+       ParseState *toppstate;
+
+       toppstate = pstate;
+       while (toppstate->parentParseState != NULL)
+           toppstate = toppstate->parentParseState;
+
+       if (paramno <= 0 ||     /* shouldn't happen, but... */
+           paramno > toppstate->p_numparams)
+           elog(ERROR, "Parameter '$%d' is out of range", paramno);
+
+       if (toppstate->p_paramtypes[paramno-1] == UNKNOWNOID)
+       {
+           /* We've successfully resolved the type */
+           toppstate->p_paramtypes[paramno-1] = targetTypeId;
+       }
+       else if (toppstate->p_paramtypes[paramno-1] == targetTypeId)
+       {
+           /* We previously resolved the type, and it matches */
+       }
+       else
+       {
+           /* Ooops */
+           elog(ERROR, "Inconsistent types deduced for parameter '$%d'"
+                "\n\tCould be either %s or %s",
+                paramno,
+                format_type_be(toppstate->p_paramtypes[paramno-1]),
+                format_type_be(targetTypeId));
+       }
+
+       param->paramtype = targetTypeId;
+       return (Node *) param;
+   }
+   if (targetTypeId == ANYOID ||
+       targetTypeId == ANYARRAYOID ||
+       targetTypeId == ANYELEMENTOID)
    {
        /* assume can_coerce_type verified that implicit coercion is okay */
        /* NB: we do NOT want a RelabelType here */
-       result = node;
+       return node;
    }
-   else if (find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
-                                  &funcId))
+   if (find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
+                             &funcId))
    {
        if (OidIsValid(funcId))
        {
@@ -247,27 +299,23 @@ coerce_type(Node *node, Oid inputTypeId, Oid targetTypeId,
                                                  cformat);
            }
        }
+       return result;
    }
-   else if (typeInheritsFrom(inputTypeId, targetTypeId))
+   if (typeInheritsFrom(inputTypeId, targetTypeId))
    {
        /*
         * Input class type is a subclass of target, so nothing to do ---
         * except relabel the type.  This is binary compatibility for
         * complex types.
         */
-       result = (Node *) makeRelabelType((Expr *) node,
-                                         targetTypeId, -1,
-                                         cformat);
+       return (Node *) makeRelabelType((Expr *) node,
+                                       targetTypeId, -1,
+                                       cformat);
    }
-   else
-   {
-       /* If we get here, caller blew it */
-       elog(ERROR, "coerce_type: no conversion function from %s to %s",
-            format_type_be(inputTypeId), format_type_be(targetTypeId));
-       result = NULL;          /* keep compiler quiet */
-   }
-
-   return result;
+   /* If we get here, caller blew it */
+   elog(ERROR, "coerce_type: no conversion function from %s to %s",
+        format_type_be(inputTypeId), format_type_be(targetTypeId));
+   return NULL;                /* keep compiler quiet */
 }
 
 
@@ -484,15 +532,19 @@ coerce_type_typmod(Node *node, Oid targetTypeId, int32 targetTypMod,
  *     (AND, OR, NOT, etc).  Also check that input is not a set.
  *
  * Returns the possibly-transformed node tree.
+ *
+ * As with coerce_type, pstate may be NULL if no special unknown-Param
+ * processing is wanted.
  */
 Node *
-coerce_to_boolean(Node *node, const char *constructName)
+coerce_to_boolean(ParseState *pstate, Node *node,
+                 const char *constructName)
 {
    Oid         inputTypeId = exprType(node);
 
    if (inputTypeId != BOOLOID)
    {
-       node = coerce_to_target_type(node, inputTypeId,
+       node = coerce_to_target_type(pstate, node, inputTypeId,
                                     BOOLOID, -1,
                                     COERCION_ASSIGNMENT,
                                     COERCE_IMPLICIT_CAST);
@@ -594,16 +646,20 @@ select_common_type(List *typeids, const char *context)
  * This is used following select_common_type() to coerce the individual
  * expressions to the desired type.  'context' is a phrase to use in the
  * error message if we fail to coerce.
+ *
+ * As with coerce_type, pstate may be NULL if no special unknown-Param
+ * processing is wanted.
  */
 Node *
-coerce_to_common_type(Node *node, Oid targetTypeId, const char *context)
+coerce_to_common_type(ParseState *pstate, Node *node,
+                     Oid targetTypeId, const char *context)
 {
    Oid         inputTypeId = exprType(node);
 
    if (inputTypeId == targetTypeId)
        return node;            /* no work */
    if (can_coerce_type(1, &inputTypeId, &targetTypeId, COERCION_IMPLICIT))
-       node = coerce_type(node, inputTypeId, targetTypeId,
+       node = coerce_type(pstate, node, inputTypeId, targetTypeId,
                           COERCION_IMPLICIT, COERCE_IMPLICIT_CAST);
    else
        elog(ERROR, "%s unable to convert to type %s",
index 10702e9a2693d924957a0497d2039fc64397bebe..429a9ac8c8a3dffe1b5c8771163008b22848972c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.147 2003/04/08 23:20:02 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.148 2003/04/29 22:13:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -39,7 +39,8 @@ static int    expr_depth_counter = 0;
 
 bool       Transform_null_equals = false;
 
-static Node *typecast_expression(Node *expr, TypeName *typename);
+static Node *typecast_expression(ParseState *pstate, Node *expr,
+                                TypeName *typename);
 static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref);
 static Node *transformIndirection(ParseState *pstate, Node *basenode,
                     List *indirection);
@@ -112,17 +113,54 @@ transformExpr(ParseState *pstate, Node *expr)
            {
                ParamRef   *pref = (ParamRef *) expr;
                int         paramno = pref->number;
-               Oid         paramtyp = param_type(paramno);
+               ParseState *toppstate;
                Param      *param;
                List       *fields;
 
-               if (!OidIsValid(paramtyp))
-                   elog(ERROR, "Parameter '$%d' is out of range", paramno);
+               /*
+                * Find topmost ParseState, which is where paramtype info
+                * lives.
+                */
+               toppstate = pstate;
+               while (toppstate->parentParseState != NULL)
+                   toppstate = toppstate->parentParseState;
+
+               /* Check parameter number is in range */
+               if (paramno <= 0) /* probably can't happen? */
+                   elog(ERROR, "Parameter '$%d' is out of range",
+                        paramno);
+               if (paramno > toppstate->p_numparams)
+               {
+                   if (!toppstate->p_variableparams)
+                       elog(ERROR, "Parameter '$%d' is out of range",
+                            paramno);
+                   /* Okay to enlarge param array */
+                   if (toppstate->p_paramtypes)
+                       toppstate->p_paramtypes =
+                           (Oid *) repalloc(toppstate->p_paramtypes,
+                                            paramno * sizeof(Oid));
+                   else
+                       toppstate->p_paramtypes =
+                           (Oid *) palloc(paramno * sizeof(Oid));
+                   /* Zero out the previously-unreferenced slots */
+                   MemSet(toppstate->p_paramtypes + toppstate->p_numparams,
+                          0,
+                          (paramno - toppstate->p_numparams) * sizeof(Oid));
+                   toppstate->p_numparams = paramno;
+               }
+               if (toppstate->p_variableparams)
+               {
+                   /* If not seen before, initialize to UNKNOWN type */
+                   if (toppstate->p_paramtypes[paramno-1] == InvalidOid)
+                       toppstate->p_paramtypes[paramno-1] = UNKNOWNOID;
+               }
+
                param = makeNode(Param);
                param->paramkind = PARAM_NUM;
                param->paramid = (AttrNumber) paramno;
-               param->paramtype = paramtyp;
+               param->paramtype = toppstate->p_paramtypes[paramno-1];
                result = (Node *) param;
+
                /* handle qualification, if any */
                foreach(fields, pref->fields)
                {
@@ -143,7 +181,8 @@ transformExpr(ParseState *pstate, Node *expr)
 
                result = (Node *) make_const(val);
                if (con->typename != NULL)
-                   result = typecast_expression(result, con->typename);
+                   result = typecast_expression(pstate, result,
+                                                con->typename);
                break;
            }
        case T_ExprFieldSelect:
@@ -170,7 +209,7 @@ transformExpr(ParseState *pstate, Node *expr)
                TypeCast   *tc = (TypeCast *) expr;
                Node       *arg = transformExpr(pstate, tc->arg);
 
-               result = typecast_expression(arg, tc->typename);
+               result = typecast_expression(pstate, arg, tc->typename);
                break;
            }
        case T_A_Expr:
@@ -212,7 +251,8 @@ transformExpr(ParseState *pstate, Node *expr)
                                Node       *rexpr = transformExpr(pstate,
                                                                  a->rexpr);
 
-                               result = (Node *) make_op(a->name,
+                               result = (Node *) make_op(pstate,
+                                                         a->name,
                                                          lexpr,
                                                          rexpr);
                            }
@@ -225,8 +265,8 @@ transformExpr(ParseState *pstate, Node *expr)
                            Node       *rexpr = transformExpr(pstate,
                                                              a->rexpr);
 
-                           lexpr = coerce_to_boolean(lexpr, "AND");
-                           rexpr = coerce_to_boolean(rexpr, "AND");
+                           lexpr = coerce_to_boolean(pstate, lexpr, "AND");
+                           rexpr = coerce_to_boolean(pstate, rexpr, "AND");
 
                            result = (Node *) makeBoolExpr(AND_EXPR,
                                                           makeList2(lexpr,
@@ -240,8 +280,8 @@ transformExpr(ParseState *pstate, Node *expr)
                            Node       *rexpr = transformExpr(pstate,
                                                              a->rexpr);
 
-                           lexpr = coerce_to_boolean(lexpr, "OR");
-                           rexpr = coerce_to_boolean(rexpr, "OR");
+                           lexpr = coerce_to_boolean(pstate, lexpr, "OR");
+                           rexpr = coerce_to_boolean(pstate, rexpr, "OR");
 
                            result = (Node *) makeBoolExpr(OR_EXPR,
                                                           makeList2(lexpr,
@@ -253,7 +293,7 @@ transformExpr(ParseState *pstate, Node *expr)
                            Node       *rexpr = transformExpr(pstate,
                                                              a->rexpr);
 
-                           rexpr = coerce_to_boolean(rexpr, "NOT");
+                           rexpr = coerce_to_boolean(pstate, rexpr, "NOT");
 
                            result = (Node *) makeBoolExpr(NOT_EXPR,
                                                           makeList1(rexpr));
@@ -266,7 +306,8 @@ transformExpr(ParseState *pstate, Node *expr)
                            Node       *rexpr = transformExpr(pstate,
                                                              a->rexpr);
 
-                           result = (Node *) make_op(a->name,
+                           result = (Node *) make_op(pstate,
+                                                     a->name,
                                                      lexpr,
                                                      rexpr);
                            if (((OpExpr *) result)->opresulttype != BOOLOID)
@@ -284,7 +325,8 @@ transformExpr(ParseState *pstate, Node *expr)
                            Node       *rexpr = transformExpr(pstate,
                                                              a->rexpr);
 
-                           result = (Node *) make_op(a->name,
+                           result = (Node *) make_op(pstate,
+                                                     a->name,
                                                      lexpr,
                                                      rexpr);
                            if (((OpExpr *) result)->opresulttype != BOOLOID)
@@ -375,7 +417,7 @@ transformExpr(ParseState *pstate, Node *expr)
                    break;
                }
                pstate->p_hasSubLinks = true;
-               qtrees = parse_analyze(sublink->subselect, pstate);
+               qtrees = parse_sub_analyze(sublink->subselect, pstate);
                if (length(qtrees) != 1)
                    elog(ERROR, "Bad query in subselect");
                qtree = (Query *) lfirst(qtrees);
@@ -523,7 +565,7 @@ transformExpr(ParseState *pstate, Node *expr)
 
                    if (needNot)
                    {
-                       expr = coerce_to_boolean(expr, "NOT");
+                       expr = coerce_to_boolean(pstate, expr, "NOT");
                        expr = (Node *) makeBoolExpr(NOT_EXPR,
                                                     makeList1(expr));
                    }
@@ -561,7 +603,8 @@ transformExpr(ParseState *pstate, Node *expr)
                    }
                    neww->expr = (Expr *) transformExpr(pstate, warg);
 
-                   neww->expr = (Expr *) coerce_to_boolean((Node *) neww->expr,
+                   neww->expr = (Expr *) coerce_to_boolean(pstate,
+                                                           (Node *) neww->expr,
                                                            "CASE/WHEN");
 
                    /*
@@ -615,7 +658,8 @@ transformExpr(ParseState *pstate, Node *expr)
 
                /* Convert default result clause, if necessary */
                newc->defresult = (Expr *)
-                   coerce_to_common_type((Node *) newc->defresult,
+                   coerce_to_common_type(pstate,
+                                         (Node *) newc->defresult,
                                          ptype,
                                          "CASE/ELSE");
 
@@ -625,7 +669,8 @@ transformExpr(ParseState *pstate, Node *expr)
                    CaseWhen   *w = (CaseWhen *) lfirst(args);
 
                    w->result = (Expr *)
-                       coerce_to_common_type((Node *) w->result,
+                       coerce_to_common_type(pstate,
+                                             (Node *) w->result,
                                              ptype,
                                              "CASE/WHEN");
                }
@@ -666,7 +711,9 @@ transformExpr(ParseState *pstate, Node *expr)
                    Node *e = (Node *) lfirst(element);
                    Node *newe;
 
-                   newe = coerce_to_common_type(e, element_type, "ARRAY");
+                   newe = coerce_to_common_type(pstate, e,
+                                                element_type,
+                                                "ARRAY");
                    newcoercedelems = lappend(newcoercedelems, newe);
                }
 
@@ -753,7 +800,8 @@ transformExpr(ParseState *pstate, Node *expr)
                    Node *e = (Node *) lfirst(args);
                    Node *newe;
 
-                   newe = coerce_to_common_type(e, newc->coalescetype,
+                   newe = coerce_to_common_type(pstate, e,
+                                                newc->coalescetype,
                                                 "COALESCE");
                    newcoercedargs = lappend(newcoercedargs, newe);
                }
@@ -806,7 +854,9 @@ transformExpr(ParseState *pstate, Node *expr)
 
                b->arg = (Expr *) transformExpr(pstate, (Node *) b->arg);
 
-               b->arg = (Expr *) coerce_to_boolean((Node *) b->arg, clausename);
+               b->arg = (Expr *) coerce_to_boolean(pstate,
+                                                   (Node *) b->arg,
+                                                   clausename);
 
                result = expr;
                break;
@@ -1404,7 +1454,7 @@ exprIsLengthCoercion(Node *expr, int32 *coercedTypmod)
  * the type name and then apply any necessary coercion function(s).
  */
 static Node *
-typecast_expression(Node *expr, TypeName *typename)
+typecast_expression(ParseState *pstate, Node *expr, TypeName *typename)
 {
    Oid         inputType = exprType(expr);
    Oid         targetType;
@@ -1414,7 +1464,7 @@ typecast_expression(Node *expr, TypeName *typename)
    if (inputType == InvalidOid)
        return expr;            /* do nothing if NULL input */
 
-   expr = coerce_to_target_type(expr, inputType,
+   expr = coerce_to_target_type(pstate, expr, inputType,
                                 targetType, typename->typmod,
                                 COERCION_EXPLICIT,
                                 COERCE_EXPLICIT_CAST);
index 7cbef96536989aac2b059e30d4d174479417cef8..058b9aad73dc8524b162955dfcf601a3b8031ddb 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.146 2003/04/24 21:16:43 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.147 2003/04/29 22:13:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -253,7 +253,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
         * We can do it as a trivial coercion. coerce_type can handle
         * these cases, so why duplicate code...
         */
-       return coerce_type(lfirst(fargs), actual_arg_types[0], rettype,
+       return coerce_type(pstate, lfirst(fargs), actual_arg_types[0],
+                          rettype,
                           COERCION_EXPLICIT, COERCE_EXPLICIT_CALL);
    }
    else if (fdresult == FUNCDETAIL_NORMAL)
@@ -316,7 +317,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
                                               rettype);
 
    /* perform the necessary typecasting of arguments */
-   make_fn_arguments(fargs, actual_arg_types, declared_arg_types);
+   make_fn_arguments(pstate, fargs, actual_arg_types, declared_arg_types);
 
    /* build the appropriate output structure */
    if (fdresult == FUNCDETAIL_NORMAL)
@@ -1145,9 +1146,13 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
  * allowed.
  *
  * Caution: given argument list is modified in-place.
+ *
+ * As with coerce_type, pstate may be NULL if no special unknown-Param
+ * processing is wanted.
  */
 void
-make_fn_arguments(List *fargs,
+make_fn_arguments(ParseState *pstate,
+                 List *fargs,
                  Oid *actual_arg_types,
                  Oid *declared_arg_types)
 {
@@ -1159,7 +1164,8 @@ make_fn_arguments(List *fargs,
        /* types don't match? then force coercion using a function call... */
        if (actual_arg_types[i] != declared_arg_types[i])
        {
-           lfirst(current_fargs) = coerce_type(lfirst(current_fargs),
+           lfirst(current_fargs) = coerce_type(pstate,
+                                               lfirst(current_fargs),
                                                actual_arg_types[i],
                                                declared_arg_types[i],
                                                COERCION_IMPLICIT,
index 700c4b158de9ff82070e7a6294f8deb3da1381c1..2f5775212cb2bee967283b89d15fe08180ac41f0 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.77 2003/04/08 23:20:02 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.78 2003/04/29 22:13:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -39,7 +39,12 @@ make_parsestate(ParseState *parentParseState)
    pstate = palloc0(sizeof(ParseState));
 
    pstate->parentParseState = parentParseState;
-   pstate->p_last_resno = 1;
+
+   /* Fill in fields that don't start at null/false/zero */
+   pstate->p_next_resno = 1;
+
+   if (parentParseState)
+       pstate->p_variableparams = parentParseState->p_variableparams;
 
    return pstate;
 }
@@ -166,7 +171,8 @@ transformArraySubscripts(ParseState *pstate,
            {
                subexpr = transformExpr(pstate, ai->lidx);
                /* If it's not int4 already, try to coerce */
-               subexpr = coerce_to_target_type(subexpr, exprType(subexpr),
+               subexpr = coerce_to_target_type(pstate,
+                                               subexpr, exprType(subexpr),
                                                INT4OID, -1,
                                                COERCION_ASSIGNMENT,
                                                COERCE_IMPLICIT_CAST);
@@ -186,7 +192,8 @@ transformArraySubscripts(ParseState *pstate,
        }
        subexpr = transformExpr(pstate, ai->uidx);
        /* If it's not int4 already, try to coerce */
-       subexpr = coerce_to_target_type(subexpr, exprType(subexpr),
+       subexpr = coerce_to_target_type(pstate,
+                                       subexpr, exprType(subexpr),
                                        INT4OID, -1,
                                        COERCION_ASSIGNMENT,
                                        COERCE_IMPLICIT_CAST);
@@ -205,7 +212,8 @@ transformArraySubscripts(ParseState *pstate,
 
        if (typesource != InvalidOid)
        {
-           assignFrom = coerce_to_target_type(assignFrom, typesource,
+           assignFrom = coerce_to_target_type(pstate,
+                                              assignFrom, typesource,
                                               typeneeded, arrayTypMod,
                                               COERCION_ASSIGNMENT,
                                               COERCE_IMPLICIT_CAST);
index 3be29e64defb749739098b7184a38e5ee7298aca..6238258ed2f6448eea2e8dfa84e32b205460d541 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.62 2003/04/08 23:20:02 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.63 2003/04/29 22:13:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1019,9 +1019,12 @@ unary_op_error(List *op, Oid arg, bool is_left_op)
  *
  * Transform operator expression ensuring type compatibility.
  * This is where some type conversion happens.
+ *
+ * As with coerce_type, pstate may be NULL if no special unknown-Param
+ * processing is wanted.
  */
 Expr *
-make_op(List *opname, Node *ltree, Node *rtree)
+make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree)
 {
    Oid         ltypeId,
                rtypeId;
@@ -1052,7 +1055,7 @@ make_op(List *opname, Node *ltree, Node *rtree)
    }
 
    /* Do typecasting and build the expression tree */
-   result = make_op_expr(tup, ltree, rtree, ltypeId, rtypeId);
+   result = make_op_expr(pstate, tup, ltree, rtree, ltypeId, rtypeId);
 
    ReleaseSysCache(tup);
 
@@ -1063,9 +1066,13 @@ make_op(List *opname, Node *ltree, Node *rtree)
 /*
  * make_op_expr()
  *     Build operator expression using an already-looked-up operator.
+ *
+ * As with coerce_type, pstate may be NULL if no special unknown-Param
+ * processing is wanted.
  */
 Expr *
-make_op_expr(Operator op, Node *ltree, Node *rtree,
+make_op_expr(ParseState *pstate, Operator op,
+            Node *ltree, Node *rtree,
             Oid ltypeId, Oid rtypeId)
 {
    Form_pg_operator opform = (Form_pg_operator) GETSTRUCT(op);
@@ -1114,7 +1121,7 @@ make_op_expr(Operator op, Node *ltree, Node *rtree,
                                               opform->oprresult);
 
    /* perform the necessary typecasting of arguments */
-   make_fn_arguments(args, actual_arg_types, declared_arg_types);
+   make_fn_arguments(pstate, args, actual_arg_types, declared_arg_types);
 
    /* and build the expression node */
    result = makeNode(OpExpr);
index 4ae3bf23153229616db8ae6e7debafe33508ae32..41fd98fc0713f0c109aef4b3208758a0259eb456 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.80 2002/12/12 15:49:39 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.81 2003/04/29 22:13:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1447,7 +1447,7 @@ expandRelAttrs(ParseState *pstate, RangeTblEntry *rte)
        Node       *varnode = (Node *) lfirst(vars);
        TargetEntry *te = makeNode(TargetEntry);
 
-       te->resdom = makeResdom((AttrNumber) (pstate->p_last_resno)++,
+       te->resdom = makeResdom((AttrNumber) pstate->p_next_resno++,
                                exprType(varnode),
                                exprTypmod(varnode),
                                label,
index e1be47b3ec56a6a674ee783a6d8b12848e6745c9..dc8f241d45ea6e03450f4ace313a3c997a8b11ca 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.99 2003/04/08 23:20:02 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.100 2003/04/29 22:13:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -73,7 +73,7 @@ transformTargetEntry(ParseState *pstate,
        colname = FigureColname(node);
    }
 
-   resnode = makeResdom((AttrNumber) pstate->p_last_resno++,
+   resnode = makeResdom((AttrNumber) pstate->p_next_resno++,
                         type_id,
                         type_mod,
                         colname,
@@ -290,7 +290,8 @@ updateTargetListEntry(ParseState *pstate,
        if (type_id != InvalidOid)
        {
            tle->expr = (Expr *)
-               coerce_to_target_type((Node *) tle->expr, type_id,
+               coerce_to_target_type(pstate,
+                                     (Node *) tle->expr, type_id,
                                      attrtype, attrtypmod,
                                      COERCION_ASSIGNMENT,
                                      COERCE_IMPLICIT_CAST);
index 85aeafacc59befaf6dacdce87d341b27a19f733e..d1a324dbf0afbab819f7271785158ccc1a200ac3 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.56 2003/04/27 20:09:44 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.57 2003/04/29 22:13:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -437,7 +437,7 @@ parseTypeString(const char *str, Oid *type_id, int32 *typmod)
    initStringInfo(&buf);
    appendStringInfo(&buf, "SELECT (NULL::%s)", str);
 
-   raw_parsetree_list = parser(buf.data, NULL, 0);
+   raw_parsetree_list = raw_parser(buf.data);
 
    /*
     * Make sure we got back exactly what we expected and no more;
index 16745f7b3708249ab8a405cee8362a472e178c16..37436d30079c92e51125b1d16cfe85b64e9d0c52 100644 (file)
@@ -14,7 +14,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.56 2003/04/27 20:09:44 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.57 2003/04/29 22:13:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 List      *parsetree;          /* result of parsing is left here */
 
-static Oid *param_type_info;   /* state for param_type() */
-static int param_count;
-
 static int lookahead_token;    /* one-token lookahead */
 static bool have_lookahead;        /* lookahead_token set? */
 
 
 /*
- * parser
- *     Given a query in string form, and optionally info about
- *     parameter types, do lexical and syntactic analysis.
+ * raw_parser
+ *     Given a query in string form, do lexical and grammatical analysis.
  *
  * Returns a list of raw (un-analyzed) parse trees.
  */
 List *
-parser(const char *str, Oid *typev, int nargs)
+raw_parser(const char *str)
 {
    int         yyresult;
 
-   parsetree = NIL;            /* in case parser forgets to set it */
+   parsetree = NIL;            /* in case grammar forgets to set it */
    have_lookahead = false;
 
    scanner_init(str);
    parser_init();
    parse_expr_init();
-   parser_param_set(typev, nargs);
 
    yyresult = yyparse();
 
@@ -69,35 +64,6 @@ parser(const char *str, Oid *typev, int nargs)
 }
 
 
-/*
- * Save information needed to fill out the type of Param references ($n)
- *
- * This is used for SQL functions, PREPARE statements, etc.  It's split
- * out from parser() setup because PREPARE needs to change the info after
- * the grammar runs and before parse analysis is done on the preparable
- * query.
- */
-void
-parser_param_set(Oid *typev, int nargs)
-{
-   param_type_info = typev;
-   param_count = nargs;
-}
-
-/*
- * param_type()
- *
- * Fetch a parameter type previously passed to parser_param_set
- */
-Oid
-param_type(int t)
-{
-   if (t > param_count || t <= 0)
-       return InvalidOid;
-   return param_type_info[t - 1];
-}
-
-
 /*
  * Intermediate filter between parser and base lexer (base_yylex in scan.l).
  *
index e39ee0efbe7498b6d843c2bd91df5b9021cc78fe..8ca7fb954f098817f29d1f3a35bcfd2b355a9018 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.118 2003/02/25 23:47:43 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.119 2003/04/29 22:13:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -498,7 +498,8 @@ build_column_default(Relation rel, int attrno)
     */
    exprtype = exprType(expr);
 
-   expr = coerce_to_target_type(expr, exprtype,
+   expr = coerce_to_target_type(NULL, /* no UNKNOWN params here */
+                                expr, exprtype,
                                 atttype, atttypmod,
                                 COERCION_ASSIGNMENT,
                                 COERCE_IMPLICIT_CAST);
index dca6455b0d0642d0634c39e70d18658b5b77913f..bc98d1d91ecd17f0a93d91d6b7ae883846799daa 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.325 2003/04/27 20:09:44 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.326 2003/04/29 22:13:11 tgl Exp $
  *
  * NOTES
  *   this is the "main" module of the postgres backend and
@@ -339,8 +339,8 @@ ReadCommand(StringInfo inBuf)
  */
 List *
 pg_parse_and_rewrite(const char *query_string, /* string to execute */
-                    Oid *typev,    /* parameter types */
-                    int nargs) /* number of parameters */
+                    Oid *paramTypes,   /* parameter types */
+                    int numParams) /* number of parameters */
 {
    List       *raw_parsetree_list;
    List       *querytree_list;
@@ -349,7 +349,7 @@ pg_parse_and_rewrite(const char *query_string, /* string to execute */
    /*
     * (1) parse the request string into a list of raw parse trees.
     */
-   raw_parsetree_list = pg_parse_query(query_string, typev, nargs);
+   raw_parsetree_list = pg_parse_query(query_string);
 
    /*
     * (2) Do parse analysis and rule rewrite.
@@ -360,7 +360,9 @@ pg_parse_and_rewrite(const char *query_string, /* string to execute */
        Node       *parsetree = (Node *) lfirst(list_item);
 
        querytree_list = nconc(querytree_list,
-                              pg_analyze_and_rewrite(parsetree));
+                              pg_analyze_and_rewrite(parsetree,
+                                                     paramTypes,
+                                                     numParams));
    }
 
    return querytree_list;
@@ -380,7 +382,7 @@ pg_parse_and_rewrite(const char *query_string, /* string to execute */
  * commands are not processed any further than the raw parse stage.
  */
 List *
-pg_parse_query(const char *query_string, Oid *typev, int nargs)
+pg_parse_query(const char *query_string)
 {
    List       *raw_parsetree_list;
 
@@ -390,7 +392,7 @@ pg_parse_query(const char *query_string, Oid *typev, int nargs)
    if (log_parser_stats)
        ResetUsage();
 
-   raw_parsetree_list = parser(query_string, typev, nargs);
+   raw_parsetree_list = raw_parser(query_string);
 
    if (log_parser_stats)
        ShowUsage("PARSER STATISTICS");
@@ -399,8 +401,8 @@ pg_parse_query(const char *query_string, Oid *typev, int nargs)
 }
 
 /*
- * Given a raw parsetree (gram.y output), perform parse analysis and
- * rule rewriting.
+ * Given a raw parsetree (gram.y output), and optionally information about
+ * types of parameter symbols ($n), perform parse analysis and rule rewriting.
  *
  * A list of Query nodes is returned, since either the analyzer or the
  * rewriter might expand one query to several.
@@ -408,7 +410,7 @@ pg_parse_query(const char *query_string, Oid *typev, int nargs)
  * NOTE: for reasons mentioned above, this must be separate from raw parsing.
  */
 List *
-pg_analyze_and_rewrite(Node *parsetree)
+pg_analyze_and_rewrite(Node *parsetree, Oid *paramTypes, int numParams)
 {
    List       *querytree_list;
    List       *list_item;
@@ -421,7 +423,7 @@ pg_analyze_and_rewrite(Node *parsetree)
    if (log_parser_stats)
        ResetUsage();
 
-   querytree_list = parse_analyze(parsetree, NULL);
+   querytree_list = parse_analyze(parsetree, paramTypes, numParams);
 
    if (log_parser_stats)
    {
@@ -562,8 +564,7 @@ pg_plan_query(Query *querytree)
  *
  * ----------------------------------------------------------------
  */
-
-void
+static void
 pg_exec_query_string(const char *query_string, /* string to execute */
                     CommandDest dest,  /* where results should go */
                     MemoryContext parse_context)       /* context for
@@ -614,7 +615,7 @@ pg_exec_query_string(const char *query_string,  /* string to execute */
     * Do basic parsing of the query or queries (this should be safe even
     * if we are in aborted transaction state!)
     */
-   parsetree_list = pg_parse_query(query_string, NULL, 0);
+   parsetree_list = pg_parse_query(query_string);
 
    /*
     * Switch back to execution context to enter the loop.
@@ -710,7 +711,7 @@ pg_exec_query_string(const char *query_string,  /* string to execute */
         */
        oldcontext = MemoryContextSwitchTo(parse_context);
 
-       querytree_list = pg_analyze_and_rewrite(parsetree);
+       querytree_list = pg_analyze_and_rewrite(parsetree, NULL, 0);
 
        /*
         * Switch back to execution context for planning and execution.
@@ -1826,7 +1827,7 @@ PostgresMain(int argc, char *argv[], const char *username)
    if (!IsUnderPostmaster)
    {
        puts("\nPOSTGRES backend interactive interface ");
-       puts("$Revision: 1.325 $ $Date: 2003/04/27 20:09:44 $\n");
+       puts("$Revision: 1.326 $ $Date: 2003/04/29 22:13:11 $\n");
    }
 
    /*
index f780ec4d294a1e5fe271c7d04649ae66ee81564c..b7d6a7d66581404a953b63d31bacfb4f912a1db1 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: analyze.h,v 1.20 2002/06/20 20:29:51 momjian Exp $
+ * $Id: analyze.h,v 1.21 2003/04/29 22:13:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "parser/parse_node.h"
 
-extern List *parse_analyze(Node *parseTree, ParseState *parentParseState);
+
+extern List *parse_analyze(Node *parseTree, Oid *paramTypes, int numParams);
+extern List *parse_analyze_varparams(Node *parseTree, Oid **paramTypes,
+                                    int *numParams);
+extern List *parse_sub_analyze(Node *parseTree, ParseState *parentParseState);
 extern List *analyzeCreateSchemaStmt(CreateSchemaStmt *stmt);
 
 extern void CheckSelectForUpdate(Query *qry);
index 97108f2b1c959a22c4f10d8c375c2388a79ddb02..f9a03959116f153f404abc89230cf205ac9542cc 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: gramparse.h,v 1.26 2003/04/27 20:09:44 tgl Exp $
+ * $Id: gramparse.h,v 1.27 2003/04/29 22:13:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,9 +17,8 @@
 
 #include "nodes/parsenodes.h"
 
+
 /* from parser.c */
-extern void parser_param_set(Oid *typev, int nargs);
-extern Oid param_type(int t);
 extern int yylex(void);
 
 /* from scan.l */
index b21a83601bf602a1f5c8aad98ed4cc04cd13586f..de2ea95db8547f1d35724aa7ce9f69cffee6d829 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_coerce.h,v 1.50 2003/04/08 23:20:04 tgl Exp $
+ * $Id: parse_coerce.h,v 1.51 2003/04/29 22:13:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,6 +17,7 @@
 #include "catalog/pg_type.h"
 #include "parser/parse_node.h"
 
+
 typedef enum CATEGORY
 {
    INVALID_TYPE,
@@ -38,22 +39,26 @@ extern bool IsBinaryCoercible(Oid srctype, Oid targettype);
 extern bool IsPreferredType(CATEGORY category, Oid type);
 extern CATEGORY TypeCategory(Oid type);
 
-extern Node *coerce_to_target_type(Node *expr, Oid exprtype,
+extern Node *coerce_to_target_type(ParseState *pstate,
+                                  Node *expr, Oid exprtype,
                                   Oid targettype, int32 targettypmod,
                                   CoercionContext ccontext,
                                   CoercionForm cformat);
 extern bool can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
                            CoercionContext ccontext);
-extern Node *coerce_type(Node *node, Oid inputTypeId, Oid targetTypeId,
+extern Node *coerce_type(ParseState *pstate, Node *node,
+                        Oid inputTypeId, Oid targetTypeId,
                         CoercionContext ccontext, CoercionForm cformat);
 extern Node *coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId,
                              CoercionForm cformat);
 
-extern Node *coerce_to_boolean(Node *node, const char *constructName);
+extern Node *coerce_to_boolean(ParseState *pstate, Node *node,
+                              const char *constructName);
 
 extern Oid select_common_type(List *typeids, const char *context);
-extern Node *coerce_to_common_type(Node *node, Oid targetTypeId,
-                     const char *context);
+extern Node *coerce_to_common_type(ParseState *pstate, Node *node,
+                                  Oid targetTypeId,
+                                  const char *context);
 
 extern bool check_generic_type_consistency(Oid *actual_arg_types,
                                           Oid *declared_arg_types,
index 3bd369e3c7041fe2a3772aa0fcba332839ae6b36..2b1a1fad4b9734f74ff9008efbc89c74a63e53cd 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_func.h,v 1.44 2003/04/08 23:20:04 tgl Exp $
+ * $Id: parse_func.h,v 1.45 2003/04/29 22:13:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,7 @@
 
 #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
@@ -49,7 +50,8 @@ extern FuncDetailCode func_get_detail(List *funcname, List *fargs,
 
 extern bool typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId);
 
-extern void make_fn_arguments(List *fargs,
+extern void make_fn_arguments(ParseState *pstate,
+                             List *fargs,
                              Oid *actual_arg_types,
                              Oid *declared_arg_types);
 
index 12dcaccbefd90d8f2634ab70b96414981b6d2558..1f52963e5c018b654dd19bbe3885b51ce35cec7d 100644 (file)
@@ -1,12 +1,13 @@
 /*-------------------------------------------------------------------------
  *
  * parse_node.h
+ *     Internal definitions for parser
  *
  *
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_node.h,v 1.34 2003/04/08 23:20:04 tgl Exp $
+ * $Id: parse_node.h,v 1.35 2003/04/29 22:13:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  * joinlist.  Note that an RTE that is present in p_namespace, but does not
  * have its inFromCl flag set, is accessible only with an explicit qualifier;
  * lookups of unqualified column names should ignore it.
+ *
+ * p_paramtypes: an array of p_numparams type OIDs for $n parameter symbols
+ * (zeroth entry in array corresponds to $1).  If p_variableparams is true, the
+ * set of param types is not predetermined; in that case, a zero array entry
+ * means that parameter number hasn't been seen, and UNKNOWNOID means the
+ * parameter has been used but its type is not yet known.  NOTE: in a stack
+ * of ParseStates, only the topmost ParseState contains paramtype info; but
+ * we copy the p_variableparams flag down to the child nodes for speed in
+ * coerce_type.
  */
 typedef struct ParseState
 {
@@ -40,9 +50,12 @@ typedef struct ParseState
    List       *p_joinlist;     /* join items so far (will become FromExpr
                                 * node's fromlist) */
    List       *p_namespace;    /* current lookup namespace (join items) */
-   int         p_last_resno;   /* last targetlist resno assigned */
+   Oid        *p_paramtypes;   /* OIDs of types for $n parameter symbols */
+   int         p_numparams;    /* allocated size of p_paramtypes[] */
+   int         p_next_resno;   /* next targetlist resno to assign */
    List       *p_forUpdate;    /* FOR UPDATE clause, if any (see gram.y) */
    Node       *p_value_substitute; /* what to replace VALUE with, if any */
+   bool        p_variableparams;
    bool        p_hasAggs;
    bool        p_hasSubLinks;
    bool        p_is_insert;
index 2cde7189ddafea945b2537912631d39a69068580..6d2268bf5573529840c8a13d77f5009841039343 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_oper.h,v 1.24 2003/04/08 23:20:04 tgl Exp $
+ * $Id: parse_oper.h,v 1.25 2003/04/29 22:13:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -15,7 +15,8 @@
 #define PARSE_OPER_H
 
 #include "access/htup.h"
-#include "nodes/parsenodes.h"
+#include "parser/parse_node.h"
+
 
 typedef HeapTuple Operator;
 
@@ -50,8 +51,10 @@ extern Oid   oprid(Operator op);
 extern Oid oprfuncid(Operator op);
 
 /* Build expression tree for an operator invocation */
-extern Expr *make_op(List *opname, Node *ltree, Node *rtree);
-extern Expr *make_op_expr(Operator op, Node *ltree, Node *rtree,
+extern Expr *make_op(ParseState *pstate, List *opname,
+                    Node *ltree, Node *rtree);
+extern Expr *make_op_expr(ParseState *pstate, Operator op,
+                         Node *ltree, Node *rtree,
                          Oid ltypeId, Oid rtypeId);
 
 #endif   /* PARSE_OPER_H */
index 42d82869f081c78a52fcfc7033bad26e0f0056b4..e5e5bddfafcbf569f819b82ccc96c06c047c2c6b 100644 (file)
@@ -1,21 +1,19 @@
 /*-------------------------------------------------------------------------
  *
  * parser.h
- *
+ *     Definitions for the "raw" parser (lex and yacc phases only)
  *
  *
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parser.h,v 1.14 2003/04/27 20:09:44 tgl Exp $
+ * $Id: parser.h,v 1.15 2003/04/29 22:13:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef PARSER_H
 #define PARSER_H
 
-#include "parser/parse_node.h"
-
-extern List *parser(const char *str, Oid *typev, int nargs);
+extern List *raw_parser(const char *str);
 
 #endif   /* PARSER_H */
index 4235d6d257f4273adead6cec18215b97fa7c8c0f..b81df05320cd106a6f423a908b4ced14a4876033 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: tcopprot.h,v 1.54 2003/04/27 20:09:44 tgl Exp $
+ * $Id: tcopprot.h,v 1.55 2003/04/29 22:13:11 tgl Exp $
  *
  * OLD COMMENTS
  *   This file was created so that other c files could get the two
@@ -35,14 +35,12 @@ extern DLLIMPORT const char *debug_query_string;
 
 #ifndef BOOTSTRAP_INCLUDE
 
-extern List *pg_parse_query(const char *query_string, Oid *typev, int nargs);
-extern List *pg_analyze_and_rewrite(Node *parsetree);
+extern List *pg_parse_query(const char *query_string);
+extern List *pg_analyze_and_rewrite(Node *parsetree,
+                                   Oid *paramTypes, int numParams);
 extern List *pg_parse_and_rewrite(const char *query_string,
-                    Oid *typev, int nargs);
+                    Oid *paramTypes, int numParams);
 extern Plan *pg_plan_query(Query *querytree);
-extern void pg_exec_query_string(const char *query_string,
-                    CommandDest dest,
-                    MemoryContext parse_context);
 
 #endif   /* BOOTSTRAP_INCLUDE */