Commit aa282d44 authored by Tom Lane's avatar Tom Lane

Infrastructure for deducing Param types from context, in the same way

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.
parent 19141f55
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * INTERFACE ROUTINES
...@@ -1592,7 +1592,7 @@ AddRelationRawConstraints(Relation rel, ...@@ -1592,7 +1592,7 @@ AddRelationRawConstraints(Relation rel,
/* /*
* Make sure it yields a boolean result. * 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. * Make sure no outside relations are referred to.
...@@ -1743,7 +1743,7 @@ cookDefault(ParseState *pstate, ...@@ -1743,7 +1743,7 @@ cookDefault(ParseState *pstate,
{ {
Oid type_id = exprType(expr); Oid type_id = exprType(expr);
if (coerce_to_target_type(expr, type_id, if (coerce_to_target_type(pstate, expr, type_id,
atttypid, atttypmod, atttypid, atttypmod,
COERCION_ASSIGNMENT, COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST) == NULL) COERCE_IMPLICIT_CAST) == NULL)
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -124,7 +124,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt)
List *querytree_list, List *querytree_list,
*querytree_item; *querytree_item;
querytree_list = parse_analyze(parsetree, NULL); querytree_list = parse_analyze(parsetree, NULL, 0);
foreach(querytree_item, querytree_list) foreach(querytree_item, querytree_list)
{ {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -2852,7 +2852,7 @@ AlterTableAddCheckConstraint(Relation rel, Constraint *constr)
/* /*
* Make sure it yields a boolean result. * 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. * Make sure no outside relations are referred to.
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the * The "DefineFoo" routines take the parse tree and pick out the
...@@ -1601,7 +1601,7 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, ...@@ -1601,7 +1601,7 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid,
/* /*
* Make sure it yields a boolean result. * 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 * Make sure no outside relations are
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -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. * 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. * Do parse analysis and rule rewrite for each raw parsetree.
...@@ -1036,7 +1036,7 @@ _SPI_execute(const char *src, int tcount, _SPI_plan *plan) ...@@ -1036,7 +1036,7 @@ _SPI_execute(const char *src, int tcount, _SPI_plan *plan)
if (plan) if (plan)
plan->origCmdType = origCmdType; 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); query_list_list = lappend(query_list_list, query_list);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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, ...@@ -495,10 +495,13 @@ convert_sublink_opers(List *lefthand, List *operOids,
* Make the expression node. * Make the expression node.
* *
* Note: we use make_op_expr in case runtime type conversion * 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, result = lappend(result,
make_op_expr(tup, make_op_expr(NULL,
tup,
leftop, leftop,
rightop, rightop,
exprType(leftop), exprType(leftop),
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -418,7 +418,8 @@ generate_setop_tlist(List *colTypes, int flag,
} }
else else
{ {
expr = coerce_to_common_type(expr, expr = coerce_to_common_type(NULL, /* no UNKNOWNs here */
expr,
colType, colType,
"UNION/INTERSECT/EXCEPT"); "UNION/INTERSECT/EXCEPT");
colTypmod = -1; colTypmod = -1;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -1747,17 +1747,17 @@ inline_function(Oid funcid, Oid result_type, List *args, ...@@ -1747,17 +1747,17 @@ inline_function(Oid funcid, Oid result_type, List *args,
/* /*
* We just do parsing and parse analysis, not rewriting, because * We just do parsing and parse analysis, not rewriting, because
* rewriting will not affect SELECT-only queries, which is all that * rewriting will not affect table-free-SELECT-only queries, which is all
* we care about. Also, we can punt as soon as we detect more than * that we care about. Also, we can punt as soon as we detect more than
* one command in the function body. * one command in the function body.
*/ */
raw_parsetree_list = pg_parse_query(src, raw_parsetree_list = pg_parse_query(src);
funcform->proargtypes,
funcform->pronargs);
if (length(raw_parsetree_list) != 1) if (length(raw_parsetree_list) != 1)
goto fail; 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) if (length(querytree_list) != 1)
goto fail; goto fail;
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -54,7 +54,7 @@ static RangeTblRef *transformRangeFunction(ParseState *pstate,
RangeFunction *r); RangeFunction *r);
static Node *transformFromClauseItem(ParseState *pstate, Node *n, static Node *transformFromClauseItem(ParseState *pstate, Node *n,
List **containedRels); List **containedRels);
static Node *buildMergedJoinVar(JoinType jointype, static Node *buildMergedJoinVar(ParseState *pstate, JoinType jointype,
Var *l_colvar, Var *r_colvar); Var *l_colvar, Var *r_colvar);
static TargetEntry *findTargetlistEntry(ParseState *pstate, Node *node, static TargetEntry *findTargetlistEntry(ParseState *pstate, Node *node,
List *tlist, int clause); List *tlist, int clause);
...@@ -284,7 +284,7 @@ transformJoinUsingClause(ParseState *pstate, List *leftVars, List *rightVars) ...@@ -284,7 +284,7 @@ transformJoinUsingClause(ParseState *pstate, List *leftVars, List *rightVars)
*/ */
result = transformExpr(pstate, result); result = transformExpr(pstate, result);
result = coerce_to_boolean(result, "JOIN/USING"); result = coerce_to_boolean(pstate, result, "JOIN/USING");
return result; return result;
} /* transformJoinUsingClause() */ } /* transformJoinUsingClause() */
...@@ -318,7 +318,7 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j, ...@@ -318,7 +318,7 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j,
/* This part is just like transformWhereClause() */ /* This part is just like transformWhereClause() */
result = transformExpr(pstate, j->quals); 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; pstate->p_namespace = save_namespace;
...@@ -398,7 +398,7 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r) ...@@ -398,7 +398,7 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
/* /*
* Analyze and transform the subquery. * 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 * Check that we got something reasonable. Some of these conditions
...@@ -759,7 +759,8 @@ transformFromClauseItem(ParseState *pstate, Node *n, List **containedRels) ...@@ -759,7 +759,8 @@ transformFromClauseItem(ParseState *pstate, Node *n, List **containedRels)
res_colnames = lappend(res_colnames, lfirst(ucol)); res_colnames = lappend(res_colnames, lfirst(ucol));
res_colvars = lappend(res_colvars, res_colvars = lappend(res_colvars,
buildMergedJoinVar(j->jointype, buildMergedJoinVar(pstate,
j->jointype,
l_colvar, l_colvar,
r_colvar)); r_colvar));
} }
...@@ -836,7 +837,8 @@ transformFromClauseItem(ParseState *pstate, Node *n, List **containedRels) ...@@ -836,7 +837,8 @@ transformFromClauseItem(ParseState *pstate, Node *n, List **containedRels)
* generate a suitable replacement expression for a merged join column * generate a suitable replacement expression for a merged join column
*/ */
static Node * static Node *
buildMergedJoinVar(JoinType jointype, Var *l_colvar, Var *r_colvar) buildMergedJoinVar(ParseState *pstate, JoinType jointype,
Var *l_colvar, Var *r_colvar)
{ {
Oid outcoltype; Oid outcoltype;
int32 outcoltypmod; int32 outcoltypmod;
...@@ -869,7 +871,7 @@ buildMergedJoinVar(JoinType jointype, Var *l_colvar, Var *r_colvar) ...@@ -869,7 +871,7 @@ buildMergedJoinVar(JoinType jointype, Var *l_colvar, Var *r_colvar)
* typmod is not same as input. * typmod is not same as input.
*/ */
if (l_colvar->vartype != outcoltype) 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, outcoltype,
COERCION_IMPLICIT, COERCE_IMPLICIT_CAST); COERCION_IMPLICIT, COERCE_IMPLICIT_CAST);
else if (l_colvar->vartypmod != outcoltypmod) else if (l_colvar->vartypmod != outcoltypmod)
...@@ -880,7 +882,7 @@ buildMergedJoinVar(JoinType jointype, Var *l_colvar, Var *r_colvar) ...@@ -880,7 +882,7 @@ buildMergedJoinVar(JoinType jointype, Var *l_colvar, Var *r_colvar)
l_node = (Node *) l_colvar; l_node = (Node *) l_colvar;
if (r_colvar->vartype != outcoltype) 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, outcoltype,
COERCION_IMPLICIT, COERCE_IMPLICIT_CAST); COERCION_IMPLICIT, COERCE_IMPLICIT_CAST);
else if (r_colvar->vartypmod != outcoltypmod) else if (r_colvar->vartypmod != outcoltypmod)
...@@ -953,7 +955,7 @@ transformWhereClause(ParseState *pstate, Node *clause) ...@@ -953,7 +955,7 @@ transformWhereClause(ParseState *pstate, Node *clause)
qual = transformExpr(pstate, clause); qual = transformExpr(pstate, clause);
qual = coerce_to_boolean(qual, "WHERE"); qual = coerce_to_boolean(pstate, qual, "WHERE");
return qual; return qual;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 @@ ...@@ -17,6 +17,7 @@
#include "catalog/pg_cast.h" #include "catalog/pg_cast.h"
#include "catalog/pg_proc.h" #include "catalog/pg_proc.h"
#include "nodes/makefuncs.h" #include "nodes/makefuncs.h"
#include "nodes/params.h"
#include "optimizer/clauses.h" #include "optimizer/clauses.h"
#include "parser/parse_coerce.h" #include "parser/parse_coerce.h"
#include "parser/parse_expr.h" #include "parser/parse_expr.h"
...@@ -49,6 +50,7 @@ static Node *build_func_call(Oid funcid, Oid rettype, List *args, ...@@ -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, * conversion is not possible. (We do this, rather than elog'ing directly,
* so that callers can generate custom error messages indicating context.) * 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) * expr - input expression tree (already transformed by transformExpr)
* exprtype - result type of expr * exprtype - result type of expr
* targettype - desired result type * targettype - desired result type
...@@ -56,13 +58,13 @@ static Node *build_func_call(Oid funcid, Oid rettype, List *args, ...@@ -56,13 +58,13 @@ static Node *build_func_call(Oid funcid, Oid rettype, List *args,
* ccontext, cformat - context indicators to control coercions * ccontext, cformat - context indicators to control coercions
*/ */
Node * Node *
coerce_to_target_type(Node *expr, Oid exprtype, coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype,
Oid targettype, int32 targettypmod, Oid targettype, int32 targettypmod,
CoercionContext ccontext, CoercionContext ccontext,
CoercionForm cformat) CoercionForm cformat)
{ {
if (can_coerce_type(1, &exprtype, &targettype, ccontext)) if (can_coerce_type(1, &exprtype, &targettype, ccontext))
expr = coerce_type(expr, exprtype, targettype, expr = coerce_type(pstate, expr, exprtype, targettype,
ccontext, cformat); ccontext, cformat);
/* /*
* String hacks to get transparent conversions for char and varchar: * String hacks to get transparent conversions for char and varchar:
...@@ -79,7 +81,7 @@ coerce_to_target_type(Node *expr, Oid exprtype, ...@@ -79,7 +81,7 @@ coerce_to_target_type(Node *expr, Oid exprtype,
if (can_coerce_type(1, &exprtype, &text_id, ccontext)) 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); ccontext, cformat);
/* Need a RelabelType if no typmod coercion is performed */ /* Need a RelabelType if no typmod coercion is performed */
if (targettypmod < 0) if (targettypmod < 0)
...@@ -117,9 +119,14 @@ coerce_to_target_type(Node *expr, Oid exprtype, ...@@ -117,9 +119,14 @@ coerce_to_target_type(Node *expr, Oid exprtype,
* call coerce_type_typmod as well, if a typmod constraint is wanted. * 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 * (But if the target type is a domain, it may internally contain a
* typmod constraint, which will be applied inside coerce_to_domain.) * 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 * Node *
coerce_type(Node *node, Oid inputTypeId, Oid targetTypeId, coerce_type(ParseState *pstate, Node *node,
Oid inputTypeId, Oid targetTypeId,
CoercionContext ccontext, CoercionForm cformat) CoercionContext ccontext, CoercionForm cformat)
{ {
Node *result; Node *result;
...@@ -129,9 +136,9 @@ coerce_type(Node *node, Oid inputTypeId, Oid targetTypeId, ...@@ -129,9 +136,9 @@ coerce_type(Node *node, Oid inputTypeId, Oid targetTypeId,
node == NULL) node == NULL)
{ {
/* no conversion needed */ /* 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. * Input is a string constant with previously undetermined type.
...@@ -187,17 +194,62 @@ coerce_type(Node *node, Oid inputTypeId, Oid targetTypeId, ...@@ -187,17 +194,62 @@ coerce_type(Node *node, Oid inputTypeId, Oid targetTypeId,
cformat); cformat);
ReleaseSysCache(targetType); ReleaseSysCache(targetType);
return result;
} }
else if (targetTypeId == ANYOID || if (inputTypeId == UNKNOWNOID && IsA(node, Param) &&
targetTypeId == ANYARRAYOID || ((Param *) node)->paramkind == PARAM_NUM &&
targetTypeId == ANYELEMENTOID) 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 */ /* assume can_coerce_type verified that implicit coercion is okay */
/* NB: we do NOT want a RelabelType here */ /* NB: we do NOT want a RelabelType here */
result = node; return node;
} }
else if (find_coercion_pathway(targetTypeId, inputTypeId, ccontext, if (find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
&funcId)) &funcId))
{ {
if (OidIsValid(funcId)) if (OidIsValid(funcId))
{ {
...@@ -247,27 +299,23 @@ coerce_type(Node *node, Oid inputTypeId, Oid targetTypeId, ...@@ -247,27 +299,23 @@ coerce_type(Node *node, Oid inputTypeId, Oid targetTypeId,
cformat); cformat);
} }
} }
return result;
} }
else if (typeInheritsFrom(inputTypeId, targetTypeId)) if (typeInheritsFrom(inputTypeId, targetTypeId))
{ {
/* /*
* Input class type is a subclass of target, so nothing to do --- * Input class type is a subclass of target, so nothing to do ---
* except relabel the type. This is binary compatibility for * except relabel the type. This is binary compatibility for
* complex types. * complex types.
*/ */
result = (Node *) makeRelabelType((Expr *) node, return (Node *) makeRelabelType((Expr *) node,
targetTypeId, -1, targetTypeId, -1,
cformat); cformat);
} }
else /* If we get here, caller blew it */
{ elog(ERROR, "coerce_type: no conversion function from %s to %s",
/* If we get here, caller blew it */ format_type_be(inputTypeId), format_type_be(targetTypeId));
elog(ERROR, "coerce_type: no conversion function from %s to %s", return NULL; /* keep compiler quiet */
format_type_be(inputTypeId), format_type_be(targetTypeId));
result = NULL; /* keep compiler quiet */
}
return result;
} }
...@@ -484,15 +532,19 @@ coerce_type_typmod(Node *node, Oid targetTypeId, int32 targetTypMod, ...@@ -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. * (AND, OR, NOT, etc). Also check that input is not a set.
* *
* Returns the possibly-transformed node tree. * Returns the possibly-transformed node tree.
*
* As with coerce_type, pstate may be NULL if no special unknown-Param
* processing is wanted.
*/ */
Node * Node *
coerce_to_boolean(Node *node, const char *constructName) coerce_to_boolean(ParseState *pstate, Node *node,
const char *constructName)
{ {
Oid inputTypeId = exprType(node); Oid inputTypeId = exprType(node);
if (inputTypeId != BOOLOID) if (inputTypeId != BOOLOID)
{ {
node = coerce_to_target_type(node, inputTypeId, node = coerce_to_target_type(pstate, node, inputTypeId,
BOOLOID, -1, BOOLOID, -1,
COERCION_ASSIGNMENT, COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST); COERCE_IMPLICIT_CAST);
...@@ -594,16 +646,20 @@ select_common_type(List *typeids, const char *context) ...@@ -594,16 +646,20 @@ select_common_type(List *typeids, const char *context)
* This is used following select_common_type() to coerce the individual * This is used following select_common_type() to coerce the individual
* expressions to the desired type. 'context' is a phrase to use in the * expressions to the desired type. 'context' is a phrase to use in the
* error message if we fail to coerce. * error message if we fail to coerce.
*
* As with coerce_type, pstate may be NULL if no special unknown-Param
* processing is wanted.
*/ */
Node * 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); Oid inputTypeId = exprType(node);
if (inputTypeId == targetTypeId) if (inputTypeId == targetTypeId)
return node; /* no work */ return node; /* no work */
if (can_coerce_type(1, &inputTypeId, &targetTypeId, COERCION_IMPLICIT)) 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); COERCION_IMPLICIT, COERCE_IMPLICIT_CAST);
else else
elog(ERROR, "%s unable to convert to type %s", elog(ERROR, "%s unable to convert to type %s",
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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; ...@@ -39,7 +39,8 @@ static int expr_depth_counter = 0;
bool Transform_null_equals = false; 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 *transformColumnRef(ParseState *pstate, ColumnRef *cref);
static Node *transformIndirection(ParseState *pstate, Node *basenode, static Node *transformIndirection(ParseState *pstate, Node *basenode,
List *indirection); List *indirection);
...@@ -112,17 +113,54 @@ transformExpr(ParseState *pstate, Node *expr) ...@@ -112,17 +113,54 @@ transformExpr(ParseState *pstate, Node *expr)
{ {
ParamRef *pref = (ParamRef *) expr; ParamRef *pref = (ParamRef *) expr;
int paramno = pref->number; int paramno = pref->number;
Oid paramtyp = param_type(paramno); ParseState *toppstate;
Param *param; Param *param;
List *fields; 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 = makeNode(Param);
param->paramkind = PARAM_NUM; param->paramkind = PARAM_NUM;
param->paramid = (AttrNumber) paramno; param->paramid = (AttrNumber) paramno;
param->paramtype = paramtyp; param->paramtype = toppstate->p_paramtypes[paramno-1];
result = (Node *) param; result = (Node *) param;
/* handle qualification, if any */ /* handle qualification, if any */
foreach(fields, pref->fields) foreach(fields, pref->fields)
{ {
...@@ -143,7 +181,8 @@ transformExpr(ParseState *pstate, Node *expr) ...@@ -143,7 +181,8 @@ transformExpr(ParseState *pstate, Node *expr)
result = (Node *) make_const(val); result = (Node *) make_const(val);
if (con->typename != NULL) if (con->typename != NULL)
result = typecast_expression(result, con->typename); result = typecast_expression(pstate, result,
con->typename);
break; break;
} }
case T_ExprFieldSelect: case T_ExprFieldSelect:
...@@ -170,7 +209,7 @@ transformExpr(ParseState *pstate, Node *expr) ...@@ -170,7 +209,7 @@ transformExpr(ParseState *pstate, Node *expr)
TypeCast *tc = (TypeCast *) expr; TypeCast *tc = (TypeCast *) expr;
Node *arg = transformExpr(pstate, tc->arg); Node *arg = transformExpr(pstate, tc->arg);
result = typecast_expression(arg, tc->typename); result = typecast_expression(pstate, arg, tc->typename);
break; break;
} }
case T_A_Expr: case T_A_Expr:
...@@ -212,7 +251,8 @@ transformExpr(ParseState *pstate, Node *expr) ...@@ -212,7 +251,8 @@ transformExpr(ParseState *pstate, Node *expr)
Node *rexpr = transformExpr(pstate, Node *rexpr = transformExpr(pstate,
a->rexpr); a->rexpr);
result = (Node *) make_op(a->name, result = (Node *) make_op(pstate,
a->name,
lexpr, lexpr,
rexpr); rexpr);
} }
...@@ -225,8 +265,8 @@ transformExpr(ParseState *pstate, Node *expr) ...@@ -225,8 +265,8 @@ transformExpr(ParseState *pstate, Node *expr)
Node *rexpr = transformExpr(pstate, Node *rexpr = transformExpr(pstate,
a->rexpr); a->rexpr);
lexpr = coerce_to_boolean(lexpr, "AND"); lexpr = coerce_to_boolean(pstate, lexpr, "AND");
rexpr = coerce_to_boolean(rexpr, "AND"); rexpr = coerce_to_boolean(pstate, rexpr, "AND");
result = (Node *) makeBoolExpr(AND_EXPR, result = (Node *) makeBoolExpr(AND_EXPR,
makeList2(lexpr, makeList2(lexpr,
...@@ -240,8 +280,8 @@ transformExpr(ParseState *pstate, Node *expr) ...@@ -240,8 +280,8 @@ transformExpr(ParseState *pstate, Node *expr)
Node *rexpr = transformExpr(pstate, Node *rexpr = transformExpr(pstate,
a->rexpr); a->rexpr);
lexpr = coerce_to_boolean(lexpr, "OR"); lexpr = coerce_to_boolean(pstate, lexpr, "OR");
rexpr = coerce_to_boolean(rexpr, "OR"); rexpr = coerce_to_boolean(pstate, rexpr, "OR");
result = (Node *) makeBoolExpr(OR_EXPR, result = (Node *) makeBoolExpr(OR_EXPR,
makeList2(lexpr, makeList2(lexpr,
...@@ -253,7 +293,7 @@ transformExpr(ParseState *pstate, Node *expr) ...@@ -253,7 +293,7 @@ transformExpr(ParseState *pstate, Node *expr)
Node *rexpr = transformExpr(pstate, Node *rexpr = transformExpr(pstate,
a->rexpr); a->rexpr);
rexpr = coerce_to_boolean(rexpr, "NOT"); rexpr = coerce_to_boolean(pstate, rexpr, "NOT");
result = (Node *) makeBoolExpr(NOT_EXPR, result = (Node *) makeBoolExpr(NOT_EXPR,
makeList1(rexpr)); makeList1(rexpr));
...@@ -266,7 +306,8 @@ transformExpr(ParseState *pstate, Node *expr) ...@@ -266,7 +306,8 @@ transformExpr(ParseState *pstate, Node *expr)
Node *rexpr = transformExpr(pstate, Node *rexpr = transformExpr(pstate,
a->rexpr); a->rexpr);
result = (Node *) make_op(a->name, result = (Node *) make_op(pstate,
a->name,
lexpr, lexpr,
rexpr); rexpr);
if (((OpExpr *) result)->opresulttype != BOOLOID) if (((OpExpr *) result)->opresulttype != BOOLOID)
...@@ -284,7 +325,8 @@ transformExpr(ParseState *pstate, Node *expr) ...@@ -284,7 +325,8 @@ transformExpr(ParseState *pstate, Node *expr)
Node *rexpr = transformExpr(pstate, Node *rexpr = transformExpr(pstate,
a->rexpr); a->rexpr);
result = (Node *) make_op(a->name, result = (Node *) make_op(pstate,
a->name,
lexpr, lexpr,
rexpr); rexpr);
if (((OpExpr *) result)->opresulttype != BOOLOID) if (((OpExpr *) result)->opresulttype != BOOLOID)
...@@ -375,7 +417,7 @@ transformExpr(ParseState *pstate, Node *expr) ...@@ -375,7 +417,7 @@ transformExpr(ParseState *pstate, Node *expr)
break; break;
} }
pstate->p_hasSubLinks = true; pstate->p_hasSubLinks = true;
qtrees = parse_analyze(sublink->subselect, pstate); qtrees = parse_sub_analyze(sublink->subselect, pstate);
if (length(qtrees) != 1) if (length(qtrees) != 1)
elog(ERROR, "Bad query in subselect"); elog(ERROR, "Bad query in subselect");
qtree = (Query *) lfirst(qtrees); qtree = (Query *) lfirst(qtrees);
...@@ -523,7 +565,7 @@ transformExpr(ParseState *pstate, Node *expr) ...@@ -523,7 +565,7 @@ transformExpr(ParseState *pstate, Node *expr)
if (needNot) if (needNot)
{ {
expr = coerce_to_boolean(expr, "NOT"); expr = coerce_to_boolean(pstate, expr, "NOT");
expr = (Node *) makeBoolExpr(NOT_EXPR, expr = (Node *) makeBoolExpr(NOT_EXPR,
makeList1(expr)); makeList1(expr));
} }
...@@ -561,7 +603,8 @@ transformExpr(ParseState *pstate, Node *expr) ...@@ -561,7 +603,8 @@ transformExpr(ParseState *pstate, Node *expr)
} }
neww->expr = (Expr *) transformExpr(pstate, warg); 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"); "CASE/WHEN");
/* /*
...@@ -615,7 +658,8 @@ transformExpr(ParseState *pstate, Node *expr) ...@@ -615,7 +658,8 @@ transformExpr(ParseState *pstate, Node *expr)
/* Convert default result clause, if necessary */ /* Convert default result clause, if necessary */
newc->defresult = (Expr *) newc->defresult = (Expr *)
coerce_to_common_type((Node *) newc->defresult, coerce_to_common_type(pstate,
(Node *) newc->defresult,
ptype, ptype,
"CASE/ELSE"); "CASE/ELSE");
...@@ -625,7 +669,8 @@ transformExpr(ParseState *pstate, Node *expr) ...@@ -625,7 +669,8 @@ transformExpr(ParseState *pstate, Node *expr)
CaseWhen *w = (CaseWhen *) lfirst(args); CaseWhen *w = (CaseWhen *) lfirst(args);
w->result = (Expr *) w->result = (Expr *)
coerce_to_common_type((Node *) w->result, coerce_to_common_type(pstate,
(Node *) w->result,
ptype, ptype,
"CASE/WHEN"); "CASE/WHEN");
} }
...@@ -666,7 +711,9 @@ transformExpr(ParseState *pstate, Node *expr) ...@@ -666,7 +711,9 @@ transformExpr(ParseState *pstate, Node *expr)
Node *e = (Node *) lfirst(element); Node *e = (Node *) lfirst(element);
Node *newe; 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); newcoercedelems = lappend(newcoercedelems, newe);
} }
...@@ -753,7 +800,8 @@ transformExpr(ParseState *pstate, Node *expr) ...@@ -753,7 +800,8 @@ transformExpr(ParseState *pstate, Node *expr)
Node *e = (Node *) lfirst(args); Node *e = (Node *) lfirst(args);
Node *newe; Node *newe;
newe = coerce_to_common_type(e, newc->coalescetype, newe = coerce_to_common_type(pstate, e,
newc->coalescetype,
"COALESCE"); "COALESCE");
newcoercedargs = lappend(newcoercedargs, newe); newcoercedargs = lappend(newcoercedargs, newe);
} }
...@@ -806,7 +854,9 @@ transformExpr(ParseState *pstate, Node *expr) ...@@ -806,7 +854,9 @@ transformExpr(ParseState *pstate, Node *expr)
b->arg = (Expr *) transformExpr(pstate, (Node *) b->arg); 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; result = expr;
break; break;
...@@ -1404,7 +1454,7 @@ exprIsLengthCoercion(Node *expr, int32 *coercedTypmod) ...@@ -1404,7 +1454,7 @@ exprIsLengthCoercion(Node *expr, int32 *coercedTypmod)
* the type name and then apply any necessary coercion function(s). * the type name and then apply any necessary coercion function(s).
*/ */
static Node * static Node *
typecast_expression(Node *expr, TypeName *typename) typecast_expression(ParseState *pstate, Node *expr, TypeName *typename)
{ {
Oid inputType = exprType(expr); Oid inputType = exprType(expr);
Oid targetType; Oid targetType;
...@@ -1414,7 +1464,7 @@ typecast_expression(Node *expr, TypeName *typename) ...@@ -1414,7 +1464,7 @@ typecast_expression(Node *expr, TypeName *typename)
if (inputType == InvalidOid) if (inputType == InvalidOid)
return expr; /* do nothing if NULL input */ 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, targetType, typename->typmod,
COERCION_EXPLICIT, COERCION_EXPLICIT,
COERCE_EXPLICIT_CAST); COERCE_EXPLICIT_CAST);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -253,7 +253,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
* We can do it as a trivial coercion. coerce_type can handle * We can do it as a trivial coercion. coerce_type can handle
* these cases, so why duplicate code... * 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); COERCION_EXPLICIT, COERCE_EXPLICIT_CALL);
} }
else if (fdresult == FUNCDETAIL_NORMAL) else if (fdresult == FUNCDETAIL_NORMAL)
...@@ -316,7 +317,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, ...@@ -316,7 +317,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
rettype); rettype);
/* perform the necessary typecasting of arguments */ /* 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 */ /* build the appropriate output structure */
if (fdresult == FUNCDETAIL_NORMAL) if (fdresult == FUNCDETAIL_NORMAL)
...@@ -1145,9 +1146,13 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId) ...@@ -1145,9 +1146,13 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
* allowed. * allowed.
* *
* Caution: given argument list is modified in-place. * 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 void
make_fn_arguments(List *fargs, make_fn_arguments(ParseState *pstate,
List *fargs,
Oid *actual_arg_types, Oid *actual_arg_types,
Oid *declared_arg_types) Oid *declared_arg_types)
{ {
...@@ -1159,7 +1164,8 @@ make_fn_arguments(List *fargs, ...@@ -1159,7 +1164,8 @@ make_fn_arguments(List *fargs,
/* types don't match? then force coercion using a function call... */ /* types don't match? then force coercion using a function call... */
if (actual_arg_types[i] != declared_arg_types[i]) 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], actual_arg_types[i],
declared_arg_types[i], declared_arg_types[i],
COERCION_IMPLICIT, COERCION_IMPLICIT,
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -39,7 +39,12 @@ make_parsestate(ParseState *parentParseState)
pstate = palloc0(sizeof(ParseState)); pstate = palloc0(sizeof(ParseState));
pstate->parentParseState = parentParseState; 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; return pstate;
} }
...@@ -166,7 +171,8 @@ transformArraySubscripts(ParseState *pstate, ...@@ -166,7 +171,8 @@ transformArraySubscripts(ParseState *pstate,
{ {
subexpr = transformExpr(pstate, ai->lidx); subexpr = transformExpr(pstate, ai->lidx);
/* If it's not int4 already, try to coerce */ /* 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, INT4OID, -1,
COERCION_ASSIGNMENT, COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST); COERCE_IMPLICIT_CAST);
...@@ -186,7 +192,8 @@ transformArraySubscripts(ParseState *pstate, ...@@ -186,7 +192,8 @@ transformArraySubscripts(ParseState *pstate,
} }
subexpr = transformExpr(pstate, ai->uidx); subexpr = transformExpr(pstate, ai->uidx);
/* If it's not int4 already, try to coerce */ /* 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, INT4OID, -1,
COERCION_ASSIGNMENT, COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST); COERCE_IMPLICIT_CAST);
...@@ -205,7 +212,8 @@ transformArraySubscripts(ParseState *pstate, ...@@ -205,7 +212,8 @@ transformArraySubscripts(ParseState *pstate,
if (typesource != InvalidOid) if (typesource != InvalidOid)
{ {
assignFrom = coerce_to_target_type(assignFrom, typesource, assignFrom = coerce_to_target_type(pstate,
assignFrom, typesource,
typeneeded, arrayTypMod, typeneeded, arrayTypMod,
COERCION_ASSIGNMENT, COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST); COERCE_IMPLICIT_CAST);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -1019,9 +1019,12 @@ unary_op_error(List *op, Oid arg, bool is_left_op)
* *
* Transform operator expression ensuring type compatibility. * Transform operator expression ensuring type compatibility.
* This is where some type conversion happens. * This is where some type conversion happens.
*
* As with coerce_type, pstate may be NULL if no special unknown-Param
* processing is wanted.
*/ */
Expr * Expr *
make_op(List *opname, Node *ltree, Node *rtree) make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree)
{ {
Oid ltypeId, Oid ltypeId,
rtypeId; rtypeId;
...@@ -1052,7 +1055,7 @@ make_op(List *opname, Node *ltree, Node *rtree) ...@@ -1052,7 +1055,7 @@ make_op(List *opname, Node *ltree, Node *rtree)
} }
/* Do typecasting and build the expression tree */ /* 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); ReleaseSysCache(tup);
...@@ -1063,9 +1066,13 @@ make_op(List *opname, Node *ltree, Node *rtree) ...@@ -1063,9 +1066,13 @@ make_op(List *opname, Node *ltree, Node *rtree)
/* /*
* make_op_expr() * make_op_expr()
* Build operator expression using an already-looked-up operator. * 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 * 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) Oid ltypeId, Oid rtypeId)
{ {
Form_pg_operator opform = (Form_pg_operator) GETSTRUCT(op); Form_pg_operator opform = (Form_pg_operator) GETSTRUCT(op);
...@@ -1114,7 +1121,7 @@ make_op_expr(Operator op, Node *ltree, Node *rtree, ...@@ -1114,7 +1121,7 @@ make_op_expr(Operator op, Node *ltree, Node *rtree,
opform->oprresult); opform->oprresult);
/* perform the necessary typecasting of arguments */ /* 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 */ /* and build the expression node */
result = makeNode(OpExpr); result = makeNode(OpExpr);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -1447,7 +1447,7 @@ expandRelAttrs(ParseState *pstate, RangeTblEntry *rte)
Node *varnode = (Node *) lfirst(vars); Node *varnode = (Node *) lfirst(vars);
TargetEntry *te = makeNode(TargetEntry); TargetEntry *te = makeNode(TargetEntry);
te->resdom = makeResdom((AttrNumber) (pstate->p_last_resno)++, te->resdom = makeResdom((AttrNumber) pstate->p_next_resno++,
exprType(varnode), exprType(varnode),
exprTypmod(varnode), exprTypmod(varnode),
label, label,
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -73,7 +73,7 @@ transformTargetEntry(ParseState *pstate,
colname = FigureColname(node); colname = FigureColname(node);
} }
resnode = makeResdom((AttrNumber) pstate->p_last_resno++, resnode = makeResdom((AttrNumber) pstate->p_next_resno++,
type_id, type_id,
type_mod, type_mod,
colname, colname,
...@@ -290,7 +290,8 @@ updateTargetListEntry(ParseState *pstate, ...@@ -290,7 +290,8 @@ updateTargetListEntry(ParseState *pstate,
if (type_id != InvalidOid) if (type_id != InvalidOid)
{ {
tle->expr = (Expr *) tle->expr = (Expr *)
coerce_to_target_type((Node *) tle->expr, type_id, coerce_to_target_type(pstate,
(Node *) tle->expr, type_id,
attrtype, attrtypmod, attrtype, attrtypmod,
COERCION_ASSIGNMENT, COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST); COERCE_IMPLICIT_CAST);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -437,7 +437,7 @@ parseTypeString(const char *str, Oid *type_id, int32 *typmod)
initStringInfo(&buf); initStringInfo(&buf);
appendStringInfo(&buf, "SELECT (NULL::%s)", str); 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; * Make sure we got back exactly what we expected and no more;
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 @@ ...@@ -30,32 +30,27 @@
List *parsetree; /* result of parsing is left here */ 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 int lookahead_token; /* one-token lookahead */
static bool have_lookahead; /* lookahead_token set? */ static bool have_lookahead; /* lookahead_token set? */
/* /*
* parser * raw_parser
* Given a query in string form, and optionally info about * Given a query in string form, do lexical and grammatical analysis.
* parameter types, do lexical and syntactic analysis.
* *
* Returns a list of raw (un-analyzed) parse trees. * Returns a list of raw (un-analyzed) parse trees.
*/ */
List * List *
parser(const char *str, Oid *typev, int nargs) raw_parser(const char *str)
{ {
int yyresult; int yyresult;
parsetree = NIL; /* in case parser forgets to set it */ parsetree = NIL; /* in case grammar forgets to set it */
have_lookahead = false; have_lookahead = false;
scanner_init(str); scanner_init(str);
parser_init(); parser_init();
parse_expr_init(); parse_expr_init();
parser_param_set(typev, nargs);
yyresult = yyparse(); yyresult = yyparse();
...@@ -69,35 +64,6 @@ parser(const char *str, Oid *typev, int nargs) ...@@ -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). * Intermediate filter between parser and base lexer (base_yylex in scan.l).
* *
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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) ...@@ -498,7 +498,8 @@ build_column_default(Relation rel, int attrno)
*/ */
exprtype = exprType(expr); exprtype = exprType(expr);
expr = coerce_to_target_type(expr, exprtype, expr = coerce_to_target_type(NULL, /* no UNKNOWN params here */
expr, exprtype,
atttype, atttypmod, atttype, atttypmod,
COERCION_ASSIGNMENT, COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST); COERCE_IMPLICIT_CAST);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* this is the "main" module of the postgres backend and * this is the "main" module of the postgres backend and
...@@ -339,8 +339,8 @@ ReadCommand(StringInfo inBuf) ...@@ -339,8 +339,8 @@ ReadCommand(StringInfo inBuf)
*/ */
List * List *
pg_parse_and_rewrite(const char *query_string, /* string to execute */ pg_parse_and_rewrite(const char *query_string, /* string to execute */
Oid *typev, /* parameter types */ Oid *paramTypes, /* parameter types */
int nargs) /* number of parameters */ int numParams) /* number of parameters */
{ {
List *raw_parsetree_list; List *raw_parsetree_list;
List *querytree_list; List *querytree_list;
...@@ -349,7 +349,7 @@ pg_parse_and_rewrite(const char *query_string, /* string to execute */ ...@@ -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. * (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. * (2) Do parse analysis and rule rewrite.
...@@ -360,7 +360,9 @@ pg_parse_and_rewrite(const char *query_string, /* string to execute */ ...@@ -360,7 +360,9 @@ pg_parse_and_rewrite(const char *query_string, /* string to execute */
Node *parsetree = (Node *) lfirst(list_item); Node *parsetree = (Node *) lfirst(list_item);
querytree_list = nconc(querytree_list, querytree_list = nconc(querytree_list,
pg_analyze_and_rewrite(parsetree)); pg_analyze_and_rewrite(parsetree,
paramTypes,
numParams));
} }
return querytree_list; return querytree_list;
...@@ -380,7 +382,7 @@ pg_parse_and_rewrite(const char *query_string, /* string to execute */ ...@@ -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. * commands are not processed any further than the raw parse stage.
*/ */
List * List *
pg_parse_query(const char *query_string, Oid *typev, int nargs) pg_parse_query(const char *query_string)
{ {
List *raw_parsetree_list; List *raw_parsetree_list;
...@@ -390,7 +392,7 @@ pg_parse_query(const char *query_string, Oid *typev, int nargs) ...@@ -390,7 +392,7 @@ pg_parse_query(const char *query_string, Oid *typev, int nargs)
if (log_parser_stats) if (log_parser_stats)
ResetUsage(); ResetUsage();
raw_parsetree_list = parser(query_string, typev, nargs); raw_parsetree_list = raw_parser(query_string);
if (log_parser_stats) if (log_parser_stats)
ShowUsage("PARSER STATISTICS"); ShowUsage("PARSER STATISTICS");
...@@ -399,8 +401,8 @@ pg_parse_query(const char *query_string, Oid *typev, int nargs) ...@@ -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 * Given a raw parsetree (gram.y output), and optionally information about
* rule rewriting. * types of parameter symbols ($n), perform parse analysis and rule rewriting.
* *
* A list of Query nodes is returned, since either the analyzer or the * A list of Query nodes is returned, since either the analyzer or the
* rewriter might expand one query to several. * rewriter might expand one query to several.
...@@ -408,7 +410,7 @@ pg_parse_query(const char *query_string, Oid *typev, int nargs) ...@@ -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. * NOTE: for reasons mentioned above, this must be separate from raw parsing.
*/ */
List * List *
pg_analyze_and_rewrite(Node *parsetree) pg_analyze_and_rewrite(Node *parsetree, Oid *paramTypes, int numParams)
{ {
List *querytree_list; List *querytree_list;
List *list_item; List *list_item;
...@@ -421,7 +423,7 @@ pg_analyze_and_rewrite(Node *parsetree) ...@@ -421,7 +423,7 @@ pg_analyze_and_rewrite(Node *parsetree)
if (log_parser_stats) if (log_parser_stats)
ResetUsage(); ResetUsage();
querytree_list = parse_analyze(parsetree, NULL); querytree_list = parse_analyze(parsetree, paramTypes, numParams);
if (log_parser_stats) if (log_parser_stats)
{ {
...@@ -562,8 +564,7 @@ pg_plan_query(Query *querytree) ...@@ -562,8 +564,7 @@ pg_plan_query(Query *querytree)
* *
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static void
void
pg_exec_query_string(const char *query_string, /* string to execute */ pg_exec_query_string(const char *query_string, /* string to execute */
CommandDest dest, /* where results should go */ CommandDest dest, /* where results should go */
MemoryContext parse_context) /* context for MemoryContext parse_context) /* context for
...@@ -614,7 +615,7 @@ pg_exec_query_string(const char *query_string, /* string to execute */ ...@@ -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 * Do basic parsing of the query or queries (this should be safe even
* if we are in aborted transaction state!) * 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. * Switch back to execution context to enter the loop.
...@@ -710,7 +711,7 @@ pg_exec_query_string(const char *query_string, /* string to execute */ ...@@ -710,7 +711,7 @@ pg_exec_query_string(const char *query_string, /* string to execute */
*/ */
oldcontext = MemoryContextSwitchTo(parse_context); 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. * Switch back to execution context for planning and execution.
...@@ -1826,7 +1827,7 @@ PostgresMain(int argc, char *argv[], const char *username) ...@@ -1826,7 +1827,7 @@ PostgresMain(int argc, char *argv[], const char *username)
if (!IsUnderPostmaster) if (!IsUnderPostmaster)
{ {
puts("\nPOSTGRES backend interactive interface "); 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");
} }
/* /*
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -15,7 +15,11 @@ ...@@ -15,7 +15,11 @@
#include "parser/parse_node.h" #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 List *analyzeCreateSchemaStmt(CreateSchemaStmt *stmt);
extern void CheckSelectForUpdate(Query *qry); extern void CheckSelectForUpdate(Query *qry);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 @@ ...@@ -17,9 +17,8 @@
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
/* from parser.c */ /* from parser.c */
extern void parser_param_set(Oid *typev, int nargs);
extern Oid param_type(int t);
extern int yylex(void); extern int yylex(void);
/* from scan.l */ /* from scan.l */
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 @@ ...@@ -17,6 +17,7 @@
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "parser/parse_node.h" #include "parser/parse_node.h"
typedef enum CATEGORY typedef enum CATEGORY
{ {
INVALID_TYPE, INVALID_TYPE,
...@@ -38,22 +39,26 @@ extern bool IsBinaryCoercible(Oid srctype, Oid targettype); ...@@ -38,22 +39,26 @@ extern bool IsBinaryCoercible(Oid srctype, Oid targettype);
extern bool IsPreferredType(CATEGORY category, Oid type); extern bool IsPreferredType(CATEGORY category, Oid type);
extern CATEGORY TypeCategory(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, Oid targettype, int32 targettypmod,
CoercionContext ccontext, CoercionContext ccontext,
CoercionForm cformat); CoercionForm cformat);
extern bool can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids, extern bool can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
CoercionContext ccontext); 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); CoercionContext ccontext, CoercionForm cformat);
extern Node *coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId, extern Node *coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId,
CoercionForm cformat); 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 Oid select_common_type(List *typeids, const char *context);
extern Node *coerce_to_common_type(Node *node, Oid targetTypeId, extern Node *coerce_to_common_type(ParseState *pstate, Node *node,
const char *context); Oid targetTypeId,
const char *context);
extern bool check_generic_type_consistency(Oid *actual_arg_types, extern bool check_generic_type_consistency(Oid *actual_arg_types,
Oid *declared_arg_types, Oid *declared_arg_types,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 @@ ...@@ -16,6 +16,7 @@
#include "parser/parse_node.h" #include "parser/parse_node.h"
/* /*
* This structure is used to explore the inheritance hierarchy above * This structure is used to explore the inheritance hierarchy above
* nodes in the type tree in order to disambiguate among polymorphic * nodes in the type tree in order to disambiguate among polymorphic
...@@ -49,7 +50,8 @@ extern FuncDetailCode func_get_detail(List *funcname, List *fargs, ...@@ -49,7 +50,8 @@ extern FuncDetailCode func_get_detail(List *funcname, List *fargs,
extern bool typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId); 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 *actual_arg_types,
Oid *declared_arg_types); Oid *declared_arg_types);
......
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* parse_node.h * parse_node.h
* Internal definitions for parser
* *
* *
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -32,6 +33,15 @@ ...@@ -32,6 +33,15 @@
* joinlist. Note that an RTE that is present in p_namespace, but does not * 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; * have its inFromCl flag set, is accessible only with an explicit qualifier;
* lookups of unqualified column names should ignore it. * 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 typedef struct ParseState
{ {
...@@ -40,9 +50,12 @@ typedef struct ParseState ...@@ -40,9 +50,12 @@ typedef struct ParseState
List *p_joinlist; /* join items so far (will become FromExpr List *p_joinlist; /* join items so far (will become FromExpr
* node's fromlist) */ * node's fromlist) */
List *p_namespace; /* current lookup namespace (join items) */ 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) */ List *p_forUpdate; /* FOR UPDATE clause, if any (see gram.y) */
Node *p_value_substitute; /* what to replace VALUE with, if any */ Node *p_value_substitute; /* what to replace VALUE with, if any */
bool p_variableparams;
bool p_hasAggs; bool p_hasAggs;
bool p_hasSubLinks; bool p_hasSubLinks;
bool p_is_insert; bool p_is_insert;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 @@ ...@@ -15,7 +15,8 @@
#define PARSE_OPER_H #define PARSE_OPER_H
#include "access/htup.h" #include "access/htup.h"
#include "nodes/parsenodes.h" #include "parser/parse_node.h"
typedef HeapTuple Operator; typedef HeapTuple Operator;
...@@ -50,8 +51,10 @@ extern Oid oprid(Operator op); ...@@ -50,8 +51,10 @@ extern Oid oprid(Operator op);
extern Oid oprfuncid(Operator op); extern Oid oprfuncid(Operator op);
/* Build expression tree for an operator invocation */ /* Build expression tree for an operator invocation */
extern Expr *make_op(List *opname, Node *ltree, Node *rtree); extern Expr *make_op(ParseState *pstate, List *opname,
extern Expr *make_op_expr(Operator op, Node *ltree, Node *rtree, Node *ltree, Node *rtree);
extern Expr *make_op_expr(ParseState *pstate, Operator op,
Node *ltree, Node *rtree,
Oid ltypeId, Oid rtypeId); Oid ltypeId, Oid rtypeId);
#endif /* PARSE_OPER_H */ #endif /* PARSE_OPER_H */
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* parser.h * parser.h
* * Definitions for the "raw" parser (lex and yacc phases only)
* *
* *
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 #ifndef PARSER_H
#define PARSER_H #define PARSER_H
#include "parser/parse_node.h" extern List *raw_parser(const char *str);
extern List *parser(const char *str, Oid *typev, int nargs);
#endif /* PARSER_H */ #endif /* PARSER_H */
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 * OLD COMMENTS
* This file was created so that other c files could get the two * This file was created so that other c files could get the two
...@@ -35,14 +35,12 @@ extern DLLIMPORT const char *debug_query_string; ...@@ -35,14 +35,12 @@ extern DLLIMPORT const char *debug_query_string;
#ifndef BOOTSTRAP_INCLUDE #ifndef BOOTSTRAP_INCLUDE
extern List *pg_parse_query(const char *query_string, Oid *typev, int nargs); extern List *pg_parse_query(const char *query_string);
extern List *pg_analyze_and_rewrite(Node *parsetree); extern List *pg_analyze_and_rewrite(Node *parsetree,
Oid *paramTypes, int numParams);
extern List *pg_parse_and_rewrite(const char *query_string, 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 Plan *pg_plan_query(Query *querytree);
extern void pg_exec_query_string(const char *query_string,
CommandDest dest,
MemoryContext parse_context);
#endif /* BOOTSTRAP_INCLUDE */ #endif /* BOOTSTRAP_INCLUDE */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment