1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-14 18:42:34 +03:00

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.
This commit is contained in:
Tom Lane
2009-11-04 22:26:08 +00:00
parent 48912acc08
commit 9bedd128d6
23 changed files with 1110 additions and 533 deletions

View File

@ -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
@ -627,6 +627,52 @@ pg_analyze_and_rewrite(Node *parsetree, const char *query_string,
return querytree_list;
}
/*
* 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.
*
@ -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++)