summaryrefslogtreecommitdiff
path: root/src/backend/parser/analyze.c
diff options
context:
space:
mode:
authorTom Lane2009-10-31 01:41:31 +0000
committerTom Lane2009-10-31 01:41:31 +0000
commitfb5d05805b3f7658e47ad2c6a4631e497bb3f627 (patch)
tree74ee6327b45c313ac0ac21e92a3d61a52135cd2f /src/backend/parser/analyze.c
parent8442317beb8fb6f180880a977c03ccae4304df25 (diff)
Implement parser hooks for processing ColumnRef and ParamRef nodes, as per my
recent proposal. As proof of concept, remove knowledge of Params from the core parser, arranging for them to be handled entirely by parser hook functions. It turns out we need an additional hook for that --- I had forgotten about the code that handles inferring a parameter's type from context. This is a preliminary step towards letting plpgsql handle its variables through parser hooks. Additional work remains to be done to expose the facility through SPI, but I think this is all the changes needed in the core parser.
Diffstat (limited to 'src/backend/parser/analyze.c')
-rw-r--r--src/backend/parser/analyze.c72
1 files changed, 10 insertions, 62 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index c89c7c82a08..49ec8481846 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -17,7 +17,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.395 2009/10/28 14:55:43 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.396 2009/10/31 01:41:31 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -35,6 +35,7 @@
#include "parser/parse_coerce.h"
#include "parser/parse_cte.h"
#include "parser/parse_oper.h"
+#include "parser/parse_param.h"
#include "parser/parse_relation.h"
#include "parser/parse_target.h"
#include "parser/parsetree.h"
@@ -62,7 +63,6 @@ static Query *transformExplainStmt(ParseState *pstate,
ExplainStmt *stmt);
static void transformLockingClause(ParseState *pstate, Query *qry,
LockingClause *lc, bool pushedDown);
-static bool check_parameter_resolution_walker(Node *node, ParseState *pstate);
/*
@@ -86,9 +86,9 @@ parse_analyze(Node *parseTree, const char *sourceText,
Assert(sourceText != NULL); /* required as of 8.4 */
pstate->p_sourcetext = sourceText;
- pstate->p_paramtypes = paramTypes;
- pstate->p_numparams = numParams;
- pstate->p_variableparams = false;
+
+ if (numParams > 0)
+ parse_fixed_parameters(pstate, paramTypes, numParams);
query = transformStmt(pstate, parseTree);
@@ -114,18 +114,13 @@ parse_analyze_varparams(Node *parseTree, const char *sourceText,
Assert(sourceText != NULL); /* required as of 8.4 */
pstate->p_sourcetext = sourceText;
- pstate->p_paramtypes = *paramTypes;
- pstate->p_numparams = *numParams;
- pstate->p_variableparams = true;
+
+ parse_variable_parameters(pstate, paramTypes, numParams);
query = transformStmt(pstate, parseTree);
/* make sure all is well with parameter types */
- if (pstate->p_numparams > 0)
- check_parameter_resolution_walker((Node *) query, pstate);
-
- *paramTypes = pstate->p_paramtypes;
- *numParams = pstate->p_numparams;
+ check_variable_parameters(pstate, query);
free_parsestate(pstate);
@@ -1982,7 +1977,7 @@ transformDeclareCursorStmt(ParseState *pstate, DeclareCursorStmt *stmt)
*
* EXPLAIN is just like other utility statements in that we emit it as a
* CMD_UTILITY Query node with no transformation of the raw parse tree.
- * However, if p_variableparams is set, it could be that the client is
+ * However, if p_coerce_param_hook is set, it could be that the client is
* expecting us to resolve parameter types in something like
* EXPLAIN SELECT * FROM tab WHERE col = $1
* To deal with such cases, we run parse analysis and throw away the result;
@@ -1996,7 +1991,7 @@ transformExplainStmt(ParseState *pstate, ExplainStmt *stmt)
{
Query *result;
- if (pstate->p_variableparams)
+ if (pstate->p_coerce_param_hook != NULL)
{
/* Since parse analysis scribbles on its input, copy the tree first! */
(void) transformStmt(pstate, copyObject(stmt->query));
@@ -2239,50 +2234,3 @@ applyLockingClause(Query *qry, Index rtindex,
rc->pushedDown = pushedDown;
qry->rowMarks = lappend(qry->rowMarks, rc);
}
-
-
-/*
- * Traverse a fully-analyzed tree to verify that parameter symbols
- * match their types. We need this because some Params might still
- * be UNKNOWN, if there wasn't anything to force their coercion,
- * and yet other instances seen later might have gotten coerced.
- */
-static bool
-check_parameter_resolution_walker(Node *node, ParseState *pstate)
-{
- if (node == NULL)
- return false;
- if (IsA(node, Param))
- {
- Param *param = (Param *) node;
-
- if (param->paramkind == PARAM_EXTERN)
- {
- int paramno = param->paramid;
-
- if (paramno <= 0 || /* shouldn't happen, but... */
- paramno > pstate->p_numparams)
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_PARAMETER),
- errmsg("there is no parameter $%d", paramno),
- parser_errposition(pstate, param->location)));
-
- if (param->paramtype != pstate->p_paramtypes[paramno - 1])
- ereport(ERROR,
- (errcode(ERRCODE_AMBIGUOUS_PARAMETER),
- errmsg("could not determine data type of parameter $%d",
- paramno),
- parser_errposition(pstate, param->location)));
- }
- return false;
- }
- if (IsA(node, Query))
- {
- /* Recurse into RTE subquery or not-yet-planned sublink subquery */
- return query_tree_walker((Query *) node,
- check_parameter_resolution_walker,
- (void *) pstate, 0);
- }
- return expression_tree_walker(node, check_parameter_resolution_walker,
- (void *) pstate);
-}