diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2021-01-04 11:03:22 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2021-01-04 11:03:22 -0500 |
commit | 844fe9f159a948377907a63d0ef3fb16dc51ce50 (patch) | |
tree | 5f2ac3f159f7a4795a01330044fd76049ed5bff6 /src/backend/executor/spi.c | |
parent | b49154b3b7a45523ce4081fdae8d65049342fcec (diff) | |
download | postgresql-844fe9f159a948377907a63d0ef3fb16dc51ce50.tar.gz postgresql-844fe9f159a948377907a63d0ef3fb16dc51ce50.zip |
Add the ability for the core grammar to have more than one parse target.
This patch essentially allows gram.y to implement a family of related
syntax trees, rather than necessarily always parsing a list of SQL
statements. raw_parser() gains a new argument, enum RawParseMode,
to say what to do. As proof of concept, add a mode that just parses
a TypeName without any other decoration, and use that to greatly
simplify typeStringToTypeName().
In addition, invent a new SPI entry point SPI_prepare_extended() to
allow SPI users (particularly plpgsql) to get at this new functionality.
In hopes of making this the last variant of SPI_prepare(), set up its
additional arguments as a struct rather than direct arguments, and
promise that future additions to the struct can default to zero.
SPI_prepare_cursor() and SPI_prepare_params() can perhaps go away at
some point.
Discussion: https://postgr.es/m/4165684.1607707277@sss.pgh.pa.us
Diffstat (limited to 'src/backend/executor/spi.c')
-rw-r--r-- | src/backend/executor/spi.c | 52 |
1 files changed, 49 insertions, 3 deletions
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index 8368ead1ef6..6c0593686a9 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -508,6 +508,7 @@ SPI_execute(const char *src, bool read_only, long tcount) memset(&plan, 0, sizeof(_SPI_plan)); plan.magic = _SPI_PLAN_MAGIC; + plan.parse_mode = RAW_PARSE_DEFAULT; plan.cursor_options = CURSOR_OPT_PARALLEL_OK; _SPI_prepare_oneshot_plan(src, &plan); @@ -681,6 +682,7 @@ SPI_execute_with_args(const char *src, memset(&plan, 0, sizeof(_SPI_plan)); plan.magic = _SPI_PLAN_MAGIC; + plan.parse_mode = RAW_PARSE_DEFAULT; plan.cursor_options = CURSOR_OPT_PARALLEL_OK; plan.nargs = nargs; plan.argtypes = argtypes; @@ -726,6 +728,7 @@ SPI_execute_with_receiver(const char *src, memset(&plan, 0, sizeof(_SPI_plan)); plan.magic = _SPI_PLAN_MAGIC; + plan.parse_mode = RAW_PARSE_DEFAULT; plan.cursor_options = CURSOR_OPT_PARALLEL_OK; if (params) { @@ -768,6 +771,7 @@ SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes, memset(&plan, 0, sizeof(_SPI_plan)); plan.magic = _SPI_PLAN_MAGIC; + plan.parse_mode = RAW_PARSE_DEFAULT; plan.cursor_options = cursorOptions; plan.nargs = nargs; plan.argtypes = argtypes; @@ -785,6 +789,42 @@ SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes, } SPIPlanPtr +SPI_prepare_extended(const char *src, + const SPIPrepareOptions *options) +{ + _SPI_plan plan; + SPIPlanPtr result; + + if (src == NULL || options == NULL) + { + SPI_result = SPI_ERROR_ARGUMENT; + return NULL; + } + + SPI_result = _SPI_begin_call(true); + if (SPI_result < 0) + return NULL; + + memset(&plan, 0, sizeof(_SPI_plan)); + plan.magic = _SPI_PLAN_MAGIC; + plan.parse_mode = options->parseMode; + plan.cursor_options = options->cursorOptions; + plan.nargs = 0; + plan.argtypes = NULL; + plan.parserSetup = options->parserSetup; + plan.parserSetupArg = options->parserSetupArg; + + _SPI_prepare_plan(src, &plan); + + /* copy plan to procedure context */ + result = _SPI_make_plan_non_temp(&plan); + + _SPI_end_call(true); + + return result; +} + +SPIPlanPtr SPI_prepare_params(const char *src, ParserSetupHook parserSetup, void *parserSetupArg, @@ -805,6 +845,7 @@ SPI_prepare_params(const char *src, memset(&plan, 0, sizeof(_SPI_plan)); plan.magic = _SPI_PLAN_MAGIC; + plan.parse_mode = RAW_PARSE_DEFAULT; plan.cursor_options = cursorOptions; plan.nargs = 0; plan.argtypes = NULL; @@ -1340,6 +1381,7 @@ SPI_cursor_open_with_args(const char *name, memset(&plan, 0, sizeof(_SPI_plan)); plan.magic = _SPI_PLAN_MAGIC; + plan.parse_mode = RAW_PARSE_DEFAULT; plan.cursor_options = cursorOptions; plan.nargs = nargs; plan.argtypes = argtypes; @@ -1400,6 +1442,7 @@ SPI_cursor_parse_open_with_paramlist(const char *name, memset(&plan, 0, sizeof(_SPI_plan)); plan.magic = _SPI_PLAN_MAGIC; + plan.parse_mode = RAW_PARSE_DEFAULT; plan.cursor_options = cursorOptions; if (params) { @@ -2036,7 +2079,8 @@ spi_printtup(TupleTableSlot *slot, DestReceiver *self) * Parse and analyze a querystring. * * At entry, plan->argtypes and plan->nargs (or alternatively plan->parserSetup - * and plan->parserSetupArg) must be valid, as must plan->cursor_options. + * and plan->parserSetupArg) must be valid, as must plan->parse_mode and + * plan->cursor_options. * * Results are stored into *plan (specifically, plan->plancache_list). * Note that the result data is all in CurrentMemoryContext or child contexts @@ -2063,7 +2107,7 @@ _SPI_prepare_plan(const char *src, SPIPlanPtr plan) /* * Parse the request string into a list of raw parse trees. */ - raw_parsetree_list = pg_parse_query(src); + raw_parsetree_list = raw_parser(src, plan->parse_mode); /* * Do parse analysis and rule rewrite for each raw parsetree, storing the @@ -2168,7 +2212,7 @@ _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan) /* * Parse the request string into a list of raw parse trees. */ - raw_parsetree_list = pg_parse_query(src); + raw_parsetree_list = raw_parser(src, plan->parse_mode); /* * Construct plancache entries, but don't do parse analysis yet. @@ -2866,6 +2910,7 @@ _SPI_make_plan_non_temp(SPIPlanPtr plan) newplan = (SPIPlanPtr) palloc0(sizeof(_SPI_plan)); newplan->magic = _SPI_PLAN_MAGIC; newplan->plancxt = plancxt; + newplan->parse_mode = plan->parse_mode; newplan->cursor_options = plan->cursor_options; newplan->nargs = plan->nargs; if (plan->nargs > 0) @@ -2930,6 +2975,7 @@ _SPI_save_plan(SPIPlanPtr plan) newplan = (SPIPlanPtr) palloc0(sizeof(_SPI_plan)); newplan->magic = _SPI_PLAN_MAGIC; newplan->plancxt = plancxt; + newplan->parse_mode = plan->parse_mode; newplan->cursor_options = plan->cursor_options; newplan->nargs = plan->nargs; if (plan->nargs > 0) |