Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 3eea7a0

Browse files
committed
Simplify executor's determination of whether to use parallelism.
Our parallel-mode code only works when we are executing a query in full, so ExecutePlan must disable parallel mode when it is asked to do partial execution. The previous logic for this involved passing down a flag (variously named execute_once or run_once) from callers of ExecutorRun or PortalRun. This is overcomplicated, and unsurprisingly some of the callers didn't get it right, since it requires keeping state that not all of them have handy; not to mention that the requirements for it were undocumented. That led to assertion failures in some corner cases. The only state we really need for this is the existing QueryDesc.already_executed flag, so let's just put all the responsibility in ExecutePlan. (It could have been done in ExecutorRun too, leading to a slightly shorter patch -- but if there's ever more than one caller of ExecutePlan, it seems better to have this logic in the subroutine than the callers.) This makes those ExecutorRun/PortalRun parameters unnecessary. In master it seems okay to just remove them, returning the API for those functions to what it was before parallelism. Such an API break is clearly not okay in stable branches, but for them we can just leave the parameters in place after documenting that they do nothing. Per report from Yugo Nagata, who also reviewed and tested this patch. Back-patch to all supported branches. Discussion: https://postgr.es/m/20241206062549.710dc01cf91224809dd6c0e1@sraoss.co.jp
1 parent 4d82750 commit 3eea7a0

File tree

19 files changed

+49
-73
lines changed

19 files changed

+49
-73
lines changed

contrib/auto_explain/auto_explain.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ static ExecutorEnd_hook_type prev_ExecutorEnd = NULL;
7979
static void explain_ExecutorStart(QueryDesc *queryDesc, int eflags);
8080
static void explain_ExecutorRun(QueryDesc *queryDesc,
8181
ScanDirection direction,
82-
uint64 count, bool execute_once);
82+
uint64 count);
8383
static void explain_ExecutorFinish(QueryDesc *queryDesc);
8484
static void explain_ExecutorEnd(QueryDesc *queryDesc);
8585

