aboutsummaryrefslogtreecommitdiff
path: root/src/backend/tcop/postgres.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2009-11-04 22:26:08 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2009-11-04 22:26:08 +0000
commit9bedd128d6ed83798004b3c7ddc33f33703ccf23 (patch)
tree95a475a5da180f19c69b5bcf2f6e764b1bc69ea7 /src/backend/tcop/postgres.c
parent48912acc089a6148529f12ab0a75b1bf026f231d (diff)
downloadpostgresql-9bedd128d6ed83798004b3c7ddc33f33703ccf23.tar.gz
postgresql-9bedd128d6ed83798004b3c7ddc33f33703ccf23.zip
Add support for invoking parser callback hooks via SPI and in cached plans.
As proof of concept, modify plpgsql to use the hooks. plpgsql is still inserting $n symbols textually, but the "back end" of the parsing process now goes through the ParamRef hook instead of using a fixed parameter-type array, and then execution only fetches actually-referenced parameters, using a hook added to ParamListInfo. Although there's a lot left to be done in plpgsql, this already cures the "if (TG_OP = 'INSERT' and NEW.foo ...)" problem, as illustrated by the changed regression test.
Diffstat (limited to 'src/backend/tcop/postgres.c')
-rw-r--r--src/backend/tcop/postgres.c53
1 files changed, 52 insertions, 1 deletions
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 67deea79624..b6a892a30f5 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.574 2009/10/08 22:34:57 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.575 2009/11/04 22:26:06 tgl Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
@@ -628,6 +628,52 @@ pg_analyze_and_rewrite(Node *parsetree, const char *query_string,
}
/*
+ * Do parse analysis and rewriting. This is the same as pg_analyze_and_rewrite
+ * except that external-parameter resolution is determined by parser callback
+ * hooks instead of a fixed list of parameter datatypes.
+ */
+List *
+pg_analyze_and_rewrite_params(Node *parsetree,
+ const char *query_string,
+ ParserSetupHook parserSetup,
+ void *parserSetupArg)
+{
+ ParseState *pstate;
+ Query *query;
+ List *querytree_list;
+
+ Assert(query_string != NULL); /* required as of 8.4 */
+
+ TRACE_POSTGRESQL_QUERY_REWRITE_START(query_string);
+
+ /*
+ * (1) Perform parse analysis.
+ */
+ if (log_parser_stats)
+ ResetUsage();
+
+ pstate = make_parsestate(NULL);
+ pstate->p_sourcetext = query_string;
+ (*parserSetup) (pstate, parserSetupArg);
+
+ query = transformStmt(pstate, parsetree);
+
+ free_parsestate(pstate);
+
+ if (log_parser_stats)
+ ShowUsage("PARSE ANALYSIS STATISTICS");
+
+ /*
+ * (2) Rewrite the queries, as necessary
+ */
+ querytree_list = pg_rewrite_query(query);
+
+ TRACE_POSTGRESQL_QUERY_REWRITE_DONE(query_string);
+
+ return querytree_list;
+}
+
+/*
* Perform rewriting of a query produced by parse analysis.
*
* Note: query must just have come from the parser, because we do not do
@@ -1536,6 +1582,11 @@ exec_bind_message(StringInfo input_message)
/* sizeof(ParamListInfoData) includes the first array element */
params = (ParamListInfo) palloc(sizeof(ParamListInfoData) +
(numParams - 1) *sizeof(ParamExternData));
+ /* we have static list of params, so no hooks needed */
+ params->paramFetch = NULL;
+ params->paramFetchArg = NULL;
+ params->parserSetup = NULL;
+ params->parserSetupArg = NULL;
params->numParams = numParams;
for (paramno = 0; paramno < numParams; paramno++)