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

Commitab1f0c8

Browse files
committed
Change representation of statement lists, and add statement location info.
This patch makes several changes that improve the consistency ofrepresentation of lists of statements. It's always been the casethat the output of parse analysis is a list of Query nodes, whateverthe types of the individual statements in the list. This patch bringssimilar consistency to the outputs of raw parsing and planning steps:* The output of raw parsing is now always a list of RawStmt nodes;the statement-type-dependent nodes are one level down from that.* The output of pg_plan_queries() is now always a list of PlannedStmtnodes, even for utility statements. In the case of a utility statement,"planning" just consists of wrapping a CMD_UTILITY PlannedStmt aroundthe utility node. This list representation is now used in Portal andCachedPlan plan lists, replacing the former convention of intermixingPlannedStmts with bare utility-statement nodes.Now, every list of statements has a consistent head-node type dependingon how far along it is in processing. This allows changing many placesthat formerly used generic "Node *" pointers to use a more specificpointer type, thus reducing the number of IsA() tests and casts needed,as well as improving code clarity.Also, the post-parse-analysis representation of DECLARE CURSOR is changedso that it looks more like EXPLAIN, PREPARE, etc. That is, the containedSELECT remains a child of the DeclareCursorStmt rather than getting flippedaround to be the other way. It's now true for both Query and PlannedStmtthat utilityStmt is non-null if and only if commandType is CMD_UTILITY.That allows simplifying a lot of places that were testing both fields.(I think some of those were just defensive programming, but in many places,it was actually necessary to avoid confusing DECLARE CURSOR with SELECT.)Because PlannedStmt carries a canSetTag field, we're also able to get ridof some ad-hoc rules about how to reconstruct canSetTag for a bare utilitystatement; specifically, the assumption that a utility is canSetTag if andonly if it's the only one in its list. While I see no near-term need forrelaxing that restriction, it's nice to get rid of the ad-hocery.The API of ProcessUtility() is changed so that what it's passed is thewrapper PlannedStmt not just the bare utility statement. This will affectall users of ProcessUtility_hook, but the changes are pretty trivial; seethe affected contrib modules for examples of the minimum change needed.(Most compilers should give pointer-type-mismatch warnings for uncorrectedcode.)There's also a change in the API of ExplainOneQuery_hook, to pass throughcursorOptions instead of expecting hook functions to know what to pick.This is needed because of the DECLARE CURSOR changes, but really shouldhave been done in 9.6; it's unlikely that any extant hook functionsknow about using CURSOR_OPT_PARALLEL_OK.Finally, teach gram.y to save statement boundary locations in RawStmtnodes, and pass those through to Query and PlannedStmt nodes. This allowsmore intelligent handling of cases where a source query string containsmultiple statements. This patch doesn't actually do anything with theinformation, but a follow-on patch will. (Passing this information throughcleanly is the true motivation for these changes; while I think this is allgood cleanup, it's unlikely we'd have bothered without this end goal.)catversion bump because addition of location fields to struct Queryaffects stored rules.This patch is by me, but it owes a good deal to Fabien Coelho who dida lot of preliminary work on the problem, and also reviewed the patch.Discussion:https://postgr.es/m/alpine.DEB.2.20.1612200926310.29821@lancre
1 parent75abb95 commitab1f0c8

File tree

53 files changed

+788
-547
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+788
-547
lines changed