@@ -321,15 +321,15 @@ explain_ExecutorStart(QueryDesc *queryDesc, int eflags)
321321
*/
322322
static void
323323
explain_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction,
324-
uint64 count, bool execute_once)
324+
uint64 count)
325325
{
326326
nesting_level++;
327327
PG_TRY();
328328
{
329329
if (prev_ExecutorRun)
330-
prev_ExecutorRun(queryDesc, direction, count, execute_once);
330+
prev_ExecutorRun(queryDesc, direction, count);
331331
else
332-
standard_ExecutorRun(queryDesc, direction, count, execute_once);
332+
standard_ExecutorRun(queryDesc, direction, count);
333333
}
334334
PG_FINALLY();
335335
{

contrib/pg_stat_statements/pg_stat_statements.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ static PlannedStmt *pgss_planner(Query *parse,
335335
static void pgss_ExecutorStart(QueryDesc *queryDesc, int eflags);
336336
static void pgss_ExecutorRun(QueryDesc *queryDesc,
337337
ScanDirection direction,
338-
uint64 count, bool execute_once);
338+
uint64 count);
339339
static void pgss_ExecutorFinish(QueryDesc *queryDesc);
340340
static void pgss_ExecutorEnd(QueryDesc *queryDesc);
341341
static void pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
@@ -1021,16 +1021,15 @@ pgss_ExecutorStart(QueryDesc *queryDesc, int eflags)
10211021
* ExecutorRun hook: all we need do is track nesting depth
10221022
*/
10231023
static void
1024-
pgss_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count,
1025-
bool execute_once)
1024+
pgss_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
10261025
{
10271026
nesting_level++;
10281027
PG_TRY();
10291028
{
10301029
if (prev_ExecutorRun)
1031-
prev_ExecutorRun(queryDesc, direction, count, execute_once);
1030+
prev_ExecutorRun(queryDesc, direction, count);
10321031
else
1033-
standard_ExecutorRun(queryDesc, direction, count, execute_once);
1032+
standard_ExecutorRun(queryDesc, direction, count);
10341033
}
10351034
PG_FINALLY();
10361035
{

src/backend/commands/copyto.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -880,7 +880,7 @@ DoCopyTo(CopyToState cstate)
880880
else
881881
{
882882
/* run the plan --- the dest receiver will send tuples */
883-
ExecutorRun(cstate->queryDesc, ForwardScanDirection, 0, true);
883+
ExecutorRun(cstate->queryDesc, ForwardScanDirection, 0);
884884
processed = ((DR_copy *) cstate->queryDesc->dest)->processed;
885885
}
886886

src/backend/commands/createas.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt,
340340
ExecutorStart(queryDesc, GetIntoRelEFlags(into));
341341

342342
/* run the plan to completion */
343-
ExecutorRun(queryDesc, ForwardScanDirection, 0, true);
343+
ExecutorRun(queryDesc, ForwardScanDirection, 0);
344344

345345
/* save the rowcount if we're given a qc to fill */
346346
if (qc)

src/backend/commands/explain.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -719,7 +719,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
719719
dir = ForwardScanDirection;
720720

721721
/* run the plan */
722-
ExecutorRun(queryDesc, dir, 0, true);
722+
ExecutorRun(queryDesc, dir, 0);
723723

724724
/* run cleanup too */
725725
ExecutorFinish(queryDesc);

src/backend/commands/extension.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -912,7 +912,7 @@ execute_sql_string(const char *sql, const char *filename)
912912
dest, NULL, NULL, 0);
913913

914914
ExecutorStart(qdesc, 0);
915-
ExecutorRun(qdesc, ForwardScanDirection, 0, true);
915+
ExecutorRun(qdesc, ForwardScanDirection, 0);
916916
ExecutorFinish(qdesc);
917917
ExecutorEnd(qdesc);
918918

src/backend/commands/matview.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ refresh_matview_datafill(DestReceiver *dest, Query *query,
446446
ExecutorStart(queryDesc, 0);
447447

448448
/* run the plan */
449-
ExecutorRun(queryDesc, ForwardScanDirection, 0, true);
449+
ExecutorRun(queryDesc, ForwardScanDirection, 0);
450450

451451
processed = queryDesc->estate->es_processed;
452452

src/backend/commands/portalcmds.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ PersistHoldablePortal(Portal portal)
427427
NULL);
428428

429429
/* Fetch the result set into the tuplestore */
430-
ExecutorRun(queryDesc, direction, 0, false);
430+
ExecutorRun(queryDesc, direction, 0);
431431

432432
queryDesc->dest->rDestroy(queryDesc->dest);
433433
queryDesc->dest = NULL;

src/backend/commands/prepare.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ ExecuteQuery(ParseState *pstate,
252252
*/
253253
PortalStart(portal, paramLI, eflags, GetActiveSnapshot());
254254

255-
(void) PortalRun(portal, count, false, true, dest, dest, qc);
255+
(void) PortalRun(portal, count, false, dest, dest, qc);
256256

257257
PortalDrop(portal, false);
258258

src/backend/executor/execMain.c

Lines changed: 22 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,12 @@ static void InitPlan(QueryDesc *queryDesc, int eflags);
7777
static void CheckValidRowMarkRel(Relation rel, RowMarkType markType);
7878
static void ExecPostprocessPlan(EState *estate);
7979
static void ExecEndPlan(PlanState *planstate, EState *estate);
80-
static void ExecutePlan(EState *estate, PlanState *planstate,
81-
bool use_parallel_mode,
80+
static void ExecutePlan(QueryDesc *queryDesc,
8281
CmdType operation,
8382
bool sendTuples,
8483
uint64 numberTuples,
8584
ScanDirection direction,
86-
DestReceiver *dest,
87-
bool execute_once);
85+
DestReceiver *dest);
8886
static bool ExecCheckOneRelPerms(RTEPermissionInfo *perminfo);
8987
static bool ExecCheckPermissionsModified(Oid relOid, Oid userid,
9088
Bitmapset *modifiedCols,
@@ -294,18 +292,17 @@ standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
294292
*/
295293
void
296294
ExecutorRun(QueryDesc *queryDesc,
297-
ScanDirection direction, uint64 count,
298-
bool execute_once)
295+
ScanDirection direction, uint64 count)
299296
{
300297
if (ExecutorRun_hook)
301-
(*ExecutorRun_hook) (queryDesc, direction, count, execute_once);
298+
(*ExecutorRun_hook) (queryDesc, direction, count);
302299
else
303-
standard_ExecutorRun(queryDesc, direction, count, execute_once);
300+
standard_ExecutorRun(queryDesc, direction, count);
304301
}
305302

306303
void
307304
standard_ExecutorRun(QueryDesc *queryDesc,
308-
ScanDirection direction, uint64 count, bool execute_once)
305+
ScanDirection direction, uint64 count)
309306
{
310307
EState *estate;
311308
CmdType operation;
@@ -354,21 +351,12 @@ standard_ExecutorRun(QueryDesc *queryDesc,
354351
* run plan
355352
*/
356353
if (!ScanDirectionIsNoMovement(direction))
357-
{
358-
if (execute_once && queryDesc->already_executed)
359-
elog(ERROR, "can't re-execute query flagged for single execution");
360-
queryDesc->already_executed = true;
361-
362-
ExecutePlan(estate,
363-
queryDesc->planstate,
364-
queryDesc->plannedstmt->parallelModeNeeded,
354+
ExecutePlan(queryDesc,
365355
operation,
366356
sendTuples,
367357
count,
368358
direction,
369-
dest,
370-
execute_once);
371-
}
359+
dest);
372360

373361
/*
374362
* Update es_total_processed to keep track of the number of tuples
@@ -1601,22 +1589,19 @@ ExecCloseRangeTableRelations(EState *estate)
16011589
* moving in the specified direction.
16021590
*
16031591
* Runs to completion if numberTuples is 0
1604-
*
1605-
* Note: the ctid attribute is a 'junk' attribute that is removed before the
1606-
* user can see it
16071592
* ----------------------------------------------------------------
16081593
*/
16091594
static void
1610-
ExecutePlan(EState *estate,
1611-
PlanState *planstate,
1612-
bool use_parallel_mode,
1595+
ExecutePlan(QueryDesc *queryDesc,
16131596
CmdType operation,
16141597
bool sendTuples,
16151598
uint64 numberTuples,
16161599
ScanDirection direction,
1617-
DestReceiver *dest,
1618-
bool execute_once)
1600+
DestReceiver *dest)
16191601
{
1602+
EState *estate = queryDesc->estate;
1603+
PlanState *planstate = queryDesc->planstate;
1604+
bool use_parallel_mode;
16201605
TupleTableSlot *slot;
16211606
uint64 current_tuple_count;
16221607

@@ -1631,11 +1616,17 @@ ExecutePlan(EState *estate,
16311616
estate->es_direction = direction;
16321617

16331618
/*
1634-
* If the plan might potentially be executed multiple times, we must force
1635-
* it to run without parallelism, because we might exit early.
1619+
* Set up parallel mode if appropriate.
1620+
*
1621+
* Parallel mode only supports complete execution of a plan. If we've
1622+
* already partially executed it, or if the caller asks us to exit early,
1623+
* we must force the plan to run without parallelism.
16361624
*/
1637-
if (!execute_once)
1625+
if (queryDesc->already_executed || numberTuples != 0)
16381626
use_parallel_mode = false;
1627+
else
1628+
use_parallel_mode = queryDesc->plannedstmt->parallelModeNeeded;
1629+
queryDesc->already_executed = true;
16391630

16401631
estate->es_use_parallel_mode = use_parallel_mode;
16411632
if (use_parallel_mode)

src/backend/executor/execParallel.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1471,8 +1471,7 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc)
14711471
*/
14721472
ExecutorRun(queryDesc,
14731473
ForwardScanDirection,
1474-
fpes->tuples_needed < 0 ? (int64) 0 : fpes->tuples_needed,
1475-
true);
1474+
fpes->tuples_needed < 0 ? (int64) 0 : fpes->tuples_needed);
14761475

14771476
/* Shut down the executor */
14781477
ExecutorFinish(queryDesc);

src/backend/executor/functions.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -894,7 +894,7 @@ postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache)
894894
/* Run regular commands to completion unless lazyEval */
895895
uint64 count = (es->lazyEval) ? 1 : 0;
896896

897-
ExecutorRun(es->qd, ForwardScanDirection, count, !fcache->returnsSet || !es->lazyEval);
897+
ExecutorRun(es->qd, ForwardScanDirection, count);
898898

899899
/*
900900
* If we requested run to completion OR there was no tuple returned,

src/backend/executor/spi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2929,7 +2929,7 @@ _SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, uint64 tcount)
29292929

29302930
ExecutorStart(queryDesc, eflags);
29312931

2932-
ExecutorRun(queryDesc, ForwardScanDirection, tcount, true);
2932+
ExecutorRun(queryDesc, ForwardScanDirection, tcount);
29332933

29342934
_SPI_current->processed = queryDesc->estate->es_processed;
29352935

src/backend/tcop/postgres.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,7 +1283,6 @@ exec_simple_query(const char *query_string)
12831283
(void) PortalRun(portal,
12841284
FETCH_ALL,
12851285
true, /* always top level */
1286-
true,
12871286
receiver,
12881287
receiver,
12891288
&qc);
@@ -2260,7 +2259,6 @@ exec_execute_message(const char *portal_name, long max_rows)
22602259
completed = PortalRun(portal,
22612260
max_rows,
22622261
true, /* always top level */
2263-
!execute_is_fetch && max_rows == FETCH_ALL,
22642262
receiver,
22652263
receiver,
22662264
&qc);

src/backend/tcop/pquery.c

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ ProcessQuery(PlannedStmt *plan,
157157
/*
158158
* Run the plan to completion.
159159
*/
160-
ExecutorRun(queryDesc, ForwardScanDirection, 0, true);
160+
ExecutorRun(queryDesc, ForwardScanDirection, 0);
161161

162162
/*
163163
* Build command completion status data, if caller wants one.
@@ -681,7 +681,7 @@ PortalSetResultFormat(Portal portal, int nFormats, int16 *formats)
681681
* suspended due to exhaustion of the count parameter.
682682
*/
683683
bool
684-
PortalRun(Portal portal, long count, bool isTopLevel, bool run_once,
684+
PortalRun(Portal portal, long count, bool isTopLevel,
685685
DestReceiver *dest, DestReceiver *altdest,
686686
QueryCompletion *qc)
687687
{
@@ -714,10 +714,6 @@ PortalRun(Portal portal, long count, bool isTopLevel, bool run_once,
714714
*/
715715
MarkPortalActive(portal);
716716

717-
/* Set run_once flag. Shouldn't be clear if previously set. */
718-
Assert(!portal->run_once || run_once);
719-
portal->run_once = run_once;
720-
721717
/*
722718
* Set up global portal context pointers.
723719
*
@@ -921,8 +917,7 @@ PortalRunSelect(Portal portal,
921917
else
922918
{
923919
PushActiveSnapshot(queryDesc->snapshot);
924-
ExecutorRun(queryDesc, direction, (uint64) count,
925-
portal->run_once);
920+
ExecutorRun(queryDesc, direction, (uint64) count);
926921
nprocessed = queryDesc->estate->es_processed;
927922
PopActiveSnapshot();
928923
}
@@ -961,8 +956,7 @@ PortalRunSelect(Portal portal,
961956
else
962957
{
963958
PushActiveSnapshot(queryDesc->snapshot);
964-
ExecutorRun(queryDesc, direction, (uint64) count,
965-
portal->run_once);
959+
ExecutorRun(queryDesc, direction, (uint64) count);
966960
nprocessed = queryDesc->estate->es_processed;
967961
PopActiveSnapshot();
968962
}
@@ -1406,9 +1400,6 @@ PortalRunFetch(Portal portal,
14061400
*/
14071401
MarkPortalActive(portal);
14081402

1409-
/* If supporting FETCH, portal can't be run-once. */
1410-
Assert(!portal->run_once);
1411-
14121403
/*
14131404
* Set up global portal context pointers.
14141405
*/

src/include/executor/execdesc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ typedef struct QueryDesc
4848
EState *estate; /* executor's query-wide state */
4949
PlanState *planstate; /* tree of per-plan-node state */
5050

51-
/* This field is set by ExecutorRun */
51+
/* This field is set by ExecutePlan */
5252
bool already_executed; /* true if previously executed */
5353

5454
/* This is always set NULL by the core system, but plugins can change it */

src/include/executor/executor.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,7 @@ extern PGDLLIMPORT ExecutorStart_hook_type ExecutorStart_hook;
7878
/* Hook for plugins to get control in ExecutorRun() */
7979
typedef void (*ExecutorRun_hook_type) (QueryDesc *queryDesc,
8080
ScanDirection direction,
81-
uint64 count,
82-
bool execute_once);
81+
uint64 count);
8382
extern PGDLLIMPORT ExecutorRun_hook_type ExecutorRun_hook;
8483

8584
/* Hook for plugins to get control in ExecutorFinish() */
@@ -200,9 +199,9 @@ ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno, bool *isNull)
200199
extern void ExecutorStart(QueryDesc *queryDesc, int eflags);
201200
extern void standard_ExecutorStart(QueryDesc *queryDesc, int eflags);
202201
extern void ExecutorRun(QueryDesc *queryDesc,
203-
ScanDirection direction, uint64 count, bool execute_once);
202+
ScanDirection direction, uint64 count);
204203
extern void standard_ExecutorRun(QueryDesc *queryDesc,
205-
ScanDirection direction, uint64 count, bool execute_once);
204+
ScanDirection direction, uint64 count);
206205
extern void ExecutorFinish(QueryDesc *queryDesc);
207206
extern void standard_ExecutorFinish(QueryDesc *queryDesc);
208207
extern void ExecutorEnd(QueryDesc *queryDesc);

src/include/tcop/pquery.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ extern void PortalSetResultFormat(Portal portal, int nFormats,
3636
int16 *formats);
3737

3838
extern bool PortalRun(Portal portal, long count, bool isTopLevel,
39-
bool run_once, DestReceiver *dest, DestReceiver *altdest,
39+
DestReceiver *dest, DestReceiver *altdest,
4040
QueryCompletion *qc);
4141

4242
extern uint64 PortalRunFetch(Portal portal,

src/include/utils/portal.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,6 @@ typedef struct PortalData
145145
/* Features/options */
146146
PortalStrategy strategy; /* see above */
147147
int cursorOptions; /* DECLARE CURSOR option bits */
148-
bool run_once; /* portal will only be run once */
149148

150149
/* Status data */
151150
PortalStatus status; /* see above */

0 commit comments

Comments
 (0)