aboutsummaryrefslogtreecommitdiff
path: root/src/include
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/include
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/include')
-rw-r--r--src/include/executor/spi.h11
-rw-r--r--src/include/executor/spi_priv.h4
-rw-r--r--src/include/nodes/params.h31
-rw-r--r--src/include/tcop/tcopprot.h6
-rw-r--r--src/include/utils/plancache.h8
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);