‎contrib/pg_stat_statements/pg_stat_statements.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ static void pgss_ExecutorRun(QueryDesc *queryDesc,
292292
uint64count);
293293
staticvoidpgss_ExecutorFinish(QueryDesc*queryDesc);
294294
staticvoidpgss_ExecutorEnd(QueryDesc*queryDesc);
295-
staticvoidpgss_ProcessUtility(Node*parsetree,constchar*queryString,
295+
staticvoidpgss_ProcessUtility(PlannedStmt*pstmt,constchar*queryString,
296296
ProcessUtilityContextcontext,ParamListInfoparams,
297297
DestReceiver*dest,char*completionTag);
298298
staticuint32pgss_hash_fn(constvoid*key,Sizekeysize);
@@ -942,10 +942,12 @@ pgss_ExecutorEnd(QueryDesc *queryDesc)
942942
* ProcessUtility hook
943943
*/
944944
staticvoid
945-
pgss_ProcessUtility(Node*parsetree,constchar*queryString,
945+
pgss_ProcessUtility(PlannedStmt*pstmt,constchar*queryString,
946946
ProcessUtilityContextcontext,ParamListInfoparams,
947947
DestReceiver*dest,char*completionTag)
948948
{
949+
Node*parsetree=pstmt->utilityStmt;
950+
949951
/*
950952
* If it's an EXECUTE statement, we don't track it and don't increment the
951953
* nesting level. This allows the cycles to be charged to the underlying
@@ -979,11 +981,11 @@ pgss_ProcessUtility(Node *parsetree, const char *queryString,
979981
PG_TRY();
980982
{
981983
if (prev_ProcessUtility)
982-
prev_ProcessUtility(parsetree,queryString,
984+
prev_ProcessUtility(pstmt,queryString,
983985
context,params,
984986
dest,completionTag);
985987
else
986-
standard_ProcessUtility(parsetree,queryString,
988+
standard_ProcessUtility(pstmt,queryString,
987989
context,params,
988990
dest,completionTag);
989991
nested_level--;
@@ -1044,11 +1046,11 @@ pgss_ProcessUtility(Node *parsetree, const char *queryString,
10441046
else
10451047
{
10461048
if (prev_ProcessUtility)
1047-
prev_ProcessUtility(parsetree,queryString,
1049+
prev_ProcessUtility(pstmt,queryString,
10481050
context,params,
10491051
dest,completionTag);
10501052
else
1051-
standard_ProcessUtility(parsetree,queryString,
1053+
standard_ProcessUtility(pstmt,queryString,
10521054
context,params,
10531055
dest,completionTag);
10541056
}

‎contrib/sepgsql/hooks.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -297,13 +297,14 @@ sepgsql_exec_check_perms(List *rangeTabls, bool abort)
297297
* break whole of the things if nefarious user would use.
298298
*/
299299
staticvoid
300-
sepgsql_utility_command(Node*parsetree,
300+
sepgsql_utility_command(PlannedStmt*pstmt,
301301
constchar*queryString,
302302
ProcessUtilityContextcontext,
303303
ParamListInfoparams,
304304
DestReceiver*dest,
305305
char*completionTag)
306306
{
307+
Node*parsetree=pstmt->utilityStmt;
307308
sepgsql_context_info_tsaved_context_info=sepgsql_context_info;
308309
ListCell*cell;
309310

@@ -362,11 +363,11 @@ sepgsql_utility_command(Node *parsetree,
362363
}
363364

364365
if (next_ProcessUtility_hook)
365-
(*next_ProcessUtility_hook) (parsetree,queryString,
366+
(*next_ProcessUtility_hook) (pstmt,queryString,
366367
context,params,
367368
dest,completionTag);
368369
else
369-
standard_ProcessUtility(parsetree,queryString,
370+
standard_ProcessUtility(pstmt,queryString,
370371
context,params,
371372
dest,completionTag);
372373
}

‎src/backend/catalog/pg_proc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -934,7 +934,7 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
934934
querytree_list=NIL;
935935
foreach(lc,raw_parsetree_list)
936936
{
937-
Node*parsetree= (Node*)lfirst(lc);
937+
RawStmt*parsetree= (RawStmt*)lfirst(lc);
938938
List*querytree_sublist;
939939

940940
querytree_sublist=pg_analyze_and_rewrite_params(parsetree,

‎src/backend/commands/copy.c

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -287,13 +287,13 @@ static const char BinarySignature[11] = "PGCOPY\n\377\r\n\0";
287287

288288

289289
/* non-export function prototypes */
290-
staticCopyStateBeginCopy(ParseState*pstate,boolis_from,Relationrel,Node*raw_query,
291-
constOidqueryRelId,List*attnamelist,
290+
staticCopyStateBeginCopy(ParseState*pstate,boolis_from,Relationrel,
291+
RawStmt*raw_query,OidqueryRelId,List*attnamelist,
292292
List*options);
293293
staticvoidEndCopy(CopyStatecstate);
294294
staticvoidClosePipeToProgram(CopyStatecstate);
295-
staticCopyStateBeginCopyTo(ParseState*pstate,Relationrel,Node*query,
296-
constOidqueryRelId,constchar*filename,boolis_program,
295+
staticCopyStateBeginCopyTo(ParseState*pstate,Relationrel,RawStmt*query,
296+
OidqueryRelId,constchar*filename,boolis_program,
297297
List*attnamelist,List*options);
298298
staticvoidEndCopyTo(CopyStatecstate);
299299
staticuint64DoCopyTo(CopyStatecstate);
@@ -770,15 +770,17 @@ CopyLoadRawBuf(CopyState cstate)
770770
* Do not allow the copy if user doesn't have proper permission to access
771771
* the table or the specifically requested columns.
772772
*/
773-
Oid
774-
DoCopy(ParseState*pstate,constCopyStmt*stmt,uint64*processed)
773+
void
774+
DoCopy(ParseState*pstate,constCopyStmt*stmt,
775+
intstmt_location,intstmt_len,
776+
uint64*processed)
775777
{
776778
CopyStatecstate;
777779
boolis_from=stmt->is_from;
778780
boolpipe= (stmt->filename==NULL);
779781
Relationrel;
780782
Oidrelid;
781-
Node*query=NULL;
783+
RawStmt*query=NULL;
782784
List*range_table=NIL;
783785

784786
/* Disallow COPY to/from file or program except to superusers. */
@@ -929,7 +931,10 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt, uint64 *processed)
929931
select->targetList=targetList;
930932
select->fromClause=list_make1(from);
931933

932-
query= (Node*)select;
934+
query=makeNode(RawStmt);
935+
query->stmt= (Node*)select;
936+
query->stmt_location=stmt_location;
937+
query->stmt_len=stmt_len;
933938

934939
/*
935940
* Close the relation for now, but keep the lock on it to prevent
@@ -945,7 +950,11 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt, uint64 *processed)
945950
{
946951
Assert(stmt->query);
947952

948-
query=stmt->query;
953+
query=makeNode(RawStmt);
954+
query->stmt=stmt->query;
955+
query->stmt_location=stmt_location;
956+
query->stmt_len=stmt_len;
957+
949958
relid=InvalidOid;
950959
rel=NULL;
951960
}
@@ -981,8 +990,6 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt, uint64 *processed)
981990
*/
982991
if (rel!=NULL)
983992
heap_close(rel, (is_from ?NoLock :AccessShareLock));
984-
985-
returnrelid;
986993
}
987994

988995
/*
@@ -1364,8 +1371,8 @@ static CopyState
13641371
BeginCopy(ParseState*pstate,
13651372
boolis_from,
13661373
Relationrel,
1367-
Node*raw_query,
1368-
constOidqueryRelId,
1374+
RawStmt*raw_query,
1375+
OidqueryRelId,
13691376
List*attnamelist,
13701377
List*options)
13711378
{
@@ -1456,7 +1463,7 @@ BeginCopy(ParseState *pstate,
14561463
* function and is executed repeatedly. (See also the same hack in
14571464
* DECLARE CURSOR and PREPARE.) XXX FIXME someday.
14581465
*/
1459-
rewritten=pg_analyze_and_rewrite((Node*)copyObject(raw_query),
1466+
rewritten=pg_analyze_and_rewrite((RawStmt*)copyObject(raw_query),
14601467
pstate->p_sourcetext,NULL,0);
14611468

14621469
/* check that we got back something we can work with */
@@ -1747,8 +1754,8 @@ EndCopy(CopyState cstate)
17471754
staticCopyState
17481755
BeginCopyTo(ParseState*pstate,
17491756
Relationrel,
1750-
Node*query,
1751-
constOidqueryRelId,
1757+
RawStmt*query,
1758+
OidqueryRelId,
17521759
constchar*filename,
17531760
boolis_program,
17541761
List*attnamelist,

‎src/backend/commands/createas.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString,
326326
query= (Query*)linitial(rewritten);
327327
Assert(query->commandType==CMD_SELECT);
328328

329-
/* plan the query */
329+
/* plan the query--- note we disallow parallelism*/
330330
plan=pg_plan_query(query,0,params);
331331

332332
/*

‎src/backend/commands/explain.c

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ explain_get_index_name_hook_type explain_get_index_name_hook = NULL;
5353
#defineX_CLOSE_IMMEDIATE 2
5454
#defineX_NOWHITESPACE 4
5555

56-
staticvoidExplainOneQuery(Query*query,IntoClause*into,ExplainState*es,
56+
staticvoidExplainOneQuery(Query*query,intcursorOptions,
57+
IntoClause*into,ExplainState*es,
5758
constchar*queryString,ParamListInfoparams);
5859
staticvoidreport_triggers(ResultRelInfo*rInfo,boolshow_relname,
5960
ExplainState*es);
@@ -245,7 +246,8 @@ ExplainQuery(ParseState *pstate, ExplainStmt *stmt, const char *queryString,
245246
/* Explain every plan */
246247
foreach(l,rewritten)
247248
{
248-
ExplainOneQuery((Query*)lfirst(l),NULL,es,
249+
ExplainOneQuery((Query*)lfirst(l),
250+
CURSOR_OPT_PARALLEL_OK,NULL,es,
249251
queryString,params);
250252

251253
/* Separate plans with an appropriate separator */
@@ -329,7 +331,8 @@ ExplainResultDesc(ExplainStmt *stmt)
329331
* "into" is NULL unless we are explaining the contents of a CreateTableAsStmt.
330332
*/
331333
staticvoid
332-
ExplainOneQuery(Query*query,IntoClause*into,ExplainState*es,
334+
ExplainOneQuery(Query*query,intcursorOptions,
335+
IntoClause*into,ExplainState*es,
333336
constchar*queryString,ParamListInfoparams)
334337
{
335338
/* planner will not cope with utility statements */
@@ -341,7 +344,8 @@ ExplainOneQuery(Query *query, IntoClause *into, ExplainState *es,
341344

342345
/* if an advisor plugin is present, let it manage things */
343346
if (ExplainOneQuery_hook)
344-
(*ExplainOneQuery_hook) (query,into,es,queryString,params);
347+
(*ExplainOneQuery_hook) (query,cursorOptions,into,es,
348+
queryString,params);
345349
else
346350
{
347351
PlannedStmt*plan;
@@ -351,7 +355,7 @@ ExplainOneQuery(Query *query, IntoClause *into, ExplainState *es,
351355
INSTR_TIME_SET_CURRENT(planstart);
352356

353357
/* plan the query */
354-
plan=pg_plan_query(query,into ?0 :CURSOR_OPT_PARALLEL_OK,params);
358+
plan=pg_plan_query(query,cursorOptions,params);
355359

356360
INSTR_TIME_SET_CURRENT(planduration);
357361
INSTR_TIME_SUBTRACT(planduration,planstart);
@@ -385,14 +389,37 @@ ExplainOneUtility(Node *utilityStmt, IntoClause *into, ExplainState *es,
385389
* We have to rewrite the contained SELECT and then pass it back to
386390
* ExplainOneQuery. It's probably not really necessary to copy the
387391
* contained parsetree another time, but let's be safe.
392+
*
393+
* Like ExecCreateTableAs, disallow parallelism in the plan.
388394
*/
389395
CreateTableAsStmt*ctas= (CreateTableAsStmt*)utilityStmt;
390396
List*rewritten;
391397

392398
Assert(IsA(ctas->query,Query));
393399
rewritten=QueryRewrite((Query*)copyObject(ctas->query));
394400
Assert(list_length(rewritten)==1);
395-
ExplainOneQuery((Query*)linitial(rewritten),ctas->into,es,
401+
ExplainOneQuery((Query*)linitial(rewritten),
402+
0,ctas->into,es,
403+
queryString,params);
404+
}
405+
elseif (IsA(utilityStmt,DeclareCursorStmt))
406+
{
407+
/*
408+
* Likewise for DECLARE CURSOR.
409+
*
410+
* Notice that if you say EXPLAIN ANALYZE DECLARE CURSOR then we'll
411+
* actually run the query. This is different from pre-8.3 behavior
412+
* but seems more useful than not running the query. No cursor will
413+
* be created, however.
414+
*/
415+
DeclareCursorStmt*dcs= (DeclareCursorStmt*)utilityStmt;
416+
List*rewritten;
417+
418+
Assert(IsA(dcs->query,Query));
419+
rewritten=QueryRewrite((Query*)copyObject(dcs->query));
420+
Assert(list_length(rewritten)==1);
421+
ExplainOneQuery((Query*)linitial(rewritten),
422+
dcs->options,NULL,es,
396423
queryString,params);
397424
}
398425
elseif (IsA(utilityStmt,ExecuteStmt))
@@ -423,11 +450,6 @@ ExplainOneUtility(Node *utilityStmt, IntoClause *into, ExplainState *es,
423450
* "into" is NULL unless we are explaining the contents of a CreateTableAsStmt,
424451
* in which case executing the query should result in creating that table.
425452
*
426-
* Since we ignore any DeclareCursorStmt that might be attached to the query,
427-
* if you say EXPLAIN ANALYZE DECLARE CURSOR then we'll actually run the
428-
* query. This is different from pre-8.3 behavior but seems more useful than
429-
* not running the query. No cursor will be created, however.
430-
*
431453
* This is exported because it's called back from prepare.c in the
432454
* EXPLAIN EXECUTE case, and because an index advisor plugin would need
433455
* to call it.
@@ -444,6 +466,8 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
444466
inteflags;
445467
intinstrument_option=0;
446468

469+
Assert(plannedstmt->commandType!=CMD_UTILITY);
470+
447471
if (es->analyze&&es->timing)
448472
instrument_option |=INSTRUMENT_TIMER;
449473
elseif (es->analyze)

‎src/backend/commands/extension.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,7 @@ execute_sql_string(const char *sql, const char *filename)
712712
*/
713713
foreach(lc1,raw_parsetree_list)
714714
{
715-
Node*parsetree= (Node*)lfirst(lc1);
715+
RawStmt*parsetree= (RawStmt*)lfirst(lc1);
716716
List*stmt_list;
717717
ListCell*lc2;
718718

@@ -724,23 +724,17 @@ execute_sql_string(const char *sql, const char *filename)
724724

725725
foreach(lc2,stmt_list)
726726
{
727-
Node*stmt= (Node*)lfirst(lc2);
728-
729-
if (IsA(stmt,TransactionStmt))
730-
ereport(ERROR,
731-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
732-
errmsg("transaction control statements are not allowed within an extension script")));
727+
PlannedStmt*stmt= (PlannedStmt*)lfirst(lc2);
733728

734729
CommandCounterIncrement();
735730

736731
PushActiveSnapshot(GetTransactionSnapshot());
737732

738-
if (IsA(stmt,PlannedStmt)&&
739-
((PlannedStmt*)stmt)->utilityStmt==NULL)
733+
if (stmt->utilityStmt==NULL)
740734
{
741735
QueryDesc*qdesc;
742736

743-
qdesc=CreateQueryDesc((PlannedStmt*)stmt,
737+
qdesc=CreateQueryDesc(stmt,
744738
sql,
745739
GetActiveSnapshot(),NULL,
746740
dest,NULL,0);
@@ -754,6 +748,11 @@ execute_sql_string(const char *sql, const char *filename)
754748
}
755749
else
756750
{
751+
if (IsA(stmt->utilityStmt,TransactionStmt))
752+
ereport(ERROR,
753+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
754+
errmsg("transaction control statements are not allowed within an extension script")));
755+
757756
ProcessUtility(stmt,
758757
sql,
759758
PROCESS_UTILITY_QUERY,
@@ -1434,7 +1433,8 @@ CreateExtensionInternal(char *extensionName,
14341433
csstmt->authrole=NULL;/* will be created by current user */
14351434
csstmt->schemaElts=NIL;
14361435
csstmt->if_not_exists= false;
1437-
CreateSchemaCommand(csstmt,NULL);
1436+
CreateSchemaCommand(csstmt,"(generated CREATE SCHEMA command)",
1437+
-1,-1);
14381438

14391439
/*
14401440
* CreateSchemaCommand includes CommandCounterIncrement, so new

‎src/backend/commands/foreigncmds.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1572,7 +1572,9 @@ ImportForeignSchema(ImportForeignSchemaStmt *stmt)
15721572
*/
15731573
foreach(lc2,raw_parsetree_list)
15741574
{
1575-
CreateForeignTableStmt*cstmt=lfirst(lc2);
1575+
RawStmt*rs= (RawStmt*)lfirst(lc2);
1576+
CreateForeignTableStmt*cstmt= (CreateForeignTableStmt*)rs->stmt;
1577+
PlannedStmt*pstmt;
15761578

15771579
/*
15781580
* Because we only allow CreateForeignTableStmt, we can skip parse
@@ -1593,8 +1595,16 @@ ImportForeignSchema(ImportForeignSchemaStmt *stmt)
15931595
/* Ensure creation schema is the one given in IMPORT statement */
15941596
cstmt->base.relation->schemaname=pstrdup(stmt->local_schema);
15951597

1598+
/* No planning needed, just make a wrapper PlannedStmt */
1599+
pstmt=makeNode(PlannedStmt);
1600+
pstmt->commandType=CMD_UTILITY;
1601+
pstmt->canSetTag= false;
1602+
pstmt->utilityStmt= (Node*)cstmt;
1603+
pstmt->stmt_location=rs->stmt_location;
1604+
pstmt->stmt_len=rs->stmt_len;
1605+
15961606
/* Execute statement */
1597-
ProcessUtility((Node*)cstmt,
1607+
ProcessUtility(pstmt,
15981608
cmd,
15991609
PROCESS_UTILITY_SUBCOMMAND,NULL,
16001610
None_Receiver,NULL);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp