Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit844fe9f

Browse files
committed
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 relatedsyntax trees, rather than necessarily always parsing a list of SQLstatements. raw_parser() gains a new argument, enum RawParseMode,to say what to do. As proof of concept, add a mode that just parsesa TypeName without any other decoration, and use that to greatlysimplify typeStringToTypeName().In addition, invent a new SPI entry point SPI_prepare_extended() toallow SPI users (particularly plpgsql) to get at this new functionality.In hopes of making this the last variant of SPI_prepare(), set up itsadditional arguments as a struct rather than direct arguments, andpromise that future additions to the struct can default to zero.SPI_prepare_cursor() and SPI_prepare_params() can perhaps go away atsome point.Discussion:https://postgr.es/m/4165684.1607707277@sss.pgh.pa.us
1 parentb49154b commit844fe9f

File tree

14 files changed

+268
-83
lines changed

14 files changed

+268
-83
lines changed

‎doc/src/sgml/spi.sgml

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,6 +1105,11 @@ SPIPlanPtr SPI_prepare_cursor(const char * <parameter>command</parameter>, int <
11051105
for the <structfield>options</structfield> field of <structname>DeclareCursorStmt</structname>.
11061106
<function>SPI_prepare</function> always takes the cursor options as zero.
11071107
</para>
1108+
1109+
<para>
1110+
This function is now deprecated in favor
1111+
of <function>SPI_prepare_extended</function>.
1112+
</para>
11081113
</refsect1>
11091114

11101115
<refsect1>
@@ -1176,6 +1181,122 @@ SPIPlanPtr SPI_prepare_cursor(const char * <parameter>command</parameter>, int <
11761181

11771182
<!-- *********************************************** -->
11781183

1184+
<refentry id="spi-spi-prepare-extended">
1185+
<indexterm><primary>SPI_prepare_extended</primary></indexterm>
1186+
1187+
<refmeta>
1188+
<refentrytitle>SPI_prepare_extended</refentrytitle>
1189+
<manvolnum>3</manvolnum>
1190+
</refmeta>
1191+
1192+
<refnamediv>
1193+
<refname>SPI_prepare_extended</refname>
1194+
<refpurpose>prepare a statement, without executing it yet</refpurpose>
1195+
</refnamediv>
1196+
1197+
<refsynopsisdiv>
1198+
<synopsis>
1199+
SPIPlanPtr SPI_prepare_extended(const char * <parameter>command</parameter>,
1200+
const SPIPrepareOptions * <parameter>options</parameter>)
1201+
</synopsis>
1202+
</refsynopsisdiv>
1203+
1204+
<refsect1>
1205+
<title>Description</title>
1206+
1207+
<para>
1208+
<function>SPI_prepare_extended</function> creates and returns a prepared
1209+
statement for the specified command, but doesn't execute the command.
1210+
This function is equivalent to <function>SPI_prepare</function>,
1211+
with the addition that the caller can specify options to control
1212+
the parsing of external parameter references, as well as other facets
1213+
of query parsing and planning.
1214+
</para>
1215+
</refsect1>
1216+
1217+
<refsect1>
1218+
<title>Arguments</title>
1219+
1220+
<variablelist>
1221+
<varlistentry>
1222+
<term><literal>const char * <parameter>command</parameter></literal></term>
1223+
<listitem>
1224+
<para>
1225+
command string
1226+
</para>
1227+
</listitem>
1228+
</varlistentry>
1229+
1230+
<varlistentry>
1231+
<term><literal>const SPIPrepareOptions * <parameter>options</parameter></literal></term>
1232+
<listitem>
1233+
<para>
1234+
struct containing optional arguments
1235+
</para>
1236+
</listitem>
1237+
</varlistentry>
1238+
</variablelist>
1239+
1240+
<para>
1241+
Callers should always zero out the entire <parameter>options</parameter>
1242+
struct, then fill whichever fields they want to set. This ensures forward
1243+
compatibility of code, since any fields that are added to the struct in
1244+
future will be defined to behave backwards-compatibly if they are zero.
1245+
The currently available <parameter>options</parameter> fields are:
1246+
</para>
1247+
1248+
<variablelist>
1249+
<varlistentry>
1250+
<term><literal>ParserSetupHook <parameter>parserSetup</parameter></literal></term>
1251+
<listitem>
1252+
<para>
1253+
Parser hook setup function
1254+
</para>
1255+
</listitem>
1256+
</varlistentry>
1257+
1258+
<varlistentry>
1259+
<term><literal>void * <parameter>parserSetupArg</parameter></literal></term>
1260+
<listitem>
1261+
<para>
1262+
pass-through argument for <parameter>parserSetup</parameter>
1263+
</para>
1264+
</listitem>
1265+
</varlistentry>
1266+
1267+
<varlistentry>
1268+
<term><literal>RawParseMode <parameter>parseMode</parameter></literal></term>
1269+
<listitem>
1270+
<para>
1271+
mode for raw parsing; <literal>RAW_PARSE_DEFAULT</literal> (zero)
1272+
produces default behavior
1273+
</para>
1274+
</listitem>
1275+
</varlistentry>
1276+
1277+
<varlistentry>
1278+
<term><literal>int <parameter>cursorOptions</parameter></literal></term>
1279+
<listitem>
1280+
<para>
1281+
integer bit mask of cursor options; zero produces default behavior
1282+
</para>
1283+
</listitem>
1284+
</varlistentry>
1285+
</variablelist>
1286+
</refsect1>
1287+
1288+
<refsect1>
1289+
<title>Return Value</title>
1290+
1291+
<para>
1292+
<function>SPI_prepare_extended</function> has the same return conventions as
1293+
<function>SPI_prepare</function>.
1294+
</para>
1295+
</refsect1>
1296+
</refentry>
1297+
1298+
<!-- *********************************************** -->
1299+
11791300
<refentry id="spi-spi-prepare-params">
11801301
<indexterm><primary>SPI_prepare_params</primary></indexterm>
11811302

@@ -1208,6 +1329,11 @@ SPIPlanPtr SPI_prepare_params(const char * <parameter>command</parameter>,
12081329
with the addition that the caller can specify parser hook functions
12091330
to control the parsing of external parameter references.
12101331
</para>
1332+
1333+
<para>
1334+
This function is now deprecated in favor
1335+
of <function>SPI_prepare_extended</function>.
1336+
</para>
12111337
</refsect1>
12121338

12131339
<refsect1>

‎src/backend/commands/tablecmds.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12095,7 +12095,7 @@ ATPostAlterTypeParse(Oid oldId, Oid oldRelId, Oid refRelId, char *cmd,
1209512095
* parse_analyze() or the rewriter, but instead we need to pass them
1209612096
* through parse_utilcmd.c to make them ready for execution.
1209712097
*/
12098-
raw_parsetree_list = raw_parser(cmd);
12098+
raw_parsetree_list = raw_parser(cmd, RAW_PARSE_DEFAULT);
1209912099
querytree_list = NIL;
1210012100
foreach(list_item, raw_parsetree_list)
1210112101
{

‎src/backend/executor/spi.c

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,7 @@ SPI_execute(const char *src, bool read_only, long tcount)
508508

509509
memset(&plan,0,sizeof(_SPI_plan));
510510
plan.magic=_SPI_PLAN_MAGIC;
511+
plan.parse_mode=RAW_PARSE_DEFAULT;
511512
plan.cursor_options=CURSOR_OPT_PARALLEL_OK;
512513

513514
_SPI_prepare_oneshot_plan(src,&plan);
@@ -681,6 +682,7 @@ SPI_execute_with_args(const char *src,
681682

682683
memset(&plan,0,sizeof(_SPI_plan));
683684
plan.magic=_SPI_PLAN_MAGIC;
685+
plan.parse_mode=RAW_PARSE_DEFAULT;
684686
plan.cursor_options=CURSOR_OPT_PARALLEL_OK;
685687
plan.nargs=nargs;
686688
plan.argtypes=argtypes;
@@ -726,6 +728,7 @@ SPI_execute_with_receiver(const char *src,
726728

727729
memset(&plan,0,sizeof(_SPI_plan));
728730
plan.magic=_SPI_PLAN_MAGIC;
731+
plan.parse_mode=RAW_PARSE_DEFAULT;
729732
plan.cursor_options=CURSOR_OPT_PARALLEL_OK;
730733
if (params)
731734
{
@@ -768,6 +771,7 @@ SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes,
768771

769772
memset(&plan,0,sizeof(_SPI_plan));
770773
plan.magic=_SPI_PLAN_MAGIC;
774+
plan.parse_mode=RAW_PARSE_DEFAULT;
771775
plan.cursor_options=cursorOptions;
772776
plan.nargs=nargs;
773777
plan.argtypes=argtypes;
@@ -784,6 +788,42 @@ SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes,
784788
returnresult;
785789
}
786790

791+
SPIPlanPtr
792+
SPI_prepare_extended(constchar*src,
793+
constSPIPrepareOptions*options)
794+
{
795+
_SPI_planplan;
796+
SPIPlanPtrresult;
797+
798+
if (src==NULL||options==NULL)
799+
{
800+
SPI_result=SPI_ERROR_ARGUMENT;
801+
returnNULL;
802+
}
803+
804+
SPI_result=_SPI_begin_call(true);
805+
if (SPI_result<0)
806+
returnNULL;
807+
808+
memset(&plan,0,sizeof(_SPI_plan));
809+
plan.magic=_SPI_PLAN_MAGIC;
810+
plan.parse_mode=options->parseMode;
811+
plan.cursor_options=options->cursorOptions;
812+
plan.nargs=0;
813+
plan.argtypes=NULL;
814+
plan.parserSetup=options->parserSetup;
815+
plan.parserSetupArg=options->parserSetupArg;
816+
817+
_SPI_prepare_plan(src,&plan);
818+
819+
/* copy plan to procedure context */
820+
result=_SPI_make_plan_non_temp(&plan);
821+
822+
_SPI_end_call(true);
823+
824+
returnresult;
825+
}
826+
787827
SPIPlanPtr
788828
SPI_prepare_params(constchar*src,
789829
ParserSetupHookparserSetup,
@@ -805,6 +845,7 @@ SPI_prepare_params(const char *src,
805845

806846
memset(&plan,0,sizeof(_SPI_plan));
807847
plan.magic=_SPI_PLAN_MAGIC;
848+
plan.parse_mode=RAW_PARSE_DEFAULT;
808849
plan.cursor_options=cursorOptions;
809850
plan.nargs=0;
810851
plan.argtypes=NULL;
@@ -1340,6 +1381,7 @@ SPI_cursor_open_with_args(const char *name,
13401381

13411382
memset(&plan,0,sizeof(_SPI_plan));
13421383
plan.magic=_SPI_PLAN_MAGIC;
1384+
plan.parse_mode=RAW_PARSE_DEFAULT;
13431385
plan.cursor_options=cursorOptions;
13441386
plan.nargs=nargs;
13451387
plan.argtypes=argtypes;
@@ -1400,6 +1442,7 @@ SPI_cursor_parse_open_with_paramlist(const char *name,
14001442

14011443
memset(&plan,0,sizeof(_SPI_plan));
14021444
plan.magic=_SPI_PLAN_MAGIC;
1445+
plan.parse_mode=RAW_PARSE_DEFAULT;
14031446
plan.cursor_options=cursorOptions;
14041447
if (params)
14051448
{
@@ -2036,7 +2079,8 @@ spi_printtup(TupleTableSlot *slot, DestReceiver *self)
20362079
* Parse and analyze a querystring.
20372080
*
20382081
* At entry, plan->argtypes and plan->nargs (or alternatively plan->parserSetup
2039-
* and plan->parserSetupArg) must be valid, as must plan->cursor_options.
2082+
* and plan->parserSetupArg) must be valid, as must plan->parse_mode and
2083+
* plan->cursor_options.
20402084
*
20412085
* Results are stored into *plan (specifically, plan->plancache_list).
20422086
* Note that the result data is all in CurrentMemoryContext or child contexts
@@ -2063,7 +2107,7 @@ _SPI_prepare_plan(const char *src, SPIPlanPtr plan)
20632107
/*
20642108
* Parse the request string into a list of raw parse trees.
20652109
*/
2066-
raw_parsetree_list=pg_parse_query(src);
2110+
raw_parsetree_list=raw_parser(src,plan->parse_mode);
20672111

20682112
/*
20692113
* 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)
21682212
/*
21692213
* Parse the request string into a list of raw parse trees.
21702214
*/
2171-
raw_parsetree_list=pg_parse_query(src);
2215+
raw_parsetree_list=raw_parser(src,plan->parse_mode);
21722216

21732217
/*
21742218
* Construct plancache entries, but don't do parse analysis yet.
@@ -2866,6 +2910,7 @@ _SPI_make_plan_non_temp(SPIPlanPtr plan)
28662910
newplan= (SPIPlanPtr)palloc0(sizeof(_SPI_plan));
28672911
newplan->magic=_SPI_PLAN_MAGIC;
28682912
newplan->plancxt=plancxt;
2913+
newplan->parse_mode=plan->parse_mode;
28692914
newplan->cursor_options=plan->cursor_options;
28702915
newplan->nargs=plan->nargs;
28712916
if (plan->nargs>0)
@@ -2930,6 +2975,7 @@ _SPI_save_plan(SPIPlanPtr plan)
29302975
newplan= (SPIPlanPtr)palloc0(sizeof(_SPI_plan));
29312976
newplan->magic=_SPI_PLAN_MAGIC;
29322977
newplan->plancxt=plancxt;
2978+
newplan->parse_mode=plan->parse_mode;
29332979
newplan->cursor_options=plan->cursor_options;
29342980
newplan->nargs=plan->nargs;
29352981
if (plan->nargs>0)

‎src/backend/parser/gram.y

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
384384
%type<node>vacuum_relation
385385
%type<selectlimit>opt_select_limitselect_limitlimit_clause
386386

387-
%type<list>stmtblockstmtmulti
387+
%type<list>parse_toplevelstmtmulti
388388
OptTableElementListTableElementListOptInheritdefinition
389389
OptTypedTableElementListTypedTableElementList
390390
reloptionsopt_reloptions
@@ -723,6 +723,15 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
723723
*/
724724
%tokenNOT_LANULLS_LAWITH_LA
725725

726+
/*
727+
* The grammar likewise thinks these tokens are keywords, but they are never
728+
* generated by the scanner. Rather, they can be injected by parser.c as
729+
* the initial token of the string (using the lookahead-token mechanism
730+
* implemented there). This provides a way to tell the grammar to parse
731+
* something other than the usual list of SQL commands.
732+
*/
733+
%tokenMODE_TYPE_NAME
734+
726735

727736
/* Precedence: lowest to highest*/
728737
%nonassocSET/* see relation_expr_opt_alias*/
@@ -787,11 +796,20 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
787796

788797
/*
789798
*The target production for the whole parse.
799+
*
800+
* Ordinarily we parse a list of statements, but if we see one of the
801+
* special MODE_XXX symbols as first token, we parse something else.
802+
* The options here correspond to enum RawParseMode, which see for details.
790803
*/
791-
stmtblock:stmtmulti
804+
parse_toplevel:
805+
stmtmulti
792806
{
793807
pg_yyget_extra(yyscanner)->parsetree = $1;
794808
}
809+
|MODE_TYPE_NAMETypename
810+
{
811+
pg_yyget_extra(yyscanner)->parsetree = list_make1($2);
812+
}
795813
;
796814

797815
/*

‎src/backend/parser/parse_coerce.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1541,7 +1541,7 @@ select_common_typmod(ParseState *pstate, List *exprs, Oid common_type)
15411541

15421542
foreach(lc,exprs)
15431543
{
1544-
Node*expr= (Node*)lfirst(lc);
1544+
Node*expr= (Node*)lfirst(lc);
15451545

15461546
/* Types must match */
15471547
if (exprType(expr)!=common_type)
@@ -2380,7 +2380,8 @@ enforce_generic_type_consistency(const Oid *actual_arg_types,
23802380
if (!OidIsValid(elem_typeid))
23812381
{
23822382
/*
2383-
* if we don't have an element type yet, use the one we just got
2383+
* if we don't have an element type yet, use the one we just
2384+
* got
23842385
*/
23852386
elem_typeid=range_typelem;
23862387
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp