aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/analyze.c163
-rw-r--r--src/backend/parser/parse_clause.c22
-rw-r--r--src/backend/parser/parse_coerce.c116
-rw-r--r--src/backend/parser/parse_expr.c102
-rw-r--r--src/backend/parser/parse_func.c16
-rw-r--r--src/backend/parser/parse_node.c18
-rw-r--r--src/backend/parser/parse_oper.c17
-rw-r--r--src/backend/parser/parse_relation.c4
-rw-r--r--src/backend/parser/parse_target.c7
-rw-r--r--src/backend/parser/parse_type.c4
-rw-r--r--src/backend/parser/parser.c44
11 files changed, 340 insertions, 173 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 5dc3d82bea8..c2159a70e0e 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -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);
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index 2fd5811000a..1c8cb8bc0e3 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -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;
}
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index a4b739b0f7e..9dc0c7f1c19 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -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",
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 10702e9a269..429a9ac8c8a 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -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);
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index 7cbef965369..058b9aad73d 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -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,
diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c
index 700c4b158de..2f5775212cb 100644
--- a/src/backend/parser/parse_node.c
+++ b/src/backend/parser/parse_node.c
@@ -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);
diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c
index 3be29e64def..6238258ed2f 100644
--- a/src/backend/parser/parse_oper.c
+++ b/src/backend/parser/parse_oper.c
@@ -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);
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 4ae3bf23153..41fd98fc071 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -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,
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index e1be47b3ec5..dc8f241d45e 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -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);
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
index 85aeafacc59..d1a324dbf0a 100644
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -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;
diff --git a/src/backend/parser/parser.c b/src/backend/parser/parser.c
index 16745f7b370..37436d30079 100644
--- a/src/backend/parser/parser.c
+++ b/src/backend/parser/parser.c
@@ -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 $
*
*-------------------------------------------------------------------------
*/
@@ -30,32 +30,27 @@
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();
@@ -70,35 +65,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).
*
* The filter is needed because in some cases SQL92 requires more than one