diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2009-11-04 22:26:08 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2009-11-04 22:26:08 +0000 |
commit | 9bedd128d6ed83798004b3c7ddc33f33703ccf23 (patch) | |
tree | 95a475a5da180f19c69b5bcf2f6e764b1bc69ea7 /src/include | |
parent | 48912acc089a6148529f12ab0a75b1bf026f231d (diff) | |
download | postgresql-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/include')
-rw-r--r-- | src/include/executor/spi.h | 11 | ||||
-rw-r--r-- | src/include/executor/spi_priv.h | 4 | ||||
-rw-r--r-- | src/include/nodes/params.h | 31 | ||||
-rw-r--r-- | src/include/tcop/tcopprot.h | 6 | ||||
-rw-r--r-- | src/include/utils/plancache.h | 8 |
5 files changed, 51 insertions, 9 deletions
diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h index 5bdde2d5241..42ba4e464d1 100644 --- a/src/include/executor/spi.h +++ b/src/include/executor/spi.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/spi.h,v 1.72 2009/06/11 14:49:11 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/spi.h,v 1.73 2009/11/04 22:26:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -73,6 +73,9 @@ extern void SPI_restore_connection(void); extern int SPI_execute(const char *src, bool read_only, long tcount); extern int SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only, long tcount); +extern int SPI_execute_plan_with_paramlist(SPIPlanPtr plan, + ParamListInfo params, + bool read_only, long tcount); extern int SPI_exec(const char *src, long tcount); extern int SPI_execp(SPIPlanPtr plan, Datum *Values, const char *Nulls, long tcount); @@ -88,6 +91,10 @@ extern int SPI_execute_with_args(const char *src, extern SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes); extern SPIPlanPtr SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes, int cursorOptions); +extern SPIPlanPtr SPI_prepare_params(const char *src, + ParserSetupHook parserSetup, + void *parserSetupArg, + int cursorOptions); extern SPIPlanPtr SPI_saveplan(SPIPlanPtr plan); extern int SPI_freeplan(SPIPlanPtr plan); @@ -122,6 +129,8 @@ extern Portal SPI_cursor_open_with_args(const char *name, int nargs, Oid *argtypes, Datum *Values, const char *Nulls, bool read_only, int cursorOptions); +extern Portal SPI_cursor_open_with_paramlist(const char *name, SPIPlanPtr plan, + ParamListInfo params, bool read_only); extern Portal SPI_cursor_find(const char *name); extern void SPI_cursor_fetch(Portal portal, bool forward, long count); extern void SPI_cursor_move(Portal portal, bool forward, long count); diff --git a/src/include/executor/spi_priv.h b/src/include/executor/spi_priv.h index ef50a9013e8..a0dee126952 100644 --- a/src/include/executor/spi_priv.h +++ b/src/include/executor/spi_priv.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/spi_priv.h,v 1.32 2009/01/01 17:23:59 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/spi_priv.h,v 1.33 2009/11/04 22:26:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -68,6 +68,8 @@ typedef struct _SPI_plan int cursor_options; /* Cursor options used for planning */ int nargs; /* number of plan arguments */ Oid *argtypes; /* Argument types (NULL if nargs is 0) */ + ParserSetupHook parserSetup; /* alternative parameter spec method */ + void *parserSetupArg; } _SPI_plan; #endif /* SPI_PRIV_H */ diff --git a/src/include/nodes/params.h b/src/include/nodes/params.h index adc58710553..96cbf5267a4 100644 --- a/src/include/nodes/params.h +++ b/src/include/nodes/params.h @@ -7,13 +7,16 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/params.h,v 1.38 2009/01/01 17:24:00 momjian Exp $ + * $PostgreSQL: pgsql/src/include/nodes/params.h,v 1.39 2009/11/04 22:26:06 tgl Exp $ * *------------------------------------------------------------------------- */ #ifndef PARAMS_H #define PARAMS_H +/* To avoid including a pile of parser headers, reference ParseState thus: */ +struct ParseState; + /* ---------------- * ParamListInfo @@ -26,10 +29,20 @@ * Although parameter numbers are normally consecutive, we allow * ptype == InvalidOid to signal an unused array entry. * + * pflags is a flags field. Currently the only used bit is: * PARAM_FLAG_CONST signals the planner that it may treat this parameter * as a constant (i.e., generate a plan that works only for this value * of the parameter). * + * There are two hook functions that can be associated with a ParamListInfo + * array to support dynamic parameter handling. First, if paramFetch + * isn't null and the executor requires a value for an invalid parameter + * (one with ptype == InvalidOid), the paramFetch hook is called to give + * it a chance to fill in the parameter value. Second, a parserSetup + * hook can be supplied to re-instantiate the original parsing hooks if + * a query needs to be re-parsed/planned (as a substitute for supposing + * that the current ptype values represent a fixed set of parameter types). + * Although the data structure is really an array, not a list, we keep * the old typedef name to avoid unnecessary code changes. * ---------------- @@ -45,14 +58,22 @@ typedef struct ParamExternData Oid ptype; /* parameter's datatype, or 0 */ } ParamExternData; +typedef struct ParamListInfoData *ParamListInfo; + +typedef void (*ParamFetchHook) (ParamListInfo params, int paramid); + +typedef void (*ParserSetupHook) (struct ParseState *pstate, void *arg); + typedef struct ParamListInfoData { + ParamFetchHook paramFetch; /* parameter fetch hook */ + void *paramFetchArg; + ParserSetupHook parserSetup; /* parser setup hook */ + void *parserSetupArg; int numParams; /* number of ParamExternDatas following */ ParamExternData params[1]; /* VARIABLE LENGTH ARRAY */ } ParamListInfoData; -typedef ParamListInfoData *ParamListInfo; - /* ---------------- * ParamExecData @@ -82,7 +103,7 @@ typedef struct ParamExecData /* Functions found in src/backend/nodes/params.c */ extern ParamListInfo copyParamList(ParamListInfo from); -extern void getParamListTypes(ParamListInfo params, - Oid **param_types, int *num_params); +extern void setupParserWithParamList(struct ParseState *pstate, + ParamListInfo params); #endif /* PARAMS_H */ diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h index b1c8b77bd5c..103a22fbc53 100644 --- a/src/include/tcop/tcopprot.h +++ b/src/include/tcop/tcopprot.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/tcop/tcopprot.h,v 1.100 2009/09/01 00:09:42 tgl Exp $ + * $PostgreSQL: pgsql/src/include/tcop/tcopprot.h,v 1.101 2009/11/04 22:26:07 tgl Exp $ * * OLD COMMENTS * This file was created so that other c files could get the two @@ -49,6 +49,10 @@ extern List *pg_parse_and_rewrite(const char *query_string, extern List *pg_parse_query(const char *query_string); extern List *pg_analyze_and_rewrite(Node *parsetree, const char *query_string, Oid *paramTypes, int numParams); +extern List *pg_analyze_and_rewrite_params(Node *parsetree, + const char *query_string, + ParserSetupHook parserSetup, + void *parserSetupArg); extern PlannedStmt *pg_plan_query(Query *querytree, int cursorOptions, ParamListInfo boundParams); extern List *pg_plan_queries(List *querytrees, int cursorOptions, diff --git a/src/include/utils/plancache.h b/src/include/utils/plancache.h index ea919bd4566..68e3f72b195 100644 --- a/src/include/utils/plancache.h +++ b/src/include/utils/plancache.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/plancache.h,v 1.15 2009/01/01 17:24:02 momjian Exp $ + * $PostgreSQL: pgsql/src/include/utils/plancache.h,v 1.16 2009/11/04 22:26:07 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,6 +16,7 @@ #define PLANCACHE_H #include "access/tupdesc.h" +#include "nodes/params.h" /* * CachedPlanSource represents the portion of a cached plan that persists @@ -50,6 +51,8 @@ typedef struct CachedPlanSource const char *commandTag; /* command tag (a constant!), or NULL */ Oid *param_types; /* array of parameter type OIDs, or NULL */ int num_params; /* length of param_types array */ + ParserSetupHook parserSetup; /* alternative parameter spec method */ + void *parserSetupArg; int cursor_options; /* cursor options used for planning */ bool fully_planned; /* do we cache planner or rewriter output? */ bool fixed_result; /* disallow change in result tupdesc? */ @@ -105,6 +108,9 @@ extern CachedPlanSource *FastCreateCachedPlan(Node *raw_parse_tree, bool fully_planned, bool fixed_result, MemoryContext context); +extern void CachedPlanSetParserHook(CachedPlanSource *plansource, + ParserSetupHook parserSetup, + void *parserSetupArg); extern void DropCachedPlan(CachedPlanSource *plansource); extern CachedPlan *RevalidateCachedPlan(CachedPlanSource *plansource, bool useResOwner); |