diff --git a/src/common/backend/utils/misc/guc.cpp b/src/common/backend/utils/misc/guc.cpp index d3c3835ac..b50184530 100644 --- a/src/common/backend/utils/misc/guc.cpp +++ b/src/common/backend/utils/misc/guc.cpp @@ -7240,7 +7240,7 @@ static void InitConfigureNamesInt64() gettext_noop("Minimum age at which VACUUM should freeze a table row."), NULL}, &u_sess->attr.attr_storage.vacuum_freeze_min_age, - INT64CONST(5000000000), + INT64CONST(2000000000), INT64CONST(0), INT64CONST(0x7FFFFFFFFFFFFFF), NULL, @@ -7266,7 +7266,7 @@ static void InitConfigureNamesInt64() gettext_noop("Age at which VACUUM should scan whole table to freeze tuples."), NULL}, &u_sess->attr.attr_storage.vacuum_freeze_table_age, - INT64CONST(15000000000), + INT64CONST(4000000000), INT64CONST(0), INT64CONST(0x7FFFFFFFFFFFFFF), NULL, @@ -7294,7 +7294,7 @@ static void InitConfigureNamesInt64() NULL}, &g_instance.attr.attr_storage.autovacuum_freeze_max_age, /* see pg_resetxlog if you change the upper-limit value */ - INT64CONST(20000000000), + INT64CONST(4000000000), INT64CONST(100000), INT64CONST(0x7FFFFFFFFFFFFFF), NULL, diff --git a/src/gausskernel/optimizer/commands/cluster.cpp b/src/gausskernel/optimizer/commands/cluster.cpp index 60ff6edc5..54b6ba377 100644 --- a/src/gausskernel/optimizer/commands/cluster.cpp +++ b/src/gausskernel/optimizer/commands/cluster.cpp @@ -1935,7 +1935,7 @@ static void copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, int * freeze_min_age to avoid having CLUSTER freeze tuples earlier than a * plain VACUUM would. */ - vacuum_set_xid_limits(OldHeap, freeze_min_age, freeze_table_age, &OldestXmin, &FreezeXid, NULL); + vacuum_set_xid_limits(OldHeap, 0, freeze_table_age, &OldestXmin, &FreezeXid, NULL); /* * FreezeXid will become the table's new relfrozenxid, and that mustn't go @@ -2113,7 +2113,7 @@ static void copyPartitionHeapData(Relation newHeap, Relation oldHeap, Oid indexO /* * compute xids used to freeze and weed out dead tuples. */ - vacuum_set_xid_limits(oldHeap, freezeMinAge, freezeTableAge, &oldestXmin, &freezeXid, NULL); + vacuum_set_xid_limits(oldHeap, 0, freezeTableAge, &oldestXmin, &freezeXid, NULL); /* * FreezeXid will become the table's new relfrozenxid, and that mustn't go diff --git a/src/gausskernel/optimizer/commands/explain.cpp b/src/gausskernel/optimizer/commands/explain.cpp index 7f0b46628..ff685d568 100644 --- a/src/gausskernel/optimizer/commands/explain.cpp +++ b/src/gausskernel/optimizer/commands/explain.cpp @@ -1082,11 +1082,6 @@ void ExplainOnePlan( } } -#ifndef ENBALE_MULTIPLE_NODE - /* Set sync point for waiting all stream threads complete. */ - StreamNodeGroup::syncQuit(STREAM_COMPLETE); -#endif /* ENABLE_MULTIPLE_NODES */ - /* Create textual dump of plan tree */ ExplainPrintPlan(es, queryDesc); diff --git a/src/gausskernel/optimizer/commands/vacuum.cpp b/src/gausskernel/optimizer/commands/vacuum.cpp index c93c21d6a..ab73bc1c6 100644 --- a/src/gausskernel/optimizer/commands/vacuum.cpp +++ b/src/gausskernel/optimizer/commands/vacuum.cpp @@ -943,7 +943,7 @@ void vacuum_set_xid_limits(Relation rel, int64 freeze_min_age, int64 freeze_tabl *freezeLimit = limit; if (freezeTableLimit != NULL) { - int freezetable; + int64 freezetable; /* * Determine the table freeze age to use: as specified by the caller, diff --git a/src/gausskernel/optimizer/commands/vacuumlazy.cpp b/src/gausskernel/optimizer/commands/vacuumlazy.cpp index dbc8ffee9..78d87e838 100644 --- a/src/gausskernel/optimizer/commands/vacuumlazy.cpp +++ b/src/gausskernel/optimizer/commands/vacuumlazy.cpp @@ -321,7 +321,7 @@ void lazy_vacuum_rel(Relation onerel, VacuumStmt* vacstmt, BufferAccessStrategy &freezeTableLimit); ereport(LOG, - (errmsg("vacuum rel %s freeze %d OldestXmin %lu, FreezeLimit %lu", + (errmsg("vacuum rel %s freeze %ld OldestXmin %lu, FreezeLimit %lu", onerel->rd_rel->relname.data, vacstmt->freeze_min_age, u_sess->cmd_cxt.OldestXmin, diff --git a/src/gausskernel/optimizer/plan/createplan.cpp b/src/gausskernel/optimizer/plan/createplan.cpp index 227ea25b8..7b4025bd0 100644 --- a/src/gausskernel/optimizer/plan/createplan.cpp +++ b/src/gausskernel/optimizer/plan/createplan.cpp @@ -8386,6 +8386,12 @@ Plan* make_stream_limit(PlannerInfo* root, Plan* lefttree, Node* limitOffset, No result_plan = (Plan*)sortPlan; } +#ifndef ENABLE_MULTIPLE_NODES + if (result_plan->dop == 1 && IsA(result_plan, Limit)) { + return result_plan; + } +#endif + /* * "stream" node make this plan as replicated, and LIMIT on this plan could produce random results * if it is evaluated on different DN nodes. so enforcing LIMIT results are produced on ONE random DN diff --git a/src/gausskernel/process/postmaster/postmaster.cpp b/src/gausskernel/process/postmaster/postmaster.cpp index 957a60deb..9301eda30 100755 --- a/src/gausskernel/process/postmaster/postmaster.cpp +++ b/src/gausskernel/process/postmaster/postmaster.cpp @@ -556,8 +556,6 @@ bool isSingleMode = false; #define EXIT_STATUS_0(st) ((st) == 0) #define EXIT_STATUS_1(st) (1 == (st)) -extern THR_LOCAL bool executorStopFlag; - /* * @hdfs * deleteHdfsUser() function is used to clean Hdfs User List and diff --git a/src/gausskernel/process/stream/execStream.cpp b/src/gausskernel/process/stream/execStream.cpp index a78abb25b..189845304 100644 --- a/src/gausskernel/process/stream/execStream.cpp +++ b/src/gausskernel/process/stream/execStream.cpp @@ -2275,7 +2275,11 @@ void ExecEndStream(StreamState* node) { if (IS_PGXC_DATANODE && node->consumer) node->consumer->deInit(); - +#ifndef ENABLE_MULTIPLE_NODES + if (u_sess->stream_cxt.global_obj) { + u_sess->stream_cxt.global_obj->SigStreamThreadClose(); + } +#endif PlanState* outer_plan = outerPlanState(node); if (outer_plan != NULL) @@ -2291,7 +2295,7 @@ void ExecEndStream(StreamState* node) bool executorEarlyStop() { /* Check if query already been stopped. */ - if (u_sess->exec_cxt.executor_stop_flag == true) + if (u_sess->exec_cxt.executorStopFlag == true) return true; /* Check if query already canceled due to error or cancel/die signal. */ else if (u_sess->stream_cxt.global_obj && u_sess->stream_cxt.global_obj->isQueryCanceled()) diff --git a/src/gausskernel/process/stream/streamCore.cpp b/src/gausskernel/process/stream/streamCore.cpp index 1b9972696..ecd46e71a 100644 --- a/src/gausskernel/process/stream/streamCore.cpp +++ b/src/gausskernel/process/stream/streamCore.cpp @@ -461,7 +461,7 @@ int StreamNodeGroup::registerStream(StreamObj* obj) return streamIdx; } else { AutoContextSwitch streamContext(u_sess->stream_cxt.stream_runtime_mem_cxt); - m_streamArray[0].stopFlag = &u_sess->exec_cxt.executor_stop_flag; + m_streamArray[0].stopFlag = &u_sess->exec_cxt.executorStopFlag; m_streamArray[0].consumerList = lcons(obj, m_streamArray[0].consumerList); m_streamArray[0].status = STREAM_INPROGRESS; return 0; @@ -524,11 +524,6 @@ void StreamNodeGroup::signalStreamThreadInNodeGroup(int signo) int ntimes = 1; StreamProducer* producer = (StreamProducer*)m_streamArray[i].streamObj; - /* thread is is InvalidTid means thread not start up */ - if (producer->getThreadId() == InvalidTid) { - continue; - } - /* * Signal slot must be already registered if stream thread already inited. * If not, wait 1ms once and then recheck. Sets the maximum total wait @@ -555,7 +550,38 @@ void StreamNodeGroup::signalStreamThreadInNodeGroup(int signo) } } } - +#ifndef ENABLE_MULTIPLE_NODES +void StreamNodeGroup::SigStreamThreadClose() +{ + if (StreamTopConsumerAmI() && m_streamArray) { + for (int i = 0; i < m_streamNum; i++) { + if (m_streamArray[i].streamObj != NULL && m_streamArray[i].streamObj->getThreadId() != InvalidTid) { + int ntimes = 1; + StreamProducer* producer = (StreamProducer*)m_streamArray[i].streamObj; + /* + * Signal slot must be already registered if stream thread already inited. + * If not, wait 1ms once and then recheck. Sets the maximum total wait + * time as 30s. + */ + while (producer->getThreadInit() == false) { + /* sleep 1ms */ + pg_usleep(1000); + ntimes++; + if (ntimes == 30000) { + /* wait 30s, just break here */ + break; + } + } + /* + * mark before send signal, + * used for signal handle to check signal whether signal is vaild. + */ + (void)SendProcSignal(producer->getThreadId(), PROCSIG_STREAM_STOP_CHECK, InvalidBackendId); + } + } + } +} +#endif /* * @Description: Cancel all stream thread registered in node group * @@ -1823,4 +1849,9 @@ bool InitStreamObject(PlannedStmt* planStmt) } return false; } + +void StreamMarkStop() +{ + u_sess->exec_cxt.executorStopFlag = true; +} #endif diff --git a/src/gausskernel/process/stream/streamMain.cpp b/src/gausskernel/process/stream/streamMain.cpp index 6c7215205..400701f5e 100644 --- a/src/gausskernel/process/stream/streamMain.cpp +++ b/src/gausskernel/process/stream/streamMain.cpp @@ -205,6 +205,7 @@ static void InitStreamSignal() (void)gspqsignal(SIGINT, StatementCancelHandler); (void)gspqsignal(SIGTERM, die); (void)gspqsignal(SIGALRM, handle_sig_alarm); /* timeout conditions */ + (void)gspqsignal(SIGUSR1, procsignal_sigusr1_handler); (void)gs_signal_unblock_sigusr2(); if (IsUnderPostmaster) { @@ -283,10 +284,10 @@ void ExtractProduerInfo() #endif if (u_sess->stream_cxt.producer_obj->isDummy()) { - u_sess->exec_cxt.executor_stop_flag = true; + u_sess->exec_cxt.executorStopFlag = true; u_sess->stream_cxt.dummy_thread = true; } else { - u_sess->exec_cxt.executor_stop_flag = false; + u_sess->exec_cxt.executorStopFlag = false; u_sess->stream_cxt.dummy_thread = false; } @@ -555,7 +556,7 @@ void ResetStreamEnv() { t_thrd.subrole = NO_SUBROLE; u_sess->stream_cxt.dummy_thread = false; - u_sess->exec_cxt.executor_stop_flag = false; + u_sess->exec_cxt.executorStopFlag = false; u_sess->stream_cxt.global_obj = NULL; u_sess->stream_cxt.producer_obj = NULL; u_sess->instr_cxt.global_instr = NULL; @@ -640,7 +641,7 @@ void SetStreamWorkerInfo(StreamProducer* proObj) // set the stopFlag; u_sess->stream_cxt.global_obj = u_sess->stream_cxt.producer_obj->getNodeGroup(); u_sess->stream_cxt.global_obj->setStopFlagPoint( - u_sess->stream_cxt.producer_obj->getNodeGroupIdx(), &u_sess->exec_cxt.executor_stop_flag); + u_sess->stream_cxt.producer_obj->getNodeGroupIdx(), &u_sess->exec_cxt.executorStopFlag); } static void ResetStreamWorkerInfo() diff --git a/src/gausskernel/process/tcop/postgres.cpp b/src/gausskernel/process/tcop/postgres.cpp index e0854e147..e08b1438c 100644 --- a/src/gausskernel/process/tcop/postgres.cpp +++ b/src/gausskernel/process/tcop/postgres.cpp @@ -1337,7 +1337,7 @@ void exec_simple_plan(PlannedStmt* plan) if (ThreadIsDummy(plan->planTree)) { u_sess->stream_cxt.dummy_thread = true; - u_sess->exec_cxt.executor_stop_flag = true; + u_sess->exec_cxt.executorStopFlag = true; } /* "IS_PGXC_DATANODE && StreamTopConsumerAmI()" means on the CN of the compute pool. */ @@ -1346,7 +1346,7 @@ void exec_simple_plan(PlannedStmt* plan) /* "IS_PGXC_DATANODE && plan->in_compute_pool" means on the DN of the compute pool. */ if (IS_PGXC_DATANODE && plan->in_compute_pool) - u_sess->exec_cxt.executor_stop_flag = false; + u_sess->exec_cxt.executorStopFlag = false; /* * Start up a transaction command. All queries generated by the @@ -2789,7 +2789,7 @@ static void exec_plan_with_params(StringInfo input_message) if (ThreadIsDummy(planstmt->planTree)) { u_sess->stream_cxt.dummy_thread = true; - u_sess->exec_cxt.executor_stop_flag = true; + u_sess->exec_cxt.executorStopFlag = true; } /* nodeid in planstmt->planTree->exec_nodes->nodeList is from DWS, @@ -2798,7 +2798,7 @@ static void exec_plan_with_params(StringInfo input_message) */ if (planstmt->in_compute_pool) { u_sess->stream_cxt.dummy_thread = false; - u_sess->exec_cxt.executor_stop_flag = false; + u_sess->exec_cxt.executorStopFlag = false; } /* get parameter numbers */ @@ -5674,7 +5674,7 @@ void HandleMemoryContextDump(void) void HandleExecutorFlag(void) { if (IS_PGXC_DATANODE) - u_sess->exec_cxt.executor_stop_flag = true; + u_sess->exec_cxt.executorStopFlag = true; } /* * RecoveryConflictInterrupt: out-of-line portion of recovery conflict diff --git a/src/gausskernel/process/threadpool/knl_session.cpp b/src/gausskernel/process/threadpool/knl_session.cpp index 958562eeb..8a616ee45 100644 --- a/src/gausskernel/process/threadpool/knl_session.cpp +++ b/src/gausskernel/process/threadpool/knl_session.cpp @@ -97,7 +97,6 @@ void knl_u_executor_init(knl_u_executor_context* exec_cxt) { exec_cxt->remotequery_list = NIL; exec_cxt->exec_result_checkqual_fail = false; - exec_cxt->executor_stop_flag = false; exec_cxt->under_stream_runtime = false; exec_cxt->under_auto_explain = false; exec_cxt->extension_is_valid = false; diff --git a/src/gausskernel/process/threadpool/threadpool_sessctl.cpp b/src/gausskernel/process/threadpool/threadpool_sessctl.cpp index 560843533..1e532a25b 100644 --- a/src/gausskernel/process/threadpool/threadpool_sessctl.cpp +++ b/src/gausskernel/process/threadpool/threadpool_sessctl.cpp @@ -288,7 +288,7 @@ void ThreadPoolSessControl::SendProcSignal(int ctrl_index, ProcSignalReason reas switch (reason) { case PROCSIG_EXECUTOR_FLAG: { if (IS_PGXC_DATANODE && ctrl->sess->debug_query_id == query_id) { - ctrl->sess->exec_cxt.executor_stop_flag = true; + ctrl->sess->exec_cxt.executorStopFlag = true; } break; } diff --git a/src/gausskernel/runtime/executor/execMain.cpp b/src/gausskernel/runtime/executor/execMain.cpp index 8e80e3536..ad2422ea9 100644 --- a/src/gausskernel/runtime/executor/execMain.cpp +++ b/src/gausskernel/runtime/executor/execMain.cpp @@ -2199,7 +2199,7 @@ static void ExecutePlan(EState *estate, PlanState *planstate, CmdType operation, * If we are supposed to send the tuple somewhere, do so. (In * practice, this is probably always the case at this point.) */ - if (sendTuples && !u_sess->exec_cxt.executor_stop_flag) { + if (sendTuples && !u_sess->exec_cxt.executorStopFlag) { (*dest->receiveSlot)(slot, dest); } @@ -2324,7 +2324,7 @@ static void ExecuteVectorizedPlan(EState *estate, PlanState *planstate, CmdType * If we are supposed to send the tuple somewhere, do so. (In * practice, this is probably always the case at this point.) */ - if (sendTuples && !u_sess->exec_cxt.executor_stop_flag) { + if (sendTuples && !u_sess->exec_cxt.executorStopFlag) { (*dest->sendBatch)(batch, dest); } diff --git a/src/gausskernel/runtime/executor/nodeHashjoin.cpp b/src/gausskernel/runtime/executor/nodeHashjoin.cpp index 1ab947f9b..ec8e6c71f 100644 --- a/src/gausskernel/runtime/executor/nodeHashjoin.cpp +++ b/src/gausskernel/runtime/executor/nodeHashjoin.cpp @@ -153,11 +153,9 @@ TupleTableSlot* ExecHashJoin(HashJoinState* node) * It should be noticed that we can not do early deinit * within predpush. */ -#ifdef ENABLE_MULTIPLE_NODES if (((PlanState*)node) != NULL && !CheckParamWalker((PlanState*)node)) { ExecEarlyDeinitConsumer((PlanState*)node); } -#endif ExecEarlyFree((PlanState*)node); EARLY_FREE_LOG(elog(LOG, "Early Free: HashJoin early return NULL" @@ -206,11 +204,10 @@ TupleTableSlot* ExecHashJoin(HashJoinState* node) * It should be noticed that we can not do early deinit * within predpush. */ -#ifdef ENABLE_MULTIPLE_NODES if (((PlanState*)node) != NULL && !CheckParamWalker((PlanState*)node)) { ExecEarlyDeinitConsumer((PlanState*)node); } -#endif + return NULL; } diff --git a/src/gausskernel/runtime/executor/nodeWorktablescan.cpp b/src/gausskernel/runtime/executor/nodeWorktablescan.cpp index dddea84d3..5654337a9 100644 --- a/src/gausskernel/runtime/executor/nodeWorktablescan.cpp +++ b/src/gausskernel/runtime/executor/nodeWorktablescan.cpp @@ -168,7 +168,7 @@ TupleTableSlot* ExecWorkTableScan(WorkTableScanState* node) * producer logic in ExecutePlan to handle ends-up steps */ if (controller->executor_stop) { - u_sess->exec_cxt.executor_stop_flag = true; + u_sess->exec_cxt.executorStopFlag = true; return NULL; } diff --git a/src/gausskernel/runtime/vecexecutor/vecnode/vecstream.cpp b/src/gausskernel/runtime/vecexecutor/vecnode/vecstream.cpp index 3929c2c24..1b9a9d07a 100644 --- a/src/gausskernel/runtime/vecexecutor/vecnode/vecstream.cpp +++ b/src/gausskernel/runtime/vecexecutor/vecnode/vecstream.cpp @@ -490,7 +490,11 @@ void ExecEndVecStream(VecStreamState* node) { if (IS_PGXC_DATANODE && node->consumer) node->consumer->deInit(); - +#ifndef ENABLE_MULTIPLE_NODES + if (u_sess->stream_cxt.global_obj) { + u_sess->stream_cxt.global_obj->SigStreamThreadClose(); + } +#endif PlanState* outer_plan = outerPlanState(node); if (outer_plan != NULL) diff --git a/src/gausskernel/storage/ipc/procsignal.cpp b/src/gausskernel/storage/ipc/procsignal.cpp index c1b55383e..03107906d 100644 --- a/src/gausskernel/storage/ipc/procsignal.cpp +++ b/src/gausskernel/storage/ipc/procsignal.cpp @@ -20,6 +20,7 @@ #include #include "commands/async.h" +#include "distributelayer/streamCore.h" #include "miscadmin.h" #include "storage/latch.h" #include "storage/ipc.h" @@ -282,6 +283,10 @@ void procsignal_sigusr1_handler(SIGNAL_ARGS) WLMCheckSigRecvData(); if (CheckProcSignal(PROCSIG_SPACE_LIMIT)) WLMCheckSpaceLimit(); +#ifndef ENABLE_MULTIPLE_NODES + if (CheckProcSignal(PROCSIG_STREAM_STOP_CHECK)) + StreamMarkStop(); +#endif #endif if (CheckProcSignal(PROCSIG_DEFAULTXACT_READONLY)) diff --git a/src/include/distributelayer/streamCore.h b/src/include/distributelayer/streamCore.h index 2a8aae119..51bd7f6c7 100644 --- a/src/include/distributelayer/streamCore.h +++ b/src/include/distributelayer/streamCore.h @@ -432,14 +432,14 @@ public: { return m_quitStatus; } + /* Send stop signal to all stream threads in node group. */ + void SigStreamThreadClose(); + + struct PortalData *m_portal; #endif /* Mark recursive vfd is invalid before aborting transaction. */ static void MarkRecursiveVfdInvalid(); -#ifndef ENABLE_MULTIPLE_NODES - struct PortalData *m_portal; -#endif - private: /* Set the executor stop flag to true. */ void stopThread(); @@ -513,5 +513,7 @@ private: extern bool IsThreadProcessStreamRecursive(); extern bool InitStreamObject(PlannedStmt* planStmt); - +#ifndef ENABLE_MULTIPLE_NODES +extern void StreamMarkStop(); +#endif #endif /* SRC_INCLUDE_DISTRIBUTELAYER_STREAMCORE_H_ */ diff --git a/src/include/executor/nodeRecursiveunion.h b/src/include/executor/nodeRecursiveunion.h index 007f26f94..d28fa7c59 100644 --- a/src/include/executor/nodeRecursiveunion.h +++ b/src/include/executor/nodeRecursiveunion.h @@ -251,7 +251,7 @@ static inline void recursive_union_sleep(long usec) recursive_union_sleep(CHECK_INTERVAL); \ \ /* Check if current thread is required to exit from top consumer*/ \ - if (u_sess->exec_cxt.executor_stop_flag) { \ + if (u_sess->exec_cxt.executorStopFlag) { \ break; \ } \ } diff --git a/src/include/knl/knl_session.h b/src/include/knl/knl_session.h index b8e45baef..20062652d 100644 --- a/src/include/knl/knl_session.h +++ b/src/include/knl/knl_session.h @@ -110,8 +110,6 @@ typedef struct knl_u_executor_context { bool exec_result_checkqual_fail; - bool executor_stop_flag; - bool under_stream_runtime; bool under_auto_explain; diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 481bdde3b..87031d4b2 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1573,8 +1573,8 @@ typedef struct VacuumStmt { int flags; /* flags to distinguish partition or btree */ /* the values for this flags are in vacuum.h */ Oid rely_oid; /* for btree, it is the heap btree or it is InvalidOid */ - int freeze_min_age; /* min freeze age, or -1 to use default */ - int freeze_table_age; /* age at which to scan whole table */ + int64 freeze_min_age; /* min freeze age, or -1 to use default */ + int64 freeze_table_age; /* age at which to scan whole table */ RangeVar* relation; /* single table to process, or NULL */ List* va_cols; /* list of column names, or NIL for all */ diff --git a/src/include/storage/procsignal.h b/src/include/storage/procsignal.h index 1b536feef..5b01df0b4 100644 --- a/src/include/storage/procsignal.h +++ b/src/include/storage/procsignal.h @@ -44,6 +44,7 @@ typedef enum { PROCSIG_MEMORYCONTEXT_DUMP, /* dump memory context on all backends */ PROCSIG_UPDATE_WORKLOAD_DATA, /* update workload data */ PROCSIG_SPACE_LIMIT, /* space limitation */ + PROCSIG_STREAM_STOP_CHECK, /* check local connections close or not */ #endif /* Recovery conflict reasons */ diff --git a/src/test/regress/expected/smp.out b/src/test/regress/expected/smp.out index 2196c4367..57850d674 100644 --- a/src/test/regress/expected/smp.out +++ b/src/test/regress/expected/smp.out @@ -580,23 +580,22 @@ select sum(b)+median(a) as result from t1; (1 row) explain (costs off) select a, count(distinct b) from t1 group by a order by 1 limit 10; - QUERY PLAN ----------------------------------------------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------- Limit - -> Limit - -> Sort - Sort Key: a - -> Streaming(type: LOCAL GATHER dop: 1/2) - -> Limit - -> Sort - Sort Key: a - -> GroupAggregate - Group By Key: a - -> Sort - Sort Key: a - -> Streaming(type: LOCAL REDISTRIBUTE dop: 2/2) - -> Seq Scan on t1 -(14 rows) + -> Sort + Sort Key: a + -> Streaming(type: LOCAL GATHER dop: 1/2) + -> Limit + -> Sort + Sort Key: a + -> GroupAggregate + Group By Key: a + -> Sort + Sort Key: a + -> Streaming(type: LOCAL REDISTRIBUTE dop: 2/2) + -> Seq Scan on t1 +(13 rows) select a, count(distinct b) from t1 group by a order by 1 limit 10; a | count