From bea8c633890fbbbd24b06b1d98715c8c59739d28 Mon Sep 17 00:00:00 2001 From: kotb Date: Mon, 2 Dec 2024 22:19:07 +0300 Subject: [PATCH 01/74] Add support for RETURNING operator for ORCA This adds support for RETURNING operator for ORCA optimizer returningList from query transforms into LogicalProject that wraps around logical dml node in dxl query dml nodes inside ORCA were changed to provide required columns for this project node nodeDML also was changed to return modified tuples to print them on coordinator through projection --- src/backend/executor/execAmi.c | 5 + src/backend/executor/nodeDML.c | 368 +++++++---- src/backend/executor/nodeMotion.c | 2 +- src/backend/executor/nodeSplitUpdate.c | 2 +- src/backend/gpopt/translate/CCTEListEntry.cpp | 8 +- .../translate/CTranslatorDXLToPlStmt.cpp | 26 +- .../gpopt/translate/CTranslatorQueryToDXL.cpp | 182 +++++- .../AddRedistributeBeforeInsert-1.mdp | 32 +- .../AddRedistributeBeforeInsert-2.mdp | 32 +- .../AddRedistributeBeforeInsert-3.mdp | 32 +- .../AddRedistributeBeforeInsert-4.mdp | 32 +- .../AddRedistributeBeforeInsert-5.mdp | 32 +- .../ParallelAppend-Insert.mdp | 27 +- .../gporca/data/dxl/minidump/CTAS-Random.mdp | 6 +- .../minidump/CTAS-With-Global-Local-Agg.mdp | 18 +- .../data/dxl/minidump/CTAS-random-distr.mdp | 12 +- ...uted-from-replicated-distributed-table.mdp | 12 +- .../data/dxl/minidump/CTAS-with-Limit.mdp | 6 +- ...with-hashed-distributed-external-table.mdp | 8 +- ...th-randomly-distributed-external-table.mdp | 12 +- src/backend/gporca/data/dxl/minidump/CTAS.mdp | 6 +- .../CTAS_OrderedAgg_multiple_cols.mdp | 404 ++++++------ .../minidump/ConvertHashToRandomInsert.mdp | 21 +- .../DML-ComputeScalar-With-Outerref.mdp | 27 +- .../dxl/minidump/DML-Filter-With-OuterRef.mdp | 27 +- .../dxl/minidump/DML-Replicated-Input.mdp | 37 +- .../minidump/DML-UnionAll-With-OuterRef.mdp | 27 +- .../DML-UnionAll-With-Universal-Child.mdp | 31 +- .../dxl/minidump/DML-Volatile-Function.mdp | 33 +- ...ith-CorrelatedNLJ-With-Universal-Child.mdp | 31 +- .../DML-With-HJ-And-UniversalChild.mdp | 21 +- .../DML-With-Join-With-Universal-Child.mdp | 31 +- .../minidump/DML-With-MasterOnlyTable-1.mdp | 21 +- .../minidump/DML-With-WindowFunc-OuterRef.mdp | 4 +- .../data/dxl/minidump/DMLCollapseProject.mdp | 43 +- .../Delete-With-Limit-In-Subquery.mdp | 21 +- .../gporca/data/dxl/minidump/DeleteInCTE.mdp | 395 ++++++++++++ .../minidump/DeleteMismatchedDistribution.mdp | 23 +- .../data/dxl/minidump/DeleteRandomDistr.mdp | 21 +- .../DeleteRandomlyDistributedTable.mdp | 24 +- .../DeleteRandomlyDistributedTableJoin.mdp | 26 +- .../data/dxl/minidump/DeleteReturning.mdp | 377 +++++++++++ .../DeleteWithAfterTriggerDroppedCol.mdp | 25 +- .../data/dxl/minidump/DeleteWithTriggers.mdp | 37 +- .../DontAddRedistributeBeforeInsert-1.mdp | 28 +- .../DontAddRedistributeBeforeInsert-2.mdp | 26 +- .../dxl/minidump/InnerJoinOverJoinExcept.mdp | 27 +- .../minidump/InnerJoinOverJoinExceptAll.mdp | 35 +- ...nsert-Parquet-Partitioned-SortDisabled.mdp | 21 +- .../data/dxl/minidump/Insert-Parquet.mdp | 21 +- .../dxl/minidump/Insert-With-HJ-CTE-Agg.mdp | 39 +- .../gporca/data/dxl/minidump/Insert.mdp | 22 +- .../data/dxl/minidump/InsertAssertSort.mdp | 45 +- .../dxl/minidump/InsertCheckConstraint.mdp | 36 +- .../data/dxl/minidump/InsertConstTuple.mdp | 22 +- .../InsertConstTupleRandomDistribution.mdp | 32 +- .../InsertConstTupleVolatileFunction.mdp | 41 +- ...nsertConstTupleVolatileFunctionMOTable.mdp | 36 +- .../InsertDirectedDispatchNullValue.mdp | 38 +- .../gporca/data/dxl/minidump/InsertInCTE.mdp | 608 ++++++++++++++++++ .../InsertIntoNonNullAfterDroppingColumn.mdp | 41 +- .../data/dxl/minidump/InsertIntoReturning.mdp | 337 ++++++++++ .../dxl/minidump/InsertMasterOnlyTable.mdp | 28 +- .../InsertMasterOnlyTableConstTuple.mdp | 28 +- .../InsertMismatchedDistrubution-2.mdp | 31 +- .../minidump/InsertMismatchedDistrubution.mdp | 31 +- .../minidump/InsertNULLNotNULLConstraint.mdp | 35 +- .../minidump/InsertNoEnforceConstraints.mdp | 29 +- .../data/dxl/minidump/InsertNonSingleton.mdp | 26 +- .../data/dxl/minidump/InsertNotNullCols.mdp | 26 +- .../minidump/InsertPrimaryKeyFromMOTable.mdp | 37 +- .../data/dxl/minidump/InsertProjectSort.mdp | 37 +- .../data/dxl/minidump/InsertRandomDistr.mdp | 28 +- ...plicatedIntoSerialHashDistributedTable.mdp | 37 +- .../gporca/data/dxl/minidump/InsertSort.mdp | 27 +- .../InsertSortDistributed2MasterOnly.mdp | 34 +- .../dxl/minidump/InsertWithDroppedCol.mdp | 37 +- .../data/dxl/minidump/InsertWithTriggers.mdp | 37 +- .../minidump/LeftJoinNullsNotColocated.mdp | 8 +- .../MultipleUpdateWithJoinOnDistCol.mdp | 33 +- .../data/dxl/minidump/PartitionedDelete.mdp | 22 +- .../data/dxl/minidump/PartitionedInsert.mdp | 29 +- .../data/dxl/minidump/PartitionedUpdate.mdp | 32 +- .../data/dxl/minidump/ProjectSetFunction.mdp | 34 +- .../dxl/minidump/ReplicatedTable-CTAS.mdp | 10 +- .../dxl/minidump/ReplicatedTableInsert.mdp | 28 +- .../ReplicatedTableSequenceInsert.mdp | 32 +- .../ReplicatedTableWithAggNoMotion.mdp | 34 +- .../gporca/data/dxl/minidump/SelfUpdate.mdp | 32 +- .../data/dxl/minidump/SqlFuncDmlScalar.mdp | 37 +- .../data/dxl/minidump/SqlFuncDmlTvf.mdp | 37 +- .../dxl/minidump/TaintedReplicatedAgg.mdp | 30 +- .../dxl/minidump/TaintedReplicatedFilter.mdp | 30 +- .../dxl/minidump/TaintedReplicatedLimit.mdp | 26 +- .../minidump/TaintedReplicatedWindowAgg.mdp | 26 +- .../dxl/minidump/UpdateCardinalityAssert.mdp | 32 +- .../dxl/minidump/UpdateCheckConstraint.mdp | 34 +- .../UpdateDistKeyMismatchedDistribution.mdp | 33 +- .../minidump/UpdateDistKeyWithNestedJoin.mdp | 32 +- .../data/dxl/minidump/UpdateDistrKey.mdp | 32 +- .../data/dxl/minidump/UpdateDroppedCols.mdp | 32 +- .../gporca/data/dxl/minidump/UpdateInCTE.mdp | 412 ++++++++++++ .../minidump/UpdateNoCardinalityAssert.mdp | 28 +- .../UpdateNoDistKeyMismatchedDistribution.mdp | 33 +- .../minidump/UpdateNoEnforceConstraints.mdp | 30 +- .../data/dxl/minidump/UpdateNotNullCols.mdp | 32 +- .../data/dxl/minidump/UpdatePartTable.mdp | 32 +- .../data/dxl/minidump/UpdateRandomDistr.mdp | 23 +- .../data/dxl/minidump/UpdateReturning.mdp | 416 ++++++++++++ .../dxl/minidump/UpdateUniqueConstraint-2.mdp | 32 +- .../dxl/minidump/UpdateUniqueConstraint.mdp | 34 +- .../dxl/minidump/UpdateVolatileFunction.mdp | 32 +- .../dxl/minidump/UpdateWindowGatherMerge.mdp | 31 +- .../data/dxl/minidump/UpdateWithHashJoin.mdp | 28 +- .../data/dxl/minidump/UpdateWithOids.mdp | 34 +- .../data/dxl/minidump/UpdateWithTriggers.mdp | 25 +- .../data/dxl/minidump/UpdateZeroRows.mdp | 37 +- .../minidump/UpdatingDistributionColumn.mdp | 34 +- .../dxl/minidump/UpdatingMultipleColumn.mdp | 33 +- .../minidump/UpdatingNonDistColSameTable.mdp | 29 +- .../UpdatingNonDistributionColumnFunc.mdp | 30 +- .../VolatileFunctionsBelowScalarAgg.mdp | 31 +- .../data/dxl/parse_tests/q57-DMLDelete.xml | 1 + .../data/dxl/parse_tests/q58-DMLInsert.xml | 1 + .../data/dxl/parse_tests/q60-DMLUpdate.xml | 1 + .../libgpopt/include/gpopt/base/CUtils.h | 3 + .../include/gpopt/operators/CLogicalDML.h | 17 +- .../include/gpopt/operators/CLogicalDelete.h | 16 + .../include/gpopt/operators/CLogicalInsert.h | 14 + .../include/gpopt/operators/CLogicalUpdate.h | 17 + .../include/gpopt/operators/CPhysicalDML.h | 32 +- .../include/gpopt/xforms/CXformUtils.h | 9 +- .../libgpopt/src/base/CQueryContext.cpp | 5 +- .../gporca/libgpopt/src/base/CUtils.cpp | 34 + .../src/operators/CExpressionPreprocessor.cpp | 4 +- .../libgpopt/src/operators/CLogicalDML.cpp | 73 ++- .../libgpopt/src/operators/CLogicalDelete.cpp | 109 +++- .../libgpopt/src/operators/CLogicalInsert.cpp | 103 ++- .../libgpopt/src/operators/CLogicalUpdate.cpp | 121 +++- .../libgpopt/src/operators/CPhysicalDML.cpp | 92 ++- .../src/translate/CTranslatorDXLToExpr.cpp | 42 +- .../src/translate/CTranslatorExprToDXL.cpp | 94 ++- .../libgpopt/src/xforms/CXformDelete2DML.cpp | 5 +- .../src/xforms/CXformImplementDML.cpp | 8 +- .../libgpopt/src/xforms/CXformInsert2DML.cpp | 4 + .../libgpopt/src/xforms/CXformUpdate2DML.cpp | 9 +- .../libgpopt/src/xforms/CXformUtils.cpp | 46 +- .../naucrates/dxl/operators/CDXLTableDescr.h | 7 + .../src/operators/CDXLPhysicalDML.cpp | 9 +- .../src/parser/CParseHandlerPhysicalDML.cpp | 20 +- .../src/unittest/gpopt/minidump/CDMLTest.cpp | 6 + src/backend/nodes/copyfuncs.c | 1 + src/backend/nodes/outfuncs.c | 1 + src/backend/nodes/readfast.c | 1 + src/backend/optimizer/plan/planner.c | 2 + src/include/executor/nodeDML.h | 2 + .../gpopt/translate/CTranslatorDXLToPlStmt.h | 6 + .../gpopt/translate/CTranslatorQueryToDXL.h | 14 + src/include/nodes/execnodes.h | 1 + src/include/nodes/plannodes.h | 1 + .../regress/expected/bfv_dml_optimizer.out | 26 +- .../expected/partition_pruning_optimizer.out | 4 +- .../expected/qp_dropped_cols_optimizer.out | 12 +- src/test/regress/expected/returning_gp.out | 10 +- .../expected/subselect_gp_optimizer.out | 183 +++--- .../expected/updatable_views_optimizer.out | 38 +- .../expected/with_clause_optimizer.out | 58 +- src/test/regress/sql/returning_gp.sql | 2 +- 168 files changed, 5645 insertions(+), 2240 deletions(-) create mode 100644 src/backend/gporca/data/dxl/minidump/DeleteInCTE.mdp create mode 100644 src/backend/gporca/data/dxl/minidump/DeleteReturning.mdp create mode 100644 src/backend/gporca/data/dxl/minidump/InsertInCTE.mdp create mode 100644 src/backend/gporca/data/dxl/minidump/InsertIntoReturning.mdp create mode 100644 src/backend/gporca/data/dxl/minidump/UpdateInCTE.mdp create mode 100644 src/backend/gporca/data/dxl/minidump/UpdateReturning.mdp diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c index 129daac0a1b7..3caa699c801f 100644 --- a/src/backend/executor/execAmi.c +++ b/src/backend/executor/execAmi.c @@ -24,6 +24,7 @@ #include "executor/nodeDynamicBitmapIndexscan.h" #include "executor/nodeBitmapOr.h" #include "executor/nodeCtescan.h" +#include "executor/nodeDML.h" #include "executor/nodeForeignscan.h" #include "executor/nodeFunctionscan.h" #include "executor/nodeHash.h" @@ -619,6 +620,10 @@ ExecSquelchNode(PlanState *node) ExecSquelchModifyTable((ModifyTableState *) node); return; + case T_DMLState: + ExecSquelchDML((DMLState *) node); + return; + /* * Node types that need custom code to recurse. */ diff --git a/src/backend/executor/nodeDML.c b/src/backend/executor/nodeDML.c index af912775e12d..74e9e1c63f18 100644 --- a/src/backend/executor/nodeDML.c +++ b/src/backend/executor/nodeDML.c @@ -36,6 +36,28 @@ ExecDMLExplainEnd(PlanState *planstate, struct StringInfoData *buf) planstate->instrument->execmemused += DML_MEM; } +/* + * Edit input attr numbers of projection using attributes map + */ +void +RemapProjection(ProjectionInfo *projInfo, AttrMap *map) +{ + int *varNumbers = projInfo->pi_varNumbers; + int numSimpleVars = projInfo->pi_numSimpleVars; + + for (int i = 0; i < numSimpleVars;++i) + { + varNumbers[i] = attrMap(map, varNumbers[i]); + } + + if (projInfo->pi_lastInnerVar > 0) + projInfo->pi_lastInnerVar = attrMap(map, projInfo->pi_lastInnerVar); + if (projInfo->pi_lastOuterVar > 0) + projInfo->pi_lastOuterVar = attrMap(map, projInfo->pi_lastOuterVar); + if (projInfo->pi_lastScanVar > 0) + projInfo->pi_lastScanVar = attrMap(map, projInfo->pi_lastScanVar); +} + /* * Executes INSERT and DELETE DML operations. The * action is specified within the TupleTableSlot at @@ -45,158 +67,192 @@ ExecDMLExplainEnd(PlanState *planstate, struct StringInfoData *buf) TupleTableSlot* ExecDML(DMLState *node) { + for (;;) + { + PlanState *outerNode = outerPlanState(node); + DML *plannode = (DML *) node->ps.plan; - PlanState *outerNode = outerPlanState(node); - DML *plannode = (DML *) node->ps.plan; - - Assert(outerNode != NULL); + Assert(outerNode != NULL); - TupleTableSlot *slot = ExecProcNode(outerNode); + TupleTableSlot *slot = ExecProcNode(outerNode); + TupleTableSlot *resultSlot = NULL; - if (TupIsNull(slot)) - { - return NULL; - } - - bool isnull = false; - int action = DatumGetUInt32(slot_getattr(slot, plannode->actionColIdx, &isnull)); - Assert(!isnull); + if (TupIsNull(slot)) + { + return NULL; + } - bool isUpdate = false; - if (node->ps.state->es_plannedstmt->commandType == CMD_UPDATE) - { - isUpdate = true; - } + bool isnull = false; + int action = DatumGetUInt32(slot_getattr(slot, plannode->actionColIdx, &isnull)); + Assert(!isnull); - Assert(action == DML_INSERT || action == DML_DELETE); + bool isUpdate = false; + if (node->ps.state->es_plannedstmt->commandType == CMD_UPDATE) + { + isUpdate = true; + } + Assert(action == DML_INSERT || action == DML_DELETE); - /* - * Reset per-tuple memory context to free any expression evaluation - * storage allocated in the previous tuple cycle. - */ - ExprContext *econtext = node->ps.ps_ExprContext; - ResetExprContext(econtext); - /* Prepare cleaned-up tuple by projecting it and filtering junk columns */ - econtext->ecxt_outertuple = slot; - TupleTableSlot *projectedSlot = ExecProject(node->ps.ps_ProjInfo, NULL); + /* + * Reset per-tuple memory context to free any expression evaluation + * storage allocated in the previous tuple cycle. + */ + ExprContext *econtext = node->ps.ps_ExprContext; + ResetExprContext(econtext); - /* remove 'junk' columns from tuple */ - node->cleanedUpSlot = ExecFilterJunk(node->junkfilter, projectedSlot); + /* Prepare cleaned-up tuple by projecting it and filtering junk columns */ + econtext->ecxt_outertuple = slot; + TupleTableSlot *projectedSlot = ExecProject(node->ps.ps_ProjInfo, NULL); - /* - * If we are modifying a leaf partition we have to ensure that partition - * selection operation will consider leaf partition's attributes as - * coherent with root partition's attribute numbers, because partition - * selection is performed using root's attribute numbers (all partition - * rules are based on the parent relation's tuple descriptor). In case - * when child partition has different attribute numbers from root's due to - * dropped columns, the partition selection may go wrong without extra - * validation. - */ - if (node->ps.state->es_result_partitions) - { - ResultRelInfo *relInfo = node->ps.state->es_result_relations; + /* remove 'junk' columns from tuple */ + node->cleanedUpSlot = ExecFilterJunk(node->junkfilter, projectedSlot); - /* - * The DML is done on a leaf partition. In order to reuse the map, - * it will be allocated at es_result_relations. - */ - if (RelationGetRelid(relInfo->ri_RelationDesc) != - node->ps.state->es_result_partitions->part->parrelid && - action != DML_DELETE) - makePartitionCheckMap(node->ps.state, relInfo); + /* restore returning projection result tuple */ + node->ps.ps_ResultTupleSlot = node->resultTupleSlot; + node->resultTupleSlot = NULL; /* - * DML node always performs partition selection, and if we want to - * reuse the map built in makePartitionCheckMap, we are allowed to - * reassign es_result_relation_info, because ExecInsert, ExecDelete - * changes it with target partition anyway. Moreover, without - * inheritance plan (ORCA never builds such plans) the - * es_result_relations will contain the only relation. - */ - node->ps.state->es_result_relation_info = relInfo; - } - - if (DML_INSERT == action) - { - /* Respect any given tuple Oid when updating a tuple. */ - if (isUpdate && plannode->tupleoidColIdx != 0) + * If we are modifying a leaf partition we have to ensure that partition + * selection operation will consider leaf partition's attributes as + * coherent with root partition's attribute numbers, because partition + * selection is performed using root's attribute numbers (all partition + * rules are based on the parent relation's tuple descriptor). In case + * when child partition has different attribute numbers from root's due to + * dropped columns, the partition selection may go wrong without extra + * validation. + */ + if (node->ps.state->es_result_partitions) { - Oid oid; - HeapTuple htuple; - - isnull = false; - oid = slot_getattr(slot, plannode->tupleoidColIdx, &isnull); - htuple = ExecFetchSlotHeapTuple(node->cleanedUpSlot); - Assert(htuple == node->cleanedUpSlot->PRIVATE_tts_heaptuple); - HeapTupleSetOid(htuple, oid); + ResultRelInfo *relInfo = node->ps.state->es_result_relations; + + /* + * The DML is done on a leaf partition. In order to reuse the map, + * it will be allocated at es_result_relations. + */ + if (RelationGetRelid(relInfo->ri_RelationDesc) != + node->ps.state->es_result_partitions->part->parrelid && + action != DML_DELETE) + makePartitionCheckMap(node->ps.state, relInfo); + + /* + * DML node always performs partition selection, and if we want to + * reuse the map built in makePartitionCheckMap, we are allowed to + * reassign es_result_relation_info, because ExecInsert, ExecDelete + * changes it with target partition anyway. Moreover, without + * inheritance plan (ORCA never builds such plans) the + * es_result_relations will contain the only relation. + */ + node->ps.state->es_result_relation_info = relInfo; } - /* - * The plan origin is required since ExecInsert performs different - * actions depending on the type of plan (constraint enforcement and - * triggers.) - */ - ExecInsert(node->cleanedUpSlot, - NULL, - node->ps.state, - node->canSetTag, - PLANGEN_OPTIMIZER /* Plan origin */, - isUpdate, - InvalidOid); - } - else /* DML_DELETE */ - { - int32 segid = GpIdentity.segindex; - Datum ctid = slot_getattr(slot, plannode->ctidColIdx, &isnull); - Oid tableoid = InvalidOid; + if (DML_INSERT == action) + { + /* Respect any given tuple Oid when updating a tuple. */ + if (isUpdate && plannode->tupleoidColIdx != 0) + { + Oid oid; + HeapTuple htuple; + + isnull = false; + oid = slot_getattr(slot, plannode->tupleoidColIdx, &isnull); + htuple = ExecFetchSlotHeapTuple(node->cleanedUpSlot); + Assert(htuple == node->cleanedUpSlot->PRIVATE_tts_heaptuple); + HeapTupleSetOid(htuple, oid); + } + + /* + * The plan origin is required since ExecInsert performs different + * actions depending on the type of plan (constraint enforcement and + * triggers.) + */ + resultSlot = ExecInsert(node->cleanedUpSlot, + NULL, + node->ps.state, + node->canSetTag, + PLANGEN_OPTIMIZER /* Plan origin */, + isUpdate, + InvalidOid); + } + else /* DML_DELETE */ + { + int32 segid = GpIdentity.segindex; + Datum ctid = slot_getattr(slot, plannode->ctidColIdx, &isnull); + Oid tableoid = InvalidOid; - Assert(!isnull); + Assert(!isnull); - if (AttributeNumberIsValid(plannode->tableoidColIdx)) - { - Datum dtableoid = slot_getattr(slot, plannode->tableoidColIdx, &isnull); - tableoid = isnull ? InvalidOid : DatumGetObjectId(dtableoid); + if (AttributeNumberIsValid(plannode->tableoidColIdx)) + { + Datum dtableoid = slot_getattr(slot, plannode->tableoidColIdx, &isnull); + tableoid = isnull ? InvalidOid : DatumGetObjectId(dtableoid); + } + + /* + * If tableoid is valid, it means that we are executing UPDATE/DELETE + * on partitioned table (root partition). In order to avoid partition + * pruning in ExecDelete one can use tableoid to build target + * ResultRelInfo for the leaf partition. + */ + if (OidIsValid(tableoid) && node->ps.state->es_result_partitions) + { + ProjectionInfo *projRet = + node->ps.state->es_result_relation_info->ri_projectReturning; + + node->ps.state->es_result_relation_info = + targetid_get_partition(tableoid, node->ps.state, true); + ResultRelInfo *relInfo = node->ps.state->es_result_relation_info; + + if (projRet != NULL && relInfo->ri_projectReturning == NULL) + { + // make linked copy of returning projection with separate remapped input attr numbers + relInfo->ri_projectReturning = makeNode(ProjectionInfo); + + *relInfo->ri_projectReturning = *projRet; + relInfo->ri_projectReturning->pi_varNumbers = + (int *) palloc(projRet->pi_numSimpleVars * sizeof(int)); + memcpy(relInfo->ri_projectReturning->pi_varNumbers, projRet->pi_varNumbers, + projRet->pi_numSimpleVars * sizeof(int)); + + RemapProjection(relInfo->ri_projectReturning, relInfo->ri_partInsertMap); + } + } + + ItemPointer tupleid = (ItemPointer) DatumGetPointer(ctid); + ItemPointerData tuple_ctid = *tupleid; + tupleid = &tuple_ctid; + + if (AttributeNumberIsValid(node->segid_attno)) + { + segid = DatumGetInt32(slot_getattr(slot, node->segid_attno, &isnull)); + Assert(!isnull); + } + + /* Correct tuple count by ignoring deletes when splitting tuples. */ + resultSlot = ExecDelete(tupleid, + segid, + NULL, /* GPDB_91_MERGE_FIXME: oldTuple? */ + node->cleanedUpSlot, + NULL /* DestReceiver */, + node->ps.state, + isUpdate ? false : node->canSetTag, /* if "isUpdate", + ExecInsert() will be run after + ExecDelete() so canSetTag should be set + properly in ExecInsert(). */ + PLANGEN_OPTIMIZER /* Plan origin */, + isUpdate); } /* - * If tableoid is valid, it means that we are executing UPDATE/DELETE - * on partitioned table (root partition). In order to avoid partition - * pruning in ExecDelete one can use tableoid to build target - * ResultRelInfo for the leaf partition. + * If we got a RETURNING result, return it to caller. We'll continue + * the work on next call. */ - if (OidIsValid(tableoid) && node->ps.state->es_result_partitions) - node->ps.state->es_result_relation_info = - targetid_get_partition(tableoid, node->ps.state, true); - - ItemPointer tupleid = (ItemPointer) DatumGetPointer(ctid); - ItemPointerData tuple_ctid = *tupleid; - tupleid = &tuple_ctid; - - if (AttributeNumberIsValid(node->segid_attno)) + if (!TupIsNull(resultSlot)) { - segid = DatumGetInt32(slot_getattr(slot, node->segid_attno, &isnull)); - Assert(!isnull); + return resultSlot; } - - /* Correct tuple count by ignoring deletes when splitting tuples. */ - ExecDelete(tupleid, - segid, - NULL, /* GPDB_91_MERGE_FIXME: oldTuple? */ - node->cleanedUpSlot, - NULL /* DestReceiver */, - node->ps.state, - isUpdate ? false : node->canSetTag, /* if "isUpdate", - ExecInsert() will be run after - ExecDelete() so canSetTag should be set - properly in ExecInsert(). */ - PLANGEN_OPTIMIZER /* Plan origin */, - isUpdate); } - - return slot; } /** @@ -206,12 +262,13 @@ DMLState* ExecInitDML(DML *node, EState *estate, int eflags) { /* check for unsupported flags */ - Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK | EXEC_FLAG_REWIND))); + Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); DMLState *dmlstate = makeNode(DMLState); dmlstate->ps.plan = (Plan *)node; dmlstate->ps.state = estate; dmlstate->canSetTag = node->canSetTag; + dmlstate->resultTupleSlot = NULL; /* * Initialize es_result_relation_info, just like ModifyTable. * GPDB_90_MERGE_FIXME: do we need to consolidate the ModifyTable and DML @@ -275,6 +332,36 @@ ExecInitDML(DML *node, EState *estate, int eflags) dmlstate->ps.state->es_result_relation_info->ri_RelationDesc->rd_att->tdhasoid, dmlstate->cleanedUpSlot); + /* + * Initialize RETURNING projections if needed. + */ + if (node->returningList) + { + TupleTableSlot *slot; + TupleTableSlot *savedResultTuple = dmlstate->ps.ps_ResultTupleSlot; + + /* Initialize result tuple slot and assign its rowtype */ + TupleDesc tupDesc = ExecTypeFromTL(node->returningList, false); + + /* Set up a slot for the output of the RETURNING projection(s) */ + ExecInitResultTupleSlot(estate, &dmlstate->ps); + ExecAssignResultType(&dmlstate->ps, tupDesc); + slot = dmlstate->ps.ps_ResultTupleSlot; + + List *rliststate = (List *) ExecInitExpr((Expr *) node->returningList, &dmlstate->ps); + resultRelInfo->ri_projectReturning = + ExecBuildProjectionInfo(rliststate, dmlstate->ps.ps_ExprContext, slot, + resultRelInfo->ri_RelationDesc->rd_att); + + /* Set up a tuple table slot for use for trigger output tuples */ + if (estate->es_trig_tuple_slot == NULL) + estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate); + + /* temporary store created tuple in dedicated state field and restore saved */ + dmlstate->resultTupleSlot = slot; + dmlstate->ps.ps_ResultTupleSlot = savedResultTuple; + } + /* * The comment below is related to ExecInsert(). The code works correctly, * because insert operations always translate full set of attrs to @@ -348,9 +435,32 @@ ExecEndDML(DMLState *node) ReleaseTupleDesc(node->junkfilter->jf_cleanTupType); ExecFreeExprContext(&node->ps); - ExecClearTuple(node->ps.ps_ResultTupleSlot); + if (node->ps.ps_ResultTupleSlot != NULL) + { + ExecClearTuple(node->ps.ps_ResultTupleSlot); + } ExecClearTuple(node->cleanedUpSlot); ExecEndNode(outerPlanState(node)); EndPlanStateGpmonPkt(&node->ps); } + +void +ExecSquelchDML(DMLState *node) +{ + /* + * DML nodes must run to completion when asked to Squelch so + * that we don't risk losing modifications which should be performed + * regardless of any LIMIT's or other forms for projections which could + * end up causing a squelch to happen. + */ + for (;;) + { + TupleTableSlot *result; + + result = ExecDML(node); + if (!result) + break; + } +} + /* EOF */ diff --git a/src/backend/executor/nodeMotion.c b/src/backend/executor/nodeMotion.c index 86de436ef3f6..e092a8b85543 100644 --- a/src/backend/executor/nodeMotion.c +++ b/src/backend/executor/nodeMotion.c @@ -279,7 +279,7 @@ execMotionSender(MotionState *node) /* need refactor */ if (node->isExplictGatherMotion) { - numsegments = motion->plan.flow->numsegments; + numsegments = motion->plan.flow != NULL ? motion->plan.flow->numsegments : node->numInputSegs; } diff --git a/src/backend/executor/nodeSplitUpdate.c b/src/backend/executor/nodeSplitUpdate.c index 32b89e7d19d3..ebc7012a7c17 100644 --- a/src/backend/executor/nodeSplitUpdate.c +++ b/src/backend/executor/nodeSplitUpdate.c @@ -173,7 +173,7 @@ SplitUpdateState* ExecInitSplitUpdate(SplitUpdate *node, EState *estate, int eflags) { /* Check for unsupported flags */ - Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK | EXEC_FLAG_REWIND))); + Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); bool has_oids; diff --git a/src/backend/gpopt/translate/CCTEListEntry.cpp b/src/backend/gpopt/translate/CCTEListEntry.cpp index f15e4284813f..dfa86ebce34b 100644 --- a/src/backend/gpopt/translate/CCTEListEntry.cpp +++ b/src/backend/gpopt/translate/CCTEListEntry.cpp @@ -45,9 +45,11 @@ CCTEListEntry::CCTEListEntry(CMemoryPool *mp, ULONG query_level, #ifdef GPOS_DEBUG BOOL result = #endif - m_cte_info->Insert( - cte->ctename, - GPOS_NEW(mp) SCTEProducerInfo(cte_producer, cte_query->targetList)); + m_cte_info->Insert(cte->ctename, + GPOS_NEW(mp) SCTEProducerInfo( + cte_producer, cte_query->returningList != NULL + ? cte_query->returningList + : cte_query->targetList)); GPOS_ASSERT(result); } diff --git a/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp b/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp index 0bd321cc028e..316bba6c2036 100644 --- a/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp +++ b/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp @@ -80,6 +80,8 @@ CTranslatorDXLToPlStmt::CTranslatorDXLToPlStmt( m_md_accessor(md_accessor), m_dxl_to_plstmt_context(dxl_to_plstmt_context), m_cmd_type(CMD_SELECT), + m_has_returning(false), + m_returning_dml_on_replicated(false), m_is_tgt_tbl_distributed(false), m_result_rel_list(NULL), m_num_of_segments(num_of_segments), @@ -263,6 +265,7 @@ CTranslatorDXLToPlStmt::GetPlannedStmtFromDXL(const CDXLNode *dxlnode, m_dxl_to_plstmt_context->GetCurrentMotionId() - 1; planned_stmt->commandType = m_cmd_type; + planned_stmt->hasReturning = m_has_returning; GPOS_ASSERT(plan->nMotionNodes >= 0); if (0 == plan->nMotionNodes && !m_is_tgt_tbl_distributed) @@ -2282,6 +2285,14 @@ CTranslatorDXLToPlStmt::TranslateDXLMotion( flow->flotype = FLOW_UNDEFINED; } + if (m_returning_dml_on_replicated && input_segids_array->Size() == 1) + { + // we set locus type in child node in this case + // to filter doubling output on executor side + flow->locustype = CdbLocusType_Replicated; + } + m_returning_dml_on_replicated = false; + child_plan->flow = flow; motion->motionID = m_dxl_to_plstmt_context->GetNextMotionId(); @@ -4171,7 +4182,8 @@ CTranslatorDXLToPlStmt::TranslateDXLDml( m_dxl_to_plstmt_context->AddRTE(rte); CDXLNode *project_list_dxlnode = (*dml_dxlnode)[0]; - CDXLNode *child_dxlnode = (*dml_dxlnode)[1]; + CDXLNode *project_list_output_dxlnode = (*dml_dxlnode)[1]; + CDXLNode *child_dxlnode = (*dml_dxlnode)[2]; CDXLTranslateContext child_context(m_mp, false, output_context->GetColIdToParamIdMap()); @@ -4189,6 +4201,18 @@ CTranslatorDXLToPlStmt::TranslateDXLDml( NULL, // translate context for the base table child_contexts, output_context); + dml->returningList = + TranslateDXLProjList(project_list_output_dxlnode, &base_table_context, + child_contexts, output_context); + + m_has_returning = m_has_returning || dml->returningList != NIL; + + if (dml->returningList != NIL && + md_rel->GetRelDistribution() == IMDRelation::EreldistrReplicated) + { + m_returning_dml_on_replicated = true; + } + // Create target list with nulls if rel has dropped cols. DELETE may have // empty target list if there no after trigger present. Skip creating in // such case. diff --git a/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp b/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp index 0388d87a56a9..df0130779539 100644 --- a/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp +++ b/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp @@ -492,11 +492,6 @@ CTranslatorQueryToDXL::TranslateSelectQueryToDXL() // We therefore need to check permissions before we go into optimization for all RTEs, including the ones not explicitly referred in the query, e.g. views. CTranslatorUtils::CheckRTEPermissions(m_query->rtable); - // RETURNING is not supported yet. - if (m_query->returningList) - GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiQuery2DXLUnsupportedFeature, - GPOS_WSZ_LIT("RETURNING clause")); - CDXLNode *child_dxlnode = NULL; IntToUlongMap *sort_group_attno_to_colid_mapping = GPOS_NEW(m_mp) IntToUlongMap(m_mp); @@ -817,7 +812,32 @@ CTranslatorQueryToDXL::TranslateInsertQueryToDXL() query_dxlnode = project_dxlnode; } - return GPOS_NEW(m_mp) CDXLNode(m_mp, insert_dxlnode, query_dxlnode); + CDXLNode *log_insert_dxlnode = + GPOS_NEW(m_mp) CDXLNode(m_mp, insert_dxlnode, query_dxlnode); + + CRefCount::SafeRelease(m_dxl_query_output_cols); + if (NULL != m_query->returningList) + { + IntToUlongMap *output_attno_to_colid_mapping = + GPOS_NEW(m_mp) IntToUlongMap(m_mp); + + log_insert_dxlnode = ProcessReturningList( + log_insert_dxlnode, table_descr, output_attno_to_colid_mapping); + + // this array is filled earlier with target list and was used to get colids by their indices earlier + // now fill it with what will truly be returned + m_dxl_query_output_cols = CreateDXLOutputCols( + m_query->returningList, output_attno_to_colid_mapping); + + output_attno_to_colid_mapping->Release(); + } + else + { + // we can safely set it to empty array here as we aren't outputting in this path + m_dxl_query_output_cols = GPOS_NEW(m_mp) CDXLNodeArray(m_mp); + } + + return log_insert_dxlnode; } //--------------------------------------------------------------------------- @@ -834,6 +854,16 @@ CTranslatorQueryToDXL::TranslateCTASToDXL() GPOS_ASSERT(CMD_SELECT == m_query->commandType); //GPOS_ASSERT(NULL != m_query->intoClause); + if (m_query->hasModifyingCTE) + { + // GPDB cannot have two writer segworker groups for one query. + // Furtherly, during execution stage an error will be thrown. + // However, showing the error early during translating stage would be more effective + GPOS_RAISE( + gpdxl::ExmaDXL, gpdxl::ExmiQuery2DXLUnsupportedFeature, + GPOS_WSZ_LIT("cannot create plan with several writing gangs")); + } + m_is_ctas_query = true; CDXLNode *query_dxlnode = TranslateSelectQueryToDXL(); @@ -1137,6 +1167,53 @@ CTranslatorQueryToDXL::GetSystemColId(INT attribute_number) return res; } +//--------------------------------------------------------------------------- +// @function: +// CTranslatorQueryToDXL::ProcessReturningList +// +// @doc: Wrap dxl node in logical project with return columns from returningList +// +//--------------------------------------------------------------------------- +CDXLNode * +CTranslatorQueryToDXL::ProcessReturningList( + CDXLNode *dml_dxlnode, CDXLTableDescr *table_descr, + IntToUlongMap *output_attno_to_colid_mapping) +{ + GPOS_ASSERT(m_query->returningList != NULL); + + CMappingVarColId *var_to_colid_map = GPOS_NEW(m_mp) CMappingVarColId(m_mp); + var_to_colid_map->LoadTblColumns(m_query_level, m_query->resultRelation, + table_descr); + + CDXLNode *returning_proj_list_dxlnode = + GPOS_NEW(m_mp) CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarProjList(m_mp)); + + ListCell *lc = NULL; + ForEach(lc, m_query->returningList) + { + TargetEntry *target_entry = (TargetEntry *) lfirst(lc); + + CDXLNode *project_elem_dxlnode = TranslateExprToDXLProject( + target_entry->expr, target_entry->resname, var_to_colid_map, true); + + ULONG colid = + CDXLScalarProjElem::Cast(project_elem_dxlnode->GetOperator())->Id(); + StoreAttnoColIdMapping(output_attno_to_colid_mapping, + target_entry->resno, colid); + + returning_proj_list_dxlnode->AddChild(project_elem_dxlnode); + } + + CDXLNode *project_dxlnode = + GPOS_NEW(m_mp) CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLLogicalProject(m_mp)); + project_dxlnode->AddChild(returning_proj_list_dxlnode); + project_dxlnode->AddChild(dml_dxlnode); + + GPOS_DELETE(var_to_colid_map); + + return project_dxlnode; +} + //--------------------------------------------------------------------------- // @function: // CTranslatorQueryToDXL::TranslateDeleteQueryToDXL @@ -1214,7 +1291,32 @@ CTranslatorQueryToDXL::TranslateDeleteQueryToDXL() CDXLLogicalDelete(m_mp, table_descr, ctid_colid, segid_colid, delete_colid_array, tableoid_colid); - return GPOS_NEW(m_mp) CDXLNode(m_mp, delete_dxlop, query_dxlnode); + CDXLNode *log_delete_dxlnode = + GPOS_NEW(m_mp) CDXLNode(m_mp, delete_dxlop, query_dxlnode); + + CRefCount::SafeRelease(m_dxl_query_output_cols); + if (NULL != m_query->returningList) + { + IntToUlongMap *output_attno_to_colid_mapping = + GPOS_NEW(m_mp) IntToUlongMap(m_mp); + + log_delete_dxlnode = ProcessReturningList( + log_delete_dxlnode, table_descr, output_attno_to_colid_mapping); + + // this array is filled earlier with target list and was used to get colids by their indices earlier + // now fill it with what will truly be returned + m_dxl_query_output_cols = CreateDXLOutputCols( + m_query->returningList, output_attno_to_colid_mapping); + + output_attno_to_colid_mapping->Release(); + } + else + { + // we can safely set it to empty array here as we aren't outputting in this path + m_dxl_query_output_cols = GPOS_NEW(m_mp) CDXLNodeArray(m_mp); + } + + return log_delete_dxlnode; } //--------------------------------------------------------------------------- @@ -1328,7 +1430,32 @@ CTranslatorQueryToDXL::TranslateUpdateQueryToDXL() m_mp, table_descr, ctid_colid, segmentid_colid, delete_colid_array, insert_colid_array, has_oids, tuple_oid_colid, tableoid_colid); - return GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopupdate, query_dxlnode); + CDXLNode *log_update_dxlnode = + GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopupdate, query_dxlnode); + + CRefCount::SafeRelease(m_dxl_query_output_cols); + if (NULL != m_query->returningList) + { + IntToUlongMap *output_attno_to_colid_mapping = + GPOS_NEW(m_mp) IntToUlongMap(m_mp); + + log_update_dxlnode = ProcessReturningList( + log_update_dxlnode, table_descr, output_attno_to_colid_mapping); + + // this array is filled earlier with target list and was used to get colids by their indices earlier + // now fill it with what will truly be returned + m_dxl_query_output_cols = CreateDXLOutputCols( + m_query->returningList, output_attno_to_colid_mapping); + + output_attno_to_colid_mapping->Release(); + } + else + { + // we can safely set it to empty array here as we aren't outputting in this path + m_dxl_query_output_cols = GPOS_NEW(m_mp) CDXLNodeArray(m_mp); + } + + return log_update_dxlnode; } //--------------------------------------------------------------------------- @@ -3891,9 +4018,24 @@ CTranslatorQueryToDXL::TranslateDerivedTablesToDXL(const RangeTblEntry *rte, //--------------------------------------------------------------------------- CDXLNode * CTranslatorQueryToDXL::TranslateExprToDXL(Expr *expr) +{ + return TranslateExprToDXL(expr, m_var_to_colid_map); +} + +//--------------------------------------------------------------------------- +// @function: +// CTranslatorQueryToDXL::TranslateExprToDXL +// +// @doc: +// Translate the Expr into a CDXLScalar node with specified mapping +// +//--------------------------------------------------------------------------- +CDXLNode * +CTranslatorQueryToDXL::TranslateExprToDXL(Expr *expr, + CMappingVarColId *var_to_colid_map) { CDXLNode *scalar_dxlnode = - m_scalar_translator->TranslateScalarToDXL(expr, m_var_to_colid_map); + m_scalar_translator->TranslateScalarToDXL(expr, var_to_colid_map); GPOS_ASSERT(NULL != scalar_dxlnode); return scalar_dxlnode; @@ -4445,11 +4587,29 @@ CDXLNode * CTranslatorQueryToDXL::TranslateExprToDXLProject(Expr *expr, const CHAR *alias_name, BOOL insist_new_colids) +{ + return TranslateExprToDXLProject(expr, alias_name, m_var_to_colid_map, + insist_new_colids); +} + +//--------------------------------------------------------------------------- +// @function: +// CTranslatorQueryToDXL::TranslateExprToDXLProject +// +// @doc: +// Create a DXL project element node from the target list entry or var. +// The function allocates memory in the translator memory pool, and the caller +// is responsible for freeing it. +//--------------------------------------------------------------------------- +CDXLNode * +CTranslatorQueryToDXL::TranslateExprToDXLProject( + Expr *expr, const CHAR *alias_name, CMappingVarColId *var_to_colid_map, + BOOL insist_new_colids) { GPOS_ASSERT(NULL != expr); // construct a scalar operator - CDXLNode *child_dxlnode = TranslateExprToDXL(expr); + CDXLNode *child_dxlnode = TranslateExprToDXL(expr, var_to_colid_map); // get the id and alias for the proj elem ULONG project_elem_id; @@ -4606,7 +4766,7 @@ CTranslatorQueryToDXL::ConstructCTEProducerList(List *cte_list, // translate query representing the cte table to its DXL representation CDXLNode *cte_child_dxlnode = - query_to_dxl_translator.TranslateSelectQueryToDXL(); + query_to_dxl_translator.TranslateQueryToDXL(); // get the output columns of the cte table CDXLNodeArray *cte_query_output_colds_dxlnode_array = diff --git a/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-1.mdp b/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-1.mdp index 49090951fc8e..b8870a0ae449 100644 --- a/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-1.mdp +++ b/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-1.mdp @@ -207,10 +207,7 @@ - - - - + @@ -244,9 +241,9 @@ - + - + @@ -257,17 +254,16 @@ + - - - - - - - - - + + + + + + + @@ -281,8 +277,8 @@ - - + + @@ -298,7 +294,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-2.mdp b/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-2.mdp index 4412465aadb9..843693d89d4e 100644 --- a/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-2.mdp +++ b/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-2.mdp @@ -198,10 +198,7 @@ - - - - + @@ -251,9 +248,9 @@ - + - + @@ -264,17 +261,16 @@ + - - - - - - - - - + + + + + + + @@ -288,8 +284,8 @@ - - + + @@ -305,7 +301,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-3.mdp b/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-3.mdp index f6b3a2994cfa..406721faec97 100644 --- a/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-3.mdp +++ b/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-3.mdp @@ -228,10 +228,7 @@ - - - - + @@ -281,9 +278,9 @@ - + - + @@ -294,17 +291,16 @@ + - - - - - - - - - + + + + + + + @@ -318,8 +314,8 @@ - - + + @@ -335,7 +331,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-4.mdp b/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-4.mdp index 1edb39f961e8..c71abd37984f 100644 --- a/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-4.mdp +++ b/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-4.mdp @@ -245,10 +245,7 @@ - - - - + @@ -335,9 +332,9 @@ - + - + @@ -348,17 +345,16 @@ + - - - - - - - - - + + + + + + + @@ -372,8 +368,8 @@ - - + + @@ -389,7 +385,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-5.mdp b/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-5.mdp index dbf0477c35ad..fa0a8958c6bd 100644 --- a/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-5.mdp +++ b/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-5.mdp @@ -214,10 +214,7 @@ - - - - + @@ -251,9 +248,9 @@ - + - + @@ -264,17 +261,16 @@ + - - - - - - - - - + + + + + + + @@ -288,8 +284,8 @@ - - + + @@ -305,7 +301,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/CPhysicalParallelUnionAllTest/ParallelAppend-Insert.mdp b/src/backend/gporca/data/dxl/minidump/CPhysicalParallelUnionAllTest/ParallelAppend-Insert.mdp index 68e9e4d3b960..cbf383d50d86 100644 --- a/src/backend/gporca/data/dxl/minidump/CPhysicalParallelUnionAllTest/ParallelAppend-Insert.mdp +++ b/src/backend/gporca/data/dxl/minidump/CPhysicalParallelUnionAllTest/ParallelAppend-Insert.mdp @@ -142,9 +142,7 @@ INSERT INTO t VALUES (11),(12),(13); - - - + @@ -191,9 +189,9 @@ INSERT INTO t VALUES (11),(12),(13); - + - + @@ -201,16 +199,17 @@ INSERT INTO t VALUES (11),(12),(13); + - - - - - - - - + + + + + + + + @@ -221,7 +220,7 @@ INSERT INTO t VALUES (11),(12),(13); - + diff --git a/src/backend/gporca/data/dxl/minidump/CTAS-Random.mdp b/src/backend/gporca/data/dxl/minidump/CTAS-Random.mdp index 97c43a0ca69d..89311fe170bf 100644 --- a/src/backend/gporca/data/dxl/minidump/CTAS-Random.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTAS-Random.mdp @@ -213,8 +213,8 @@ - - + + @@ -236,7 +236,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/CTAS-With-Global-Local-Agg.mdp b/src/backend/gporca/data/dxl/minidump/CTAS-With-Global-Local-Agg.mdp index d1447b6788f2..fd0a0fc4cc87 100644 --- a/src/backend/gporca/data/dxl/minidump/CTAS-With-Global-Local-Agg.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTAS-With-Global-Local-Agg.mdp @@ -717,7 +717,7 @@ - + @@ -733,7 +733,7 @@ - + @@ -757,9 +757,9 @@ - + - + @@ -773,8 +773,8 @@ - - + + @@ -785,10 +785,10 @@ - - + + - + diff --git a/src/backend/gporca/data/dxl/minidump/CTAS-random-distr.mdp b/src/backend/gporca/data/dxl/minidump/CTAS-random-distr.mdp index 774f0fa5e24f..81505553e034 100644 --- a/src/backend/gporca/data/dxl/minidump/CTAS-random-distr.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTAS-random-distr.mdp @@ -178,9 +178,9 @@ - - - + + + @@ -208,8 +208,8 @@ - - + + @@ -228,7 +228,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/CTAS-random-distributed-from-replicated-distributed-table.mdp b/src/backend/gporca/data/dxl/minidump/CTAS-random-distributed-from-replicated-distributed-table.mdp index bbaf037be151..cb5dd26fd068 100644 --- a/src/backend/gporca/data/dxl/minidump/CTAS-random-distributed-from-replicated-distributed-table.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTAS-random-distributed-from-replicated-distributed-table.mdp @@ -243,8 +243,8 @@ - - + + @@ -266,8 +266,8 @@ - - + + @@ -283,7 +283,7 @@ - + @@ -316,7 +316,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/CTAS-with-Limit.mdp b/src/backend/gporca/data/dxl/minidump/CTAS-with-Limit.mdp index e1db851c6cdc..892b40a0e1b0 100644 --- a/src/backend/gporca/data/dxl/minidump/CTAS-with-Limit.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTAS-with-Limit.mdp @@ -656,8 +656,8 @@ - - + + @@ -679,7 +679,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/CTAS-with-hashed-distributed-external-table.mdp b/src/backend/gporca/data/dxl/minidump/CTAS-with-hashed-distributed-external-table.mdp index 4163127856d3..5278b5afe947 100644 --- a/src/backend/gporca/data/dxl/minidump/CTAS-with-hashed-distributed-external-table.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTAS-with-hashed-distributed-external-table.mdp @@ -247,9 +247,9 @@ EXPLAIN CREATE TABLE Test AS SELECT * FROM test_gpfdist_ext DISTRIBUTED BY (a); - - - + + + @@ -277,7 +277,7 @@ EXPLAIN CREATE TABLE Test AS SELECT * FROM test_gpfdist_ext DISTRIBUTED BY (a); - + diff --git a/src/backend/gporca/data/dxl/minidump/CTAS-with-randomly-distributed-external-table.mdp b/src/backend/gporca/data/dxl/minidump/CTAS-with-randomly-distributed-external-table.mdp index 50ea84fb45c8..6b856921ebcc 100644 --- a/src/backend/gporca/data/dxl/minidump/CTAS-with-randomly-distributed-external-table.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTAS-with-randomly-distributed-external-table.mdp @@ -234,9 +234,9 @@ EXPLAIN CREATE TABLE Test AS SELECT * FROM test_ext DISTRIBUTED RANDOMLY; - - - + + + @@ -264,8 +264,8 @@ EXPLAIN CREATE TABLE Test AS SELECT * FROM test_ext DISTRIBUTED RANDOMLY; - - + + @@ -284,7 +284,7 @@ EXPLAIN CREATE TABLE Test AS SELECT * FROM test_ext DISTRIBUTED RANDOMLY; - + diff --git a/src/backend/gporca/data/dxl/minidump/CTAS.mdp b/src/backend/gporca/data/dxl/minidump/CTAS.mdp index 2323355c74bb..00618b0ce76b 100644 --- a/src/backend/gporca/data/dxl/minidump/CTAS.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTAS.mdp @@ -223,8 +223,8 @@ - - + + @@ -246,7 +246,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/CTAS_OrderedAgg_multiple_cols.mdp b/src/backend/gporca/data/dxl/minidump/CTAS_OrderedAgg_multiple_cols.mdp index 7d05fe0c4deb..be5008e1ae8b 100644 --- a/src/backend/gporca/data/dxl/minidump/CTAS_OrderedAgg_multiple_cols.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTAS_OrderedAgg_multiple_cols.mdp @@ -1815,9 +1815,9 @@ EXPLAIN CREATE TABLE test AS - - - + + + @@ -1845,7 +1845,7 @@ EXPLAIN CREATE TABLE test AS - + @@ -1913,16 +1913,16 @@ EXPLAIN CREATE TABLE test AS - + - - + + - - + + @@ -1930,16 +1930,16 @@ EXPLAIN CREATE TABLE test AS - + - - + + - + - + @@ -1953,13 +1953,13 @@ EXPLAIN CREATE TABLE test AS - - + + - + @@ -1968,23 +1968,23 @@ EXPLAIN CREATE TABLE test AS - - + + - - - - - - - - - - + + + + + + + + + + @@ -2024,16 +2024,16 @@ EXPLAIN CREATE TABLE test AS - + - - + + - - + + @@ -2041,16 +2041,16 @@ EXPLAIN CREATE TABLE test AS - + - - + + - + - + @@ -2064,13 +2064,13 @@ EXPLAIN CREATE TABLE test AS - - + + - + @@ -2079,15 +2079,15 @@ EXPLAIN CREATE TABLE test AS - - + + - + @@ -2095,23 +2095,23 @@ EXPLAIN CREATE TABLE test AS - - + + - - - - - - - - - - + + + + + + + + + + @@ -2152,16 +2152,16 @@ EXPLAIN CREATE TABLE test AS - + - - + + - - + + @@ -2169,16 +2169,16 @@ EXPLAIN CREATE TABLE test AS - + - - + + - + - + @@ -2192,13 +2192,13 @@ EXPLAIN CREATE TABLE test AS - - + + - + @@ -2207,15 +2207,15 @@ EXPLAIN CREATE TABLE test AS - - + + - + @@ -2223,23 +2223,23 @@ EXPLAIN CREATE TABLE test AS - - + + - - - - - - - - - - + + + + + + + + + + @@ -2360,8 +2360,8 @@ EXPLAIN CREATE TABLE test AS - - + + @@ -2375,8 +2375,8 @@ EXPLAIN CREATE TABLE test AS - - + + @@ -2390,8 +2390,8 @@ EXPLAIN CREATE TABLE test AS - - + + @@ -2408,11 +2408,11 @@ EXPLAIN CREATE TABLE test AS - - + + - - + + @@ -2423,11 +2423,11 @@ EXPLAIN CREATE TABLE test AS - - + + - - + + @@ -2442,18 +2442,18 @@ EXPLAIN CREATE TABLE test AS - - + + - - + + - + @@ -2461,8 +2461,8 @@ EXPLAIN CREATE TABLE test AS - - + + @@ -2471,8 +2471,8 @@ EXPLAIN CREATE TABLE test AS - - + + @@ -2481,9 +2481,9 @@ EXPLAIN CREATE TABLE test AS - - - + + + @@ -2494,8 +2494,8 @@ EXPLAIN CREATE TABLE test AS - - + + @@ -2506,10 +2506,10 @@ EXPLAIN CREATE TABLE test AS - + - + @@ -2523,8 +2523,8 @@ EXPLAIN CREATE TABLE test AS - - + + @@ -2535,10 +2535,10 @@ EXPLAIN CREATE TABLE test AS - + - + @@ -2547,16 +2547,16 @@ EXPLAIN CREATE TABLE test AS - + - - + + - - + + @@ -2605,8 +2605,8 @@ EXPLAIN CREATE TABLE test AS - - + + @@ -2620,8 +2620,8 @@ EXPLAIN CREATE TABLE test AS - - + + @@ -2635,8 +2635,8 @@ EXPLAIN CREATE TABLE test AS - - + + @@ -2653,11 +2653,11 @@ EXPLAIN CREATE TABLE test AS - - + + - - + + @@ -2668,11 +2668,11 @@ EXPLAIN CREATE TABLE test AS - - + + - - + + @@ -2687,18 +2687,18 @@ EXPLAIN CREATE TABLE test AS - - + + - - + + - + @@ -2706,8 +2706,8 @@ EXPLAIN CREATE TABLE test AS - - + + @@ -2716,8 +2716,8 @@ EXPLAIN CREATE TABLE test AS - - + + @@ -2726,8 +2726,8 @@ EXPLAIN CREATE TABLE test AS - - + + @@ -2737,9 +2737,9 @@ EXPLAIN CREATE TABLE test AS - - - + + + @@ -2751,10 +2751,10 @@ EXPLAIN CREATE TABLE test AS - + - + @@ -2768,8 +2768,8 @@ EXPLAIN CREATE TABLE test AS - - + + @@ -2780,10 +2780,10 @@ EXPLAIN CREATE TABLE test AS - + - + @@ -2792,16 +2792,16 @@ EXPLAIN CREATE TABLE test AS - + - - + + - - + + @@ -2852,8 +2852,8 @@ EXPLAIN CREATE TABLE test AS - - + + @@ -2867,8 +2867,8 @@ EXPLAIN CREATE TABLE test AS - - + + @@ -2882,8 +2882,8 @@ EXPLAIN CREATE TABLE test AS - - + + @@ -2900,11 +2900,11 @@ EXPLAIN CREATE TABLE test AS - - + + - - + + @@ -2915,11 +2915,11 @@ EXPLAIN CREATE TABLE test AS - - + + - - + + @@ -2934,18 +2934,18 @@ EXPLAIN CREATE TABLE test AS - - + + - - + + - + @@ -2953,8 +2953,8 @@ EXPLAIN CREATE TABLE test AS - - + + @@ -2963,8 +2963,8 @@ EXPLAIN CREATE TABLE test AS - - + + @@ -2973,8 +2973,8 @@ EXPLAIN CREATE TABLE test AS - - + + @@ -2984,9 +2984,9 @@ EXPLAIN CREATE TABLE test AS - - - + + + @@ -2998,10 +2998,10 @@ EXPLAIN CREATE TABLE test AS - + - + @@ -3015,8 +3015,8 @@ EXPLAIN CREATE TABLE test AS - - + + @@ -3027,10 +3027,10 @@ EXPLAIN CREATE TABLE test AS - + - + @@ -3039,16 +3039,16 @@ EXPLAIN CREATE TABLE test AS - + - - + + - - + + diff --git a/src/backend/gporca/data/dxl/minidump/ConvertHashToRandomInsert.mdp b/src/backend/gporca/data/dxl/minidump/ConvertHashToRandomInsert.mdp index 6b3fa10d1d77..bb1d6aa840d5 100644 --- a/src/backend/gporca/data/dxl/minidump/ConvertHashToRandomInsert.mdp +++ b/src/backend/gporca/data/dxl/minidump/ConvertHashToRandomInsert.mdp @@ -597,10 +597,7 @@ explain analyze insert into t1 select t2.a,t3.b from t2, t3 where t2.a = t3.a; - - - - + @@ -643,9 +640,9 @@ explain analyze insert into t1 select t2.a,t3.b from t2, t3 where t2.a = t3.a; - + - + @@ -656,13 +653,13 @@ explain analyze insert into t1 select t2.a,t3.b from t2, t3 where t2.a = t3.a; + - - - - - + + + + @@ -676,7 +673,7 @@ explain analyze insert into t1 select t2.a,t3.b from t2, t3 where t2.a = t3.a; - + diff --git a/src/backend/gporca/data/dxl/minidump/DML-ComputeScalar-With-Outerref.mdp b/src/backend/gporca/data/dxl/minidump/DML-ComputeScalar-With-Outerref.mdp index 7fa3c0255346..85fb2b4368f9 100644 --- a/src/backend/gporca/data/dxl/minidump/DML-ComputeScalar-With-Outerref.mdp +++ b/src/backend/gporca/data/dxl/minidump/DML-ComputeScalar-With-Outerref.mdp @@ -236,9 +236,7 @@ - - - + @@ -319,9 +317,9 @@ - + - + @@ -329,16 +327,17 @@ + - - - - - - - - + + + + + + + + @@ -349,7 +348,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DML-Filter-With-OuterRef.mdp b/src/backend/gporca/data/dxl/minidump/DML-Filter-With-OuterRef.mdp index 7d25616af5ce..f8fe38d54e5b 100644 --- a/src/backend/gporca/data/dxl/minidump/DML-Filter-With-OuterRef.mdp +++ b/src/backend/gporca/data/dxl/minidump/DML-Filter-With-OuterRef.mdp @@ -261,9 +261,7 @@ - - - + @@ -340,9 +338,9 @@ - + - + @@ -350,16 +348,17 @@ + - - - - - - - - + + + + + + + + @@ -370,7 +369,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DML-Replicated-Input.mdp b/src/backend/gporca/data/dxl/minidump/DML-Replicated-Input.mdp index 9deff61aa45e..34807789dc6a 100644 --- a/src/backend/gporca/data/dxl/minidump/DML-Replicated-Input.mdp +++ b/src/backend/gporca/data/dxl/minidump/DML-Replicated-Input.mdp @@ -269,11 +269,7 @@ WHERE sach_vsnr = 465132477; - - - - - + @@ -339,9 +335,9 @@ WHERE sach_vsnr = 465132477; - + - + @@ -359,18 +355,17 @@ WHERE sach_vsnr = 465132477; + - - - - - - - - - - + + + + + + + + @@ -387,8 +382,8 @@ WHERE sach_vsnr = 465132477; - - + + @@ -410,11 +405,11 @@ WHERE sach_vsnr = 465132477; - + - + diff --git a/src/backend/gporca/data/dxl/minidump/DML-UnionAll-With-OuterRef.mdp b/src/backend/gporca/data/dxl/minidump/DML-UnionAll-With-OuterRef.mdp index 75b6255961de..af3cc95e63a0 100644 --- a/src/backend/gporca/data/dxl/minidump/DML-UnionAll-With-OuterRef.mdp +++ b/src/backend/gporca/data/dxl/minidump/DML-UnionAll-With-OuterRef.mdp @@ -291,9 +291,7 @@ - - - + @@ -387,9 +385,9 @@ - + - + @@ -397,16 +395,17 @@ + - - - - - - - - + + + + + + + + @@ -417,7 +416,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DML-UnionAll-With-Universal-Child.mdp b/src/backend/gporca/data/dxl/minidump/DML-UnionAll-With-Universal-Child.mdp index 1575731dddc4..e54aaafd068e 100644 --- a/src/backend/gporca/data/dxl/minidump/DML-UnionAll-With-Universal-Child.mdp +++ b/src/backend/gporca/data/dxl/minidump/DML-UnionAll-With-Universal-Child.mdp @@ -209,9 +209,7 @@ - - - + @@ -270,9 +268,9 @@ - + - + @@ -280,16 +278,17 @@ + - - - - - - - - + + + + + + + + @@ -300,8 +299,8 @@ - - + + @@ -319,7 +318,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DML-Volatile-Function.mdp b/src/backend/gporca/data/dxl/minidump/DML-Volatile-Function.mdp index 150968b16a45..7bb05904ad79 100644 --- a/src/backend/gporca/data/dxl/minidump/DML-Volatile-Function.mdp +++ b/src/backend/gporca/data/dxl/minidump/DML-Volatile-Function.mdp @@ -201,9 +201,7 @@ - - - + @@ -249,9 +247,9 @@ - + - + @@ -259,16 +257,17 @@ + - - - - - - - - + + + + + + + + @@ -279,8 +278,8 @@ - - + + @@ -298,7 +297,7 @@ - + @@ -330,7 +329,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DML-With-CorrelatedNLJ-With-Universal-Child.mdp b/src/backend/gporca/data/dxl/minidump/DML-With-CorrelatedNLJ-With-Universal-Child.mdp index 2d217a035871..863d6f461994 100644 --- a/src/backend/gporca/data/dxl/minidump/DML-With-CorrelatedNLJ-With-Universal-Child.mdp +++ b/src/backend/gporca/data/dxl/minidump/DML-With-CorrelatedNLJ-With-Universal-Child.mdp @@ -230,9 +230,7 @@ - - - + @@ -283,9 +281,9 @@ - + - + @@ -297,16 +295,17 @@ + - - - - - - - - + + + + + + + + @@ -317,8 +316,8 @@ - - + + @@ -336,7 +335,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DML-With-HJ-And-UniversalChild.mdp b/src/backend/gporca/data/dxl/minidump/DML-With-HJ-And-UniversalChild.mdp index 3ba8bf406547..d7e47246ce50 100644 --- a/src/backend/gporca/data/dxl/minidump/DML-With-HJ-And-UniversalChild.mdp +++ b/src/backend/gporca/data/dxl/minidump/DML-With-HJ-And-UniversalChild.mdp @@ -712,22 +712,23 @@ - + + - - - - - - - - + + + + + + + + @@ -741,7 +742,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DML-With-Join-With-Universal-Child.mdp b/src/backend/gporca/data/dxl/minidump/DML-With-Join-With-Universal-Child.mdp index e50b711dcf67..61af032c2c14 100644 --- a/src/backend/gporca/data/dxl/minidump/DML-With-Join-With-Universal-Child.mdp +++ b/src/backend/gporca/data/dxl/minidump/DML-With-Join-With-Universal-Child.mdp @@ -185,9 +185,7 @@ - - - + @@ -238,9 +236,9 @@ - + - + @@ -248,16 +246,17 @@ + - - - - - - - - + + + + + + + + @@ -268,8 +267,8 @@ - - + + @@ -287,7 +286,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DML-With-MasterOnlyTable-1.mdp b/src/backend/gporca/data/dxl/minidump/DML-With-MasterOnlyTable-1.mdp index 72a1d843aa12..a9ea9b9892c1 100644 --- a/src/backend/gporca/data/dxl/minidump/DML-With-MasterOnlyTable-1.mdp +++ b/src/backend/gporca/data/dxl/minidump/DML-With-MasterOnlyTable-1.mdp @@ -367,22 +367,23 @@ - + + - - - - - - - - + + + + + + + + @@ -396,7 +397,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DML-With-WindowFunc-OuterRef.mdp b/src/backend/gporca/data/dxl/minidump/DML-With-WindowFunc-OuterRef.mdp index 9eb9b5249fd2..0867830e9e5c 100644 --- a/src/backend/gporca/data/dxl/minidump/DML-With-WindowFunc-OuterRef.mdp +++ b/src/backend/gporca/data/dxl/minidump/DML-With-WindowFunc-OuterRef.mdp @@ -367,7 +367,7 @@ - + @@ -383,7 +383,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DMLCollapseProject.mdp b/src/backend/gporca/data/dxl/minidump/DMLCollapseProject.mdp index 3e6e8eedd88e..399b4daedbb1 100644 --- a/src/backend/gporca/data/dxl/minidump/DMLCollapseProject.mdp +++ b/src/backend/gporca/data/dxl/minidump/DMLCollapseProject.mdp @@ -292,12 +292,7 @@ - - - - - - + @@ -364,9 +359,9 @@ - + - + @@ -383,19 +378,17 @@ + - - - - - - - - - - - + + + + + + + + @@ -415,8 +408,8 @@ - - + + @@ -443,13 +436,13 @@ - + - + @@ -486,7 +479,7 @@ - + @@ -496,7 +489,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/Delete-With-Limit-In-Subquery.mdp b/src/backend/gporca/data/dxl/minidump/Delete-With-Limit-In-Subquery.mdp index 10d155f5c64a..5a69ae0e56f9 100644 --- a/src/backend/gporca/data/dxl/minidump/Delete-With-Limit-In-Subquery.mdp +++ b/src/backend/gporca/data/dxl/minidump/Delete-With-Limit-In-Subquery.mdp @@ -722,22 +722,23 @@ - + + - - - - - - - - + + + + + + + + @@ -751,7 +752,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DeleteInCTE.mdp b/src/backend/gporca/data/dxl/minidump/DeleteInCTE.mdp new file mode 100644 index 000000000000..687b04441f92 --- /dev/null +++ b/src/backend/gporca/data/dxl/minidump/DeleteInCTE.mdp @@ -0,0 +1,395 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/backend/gporca/data/dxl/minidump/DeleteMismatchedDistribution.mdp b/src/backend/gporca/data/dxl/minidump/DeleteMismatchedDistribution.mdp index 7981139961e2..3a8cede85a9d 100644 --- a/src/backend/gporca/data/dxl/minidump/DeleteMismatchedDistribution.mdp +++ b/src/backend/gporca/data/dxl/minidump/DeleteMismatchedDistribution.mdp @@ -338,24 +338,23 @@ - + + - - - - - - - - - - + + + + + + + + @@ -369,7 +368,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DeleteRandomDistr.mdp b/src/backend/gporca/data/dxl/minidump/DeleteRandomDistr.mdp index 3e0c0bb5176e..8e7954e657aa 100644 --- a/src/backend/gporca/data/dxl/minidump/DeleteRandomDistr.mdp +++ b/src/backend/gporca/data/dxl/minidump/DeleteRandomDistr.mdp @@ -203,23 +203,22 @@ - + + - - - - - - - - - + + + + + + + @@ -233,7 +232,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DeleteRandomlyDistributedTable.mdp b/src/backend/gporca/data/dxl/minidump/DeleteRandomlyDistributedTable.mdp index 7b1cbff5f6ba..5cca4ce4d5af 100644 --- a/src/backend/gporca/data/dxl/minidump/DeleteRandomlyDistributedTable.mdp +++ b/src/backend/gporca/data/dxl/minidump/DeleteRandomlyDistributedTable.mdp @@ -196,22 +196,22 @@ - + - + + - - - - - - - - + + + + + + + @@ -225,7 +225,7 @@ - + @@ -244,7 +244,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DeleteRandomlyDistributedTableJoin.mdp b/src/backend/gporca/data/dxl/minidump/DeleteRandomlyDistributedTableJoin.mdp index 6b11f1b80d69..ab26edfe3494 100644 --- a/src/backend/gporca/data/dxl/minidump/DeleteRandomlyDistributedTableJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/DeleteRandomlyDistributedTableJoin.mdp @@ -278,22 +278,22 @@ - + - + + - - - - - - - - + + + + + + + @@ -307,7 +307,7 @@ - + @@ -385,7 +385,7 @@ - + @@ -409,7 +409,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DeleteReturning.mdp b/src/backend/gporca/data/dxl/minidump/DeleteReturning.mdp new file mode 100644 index 000000000000..516857ac8aab --- /dev/null +++ b/src/backend/gporca/data/dxl/minidump/DeleteReturning.mdp @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/backend/gporca/data/dxl/minidump/DeleteWithAfterTriggerDroppedCol.mdp b/src/backend/gporca/data/dxl/minidump/DeleteWithAfterTriggerDroppedCol.mdp index fc5736e6dd0a..6cb830e68c75 100644 --- a/src/backend/gporca/data/dxl/minidump/DeleteWithAfterTriggerDroppedCol.mdp +++ b/src/backend/gporca/data/dxl/minidump/DeleteWithAfterTriggerDroppedCol.mdp @@ -251,7 +251,7 @@ drop function func_trigger(); - + @@ -261,16 +261,21 @@ drop function func_trigger(); + + + + + - - - - - - - - + + + + + + + + @@ -287,7 +292,7 @@ drop function func_trigger(); - + diff --git a/src/backend/gporca/data/dxl/minidump/DeleteWithTriggers.mdp b/src/backend/gporca/data/dxl/minidump/DeleteWithTriggers.mdp index 12c7c39db808..58488b4151ac 100644 --- a/src/backend/gporca/data/dxl/minidump/DeleteWithTriggers.mdp +++ b/src/backend/gporca/data/dxl/minidump/DeleteWithTriggers.mdp @@ -233,7 +233,7 @@ - + @@ -249,18 +249,27 @@ + + + + + + + + + + + - - - - - - - - - - + + + + + + + + @@ -283,8 +292,8 @@ - - + + @@ -307,7 +316,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DontAddRedistributeBeforeInsert-1.mdp b/src/backend/gporca/data/dxl/minidump/DontAddRedistributeBeforeInsert-1.mdp index 5720e5ef715e..d997793fca6b 100644 --- a/src/backend/gporca/data/dxl/minidump/DontAddRedistributeBeforeInsert-1.mdp +++ b/src/backend/gporca/data/dxl/minidump/DontAddRedistributeBeforeInsert-1.mdp @@ -265,10 +265,7 @@ Physical plan: - - - - + @@ -355,9 +352,9 @@ Physical plan: - + - + @@ -368,17 +365,16 @@ Physical plan: + - - - - - - - - - + + + + + + + @@ -392,7 +388,7 @@ Physical plan: - + diff --git a/src/backend/gporca/data/dxl/minidump/DontAddRedistributeBeforeInsert-2.mdp b/src/backend/gporca/data/dxl/minidump/DontAddRedistributeBeforeInsert-2.mdp index 92b167af0a71..70cfa98457af 100644 --- a/src/backend/gporca/data/dxl/minidump/DontAddRedistributeBeforeInsert-2.mdp +++ b/src/backend/gporca/data/dxl/minidump/DontAddRedistributeBeforeInsert-2.mdp @@ -168,9 +168,7 @@ - - - + @@ -221,9 +219,9 @@ - + - + @@ -231,16 +229,16 @@ + - - - - - - - - + + + + + + + @@ -251,7 +249,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExcept.mdp b/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExcept.mdp index 84b94940e4b7..9a72b0948836 100644 --- a/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExcept.mdp +++ b/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExcept.mdp @@ -203,9 +203,7 @@ ON (a.col = b.col); - - - + @@ -296,9 +294,9 @@ ON (a.col = b.col); - + - + @@ -306,16 +304,17 @@ ON (a.col = b.col); + - - - - - - - - + + + + + + + + @@ -326,7 +325,7 @@ ON (a.col = b.col); - + diff --git a/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExceptAll.mdp b/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExceptAll.mdp index 5eca98beb654..1dc95f988779 100644 --- a/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExceptAll.mdp +++ b/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExceptAll.mdp @@ -241,9 +241,7 @@ ON (a.col = b.col); - - - + @@ -334,9 +332,9 @@ ON (a.col = b.col); - + - + @@ -344,16 +342,17 @@ ON (a.col = b.col); + - - - - - - - - + + + + + + + + @@ -364,7 +363,7 @@ ON (a.col = b.col); - + @@ -430,8 +429,8 @@ ON (a.col = b.col); - - + + @@ -440,7 +439,7 @@ ON (a.col = b.col); - + @@ -539,7 +538,7 @@ ON (a.col = b.col); - + diff --git a/src/backend/gporca/data/dxl/minidump/Insert-Parquet-Partitioned-SortDisabled.mdp b/src/backend/gporca/data/dxl/minidump/Insert-Parquet-Partitioned-SortDisabled.mdp index f68421f2a3a1..ed4743c7d00d 100644 --- a/src/backend/gporca/data/dxl/minidump/Insert-Parquet-Partitioned-SortDisabled.mdp +++ b/src/backend/gporca/data/dxl/minidump/Insert-Parquet-Partitioned-SortDisabled.mdp @@ -196,10 +196,7 @@ - - - - + @@ -229,9 +226,9 @@ - + - + @@ -242,13 +239,13 @@ + - - - - - + + + + @@ -262,7 +259,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/Insert-Parquet.mdp b/src/backend/gporca/data/dxl/minidump/Insert-Parquet.mdp index 9007526f494c..86dadf4f46e4 100644 --- a/src/backend/gporca/data/dxl/minidump/Insert-Parquet.mdp +++ b/src/backend/gporca/data/dxl/minidump/Insert-Parquet.mdp @@ -177,10 +177,7 @@ - - - - + @@ -210,9 +207,9 @@ - + - + @@ -223,13 +220,13 @@ + - - - - - + + + + @@ -243,7 +240,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/Insert-With-HJ-CTE-Agg.mdp b/src/backend/gporca/data/dxl/minidump/Insert-With-HJ-CTE-Agg.mdp index 42b2a550c565..d8347adb195a 100644 --- a/src/backend/gporca/data/dxl/minidump/Insert-With-HJ-CTE-Agg.mdp +++ b/src/backend/gporca/data/dxl/minidump/Insert-With-HJ-CTE-Agg.mdp @@ -382,13 +382,7 @@ - - - - - - - + @@ -509,9 +503,9 @@ - + - + @@ -531,20 +525,17 @@ + - - - - - - - - - - - - + + + + + + + + @@ -559,7 +550,7 @@ - + @@ -573,7 +564,7 @@ - + @@ -663,7 +654,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/Insert.mdp b/src/backend/gporca/data/dxl/minidump/Insert.mdp index 8fb25b77b944..5d32bb85f3a7 100644 --- a/src/backend/gporca/data/dxl/minidump/Insert.mdp +++ b/src/backend/gporca/data/dxl/minidump/Insert.mdp @@ -179,7 +179,7 @@ - + @@ -192,17 +192,17 @@ + - - - - - - - - - + + + + + + + + @@ -216,7 +216,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertAssertSort.mdp b/src/backend/gporca/data/dxl/minidump/InsertAssertSort.mdp index e93774f5ed43..058f349e9067 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertAssertSort.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertAssertSort.mdp @@ -303,11 +303,7 @@ explain insert into tbl_cds_buysell_orders_new (a,b,c) - - - - - + @@ -366,9 +362,9 @@ explain insert into tbl_cds_buysell_orders_new (a,b,c) - + - + @@ -394,18 +390,15 @@ explain insert into tbl_cds_buysell_orders_new (a,b,c) + - - - - - - - - - - + + + + + + @@ -434,8 +427,8 @@ explain insert into tbl_cds_buysell_orders_new (a,b,c) - - + + @@ -477,8 +470,8 @@ explain insert into tbl_cds_buysell_orders_new (a,b,c) - - + + @@ -497,20 +490,20 @@ explain insert into tbl_cds_buysell_orders_new (a,b,c) - + - + - + - + - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertCheckConstraint.mdp b/src/backend/gporca/data/dxl/minidump/InsertCheckConstraint.mdp index 981881230aec..946975b340cb 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertCheckConstraint.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertCheckConstraint.mdp @@ -280,7 +280,7 @@ - + @@ -303,19 +303,17 @@ + - - - - - - - - - - - + + + + + + + + @@ -335,8 +333,8 @@ - - + + @@ -363,8 +361,8 @@ - - + + @@ -404,8 +402,8 @@ - - + + @@ -422,7 +420,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertConstTuple.mdp b/src/backend/gporca/data/dxl/minidump/InsertConstTuple.mdp index a3482d548076..6ac932fb71af 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertConstTuple.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertConstTuple.mdp @@ -193,7 +193,7 @@ - + @@ -210,17 +210,17 @@ + - - - - - - - - - + + + + + + + + @@ -234,7 +234,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertConstTupleRandomDistribution.mdp b/src/backend/gporca/data/dxl/minidump/InsertConstTupleRandomDistribution.mdp index 1832797fd3d9..ef134dae13e9 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertConstTupleRandomDistribution.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertConstTupleRandomDistribution.mdp @@ -169,10 +169,7 @@ - - - - + @@ -209,9 +206,9 @@ - + - + @@ -222,17 +219,16 @@ + - - - - - - - - - + + + + + + + @@ -246,8 +242,8 @@ - - + + @@ -263,7 +259,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertConstTupleVolatileFunction.mdp b/src/backend/gporca/data/dxl/minidump/InsertConstTupleVolatileFunction.mdp index 63d137b0f72a..71e869fceda1 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertConstTupleVolatileFunction.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertConstTupleVolatileFunction.mdp @@ -187,10 +187,7 @@ - - - - + @@ -231,9 +228,9 @@ - + - + @@ -244,17 +241,17 @@ + - - - - - - - - - + + + + + + + + @@ -268,8 +265,8 @@ - - + + @@ -290,8 +287,8 @@ - - + + @@ -308,12 +305,12 @@ - + - - + + diff --git a/src/backend/gporca/data/dxl/minidump/InsertConstTupleVolatileFunctionMOTable.mdp b/src/backend/gporca/data/dxl/minidump/InsertConstTupleVolatileFunctionMOTable.mdp index 0e8b62f5c330..01fc6eb03cb8 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertConstTupleVolatileFunctionMOTable.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertConstTupleVolatileFunctionMOTable.mdp @@ -177,10 +177,7 @@ - - - - + @@ -221,9 +218,9 @@ - + - + @@ -234,17 +231,16 @@ + - - - - - - - - - + + + + + + + @@ -258,8 +254,8 @@ - - + + @@ -276,15 +272,15 @@ - + - - + + diff --git a/src/backend/gporca/data/dxl/minidump/InsertDirectedDispatchNullValue.mdp b/src/backend/gporca/data/dxl/minidump/InsertDirectedDispatchNullValue.mdp index 10d1979d9519..23de0bea2f87 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertDirectedDispatchNullValue.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertDirectedDispatchNullValue.mdp @@ -163,10 +163,7 @@ - - - - + @@ -211,9 +208,9 @@ - + - + @@ -231,18 +228,17 @@ + - - - - - - - - - - + + + + + + + + @@ -259,8 +255,8 @@ - - + + @@ -284,8 +280,8 @@ - - + + @@ -302,7 +298,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertInCTE.mdp b/src/backend/gporca/data/dxl/minidump/InsertInCTE.mdp new file mode 100644 index 000000000000..2ee2ebb48030 --- /dev/null +++ b/src/backend/gporca/data/dxl/minidump/InsertInCTE.mdp @@ -0,0 +1,608 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/backend/gporca/data/dxl/minidump/InsertIntoNonNullAfterDroppingColumn.mdp b/src/backend/gporca/data/dxl/minidump/InsertIntoNonNullAfterDroppingColumn.mdp index 44b2c3d09545..29a5bdfd64c3 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertIntoNonNullAfterDroppingColumn.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertIntoNonNullAfterDroppingColumn.mdp @@ -148,9 +148,7 @@ EXPLAIN INSERT INTO ColumnMapping VALUES (NULL); - - - + @@ -182,14 +180,14 @@ EXPLAIN INSERT INTO ColumnMapping VALUES (NULL); - - + + - + - + @@ -197,16 +195,17 @@ EXPLAIN INSERT INTO ColumnMapping VALUES (NULL); + - - - - - - - - + + + + + + + + @@ -217,8 +216,8 @@ EXPLAIN INSERT INTO ColumnMapping VALUES (NULL); - - + + @@ -236,8 +235,8 @@ EXPLAIN INSERT INTO ColumnMapping VALUES (NULL); - - + + @@ -254,11 +253,11 @@ EXPLAIN INSERT INTO ColumnMapping VALUES (NULL); - + - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertIntoReturning.mdp b/src/backend/gporca/data/dxl/minidump/InsertIntoReturning.mdp new file mode 100644 index 000000000000..8a7a0c4a6835 --- /dev/null +++ b/src/backend/gporca/data/dxl/minidump/InsertIntoReturning.mdp @@ -0,0 +1,337 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/backend/gporca/data/dxl/minidump/InsertMasterOnlyTable.mdp b/src/backend/gporca/data/dxl/minidump/InsertMasterOnlyTable.mdp index 3f095c78d4dd..65d364d88cf4 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertMasterOnlyTable.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertMasterOnlyTable.mdp @@ -197,10 +197,7 @@ - - - - + @@ -234,9 +231,9 @@ - + - + @@ -247,17 +244,16 @@ + - - - - - - - - - + + + + + + + @@ -271,7 +267,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertMasterOnlyTableConstTuple.mdp b/src/backend/gporca/data/dxl/minidump/InsertMasterOnlyTableConstTuple.mdp index 116f585d839c..99fc96d3939e 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertMasterOnlyTableConstTuple.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertMasterOnlyTableConstTuple.mdp @@ -135,10 +135,7 @@ - - - - + @@ -175,9 +172,9 @@ - + - + @@ -188,17 +185,16 @@ + - - - - - - - - - + + + + + + + @@ -212,7 +208,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertMismatchedDistrubution-2.mdp b/src/backend/gporca/data/dxl/minidump/InsertMismatchedDistrubution-2.mdp index 26b336933f48..ddfcb7662959 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertMismatchedDistrubution-2.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertMismatchedDistrubution-2.mdp @@ -225,11 +225,7 @@ explain insert into pt2 select * from r; - - - - - + @@ -265,9 +261,9 @@ explain insert into pt2 select * from r; - + - + @@ -281,18 +277,17 @@ explain insert into pt2 select * from r; + - - - - - - - - - - + + + + + + + + @@ -309,7 +304,7 @@ explain insert into pt2 select * from r; - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertMismatchedDistrubution.mdp b/src/backend/gporca/data/dxl/minidump/InsertMismatchedDistrubution.mdp index c5e4b7a1884e..86f60a655e9a 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertMismatchedDistrubution.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertMismatchedDistrubution.mdp @@ -225,11 +225,7 @@ explain insert into pt2 select * from r; - - - - - + @@ -265,9 +261,9 @@ explain insert into pt2 select * from r; - + - + @@ -281,18 +277,17 @@ explain insert into pt2 select * from r; + - - - - - - - - - - + + + + + + + + @@ -309,7 +304,7 @@ explain insert into pt2 select * from r; - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertNULLNotNULLConstraint.mdp b/src/backend/gporca/data/dxl/minidump/InsertNULLNotNULLConstraint.mdp index 486cb39248be..50cecb044c38 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertNULLNotNULLConstraint.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertNULLNotNULLConstraint.mdp @@ -132,9 +132,7 @@ - - - + @@ -167,9 +165,9 @@ - + - + @@ -181,16 +179,17 @@ + - - - - - - - - + + + + + + + + @@ -201,8 +200,8 @@ - - + + @@ -220,8 +219,8 @@ - - + + @@ -238,7 +237,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertNoEnforceConstraints.mdp b/src/backend/gporca/data/dxl/minidump/InsertNoEnforceConstraints.mdp index 31b1fef69723..4d6626819d67 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertNoEnforceConstraints.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertNoEnforceConstraints.mdp @@ -167,10 +167,7 @@ insert into constraints_tab values (NULL, -1); - - - - + @@ -207,9 +204,9 @@ insert into constraints_tab values (NULL, -1); - + - + @@ -220,17 +217,17 @@ insert into constraints_tab values (NULL, -1); + - - - - - - - - - + + + + + + + + @@ -244,7 +241,7 @@ insert into constraints_tab values (NULL, -1); - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertNonSingleton.mdp b/src/backend/gporca/data/dxl/minidump/InsertNonSingleton.mdp index 6317e6d9ce13..dd39207da320 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertNonSingleton.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertNonSingleton.mdp @@ -241,9 +241,7 @@ EXPLAIN INSERT INTO snackbox SELECT a FROM (SELECT c FROM hottoast LIMIT 3) hott - - - + @@ -302,9 +300,9 @@ EXPLAIN INSERT INTO snackbox SELECT a FROM (SELECT c FROM hottoast LIMIT 3) hott - + - + @@ -312,16 +310,16 @@ EXPLAIN INSERT INTO snackbox SELECT a FROM (SELECT c FROM hottoast LIMIT 3) hott + - - - - - - - - + + + + + + + @@ -332,7 +330,7 @@ EXPLAIN INSERT INTO snackbox SELECT a FROM (SELECT c FROM hottoast LIMIT 3) hott - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertNotNullCols.mdp b/src/backend/gporca/data/dxl/minidump/InsertNotNullCols.mdp index c06d5da9a90b..8aee983f188b 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertNotNullCols.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertNotNullCols.mdp @@ -213,7 +213,7 @@ - + @@ -226,17 +226,17 @@ + - - - - - - - - - + + + + + + + + @@ -250,8 +250,8 @@ - - + + @@ -268,7 +268,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertPrimaryKeyFromMOTable.mdp b/src/backend/gporca/data/dxl/minidump/InsertPrimaryKeyFromMOTable.mdp index b662c37bb44c..c52933adcc18 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertPrimaryKeyFromMOTable.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertPrimaryKeyFromMOTable.mdp @@ -199,10 +199,7 @@ - - - - + @@ -236,9 +233,9 @@ - + - + @@ -249,17 +246,17 @@ + - - - - - - - - - + + + + + + + + @@ -273,8 +270,8 @@ - - + + @@ -295,8 +292,8 @@ - - + + @@ -313,7 +310,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertProjectSort.mdp b/src/backend/gporca/data/dxl/minidump/InsertProjectSort.mdp index 126aa598aec9..a55e6139e508 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertProjectSort.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertProjectSort.mdp @@ -231,11 +231,7 @@ explain insert into tbl_cds_buysell_orders_new (a,b,c) - - - - - + @@ -294,9 +290,9 @@ explain insert into tbl_cds_buysell_orders_new (a,b,c) - + - + @@ -322,18 +318,15 @@ explain insert into tbl_cds_buysell_orders_new (a,b,c) + - - - - - - - - - - + + + + + + @@ -351,18 +344,18 @@ explain insert into tbl_cds_buysell_orders_new (a,b,c) - + - + - + - + - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertRandomDistr.mdp b/src/backend/gporca/data/dxl/minidump/InsertRandomDistr.mdp index 77e8d43e42fd..15c7f3d1de52 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertRandomDistr.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertRandomDistr.mdp @@ -195,10 +195,7 @@ - - - - + @@ -232,9 +229,9 @@ - + - + @@ -245,17 +242,16 @@ + - - - - - - - - - + + + + + + + @@ -269,7 +265,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertReplicatedIntoSerialHashDistributedTable.mdp b/src/backend/gporca/data/dxl/minidump/InsertReplicatedIntoSerialHashDistributedTable.mdp index 6fc44f056968..214481151326 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertReplicatedIntoSerialHashDistributedTable.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertReplicatedIntoSerialHashDistributedTable.mdp @@ -272,11 +272,7 @@ EXPLAIN (COSTS OFF) INSERT INTO distributed_table (val1, val2) SELECT val1, val2 - - - - - + @@ -320,9 +316,9 @@ EXPLAIN (COSTS OFF) INSERT INTO distributed_table (val1, val2) SELECT val1, val2 - + - + @@ -336,18 +332,17 @@ EXPLAIN (COSTS OFF) INSERT INTO distributed_table (val1, val2) SELECT val1, val2 - + + - - - - - - - - - - + + + + + + + + @@ -364,7 +359,7 @@ EXPLAIN (COSTS OFF) INSERT INTO distributed_table (val1, val2) SELECT val1, val2 - + @@ -415,7 +410,7 @@ EXPLAIN (COSTS OFF) INSERT INTO distributed_table (val1, val2) SELECT val1, val2 - + @@ -441,7 +436,7 @@ EXPLAIN (COSTS OFF) INSERT INTO distributed_table (val1, val2) SELECT val1, val2 - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertSort.mdp b/src/backend/gporca/data/dxl/minidump/InsertSort.mdp index 69208c10a1a5..f2275a970b60 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertSort.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertSort.mdp @@ -317,9 +317,7 @@ explain insert into nim1 select * from nim order by 1; - - - + @@ -358,9 +356,9 @@ explain insert into nim1 select * from nim order by 1; - + - + @@ -368,16 +366,17 @@ explain insert into nim1 select * from nim order by 1; + - - - - - - - - + + + + + + + + @@ -388,7 +387,7 @@ explain insert into nim1 select * from nim order by 1; - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertSortDistributed2MasterOnly.mdp b/src/backend/gporca/data/dxl/minidump/InsertSortDistributed2MasterOnly.mdp index 69ed58315668..7f511bf01dc2 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertSortDistributed2MasterOnly.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertSortDistributed2MasterOnly.mdp @@ -238,11 +238,7 @@ explain insert into masteronly select * from distributedtable order by 1; - - - - - + @@ -285,9 +281,9 @@ explain insert into masteronly select * from distributedtable order by 1; - + - + @@ -301,18 +297,16 @@ explain insert into masteronly select * from distributedtable order by 1; + - - - - - - - - - - + + + + + + + @@ -329,8 +323,8 @@ explain insert into masteronly select * from distributedtable order by 1; - - + + @@ -349,7 +343,7 @@ explain insert into masteronly select * from distributedtable order by 1; - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertWithDroppedCol.mdp b/src/backend/gporca/data/dxl/minidump/InsertWithDroppedCol.mdp index 0c7287f305cc..67d75e9738da 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertWithDroppedCol.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertWithDroppedCol.mdp @@ -201,10 +201,7 @@ - - - - + @@ -241,9 +238,9 @@ - + - + @@ -258,17 +255,17 @@ + - - - - - - - - - + + + + + + + + @@ -282,8 +279,8 @@ - - + + @@ -304,8 +301,8 @@ - - + + @@ -324,7 +321,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertWithTriggers.mdp b/src/backend/gporca/data/dxl/minidump/InsertWithTriggers.mdp index f4013ae61377..57387f2f2a09 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertWithTriggers.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertWithTriggers.mdp @@ -266,7 +266,7 @@ - + @@ -286,18 +286,27 @@ + + + + + + + + + + + - - - - - - - - - - + + + + + + + + @@ -314,8 +323,8 @@ - - + + @@ -332,7 +341,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/LeftJoinNullsNotColocated.mdp b/src/backend/gporca/data/dxl/minidump/LeftJoinNullsNotColocated.mdp index 5b8f2c06474e..1a1c4a2e1088 100644 --- a/src/backend/gporca/data/dxl/minidump/LeftJoinNullsNotColocated.mdp +++ b/src/backend/gporca/data/dxl/minidump/LeftJoinNullsNotColocated.mdp @@ -427,9 +427,9 @@ on id2 = id3 distributed by (id1); - - - + + + @@ -457,7 +457,7 @@ on id2 = id3 distributed by (id1); - + diff --git a/src/backend/gporca/data/dxl/minidump/MultipleUpdateWithJoinOnDistCol.mdp b/src/backend/gporca/data/dxl/minidump/MultipleUpdateWithJoinOnDistCol.mdp index ff3c9dc87d38..c9d11dd7792f 100644 --- a/src/backend/gporca/data/dxl/minidump/MultipleUpdateWithJoinOnDistCol.mdp +++ b/src/backend/gporca/data/dxl/minidump/MultipleUpdateWithJoinOnDistCol.mdp @@ -240,10 +240,7 @@ - - - - + @@ -302,7 +299,7 @@ - + @@ -315,17 +312,17 @@ + - - - - - - - - - + + + + + + + + @@ -345,8 +342,8 @@ - - + + @@ -356,7 +353,7 @@ - + @@ -373,7 +370,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PartitionedDelete.mdp b/src/backend/gporca/data/dxl/minidump/PartitionedDelete.mdp index fccf463ab69c..b2169cdfd2c1 100644 --- a/src/backend/gporca/data/dxl/minidump/PartitionedDelete.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartitionedDelete.mdp @@ -234,23 +234,23 @@ - + + - - - - - - - - - + + + + + + + + @@ -267,7 +267,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PartitionedInsert.mdp b/src/backend/gporca/data/dxl/minidump/PartitionedInsert.mdp index 403ab31b3373..1cacfed9626d 100644 --- a/src/backend/gporca/data/dxl/minidump/PartitionedInsert.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartitionedInsert.mdp @@ -173,10 +173,7 @@ - - - - + @@ -213,9 +210,9 @@ - + - + @@ -230,17 +227,17 @@ + - - - - - - - - - + + + + + + + + @@ -254,7 +251,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PartitionedUpdate.mdp b/src/backend/gporca/data/dxl/minidump/PartitionedUpdate.mdp index 7125f4e8e7fd..1ba9d2796b31 100644 --- a/src/backend/gporca/data/dxl/minidump/PartitionedUpdate.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartitionedUpdate.mdp @@ -197,9 +197,7 @@ - - - + @@ -246,7 +244,7 @@ - + @@ -259,17 +257,17 @@ + - - - - - - - - - + + + + + + + + @@ -292,8 +290,8 @@ - - + + @@ -303,7 +301,7 @@ - + @@ -323,7 +321,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/ProjectSetFunction.mdp b/src/backend/gporca/data/dxl/minidump/ProjectSetFunction.mdp index 5866ae295619..9b86bc007438 100644 --- a/src/backend/gporca/data/dxl/minidump/ProjectSetFunction.mdp +++ b/src/backend/gporca/data/dxl/minidump/ProjectSetFunction.mdp @@ -187,10 +187,7 @@ - - - - + @@ -230,9 +227,9 @@ - + - + @@ -243,17 +240,16 @@ + - - - - - - - - - + + + + + + + @@ -267,8 +263,8 @@ - - + + @@ -284,7 +280,7 @@ - + @@ -313,7 +309,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/ReplicatedTable-CTAS.mdp b/src/backend/gporca/data/dxl/minidump/ReplicatedTable-CTAS.mdp index b3afb84e8ed8..9f9d398b16d6 100644 --- a/src/backend/gporca/data/dxl/minidump/ReplicatedTable-CTAS.mdp +++ b/src/backend/gporca/data/dxl/minidump/ReplicatedTable-CTAS.mdp @@ -99,8 +99,8 @@ - - + + @@ -122,8 +122,8 @@ - - + + @@ -133,7 +133,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/ReplicatedTableInsert.mdp b/src/backend/gporca/data/dxl/minidump/ReplicatedTableInsert.mdp index 13ec859f53ab..0706c7e72760 100644 --- a/src/backend/gporca/data/dxl/minidump/ReplicatedTableInsert.mdp +++ b/src/backend/gporca/data/dxl/minidump/ReplicatedTableInsert.mdp @@ -149,10 +149,7 @@ - - - - + @@ -178,9 +175,9 @@ - + - + @@ -191,17 +188,16 @@ + - - - - - - - - - + + + + + + + @@ -209,7 +205,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/ReplicatedTableSequenceInsert.mdp b/src/backend/gporca/data/dxl/minidump/ReplicatedTableSequenceInsert.mdp index d391b006caf2..b9b452d00361 100644 --- a/src/backend/gporca/data/dxl/minidump/ReplicatedTableSequenceInsert.mdp +++ b/src/backend/gporca/data/dxl/minidump/ReplicatedTableSequenceInsert.mdp @@ -253,10 +253,7 @@ - - - - + @@ -300,9 +297,9 @@ - + - + @@ -313,17 +310,16 @@ + - - - - - - - - - + + + + + + + @@ -337,7 +333,7 @@ - + @@ -377,8 +373,8 @@ - - + + diff --git a/src/backend/gporca/data/dxl/minidump/ReplicatedTableWithAggNoMotion.mdp b/src/backend/gporca/data/dxl/minidump/ReplicatedTableWithAggNoMotion.mdp index f43d5ebd109c..f40c35c9b3f0 100644 --- a/src/backend/gporca/data/dxl/minidump/ReplicatedTableWithAggNoMotion.mdp +++ b/src/backend/gporca/data/dxl/minidump/ReplicatedTableWithAggNoMotion.mdp @@ -225,9 +225,7 @@ - - - + @@ -283,9 +281,9 @@ - + - + @@ -293,16 +291,16 @@ - + + - - - - - - - - + + + + + + + @@ -311,11 +309,11 @@ - + - + @@ -328,7 +326,7 @@ - + @@ -349,7 +347,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/SelfUpdate.mdp b/src/backend/gporca/data/dxl/minidump/SelfUpdate.mdp index 77cd608aec88..b101ef64571f 100644 --- a/src/backend/gporca/data/dxl/minidump/SelfUpdate.mdp +++ b/src/backend/gporca/data/dxl/minidump/SelfUpdate.mdp @@ -178,9 +178,7 @@ update t1 set b = c; - - - + @@ -216,7 +214,7 @@ update t1 set b = c; - + @@ -232,18 +230,16 @@ update t1 set b = c; + - - - - - - - - - - + + + + + + + @@ -266,8 +262,8 @@ update t1 set b = c; - - + + @@ -279,7 +275,7 @@ update t1 set b = c; - + @@ -299,7 +295,7 @@ update t1 set b = c; - + diff --git a/src/backend/gporca/data/dxl/minidump/SqlFuncDmlScalar.mdp b/src/backend/gporca/data/dxl/minidump/SqlFuncDmlScalar.mdp index db336e845026..17700129bc45 100644 --- a/src/backend/gporca/data/dxl/minidump/SqlFuncDmlScalar.mdp +++ b/src/backend/gporca/data/dxl/minidump/SqlFuncDmlScalar.mdp @@ -245,9 +245,7 @@ LIMIT 999 - - - + @@ -295,9 +293,9 @@ LIMIT 999 - + - + @@ -305,16 +303,17 @@ LIMIT 999 - + + - - - - - - - - + + + + + + + + @@ -325,8 +324,8 @@ LIMIT 999 - - + + @@ -344,7 +343,7 @@ LIMIT 999 - + @@ -376,7 +375,7 @@ LIMIT 999 - + @@ -393,7 +392,7 @@ LIMIT 999 - + diff --git a/src/backend/gporca/data/dxl/minidump/SqlFuncDmlTvf.mdp b/src/backend/gporca/data/dxl/minidump/SqlFuncDmlTvf.mdp index 9142075dd62a..1dc4af70fb3d 100644 --- a/src/backend/gporca/data/dxl/minidump/SqlFuncDmlTvf.mdp +++ b/src/backend/gporca/data/dxl/minidump/SqlFuncDmlTvf.mdp @@ -254,10 +254,7 @@ LIMIT 999 - - - - + @@ -306,9 +303,9 @@ LIMIT 999 - + - + @@ -319,17 +316,17 @@ LIMIT 999 - + + - - - - - - - - - + + + + + + + + @@ -343,8 +340,8 @@ LIMIT 999 - - + + @@ -365,7 +362,7 @@ LIMIT 999 - + @@ -423,7 +420,7 @@ LIMIT 999 - + diff --git a/src/backend/gporca/data/dxl/minidump/TaintedReplicatedAgg.mdp b/src/backend/gporca/data/dxl/minidump/TaintedReplicatedAgg.mdp index 452dbf9774c7..b588b4ce9f96 100644 --- a/src/backend/gporca/data/dxl/minidump/TaintedReplicatedAgg.mdp +++ b/src/backend/gporca/data/dxl/minidump/TaintedReplicatedAgg.mdp @@ -219,9 +219,7 @@ - - - + @@ -268,9 +266,9 @@ - + - + @@ -278,16 +276,16 @@ + - - - - - - - - + + + + + + + @@ -298,7 +296,7 @@ - + @@ -322,9 +320,9 @@ - + - + diff --git a/src/backend/gporca/data/dxl/minidump/TaintedReplicatedFilter.mdp b/src/backend/gporca/data/dxl/minidump/TaintedReplicatedFilter.mdp index db85e1a0d25d..3516fbaf308d 100644 --- a/src/backend/gporca/data/dxl/minidump/TaintedReplicatedFilter.mdp +++ b/src/backend/gporca/data/dxl/minidump/TaintedReplicatedFilter.mdp @@ -206,10 +206,7 @@ - - - - + @@ -251,9 +248,9 @@ - + - + @@ -264,17 +261,16 @@ + - - - - - - - - - + + + + + + + @@ -288,7 +284,7 @@ - + @@ -325,7 +321,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/TaintedReplicatedLimit.mdp b/src/backend/gporca/data/dxl/minidump/TaintedReplicatedLimit.mdp index 1eaca5f5ab04..120811732fbb 100644 --- a/src/backend/gporca/data/dxl/minidump/TaintedReplicatedLimit.mdp +++ b/src/backend/gporca/data/dxl/minidump/TaintedReplicatedLimit.mdp @@ -215,9 +215,7 @@ - - - + @@ -256,9 +254,9 @@ - + - + @@ -266,16 +264,16 @@ + - - - - - - - - + + + + + + + @@ -286,7 +284,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/TaintedReplicatedWindowAgg.mdp b/src/backend/gporca/data/dxl/minidump/TaintedReplicatedWindowAgg.mdp index ea47d8fc6fe3..542b0f228b37 100644 --- a/src/backend/gporca/data/dxl/minidump/TaintedReplicatedWindowAgg.mdp +++ b/src/backend/gporca/data/dxl/minidump/TaintedReplicatedWindowAgg.mdp @@ -220,9 +220,7 @@ - - - + @@ -271,9 +269,9 @@ - + - + @@ -281,16 +279,16 @@ + - - - - - - - - + + + + + + + @@ -301,7 +299,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateCardinalityAssert.mdp b/src/backend/gporca/data/dxl/minidump/UpdateCardinalityAssert.mdp index 0e701f0c3b67..6b208aca8332 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateCardinalityAssert.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateCardinalityAssert.mdp @@ -218,9 +218,7 @@ - - - + @@ -275,7 +273,7 @@ - + @@ -288,17 +286,17 @@ + - - - - - - - - - + + + + + + + + @@ -318,8 +316,8 @@ - - + + @@ -329,7 +327,7 @@ - + @@ -346,7 +344,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateCheckConstraint.mdp b/src/backend/gporca/data/dxl/minidump/UpdateCheckConstraint.mdp index d57ae91617d9..d1e8035edeb6 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateCheckConstraint.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateCheckConstraint.mdp @@ -294,7 +294,7 @@ - + @@ -313,19 +313,17 @@ + - - - - - - - - - - - + + + + + + + + @@ -351,8 +349,8 @@ - - + + @@ -398,8 +396,8 @@ - - + + @@ -411,7 +409,7 @@ - + @@ -437,7 +435,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateDistKeyMismatchedDistribution.mdp b/src/backend/gporca/data/dxl/minidump/UpdateDistKeyMismatchedDistribution.mdp index e0fe02081aaf..80573d1b7b0c 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateDistKeyMismatchedDistribution.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateDistKeyMismatchedDistribution.mdp @@ -234,9 +234,7 @@ - - - + @@ -302,7 +300,7 @@ - + @@ -318,18 +316,17 @@ + - - - - - - - - - - + + + + + + + + @@ -352,8 +349,8 @@ - - + + @@ -363,7 +360,7 @@ - + @@ -383,7 +380,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateDistKeyWithNestedJoin.mdp b/src/backend/gporca/data/dxl/minidump/UpdateDistKeyWithNestedJoin.mdp index fe9965b45a91..80f6cdcf9fe8 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateDistKeyWithNestedJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateDistKeyWithNestedJoin.mdp @@ -602,9 +602,7 @@ WHERE t1.id1 = t2.id1; - - - + @@ -680,7 +678,7 @@ WHERE t1.id1 = t2.id1; - + @@ -693,17 +691,17 @@ WHERE t1.id1 = t2.id1; + - - - - - - - - - + + + + + + + + @@ -723,8 +721,8 @@ WHERE t1.id1 = t2.id1; - - + + @@ -734,7 +732,7 @@ WHERE t1.id1 = t2.id1; - + @@ -751,7 +749,7 @@ WHERE t1.id1 = t2.id1; - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateDistrKey.mdp b/src/backend/gporca/data/dxl/minidump/UpdateDistrKey.mdp index ec554d353b14..ed407018f10f 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateDistrKey.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateDistrKey.mdp @@ -213,9 +213,7 @@ - - - + @@ -270,7 +268,7 @@ - + @@ -283,17 +281,17 @@ + - - - - - - - - - + + + + + + + + @@ -313,8 +311,8 @@ - - + + @@ -324,7 +322,7 @@ - + @@ -341,7 +339,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateDroppedCols.mdp b/src/backend/gporca/data/dxl/minidump/UpdateDroppedCols.mdp index 5999d1537c19..1980af473399 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateDroppedCols.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateDroppedCols.mdp @@ -198,9 +198,7 @@ - - - + @@ -247,7 +245,7 @@ - + @@ -260,17 +258,17 @@ + - - - - - - - - - + + + + + + + + @@ -290,8 +288,8 @@ - - + + @@ -301,7 +299,7 @@ - + @@ -318,7 +316,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateInCTE.mdp b/src/backend/gporca/data/dxl/minidump/UpdateInCTE.mdp new file mode 100644 index 000000000000..3474112dff99 --- /dev/null +++ b/src/backend/gporca/data/dxl/minidump/UpdateInCTE.mdp @@ -0,0 +1,412 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/backend/gporca/data/dxl/minidump/UpdateNoCardinalityAssert.mdp b/src/backend/gporca/data/dxl/minidump/UpdateNoCardinalityAssert.mdp index 31e7fd14bfe7..1c05805f97b0 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateNoCardinalityAssert.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateNoCardinalityAssert.mdp @@ -391,7 +391,7 @@ - + @@ -404,17 +404,17 @@ + - - - - - - - - - + + + + + + + + @@ -434,8 +434,8 @@ - - + + @@ -445,7 +445,7 @@ - + @@ -462,7 +462,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateNoDistKeyMismatchedDistribution.mdp b/src/backend/gporca/data/dxl/minidump/UpdateNoDistKeyMismatchedDistribution.mdp index d7dd7212dca9..cd30c13a9f48 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateNoDistKeyMismatchedDistribution.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateNoDistKeyMismatchedDistribution.mdp @@ -235,9 +235,7 @@ - - - + @@ -303,7 +301,7 @@ - + @@ -319,18 +317,17 @@ + - - - - - - - - - - + + + + + + + + @@ -353,13 +350,13 @@ - - + + - + @@ -379,7 +376,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateNoEnforceConstraints.mdp b/src/backend/gporca/data/dxl/minidump/UpdateNoEnforceConstraints.mdp index 6d2e6ade0c3e..3a16d0c4195a 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateNoEnforceConstraints.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateNoEnforceConstraints.mdp @@ -190,10 +190,7 @@ update constraints_tab SET notnullcol = NULL, positivecol =-1; - - - - + @@ -239,7 +236,7 @@ update constraints_tab SET notnullcol = NULL, positivecol =-1; - + @@ -255,21 +252,20 @@ update constraints_tab SET notnullcol = NULL, positivecol =-1; + - - - - - - - - - - + + + + + + + + - + @@ -289,7 +285,7 @@ update constraints_tab SET notnullcol = NULL, positivecol =-1; - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateNotNullCols.mdp b/src/backend/gporca/data/dxl/minidump/UpdateNotNullCols.mdp index f1d00b8d3a30..f7f6b567bf23 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateNotNullCols.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateNotNullCols.mdp @@ -328,7 +328,7 @@ - + @@ -341,17 +341,17 @@ + - - - - - - - - - + + + + + + + + @@ -371,8 +371,8 @@ - - + + @@ -399,8 +399,8 @@ - - + + @@ -412,7 +412,7 @@ - + @@ -432,7 +432,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdatePartTable.mdp b/src/backend/gporca/data/dxl/minidump/UpdatePartTable.mdp index bad577f8ed51..c9bc12c55994 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdatePartTable.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdatePartTable.mdp @@ -198,9 +198,7 @@ - - - + @@ -247,7 +245,7 @@ - + @@ -260,17 +258,17 @@ + - - - - - - - - - + + + + + + + + @@ -290,8 +288,8 @@ - - + + @@ -301,7 +299,7 @@ - + @@ -318,7 +316,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateRandomDistr.mdp b/src/backend/gporca/data/dxl/minidump/UpdateRandomDistr.mdp index e7979bb06aa8..02b5a3e16440 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateRandomDistr.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateRandomDistr.mdp @@ -196,7 +196,7 @@ - + @@ -209,20 +209,19 @@ + - - - - - - - - - + + + + + + + - + @@ -239,7 +238,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateReturning.mdp b/src/backend/gporca/data/dxl/minidump/UpdateReturning.mdp new file mode 100644 index 000000000000..ae88e46cd062 --- /dev/null +++ b/src/backend/gporca/data/dxl/minidump/UpdateReturning.mdp @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/backend/gporca/data/dxl/minidump/UpdateUniqueConstraint-2.mdp b/src/backend/gporca/data/dxl/minidump/UpdateUniqueConstraint-2.mdp index f05bcb78f115..6861ac0695ea 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateUniqueConstraint-2.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateUniqueConstraint-2.mdp @@ -699,9 +699,7 @@ - - - + @@ -765,7 +763,7 @@ - + @@ -778,17 +776,17 @@ + - - - - - - - - - + + + + + + + + @@ -808,8 +806,8 @@ - - + + @@ -821,7 +819,7 @@ - + @@ -838,7 +836,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateUniqueConstraint.mdp b/src/backend/gporca/data/dxl/minidump/UpdateUniqueConstraint.mdp index 890d4d335bcb..abc6b8052e95 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateUniqueConstraint.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateUniqueConstraint.mdp @@ -196,7 +196,7 @@ - + @@ -209,17 +209,17 @@ + - - - - - - - - - + + + + + + + + @@ -239,13 +239,13 @@ - - + + - + @@ -266,8 +266,8 @@ - - + + @@ -277,7 +277,7 @@ - + @@ -294,7 +294,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateVolatileFunction.mdp b/src/backend/gporca/data/dxl/minidump/UpdateVolatileFunction.mdp index 43e7b17a4839..0907b745d581 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateVolatileFunction.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateVolatileFunction.mdp @@ -411,7 +411,7 @@ - + @@ -424,17 +424,17 @@ + - - - - - - - - - + + + + + + + + @@ -454,8 +454,8 @@ - - + + @@ -465,7 +465,7 @@ - + @@ -482,7 +482,7 @@ - + @@ -498,8 +498,8 @@ - - + + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateWindowGatherMerge.mdp b/src/backend/gporca/data/dxl/minidump/UpdateWindowGatherMerge.mdp index 55d3f01242eb..e05a7a4d2a15 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateWindowGatherMerge.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateWindowGatherMerge.mdp @@ -629,9 +629,7 @@ - - - + @@ -709,7 +707,7 @@ - + @@ -722,17 +720,16 @@ + - - - - - - - - - + + + + + + + @@ -752,13 +749,13 @@ - - + + - + @@ -775,7 +772,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateWithHashJoin.mdp b/src/backend/gporca/data/dxl/minidump/UpdateWithHashJoin.mdp index e7e1b1db9797..1c8ad1c4268b 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateWithHashJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateWithHashJoin.mdp @@ -240,9 +240,7 @@ - - - + @@ -301,7 +299,7 @@ - + @@ -314,20 +312,20 @@ + - - - - - - - - - + + + + + + + + - + @@ -344,7 +342,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateWithOids.mdp b/src/backend/gporca/data/dxl/minidump/UpdateWithOids.mdp index 26f539d0c504..17358b21e0bb 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateWithOids.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateWithOids.mdp @@ -157,9 +157,7 @@ - - - + @@ -208,7 +206,7 @@ - + @@ -221,18 +219,18 @@ + - - - - - - - - - - + + + + + + + + + @@ -255,8 +253,8 @@ - - + + @@ -266,7 +264,7 @@ - + @@ -286,7 +284,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateWithTriggers.mdp b/src/backend/gporca/data/dxl/minidump/UpdateWithTriggers.mdp index e626def55975..4ddc9357d783 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateWithTriggers.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateWithTriggers.mdp @@ -204,7 +204,7 @@ - + @@ -220,21 +220,20 @@ + - - - - - - - - - - + + + + + + + + - + @@ -254,7 +253,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateZeroRows.mdp b/src/backend/gporca/data/dxl/minidump/UpdateZeroRows.mdp index 8e063421b638..54d79c26d7bc 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateZeroRows.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateZeroRows.mdp @@ -359,9 +359,7 @@ - - - + @@ -410,7 +408,7 @@ - + @@ -426,18 +424,17 @@ + - - - - - - - - - - + + + + + + + + @@ -460,8 +457,8 @@ - - + + @@ -491,8 +488,8 @@ - - + + @@ -530,7 +527,7 @@ - + @@ -553,7 +550,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdatingDistributionColumn.mdp b/src/backend/gporca/data/dxl/minidump/UpdatingDistributionColumn.mdp index 32023291390b..90bdae67b35d 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdatingDistributionColumn.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdatingDistributionColumn.mdp @@ -209,9 +209,7 @@ - - - + @@ -270,7 +268,7 @@ - + @@ -283,17 +281,17 @@ + - - - - - - - - - + + + + + + + + @@ -313,8 +311,8 @@ - - + + @@ -324,7 +322,7 @@ - + @@ -341,7 +339,7 @@ - + @@ -358,7 +356,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdatingMultipleColumn.mdp b/src/backend/gporca/data/dxl/minidump/UpdatingMultipleColumn.mdp index cd589c11448f..64f478dd8359 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdatingMultipleColumn.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdatingMultipleColumn.mdp @@ -547,10 +547,7 @@ - - - - + @@ -584,7 +581,7 @@ - + @@ -597,17 +594,17 @@ + - - - - - - - - - + + + + + + + + @@ -627,8 +624,8 @@ - - + + @@ -638,7 +635,7 @@ - + @@ -655,7 +652,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdatingNonDistColSameTable.mdp b/src/backend/gporca/data/dxl/minidump/UpdatingNonDistColSameTable.mdp index 0c724aa138bc..461a2e91fd95 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdatingNonDistColSameTable.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdatingNonDistColSameTable.mdp @@ -196,9 +196,7 @@ - - - + @@ -234,7 +232,7 @@ - + @@ -250,21 +248,20 @@ + - - - - - - - - - - + + + + + + + + - + @@ -284,7 +281,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdatingNonDistributionColumnFunc.mdp b/src/backend/gporca/data/dxl/minidump/UpdatingNonDistributionColumnFunc.mdp index 30bd81e5f423..faa17ed7e34c 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdatingNonDistributionColumnFunc.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdatingNonDistributionColumnFunc.mdp @@ -188,9 +188,7 @@ - - - + @@ -239,7 +237,7 @@ - + @@ -252,20 +250,20 @@ + - - - - - - - - - + + + + + + + + - + @@ -282,7 +280,7 @@ - + @@ -299,7 +297,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/VolatileFunctionsBelowScalarAgg.mdp b/src/backend/gporca/data/dxl/minidump/VolatileFunctionsBelowScalarAgg.mdp index f1036d65cf1c..bfae7ced91e4 100644 --- a/src/backend/gporca/data/dxl/minidump/VolatileFunctionsBelowScalarAgg.mdp +++ b/src/backend/gporca/data/dxl/minidump/VolatileFunctionsBelowScalarAgg.mdp @@ -192,9 +192,7 @@ - - - + @@ -251,9 +249,9 @@ - + - + @@ -261,16 +259,17 @@ + - - - - - - - - + + + + + + + + @@ -281,7 +280,7 @@ - + @@ -323,9 +322,9 @@ - + - + diff --git a/src/backend/gporca/data/dxl/parse_tests/q57-DMLDelete.xml b/src/backend/gporca/data/dxl/parse_tests/q57-DMLDelete.xml index bda6d69b845d..3d3bc00350d8 100644 --- a/src/backend/gporca/data/dxl/parse_tests/q57-DMLDelete.xml +++ b/src/backend/gporca/data/dxl/parse_tests/q57-DMLDelete.xml @@ -14,6 +14,7 @@ + diff --git a/src/backend/gporca/data/dxl/parse_tests/q58-DMLInsert.xml b/src/backend/gporca/data/dxl/parse_tests/q58-DMLInsert.xml index ed5c5fb4b0c1..3ecc9607d996 100644 --- a/src/backend/gporca/data/dxl/parse_tests/q58-DMLInsert.xml +++ b/src/backend/gporca/data/dxl/parse_tests/q58-DMLInsert.xml @@ -39,6 +39,7 @@ + diff --git a/src/backend/gporca/data/dxl/parse_tests/q60-DMLUpdate.xml b/src/backend/gporca/data/dxl/parse_tests/q60-DMLUpdate.xml index 038c6673722a..65157473d473 100644 --- a/src/backend/gporca/data/dxl/parse_tests/q60-DMLUpdate.xml +++ b/src/backend/gporca/data/dxl/parse_tests/q60-DMLUpdate.xml @@ -17,6 +17,7 @@ + diff --git a/src/backend/gporca/libgpopt/include/gpopt/base/CUtils.h b/src/backend/gporca/libgpopt/include/gpopt/base/CUtils.h index 783603a4c950..71d4ad7a006f 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/base/CUtils.h +++ b/src/backend/gporca/libgpopt/include/gpopt/base/CUtils.h @@ -776,6 +776,9 @@ class CUtils // check if the given operator is a logical DML operator static BOOL FLogicalDML(COperator *pop); + // recursively checks if the given expression has logical DML operator + static BOOL FHasLogicalDML(CMemoryPool *mp, CExpression *pexpr); + // return regular string from wide-character string static CHAR *CreateMultiByteCharStringFromWCString(CMemoryPool *mp, WCHAR *wsz); diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDML.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDML.h index 5a83a1c009a7..ffeca0f89239 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDML.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDML.h @@ -52,6 +52,9 @@ class CLogicalDML : public CLogical // source columns CColRefArray *m_pdrgpcrSource; + // returning columns + CColRefArray *m_pdrgpcrOutput; + // set of modified columns from the target table CBitSet *m_pbsModified; @@ -81,9 +84,9 @@ class CLogicalDML : public CLogical // ctor CLogicalDML(CMemoryPool *mp, EDMLOperator edmlop, CTableDescriptor *ptabdesc, CColRefArray *colref_array, - CBitSet *pbsModified, CColRef *pcrAction, CColRef *pcrCtid, - CColRef *pcrSegmentId, CColRef *pcrTupleOid, - CColRef *pcrTableOid); + CColRefArray *pdrgpcrOutput, CBitSet *pbsModified, + CColRef *pcrAction, CColRef *pcrCtid, CColRef *pcrSegmentId, + CColRef *pcrTupleOid, CColRef *pcrTableOid); // dtor virtual ~CLogicalDML(); @@ -116,6 +119,14 @@ class CLogicalDML : public CLogical return m_pdrgpcrSource; } + // output columns + CColRefArray * + PdrgpcrOutput() const + { + return m_pdrgpcrOutput; + } + + // modified columns set CBitSet * PbsModified() const diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h index 9c270733c3f1..1771beb98584 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h @@ -37,6 +37,9 @@ class CLogicalDelete : public CLogical // columns to delete CColRefArray *m_pdrgpcr; + // returning columns + CColRefArray *m_pdrgpcrOutput; + // ctid column CColRef *m_pcrCtid; @@ -58,6 +61,12 @@ class CLogicalDelete : public CLogical CColRefArray *colref_array, CColRef *pcrCtid, CColRef *pcrSegmentId, CColRef *pcrTableOid); + // ctor + CLogicalDelete(CMemoryPool *mp, CTableDescriptor *ptabdesc, + CColRefArray *colref_array, CColRefArray *pdrgpcrOutput, + CColRef *pcrCtid, CColRef *pcrSegmentId, + CColRef *pcrTableOid); + // dtor virtual ~CLogicalDelete(); @@ -82,6 +91,13 @@ class CLogicalDelete : public CLogical return m_pdrgpcr; } + // output columns + CColRefArray * + PdrgpcrOutput() const + { + return m_pdrgpcrOutput; + } + // ctid column CColRef * PcrCtid() const diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalInsert.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalInsert.h index 6de2023612ce..2dff0a204ec2 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalInsert.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalInsert.h @@ -37,6 +37,9 @@ class CLogicalInsert : public CLogical // source columns CColRefArray *m_pdrgpcrSource; + // returning columns + CColRefArray *m_pdrgpcrOutput; + // private copy ctor CLogicalInsert(const CLogicalInsert &); @@ -48,6 +51,10 @@ class CLogicalInsert : public CLogical CLogicalInsert(CMemoryPool *mp, CTableDescriptor *ptabdesc, CColRefArray *colref_array); + // ctor + CLogicalInsert(CMemoryPool *mp, CTableDescriptor *ptabdesc, + CColRefArray *colref_array, CColRefArray *pdrgpcrOutput); + // dtor virtual ~CLogicalInsert(); @@ -72,6 +79,13 @@ class CLogicalInsert : public CLogical return m_pdrgpcrSource; } + // output columns + CColRefArray * + PdrgpcrOutput() const + { + return m_pdrgpcrOutput; + } + // return table's descriptor CTableDescriptor * Ptabdesc() const diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalUpdate.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalUpdate.h index 4c290bed7ff2..c65ee61a92e5 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalUpdate.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalUpdate.h @@ -40,6 +40,9 @@ class CLogicalUpdate : public CLogical // columns to insert CColRefArray *m_pdrgpcrInsert; + // returning columns + CColRefArray *m_pdrgpcrOutput; + // ctid column CColRef *m_pcrCtid; @@ -65,6 +68,13 @@ class CLogicalUpdate : public CLogical CColRef *pcrCtid, CColRef *pcrSegmentId, CColRef *pcrTupleOid, CColRef *pcrTableOid); + // ctor + CLogicalUpdate(CMemoryPool *mp, CTableDescriptor *ptabdesc, + CColRefArray *pdrgpcrDelete, CColRefArray *pdrgpcrInsert, + CColRefArray *pdrgpcrOutput, CColRef *pcrCtid, + CColRef *pcrSegmentId, CColRef *pcrTupleOid, + CColRef *pcrTableOid); + // dtor virtual ~CLogicalUpdate(); @@ -96,6 +106,13 @@ class CLogicalUpdate : public CLogical return m_pdrgpcrInsert; } + // output columns + CColRefArray * + PdrgpcrOutput() const + { + return m_pdrgpcrOutput; + } + // ctid column CColRef * PcrCtid() const diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CPhysicalDML.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CPhysicalDML.h index 377c02fe210c..c569b816950f 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CPhysicalDML.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CPhysicalDML.h @@ -42,6 +42,9 @@ class CPhysicalDML : public CPhysical // array of source columns CColRefArray *m_pdrgpcrSource; + // returning columns + CColRefArray *m_pdrgpcrOutput; + // set of modified columns from the target table CBitSet *m_pbsModified; @@ -67,9 +70,18 @@ class CPhysicalDML : public CPhysical // required order spec COrderSpec *m_pos; + // output distribution + CDistributionSpec *m_pdsOutput; + // required columns by local members CColRefSet *m_pcrsRequiredLocal; + // in case of CTAS dml node will output source columns + const BOOL m_isCTAS; + + // is there any triggers for this kind of dml operation + const BOOL m_hasTriggers; + // compute required order spec COrderSpec *PosComputeRequired(CMemoryPool *mp, CTableDescriptor *ptabdesc); @@ -83,9 +95,9 @@ class CPhysicalDML : public CPhysical // ctor CPhysicalDML(CMemoryPool *mp, CLogicalDML::EDMLOperator edmlop, CTableDescriptor *ptabdesc, CColRefArray *pdrgpcrSource, - CBitSet *pbsModified, CColRef *pcrAction, CColRef *pcrCtid, - CColRef *pcrSegmentId, CColRef *pcrTupleOid, - CColRef *prcTableOid); + CColRefArray *pdrgpcrOutput, CBitSet *pbsModified, + CColRef *pcrAction, CColRef *pcrCtid, CColRef *pcrSegmentId, + CColRef *pcrTupleOid, CColRef *prcTableOid); // dtor virtual ~CPhysicalDML(); @@ -160,6 +172,13 @@ class CPhysicalDML : public CPhysical return m_pdrgpcrSource; } + // output columns + virtual CColRefArray * + PdrgpcrOutput() const + { + return m_pdrgpcrOutput; + } + // match function virtual BOOL Matches(COperator *pop) const; @@ -173,6 +192,13 @@ class CPhysicalDML : public CPhysical return false; } + // does dml node has corresponding triggers + virtual BOOL + HasTriggers() const + { + return m_hasTriggers; + } + //------------------------------------------------------------------------------------- // Required Plan Properties //------------------------------------------------------------------------------------- diff --git a/src/backend/gporca/libgpopt/include/gpopt/xforms/CXformUtils.h b/src/backend/gporca/libgpopt/include/gpopt/xforms/CXformUtils.h index 23882b086d91..f417f5d2d8aa 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/xforms/CXformUtils.h +++ b/src/backend/gporca/libgpopt/include/gpopt/xforms/CXformUtils.h @@ -423,14 +423,19 @@ class CXformUtils static CExpression *PexprLogicalDMLOverProject( CMemoryPool *mp, CExpression *pexprChild, CLogicalDML::EDMLOperator edmlop, CTableDescriptor *ptabdesc, - CColRefArray *colref_array, CColRef *pcrCtid, CColRef *pcrSegmentId, - CColRef *pcrTableOid); + CColRefArray *colref_array, CColRefArray *pdrgpcrOutput, + CColRef *pcrCtid, CColRef *pcrSegmentId, CColRef *pcrTableOid); // check whether there are any BEFORE or AFTER triggers on the // given table that match the given DML operation static BOOL FTriggersExist(CLogicalDML::EDMLOperator edmlop, CTableDescriptor *ptabdesc, BOOL fBefore); + // check whether there are any triggers on the + // given table that match the given DML operation + static BOOL FTriggersExist(CLogicalDML::EDMLOperator edmlop, + CTableDescriptor *ptabdesc); + // does the given trigger type match the given logical DML type static BOOL FTriggerApplies(CLogicalDML::EDMLOperator edmlop, const IMDTrigger *pmdtrigger); diff --git a/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp b/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp index ae84429e585b..97a298059440 100644 --- a/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp +++ b/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp @@ -211,12 +211,11 @@ CQueryContext::PqcGenerate(CMemoryPool *mp, CExpression *pexpr, CDistributionSpec *pds = NULL; - BOOL fDML = CUtils::FLogicalDML(pexpr->Pop()); - poptctxt->MarkDMLQuery(fDML); + poptctxt->MarkDMLQuery(CUtils::FHasLogicalDML(mp, pexpr)); // DML commands do not have distribution requirement. Otherwise the // distribution requirement is Singleton. - if (fDML) + if (CUtils::FLogicalDML(pexpr->Pop())) { pds = GPOS_NEW(mp) CDistributionSpecAny(COperator::EopSentinel); } diff --git a/src/backend/gporca/libgpopt/src/base/CUtils.cpp b/src/backend/gporca/libgpopt/src/base/CUtils.cpp index a1fddc6f565d..b5bafbbd273b 100644 --- a/src/backend/gporca/libgpopt/src/base/CUtils.cpp +++ b/src/backend/gporca/libgpopt/src/base/CUtils.cpp @@ -10,6 +10,7 @@ //--------------------------------------------------------------------------- #include "gpopt/base/CUtils.h" +#include "gpos/common/CDynamicPtrArray.h" #include "gpos/common/clibwrapper.h" #include "gpos/common/syslibwrapper.h" #include "gpos/io/CFileDescriptor.h" @@ -3276,6 +3277,39 @@ CUtils::FLogicalDML(COperator *pop) COperator::EopLogicalUpdate == op_id; } +// recursively checks if the given expression has logical DML operator +BOOL +CUtils::FHasLogicalDML(CMemoryPool *mp, CExpression *pexpr) +{ + GPOS_ASSERT(NULL != mp); + GPOS_ASSERT(NULL != pexpr); + + CDynamicPtrArray *exprsToCheck = + GPOS_NEW(mp) CDynamicPtrArray(mp); + exprsToCheck->Append(pexpr); + + while (exprsToCheck->Size() > 0) + { + CExpression *pexprCurrent = (*exprsToCheck)[exprsToCheck->Size() - 1]; + exprsToCheck->RemoveLast(); + + if (FLogicalDML(pexprCurrent->Pop())) + { + exprsToCheck->Release(); + return true; + } + + const ULONG arity = pexprCurrent->Arity(); + for (ULONG ul = 0; ul < arity; ++ul) + { + exprsToCheck->Append((*pexprCurrent)[ul]); + } + } + + exprsToCheck->Release(); + return false; +} + // return regular string from wide-character string CHAR * CUtils::CreateMultiByteCharStringFromWCString(CMemoryPool *mp, WCHAR *wsz) diff --git a/src/backend/gporca/libgpopt/src/operators/CExpressionPreprocessor.cpp b/src/backend/gporca/libgpopt/src/operators/CExpressionPreprocessor.cpp index 01fcb7a97b13..ab38d15284c4 100644 --- a/src/backend/gporca/libgpopt/src/operators/CExpressionPreprocessor.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CExpressionPreprocessor.cpp @@ -1542,7 +1542,7 @@ CExpressionPreprocessor::PexprAddEqualityPreds(CMemoryPool *mp, CExpression *pexprPred = NULL; COperator *pop = pexpr->Pop(); - if (CUtils::FLogicalDML(pop)) + if (CUtils::FHasLogicalDML(mp, pexpr)) { pexprPred = CUtils::PexprScalarConstBool(mp, true); } @@ -1943,7 +1943,7 @@ CExpressionPreprocessor::PexprPruneEmptySubtrees(CMemoryPool *mp, GPOS_ASSERT(NULL != pexpr); COperator *pop = pexpr->Pop(); - if (pop->FLogical() && !CUtils::FLogicalDML(pop)) + if (pop->FLogical() && !CUtils::FHasLogicalDML(mp, pexpr)) { // if maxcard = 0: return a const table get with same output columns and zero tuples if (0 == pexpr->DeriveMaxCard()) diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp index dad8e05ab9db..15e8a12b2fd7 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp @@ -37,6 +37,7 @@ CLogicalDML::CLogicalDML(CMemoryPool *mp) : CLogical(mp), m_ptabdesc(NULL), m_pdrgpcrSource(NULL), + m_pdrgpcrOutput(NULL), m_pbsModified(NULL), m_pcrAction(NULL), m_pcrTableOid(NULL), @@ -57,7 +58,8 @@ CLogicalDML::CLogicalDML(CMemoryPool *mp) //--------------------------------------------------------------------------- CLogicalDML::CLogicalDML(CMemoryPool *mp, EDMLOperator edmlop, CTableDescriptor *ptabdesc, - CColRefArray *pdrgpcrSource, CBitSet *pbsModified, + CColRefArray *pdrgpcrSource, + CColRefArray *pdrgpcrOutput, CBitSet *pbsModified, CColRef *pcrAction, CColRef *pcrCtid, CColRef *pcrSegmentId, CColRef *pcrTupleOid, CColRef *pcrTableOid) @@ -65,6 +67,7 @@ CLogicalDML::CLogicalDML(CMemoryPool *mp, EDMLOperator edmlop, m_edmlop(edmlop), m_ptabdesc(ptabdesc), m_pdrgpcrSource(pdrgpcrSource), + m_pdrgpcrOutput(pdrgpcrOutput), m_pbsModified(pbsModified), m_pcrAction(pcrAction), m_pcrTableOid(pcrTableOid), @@ -81,6 +84,7 @@ CLogicalDML::CLogicalDML(CMemoryPool *mp, EDMLOperator edmlop, NULL != pcrCtid && NULL != pcrSegmentId); m_pcrsLocalUsed->Include(m_pdrgpcrSource); + m_pcrsLocalUsed->Include(m_pdrgpcrOutput); m_pcrsLocalUsed->Include(m_pcrAction); if (NULL != m_pcrTableOid) { @@ -116,6 +120,7 @@ CLogicalDML::~CLogicalDML() { CRefCount::SafeRelease(m_ptabdesc); CRefCount::SafeRelease(m_pdrgpcrSource); + CRefCount::SafeRelease(m_pdrgpcrOutput); CRefCount::SafeRelease(m_pbsModified); } @@ -143,7 +148,8 @@ CLogicalDML::Matches(COperator *pop) const m_pcrSegmentId == popDML->PcrSegmentId() && m_pcrTupleOid == popDML->PcrTupleOid() && m_ptabdesc->MDId()->Equals(popDML->Ptabdesc()->MDId()) && - m_pdrgpcrSource->Equals(popDML->PdrgpcrSource()); + m_pdrgpcrSource->Equals(popDML->PdrgpcrSource()) && + m_pdrgpcrOutput->Equals(popDML->PdrgpcrOutput()); } //--------------------------------------------------------------------------- @@ -162,6 +168,8 @@ CLogicalDML::HashValue() const ulHash = gpos::CombineHashes(ulHash, gpos::HashPtr(m_pcrAction)); ulHash = gpos::CombineHashes(ulHash, CUtils::UlHashColArray(m_pdrgpcrSource)); + ulHash = + gpos::CombineHashes(ulHash, CUtils::UlHashColArray(m_pdrgpcrOutput)); ulHash = gpos::CombineHashes(ulHash, gpos::HashPtr(m_pcrTableOid)); if (EdmlDelete == m_edmlop || EdmlUpdate == m_edmlop) @@ -189,6 +197,18 @@ CLogicalDML::PopCopyWithRemappedColumns(CMemoryPool *mp, { CColRefArray *colref_array = CUtils::PdrgpcrRemap(mp, m_pdrgpcrSource, colref_mapping, must_exist); + + CColRefArray *pdrgpcrOutput = NULL; + if (must_exist) + { + pdrgpcrOutput = + CUtils::PdrgpcrRemapAndCreate(mp, m_pdrgpcrOutput, colref_mapping); + } + else + { + pdrgpcrOutput = CUtils::PdrgpcrRemap(mp, m_pdrgpcrOutput, + colref_mapping, must_exist); + } CColRef *pcrAction = CUtils::PcrRemap(m_pcrAction, colref_mapping, must_exist); @@ -225,9 +245,9 @@ CLogicalDML::PopCopyWithRemappedColumns(CMemoryPool *mp, m_ptabdesc->AddRef(); - return GPOS_NEW(mp) - CLogicalDML(mp, m_edmlop, m_ptabdesc, colref_array, m_pbsModified, - pcrAction, pcrCtid, pcrSegmentId, pcrTupleOid, pcrTableOid); + return GPOS_NEW(mp) CLogicalDML( + mp, m_edmlop, m_ptabdesc, colref_array, pdrgpcrOutput, m_pbsModified, + pcrAction, pcrCtid, pcrSegmentId, pcrTupleOid, pcrTableOid); } //--------------------------------------------------------------------------- @@ -245,6 +265,7 @@ CLogicalDML::DeriveOutputColumns(CMemoryPool *mp, { CColRefSet *pcrsOutput = GPOS_NEW(mp) CColRefSet(mp); pcrsOutput->Include(m_pdrgpcrSource); + pcrsOutput->Include(m_pdrgpcrOutput); if (NULL != m_pcrCtid) { GPOS_ASSERT(NULL != m_pcrSegmentId); @@ -276,6 +297,7 @@ CLogicalDML::DerivePropertyConstraint(CMemoryPool *mp, { CColRefSet *pcrsOutput = GPOS_NEW(mp) CColRefSet(mp); pcrsOutput->Include(m_pdrgpcrSource); + pcrsOutput->Include(m_pdrgpcrOutput); CPropConstraint *ppc = PpcDeriveConstraintRestrict(mp, exprhdl, pcrsOutput); pcrsOutput->Release(); @@ -291,10 +313,13 @@ CLogicalDML::DerivePropertyConstraint(CMemoryPool *mp, // //--------------------------------------------------------------------------- CKeyCollection * -CLogicalDML::DeriveKeyCollection(CMemoryPool *, // mp - CExpressionHandle &exprhdl) const +CLogicalDML::DeriveKeyCollection(CMemoryPool *mp, + CExpressionHandle & // exprhdl +) const { - return PkcDeriveKeysPassThru(exprhdl, 0 /* ulChild */); + const CBitSetArray *pdrgpbs = m_ptabdesc->PdrgpbsKeys(); + + return CLogical::PkcKeysBaseTable(mp, pdrgpbs, m_pdrgpcrOutput); } //--------------------------------------------------------------------------- @@ -386,6 +411,38 @@ CLogicalDML::OsPrint(IOstream &os) const m_pcrSegmentId->OsPrint(os); } + os << ", Output Columns: ["; + CUtils::OsPrintDrgPcr(os, m_pdrgpcrOutput); + os << "] Key sets: {"; + + const ULONG ulColumns = m_pdrgpcrOutput->Size(); + const CBitSetArray *pdrgpbsKeys = m_ptabdesc->PdrgpbsKeys(); + for (ULONG ul = 0; ul < pdrgpbsKeys->Size(); ul++) + { + CBitSet *pbs = (*pdrgpbsKeys)[ul]; + if (0 < ul) + { + os << ", "; + } + os << "["; + ULONG ulPrintedKeys = 0; + for (ULONG ulKey = 0; ulKey < ulColumns; ulKey++) + { + if (pbs->Get(ulKey)) + { + if (0 < ulPrintedKeys) + { + os << ","; + } + os << ulKey; + ulPrintedKeys++; + } + } + os << "]"; + } + os << "}"; + + return os; } diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp index 10f126f7f925..6247487b7ca9 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp @@ -33,6 +33,7 @@ CLogicalDelete::CLogicalDelete(CMemoryPool *mp) : CLogical(mp), m_ptabdesc(NULL), m_pdrgpcr(NULL), + m_pdrgpcrOutput(NULL), m_pcrCtid(NULL), m_pcrSegmentId(NULL), m_pcrTableOid(NULL) @@ -54,6 +55,45 @@ CLogicalDelete::CLogicalDelete(CMemoryPool *mp, CTableDescriptor *ptabdesc, : CLogical(mp), m_ptabdesc(ptabdesc), m_pdrgpcr(colref_array), + m_pdrgpcrOutput(NULL), + m_pcrCtid(pcrCtid), + m_pcrSegmentId(pcrSegmentId), + m_pcrTableOid(pcrTableOid) +{ + GPOS_ASSERT(NULL != ptabdesc); + GPOS_ASSERT(NULL != colref_array); + GPOS_ASSERT(NULL != pcrCtid); + GPOS_ASSERT(NULL != pcrSegmentId); + + m_pdrgpcrOutput = + PdrgpcrCreateMapping(mp, ptabdesc->Pdrgpcoldesc(), UlOpId()); + + m_pcrsLocalUsed->Include(m_pdrgpcr); + m_pcrsLocalUsed->Include(m_pdrgpcrOutput); + m_pcrsLocalUsed->Include(m_pcrCtid); + m_pcrsLocalUsed->Include(m_pcrSegmentId); + if (NULL != m_pcrTableOid) + { + m_pcrsLocalUsed->Include(m_pcrTableOid); + } +} + +//--------------------------------------------------------------------------- +// @function: +// CLogicalDelete::CLogicalDelete +// +// @doc: +// Ctor +// +//--------------------------------------------------------------------------- +CLogicalDelete::CLogicalDelete(CMemoryPool *mp, CTableDescriptor *ptabdesc, + CColRefArray *colref_array, + CColRefArray *pdrgpcrOutput, CColRef *pcrCtid, + CColRef *pcrSegmentId, CColRef *pcrTableOid) + : CLogical(mp), + m_ptabdesc(ptabdesc), + m_pdrgpcr(colref_array), + m_pdrgpcrOutput(pdrgpcrOutput), m_pcrCtid(pcrCtid), m_pcrSegmentId(pcrSegmentId), m_pcrTableOid(pcrTableOid) @@ -64,6 +104,7 @@ CLogicalDelete::CLogicalDelete(CMemoryPool *mp, CTableDescriptor *ptabdesc, GPOS_ASSERT(NULL != pcrSegmentId); m_pcrsLocalUsed->Include(m_pdrgpcr); + m_pcrsLocalUsed->Include(m_pdrgpcrOutput); m_pcrsLocalUsed->Include(m_pcrCtid); m_pcrsLocalUsed->Include(m_pcrSegmentId); if (NULL != m_pcrTableOid) @@ -84,6 +125,7 @@ CLogicalDelete::~CLogicalDelete() { CRefCount::SafeRelease(m_ptabdesc); CRefCount::SafeRelease(m_pdrgpcr); + CRefCount::SafeRelease(m_pdrgpcrOutput); } //--------------------------------------------------------------------------- @@ -108,10 +150,11 @@ CLogicalDelete::Matches(COperator *pop) const m_pcrSegmentId == popDelete->PcrSegmentId() && m_pcrTableOid == popDelete->PcrTableOid() && m_ptabdesc->MDId()->Equals(popDelete->Ptabdesc()->MDId()) && - m_pdrgpcr->Equals(popDelete->Pdrgpcr()); + m_pdrgpcr->Equals(popDelete->Pdrgpcr()) && + m_pdrgpcrOutput->Equals(popDelete->PdrgpcrOutput()); } - //--------------------------------------------------------------------------- + // @function: // CLogicalDelete::HashValue // @@ -125,6 +168,8 @@ CLogicalDelete::HashValue() const ULONG ulHash = gpos::CombineHashes(COperator::HashValue(), m_ptabdesc->MDId()->HashValue()); ulHash = gpos::CombineHashes(ulHash, CUtils::UlHashColArray(m_pdrgpcr)); + ulHash = + gpos::CombineHashes(ulHash, CUtils::UlHashColArray(m_pdrgpcrOutput)); ulHash = gpos::CombineHashes(ulHash, gpos::HashPtr(m_pcrCtid)); ulHash = gpos::CombineHashes(ulHash, gpos::HashPtr(m_pcrSegmentId)); @@ -148,6 +193,19 @@ CLogicalDelete::PopCopyWithRemappedColumns(CMemoryPool *mp, { CColRefArray *colref_array = CUtils::PdrgpcrRemap(mp, m_pdrgpcr, colref_mapping, must_exist); + + CColRefArray *pdrgpcrOutput = NULL; + if (must_exist) + { + pdrgpcrOutput = + CUtils::PdrgpcrRemapAndCreate(mp, m_pdrgpcrOutput, colref_mapping); + } + else + { + pdrgpcrOutput = CUtils::PdrgpcrRemap(mp, m_pdrgpcrOutput, + colref_mapping, must_exist); + } + CColRef *pcrCtid = CUtils::PcrRemap(m_pcrCtid, colref_mapping, must_exist); CColRef *pcrSegmentId = CUtils::PcrRemap(m_pcrSegmentId, colref_mapping, must_exist); @@ -159,8 +217,9 @@ CLogicalDelete::PopCopyWithRemappedColumns(CMemoryPool *mp, CUtils::PcrRemap(m_pcrTableOid, colref_mapping, must_exist); } - return GPOS_NEW(mp) CLogicalDelete(mp, m_ptabdesc, colref_array, pcrCtid, - pcrSegmentId, pcrTableOid); + return GPOS_NEW(mp) + CLogicalDelete(mp, m_ptabdesc, colref_array, pdrgpcrOutput, pcrCtid, + pcrSegmentId, pcrTableOid); } //--------------------------------------------------------------------------- @@ -178,6 +237,8 @@ CLogicalDelete::DeriveOutputColumns(CMemoryPool *mp, { CColRefSet *pcrsOutput = GPOS_NEW(mp) CColRefSet(mp); pcrsOutput->Include(m_pdrgpcr); + pcrsOutput->Include(m_pdrgpcrOutput); + return pcrsOutput; } @@ -190,10 +251,13 @@ CLogicalDelete::DeriveOutputColumns(CMemoryPool *mp, // //--------------------------------------------------------------------------- CKeyCollection * -CLogicalDelete::DeriveKeyCollection(CMemoryPool *, // mp - CExpressionHandle &exprhdl) const +CLogicalDelete::DeriveKeyCollection(CMemoryPool *mp, + CExpressionHandle & // exprhdl +) const { - return PkcDeriveKeysPassThru(exprhdl, 0 /* ulChild */); + const CBitSetArray *pdrgpbs = m_ptabdesc->PdrgpbsKeys(); + + return CLogical::PkcKeysBaseTable(mp, pdrgpbs, m_pdrgpcrOutput); } //--------------------------------------------------------------------------- @@ -276,6 +340,37 @@ CLogicalDelete::OsPrint(IOstream &os) const os << ", "; } + os << "Output Columns: ["; + CUtils::OsPrintDrgPcr(os, m_pdrgpcrOutput); + os << "] Key sets: {"; + + const ULONG ulColumns = m_pdrgpcrOutput->Size(); + const CBitSetArray *pdrgpbsKeys = m_ptabdesc->PdrgpbsKeys(); + for (ULONG ul = 0; ul < pdrgpbsKeys->Size(); ul++) + { + CBitSet *pbs = (*pdrgpbsKeys)[ul]; + if (0 < ul) + { + os << ", "; + } + os << "["; + ULONG ulPrintedKeys = 0; + for (ULONG ulKey = 0; ulKey < ulColumns; ulKey++) + { + if (pbs->Get(ulKey)) + { + if (0 < ulPrintedKeys) + { + os << ","; + } + os << ulKey; + ulPrintedKeys++; + } + } + os << "]"; + } + os << "}"; + return os; } diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp index 15e948216263..a6366a2fa498 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp @@ -30,7 +30,11 @@ using namespace gpopt; // //--------------------------------------------------------------------------- CLogicalInsert::CLogicalInsert(CMemoryPool *mp) - : CLogical(mp), m_ptabdesc(NULL), m_pdrgpcrSource(NULL) + : CLogical(mp), + m_ptabdesc(NULL), + m_pdrgpcrSource(NULL), + m_pdrgpcrOutput(NULL) + { m_fPattern = true; } @@ -45,13 +49,45 @@ CLogicalInsert::CLogicalInsert(CMemoryPool *mp) //--------------------------------------------------------------------------- CLogicalInsert::CLogicalInsert(CMemoryPool *mp, CTableDescriptor *ptabdesc, CColRefArray *pdrgpcrSource) - : CLogical(mp), m_ptabdesc(ptabdesc), m_pdrgpcrSource(pdrgpcrSource) + : CLogical(mp), + m_ptabdesc(ptabdesc), + m_pdrgpcrSource(pdrgpcrSource), + m_pdrgpcrOutput(NULL) { GPOS_ASSERT(NULL != ptabdesc); GPOS_ASSERT(NULL != pdrgpcrSource); + m_pdrgpcrOutput = + PdrgpcrCreateMapping(mp, ptabdesc->Pdrgpcoldesc(), UlOpId()); + m_pcrsLocalUsed->Include(m_pdrgpcrSource); + m_pcrsLocalUsed->Include(m_pdrgpcrOutput); +} + + +//--------------------------------------------------------------------------- +// @function: +// CLogicalInsert::CLogicalInsert +// +// @doc: +// Ctor +// +//--------------------------------------------------------------------------- +CLogicalInsert::CLogicalInsert(CMemoryPool *mp, CTableDescriptor *ptabdesc, + CColRefArray *pdrgpcrSource, + CColRefArray *pdrgpcrOutput) + : CLogical(mp), + m_ptabdesc(ptabdesc), + m_pdrgpcrSource(pdrgpcrSource), + m_pdrgpcrOutput(pdrgpcrOutput) + +{ + GPOS_ASSERT(NULL != ptabdesc); + GPOS_ASSERT(NULL != pdrgpcrSource); + + m_pcrsLocalUsed->Include(m_pdrgpcrSource); + m_pcrsLocalUsed->Include(m_pdrgpcrOutput); } //--------------------------------------------------------------------------- @@ -66,6 +102,7 @@ CLogicalInsert::~CLogicalInsert() { CRefCount::SafeRelease(m_ptabdesc); CRefCount::SafeRelease(m_pdrgpcrSource); + CRefCount::SafeRelease(m_pdrgpcrOutput); } //--------------------------------------------------------------------------- @@ -87,7 +124,8 @@ CLogicalInsert::Matches(COperator *pop) const CLogicalInsert *popInsert = CLogicalInsert::PopConvert(pop); return m_ptabdesc->MDId()->Equals(popInsert->Ptabdesc()->MDId()) && - m_pdrgpcrSource->Equals(popInsert->PdrgpcrSource()); + m_pdrgpcrSource->Equals(popInsert->PdrgpcrSource()) && + m_pdrgpcrOutput->Equals(popInsert->PdrgpcrOutput()); } //--------------------------------------------------------------------------- @@ -106,6 +144,9 @@ CLogicalInsert::HashValue() const ulHash = gpos::CombineHashes(ulHash, CUtils::UlHashColArray(m_pdrgpcrSource)); + ulHash = + gpos::CombineHashes(ulHash, CUtils::UlHashColArray(m_pdrgpcrOutput)); + return ulHash; } @@ -124,9 +165,22 @@ CLogicalInsert::PopCopyWithRemappedColumns(CMemoryPool *mp, { CColRefArray *colref_array = CUtils::PdrgpcrRemap(mp, m_pdrgpcrSource, colref_mapping, must_exist); + + CColRefArray *pdrgpcrOutput = NULL; + if (must_exist) + { + pdrgpcrOutput = + CUtils::PdrgpcrRemapAndCreate(mp, m_pdrgpcrOutput, colref_mapping); + } + else + { + pdrgpcrOutput = CUtils::PdrgpcrRemap(mp, m_pdrgpcrOutput, + colref_mapping, must_exist); + } m_ptabdesc->AddRef(); - return GPOS_NEW(mp) CLogicalInsert(mp, m_ptabdesc, colref_array); + return GPOS_NEW(mp) + CLogicalInsert(mp, m_ptabdesc, colref_array, pdrgpcrOutput); } //--------------------------------------------------------------------------- @@ -144,6 +198,8 @@ CLogicalInsert::DeriveOutputColumns(CMemoryPool *mp, { CColRefSet *pcrsOutput = GPOS_NEW(mp) CColRefSet(mp); pcrsOutput->Include(m_pdrgpcrSource); + pcrsOutput->Include(m_pdrgpcrOutput); + return pcrsOutput; } @@ -156,10 +212,13 @@ CLogicalInsert::DeriveOutputColumns(CMemoryPool *mp, // //--------------------------------------------------------------------------- CKeyCollection * -CLogicalInsert::DeriveKeyCollection(CMemoryPool *, // mp - CExpressionHandle &exprhdl) const +CLogicalInsert::DeriveKeyCollection(CMemoryPool *mp, + CExpressionHandle & // exprhdl +) const { - return PkcDeriveKeysPassThru(exprhdl, 0 /* ulChild */); + const CBitSetArray *pdrgpbs = m_ptabdesc->PdrgpbsKeys(); + + return CLogical::PkcKeysBaseTable(mp, pdrgpbs, m_pdrgpcrOutput); } //--------------------------------------------------------------------------- @@ -232,6 +291,36 @@ CLogicalInsert::OsPrint(IOstream &os) const os << "), Source Columns: ["; CUtils::OsPrintDrgPcr(os, m_pdrgpcrSource); os << "]"; + os << ", Output Columns: ["; + CUtils::OsPrintDrgPcr(os, m_pdrgpcrOutput); + os << "] Key sets: {"; + + const ULONG ulColumns = m_pdrgpcrOutput->Size(); + const CBitSetArray *pdrgpbsKeys = m_ptabdesc->PdrgpbsKeys(); + for (ULONG ul = 0; ul < pdrgpbsKeys->Size(); ul++) + { + CBitSet *pbs = (*pdrgpbsKeys)[ul]; + if (0 < ul) + { + os << ", "; + } + os << "["; + ULONG ulPrintedKeys = 0; + for (ULONG ulKey = 0; ulKey < ulColumns; ulKey++) + { + if (pbs->Get(ulKey)) + { + if (0 < ulPrintedKeys) + { + os << ","; + } + os << ulKey; + ulPrintedKeys++; + } + } + os << "]"; + } + os << "}"; return os; } diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp index 9fb4cbbb57bb..5fed6926e7de 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp @@ -34,6 +34,7 @@ CLogicalUpdate::CLogicalUpdate(CMemoryPool *mp) m_ptabdesc(NULL), m_pdrgpcrDelete(NULL), m_pdrgpcrInsert(NULL), + m_pdrgpcrOutput(NULL), m_pcrCtid(NULL), m_pcrSegmentId(NULL), m_pcrTupleOid(NULL), @@ -59,6 +60,7 @@ CLogicalUpdate::CLogicalUpdate(CMemoryPool *mp, CTableDescriptor *ptabdesc, m_ptabdesc(ptabdesc), m_pdrgpcrDelete(pdrgpcrDelete), m_pdrgpcrInsert(pdrgpcrInsert), + m_pdrgpcrOutput(NULL), m_pcrCtid(pcrCtid), m_pcrSegmentId(pcrSegmentId), m_pcrTupleOid(pcrTupleOid), @@ -71,8 +73,12 @@ CLogicalUpdate::CLogicalUpdate(CMemoryPool *mp, CTableDescriptor *ptabdesc, GPOS_ASSERT(NULL != pcrCtid); GPOS_ASSERT(NULL != pcrSegmentId); + m_pdrgpcrOutput = + PdrgpcrCreateMapping(mp, ptabdesc->Pdrgpcoldesc(), UlOpId()); + m_pcrsLocalUsed->Include(m_pdrgpcrDelete); m_pcrsLocalUsed->Include(m_pdrgpcrInsert); + m_pcrsLocalUsed->Include(m_pdrgpcrOutput); m_pcrsLocalUsed->Include(m_pcrCtid); m_pcrsLocalUsed->Include(m_pcrSegmentId); @@ -87,6 +93,55 @@ CLogicalUpdate::CLogicalUpdate(CMemoryPool *mp, CTableDescriptor *ptabdesc, } } +//--------------------------------------------------------------------------- +// @function: +// CLogicalUpdate::CLogicalUpdate +// +// @doc: +// Ctor +// +//--------------------------------------------------------------------------- +CLogicalUpdate::CLogicalUpdate(CMemoryPool *mp, CTableDescriptor *ptabdesc, + CColRefArray *pdrgpcrDelete, + CColRefArray *pdrgpcrInsert, + CColRefArray *pdrgpcrOutput, CColRef *pcrCtid, + CColRef *pcrSegmentId, CColRef *pcrTupleOid, + CColRef *pcrTableOid) + : CLogical(mp), + m_ptabdesc(ptabdesc), + m_pdrgpcrDelete(pdrgpcrDelete), + m_pdrgpcrInsert(pdrgpcrInsert), + m_pdrgpcrOutput(pdrgpcrOutput), + m_pcrCtid(pcrCtid), + m_pcrSegmentId(pcrSegmentId), + m_pcrTupleOid(pcrTupleOid), + m_pcrTableOid(pcrTableOid) +{ + GPOS_ASSERT(NULL != ptabdesc); + GPOS_ASSERT(NULL != pdrgpcrDelete); + GPOS_ASSERT(NULL != pdrgpcrInsert); + GPOS_ASSERT(pdrgpcrDelete->Size() == pdrgpcrInsert->Size()); + GPOS_ASSERT(NULL != pcrCtid); + GPOS_ASSERT(NULL != pcrSegmentId); + + m_pcrsLocalUsed->Include(m_pdrgpcrDelete); + m_pcrsLocalUsed->Include(m_pdrgpcrInsert); + m_pcrsLocalUsed->Include(m_pdrgpcrOutput); + m_pcrsLocalUsed->Include(m_pcrCtid); + m_pcrsLocalUsed->Include(m_pcrSegmentId); + + if (NULL != m_pcrTupleOid) + { + m_pcrsLocalUsed->Include(m_pcrTupleOid); + } + + if (NULL != m_pcrTableOid) + { + m_pcrsLocalUsed->Include(m_pcrTableOid); + } +} + + //--------------------------------------------------------------------------- // @function: // CLogicalUpdate::~CLogicalUpdate @@ -100,6 +155,7 @@ CLogicalUpdate::~CLogicalUpdate() CRefCount::SafeRelease(m_ptabdesc); CRefCount::SafeRelease(m_pdrgpcrDelete); CRefCount::SafeRelease(m_pdrgpcrInsert); + CRefCount::SafeRelease(m_pdrgpcrOutput); } //--------------------------------------------------------------------------- @@ -126,7 +182,8 @@ CLogicalUpdate::Matches(COperator *pop) const m_pcrTableOid == popUpdate->PcrTableOid() && m_ptabdesc->MDId()->Equals(popUpdate->Ptabdesc()->MDId()) && m_pdrgpcrDelete->Equals(popUpdate->PdrgpcrDelete()) && - m_pdrgpcrInsert->Equals(popUpdate->PdrgpcrInsert()); + m_pdrgpcrInsert->Equals(popUpdate->PdrgpcrInsert()) && + m_pdrgpcrOutput->Equals(popUpdate->PdrgpcrOutput()); } //--------------------------------------------------------------------------- @@ -146,6 +203,8 @@ CLogicalUpdate::HashValue() const gpos::CombineHashes(ulHash, CUtils::UlHashColArray(m_pdrgpcrDelete)); ulHash = gpos::CombineHashes(ulHash, CUtils::UlHashColArray(m_pdrgpcrInsert)); + ulHash = + gpos::CombineHashes(ulHash, CUtils::UlHashColArray(m_pdrgpcrOutput)); ulHash = gpos::CombineHashes(ulHash, gpos::HashPtr(m_pcrCtid)); ulHash = gpos::CombineHashes(ulHash, gpos::HashPtr(m_pcrSegmentId)); @@ -171,6 +230,19 @@ CLogicalUpdate::PopCopyWithRemappedColumns(CMemoryPool *mp, CUtils::PdrgpcrRemap(mp, m_pdrgpcrDelete, colref_mapping, must_exist); CColRefArray *pdrgpcrInsert = CUtils::PdrgpcrRemap(mp, m_pdrgpcrInsert, colref_mapping, must_exist); + + CColRefArray *pdrgpcrOutput = NULL; + if (must_exist) + { + pdrgpcrOutput = + CUtils::PdrgpcrRemapAndCreate(mp, m_pdrgpcrOutput, colref_mapping); + } + else + { + pdrgpcrOutput = CUtils::PdrgpcrRemap(mp, m_pdrgpcrOutput, + colref_mapping, must_exist); + } + CColRef *pcrCtid = CUtils::PcrRemap(m_pcrCtid, colref_mapping, must_exist); CColRef *pcrSegmentId = CUtils::PcrRemap(m_pcrSegmentId, colref_mapping, must_exist); @@ -189,9 +261,9 @@ CLogicalUpdate::PopCopyWithRemappedColumns(CMemoryPool *mp, pcrTableOid = CUtils::PcrRemap(m_pcrTableOid, colref_mapping, must_exist); } - return GPOS_NEW(mp) - CLogicalUpdate(mp, m_ptabdesc, pdrgpcrDelete, pdrgpcrInsert, pcrCtid, - pcrSegmentId, pcrTupleOid, pcrTableOid); + return GPOS_NEW(mp) CLogicalUpdate(mp, m_ptabdesc, pdrgpcrDelete, + pdrgpcrInsert, pdrgpcrOutput, pcrCtid, + pcrSegmentId, pcrTupleOid, pcrTableOid); } //--------------------------------------------------------------------------- @@ -209,6 +281,7 @@ CLogicalUpdate::DeriveOutputColumns(CMemoryPool *mp, { CColRefSet *pcrsOutput = GPOS_NEW(mp) CColRefSet(mp); pcrsOutput->Include(m_pdrgpcrInsert); + pcrsOutput->Include(m_pdrgpcrOutput); pcrsOutput->Include(m_pcrCtid); pcrsOutput->Include(m_pcrSegmentId); @@ -232,10 +305,13 @@ CLogicalUpdate::DeriveOutputColumns(CMemoryPool *mp, // //--------------------------------------------------------------------------- CKeyCollection * -CLogicalUpdate::DeriveKeyCollection(CMemoryPool *, // mp - CExpressionHandle &exprhdl) const +CLogicalUpdate::DeriveKeyCollection(CMemoryPool *mp, + CExpressionHandle & // exprhdl +) const { - return PkcDeriveKeysPassThru(exprhdl, 0 /* ulChild */); + const CBitSetArray *pdrgpbs = m_ptabdesc->PdrgpbsKeys(); + + return CLogical::PkcKeysBaseTable(mp, pdrgpbs, m_pdrgpcrOutput); } //--------------------------------------------------------------------------- @@ -320,6 +396,37 @@ CLogicalUpdate::OsPrint(IOstream &os) const os << ", "; } + os << "Output Columns: ["; + CUtils::OsPrintDrgPcr(os, m_pdrgpcrOutput); + os << "] Key sets: {"; + + const ULONG ulColumns = m_pdrgpcrOutput->Size(); + const CBitSetArray *pdrgpbsKeys = m_ptabdesc->PdrgpbsKeys(); + for (ULONG ul = 0; ul < pdrgpbsKeys->Size(); ul++) + { + CBitSet *pbs = (*pdrgpbsKeys)[ul]; + if (0 < ul) + { + os << ", "; + } + os << "["; + ULONG ulPrintedKeys = 0; + for (ULONG ulKey = 0; ulKey < ulColumns; ulKey++) + { + if (pbs->Get(ulKey)) + { + if (0 < ulPrintedKeys) + { + os << ","; + } + os << ulKey; + ulPrintedKeys++; + } + } + os << "]"; + } + os << "}"; + return os; } diff --git a/src/backend/gporca/libgpopt/src/operators/CPhysicalDML.cpp b/src/backend/gporca/libgpopt/src/operators/CPhysicalDML.cpp index 2694618be87a..28425b0390ac 100644 --- a/src/backend/gporca/libgpopt/src/operators/CPhysicalDML.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CPhysicalDML.cpp @@ -37,7 +37,8 @@ using namespace gpopt; //--------------------------------------------------------------------------- CPhysicalDML::CPhysicalDML(CMemoryPool *mp, CLogicalDML::EDMLOperator edmlop, CTableDescriptor *ptabdesc, - CColRefArray *pdrgpcrSource, CBitSet *pbsModified, + CColRefArray *pdrgpcrSource, + CColRefArray *pdrgpcrOutput, CBitSet *pbsModified, CColRef *pcrAction, CColRef *pcrCtid, CColRef *pcrSegmentId, CColRef *pcrTupleOid, CColRef *pcrTableOid) @@ -45,6 +46,7 @@ CPhysicalDML::CPhysicalDML(CMemoryPool *mp, CLogicalDML::EDMLOperator edmlop, m_edmlop(edmlop), m_ptabdesc(ptabdesc), m_pdrgpcrSource(pdrgpcrSource), + m_pdrgpcrOutput(pdrgpcrOutput), m_pbsModified(pbsModified), m_pcrAction(pcrAction), m_pcrTableOid(pcrTableOid), @@ -53,11 +55,14 @@ CPhysicalDML::CPhysicalDML(CMemoryPool *mp, CLogicalDML::EDMLOperator edmlop, m_pcrTupleOid(pcrTupleOid), m_pds(NULL), m_pos(NULL), - m_pcrsRequiredLocal(NULL) + m_pcrsRequiredLocal(NULL), + m_isCTAS(IMDId::EmdidGPDBCtas == ptabdesc->MDId()->MdidType()), + m_hasTriggers(CXformUtils::FTriggersExist(edmlop, ptabdesc)) { GPOS_ASSERT(CLogicalDML::EdmlSentinel != edmlop); GPOS_ASSERT(NULL != ptabdesc); GPOS_ASSERT(NULL != pdrgpcrSource); + GPOS_ASSERT(NULL != pdrgpcrOutput); GPOS_ASSERT(NULL != pbsModified); GPOS_ASSERT(NULL != pcrAction); GPOS_ASSERT_IMP( @@ -67,6 +72,17 @@ CPhysicalDML::CPhysicalDML(CMemoryPool *mp, CLogicalDML::EDMLOperator edmlop, m_pds = CPhysical::PdsCompute(m_mp, m_ptabdesc, pdrgpcrSource, pcrSegmentId); + if (ptabdesc->ConvertHashToRandom()) + { + // Treating a hash distributed table as random during planning + m_pdsOutput = GPOS_NEW(m_mp) CDistributionSpecRandom(); + } + else + { + m_pdsOutput = CPhysical::PdsCompute(m_mp, ptabdesc, pdrgpcrOutput, + NULL /* gp_segment_id */); + } + if (CDistributionSpec::EdtHashed == m_pds->Edt() && ptabdesc->ConvertHashToRandom()) { @@ -150,9 +166,11 @@ CPhysicalDML::~CPhysicalDML() { m_ptabdesc->Release(); m_pdrgpcrSource->Release(); + m_pdrgpcrOutput->Release(); m_pbsModified->Release(); m_pds->Release(); m_pos->Release(); + m_pdsOutput->Release(); m_pcrsRequiredLocal->Release(); } @@ -251,7 +269,11 @@ CPhysicalDML::PcrsRequired(CMemoryPool *mp, "Required properties can only be computed on the relational child"); CColRefSet *pcrs = GPOS_NEW(mp) CColRefSet(mp, *m_pcrsRequiredLocal); - pcrs->Union(pcrsRequired); + + if (m_isCTAS || m_hasTriggers) + { + pcrs->Union(pcrsRequired); + } return pcrs; } @@ -379,7 +401,25 @@ CPhysicalDML::FProvidesReqdCols(CExpressionHandle &exprhdl, ULONG // ulOptReq ) const { - return FUnaryProvidesReqdCols(exprhdl, pcrsRequired); + if (m_isCTAS) + { + return FUnaryProvidesReqdCols(exprhdl, pcrsRequired); + } + + GPOS_ASSERT(NULL != pcrsRequired); + + CColRefSet *pcrs = GPOS_NEW(m_mp) CColRefSet(m_mp); + pcrs->Include(m_pdrgpcrOutput); + + if (m_hasTriggers) + { + pcrs->Include(m_pdrgpcrSource); + } + + BOOL result = pcrs->ContainsAll(pcrsRequired); + pcrs->Release(); + + return result; } //--------------------------------------------------------------------------- @@ -394,7 +434,13 @@ CDistributionSpec * CPhysicalDML::PdsDerive(CMemoryPool *, //mp, CExpressionHandle &exprhdl) const { - return PdsDerivePassThruOuter(exprhdl); + if (m_isCTAS) + { + return PdsDerivePassThruOuter(exprhdl); + } + + m_pdsOutput->AddRef(); + return m_pdsOutput; } //--------------------------------------------------------------------------- @@ -428,6 +474,8 @@ CPhysicalDML::HashValue() const ulHash = gpos::CombineHashes(ulHash, gpos::HashPtr(m_pcrTableOid)); ulHash = gpos::CombineHashes(ulHash, CUtils::UlHashColArray(m_pdrgpcrSource)); + ulHash = + gpos::CombineHashes(ulHash, CUtils::UlHashColArray(m_pdrgpcrOutput)); if (CLogicalDML::EdmlDelete == m_edmlop || CLogicalDML::EdmlUpdate == m_edmlop) @@ -461,7 +509,8 @@ CPhysicalDML::Matches(COperator *pop) const m_pcrSegmentId == popDML->PcrSegmentId() && m_pcrTupleOid == popDML->PcrTupleOid() && m_ptabdesc->MDId()->Equals(popDML->Ptabdesc()->MDId()) && - m_pdrgpcrSource->Equals(popDML->PdrgpcrSource()); + m_pdrgpcrSource->Equals(popDML->PdrgpcrSource()) && + m_pdrgpcrOutput->Equals(popDML->PdrgpcrOutput()); } return false; @@ -623,6 +672,37 @@ CPhysicalDML::OsPrint(IOstream &os) const m_pcrSegmentId->OsPrint(os); } + os << ", Output Columns: ["; + CUtils::OsPrintDrgPcr(os, m_pdrgpcrOutput); + os << "] Key sets: {"; + + const ULONG ulColumns = m_pdrgpcrOutput->Size(); + const CBitSetArray *pdrgpbsKeys = m_ptabdesc->PdrgpbsKeys(); + for (ULONG ul = 0; ul < pdrgpbsKeys->Size(); ul++) + { + CBitSet *pbs = (*pdrgpbsKeys)[ul]; + if (0 < ul) + { + os << ", "; + } + os << "["; + ULONG ulPrintedKeys = 0; + for (ULONG ulKey = 0; ulKey < ulColumns; ulKey++) + { + if (pbs->Get(ulKey)) + { + if (0 < ulPrintedKeys) + { + os << ","; + } + os << ulKey; + ulPrintedKeys++; + } + } + os << "]"; + } + os << "}"; + return os; } diff --git a/src/backend/gporca/libgpopt/src/translate/CTranslatorDXLToExpr.cpp b/src/backend/gporca/libgpopt/src/translate/CTranslatorDXLToExpr.cpp index e7cf86eab727..3148832b9219 100644 --- a/src/backend/gporca/libgpopt/src/translate/CTranslatorDXLToExpr.cpp +++ b/src/backend/gporca/libgpopt/src/translate/CTranslatorDXLToExpr.cpp @@ -1398,9 +1398,15 @@ CTranslatorDXLToExpr::PexprLogicalInsert(const CDXLNode *dxlnode) CColRefArray *colref_array = CTranslatorDXLToExprUtils::Pdrgpcr(m_mp, m_phmulcr, pdrgpulSourceCols); - return GPOS_NEW(m_mp) CExpression( - m_mp, GPOS_NEW(m_mp) CLogicalInsert(m_mp, ptabdesc, colref_array), - pexprChild); + CLogicalInsert *pexprLogInsert = + GPOS_NEW(m_mp) CLogicalInsert(m_mp, ptabdesc, colref_array); + + // add mapping between the DXL ColId and CColRef to m_phmulcr + ConstructDXLColId2ColRefMapping( + pdxlopInsert->GetDXLTableDescr()->GetColumnDescr(), + pexprLogInsert->PdrgpcrOutput()); + + return GPOS_NEW(m_mp) CExpression(m_mp, pexprLogInsert, pexprChild); } //--------------------------------------------------------------------------- @@ -1447,11 +1453,15 @@ CTranslatorDXLToExpr::PexprLogicalDelete(const CDXLNode *dxlnode) CColRefArray *colref_array = CTranslatorDXLToExprUtils::Pdrgpcr(m_mp, m_phmulcr, pdrgpulCols); - return GPOS_NEW(m_mp) CExpression( - m_mp, - GPOS_NEW(m_mp) CLogicalDelete(m_mp, ptabdesc, colref_array, pcrCtid, - pcrSegmentId, pcrTableOid), - pexprChild); + CLogicalDelete *pexprLogDelete = GPOS_NEW(m_mp) CLogicalDelete( + m_mp, ptabdesc, colref_array, pcrCtid, pcrSegmentId, pcrTableOid); + + // add mapping between the DXL ColId and CColRef to m_phmulcr + ConstructDXLColId2ColRefMapping( + pdxlopDelete->GetDXLTableDescr()->GetColumnDescr(), + pexprLogDelete->PdrgpcrOutput()); + + return GPOS_NEW(m_mp) CExpression(m_mp, pexprLogDelete, pexprChild); } //--------------------------------------------------------------------------- @@ -1509,12 +1519,16 @@ CTranslatorDXLToExpr::PexprLogicalUpdate(const CDXLNode *dxlnode) pcrTupleOid = LookupColRef(m_phmulcr, tuple_oid); } - return GPOS_NEW(m_mp) CExpression( - m_mp, - GPOS_NEW(m_mp) - CLogicalUpdate(m_mp, ptabdesc, pdrgpcrDelete, pdrgpcrInsert, - pcrCtid, pcrSegmentId, pcrTupleOid, pcrTableOid), - pexprChild); + CLogicalUpdate *pexprLogUpdate = GPOS_NEW(m_mp) + CLogicalUpdate(m_mp, ptabdesc, pdrgpcrDelete, pdrgpcrInsert, pcrCtid, + pcrSegmentId, pcrTupleOid, pcrTableOid); + + // add mapping between the DXL ColId and CColRef to m_phmulcr + ConstructDXLColId2ColRefMapping( + pdxlopUpdate->GetDXLTableDescr()->GetColumnDescr(), + pexprLogUpdate->PdrgpcrOutput()); + + return GPOS_NEW(m_mp) CExpression(m_mp, pexprLogUpdate, pexprChild); } //--------------------------------------------------------------------------- diff --git a/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp b/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp index 5e0d2718db6d..2e6a2046c986 100644 --- a/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp +++ b/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp @@ -22,6 +22,7 @@ #include "gpos/common/CHashMap.h" #include "gpopt/base/CCastUtils.h" +#include "gpopt/base/CColRef.h" #include "gpopt/base/CColRefSetIter.h" #include "gpopt/base/CConstraintInterval.h" #include "gpopt/base/CUtils.h" @@ -32,6 +33,7 @@ #include "gpopt/operators/CPhysicalIndexOnlyScan.h" #include "gpopt/operators/CPhysicalMotionRandom.h" #include "gpopt/operators/CPredicateUtils.h" +#include "gpopt/search/CScheduler.h" #include "gpopt/translate/CTranslatorDXLToExpr.h" #include "gpopt/translate/CTranslatorExprToDXLUtils.h" #include "naucrates/base/CDatumBoolGPDB.h" @@ -4511,8 +4513,19 @@ CTranslatorExprToDXL::PdxlnMotion(CExpression *pexprMotion, GPOS_ASSERT(NULL != motion); // construct project list from child project list - GPOS_ASSERT(NULL != child_dxlnode && 1 <= child_dxlnode->Arity()); - CDXLNode *pdxlnProjListChild = (*child_dxlnode)[0]; + CDXLNode *pdxlnProjListChild; + if (COperator::EopPhysicalDML == pexprChild->Pop()->Eopid() && + COperator::EopPhysicalMotionGather == pexprMotion->Pop()->Eopid()) + { + // dml nodes unlike others have output proj list in second child + GPOS_ASSERT(NULL != child_dxlnode && 2 <= child_dxlnode->Arity()); + pdxlnProjListChild = (*child_dxlnode)[1]; + } + else + { + GPOS_ASSERT(NULL != child_dxlnode && 1 <= child_dxlnode->Arity()); + pdxlnProjListChild = (*child_dxlnode)[0]; + } CDXLNode *proj_list_dxlnode = CTranslatorExprToDXLUtils::PdxlnProjListFromChildProjList( @@ -5755,6 +5768,7 @@ CTranslatorExprToDXL::PdxlnDML(CExpression *pexpr, CExpression *pexprChild = (*pexpr)[0]; CTableDescriptor *ptabdesc = popDML->Ptabdesc(); CColRefArray *pdrgpcrSource = popDML->PdrgpcrSource(); + CColRefArray *pdrgpcrOutput = popDML->PdrgpcrOutput(); CColRef *pcrAction = popDML->PcrAction(); GPOS_ASSERT(NULL != pcrAction); @@ -5788,8 +5802,8 @@ CTranslatorExprToDXL::PdxlnDML(CExpression *pexpr, pexprChild, pdrgpcrSource, pdrgpdsBaseTables, pulNonGatherMotions, pfDML, false /*fRemap*/, false /*fRoot*/); - CDXLTableDescr *table_descr = MakeDXLTableDescr( - ptabdesc, NULL /*pdrgpcrOutput*/, NULL /*requiredProperties*/); + CDXLTableDescr *table_descr = + MakeDXLTableDescr(ptabdesc, pdrgpcrOutput, pexpr->Prpp()); ULongPtrArray *pdrgpul = CUtils::Pdrgpul(m_mp, pdrgpcrSource); CDXLDirectDispatchInfo *dxl_direct_dispatch_info = @@ -5799,15 +5813,57 @@ CTranslatorExprToDXL::PdxlnDML(CExpression *pexpr, ctid_colid, segid_colid, preserve_oids, tuple_oid, tableoid_colid, dxl_direct_dispatch_info); + // if dml node has triggers we should also output source columns + if (popDML->HasTriggers()) + { + pdrgpcrOutput->AppendArray(pdrgpcrSource); + } + // project list - CColRefSet *pcrsOutput = pexpr->Prpp()->PcrsRequired(); - CDXLNode *pdxlnPrL = PdxlnProjList(pcrsOutput, pdrgpcrSource); + CDXLNode *pdxlnPrL = PdxlnProjList(NULL, pdrgpcrSource); + + // configure output project list if output was required + CDXLNode *pdxlnPrLOutput; + if (pexpr->Prpp()->PcrsRequired()->Size() > 0) + { + ULongPtrArray *indexes = GPOS_NEW(m_mp) ULongPtrArray(m_mp); + + for (ULONG outputColIndex = 0; outputColIndex < pdrgpcrOutput->Size(); + outputColIndex++) + { + CColRef *colref = (*pdrgpcrOutput)[outputColIndex]; + if (colref->GetUsage(true, true) == CColRef::EUsed) + { + indexes->Append(GPOS_NEW(m_mp) ULONG(outputColIndex)); + } + } + + if (pdrgpcrOutput->Size() == indexes->Size()) + { + pdxlnPrLOutput = PdxlnProjList(NULL, pdrgpcrOutput); + } + else + { + CColRefArray *reducedOutput = + pdrgpcrOutput->CreateReducedArray(indexes); + pdxlnPrLOutput = PdxlnProjList(NULL, reducedOutput); + reducedOutput->Release(); + } + + indexes->Release(); + } + else + { + pdxlnPrLOutput = GPOS_NEW(m_mp) + CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarProjList(m_mp)); + } CDXLNode *pdxlnDML = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopDML); CDXLPhysicalProperties *dxl_properties = GetProperties(pexpr); pdxlnDML->SetProperties(dxl_properties); pdxlnDML->AddChild(pdxlnPrL); + pdxlnDML->AddChild(pdxlnPrLOutput); pdxlnDML->AddChild(child_dxlnode); #ifdef GPOS_DEBUG @@ -7707,7 +7763,7 @@ CDXLNode * CTranslatorExprToDXL::PdxlnProjList(const CColRefSet *pcrsOutput, CColRefArray *colref_array) { - GPOS_ASSERT(NULL != pcrsOutput); + GPOS_ASSERT_IMP(NULL == pcrsOutput, colref_array != NULL); CDXLScalarProjList *pdxlopPrL = GPOS_NEW(m_mp) CDXLScalarProjList(m_mp); CDXLNode *pdxlnPrL = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopPrL); @@ -7726,18 +7782,22 @@ CTranslatorExprToDXL::PdxlnProjList(const CColRefSet *pcrsOutput, pcrs->Include(colref); } - // add the remaining required columns - CColRefSetIter crsi(*pcrsOutput); - while (crsi.Advance()) + if (pcrsOutput != NULL) { - CColRef *colref = crsi.Pcr(); - - if (!pcrs->FMember(colref)) + // add the remaining required columns + CColRefSetIter crsi(*pcrsOutput); + while (crsi.Advance()) { - CDXLNode *pdxlnPrEl = CTranslatorExprToDXLUtils::PdxlnProjElem( - m_mp, m_phmcrdxln, colref); - pdxlnPrL->AddChild(pdxlnPrEl); - pcrs->Include(colref); + CColRef *colref = crsi.Pcr(); + + if (!pcrs->FMember(colref)) + { + CDXLNode *pdxlnPrEl = + CTranslatorExprToDXLUtils::PdxlnProjElem( + m_mp, m_phmcrdxln, colref); + pdxlnPrL->AddChild(pdxlnPrEl); + pcrs->Include(colref); + } } } pcrs->Release(); diff --git a/src/backend/gporca/libgpopt/src/xforms/CXformDelete2DML.cpp b/src/backend/gporca/libgpopt/src/xforms/CXformDelete2DML.cpp index 9c764b6f79e2..d3bb8c8e24d2 100644 --- a/src/backend/gporca/libgpopt/src/xforms/CXformDelete2DML.cpp +++ b/src/backend/gporca/libgpopt/src/xforms/CXformDelete2DML.cpp @@ -80,6 +80,9 @@ CXformDelete2DML::Transform(CXformContext *pxfctxt, CXformResult *pxfres, CColRefArray *colref_array = popDelete->Pdrgpcr(); colref_array->AddRef(); + CColRefArray *pdrgpcrOutput = popDelete->PdrgpcrOutput(); + pdrgpcrOutput->AddRef(); + CColRef *pcrCtid = popDelete->PcrCtid(); CColRef *pcrSegmentId = popDelete->PcrSegmentId(); @@ -93,7 +96,7 @@ CXformDelete2DML::Transform(CXformContext *pxfctxt, CXformResult *pxfres, // create logical DML CExpression *pexprAlt = CXformUtils::PexprLogicalDMLOverProject( mp, pexprChild, CLogicalDML::EdmlDelete, ptabdesc, colref_array, - pcrCtid, pcrSegmentId, pcrTableOid); + pdrgpcrOutput, pcrCtid, pcrSegmentId, pcrTableOid); // add alternative to transformation result pxfres->Add(pexprAlt); diff --git a/src/backend/gporca/libgpopt/src/xforms/CXformImplementDML.cpp b/src/backend/gporca/libgpopt/src/xforms/CXformImplementDML.cpp index beaaa976e40c..4c2d0e88c4c0 100644 --- a/src/backend/gporca/libgpopt/src/xforms/CXformImplementDML.cpp +++ b/src/backend/gporca/libgpopt/src/xforms/CXformImplementDML.cpp @@ -82,6 +82,8 @@ CXformImplementDML::Transform(CXformContext *pxfctxt, CXformResult *pxfres, CColRefArray *pdrgpcrSource = popDML->PdrgpcrSource(); pdrgpcrSource->AddRef(); + CColRefArray *pdrgpcrOutput = popDML->PdrgpcrOutput(); + pdrgpcrOutput->AddRef(); CBitSet *pbsModified = popDML->PbsModified(); pbsModified->AddRef(); @@ -98,9 +100,9 @@ CXformImplementDML::Transform(CXformContext *pxfctxt, CXformResult *pxfres, // create physical DML CExpression *pexprAlt = GPOS_NEW(mp) CExpression( mp, - GPOS_NEW(mp) CPhysicalDML(mp, edmlop, ptabdesc, pdrgpcrSource, - pbsModified, pcrAction, pcrCtid, pcrSegmentId, - pcrTupleOid, pcrTableOid), + GPOS_NEW(mp) CPhysicalDML( + mp, edmlop, ptabdesc, pdrgpcrSource, pdrgpcrOutput, pbsModified, + pcrAction, pcrCtid, pcrSegmentId, pcrTupleOid, pcrTableOid), pexprChild); // add alternative to transformation result pxfres->Add(pexprAlt); diff --git a/src/backend/gporca/libgpopt/src/xforms/CXformInsert2DML.cpp b/src/backend/gporca/libgpopt/src/xforms/CXformInsert2DML.cpp index fa6d733fb66f..bedd7d6cac37 100644 --- a/src/backend/gporca/libgpopt/src/xforms/CXformInsert2DML.cpp +++ b/src/backend/gporca/libgpopt/src/xforms/CXformInsert2DML.cpp @@ -80,6 +80,9 @@ CXformInsert2DML::Transform(CXformContext *pxfctxt, CXformResult *pxfres, CColRefArray *pdrgpcrSource = popInsert->PdrgpcrSource(); pdrgpcrSource->AddRef(); + CColRefArray *pdrgpcrOutput = popInsert->PdrgpcrOutput(); + pdrgpcrOutput->AddRef(); + // child of insert operator CExpression *pexprChild = (*pexpr)[0]; pexprChild->AddRef(); @@ -87,6 +90,7 @@ CXformInsert2DML::Transform(CXformContext *pxfctxt, CXformResult *pxfres, // create logical DML CExpression *pexprAlt = CXformUtils::PexprLogicalDMLOverProject( mp, pexprChild, CLogicalDML::EdmlInsert, ptabdesc, pdrgpcrSource, + pdrgpcrOutput, NULL, //pcrCtid NULL, //pcrSegmentId NULL //pcrTable diff --git a/src/backend/gporca/libgpopt/src/xforms/CXformUpdate2DML.cpp b/src/backend/gporca/libgpopt/src/xforms/CXformUpdate2DML.cpp index 0145cb9e9cc0..3f0d4731da7a 100644 --- a/src/backend/gporca/libgpopt/src/xforms/CXformUpdate2DML.cpp +++ b/src/backend/gporca/libgpopt/src/xforms/CXformUpdate2DML.cpp @@ -84,6 +84,7 @@ CXformUpdate2DML::Transform(CXformContext *pxfctxt, CXformResult *pxfres, CTableDescriptor *ptabdesc = popUpdate->Ptabdesc(); CColRefArray *pdrgpcrDelete = popUpdate->PdrgpcrDelete(); CColRefArray *pdrgpcrInsert = popUpdate->PdrgpcrInsert(); + CColRefArray *pdrgpcrOutput = popUpdate->PdrgpcrOutput(); CColRef *pcrCtid = popUpdate->PcrCtid(); CColRef *pcrSegmentId = popUpdate->PcrSegmentId(); CColRef *pcrTupleOid = popUpdate->PcrTupleOid(); @@ -160,11 +161,13 @@ CXformUpdate2DML::Transform(CXformContext *pxfctxt, CXformResult *pxfres, // create logical DML ptabdesc->AddRef(); pdrgpcrDelete->AddRef(); + pdrgpcrOutput->AddRef(); CExpression *pexprDML = GPOS_NEW(mp) CExpression( mp, - GPOS_NEW(mp) CLogicalDML(mp, CLogicalDML::EdmlUpdate, ptabdesc, - pdrgpcrDelete, pbsModified, pcrAction, pcrCtid, - pcrSegmentId, pcrTupleOid, pcrTableOid), + GPOS_NEW(mp) + CLogicalDML(mp, CLogicalDML::EdmlUpdate, ptabdesc, pdrgpcrDelete, + pdrgpcrOutput, pbsModified, pcrAction, pcrCtid, + pcrSegmentId, pcrTupleOid, pcrTableOid), pexprAssertConstraints); // TODO: - Oct 30, 2012; detect and handle AFTER triggers on update diff --git a/src/backend/gporca/libgpopt/src/xforms/CXformUtils.cpp b/src/backend/gporca/libgpopt/src/xforms/CXformUtils.cpp index 8304bdd9e984..7a0d6ff5cef9 100644 --- a/src/backend/gporca/libgpopt/src/xforms/CXformUtils.cpp +++ b/src/backend/gporca/libgpopt/src/xforms/CXformUtils.cpp @@ -1312,8 +1312,9 @@ CXformUtils::PexprLogicalPartitionSelector(CMemoryPool *mp, CExpression * CXformUtils::PexprLogicalDMLOverProject( CMemoryPool *mp, CExpression *pexprChild, CLogicalDML::EDMLOperator edmlop, - CTableDescriptor *ptabdesc, CColRefArray *colref_array, CColRef *pcrCtid, - CColRef *pcrSegmentId, CColRef *pcrTableOid) + CTableDescriptor *ptabdesc, CColRefArray *colref_array, + CColRefArray *pdrgpcrOutput, CColRef *pcrCtid, CColRef *pcrSegmentId, + CColRef *pcrTableOid) { GPOS_ASSERT(CLogicalDML::EdmlInsert == edmlop || CLogicalDML::EdmlDelete == edmlop); @@ -1353,10 +1354,10 @@ CXformUtils::PexprLogicalDMLOverProject( CExpression *pexprDML = GPOS_NEW(mp) CExpression( mp, - GPOS_NEW(mp) CLogicalDML(mp, edmlop, ptabdesc, colref_array, - GPOS_NEW(mp) CBitSet(mp) /*pbsModified*/, - pcrAction, pcrCtid, pcrSegmentId, - NULL /*pcrTupleOid*/, pcrTableOid), + GPOS_NEW(mp) CLogicalDML( + mp, edmlop, ptabdesc, colref_array, pdrgpcrOutput, + GPOS_NEW(mp) CBitSet(mp) /*pbsModified*/, pcrAction, pcrCtid, + pcrSegmentId, NULL /*pcrTupleOid*/, pcrTableOid), pexprProject); CExpression *pexprOutput = pexprDML; @@ -1407,6 +1408,39 @@ CXformUtils::FTriggersExist(CLogicalDML::EDMLOperator edmlop, return false; } +//--------------------------------------------------------------------------- +// @function: +// CXformUtils::FTriggersExist +// +// @doc: +// Check whether there are any row-level triggers on +// the given table that match the given DML operation +// +//--------------------------------------------------------------------------- +BOOL +CXformUtils::FTriggersExist(CLogicalDML::EDMLOperator edmlop, + CTableDescriptor *ptabdesc) +{ + CMDAccessor *md_accessor = COptCtxt::PoctxtFromTLS()->Pmda(); + const IMDRelation *pmdrel = md_accessor->RetrieveRel(ptabdesc->MDId()); + const ULONG ulTriggers = pmdrel->TriggerCount(); + + for (ULONG ul = 0; ul < ulTriggers; ul++) + { + const IMDTrigger *pmdtrigger = + md_accessor->RetrieveTrigger(pmdrel->TriggerMDidAt(ul)); + if (!pmdtrigger->IsEnabled() || !pmdtrigger->ExecutesOnRowLevel() || + !FTriggerApplies(edmlop, pmdtrigger)) + { + continue; + } + + return true; + } + + return false; +} + //--------------------------------------------------------------------------- // @function: // CXformUtils::FTriggerApplies diff --git a/src/backend/gporca/libnaucrates/include/naucrates/dxl/operators/CDXLTableDescr.h b/src/backend/gporca/libnaucrates/include/naucrates/dxl/operators/CDXLTableDescr.h index f1eb8e3a9a62..c619275f2b1e 100644 --- a/src/backend/gporca/libnaucrates/include/naucrates/dxl/operators/CDXLTableDescr.h +++ b/src/backend/gporca/libnaucrates/include/naucrates/dxl/operators/CDXLTableDescr.h @@ -87,6 +87,13 @@ class CDXLTableDescr : public CRefCount // user id ULONG GetExecuteAsUserId() const; + // get the column descriptor array + const CDXLColDescrArray * + GetColumnDescr() const + { + return m_dxl_column_descr_array; + } + // get the column descriptor at the given position const CDXLColDescr *GetColumnDescrAt(ULONG idx) const; diff --git a/src/backend/gporca/libnaucrates/src/operators/CDXLPhysicalDML.cpp b/src/backend/gporca/libnaucrates/src/operators/CDXLPhysicalDML.cpp index 5190b429eada..edee0f19882d 100644 --- a/src/backend/gporca/libnaucrates/src/operators/CDXLPhysicalDML.cpp +++ b/src/backend/gporca/libnaucrates/src/operators/CDXLPhysicalDML.cpp @@ -172,11 +172,14 @@ CDXLPhysicalDML::SerializeToDXL(CXMLSerializer *xml_serializer, // serialize project list (*node)[0]->SerializeToDXL(xml_serializer); + // serialize project list for returning list + (*node)[1]->SerializeToDXL(xml_serializer); + // serialize table descriptor m_dxl_table_descr->SerializeToDXL(xml_serializer); // serialize physical child - (*node)[1]->SerializeToDXL(xml_serializer); + (*node)[2]->SerializeToDXL(xml_serializer); xml_serializer->CloseElement( CDXLTokens::GetDXLTokenStr(EdxltokenNamespacePrefix), element_name); @@ -194,8 +197,8 @@ CDXLPhysicalDML::SerializeToDXL(CXMLSerializer *xml_serializer, void CDXLPhysicalDML::AssertValid(const CDXLNode *node, BOOL validate_children) const { - GPOS_ASSERT(2 == node->Arity()); - CDXLNode *child_dxlnode = (*node)[1]; + GPOS_ASSERT(3 == node->Arity()); + CDXLNode *child_dxlnode = (*node)[2]; GPOS_ASSERT(EdxloptypePhysical == child_dxlnode->GetOperator()->GetDXLOperatorType()); diff --git a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerPhysicalDML.cpp b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerPhysicalDML.cpp index 65f88d2a09e6..8e034dec9e1f 100644 --- a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerPhysicalDML.cpp +++ b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerPhysicalDML.cpp @@ -145,6 +145,13 @@ CParseHandlerPhysicalDML::StartElement(const XMLCh *const, // element_uri, m_parse_handler_mgr, this); m_parse_handler_mgr->ActivateParseHandler(table_descr_parse_handler); + // parse handler for the returning proj list + CParseHandlerBase *proj_list_output_parse_handler = + CParseHandlerFactory::GetParseHandler( + m_mp, CDXLTokens::XmlstrToken(EdxltokenScalarProjList), + m_parse_handler_mgr, this); + m_parse_handler_mgr->ActivateParseHandler(proj_list_output_parse_handler); + // parse handler for the proj list CParseHandlerBase *proj_list_parse_handler = CParseHandlerFactory::GetParseHandler( @@ -170,6 +177,7 @@ CParseHandlerPhysicalDML::StartElement(const XMLCh *const, // element_uri, this->Append(prop_parse_handler); this->Append(direct_dispatch_parse_handler); this->Append(proj_list_parse_handler); + this->Append(proj_list_output_parse_handler); this->Append(table_descr_parse_handler); this->Append(child_parse_handler); } @@ -199,7 +207,7 @@ CParseHandlerPhysicalDML::EndElement(const XMLCh *const, // element_uri, str->GetBuffer()); } - GPOS_ASSERT(5 == this->Length()); + GPOS_ASSERT(6 == this->Length()); CParseHandlerProperties *prop_parse_handler = dynamic_cast((*this)[0]); @@ -217,15 +225,20 @@ CParseHandlerPhysicalDML::EndElement(const XMLCh *const, // element_uri, GPOS_ASSERT(NULL != proj_list_parse_handler); GPOS_ASSERT(NULL != proj_list_parse_handler->CreateDXLNode()); + CParseHandlerProjList *proj_list_output_parse_handler = + dynamic_cast((*this)[3]); + GPOS_ASSERT(NULL != proj_list_output_parse_handler); + GPOS_ASSERT(NULL != proj_list_output_parse_handler->CreateDXLNode()); + CParseHandlerTableDescr *table_descr_parse_handler = - dynamic_cast((*this)[3]); + dynamic_cast((*this)[4]); GPOS_ASSERT(NULL != table_descr_parse_handler); GPOS_ASSERT(NULL != table_descr_parse_handler->GetDXLTableDescr()); CDXLTableDescr *table_descr = table_descr_parse_handler->GetDXLTableDescr(); table_descr->AddRef(); CParseHandlerPhysicalOp *child_parse_handler = - dynamic_cast((*this)[4]); + dynamic_cast((*this)[5]); GPOS_ASSERT(NULL != child_parse_handler); GPOS_ASSERT(NULL != child_parse_handler->CreateDXLNode()); @@ -242,6 +255,7 @@ CParseHandlerPhysicalDML::EndElement(const XMLCh *const, // element_uri, CParseHandlerUtils::SetProperties(m_dxl_node, prop_parse_handler); AddChildFromParseHandler(proj_list_parse_handler); + AddChildFromParseHandler(proj_list_output_parse_handler); AddChildFromParseHandler(child_parse_handler); #ifdef GPOS_DEBUG diff --git a/src/backend/gporca/server/src/unittest/gpopt/minidump/CDMLTest.cpp b/src/backend/gporca/server/src/unittest/gpopt/minidump/CDMLTest.cpp index 55015c96ae38..f71a57e6b710 100644 --- a/src/backend/gporca/server/src/unittest/gpopt/minidump/CDMLTest.cpp +++ b/src/backend/gporca/server/src/unittest/gpopt/minidump/CDMLTest.cpp @@ -28,6 +28,12 @@ ULONG CDMLTest::m_ulDMLTestCounter = 0; // start from first test // minidump files const CHAR *rgszDMLFileNames[] = { "../data/dxl/minidump/Insert.mdp", + "../data/dxl/minidump/InsertIntoReturning.mdp", + "../data/dxl/minidump/DeleteReturning.mdp", + "../data/dxl/minidump/UpdateReturning.mdp", + "../data/dxl/minidump/InsertInCTE.mdp", + "../data/dxl/minidump/DeleteInCTE.mdp", + "../data/dxl/minidump/UpdateInCTE.mdp", "../data/dxl/minidump/MultipleUpdateWithJoinOnDistCol.mdp", "../data/dxl/minidump/UpdatingNonDistributionColumnFunc.mdp", "../data/dxl/minidump/UpdatingMultipleColumn.mdp", diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index d14dd2013d82..232b797d210a 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -1339,6 +1339,7 @@ _copyDML(const DML *from) COPY_SCALAR_FIELD(tupleoidColIdx); COPY_SCALAR_FIELD(tableoidColIdx); COPY_SCALAR_FIELD(canSetTag); + COPY_NODE_FIELD(returningList); return newnode; } diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 3674f6bfdfb3..365f6c7e5bc8 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -1219,6 +1219,7 @@ _outDML(StringInfo str, const DML *node) WRITE_INT_FIELD(tupleoidColIdx); WRITE_INT_FIELD(tableoidColIdx); WRITE_BOOL_FIELD(canSetTag); + WRITE_NODE_FIELD(returningList); _outPlanInfo(str, (Plan *) node); } diff --git a/src/backend/nodes/readfast.c b/src/backend/nodes/readfast.c index 8dcb032b8694..20f7828e62e3 100644 --- a/src/backend/nodes/readfast.c +++ b/src/backend/nodes/readfast.c @@ -2240,6 +2240,7 @@ _readDML(void) READ_INT_FIELD(tupleoidColIdx); READ_INT_FIELD(tableoidColIdx); READ_BOOL_FIELD(canSetTag); + READ_NODE_FIELD(returningList); readPlanInfo((Plan *)local_node); diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 52c0eda6564d..3a7dc91cc3df 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -248,7 +248,9 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams) } if (result) + { return result; + } } /* diff --git a/src/include/executor/nodeDML.h b/src/include/executor/nodeDML.h index 5ca551e3061d..828e6a9bbc7e 100644 --- a/src/include/executor/nodeDML.h +++ b/src/include/executor/nodeDML.h @@ -17,9 +17,11 @@ #define NODEDML_H extern void ExecDMLExplainEnd(PlanState *planstate, struct StringInfoData *buf); +extern void RemapProjection(ProjectionInfo *projInfo, AttrMap *map); extern TupleTableSlot* ExecDML(DMLState *node); extern DMLState* ExecInitDML(DML *node, EState *estate, int eflags); extern void ExecEndDML(DMLState *node); +extern void ExecSquelchDML(DMLState *node); #endif /* NODEDML_H */ diff --git a/src/include/gpopt/translate/CTranslatorDXLToPlStmt.h b/src/include/gpopt/translate/CTranslatorDXLToPlStmt.h index 778c81d42e86..5c6518e46d1a 100644 --- a/src/include/gpopt/translate/CTranslatorDXLToPlStmt.h +++ b/src/include/gpopt/translate/CTranslatorDXLToPlStmt.h @@ -137,6 +137,12 @@ class CTranslatorDXLToPlStmt // command type CmdType m_cmd_type; + // is dml operation requiring returning + BOOL m_has_returning; + + // has dml operation with returning on replicated table + BOOL m_returning_dml_on_replicated; + // is target table distributed, false when in non DML statements BOOL m_is_tgt_tbl_distributed; diff --git a/src/include/gpopt/translate/CTranslatorQueryToDXL.h b/src/include/gpopt/translate/CTranslatorQueryToDXL.h index 10887c772d04..bf8e803e4243 100644 --- a/src/include/gpopt/translate/CTranslatorQueryToDXL.h +++ b/src/include/gpopt/translate/CTranslatorQueryToDXL.h @@ -211,6 +211,10 @@ class CTranslatorQueryToDXL // translate an Expr into CDXLNode CDXLNode *TranslateExprToDXL(Expr *expr); + // translate an Expr into CDXLNode with specified mapping + CDXLNode *TranslateExprToDXL(Expr *expr, + CMappingVarColId *var_to_colid_map); + // translate the JoinExpr (inside FromExpr) into a CDXLLogicalJoin node CDXLNode *TranslateJoinExprInFromToDXL(JoinExpr *join_expr); @@ -298,6 +302,11 @@ class CTranslatorQueryToDXL CDXLNode *TranslateExprToDXLProject(Expr *expr, const CHAR *alias_name, BOOL insist_new_colids = false); + // translate a target list entry or a join alias entry into a project element using specified mapping + CDXLNode *TranslateExprToDXLProject(Expr *expr, const CHAR *alias_name, + CMappingVarColId *var_to_colid_map, + BOOL insist_new_colids = false); + // translate a CTE into a DXL logical CTE operator CDXLNode *TranslateCTEToDXL(const RangeTblEntry *rte, ULONG rti, ULONG current_query_level); @@ -423,6 +432,11 @@ class CTranslatorQueryToDXL // returns the corresponding ColId for the given system attribute numbber ULONG GetSystemColId(INT attribute_number); + // Wrap dxl node in logical project with return columns from returningList + CDXLNode *ProcessReturningList( + CDXLNode *dml_dxlnode, CDXLTableDescr *table_descr, + IntToUlongMap *output_attno_to_colid_mapping); + public: // dtor ~CTranslatorQueryToDXL(); diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 81700a2a66dd..36552209bdea 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -2835,6 +2835,7 @@ typedef struct DMLState TupleTableSlot *cleanedUpSlot; /* holds 'final' tuple which matches the target relation schema */ AttrNumber segid_attno; /* attribute number of "gp_segment_id" */ bool canSetTag; /* calculate processed tuples */ + TupleTableSlot *resultTupleSlot;/* slot for temporary storing projection result tuples */ } DMLState; /* diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 21e8e8c88b1b..b162e9c11bc4 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -1330,6 +1330,7 @@ typedef struct DML AttrNumber tupleoidColIdx; /* index of tuple oid column into the target list */ AttrNumber tableoidColIdx; /* index of table oid column into the target list */ bool canSetTag; /* calculate processed tuples */ + List *returningList; /* return-values list (of TargetEntry) */ } DML; /* diff --git a/src/test/regress/expected/bfv_dml_optimizer.out b/src/test/regress/expected/bfv_dml_optimizer.out index 5b53b1bce19f..c51ca794bb9e 100644 --- a/src/test/regress/expected/bfv_dml_optimizer.out +++ b/src/test/regress/expected/bfv_dml_optimizer.out @@ -393,18 +393,20 @@ analyze bar; explain delete from foo using bar where foo.a = bar.a returning foo.*; QUERY PLAN ----------------------------------------------------------------------------------------------------------- - Gather Motion 3:1 (slice3; segments: 3) (cost=3.23..6.66 rows=10 width=16) - -> Delete on foo (cost=3.23..6.66 rows=4 width=16) - -> Explicit Redistribute Motion 3:3 (slice2; segments: 3) (cost=3.23..6.66 rows=4 width=16) - -> Hash Join (cost=3.23..6.66 rows=4 width=16) - Hash Cond: (foo.a = bar.a) - -> Redistribute Motion 3:3 (slice1; segments: 3) (cost=0.00..3.30 rows=4 width=14) - Hash Key: foo.a - -> Seq Scan on foo (cost=0.00..3.10 rows=4 width=14) - -> Hash (cost=3.10..3.10 rows=4 width=10) - -> Seq Scan on bar (cost=0.00..3.10 rows=4 width=10) - Optimizer: Postgres query optimizer -(11 rows) + Gather Motion 3:1 (slice3; segments: 3) (cost=0.00..862.18 rows=10 width=8) + -> Result (cost=0.00..862.18 rows=4 width=8) + -> Delete (cost=0.00..862.18 rows=4 width=8) + -> Result (cost=0.00..862.00 rows=4 width=14) + -> Explicit Redistribute Motion 3:3 (slice2; segments: 3) (cost=0.00..862.00 rows=4 width=10) + -> Hash Join (cost=0.00..862.00 rows=4 width=10) + Hash Cond: (foo.a = bar.a) + -> Redistribute Motion 3:3 (slice1; segments: 3) (cost=0.00..431.00 rows=4 width=14) + Hash Key: foo.a + -> Seq Scan on foo (cost=0.00..431.00 rows=4 width=14) + -> Hash (cost=431.00..431.00 rows=4 width=4) + -> Seq Scan on bar (cost=0.00..431.00 rows=4 width=4) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) delete from foo using bar where foo.a = bar.a returning foo.*; a | b diff --git a/src/test/regress/expected/partition_pruning_optimizer.out b/src/test/regress/expected/partition_pruning_optimizer.out index 76b541fca91a..00c2f2d735d2 100644 --- a/src/test/regress/expected/partition_pruning_optimizer.out +++ b/src/test/regress/expected/partition_pruning_optimizer.out @@ -3492,7 +3492,7 @@ explain (verbose, costs off) delete from test_1_prt_extra where j = 2; QUERY PLAN --------------------------------------------------------------------------------------------------------------------- Delete - Output: "outer".ColRef_0009, test_1_prt_extra.ctid + Output: "outer".ColRef_0018, test_1_prt_extra.ctid -> Result Output: test_1_prt_extra.ctid, test_1_prt_extra.gp_segment_id, 0 -> Seq Scan on partition_pruning.test_1_prt_extra @@ -3558,7 +3558,7 @@ HINT: For non-partitioned tables, run analyze (). For QUERY PLAN ------------------------------------------------------------------------------------------------------------------- Delete - Output: "outer".ColRef_0025, test.ctid, test.tableoid + Output: "outer".ColRef_0034, test.ctid, test.tableoid -> Result Output: test.ctid, test.tableoid, test.gp_segment_id, 0 -> Hash Anti Join diff --git a/src/test/regress/expected/qp_dropped_cols_optimizer.out b/src/test/regress/expected/qp_dropped_cols_optimizer.out index 198ca1294e8b..bf6b1b200b3d 100644 --- a/src/test/regress/expected/qp_dropped_cols_optimizer.out +++ b/src/test/regress/expected/qp_dropped_cols_optimizer.out @@ -16290,7 +16290,7 @@ EXPLAIN (COSTS OFF, VERBOSE) INSERT INTO t_part_dropped VALUES (1, 2, 4); QUERY PLAN -------------------------------------------------- Insert - Output: c1, NULL::integer, c3, c4, ColRef_0004 + Output: c1, NULL::integer, c3, c4, ColRef_0014 -> Result Output: c1, c3, c4, 1 -> Result @@ -16307,7 +16307,7 @@ EXPLAIN (COSTS OFF, VERBOSE) INSERT INTO t_part_dropped_1_prt_p2 VALUES (1, 2, 4 QUERY PLAN ---------------------------------------- Insert - Output: c1, c3, c4, ColRef_0004 + Output: c1, c3, c4, ColRef_0014 -> Result Output: c1, c3, c4, 1 -> Result @@ -16415,7 +16415,7 @@ EXPLAIN (COSTS OFF, VERBOSE) DELETE FROM t_part_dropped_1_prt_p2; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Delete - Output: "outer".ColRef_0010, t_part_dropped_1_prt_p2.ctid + Output: "outer".ColRef_0020, t_part_dropped_1_prt_p2.ctid -> Result Output: t_part_dropped_1_prt_p2.ctid, t_part_dropped_1_prt_p2.gp_segment_id, 0 -> Seq Scan on public.t_part_dropped_1_prt_p2 @@ -16442,7 +16442,7 @@ EXPLAIN (COSTS OFF, VERBOSE) INSERT INTO t_part VALUES (1, 5, 2, 5); QUERY PLAN ---------------------------------------- Insert - Output: c1, c2, c3, c4, ColRef_0005 + Output: c1, c2, c3, c4, ColRef_0016 -> Result Output: c1, c2, c3, c4, 1 -> Result @@ -16459,7 +16459,7 @@ EXPLAIN (COSTS OFF, VERBOSE) INSERT INTO t_part_1_prt_p2 VALUES (1, 5, 2, 5); QUERY PLAN ------------------------------------------------------ Insert - Output: c1, NULL::integer, c2, c3, c4, ColRef_0005 + Output: c1, NULL::integer, c2, c3, c4, ColRef_0016 -> Result Output: c1, c2, c3, c4, 1 -> Result @@ -16529,7 +16529,7 @@ EXPLAIN (COSTS OFF, VERBOSE) DELETE FROM t_part_1_prt_p2; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------- Delete - Output: "outer".ColRef_0011, t_part_1_prt_p2.ctid + Output: "outer".ColRef_0022, t_part_1_prt_p2.ctid -> Result Output: t_part_1_prt_p2.ctid, t_part_1_prt_p2.gp_segment_id, 0 -> Seq Scan on public.t_part_1_prt_p2 diff --git a/src/test/regress/expected/returning_gp.out b/src/test/regress/expected/returning_gp.out index e10c1b6998e1..84737d1b1221 100644 --- a/src/test/regress/expected/returning_gp.out +++ b/src/test/regress/expected/returning_gp.out @@ -64,9 +64,13 @@ update returning_parttab set partkey = 19 where partkey = 13 returning *; 2 | 19 | multi2 3 (1 row) --- update that moves the tuple across partitions (not supported) +-- update that moves the tuple across partitions update returning_parttab set partkey = 18 where partkey = 4 returning *; -ERROR: moving tuple from partition "returning_parttab_1_prt_1" to partition "returning_parttab_1_prt_newpart" not supported (seg0 slice1 127.0.0.1:40000 pid=5753) + distkey | partkey | t +---------+---------+--------- + 1 | 18 | multi 4 +(1 row) + -- delete delete from returning_parttab where partkey = 14 returning *; distkey | partkey | t @@ -81,10 +85,10 @@ select * from returning_parttab; 1 | 1 | single insert 1 | 1 | multi 1 1 | 2 | multi 2 - 1 | 4 | multi 4 1 | 5 | multi 5 1 | 9 | multi 3 1 | 10 | single2 insert + 1 | 18 | multi 4 2 | 11 | multi2 1 2 | 12 | multi2 2 2 | 15 | multi2 5 diff --git a/src/test/regress/expected/subselect_gp_optimizer.out b/src/test/regress/expected/subselect_gp_optimizer.out index 3a37f5a98a9c..9e7922f71c76 100644 --- a/src/test/regress/expected/subselect_gp_optimizer.out +++ b/src/test/regress/expected/subselect_gp_optimizer.out @@ -3730,19 +3730,26 @@ select i from t2 where 0 = (select i from cte); QUERY PLAN -------------------------------------------------------------------------- - Gather Motion 3:1 (slice3; segments: 3) + Nested Loop + Join Filter: true -> Result - One-Time Filter: (0 = $1) - InitPlan 1 (returns $1) (slice4) - -> Gather Motion 3:1 (slice2; segments: 3) - -> Update on t1 - -> Redistribute Motion 3:3 (slice1; segments: 3) - Hash Key: "outer".i - -> Split - -> Seq Scan on t1 - -> Seq Scan on t2 - Optimizer: Postgres query optimizer -(12 rows) + Filter: (0 = t1.i) + -> Assert + Assert Cond: ((row_number() OVER (?)) = 1) + -> WindowAgg + -> Gather Motion 3:1 (slice3; segments: 3) + -> Result + -> Update + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: t1.i + -> Split + -> Result + -> Seq Scan on t1 + -> Materialize + -> Gather Motion 3:1 (slice1; segments: 3) + -> Seq Scan on t2 + Optimizer: Pivotal Optimizer (GPORCA) +(19 rows) with cte as (update t1 set i = 0 @@ -3784,25 +3791,26 @@ where t2.i in (select i from cte where t2.i = cte.i and cte.i > 0) order by i; QUERY PLAN -------------------------------------------------------------------------------------------------- - Gather Motion 3:1 (slice3; segments: 3) + Gather Motion 3:1 (slice2; segments: 3) Merge Key: t2.i -> Sort Sort Key: t2.i - -> Seq Scan on t2 - Filter: (SubPlan 1) - SubPlan 1 (slice3; segments: 3) - -> Result - Filter: (t2.i = cte.i) - -> Materialize - -> Broadcast Motion 3:3 (slice2; segments: 3) - -> Subquery Scan on cte - Filter: (cte.i > 0) - -> Insert on t1 - -> Redistribute Motion 1:3 (slice1; segments: 1) - Hash Key: i.i - -> Function Scan on generate_series i - Optimizer: Postgres query optimizer -(18 rows) + -> Hash Semi Join + Hash Cond: ((t2.i = generate_series.generate_series) AND (t2.i = generate_series.generate_series)) + -> Seq Scan on t2 + Filter: (i > 0) + -> Hash + -> Redistribute Motion 3:3 (slice1; segments: 3) + Hash Key: generate_series.generate_series + -> Result + Filter: (generate_series.generate_series > 0) + -> Result + -> Insert + -> Result + -> Result + -> Function Scan on generate_series + Optimizer: Pivotal Optimizer (GPORCA) +(19 rows) with cte as (insert into t1 @@ -3839,24 +3847,27 @@ where t_repl.i in (select i from cte where t_repl.i = cte.i and cte.i > 0) order by i; QUERY PLAN -------------------------------------------------------------------------------------------------- - Gather Motion 1:1 (slice3; segments: 1) + Gather Motion 3:1 (slice2; segments: 3) + Merge Key: t_repl.i -> Sort Sort Key: t_repl.i - -> Seq Scan on t_repl - Filter: (SubPlan 1) - SubPlan 1 (slice3; segments: 1) - -> Result - Filter: (t_repl.i = cte.i) - -> Materialize - -> Gather Motion 3:1 (slice2; segments: 3) - -> Subquery Scan on cte - Filter: (cte.i > 0) - -> Insert on t1 - -> Redistribute Motion 1:3 (slice1; segments: 1) - Hash Key: i.i - -> Function Scan on generate_series i - Optimizer: Postgres query optimizer -(17 rows) + -> Hash Semi Join + Hash Cond: ((t_repl.i = generate_series.generate_series) AND (t_repl.i = generate_series.generate_series)) + -> Result + -> Seq Scan on t_repl + Filter: (i > 0) + -> Hash + -> Redistribute Motion 3:3 (slice1; segments: 3) + Hash Key: generate_series.generate_series, generate_series.generate_series + -> Result + Filter: (generate_series.generate_series > 0) + -> Result + -> Insert + -> Result + -> Result + -> Function Scan on generate_series + Optimizer: Pivotal Optimizer (GPORCA) +(20 rows) with cte as (insert into t1 @@ -3893,30 +3904,29 @@ where t2.i in (select i from cte join t3 using (i) where t3.j = t2.i) order by i; QUERY PLAN -------------------------------------------------------------------------------------------------- - Gather Motion 3:1 (slice4; segments: 3) + Gather Motion 3:1 (slice3; segments: 3) Merge Key: t2.i -> Sort Sort Key: t2.i - -> Seq Scan on t2 - Filter: (SubPlan 1) - SubPlan 1 (slice4; segments: 3) - -> Hash Join - Hash Cond: (t1.i = t3.i) - -> Result - -> Materialize - -> Broadcast Motion 3:3 (slice2; segments: 3) - -> Insert on t1 - -> Redistribute Motion 1:3 (slice1; segments: 1) - Hash Key: i.i - -> Function Scan on generate_series i - -> Hash - -> Result - Filter: (t3.j = t2.i) - -> Materialize - -> Broadcast Motion 3:3 (slice3; segments: 3) - -> Seq Scan on t3 - Optimizer: Postgres query optimizer -(23 rows) + -> Hash Semi Join + Hash Cond: ((t2.i = t3.j) AND (t2.i = generate_series.generate_series)) + -> Seq Scan on t2 + Filter: (NOT (i IS NULL)) + -> Hash + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: generate_series.generate_series + -> Hash Join + Hash Cond: (generate_series.generate_series = t3.i) + -> Result + -> Insert + -> Result + -> Result + -> Function Scan on generate_series + -> Hash + -> Broadcast Motion 3:3 (slice1; segments: 3) + -> Seq Scan on t3 + Optimizer: Pivotal Optimizer (GPORCA) +(22 rows) with cte as (insert into t1 @@ -3947,29 +3957,30 @@ where t_repl.i in (select i from cte join t3 using (i) where t3.j = t_repl.i) order by i; QUERY PLAN -------------------------------------------------------------------------------------------------- - Gather Motion 1:1 (slice4; segments: 1) + Gather Motion 3:1 (slice3; segments: 3) + Merge Key: t_repl.i -> Sort Sort Key: t_repl.i - -> Seq Scan on t_repl - Filter: (SubPlan 1) - SubPlan 1 (slice4; segments: 3) - -> Hash Join - Hash Cond: (t1.i = t3.i) - -> Result - -> Materialize - -> Gather Motion 3:1 (slice2; segments: 3) - -> Insert on t1 - -> Redistribute Motion 1:3 (slice1; segments: 1) - Hash Key: i.i - -> Function Scan on generate_series i - -> Hash - -> Result - Filter: (t3.j = t_repl.i) - -> Materialize - -> Gather Motion 3:1 (slice3; segments: 3) - -> Seq Scan on t3 - Optimizer: Postgres query optimizer -(22 rows) + -> Hash Semi Join + Hash Cond: ((t_repl.i = t3.j) AND (t_repl.i = generate_series.generate_series)) + -> Result + -> Seq Scan on t_repl + Filter: (NOT (i IS NULL)) + -> Hash + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: t3.j, generate_series.generate_series + -> Hash Join + Hash Cond: (generate_series.generate_series = t3.i) + -> Result + -> Insert + -> Result + -> Result + -> Function Scan on generate_series + -> Hash + -> Broadcast Motion 3:3 (slice1; segments: 3) + -> Seq Scan on t3 + Optimizer: Pivotal Optimizer (GPORCA) +(23 rows) with cte as (insert into t1 diff --git a/src/test/regress/expected/updatable_views_optimizer.out b/src/test/regress/expected/updatable_views_optimizer.out index 8e10f46593d8..ae34c850cd95 100644 --- a/src/test/regress/expected/updatable_views_optimizer.out +++ b/src/test/regress/expected/updatable_views_optimizer.out @@ -913,12 +913,15 @@ UPDATE rw_view1 v SET bb='Updated row 2' WHERE rw_view1_aa(v)=2 RETURNING rw_view1_aa(v), v.bb; QUERY PLAN ------------------------------------------ - Gather Motion 1:1 (slice1; segments: 1) - -> Update on base_tbl - -> Seq Scan on base_tbl - Filter: (a = 2) - Optimizer: Postgres query optimizer -(5 rows) + Gather Motion 3:1 (slice1; segments: 3) + -> Result + -> Update + -> Split + -> Result + -> Index Scan using base_tbl_pkey on base_tbl + Index Cond: (a = 2) + Optimizer: Pivotal Optimizer (GPORCA) +(8 rows) DROP TABLE base_tbl CASCADE; NOTICE: drop cascades to 2 other objects @@ -1113,13 +1116,18 @@ EXPLAIN (verbose, costs off) UPDATE rw_view1 SET b = b + 1 RETURNING *; ------------------------------------------------------------------------------------------- Gather Motion 3:1 (slice1; segments: 3) Output: base_tbl.a, base_tbl.b - -> Update on public.base_tbl + -> Result Output: base_tbl.a, base_tbl.b - -> Seq Scan on public.base_tbl - Output: base_tbl.a, (base_tbl.b + 1), base_tbl.ctid, base_tbl.gp_segment_id - Optimizer: Postgres query optimizer - Settings: optimizer=off -(8 rows) + -> Update + Output: base_tbl.a, base_tbl.b, (DMLAction), base_tbl.ctid + -> Split + Output: base_tbl.a, base_tbl.b, base_tbl.ctid, base_tbl.gp_segment_id, DMLAction + -> Result + Output: base_tbl.a, base_tbl.b, (base_tbl.b + 1), base_tbl.ctid, base_tbl.gp_segment_id + -> Seq Scan on public.base_tbl + Output: base_tbl.a, base_tbl.b, base_tbl.ctid, base_tbl.gp_segment_id + Optimizer: Pivotal Optimizer (GPORCA) +(14 rows) UPDATE rw_view1 SET b = b + 1 RETURNING *; a | b @@ -2054,11 +2062,11 @@ EXPLAIN (costs off) INSERT INTO rw_view1 VALUES (2, 'New row 2'); Hash Key: "outer".id -> Result -> GroupAggregate - Group Key: "outer"., "outer".ColRef_0015 + Group Key: "outer"., "outer".ColRef_0025 -> Sort - Sort Key: "outer"., "outer".ColRef_0015 + Sort Key: "outer"., "outer".ColRef_0025 -> Result - Filter: (CASE WHEN (NOT ("outer".ColRef_0015 IS NULL)) THEN true ELSE false END IS NOT TRUE) + Filter: (CASE WHEN (NOT ("outer".ColRef_0025 IS NULL)) THEN true ELSE false END IS NOT TRUE) -> Nested Loop Left Join Join Filter: true -> Result diff --git a/src/test/regress/expected/with_clause_optimizer.out b/src/test/regress/expected/with_clause_optimizer.out index 963c85316c14..57861ead4adb 100644 --- a/src/test/regress/expected/with_clause_optimizer.out +++ b/src/test/regress/expected/with_clause_optimizer.out @@ -3062,15 +3062,16 @@ order by 1; Merge Key: t1.i -> Sort Sort Key: t1.i - -> Seq Scan on t1 - Filter: (hashed SubPlan 1) - SubPlan 1 (slice1; segments: 3) - -> Materialize - -> Subquery Scan on cte - -> Insert on with_dml_dr - -> Function Scan on generate_series i - Optimizer: Postgres query optimizer -(12 rows) + -> Hash Semi Join + Hash Cond: (t1.i = generate_series.generate_series) + -> Seq Scan on t1 + -> Hash + -> Result + -> Insert + -> Result + -> Function Scan on generate_series + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) with cte as ( insert into with_dml_dr @@ -3103,17 +3104,20 @@ order by 1; Merge Key: t1.i -> Sort Sort Key: t1.i - -> Seq Scan on t1 - Filter: (SubPlan 1) - SubPlan 1 (slice1; segments: 3) - -> Result - Filter: (cte.i = t1.j) - -> Materialize - -> Subquery Scan on cte - -> Insert on with_dml_dr - -> Function Scan on generate_series i - Optimizer: Postgres query optimizer -(14 rows) + -> Hash Join + Hash Cond: ((generate_series.generate_series = t1.j) AND (generate_series.generate_series = t1.i)) + -> Result + -> HashAggregate + Group Key: generate_series.generate_series + -> Result + -> Insert + -> Result + -> Function Scan on generate_series + -> Hash + -> Seq Scan on t1 + Filter: (NOT (j IS NULL)) + Optimizer: Pivotal Optimizer (GPORCA) +(17 rows) with cte as ( insert into with_dml_dr @@ -3202,15 +3206,17 @@ order by 1; QUERY PLAN --------------------------------------------------- Explicit Gather Motion 3:1 (slice1; segments: 3) - Merge Key: with_dml_dr.i + Merge Key: "outer".i -> Sort - Sort Key: with_dml_dr.i + Sort Key: "outer".i -> Append - -> Insert on with_dml_dr - -> Result + -> Result + -> Insert + -> Result + -> Result -> Seq Scan on t_repl - Optimizer: Postgres query optimizer -(9 rows) + Optimizer: Pivotal Optimizer (GPORCA) +(11 rows) with cte as ( insert into with_dml_dr diff --git a/src/test/regress/sql/returning_gp.sql b/src/test/regress/sql/returning_gp.sql index 8ca158a520e7..8dca66969d82 100644 --- a/src/test/regress/sql/returning_gp.sql +++ b/src/test/regress/sql/returning_gp.sql @@ -31,7 +31,7 @@ returning distkey, partkey, t; update returning_parttab set partkey = 9 where partkey = 3 returning *; update returning_parttab set partkey = 19 where partkey = 13 returning *; --- update that moves the tuple across partitions (not supported) +-- update that moves the tuple across partitions update returning_parttab set partkey = 18 where partkey = 4 returning *; -- delete From 4372190e39f7f768fff4854f15e1a55a0b018aae Mon Sep 17 00:00:00 2001 From: kotb Date: Mon, 10 Mar 2025 22:28:15 +0300 Subject: [PATCH 02/74] adapt leftover regress test to orca --- .../expected/explain_analyze_optimizer.out | 37 ++-- .../expected/subselect_gp_optimizer.out | 37 ++-- .../regress/expected/update_gp_optimizer.out | 23 ++- .../expected/with_clause_optimizer.out | 176 ++++++++++-------- 4 files changed, 157 insertions(+), 116 deletions(-) diff --git a/src/test/regress/expected/explain_analyze_optimizer.out b/src/test/regress/expected/explain_analyze_optimizer.out index 1f99de7109d8..0b78aa85c80b 100644 --- a/src/test/regress/expected/explain_analyze_optimizer.out +++ b/src/test/regress/expected/explain_analyze_optimizer.out @@ -108,17 +108,17 @@ WITH cte AS ( ) SELECT * FROM cte; QUERY PLAN ------------------------------------------------------------------------------------ - Gather Motion 3:1 (slice2; segments: 3) (actual rows=5 loops=1) - -> Insert on with_dml (actual rows=3 loops=1) - -> Redistribute Motion 1:3 (slice1; segments: 1) (actual rows=3 loops=1) - Hash Key: i.i - -> Function Scan on generate_series i (actual rows=5 loops=1) + Gather Motion 3:1 (slice1; segments: 3) (actual rows=5 loops=1) + -> Result (actual rows=3 loops=1) + -> Insert (actual rows=3 loops=1) + -> Result (actual rows=3 loops=1) + -> Result (actual rows=5 loops=1) + -> Function Scan on generate_series (actual rows=5 loops=1) Planning time: 20.649 ms (slice0) Executor memory: 59K bytes. - (slice1) Executor memory: 58K bytes (seg1). Work_mem: 17K bytes max. - (slice2) Executor memory: 42K bytes avg x 3 workers, 42K bytes max (seg0). + (slice1) Executor memory: 90K bytes avg x 3 workers, 90K bytes max (seg0). Work_mem: 17K bytes max. Memory used: 128000kB - Optimizer: Postgres query optimizer + Optimizer: Pivotal Optimizer (GPORCA) Execution time: 21.314 ms (12 rows) @@ -130,15 +130,18 @@ WITH cte AS ( QUERY PLAN --------------------------------------------------------------------------------- Gather Motion 3:1 (slice1; segments: 3) (actual rows=5 loops=1) - -> Update on with_dml (actual rows=3 loops=1) - -> Seq Scan on with_dml (actual rows=3 loops=1) + -> Result (actual rows=3 loops=1) + -> Update (actual rows=3 loops=1) + -> Split (actual rows=6 loops=1) + -> Result (actual rows=3 loops=1) + -> Seq Scan on with_dml (actual rows=3 loops=1) Planning time: 13.933 ms (slice0) Executor memory: 59K bytes. (slice1) Executor memory: 58K bytes avg x 3 workers, 58K bytes max (seg0). Memory used: 128000kB - Optimizer: Postgres query optimizer + Optimizer: Pivotal Optimizer (GPORCA) Execution time: 4.397 ms -(9 rows) +(12 rows) EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF) WITH cte AS ( @@ -148,14 +151,16 @@ WITH cte AS ( QUERY PLAN --------------------------------------------------------------------------------- Gather Motion 3:1 (slice1; segments: 3) (actual rows=5 loops=1) - -> Delete on with_dml (actual rows=3 loops=1) - -> Seq Scan on with_dml (actual rows=3 loops=1) - Filter: (i > 0) + -> Result (actual rows=3 loops=1) + -> Delete (actual rows=3 loops=1) + -> Result (actual rows=3 loops=1) + -> Seq Scan on with_dml (actual rows=3 loops=1) + Filter: (i > 0) Planning time: 8.322 ms (slice0) Executor memory: 59K bytes. (slice1) Executor memory: 57K bytes avg x 3 workers, 57K bytes max (seg0). Memory used: 128000kB - Optimizer: Postgres query optimizer + Optimizer: Pivotal Optimizer (GPORCA) Execution time: 9.462 ms (10 rows) diff --git a/src/test/regress/expected/subselect_gp_optimizer.out b/src/test/regress/expected/subselect_gp_optimizer.out index 9e7922f71c76..7ed0c86560bc 100644 --- a/src/test/regress/expected/subselect_gp_optimizer.out +++ b/src/test/regress/expected/subselect_gp_optimizer.out @@ -3670,24 +3670,25 @@ where exists (select i from cte); QUERY PLAN -------------------------------------------------------------------------------------------------- Gather Motion 3:1 (slice4; segments: 3) - -> Result - One-Time Filter: $1 - InitPlan 1 (returns $1) (slice5) - -> Limit - -> Gather Motion 3:1 (slice3; segments: 3) - -> Limit - -> Delete on t1 - -> Explicit Redistribute Motion 3:3 (slice2; segments: 3) - -> Hash Join - Hash Cond: (t1.i = t2_1.i) - -> Redistribute Motion 3:3 (slice1; segments: 3) - Hash Key: t1.i - -> Seq Scan on t1 - -> Hash - -> Seq Scan on t2 t2_1 - -> Seq Scan on t2 - Optimizer: Postgres query optimizer -(18 rows) + -> Nested Loop Semi Join + Join Filter: true + -> Seq Scan on t2 t2_1 + -> Materialize + -> Broadcast Motion 1:3 (slice3) + -> Limit + -> Gather Motion 3:1 (slice2; segments: 3) + -> Result + -> Result + -> Delete + -> Result + -> Hash Join + Hash Cond: (t1.i = t2.i) + -> Seq Scan on t1 + -> Hash + -> Broadcast Motion 3:3 (slice1; segments: 3) + -> Seq Scan on t2 + Optimizer: Pivotal Optimizer (GPORCA) +(19 rows) with cte as (delete from t1 diff --git a/src/test/regress/expected/update_gp_optimizer.out b/src/test/regress/expected/update_gp_optimizer.out index bee8de0f2b42..6ec50731a569 100644 --- a/src/test/regress/expected/update_gp_optimizer.out +++ b/src/test/regress/expected/update_gp_optimizer.out @@ -259,18 +259,23 @@ SELECT count(*) AS a FROM t_strewn JOIN cte USING (i); QUERY PLAN --------------------------------------------------------------------------- Aggregate - -> Gather Motion 3:1 (slice2; segments: 3) + -> Gather Motion 3:1 (slice3; segments: 3) -> Aggregate -> Hash Join - Hash Cond: (t_strewn.i = cte.i) - -> Seq Scan on t_strewn + Hash Cond: (t_strewn.i = "outer".ColRef_0049) + -> Redistribute Motion 3:3 (slice1; segments: 3) + Hash Key: t_strewn.i + -> Seq Scan on t_strewn -> Hash - -> Broadcast Motion 3:3 (slice1; segments: 3) - -> Subquery Scan on cte - -> Delete on t1 - -> Seq Scan on t1 - Optimizer: Postgres query optimizer -(12 rows) + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: "outer".ColRef_0049 + -> Result + -> Result + -> Delete + -> Result + -> Seq Scan on t1 + Optimizer: Pivotal Optimizer (GPORCA) +(17 rows) WITH CTE AS (DELETE FROM t1 RETURNING *) SELECT count(*) AS a FROM t_strewn JOIN cte USING (i); diff --git a/src/test/regress/expected/with_clause_optimizer.out b/src/test/regress/expected/with_clause_optimizer.out index 57861ead4adb..0817089a9db8 100644 --- a/src/test/regress/expected/with_clause_optimizer.out +++ b/src/test/regress/expected/with_clause_optimizer.out @@ -2304,16 +2304,17 @@ with cte as ( QUERY PLAN ------------------------------------------------------------------------------ Aggregate - -> Gather Motion 3:1 (slice2; segments: 3) + -> Gather Motion 3:1 (slice1; segments: 3) -> Aggregate - -> Subquery Scan on cte - Filter: (cte.i > 2) - -> Insert on with_dml - -> Redistribute Motion 1:3 (slice1; segments: 1) - Hash Key: i.i - -> Function Scan on generate_series i - Optimizer: Postgres query optimizer -(10 rows) + -> Result + Filter: (generate_series.generate_series > 2) + -> Result + -> Insert + -> Result + -> Result + -> Function Scan on generate_series + Optimizer: Pivotal Optimizer (GPORCA) +(11 rows) with cte as ( insert into with_dml select i, i * 100 from generate_series(1,5) i @@ -2407,12 +2408,15 @@ with cte as ( ) select count(*) from cte; QUERY PLAN ------------------------------------------------------ - Explicit Gather Motion 3:1 (slice1; segments: 3) - -> Aggregate - -> Insert on with_dml_dr - -> Function Scan on generate_series i - Optimizer: Postgres query optimizer -(5 rows) + Aggregate + -> Explicit Gather Motion 3:1 (slice1; segments: 3) + -> Aggregate + -> Result + -> Insert + -> Result + -> Function Scan on generate_series + Optimizer: Pivotal Optimizer (GPORCA) +(8 rows) with cte as ( insert into with_dml_dr @@ -2485,13 +2489,15 @@ with cte as ( QUERY PLAN ------------------------------------------------------ Explicit Gather Motion 3:1 (slice1; segments: 3) - Merge Key: with_dml_dr.i + Merge Key: generate_series.generate_series -> Sort - Sort Key: with_dml_dr.i - -> Insert on with_dml_dr - -> Function Scan on generate_series i - Optimizer: Postgres query optimizer -(7 rows) + Sort Key: generate_series.generate_series + -> Result + -> Insert + -> Result + -> Function Scan on generate_series + Optimizer: Pivotal Optimizer (GPORCA) +(9 rows) with cte as ( insert into with_dml_dr @@ -2525,16 +2531,19 @@ with cte as ( ) select count(*) from cte join t_repl using (i); QUERY PLAN ------------------------------------------------------------ - Explicit Gather Motion 3:1 (slice1; segments: 3) - -> Aggregate - -> Hash Join - Hash Cond: (with_dml_dr.i = t_repl.i) - -> Insert on with_dml_dr - -> Function Scan on generate_series i - -> Hash - -> Seq Scan on t_repl - Optimizer: Postgres query optimizer -(9 rows) + Aggregate + -> Explicit Gather Motion 3:1 (slice1; segments: 3) + -> Aggregate + -> Hash Join + Hash Cond: (generate_series.generate_series = t_repl.i) + -> Result + -> Insert + -> Result + -> Function Scan on generate_series + -> Hash + -> Seq Scan on t_repl + Optimizer: Pivotal Optimizer (GPORCA) +(12 rows) with cte as ( insert into with_dml_dr @@ -2702,16 +2711,21 @@ select count(*) from cte join (select a from generate_series(1,5) a) x on cte.i = x.a; QUERY PLAN ------------------------------------------------------------ - Explicit Gather Motion 3:1 (slice1; segments: 3) - -> Aggregate - -> Hash Join - Hash Cond: (with_dml_dr.i = a.a) - -> Insert on with_dml_dr - -> Function Scan on generate_series i - -> Hash - -> Function Scan on generate_series a - Optimizer: Postgres query optimizer -(9 rows) + Aggregate + -> Gather Motion 3:1 (slice1; segments: 3) + -> Aggregate + -> Hash Join + Hash Cond: (generate_series.generate_series = generate_series_1.generate_series) + -> Result + One-Time Filter: (gp_execution_segment() = 1) + -> Function Scan on generate_series + -> Hash + -> Result + -> Insert + -> Result + -> Function Scan on generate_series generate_series_1 + Optimizer: Pivotal Optimizer (GPORCA) +(14 rows) with cte as ( insert into with_dml_dr @@ -2748,13 +2762,16 @@ with cte as ( -> Gather Motion 3:1 (slice1; segments: 3) -> Aggregate -> Hash Join - Hash Cond: (with_dml_dr.i = t_hashed.i) - -> Insert on with_dml_dr - -> Function Scan on generate_series i + Hash Cond: (generate_series.generate_series = t_hashed.i) + -> Result + -> Result + -> Insert + -> Result + -> Function Scan on generate_series -> Hash -> Seq Scan on t_hashed - Optimizer: Postgres query optimizer -(10 rows) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) with cte as ( insert into with_dml_dr @@ -2775,16 +2792,19 @@ with cte as ( QUERY PLAN --------------------------------------------------------------- Aggregate - -> Hash Left Join - Hash Cond: (with_dml_dr.i = t_hashed.i) - -> Explicit Gather Motion 3:1 (slice1; segments: 3) - -> Insert on with_dml_dr - -> Function Scan on generate_series i - -> Hash - -> Gather Motion 3:1 (slice2; segments: 3) - -> Seq Scan on t_hashed - Optimizer: Postgres query optimizer -(10 rows) + -> Gather Motion 3:1 (slice1; segments: 3) + -> Aggregate + -> Hash Left Join + Hash Cond: (generate_series.generate_series = t_hashed.i) + -> Result + -> Result + -> Insert + -> Result + -> Function Scan on generate_series + -> Hash + -> Seq Scan on t_hashed + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) with cte as ( insert into with_dml_dr @@ -2805,16 +2825,21 @@ with cte as ( QUERY PLAN ------------------------------------------------------------------ Aggregate - -> Gather Motion 3:1 (slice1; segments: 3) + -> Gather Motion 3:1 (slice2; segments: 3) -> Aggregate -> Hash Join - Hash Cond: (with_dml_dr.i = t_strewn.i) - -> Insert on with_dml_dr - -> Function Scan on generate_series i + Hash Cond: (generate_series.generate_series = t_strewn.i) + -> Result + -> Result + -> Insert + -> Result + -> Function Scan on generate_series -> Hash - -> Seq Scan on t_strewn - Optimizer: Postgres query optimizer -(10 rows) + -> Redistribute Motion 3:3 (slice1; segments: 3) + Hash Key: t_strewn.i + -> Seq Scan on t_strewn + Optimizer: Pivotal Optimizer (GPORCA) +(15 rows) with cte as ( insert into with_dml_dr @@ -2835,16 +2860,21 @@ with cte as ( QUERY PLAN --------------------------------------------------------------- Aggregate - -> Hash Left Join - Hash Cond: (with_dml_dr.i = t_strewn.i) - -> Explicit Gather Motion 3:1 (slice1; segments: 3) - -> Insert on with_dml_dr - -> Function Scan on generate_series i - -> Hash - -> Gather Motion 3:1 (slice2; segments: 3) - -> Seq Scan on t_strewn - Optimizer: Postgres query optimizer -(10 rows) + -> Gather Motion 3:1 (slice2; segments: 3) + -> Aggregate + -> Hash Left Join + Hash Cond: (generate_series.generate_series = t_strewn.i) + -> Result + -> Result + -> Insert + -> Result + -> Function Scan on generate_series + -> Hash + -> Redistribute Motion 3:3 (slice1; segments: 3) + Hash Key: t_strewn.i + -> Seq Scan on t_strewn + Optimizer: Pivotal Optimizer (GPORCA) +(15 rows) with cte as ( insert into with_dml_dr From ebac187dc89f97ff86d436f976fe97c717329c48 Mon Sep 17 00:00:00 2001 From: kotb Date: Mon, 10 Mar 2025 23:56:05 +0300 Subject: [PATCH 03/74] change expectance in regress with multiple DML CTE references --- .../expected/with_clause_optimizer.out | 75 +++++++++++++++++-- 1 file changed, 70 insertions(+), 5 deletions(-) diff --git a/src/test/regress/expected/with_clause_optimizer.out b/src/test/regress/expected/with_clause_optimizer.out index 0817089a9db8..762184cd272b 100644 --- a/src/test/regress/expected/with_clause_optimizer.out +++ b/src/test/regress/expected/with_clause_optimizer.out @@ -2331,26 +2331,91 @@ select count(*) c from with_dml; 5 (1 row) --- Test one cannot use DML CTE if multiple CTE references found. --- Otherwise it will cause duplicated DML operations or planner errors. +-- Test ORCA shares DML CTE results if multiple CTE references found. explain (costs off) with cte as ( insert into with_dml select i, i * 100 from generate_series(1,5) i returning i ) select count(*) from cte where i < (select avg(i) from cte); -ERROR: Too much references to non-SELECT CTE (allpaths.c:2043) + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------ + Gather Motion 3:1 (slice5; segments: 3) + -> Sequence + -> Shared Scan (share slice:id 5:0) + -> Materialize + -> Result + -> Insert + -> Result + -> Result + -> Function Scan on generate_series + -> Redistribute Motion 1:3 (slice4) + -> Aggregate + -> Gather Motion 3:1 (slice3; segments: 3) + -> Aggregate + -> Nested Loop + Join Filter: ((share0_ref2.i)::numeric < (pg_catalog.avg((avg(share0_ref3.i))))) + -> Broadcast Motion 1:3 (slice2) + -> Aggregate + -> Gather Motion 3:1 (slice1; segments: 3) + -> Aggregate + -> Shared Scan (share slice:id 1:0) + -> Materialize + -> Shared Scan (share slice:id 3:0) + Optimizer: Pivotal Optimizer (GPORCA) +(23 rows) + explain (costs off) with cte as ( update with_dml set j = j + 1 returning i ) select count(*) from cte where i < (select avg(i) from cte); -ERROR: Too much references to non-SELECT CTE (allpaths.c:2043) + QUERY PLAN +------------------------------------------------------------------------------ + Sequence + -> Shared Scan (share slice:id 0:0) + -> Materialize + -> Gather Motion 3:1 (slice1; segments: 3) + -> Result + -> Update + -> Split + -> Result + -> Seq Scan on with_dml + -> Aggregate + -> Nested Loop + Join Filter: ((share0_ref2.i)::numeric < (avg(share0_ref3.i))) + -> Aggregate + -> Shared Scan (share slice:id 0:0) + -> Materialize + -> Shared Scan (share slice:id 0:0) + Optimizer: Pivotal Optimizer (GPORCA) +(17 rows) + explain (costs off) with cte as ( delete from with_dml where i > 0 returning i ) select count(*) from cte where i < (select avg(i) from cte); -ERROR: Too much references to non-SELECT CTE (allpaths.c:2043) + QUERY PLAN +------------------------------------------------------------------------------ + Sequence + -> Shared Scan (share slice:id 0:0) + -> Materialize + -> Gather Motion 3:1 (slice1; segments: 3) + -> Result + -> Delete + -> Result + -> Seq Scan on with_dml + Filter: (i > 0) + -> Aggregate + -> Nested Loop + Join Filter: ((share0_ref2.i)::numeric < (avg(share0_ref3.i))) + -> Aggregate + -> Shared Scan (share slice:id 0:0) + -> Materialize + -> Shared Scan (share slice:id 0:0) + Optimizer: Pivotal Optimizer (GPORCA) +(17 rows) + -- Greenplum fails to execute SELECT INTO and CREATE TABLE AS statements, whose -- queries contain modifying CTEs, because Greenplum cannot have two writer -- segworker groups, and during execution an error is thrown. Showing From 79c1cd35efd8d3daee68e1d03cc43a69101d5333 Mon Sep 17 00:00:00 2001 From: kotb Date: Tue, 11 Mar 2025 00:35:04 +0300 Subject: [PATCH 04/74] also check CTEs when marking query as DML --- .../libgpopt/src/base/CQueryContext.cpp | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp b/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp index 97a298059440..ca81b7dd240c 100644 --- a/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp +++ b/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp @@ -16,6 +16,7 @@ #include "gpopt/base/CColRefSetIter.h" #include "gpopt/base/CColumnFactory.h" +#include "gpopt/base/CCTEReq.h" #include "gpopt/base/CDistributionSpecAny.h" #include "gpopt/base/COptCtxt.h" #include "gpopt/operators/CLogicalLimit.h" @@ -211,8 +212,6 @@ CQueryContext::PqcGenerate(CMemoryPool *mp, CExpression *pexpr, CDistributionSpec *pds = NULL; - poptctxt->MarkDMLQuery(CUtils::FHasLogicalDML(mp, pexpr)); - // DML commands do not have distribution requirement. Otherwise the // distribution requirement is Singleton. if (CUtils::FLogicalDML(pexpr->Pop())) @@ -239,6 +238,28 @@ CQueryContext::PqcGenerate(CMemoryPool *mp, CExpression *pexpr, // Required CTEs are obtained from the CTEInfo global information in the optimizer context CCTEReq *pcter = poptctxt->Pcteinfo()->PcterProducers(mp); + // check if query has DML operation and mark it + BOOL fDML = CUtils::FHasLogicalDML(mp, pexpr); + if (!fDML) + { + // also check all required CTEs + CExpressionArray *pdrgpexpr = poptctxt->Pcteinfo()->PdrgPexpr(mp); + + const ULONG size = pdrgpexpr->Size(); + for (ULONG ul = 0; ul < size; ul++) + { + CExpression *pCteExpr = (*pdrgpexpr)[ul]; + if (CUtils::FHasLogicalDML(mp, pCteExpr)) + { + fDML = true; + break; + } + } + + pdrgpexpr->Release(); + } + poptctxt->MarkDMLQuery(fDML); + // NB: Partition propagation requirements are not initialized here. They are // constructed later based on derived relation properties (CPartInfo) by // CReqdPropPlan::InitReqdPartitionPropagation(). From 3120298ede6f2cfa24955eb2559bdcafd61f73b9 Mon Sep 17 00:00:00 2001 From: kotb Date: Tue, 11 Mar 2025 00:41:38 +0300 Subject: [PATCH 05/74] remove unused header --- src/backend/gporca/libgpopt/src/base/CQueryContext.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp b/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp index ca81b7dd240c..1c45e2d93f33 100644 --- a/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp +++ b/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp @@ -16,7 +16,6 @@ #include "gpopt/base/CColRefSetIter.h" #include "gpopt/base/CColumnFactory.h" -#include "gpopt/base/CCTEReq.h" #include "gpopt/base/CDistributionSpecAny.h" #include "gpopt/base/COptCtxt.h" #include "gpopt/operators/CLogicalLimit.h" From b5b22a4e87bee0f079a4cf6c42597c2b0b98d6f4 Mon Sep 17 00:00:00 2001 From: kotb Date: Tue, 11 Mar 2025 09:18:57 +0300 Subject: [PATCH 06/74] fix tests --- .../expected/explain_analyze_optimizer.out | 2 +- .../expected/subselect_gp_optimizer.out | 41 +-- .../regress/expected/update_gp_optimizer.out | 33 +- src/test/regress/expected/with.out | 2 + .../expected/with_clause_optimizer.out | 303 ++++++++++-------- src/test/regress/sql/with.sql | 2 + src/test/regress/sql/with_clause.sql | 3 +- 7 files changed, 210 insertions(+), 176 deletions(-) diff --git a/src/test/regress/expected/explain_analyze_optimizer.out b/src/test/regress/expected/explain_analyze_optimizer.out index 0b78aa85c80b..4d272391e8b1 100644 --- a/src/test/regress/expected/explain_analyze_optimizer.out +++ b/src/test/regress/expected/explain_analyze_optimizer.out @@ -112,7 +112,7 @@ WITH cte AS ( -> Result (actual rows=3 loops=1) -> Insert (actual rows=3 loops=1) -> Result (actual rows=3 loops=1) - -> Result (actual rows=5 loops=1) + -> Result (actual rows=3 loops=1) -> Function Scan on generate_series (actual rows=5 loops=1) Planning time: 20.649 ms (slice0) Executor memory: 59K bytes. diff --git a/src/test/regress/expected/subselect_gp_optimizer.out b/src/test/regress/expected/subselect_gp_optimizer.out index 7ed0c86560bc..81030eb75022 100644 --- a/src/test/regress/expected/subselect_gp_optimizer.out +++ b/src/test/regress/expected/subselect_gp_optimizer.out @@ -3674,7 +3674,7 @@ where exists (select i from cte); Join Filter: true -> Seq Scan on t2 t2_1 -> Materialize - -> Broadcast Motion 1:3 (slice3) + -> Broadcast Motion 1:3 (slice3; segments: 1) -> Limit -> Gather Motion 3:1 (slice2; segments: 3) -> Result @@ -3731,26 +3731,27 @@ select i from t2 where 0 = (select i from cte); QUERY PLAN -------------------------------------------------------------------------- - Nested Loop - Join Filter: true - -> Result - Filter: (0 = t1.i) - -> Assert - Assert Cond: ((row_number() OVER (?)) = 1) - -> WindowAgg - -> Gather Motion 3:1 (slice3; segments: 3) - -> Result - -> Update - -> Redistribute Motion 3:3 (slice2; segments: 3) - Hash Key: t1.i - -> Split - -> Result - -> Seq Scan on t1 - -> Materialize - -> Gather Motion 3:1 (slice1; segments: 3) - -> Seq Scan on t2 + Gather Motion 1:1 (slice4; segments: 1) + -> Nested Loop + Join Filter: true + -> Result + Filter: (0 = t1.i) + -> Assert + Assert Cond: ((row_number() OVER (?)) = 1) + -> WindowAgg + -> Gather Motion 3:1 (slice3; segments: 3) + -> Result + -> Update + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: t1.i + -> Split + -> Result + -> Seq Scan on t1 + -> Materialize + -> Gather Motion 3:1 (slice1; segments: 3) + -> Seq Scan on t2 Optimizer: Pivotal Optimizer (GPORCA) -(19 rows) +(20 rows) with cte as (update t1 set i = 0 diff --git a/src/test/regress/expected/update_gp_optimizer.out b/src/test/regress/expected/update_gp_optimizer.out index 6ec50731a569..fe27f93e5fc5 100644 --- a/src/test/regress/expected/update_gp_optimizer.out +++ b/src/test/regress/expected/update_gp_optimizer.out @@ -258,24 +258,25 @@ WITH CTE AS (DELETE FROM t1 RETURNING *) SELECT count(*) AS a FROM t_strewn JOIN cte USING (i); QUERY PLAN --------------------------------------------------------------------------- - Aggregate - -> Gather Motion 3:1 (slice3; segments: 3) - -> Aggregate - -> Hash Join - Hash Cond: (t_strewn.i = "outer".ColRef_0049) - -> Redistribute Motion 3:3 (slice1; segments: 3) - Hash Key: t_strewn.i - -> Seq Scan on t_strewn - -> Hash - -> Redistribute Motion 3:3 (slice2; segments: 3) - Hash Key: "outer".ColRef_0049 - -> Result + Gather Motion 1:1 (slice4; segments: 1) + -> Aggregate + -> Gather Motion 3:1 (slice3; segments: 3) + -> Aggregate + -> Hash Join + Hash Cond: (t_strewn.i = "outer".ColRef_0049) + -> Redistribute Motion 3:3 (slice1; segments: 3) + Hash Key: t_strewn.i + -> Seq Scan on t_strewn + -> Hash + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: "outer".ColRef_0049 -> Result - -> Delete - -> Result - -> Seq Scan on t1 + -> Result + -> Delete + -> Result + -> Seq Scan on t1 Optimizer: Pivotal Optimizer (GPORCA) -(17 rows) +(18 rows) WITH CTE AS (DELETE FROM t1 RETURNING *) SELECT count(*) AS a FROM t_strewn JOIN cte USING (i); diff --git a/src/test/regress/expected/with.out b/src/test/regress/expected/with.out index 029f2910300c..21b5907910c1 100644 --- a/src/test/regress/expected/with.out +++ b/src/test/regress/expected/with.out @@ -2213,6 +2213,7 @@ DROP TABLE IF EXISTS t1; NOTICE: table "t1" does not exist, skipping --end_ignore CREATE TABLE t1 (c1 int, c2 int) DISTRIBUTED RANDOMLY; +SET optimizer=off; EXPLAIN (VERBOSE, COSTS OFF) WITH cte1 AS ( INSERT INTO t1 VALUES ( 1, 2 ) RETURNING * @@ -2261,6 +2262,7 @@ SELECT * FROM cte1 a JOIN cte1 b USING (c1); (1 row) DROP TABLE t1; +SET optimizer=on; -- Ensure that prefetch is not disabled for HashJoin in case of join at single segment. -- Test Shared Scan producer is executed under inner part of join first and the -- deadlock between Shared Scans does not occur diff --git a/src/test/regress/expected/with_clause_optimizer.out b/src/test/regress/expected/with_clause_optimizer.out index 762184cd272b..2c8c051078e5 100644 --- a/src/test/regress/expected/with_clause_optimizer.out +++ b/src/test/regress/expected/with_clause_optimizer.out @@ -2303,18 +2303,19 @@ with cte as ( ) select count(*) from cte where i > 2; QUERY PLAN ------------------------------------------------------------------------------ - Aggregate - -> Gather Motion 3:1 (slice1; segments: 3) - -> Aggregate - -> Result - Filter: (generate_series.generate_series > 2) + Gather Motion 1:1 (slice2; segments: 1) + -> Aggregate + -> Gather Motion 3:1 (slice1; segments: 3) + -> Aggregate -> Result - -> Insert - -> Result + Filter: (generate_series.generate_series > 2) + -> Result + -> Insert -> Result - -> Function Scan on generate_series + -> Result + -> Function Scan on generate_series Optimizer: Pivotal Optimizer (GPORCA) -(11 rows) +(12 rows) with cte as ( insert into with_dml select i, i * 100 from generate_series(1,5) i @@ -2348,13 +2349,13 @@ with cte as ( -> Result -> Result -> Function Scan on generate_series - -> Redistribute Motion 1:3 (slice4) + -> Redistribute Motion 1:3 (slice4; segments: 1) -> Aggregate -> Gather Motion 3:1 (slice3; segments: 3) -> Aggregate -> Nested Loop Join Filter: ((share0_ref2.i)::numeric < (pg_catalog.avg((avg(share0_ref3.i))))) - -> Broadcast Motion 1:3 (slice2) + -> Broadcast Motion 1:3 (slice2; segments: 1) -> Aggregate -> Gather Motion 3:1 (slice1; segments: 3) -> Aggregate @@ -2371,24 +2372,28 @@ with cte as ( ) select count(*) from cte where i < (select avg(i) from cte); QUERY PLAN ------------------------------------------------------------------------------ - Sequence - -> Shared Scan (share slice:id 0:0) - -> Materialize - -> Gather Motion 3:1 (slice1; segments: 3) + Gather Motion 3:1 (slice4; segments: 3) + -> Sequence + -> Shared Scan (share slice:id 4:0) + -> Materialize -> Result -> Update -> Split -> Result -> Seq Scan on with_dml - -> Aggregate - -> Nested Loop - Join Filter: ((share0_ref2.i)::numeric < (avg(share0_ref3.i))) + -> Redistribute Motion 1:3 (slice3; segments: 1) -> Aggregate - -> Shared Scan (share slice:id 0:0) - -> Materialize - -> Shared Scan (share slice:id 0:0) + -> Nested Loop + Join Filter: ((share0_ref2.i)::numeric < (pg_catalog.avg((avg(share0_ref3.i))))) + -> Aggregate + -> Gather Motion 3:1 (slice2; segments: 3) + -> Aggregate + -> Shared Scan (share slice:id 2:0) + -> Materialize + -> Gather Motion 3:1 (slice1; segments: 3) + -> Shared Scan (share slice:id 1:0) Optimizer: Pivotal Optimizer (GPORCA) -(17 rows) +(21 rows) explain (costs off) with cte as ( @@ -2397,24 +2402,28 @@ with cte as ( ) select count(*) from cte where i < (select avg(i) from cte); QUERY PLAN ------------------------------------------------------------------------------ - Sequence - -> Shared Scan (share slice:id 0:0) - -> Materialize - -> Gather Motion 3:1 (slice1; segments: 3) + Gather Motion 3:1 (slice4; segments: 3) + -> Sequence + -> Shared Scan (share slice:id 4:0) + -> Materialize -> Result -> Delete -> Result -> Seq Scan on with_dml Filter: (i > 0) - -> Aggregate - -> Nested Loop - Join Filter: ((share0_ref2.i)::numeric < (avg(share0_ref3.i))) + -> Redistribute Motion 1:3 (slice3; segments: 1) -> Aggregate - -> Shared Scan (share slice:id 0:0) - -> Materialize - -> Shared Scan (share slice:id 0:0) + -> Nested Loop + Join Filter: ((share0_ref2.i)::numeric < (pg_catalog.avg((avg(share0_ref3.i))))) + -> Aggregate + -> Gather Motion 3:1 (slice2; segments: 3) + -> Aggregate + -> Shared Scan (share slice:id 2:0) + -> Materialize + -> Gather Motion 3:1 (slice1; segments: 3) + -> Shared Scan (share slice:id 1:0) Optimizer: Pivotal Optimizer (GPORCA) -(17 rows) +(21 rows) -- Greenplum fails to execute SELECT INTO and CREATE TABLE AS statements, whose -- queries contain modifying CTEs, because Greenplum cannot have two writer @@ -2473,15 +2482,14 @@ with cte as ( ) select count(*) from cte; QUERY PLAN ------------------------------------------------------ - Aggregate - -> Explicit Gather Motion 3:1 (slice1; segments: 3) - -> Aggregate - -> Result - -> Insert - -> Result - -> Function Scan on generate_series + Explicit Gather Motion 3:1 (slice1; segments: 3) + -> Aggregate + -> Result + -> Insert + -> Result + -> Function Scan on generate_series Optimizer: Pivotal Optimizer (GPORCA) -(8 rows) +(7 rows) with cte as ( insert into with_dml_dr @@ -2596,19 +2604,18 @@ with cte as ( ) select count(*) from cte join t_repl using (i); QUERY PLAN ------------------------------------------------------------ - Aggregate - -> Explicit Gather Motion 3:1 (slice1; segments: 3) - -> Aggregate - -> Hash Join - Hash Cond: (generate_series.generate_series = t_repl.i) - -> Result - -> Insert - -> Result - -> Function Scan on generate_series - -> Hash - -> Seq Scan on t_repl + Explicit Gather Motion 3:1 (slice1; segments: 3) + -> Aggregate + -> Hash Join + Hash Cond: (generate_series.generate_series = t_repl.i) + -> Result + -> Insert + -> Result + -> Function Scan on generate_series + -> Hash + -> Seq Scan on t_repl Optimizer: Pivotal Optimizer (GPORCA) -(12 rows) +(11 rows) with cte as ( insert into with_dml_dr @@ -2776,21 +2783,22 @@ select count(*) from cte join (select a from generate_series(1,5) a) x on cte.i = x.a; QUERY PLAN ------------------------------------------------------------ - Aggregate - -> Gather Motion 3:1 (slice1; segments: 3) - -> Aggregate - -> Hash Join - Hash Cond: (generate_series.generate_series = generate_series_1.generate_series) - -> Result - One-Time Filter: (gp_execution_segment() = 1) - -> Function Scan on generate_series - -> Hash + Gather Motion 1:1 (slice2; segments: 1) + -> Aggregate + -> Gather Motion 3:1 (slice1; segments: 3) + -> Aggregate + -> Hash Join + Hash Cond: (generate_series.generate_series = generate_series_1.generate_series) -> Result - -> Insert - -> Result - -> Function Scan on generate_series generate_series_1 + -> Result + -> Insert + -> Result + -> Function Scan on generate_series + -> Hash + -> Result + -> Function Scan on generate_series generate_series_1 Optimizer: Pivotal Optimizer (GPORCA) -(14 rows) +(15 rows) with cte as ( insert into with_dml_dr @@ -2823,20 +2831,21 @@ with cte as ( ) select count(*) from cte join t_hashed on cte.i = t_hashed.i; QUERY PLAN ------------------------------------------------------------------ - Aggregate - -> Gather Motion 3:1 (slice1; segments: 3) - -> Aggregate - -> Hash Join - Hash Cond: (generate_series.generate_series = t_hashed.i) - -> Result + Gather Motion 1:1 (slice2; segments: 1) + -> Aggregate + -> Gather Motion 3:1 (slice1; segments: 3) + -> Aggregate + -> Hash Join + Hash Cond: (generate_series.generate_series = t_hashed.i) -> Result - -> Insert - -> Result - -> Function Scan on generate_series - -> Hash - -> Seq Scan on t_hashed + -> Result + -> Insert + -> Result + -> Function Scan on generate_series + -> Hash + -> Seq Scan on t_hashed Optimizer: Pivotal Optimizer (GPORCA) -(13 rows) +(14 rows) with cte as ( insert into with_dml_dr @@ -2856,20 +2865,21 @@ with cte as ( ) select count(*) from cte left join t_hashed on cte.i = t_hashed.i; QUERY PLAN --------------------------------------------------------------- - Aggregate - -> Gather Motion 3:1 (slice1; segments: 3) - -> Aggregate - -> Hash Left Join - Hash Cond: (generate_series.generate_series = t_hashed.i) - -> Result + Gather Motion 1:1 (slice2; segments: 1) + -> Aggregate + -> Gather Motion 3:1 (slice1; segments: 3) + -> Aggregate + -> Hash Left Join + Hash Cond: (generate_series.generate_series = t_hashed.i) -> Result - -> Insert - -> Result - -> Function Scan on generate_series - -> Hash - -> Seq Scan on t_hashed + -> Result + -> Insert + -> Result + -> Function Scan on generate_series + -> Hash + -> Seq Scan on t_hashed Optimizer: Pivotal Optimizer (GPORCA) -(13 rows) +(14 rows) with cte as ( insert into with_dml_dr @@ -2889,22 +2899,23 @@ with cte as ( ) select count(*) from cte join t_strewn on cte.i = t_strewn.i; QUERY PLAN ------------------------------------------------------------------ - Aggregate - -> Gather Motion 3:1 (slice2; segments: 3) - -> Aggregate - -> Hash Join - Hash Cond: (generate_series.generate_series = t_strewn.i) - -> Result + Gather Motion 1:1 (slice3; segments: 1) + -> Aggregate + -> Gather Motion 3:1 (slice2; segments: 3) + -> Aggregate + -> Hash Join + Hash Cond: (generate_series.generate_series = t_strewn.i) -> Result - -> Insert - -> Result - -> Function Scan on generate_series - -> Hash - -> Redistribute Motion 3:3 (slice1; segments: 3) - Hash Key: t_strewn.i - -> Seq Scan on t_strewn + -> Result + -> Insert + -> Result + -> Function Scan on generate_series + -> Hash + -> Redistribute Motion 3:3 (slice1; segments: 3) + Hash Key: t_strewn.i + -> Seq Scan on t_strewn Optimizer: Pivotal Optimizer (GPORCA) -(15 rows) +(16 rows) with cte as ( insert into with_dml_dr @@ -2924,22 +2935,23 @@ with cte as ( ) select count(*) from cte left join t_strewn on cte.i = t_strewn.i; QUERY PLAN --------------------------------------------------------------- - Aggregate - -> Gather Motion 3:1 (slice2; segments: 3) - -> Aggregate - -> Hash Left Join - Hash Cond: (generate_series.generate_series = t_strewn.i) - -> Result + Gather Motion 1:1 (slice3; segments: 1) + -> Aggregate + -> Gather Motion 3:1 (slice2; segments: 3) + -> Aggregate + -> Hash Left Join + Hash Cond: (generate_series.generate_series = t_strewn.i) -> Result - -> Insert - -> Result - -> Function Scan on generate_series - -> Hash - -> Redistribute Motion 3:3 (slice1; segments: 3) - Hash Key: t_strewn.i - -> Seq Scan on t_strewn + -> Result + -> Insert + -> Result + -> Function Scan on generate_series + -> Hash + -> Redistribute Motion 3:3 (slice1; segments: 3) + Hash Key: t_strewn.i + -> Seq Scan on t_strewn Optimizer: Pivotal Optimizer (GPORCA) -(15 rows) +(16 rows) with cte as ( insert into with_dml_dr @@ -3153,20 +3165,29 @@ where t1.i in (select i from cte) order by 1; QUERY PLAN -------------------------------------------------------------------------- - Gather Motion 3:1 (slice1; segments: 3) + Gather Motion 3:1 (slice2; segments: 3) Merge Key: t1.i -> Sort Sort Key: t1.i - -> Hash Semi Join - Hash Cond: (t1.i = generate_series.generate_series) - -> Seq Scan on t1 - -> Hash - -> Result - -> Insert + -> Hash Join + Hash Cond: (generate_series.generate_series = t1.i) + -> HashAggregate + Group Key: generate_series.generate_series + -> Redistribute Motion 3:3 (slice1; segments: 3) + Hash Key: generate_series.generate_series + -> HashAggregate + Group Key: generate_series.generate_series -> Result - -> Function Scan on generate_series + One-Time Filter: (gp_execution_segment() = 2) + -> Result + -> Result + -> Insert + -> Result + -> Function Scan on generate_series + -> Hash + -> Seq Scan on t1 Optimizer: Pivotal Optimizer (GPORCA) -(13 rows) +(22 rows) with cte as ( insert into with_dml_dr @@ -3195,24 +3216,32 @@ where t1.i in (select i from cte where cte.i = t1.j) order by 1; QUERY PLAN -------------------------------------------------------------------------------- - Gather Motion 3:1 (slice1; segments: 3) + Gather Motion 3:1 (slice3; segments: 3) Merge Key: t1.i -> Sort Sort Key: t1.i -> Hash Join - Hash Cond: ((generate_series.generate_series = t1.j) AND (generate_series.generate_series = t1.i)) - -> Result + Hash Cond: ((t1.j = generate_series.generate_series) AND (t1.i = generate_series.generate_series)) + -> Redistribute Motion 3:3 (slice1; segments: 3) + Hash Key: t1.j + -> Seq Scan on t1 + Filter: (NOT (j IS NULL)) + -> Hash -> HashAggregate Group Key: generate_series.generate_series - -> Result - -> Insert + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: generate_series.generate_series + -> HashAggregate + Group Key: generate_series.generate_series -> Result - -> Function Scan on generate_series - -> Hash - -> Seq Scan on t1 - Filter: (NOT (j IS NULL)) + One-Time Filter: (gp_execution_segment() = 0) + -> Result + -> Result + -> Insert + -> Result + -> Function Scan on generate_series Optimizer: Pivotal Optimizer (GPORCA) -(17 rows) +(25 rows) with cte as ( insert into with_dml_dr diff --git a/src/test/regress/sql/with.sql b/src/test/regress/sql/with.sql index 5b0028f5b9e0..ad9cf4b740d6 100644 --- a/src/test/regress/sql/with.sql +++ b/src/test/regress/sql/with.sql @@ -1052,6 +1052,7 @@ select count(*) from rank_tbl where rank in (select rank from updated); DROP TABLE IF EXISTS t1; --end_ignore CREATE TABLE t1 (c1 int, c2 int) DISTRIBUTED RANDOMLY; +SET optimizer=off; EXPLAIN (VERBOSE, COSTS OFF) WITH cte1 AS ( @@ -1065,6 +1066,7 @@ WITH cte1 AS ( SELECT * FROM cte1 a JOIN cte1 b USING (c1); DROP TABLE t1; +SET optimizer=on; -- Ensure that prefetch is not disabled for HashJoin in case of join at single segment. -- Test Shared Scan producer is executed under inner part of join first and the diff --git a/src/test/regress/sql/with_clause.sql b/src/test/regress/sql/with_clause.sql index ba1eea4ec5d7..ef706c79556f 100644 --- a/src/test/regress/sql/with_clause.sql +++ b/src/test/regress/sql/with_clause.sql @@ -442,8 +442,7 @@ with cte as ( ) select count(*) from cte where i > 2; select count(*) c from with_dml; --- Test one cannot use DML CTE if multiple CTE references found. --- Otherwise it will cause duplicated DML operations or planner errors. +-- Test ORCA shares DML CTE results if multiple CTE references found. explain (costs off) with cte as ( insert into with_dml select i, i * 100 from generate_series(1,5) i From 75dc8e951ab79b64ca0449a07c3e77120e1cb5e7 Mon Sep 17 00:00:00 2001 From: kotb Date: Tue, 11 Mar 2025 22:38:51 +0300 Subject: [PATCH 07/74] fix double delete on logical delete --- src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp index 6247487b7ca9..61ff88c558d9 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp @@ -216,6 +216,7 @@ CLogicalDelete::PopCopyWithRemappedColumns(CMemoryPool *mp, pcrTableOid = CUtils::PcrRemap(m_pcrTableOid, colref_mapping, must_exist); } + m_ptabdesc->AddRef(); return GPOS_NEW(mp) CLogicalDelete(mp, m_ptabdesc, colref_array, pdrgpcrOutput, pcrCtid, From 5ddee8dd89eefd860eb2cc00ade3bb0d1c9b7993 Mon Sep 17 00:00:00 2001 From: kotb Date: Tue, 11 Mar 2025 23:01:15 +0300 Subject: [PATCH 08/74] fix gporca unit tests expected dumps --- .../gporca/data/dxl/minidump/InsertInCTE.mdp | 114 ++- .../data/dxl/minidump/InsertIntoReturning.mdp | 711 ++++++++++-------- 2 files changed, 438 insertions(+), 387 deletions(-) diff --git a/src/backend/gporca/data/dxl/minidump/InsertInCTE.mdp b/src/backend/gporca/data/dxl/minidump/InsertInCTE.mdp index 2ee2ebb48030..00b4f838e4a7 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertInCTE.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertInCTE.mdp @@ -37,28 +37,6 @@ where t1.i in (select i from cte); - - - - - - - - - - - - - - - - - - - - - - @@ -204,11 +182,33 @@ where t1.i in (select i from cte); + + + + + + + + + + + + + + + + + + + + + + - - + + @@ -245,7 +245,7 @@ where t1.i in (select i from cte); - + @@ -325,7 +325,7 @@ where t1.i in (select i from cte); - + @@ -366,7 +366,7 @@ where t1.i in (select i from cte); - + @@ -383,10 +383,10 @@ where t1.i in (select i from cte); - + - + @@ -400,7 +400,7 @@ where t1.i in (select i from cte); - + @@ -431,7 +431,7 @@ where t1.i in (select i from cte); - + @@ -447,7 +447,7 @@ where t1.i in (select i from cte); - + @@ -463,7 +463,7 @@ where t1.i in (select i from cte); - + @@ -474,7 +474,7 @@ where t1.i in (select i from cte); - + @@ -488,7 +488,7 @@ where t1.i in (select i from cte); - + @@ -528,7 +528,7 @@ where t1.i in (select i from cte); - + @@ -541,48 +541,42 @@ where t1.i in (select i from cte); - + - + - + + + + - + - - - - - - - + + - + - - - - - - - - - - + + + + + + @@ -595,8 +589,8 @@ where t1.i in (select i from cte); - - + + diff --git a/src/backend/gporca/data/dxl/minidump/InsertIntoReturning.mdp b/src/backend/gporca/data/dxl/minidump/InsertIntoReturning.mdp index 8a7a0c4a6835..a1079db7a879 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertIntoReturning.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertIntoReturning.mdp @@ -7,331 +7,388 @@ insert into ttt values (123, 'daad') returning id+length(data); --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From bed16f14c37bb6c01f29ddd10916af40df7e780b Mon Sep 17 00:00:00 2001 From: kotb Date: Tue, 11 Mar 2025 23:17:33 +0300 Subject: [PATCH 09/74] revert comment edit --- src/test/regress/expected/with_clause_optimizer.out | 3 ++- src/test/regress/sql/with_clause.sql | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/regress/expected/with_clause_optimizer.out b/src/test/regress/expected/with_clause_optimizer.out index 2c8c051078e5..c92f94e37418 100644 --- a/src/test/regress/expected/with_clause_optimizer.out +++ b/src/test/regress/expected/with_clause_optimizer.out @@ -2332,7 +2332,8 @@ select count(*) c from with_dml; 5 (1 row) --- Test ORCA shares DML CTE results if multiple CTE references found. +-- Test one cannot use DML CTE if multiple CTE references found. +-- Otherwise it will cause duplicated DML operations or planner errors. explain (costs off) with cte as ( insert into with_dml select i, i * 100 from generate_series(1,5) i diff --git a/src/test/regress/sql/with_clause.sql b/src/test/regress/sql/with_clause.sql index ef706c79556f..ba1eea4ec5d7 100644 --- a/src/test/regress/sql/with_clause.sql +++ b/src/test/regress/sql/with_clause.sql @@ -442,7 +442,8 @@ with cte as ( ) select count(*) from cte where i > 2; select count(*) c from with_dml; --- Test ORCA shares DML CTE results if multiple CTE references found. +-- Test one cannot use DML CTE if multiple CTE references found. +-- Otherwise it will cause duplicated DML operations or planner errors. explain (costs off) with cte as ( insert into with_dml select i, i * 100 from generate_series(1,5) i From 8fb65ac025800a39d3f5d8db986166496a7a6fa7 Mon Sep 17 00:00:00 2001 From: kotb Date: Tue, 11 Mar 2025 23:19:38 +0300 Subject: [PATCH 10/74] gracer setting optimizer --- src/test/regress/expected/with.out | 4 ++-- src/test/regress/sql/with.sql | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/regress/expected/with.out b/src/test/regress/expected/with.out index 21b5907910c1..f65239de1e71 100644 --- a/src/test/regress/expected/with.out +++ b/src/test/regress/expected/with.out @@ -2213,7 +2213,7 @@ DROP TABLE IF EXISTS t1; NOTICE: table "t1" does not exist, skipping --end_ignore CREATE TABLE t1 (c1 int, c2 int) DISTRIBUTED RANDOMLY; -SET optimizer=off; +SET optimizer = off; EXPLAIN (VERBOSE, COSTS OFF) WITH cte1 AS ( INSERT INTO t1 VALUES ( 1, 2 ) RETURNING * @@ -2262,7 +2262,7 @@ SELECT * FROM cte1 a JOIN cte1 b USING (c1); (1 row) DROP TABLE t1; -SET optimizer=on; +RESET optimizer; -- Ensure that prefetch is not disabled for HashJoin in case of join at single segment. -- Test Shared Scan producer is executed under inner part of join first and the -- deadlock between Shared Scans does not occur diff --git a/src/test/regress/sql/with.sql b/src/test/regress/sql/with.sql index ad9cf4b740d6..e4b3ff91be1f 100644 --- a/src/test/regress/sql/with.sql +++ b/src/test/regress/sql/with.sql @@ -1052,7 +1052,7 @@ select count(*) from rank_tbl where rank in (select rank from updated); DROP TABLE IF EXISTS t1; --end_ignore CREATE TABLE t1 (c1 int, c2 int) DISTRIBUTED RANDOMLY; -SET optimizer=off; +SET optimizer = off; EXPLAIN (VERBOSE, COSTS OFF) WITH cte1 AS ( @@ -1066,7 +1066,7 @@ WITH cte1 AS ( SELECT * FROM cte1 a JOIN cte1 b USING (c1); DROP TABLE t1; -SET optimizer=on; +RESET optimizer; -- Ensure that prefetch is not disabled for HashJoin in case of join at single segment. -- Test Shared Scan producer is executed under inner part of join first and the From 8272021d5ec041864a0e0e5923d7d9310c3fd2d1 Mon Sep 17 00:00:00 2001 From: kotb Date: Wed, 12 Mar 2025 23:43:09 +0300 Subject: [PATCH 11/74] separate returning_gp regress expected to orca's and planner's, revert planner's to original --- src/test/regress/expected/returning_gp.out | 10 +- .../expected/returning_gp_optimizer.out | 191 ++++++++++++++++++ 2 files changed, 194 insertions(+), 7 deletions(-) create mode 100644 src/test/regress/expected/returning_gp_optimizer.out diff --git a/src/test/regress/expected/returning_gp.out b/src/test/regress/expected/returning_gp.out index 84737d1b1221..7f91a26a7dbd 100644 --- a/src/test/regress/expected/returning_gp.out +++ b/src/test/regress/expected/returning_gp.out @@ -66,11 +66,7 @@ update returning_parttab set partkey = 19 where partkey = 13 returning *; -- update that moves the tuple across partitions update returning_parttab set partkey = 18 where partkey = 4 returning *; - distkey | partkey | t ----------+---------+--------- - 1 | 18 | multi 4 -(1 row) - +ERROR: moving tuple from partition "returning_parttab_1_prt_1" to partition "returning_parttab_1_prt_newpart" not supported (seg0 slice1 127.0.0.1:40000 pid=5753) -- delete delete from returning_parttab where partkey = 14 returning *; distkey | partkey | t @@ -85,10 +81,10 @@ select * from returning_parttab; 1 | 1 | single insert 1 | 1 | multi 1 1 | 2 | multi 2 + 1 | 4 | multi 4 1 | 5 | multi 5 1 | 9 | multi 3 1 | 10 | single2 insert - 1 | 18 | multi 4 2 | 11 | multi2 1 2 | 12 | multi2 2 2 | 15 | multi2 5 @@ -188,4 +184,4 @@ DROP TRIGGER DROP FUNCTION trig_row_before_insupdate() CASCADE; DROP FUNCTION DROP TABLE returning_ctid_aoco; -DROP TABLE +DROP TABLE \ No newline at end of file diff --git a/src/test/regress/expected/returning_gp_optimizer.out b/src/test/regress/expected/returning_gp_optimizer.out new file mode 100644 index 000000000000..84737d1b1221 --- /dev/null +++ b/src/test/regress/expected/returning_gp_optimizer.out @@ -0,0 +1,191 @@ +-- +-- Extra GPDB tests on INSERT/UPDATE/DELETE RETURNING +-- +CREATE TABLE returning_parttab (distkey int4, partkey int4, i int, t text) +DISTRIBUTED BY (distkey) +PARTITION BY RANGE (partkey) (START (1) END (10)); +NOTICE: CREATE TABLE will create partition "returning_parttab_1_prt_1" for table "returning_parttab" +-- +-- Test INSERT RETURNING with partitioning +-- +insert into returning_parttab values (1, 1, 1, 'single insert') returning *; + distkey | partkey | i | t +---------+---------+---+--------------- + 1 | 1 | 1 | single insert +(1 row) + +insert into returning_parttab +select 1, g, g, 'multi ' || g from generate_series(1, 5) g +returning distkey, partkey, i, t; + distkey | partkey | i | t +---------+---------+---+--------- + 1 | 1 | 1 | multi 1 + 1 | 2 | 2 | multi 2 + 1 | 3 | 3 | multi 3 + 1 | 4 | 4 | multi 4 + 1 | 5 | 5 | multi 5 +(5 rows) + +-- Drop a column, and create a new partition. The new partition will not have +-- the dropped column, while in the old partition, it's still physically there, +-- just marked as dropped. Make sure the executor maps the columns correctly. +ALTER TABLE returning_parttab DROP COLUMN i; +alter table returning_parttab add partition newpart start (10) end (20); +NOTICE: CREATE TABLE will create partition "returning_parttab_1_prt_newpart" for table "returning_parttab" +insert into returning_parttab values (1, 10, 'single2 insert') returning *; + distkey | partkey | t +---------+---------+---------------- + 1 | 10 | single2 insert +(1 row) + +insert into returning_parttab select 2, g + 10, 'multi2 ' || g from generate_series(1, 5) g +returning distkey, partkey, t; + distkey | partkey | t +---------+---------+---------- + 2 | 11 | multi2 1 + 2 | 12 | multi2 2 + 2 | 13 | multi2 3 + 2 | 14 | multi2 4 + 2 | 15 | multi2 5 +(5 rows) + +-- +-- Test UPDATE/DELETE RETURNING with partitioning +-- +update returning_parttab set partkey = 9 where partkey = 3 returning *; + distkey | partkey | t +---------+---------+--------- + 1 | 9 | multi 3 +(1 row) + +update returning_parttab set partkey = 19 where partkey = 13 returning *; + distkey | partkey | t +---------+---------+---------- + 2 | 19 | multi2 3 +(1 row) + +-- update that moves the tuple across partitions +update returning_parttab set partkey = 18 where partkey = 4 returning *; + distkey | partkey | t +---------+---------+--------- + 1 | 18 | multi 4 +(1 row) + +-- delete +delete from returning_parttab where partkey = 14 returning *; + distkey | partkey | t +---------+---------+---------- + 2 | 14 | multi2 4 +(1 row) + +-- Check table contents, to be sure that all the commands did what they claimed. +select * from returning_parttab; + distkey | partkey | t +---------+---------+---------------- + 1 | 1 | single insert + 1 | 1 | multi 1 + 1 | 2 | multi 2 + 1 | 5 | multi 5 + 1 | 9 | multi 3 + 1 | 10 | single2 insert + 1 | 18 | multi 4 + 2 | 11 | multi2 1 + 2 | 12 | multi2 2 + 2 | 15 | multi2 5 + 2 | 19 | multi2 3 +(11 rows) + +-- +-- Test UPDATE RETURNING with a split update, i.e. an update of the distribution +-- key. +-- +CREATE TEMP TABLE returning_disttest (id int4) DISTRIBUTED BY (id); +INSERT INTO returning_disttest VALUES (1), (2); +-- Disable QUIET mode, so that we get some testing of the command tag as well. +-- (At one point, each split update incorrectly counted as two updated rows.) +\set QUIET off +UPDATE returning_disttest SET id = id + 1; +UPDATE 2 +SELECT * FROM returning_disttest; + id +---- + 3 + 2 +(2 rows) + +-- +-- Test returning ctid with trigger +-- +CREATE TABLE returning_ctid (f1 serial, f2 text) DISTRIBUTED BY (f1); +CREATE TABLE +-- Create function used by trigger +CREATE FUNCTION trig_row_before_insupdate() RETURNS TRIGGER AS $$ + BEGIN + NEW.f2 := NEW.f2 || ' triggered !'; + RETURN NEW; + END +$$ language plpgsql; +CREATE FUNCTION +-- Create trigger for each row insert or update +CREATE TRIGGER trig_row_before BEFORE INSERT OR UPDATE ON returning_ctid +FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate(); +CREATE TRIGGER +-- Check returning sys attribute on insert +INSERT INTO returning_ctid(f2) VALUES ('test') RETURNING ctid; + ctid +------- + (0,1) +(1 row) + +INSERT 0 1 +SELECT *, ctid FROM returning_ctid; + f1 | f2 | ctid +----+------------------+------- + 1 | test triggered ! | (0,1) +(1 row) + +-- Clean up +DROP TRIGGER trig_row_before ON returning_ctid; +DROP TRIGGER +DROP FUNCTION trig_row_before_insupdate() CASCADE; +DROP FUNCTION +DROP TABLE returning_ctid; +DROP TABLE +-- +-- Test returning ctid with trigger for AOCO table +-- +CREATE TABLE returning_ctid_aoco (f1 serial, f2 text) WITH (appendonly=true, orientation=column) DISTRIBUTED BY (f1); +CREATE TABLE +-- Create function used by trigger +CREATE FUNCTION trig_row_before_insupdate() RETURNS TRIGGER AS $$ + BEGIN + NEW.f2 := NEW.f2 || ' triggered !'; + RETURN NEW; + END +$$ language plpgsql; +CREATE FUNCTION +-- Create trigger for each row insert +CREATE TRIGGER trig_row_before BEFORE INSERT ON returning_ctid_aoco +FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate(); +CREATE TRIGGER +-- Check returning sys attribute on insert +INSERT INTO returning_ctid_aoco(f2) VALUES ('test') RETURNING ctid; + ctid +-------------- + (33554432,2) +(1 row) + +INSERT 0 1 +SELECT *, ctid FROM returning_ctid_aoco; + f1 | f2 | ctid +----+------------------+-------------- + 1 | test triggered ! | (33554432,2) +(1 row) + +-- Clean up +DROP TRIGGER trig_row_before ON returning_ctid_aoco; +DROP TRIGGER +DROP FUNCTION trig_row_before_insupdate() CASCADE; +DROP FUNCTION +DROP TABLE returning_ctid_aoco; +DROP TABLE From d19e2fdc3040a31d1b394b03f4cdf75396e5d065 Mon Sep 17 00:00:00 2001 From: kotb Date: Thu, 13 Mar 2025 12:11:45 +0300 Subject: [PATCH 12/74] add newline to returning_gp.out --- src/test/regress/expected/returning_gp.out | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/regress/expected/returning_gp.out b/src/test/regress/expected/returning_gp.out index 7f91a26a7dbd..5eb99a7ceeab 100644 --- a/src/test/regress/expected/returning_gp.out +++ b/src/test/regress/expected/returning_gp.out @@ -184,4 +184,4 @@ DROP TRIGGER DROP FUNCTION trig_row_before_insupdate() CASCADE; DROP FUNCTION DROP TABLE returning_ctid_aoco; -DROP TABLE \ No newline at end of file +DROP TABLE From 165b98d7dca9793a6f4ee65ed529d2e79a2ded82 Mon Sep 17 00:00:00 2001 From: kotb Date: Sat, 15 Mar 2025 00:45:11 +0300 Subject: [PATCH 13/74] dont request extra result if no projection needed --- .../translate/CTranslatorDXLToPlStmt.cpp | 4 +- .../gpopt/translate/CTranslatorQueryToDXL.cpp | 120 +++++------------- .../libgpopt/src/base/CQueryContext.cpp | 3 +- .../gpopt/translate/CTranslatorQueryToDXL.h | 5 +- 4 files changed, 42 insertions(+), 90 deletions(-) diff --git a/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp b/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp index 316bba6c2036..12b8232851e6 100644 --- a/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp +++ b/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp @@ -2058,7 +2058,9 @@ CTranslatorDXLToPlStmt::TranslateDXLHash( // create a reference to each entry in the child project list to create the target list of // the hash node - CDXLNode *project_list_dxlnode = (*dxlnode)[0]; + Edxlopid dxl_op_id = dxlnode->GetOperator()->GetDXLOperator(); + CDXLNode *project_list_dxlnode = + (*dxlnode)[EdxlopPhysicalDML == dxl_op_id ? 1 : 0]; List *target_list = TranslateDXLProjectListToHashTargetList( project_list_dxlnode, &dxl_translate_ctxt, output_context); diff --git a/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp b/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp index df0130779539..66f8e0e3985a 100644 --- a/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp +++ b/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp @@ -816,26 +816,8 @@ CTranslatorQueryToDXL::TranslateInsertQueryToDXL() GPOS_NEW(m_mp) CDXLNode(m_mp, insert_dxlnode, query_dxlnode); CRefCount::SafeRelease(m_dxl_query_output_cols); - if (NULL != m_query->returningList) - { - IntToUlongMap *output_attno_to_colid_mapping = - GPOS_NEW(m_mp) IntToUlongMap(m_mp); - - log_insert_dxlnode = ProcessReturningList( - log_insert_dxlnode, table_descr, output_attno_to_colid_mapping); - - // this array is filled earlier with target list and was used to get colids by their indices earlier - // now fill it with what will truly be returned - m_dxl_query_output_cols = CreateDXLOutputCols( - m_query->returningList, output_attno_to_colid_mapping); - output_attno_to_colid_mapping->Release(); - } - else - { - // we can safely set it to empty array here as we aren't outputting in this path - m_dxl_query_output_cols = GPOS_NEW(m_mp) CDXLNodeArray(m_mp); - } + log_insert_dxlnode = ProcessReturningList(log_insert_dxlnode, table_descr); return log_insert_dxlnode; } @@ -1175,43 +1157,47 @@ CTranslatorQueryToDXL::GetSystemColId(INT attribute_number) // //--------------------------------------------------------------------------- CDXLNode * -CTranslatorQueryToDXL::ProcessReturningList( - CDXLNode *dml_dxlnode, CDXLTableDescr *table_descr, - IntToUlongMap *output_attno_to_colid_mapping) +CTranslatorQueryToDXL::ProcessReturningList(CDXLNode *dml_dxlnode, + CDXLTableDescr *table_descr) { - GPOS_ASSERT(m_query->returningList != NULL); - - CMappingVarColId *var_to_colid_map = GPOS_NEW(m_mp) CMappingVarColId(m_mp); - var_to_colid_map->LoadTblColumns(m_query_level, m_query->resultRelation, - table_descr); - - CDXLNode *returning_proj_list_dxlnode = - GPOS_NEW(m_mp) CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarProjList(m_mp)); + GPOS_ASSERT(dml_dxlnode != NULL); - ListCell *lc = NULL; - ForEach(lc, m_query->returningList) + if (m_query->returningList != NULL) { - TargetEntry *target_entry = (TargetEntry *) lfirst(lc); + IntToUlongMap *sort_group_attno_to_colid_mapping = + GPOS_NEW(m_mp) IntToUlongMap(m_mp); + IntToUlongMap *output_attno_to_colid_mapping = + GPOS_NEW(m_mp) IntToUlongMap(m_mp); - CDXLNode *project_elem_dxlnode = TranslateExprToDXLProject( - target_entry->expr, target_entry->resname, var_to_colid_map, true); + // DML nodes output columns as in descriptor, temporary replace mapping + CMappingVarColId *var_to_colid_map_saved = m_var_to_colid_map; + m_var_to_colid_map = GPOS_NEW(m_mp) CMappingVarColId(m_mp); + m_var_to_colid_map->LoadTblColumns( + m_query_level, m_query->resultRelation, table_descr); - ULONG colid = - CDXLScalarProjElem::Cast(project_elem_dxlnode->GetOperator())->Id(); - StoreAttnoColIdMapping(output_attno_to_colid_mapping, - target_entry->resno, colid); + dml_dxlnode = TranslateTargetListToDXLProject( + m_query->returningList, dml_dxlnode, sort_group_attno_to_colid_mapping, + output_attno_to_colid_mapping, m_query->groupClause); - returning_proj_list_dxlnode->AddChild(project_elem_dxlnode); - } + // this array is filled earlier with target list and was used to get colids by their indices earlier + // now fill it with what will truly be returned + m_dxl_query_output_cols = CreateDXLOutputCols( + m_query->returningList, output_attno_to_colid_mapping); - CDXLNode *project_dxlnode = - GPOS_NEW(m_mp) CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLLogicalProject(m_mp)); - project_dxlnode->AddChild(returning_proj_list_dxlnode); - project_dxlnode->AddChild(dml_dxlnode); + GPOS_DELETE(m_var_to_colid_map); + m_var_to_colid_map = var_to_colid_map_saved; - GPOS_DELETE(var_to_colid_map); + output_attno_to_colid_mapping->Release(); + sort_group_attno_to_colid_mapping->Release(); + } + else + { + // we can safely set it to empty array here as we aren't outputting in this path + m_dxl_query_output_cols = GPOS_NEW(m_mp) CDXLNodeArray(m_mp); + } - return project_dxlnode; + // return project_dxlnode; + return dml_dxlnode; } //--------------------------------------------------------------------------- @@ -1295,26 +1281,8 @@ CTranslatorQueryToDXL::TranslateDeleteQueryToDXL() GPOS_NEW(m_mp) CDXLNode(m_mp, delete_dxlop, query_dxlnode); CRefCount::SafeRelease(m_dxl_query_output_cols); - if (NULL != m_query->returningList) - { - IntToUlongMap *output_attno_to_colid_mapping = - GPOS_NEW(m_mp) IntToUlongMap(m_mp); - - log_delete_dxlnode = ProcessReturningList( - log_delete_dxlnode, table_descr, output_attno_to_colid_mapping); - // this array is filled earlier with target list and was used to get colids by their indices earlier - // now fill it with what will truly be returned - m_dxl_query_output_cols = CreateDXLOutputCols( - m_query->returningList, output_attno_to_colid_mapping); - - output_attno_to_colid_mapping->Release(); - } - else - { - // we can safely set it to empty array here as we aren't outputting in this path - m_dxl_query_output_cols = GPOS_NEW(m_mp) CDXLNodeArray(m_mp); - } + log_delete_dxlnode = ProcessReturningList(log_delete_dxlnode, table_descr); return log_delete_dxlnode; } @@ -1434,26 +1402,8 @@ CTranslatorQueryToDXL::TranslateUpdateQueryToDXL() GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopupdate, query_dxlnode); CRefCount::SafeRelease(m_dxl_query_output_cols); - if (NULL != m_query->returningList) - { - IntToUlongMap *output_attno_to_colid_mapping = - GPOS_NEW(m_mp) IntToUlongMap(m_mp); - - log_update_dxlnode = ProcessReturningList( - log_update_dxlnode, table_descr, output_attno_to_colid_mapping); - // this array is filled earlier with target list and was used to get colids by their indices earlier - // now fill it with what will truly be returned - m_dxl_query_output_cols = CreateDXLOutputCols( - m_query->returningList, output_attno_to_colid_mapping); - - output_attno_to_colid_mapping->Release(); - } - else - { - // we can safely set it to empty array here as we aren't outputting in this path - m_dxl_query_output_cols = GPOS_NEW(m_mp) CDXLNodeArray(m_mp); - } + log_update_dxlnode = ProcessReturningList(log_update_dxlnode, table_descr); return log_update_dxlnode; } diff --git a/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp b/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp index 1c45e2d93f33..0185b9fac810 100644 --- a/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp +++ b/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp @@ -213,7 +213,8 @@ CQueryContext::PqcGenerate(CMemoryPool *mp, CExpression *pexpr, // DML commands do not have distribution requirement. Otherwise the // distribution requirement is Singleton. - if (CUtils::FLogicalDML(pexpr->Pop())) + // if (CUtils::FLogicalDML(pexpr->Pop())) + if (pdrgpulQueryOutputColRefId->Size() == 0) { pds = GPOS_NEW(mp) CDistributionSpecAny(COperator::EopSentinel); } diff --git a/src/include/gpopt/translate/CTranslatorQueryToDXL.h b/src/include/gpopt/translate/CTranslatorQueryToDXL.h index bf8e803e4243..0b5154bacf49 100644 --- a/src/include/gpopt/translate/CTranslatorQueryToDXL.h +++ b/src/include/gpopt/translate/CTranslatorQueryToDXL.h @@ -433,9 +433,8 @@ class CTranslatorQueryToDXL ULONG GetSystemColId(INT attribute_number); // Wrap dxl node in logical project with return columns from returningList - CDXLNode *ProcessReturningList( - CDXLNode *dml_dxlnode, CDXLTableDescr *table_descr, - IntToUlongMap *output_attno_to_colid_mapping); + CDXLNode *ProcessReturningList(CDXLNode *dml_dxlnode, + CDXLTableDescr *table_descr); public: // dtor From 7d6fa90423013da6666e439dd89042cec4f936d5 Mon Sep 17 00:00:00 2001 From: kotb Date: Sat, 15 Mar 2025 00:54:24 +0300 Subject: [PATCH 14/74] fix comment --- src/backend/gporca/libgpopt/src/base/CQueryContext.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp b/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp index 0185b9fac810..ebcec20d0226 100644 --- a/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp +++ b/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp @@ -211,9 +211,8 @@ CQueryContext::PqcGenerate(CMemoryPool *mp, CExpression *pexpr, CDistributionSpec *pds = NULL; - // DML commands do not have distribution requirement. Otherwise the + // Dont require distribution on empty output. Otherwise the // distribution requirement is Singleton. - // if (CUtils::FLogicalDML(pexpr->Pop())) if (pdrgpulQueryOutputColRefId->Size() == 0) { pds = GPOS_NEW(mp) CDistributionSpecAny(COperator::EopSentinel); From 7b3801f38fb0c01033f9cd1f4b83e212764dddf0 Mon Sep 17 00:00:00 2001 From: kotb Date: Sat, 15 Mar 2025 01:21:12 +0300 Subject: [PATCH 15/74] fix CTAS requesting motion for gathering output --- .../gporca/libgpopt/include/gpopt/base/CUtils.h | 3 +++ .../gporca/libgpopt/src/base/CQueryContext.cpp | 4 ++-- src/backend/gporca/libgpopt/src/base/CUtils.cpp | 15 +++++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/backend/gporca/libgpopt/include/gpopt/base/CUtils.h b/src/backend/gporca/libgpopt/include/gpopt/base/CUtils.h index 71d4ad7a006f..efcee4019c63 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/base/CUtils.h +++ b/src/backend/gporca/libgpopt/include/gpopt/base/CUtils.h @@ -779,6 +779,9 @@ class CUtils // recursively checks if the given expression has logical DML operator static BOOL FHasLogicalDML(CMemoryPool *mp, CExpression *pexpr); + // is operator responsible for CTAS operation + static BOOL FCTAS(COperator *pop); + // return regular string from wide-character string static CHAR *CreateMultiByteCharStringFromWCString(CMemoryPool *mp, WCHAR *wsz); diff --git a/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp b/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp index ebcec20d0226..d0868757105f 100644 --- a/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp +++ b/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp @@ -211,9 +211,9 @@ CQueryContext::PqcGenerate(CMemoryPool *mp, CExpression *pexpr, CDistributionSpec *pds = NULL; - // Dont require distribution on empty output. Otherwise the + // Dont require distribution on empty output or CTAS. Otherwise the // distribution requirement is Singleton. - if (pdrgpulQueryOutputColRefId->Size() == 0) + if (pdrgpulQueryOutputColRefId->Size() == 0 || CUtils::FCTAS(pexpr->Pop())) { pds = GPOS_NEW(mp) CDistributionSpecAny(COperator::EopSentinel); } diff --git a/src/backend/gporca/libgpopt/src/base/CUtils.cpp b/src/backend/gporca/libgpopt/src/base/CUtils.cpp index b5bafbbd273b..c83efcb396e0 100644 --- a/src/backend/gporca/libgpopt/src/base/CUtils.cpp +++ b/src/backend/gporca/libgpopt/src/base/CUtils.cpp @@ -3277,6 +3277,21 @@ CUtils::FLogicalDML(COperator *pop) COperator::EopLogicalUpdate == op_id; } +BOOL +CUtils::FCTAS(COperator *pop) +{ + GPOS_ASSERT(NULL != pop); + + if (COperator::EopLogicalInsert != pop->Eopid()) + { + return false; + } + + CLogicalInsert *popInsert = CLogicalInsert::PopConvert(pop); + + return IMDId::EmdidGPDBCtas == popInsert->Ptabdesc()->MDId()->MdidType(); +} + // recursively checks if the given expression has logical DML operator BOOL CUtils::FHasLogicalDML(CMemoryPool *mp, CExpression *pexpr) From 6ceffeb7d524fb8cfa2264651207053e7142ab4e Mon Sep 17 00:00:00 2001 From: kotb Date: Sat, 15 Mar 2025 12:05:50 +0300 Subject: [PATCH 16/74] fix orca checking wrong target list for dml --- src/backend/executor/nodeMaterial.c | 9 ++++++++- .../gpopt/translate/CTranslatorDXLToPlStmt.cpp | 13 +++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c index f9b65aca4622..77c4ea2f07fc 100644 --- a/src/backend/executor/nodeMaterial.c +++ b/src/backend/executor/nodeMaterial.c @@ -358,7 +358,14 @@ ExecInitMaterial(Material *node, EState *estate, int eflags) * index into range table, while the material may refer to the same relation as "outer" varno) * [JIRA: MPP-25365] */ - if (list_length(node->plan.targetlist) != list_length(outerPlan->targetlist)) + List *outerPlanTargetList = outerPlan->targetlist; + if (IsA(outerPlan, DML)) + { + // DML node output is located in returningList + DML *dmlPlan = (DML *) outerPlan; + outerPlanTargetList = dmlPlan->returningList; + } + if (list_length(node->plan.targetlist) != list_length(outerPlanTargetList)) elog(ERROR, "Material operator does not support projection"); outerPlanState(matstate) = ExecInitNode(outerPlan, estate, eflags); diff --git a/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp b/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp index 12b8232851e6..79ff2c652407 100644 --- a/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp +++ b/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp @@ -3634,6 +3634,14 @@ CTranslatorDXLToPlStmt::TranslateDXLCTEProducerToSharedScan( child_dxlnode, &child_context, ctxt_translation_prev_siblings); GPOS_ASSERT(NULL != child_plan && "child plan cannot be NULL"); + List *child_plan_target_list = child_plan->targetlist; + if (IsA(child_plan, DML)) + { + // DML node output is located in returningList + DML *dml_plan = (DML *) child_plan; + child_plan_target_list = dml_plan->returningList; + } + CDXLTranslationContextArray *child_contexts = GPOS_NEW(m_mp) CDXLTranslationContextArray(m_mp); child_contexts->Append(&child_context); @@ -3664,7 +3672,7 @@ CTranslatorDXLToPlStmt::TranslateDXLCTEProducerToSharedScan( // materialize does not project, so it must use the child's target list ListCell *lc_target_entry = NULL; materialize_plan->targetlist = NIL; - ForEach(lc_target_entry, child_plan->targetlist) + ForEach(lc_target_entry, child_plan_target_list) { TargetEntry *te = (TargetEntry *) lfirst(lc_target_entry); Var *var_new = gpdb::MakeVar( @@ -3682,12 +3690,13 @@ CTranslatorDXLToPlStmt::TranslateDXLCTEProducerToSharedScan( materialize_plan->nMotionNodes = child_plan->nMotionNodes; child_plan = materialize_plan; + child_plan_target_list = child_plan->targetlist; } // Targetlist mismatch leads to different tuple bindings, see #12796. // We assume targetlist's equivalence. In case of inequality one list // is a subset of another, so it safe to compare only length. - if (list_length(child_plan->targetlist) != list_length(plan->targetlist)) + if (list_length(child_plan_target_list) != list_length(plan->targetlist)) GPOS_RAISE( gpdxl::ExmaDXL, gpdxl::ExmiDXL2PlStmtConversion, GPOS_WSZ_LIT("Shared Scan and child plan targetlist mismatch.")); From e3a1a856b79167e546ef846b1048c08c9efee70b Mon Sep 17 00:00:00 2001 From: kotb Date: Sat, 15 Mar 2025 12:06:08 +0300 Subject: [PATCH 17/74] fix empty update output --- .../src/translate/CTranslatorDXLToExpr.cpp | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/backend/gporca/libgpopt/src/translate/CTranslatorDXLToExpr.cpp b/src/backend/gporca/libgpopt/src/translate/CTranslatorDXLToExpr.cpp index 3148832b9219..42a3e32d4b4e 100644 --- a/src/backend/gporca/libgpopt/src/translate/CTranslatorDXLToExpr.cpp +++ b/src/backend/gporca/libgpopt/src/translate/CTranslatorDXLToExpr.cpp @@ -272,9 +272,6 @@ CTranslatorDXLToExpr::Pexpr(const CDXLNode *dxlnode, m_pdrgpulOutputColRefs = GPOS_NEW(m_mp) ULongPtrArray(m_mp); m_pdrgpmdname = GPOS_NEW(m_mp) CMDNameArray(m_mp); - BOOL fGenerateRequiredColumns = - COperator::EopLogicalUpdate != pexpr->Pop()->Eopid(); - const ULONG length = query_output_dxlnode_array->Size(); for (ULONG ul = 0; ul < length; ul++) { @@ -292,18 +289,15 @@ CTranslatorDXLToExpr::Pexpr(const CDXLNode *dxlnode, // get its column reference from the hash map const CColRef *colref = LookupColRef(m_phmulcr, colid); - if (fGenerateRequiredColumns) - { - const ULONG ulColRefId = colref->Id(); - ULONG *pulCopy = GPOS_NEW(m_mp) ULONG(ulColRefId); - // add to the array of output column reference ids - m_pdrgpulOutputColRefs->Append(pulCopy); - - // get the column names and add it to the array of output column names - CMDName *mdname = - GPOS_NEW(m_mp) CMDName(m_mp, dxl_colref->MdName()->GetMDName()); - m_pdrgpmdname->Append(mdname); - } + const ULONG ulColRefId = colref->Id(); + ULONG *pulCopy = GPOS_NEW(m_mp) ULONG(ulColRefId); + // add to the array of output column reference ids + m_pdrgpulOutputColRefs->Append(pulCopy); + + // get the column names and add it to the array of output column names + CMDName *mdname = + GPOS_NEW(m_mp) CMDName(m_mp, dxl_colref->MdName()->GetMDName()); + m_pdrgpmdname->Append(mdname); } return pexpr; From 2d65cc1d56fdd4dfa39525379bcce57b413316e9 Mon Sep 17 00:00:00 2001 From: kotb Date: Sat, 15 Mar 2025 12:48:28 +0300 Subject: [PATCH 18/74] reorder proj lists in dml dxl plan node output is first because most of other nodes expects it fixed serializers, readers Also small cleanup of unused changes --- .../translate/CTranslatorDXLToPlStmt.cpp | 4 ++-- .../src/translate/CTranslatorExprToDXL.cpp | 19 +++---------------- .../src/operators/CDXLPhysicalDML.cpp | 4 ++-- .../src/parser/CParseHandlerPhysicalDML.cpp | 16 ++++++++-------- src/backend/optimizer/plan/planner.c | 2 -- 5 files changed, 15 insertions(+), 30 deletions(-) diff --git a/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp b/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp index 79ff2c652407..0f816df2b9d1 100644 --- a/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp +++ b/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp @@ -4192,8 +4192,8 @@ CTranslatorDXLToPlStmt::TranslateDXLDml( rte->requiredPerms |= acl_mode; m_dxl_to_plstmt_context->AddRTE(rte); - CDXLNode *project_list_dxlnode = (*dml_dxlnode)[0]; - CDXLNode *project_list_output_dxlnode = (*dml_dxlnode)[1]; + CDXLNode *project_list_output_dxlnode = (*dml_dxlnode)[0]; + CDXLNode *project_list_dxlnode = (*dml_dxlnode)[1]; CDXLNode *child_dxlnode = (*dml_dxlnode)[2]; CDXLTranslateContext child_context(m_mp, false, diff --git a/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp b/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp index 2e6a2046c986..33639b47973b 100644 --- a/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp +++ b/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp @@ -22,7 +22,6 @@ #include "gpos/common/CHashMap.h" #include "gpopt/base/CCastUtils.h" -#include "gpopt/base/CColRef.h" #include "gpopt/base/CColRefSetIter.h" #include "gpopt/base/CConstraintInterval.h" #include "gpopt/base/CUtils.h" @@ -33,7 +32,6 @@ #include "gpopt/operators/CPhysicalIndexOnlyScan.h" #include "gpopt/operators/CPhysicalMotionRandom.h" #include "gpopt/operators/CPredicateUtils.h" -#include "gpopt/search/CScheduler.h" #include "gpopt/translate/CTranslatorDXLToExpr.h" #include "gpopt/translate/CTranslatorExprToDXLUtils.h" #include "naucrates/base/CDatumBoolGPDB.h" @@ -4513,19 +4511,8 @@ CTranslatorExprToDXL::PdxlnMotion(CExpression *pexprMotion, GPOS_ASSERT(NULL != motion); // construct project list from child project list - CDXLNode *pdxlnProjListChild; - if (COperator::EopPhysicalDML == pexprChild->Pop()->Eopid() && - COperator::EopPhysicalMotionGather == pexprMotion->Pop()->Eopid()) - { - // dml nodes unlike others have output proj list in second child - GPOS_ASSERT(NULL != child_dxlnode && 2 <= child_dxlnode->Arity()); - pdxlnProjListChild = (*child_dxlnode)[1]; - } - else - { - GPOS_ASSERT(NULL != child_dxlnode && 1 <= child_dxlnode->Arity()); - pdxlnProjListChild = (*child_dxlnode)[0]; - } + GPOS_ASSERT(NULL != child_dxlnode && 1 <= child_dxlnode->Arity()); + CDXLNode *pdxlnProjListChild = (*child_dxlnode)[0]; CDXLNode *proj_list_dxlnode = CTranslatorExprToDXLUtils::PdxlnProjListFromChildProjList( @@ -5862,8 +5849,8 @@ CTranslatorExprToDXL::PdxlnDML(CExpression *pexpr, CDXLPhysicalProperties *dxl_properties = GetProperties(pexpr); pdxlnDML->SetProperties(dxl_properties); - pdxlnDML->AddChild(pdxlnPrL); pdxlnDML->AddChild(pdxlnPrLOutput); + pdxlnDML->AddChild(pdxlnPrL); pdxlnDML->AddChild(child_dxlnode); #ifdef GPOS_DEBUG diff --git a/src/backend/gporca/libnaucrates/src/operators/CDXLPhysicalDML.cpp b/src/backend/gporca/libnaucrates/src/operators/CDXLPhysicalDML.cpp index edee0f19882d..8edc89fcd00d 100644 --- a/src/backend/gporca/libnaucrates/src/operators/CDXLPhysicalDML.cpp +++ b/src/backend/gporca/libnaucrates/src/operators/CDXLPhysicalDML.cpp @@ -169,10 +169,10 @@ CDXLPhysicalDML::SerializeToDXL(CXMLSerializer *xml_serializer, CDXLTokens::GetDXLTokenStr(EdxltokenDirectDispatchInfo)); } - // serialize project list + // serialize project list for returning list (*node)[0]->SerializeToDXL(xml_serializer); - // serialize project list for returning list + // serialize project list (*node)[1]->SerializeToDXL(xml_serializer); // serialize table descriptor diff --git a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerPhysicalDML.cpp b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerPhysicalDML.cpp index 8e034dec9e1f..96ead8df8057 100644 --- a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerPhysicalDML.cpp +++ b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerPhysicalDML.cpp @@ -176,8 +176,8 @@ CParseHandlerPhysicalDML::StartElement(const XMLCh *const, // element_uri, // store child parse handlers in array this->Append(prop_parse_handler); this->Append(direct_dispatch_parse_handler); - this->Append(proj_list_parse_handler); this->Append(proj_list_output_parse_handler); + this->Append(proj_list_parse_handler); this->Append(table_descr_parse_handler); this->Append(child_parse_handler); } @@ -220,16 +220,16 @@ CParseHandlerPhysicalDML::EndElement(const XMLCh *const, // element_uri, GPOS_ASSERT(NULL != direct_dispatch_parse_handler->GetDXLDirectDispatchInfo()); - CParseHandlerProjList *proj_list_parse_handler = - dynamic_cast((*this)[2]); - GPOS_ASSERT(NULL != proj_list_parse_handler); - GPOS_ASSERT(NULL != proj_list_parse_handler->CreateDXLNode()); - CParseHandlerProjList *proj_list_output_parse_handler = - dynamic_cast((*this)[3]); + dynamic_cast((*this)[2]); GPOS_ASSERT(NULL != proj_list_output_parse_handler); GPOS_ASSERT(NULL != proj_list_output_parse_handler->CreateDXLNode()); + CParseHandlerProjList *proj_list_parse_handler = + dynamic_cast((*this)[3]); + GPOS_ASSERT(NULL != proj_list_parse_handler); + GPOS_ASSERT(NULL != proj_list_parse_handler->CreateDXLNode()); + CParseHandlerTableDescr *table_descr_parse_handler = dynamic_cast((*this)[4]); GPOS_ASSERT(NULL != table_descr_parse_handler); @@ -254,8 +254,8 @@ CParseHandlerPhysicalDML::EndElement(const XMLCh *const, // element_uri, // set statistics and physical properties CParseHandlerUtils::SetProperties(m_dxl_node, prop_parse_handler); - AddChildFromParseHandler(proj_list_parse_handler); AddChildFromParseHandler(proj_list_output_parse_handler); + AddChildFromParseHandler(proj_list_parse_handler); AddChildFromParseHandler(child_parse_handler); #ifdef GPOS_DEBUG diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 3a7dc91cc3df..52c0eda6564d 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -248,9 +248,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams) } if (result) - { return result; - } } /* From 096ab3494153f0ffef441c713a737113473e3b55 Mon Sep 17 00:00:00 2001 From: kotb Date: Sat, 15 Mar 2025 16:05:39 +0300 Subject: [PATCH 19/74] check output existence by columns usage rather than by required columns --- .../src/translate/CTranslatorExprToDXL.cpp | 44 ++++++++----------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp b/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp index 33639b47973b..705039fc126c 100644 --- a/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp +++ b/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp @@ -5809,42 +5809,34 @@ CTranslatorExprToDXL::PdxlnDML(CExpression *pexpr, // project list CDXLNode *pdxlnPrL = PdxlnProjList(NULL, pdrgpcrSource); - // configure output project list if output was required + // configure output project list for used columns CDXLNode *pdxlnPrLOutput; - if (pexpr->Prpp()->PcrsRequired()->Size() > 0) - { - ULongPtrArray *indexes = GPOS_NEW(m_mp) ULongPtrArray(m_mp); + ULongPtrArray *usedColsIndexes = GPOS_NEW(m_mp) ULongPtrArray(m_mp); - for (ULONG outputColIndex = 0; outputColIndex < pdrgpcrOutput->Size(); - outputColIndex++) - { - CColRef *colref = (*pdrgpcrOutput)[outputColIndex]; - if (colref->GetUsage(true, true) == CColRef::EUsed) - { - indexes->Append(GPOS_NEW(m_mp) ULONG(outputColIndex)); - } - } - - if (pdrgpcrOutput->Size() == indexes->Size()) - { - pdxlnPrLOutput = PdxlnProjList(NULL, pdrgpcrOutput); - } - else + for (ULONG outputColIndex = 0; outputColIndex < pdrgpcrOutput->Size(); + outputColIndex++) + { + CColRef *colref = (*pdrgpcrOutput)[outputColIndex]; + if (colref->GetUsage(true, true) == CColRef::EUsed) { - CColRefArray *reducedOutput = - pdrgpcrOutput->CreateReducedArray(indexes); - pdxlnPrLOutput = PdxlnProjList(NULL, reducedOutput); - reducedOutput->Release(); + usedColsIndexes->Append(GPOS_NEW(m_mp) ULONG(outputColIndex)); } + } - indexes->Release(); + if (pdrgpcrOutput->Size() == usedColsIndexes->Size()) + { + pdxlnPrLOutput = PdxlnProjList(NULL, pdrgpcrOutput); } else { - pdxlnPrLOutput = GPOS_NEW(m_mp) - CDXLNode(m_mp, GPOS_NEW(m_mp) CDXLScalarProjList(m_mp)); + CColRefArray *reducedOutput = + pdrgpcrOutput->CreateReducedArray(usedColsIndexes); + pdxlnPrLOutput = PdxlnProjList(NULL, reducedOutput); + reducedOutput->Release(); } + usedColsIndexes->Release(); + CDXLNode *pdxlnDML = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopDML); CDXLPhysicalProperties *dxl_properties = GetProperties(pexpr); pdxlnDML->SetProperties(dxl_properties); From 1a134eff6126dec9d34c30c17ccc1fa51db29936 Mon Sep 17 00:00:00 2001 From: kotb Date: Sat, 15 Mar 2025 16:20:50 +0300 Subject: [PATCH 20/74] Dont require distribution only for DML SELECT on table with no columns is accepted but RETURNING cannot have zero columns. The only way to output from DML node is by using RETURNING. So to require output for SELECT with zero columns tighten condition for only DML operations --- src/backend/gporca/libgpopt/src/base/CQueryContext.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp b/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp index d0868757105f..3c9a6885a22f 100644 --- a/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp +++ b/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp @@ -211,9 +211,11 @@ CQueryContext::PqcGenerate(CMemoryPool *mp, CExpression *pexpr, CDistributionSpec *pds = NULL; - // Dont require distribution on empty output or CTAS. Otherwise the - // distribution requirement is Singleton. - if (pdrgpulQueryOutputColRefId->Size() == 0 || CUtils::FCTAS(pexpr->Pop())) + // Dont require distribution for DML with empty output or CTAS. + // Otherwise the distribution requirement is Singleton. + if ((CUtils::FLogicalDML(pexpr->Pop()) && + pdrgpulQueryOutputColRefId->Size() == 0) || + CUtils::FCTAS(pexpr->Pop())) { pds = GPOS_NEW(mp) CDistributionSpecAny(COperator::EopSentinel); } From f2d3a6cfd6922ee53346acd3f6acf1c8b2433f8a Mon Sep 17 00:00:00 2001 From: kotb Date: Sat, 15 Mar 2025 23:30:59 +0300 Subject: [PATCH 21/74] fix column names in returning output --- .../src/translate/CTranslatorExprToDXL.cpp | 68 +++++++++---------- 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp b/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp index 705039fc126c..56897dde0eb7 100644 --- a/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp +++ b/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp @@ -361,47 +361,43 @@ CTranslatorExprToDXL::PdxlnTranslate(CExpression *pexpr, &ulNonGatherMotions, &fDML, true /*fRemap*/, true /*fRoot*/); - if (fDML) - { - pdrgpdsBaseTables->Release(); - return dxlnode; - } - - CDXLNode *pdxlnPrL = (*dxlnode)[0]; - GPOS_ASSERT(EdxlopScalarProjectList == - pdxlnPrL->GetOperator()->GetDXLOperator()); - const ULONG length = pdrgpmdname->Size(); - GPOS_ASSERT(length == colref_array->Size()); - GPOS_ASSERT(length == pdxlnPrL->Arity()); - for (ULONG ul = 0; ul < length; ul++) - { - // desired output column name - CMDName *mdname = - GPOS_NEW(m_mp) CMDName(m_mp, (*pdrgpmdname)[ul]->GetMDName()); - - // get the old project element for the ColId - CDXLNode *pdxlnPrElOld = (*pdxlnPrL)[ul]; - CDXLScalarProjElem *pdxlopPrElOld = - CDXLScalarProjElem::Cast(pdxlnPrElOld->GetOperator()); - GPOS_ASSERT(1 == pdxlnPrElOld->Arity()); - CDXLNode *child_dxlnode = (*pdxlnPrElOld)[0]; - const ULONG colid = pdxlopPrElOld->Id(); - // create a new project element node with the col id and new column name - // and add the scalar child - CDXLNode *pdxlnPrElNew = GPOS_NEW(m_mp) CDXLNode( - m_mp, GPOS_NEW(m_mp) CDXLScalarProjElem(m_mp, colid, mdname)); - child_dxlnode->AddRef(); - pdxlnPrElNew->AddChild(child_dxlnode); + if (length > 0) + { + CDXLNode *pdxlnPrL = (*dxlnode)[0]; + GPOS_ASSERT(EdxlopScalarProjectList == + pdxlnPrL->GetOperator()->GetDXLOperator()); - // replace the project element - pdxlnPrL->ReplaceChild(ul, pdxlnPrElNew); + GPOS_ASSERT(length == colref_array->Size()); + GPOS_ASSERT(length == pdxlnPrL->Arity()); + for (ULONG ul = 0; ul < length; ul++) + { + // desired output column name + CMDName *mdname = + GPOS_NEW(m_mp) CMDName(m_mp, (*pdrgpmdname)[ul]->GetMDName()); + + // get the old project element for the ColId + CDXLNode *pdxlnPrElOld = (*pdxlnPrL)[ul]; + CDXLScalarProjElem *pdxlopPrElOld = + CDXLScalarProjElem::Cast(pdxlnPrElOld->GetOperator()); + GPOS_ASSERT(1 == pdxlnPrElOld->Arity()); + CDXLNode *child_dxlnode = (*pdxlnPrElOld)[0]; + const ULONG colid = pdxlopPrElOld->Id(); + + // create a new project element node with the col id and new column name + // and add the scalar child + CDXLNode *pdxlnPrElNew = GPOS_NEW(m_mp) CDXLNode( + m_mp, GPOS_NEW(m_mp) CDXLScalarProjElem(m_mp, colid, mdname)); + child_dxlnode->AddRef(); + pdxlnPrElNew->AddChild(child_dxlnode); + + // replace the project element + pdxlnPrL->ReplaceChild(ul, pdxlnPrElNew); + } } - - - if (0 == ulNonGatherMotions) + if (!fDML && 0 == ulNonGatherMotions) { CTranslatorExprToDXLUtils::SetDirectDispatchInfo( m_mp, m_pmda, dxlnode, pexpr, pdrgpdsBaseTables); From 64b98d3a75acd6cb2bfe02f65a4b87ffb96da791 Mon Sep 17 00:00:00 2001 From: kotb Date: Sun, 16 Mar 2025 00:05:45 +0300 Subject: [PATCH 22/74] linter fixes --- src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp | 5 +++-- src/backend/gporca/libgpopt/src/base/CUtils.cpp | 2 +- .../gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp b/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp index 66f8e0e3985a..9405432b5a0b 100644 --- a/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp +++ b/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp @@ -1176,8 +1176,9 @@ CTranslatorQueryToDXL::ProcessReturningList(CDXLNode *dml_dxlnode, m_query_level, m_query->resultRelation, table_descr); dml_dxlnode = TranslateTargetListToDXLProject( - m_query->returningList, dml_dxlnode, sort_group_attno_to_colid_mapping, - output_attno_to_colid_mapping, m_query->groupClause); + m_query->returningList, dml_dxlnode, + sort_group_attno_to_colid_mapping, output_attno_to_colid_mapping, + m_query->groupClause); // this array is filled earlier with target list and was used to get colids by their indices earlier // now fill it with what will truly be returned diff --git a/src/backend/gporca/libgpopt/src/base/CUtils.cpp b/src/backend/gporca/libgpopt/src/base/CUtils.cpp index c83efcb396e0..99bcb4b1e520 100644 --- a/src/backend/gporca/libgpopt/src/base/CUtils.cpp +++ b/src/backend/gporca/libgpopt/src/base/CUtils.cpp @@ -3286,7 +3286,7 @@ CUtils::FCTAS(COperator *pop) { return false; } - + CLogicalInsert *popInsert = CLogicalInsert::PopConvert(pop); return IMDId::EmdidGPDBCtas == popInsert->Ptabdesc()->MDId()->MdidType(); diff --git a/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp b/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp index 56897dde0eb7..3ddaca9841c3 100644 --- a/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp +++ b/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp @@ -5810,7 +5810,7 @@ CTranslatorExprToDXL::PdxlnDML(CExpression *pexpr, ULongPtrArray *usedColsIndexes = GPOS_NEW(m_mp) ULongPtrArray(m_mp); for (ULONG outputColIndex = 0; outputColIndex < pdrgpcrOutput->Size(); - outputColIndex++) + outputColIndex++) { CColRef *colref = (*pdrgpcrOutput)[outputColIndex]; if (colref->GetUsage(true, true) == CColRef::EUsed) From 070153964f35d475e606be17a2d7ab2b7918e78f Mon Sep 17 00:00:00 2001 From: kotb Date: Sun, 16 Mar 2025 00:39:59 +0300 Subject: [PATCH 23/74] revert changind index of checked proj list in hash join --- src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp b/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp index 0f816df2b9d1..7feec1fc6cb0 100644 --- a/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp +++ b/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp @@ -2058,9 +2058,7 @@ CTranslatorDXLToPlStmt::TranslateDXLHash( // create a reference to each entry in the child project list to create the target list of // the hash node - Edxlopid dxl_op_id = dxlnode->GetOperator()->GetDXLOperator(); - CDXLNode *project_list_dxlnode = - (*dxlnode)[EdxlopPhysicalDML == dxl_op_id ? 1 : 0]; + CDXLNode *project_list_dxlnode = (*dxlnode)[0]; List *target_list = TranslateDXLProjectListToHashTargetList( project_list_dxlnode, &dxl_translate_ctxt, output_context); From 89ca77992ca18a77eefda215a148fb89009d1036 Mon Sep 17 00:00:00 2001 From: kotb Date: Sun, 16 Mar 2025 01:06:53 +0300 Subject: [PATCH 24/74] adapt regress orca expected --- .../regress/expected/bfv_dml_optimizer.out | 23 ++- .../expected/explain_analyze_optimizer.out | 12 +- .../expected/subselect_gp_optimizer.out | 127 ++++++-------- .../expected/updatable_views_optimizer.out | 33 ++-- .../regress/expected/update_gp_optimizer.out | 29 ++-- .../expected/with_clause_optimizer.out | 163 +++++++++--------- 6 files changed, 181 insertions(+), 206 deletions(-) diff --git a/src/test/regress/expected/bfv_dml_optimizer.out b/src/test/regress/expected/bfv_dml_optimizer.out index c51ca794bb9e..1c5552282076 100644 --- a/src/test/regress/expected/bfv_dml_optimizer.out +++ b/src/test/regress/expected/bfv_dml_optimizer.out @@ -394,19 +394,18 @@ explain delete from foo using bar where foo.a = bar.a returning foo.*; QUERY PLAN ----------------------------------------------------------------------------------------------------------- Gather Motion 3:1 (slice3; segments: 3) (cost=0.00..862.18 rows=10 width=8) - -> Result (cost=0.00..862.18 rows=4 width=8) - -> Delete (cost=0.00..862.18 rows=4 width=8) - -> Result (cost=0.00..862.00 rows=4 width=14) - -> Explicit Redistribute Motion 3:3 (slice2; segments: 3) (cost=0.00..862.00 rows=4 width=10) - -> Hash Join (cost=0.00..862.00 rows=4 width=10) - Hash Cond: (foo.a = bar.a) - -> Redistribute Motion 3:3 (slice1; segments: 3) (cost=0.00..431.00 rows=4 width=14) - Hash Key: foo.a - -> Seq Scan on foo (cost=0.00..431.00 rows=4 width=14) - -> Hash (cost=431.00..431.00 rows=4 width=4) - -> Seq Scan on bar (cost=0.00..431.00 rows=4 width=4) + -> Delete (cost=0.00..862.18 rows=4 width=8) + -> Result (cost=0.00..862.00 rows=4 width=14) + -> Explicit Redistribute Motion 3:3 (slice2; segments: 3) (cost=0.00..862.00 rows=4 width=10) + -> Hash Join (cost=0.00..862.00 rows=4 width=10) + Hash Cond: (foo.a = bar.a) + -> Redistribute Motion 3:3 (slice1; segments: 3) (cost=0.00..431.00 rows=4 width=14) + Hash Key: foo.a + -> Seq Scan on foo (cost=0.00..431.00 rows=4 width=14) + -> Hash (cost=431.00..431.00 rows=4 width=4) + -> Seq Scan on bar (cost=0.00..431.00 rows=4 width=4) Optimizer: Pivotal Optimizer (GPORCA) -(13 rows) +(12 rows) delete from foo using bar where foo.a = bar.a returning foo.*; a | b diff --git a/src/test/regress/expected/explain_analyze_optimizer.out b/src/test/regress/expected/explain_analyze_optimizer.out index 4d272391e8b1..e36f5ab363b4 100644 --- a/src/test/regress/expected/explain_analyze_optimizer.out +++ b/src/test/regress/expected/explain_analyze_optimizer.out @@ -108,8 +108,8 @@ WITH cte AS ( ) SELECT * FROM cte; QUERY PLAN ------------------------------------------------------------------------------------ - Gather Motion 3:1 (slice1; segments: 3) (actual rows=5 loops=1) - -> Result (actual rows=3 loops=1) + Result (actual rows=5 loops=1) + -> Gather Motion 3:1 (slice1; segments: 3) (actual rows=5 loops=1) -> Insert (actual rows=3 loops=1) -> Result (actual rows=3 loops=1) -> Result (actual rows=3 loops=1) @@ -129,8 +129,8 @@ WITH cte AS ( ) SELECT * FROM cte; QUERY PLAN --------------------------------------------------------------------------------- - Gather Motion 3:1 (slice1; segments: 3) (actual rows=5 loops=1) - -> Result (actual rows=3 loops=1) + Result (actual rows=5 loops=1) + -> Gather Motion 3:1 (slice1; segments: 3) (actual rows=5 loops=1) -> Update (actual rows=3 loops=1) -> Split (actual rows=6 loops=1) -> Result (actual rows=3 loops=1) @@ -150,8 +150,8 @@ WITH cte AS ( ) SELECT * FROM cte; QUERY PLAN --------------------------------------------------------------------------------- - Gather Motion 3:1 (slice1; segments: 3) (actual rows=5 loops=1) - -> Result (actual rows=3 loops=1) + Result (actual rows=5 loops=1) + -> Gather Motion 3:1 (slice1; segments: 3) (actual rows=5 loops=1) -> Delete (actual rows=3 loops=1) -> Result (actual rows=3 loops=1) -> Seq Scan on with_dml (actual rows=3 loops=1) diff --git a/src/test/regress/expected/subselect_gp_optimizer.out b/src/test/regress/expected/subselect_gp_optimizer.out index 81030eb75022..1bf71d2fb1c6 100644 --- a/src/test/regress/expected/subselect_gp_optimizer.out +++ b/src/test/regress/expected/subselect_gp_optimizer.out @@ -3669,24 +3669,24 @@ select i from t2 where exists (select i from cte); QUERY PLAN -------------------------------------------------------------------------------------------------- - Gather Motion 3:1 (slice4; segments: 3) - -> Nested Loop Semi Join + Gather Motion 1:1 (slice4; segments: 1) + -> Nested Loop Join Filter: true - -> Seq Scan on t2 t2_1 - -> Materialize - -> Broadcast Motion 1:3 (slice3; segments: 1) - -> Limit - -> Gather Motion 3:1 (slice2; segments: 3) + -> Result + Filter: ((count()) > '0'::bigint) + -> Aggregate + -> Gather Motion 3:1 (slice3; segments: 3) + -> Delete -> Result - -> Result - -> Delete - -> Result - -> Hash Join - Hash Cond: (t1.i = t2.i) - -> Seq Scan on t1 - -> Hash - -> Broadcast Motion 3:3 (slice1; segments: 3) - -> Seq Scan on t2 + -> Hash Join + Hash Cond: (t1.i = t2_1.i) + -> Seq Scan on t1 + -> Hash + -> Broadcast Motion 3:3 (slice2; segments: 3) + -> Seq Scan on t2 t2_1 + -> Materialize + -> Gather Motion 3:1 (slice1; segments: 3) + -> Seq Scan on t2 Optimizer: Pivotal Optimizer (GPORCA) (19 rows) @@ -3740,18 +3740,17 @@ where 0 = (select i from cte); Assert Cond: ((row_number() OVER (?)) = 1) -> WindowAgg -> Gather Motion 3:1 (slice3; segments: 3) - -> Result - -> Update - -> Redistribute Motion 3:3 (slice2; segments: 3) - Hash Key: t1.i - -> Split - -> Result - -> Seq Scan on t1 + -> Update + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: t1.i + -> Split + -> Result + -> Seq Scan on t1 -> Materialize -> Gather Motion 3:1 (slice1; segments: 3) -> Seq Scan on t2 Optimizer: Pivotal Optimizer (GPORCA) -(20 rows) +(19 rows) with cte as (update t1 set i = 0 @@ -3793,7 +3792,7 @@ where t2.i in (select i from cte where t2.i = cte.i and cte.i > 0) order by i; QUERY PLAN -------------------------------------------------------------------------------------------------- - Gather Motion 3:1 (slice2; segments: 3) + Gather Motion 3:1 (slice1; segments: 3) Merge Key: t2.i -> Sort Sort Key: t2.i @@ -3802,17 +3801,14 @@ order by i; -> Seq Scan on t2 Filter: (i > 0) -> Hash - -> Redistribute Motion 3:3 (slice1; segments: 3) - Hash Key: generate_series.generate_series - -> Result - Filter: (generate_series.generate_series > 0) + -> Result + Filter: (generate_series.generate_series > 0) + -> Insert -> Result - -> Insert - -> Result - -> Result - -> Function Scan on generate_series + -> Result + -> Function Scan on generate_series Optimizer: Pivotal Optimizer (GPORCA) -(19 rows) +(16 rows) with cte as (insert into t1 @@ -3849,7 +3845,7 @@ where t_repl.i in (select i from cte where t_repl.i = cte.i and cte.i > 0) order by i; QUERY PLAN -------------------------------------------------------------------------------------------------- - Gather Motion 3:1 (slice2; segments: 3) + Gather Motion 3:1 (slice1; segments: 3) Merge Key: t_repl.i -> Sort Sort Key: t_repl.i @@ -3859,17 +3855,14 @@ order by i; -> Seq Scan on t_repl Filter: (i > 0) -> Hash - -> Redistribute Motion 3:3 (slice1; segments: 3) - Hash Key: generate_series.generate_series, generate_series.generate_series - -> Result - Filter: (generate_series.generate_series > 0) + -> Result + Filter: (generate_series.generate_series > 0) + -> Insert -> Result - -> Insert - -> Result - -> Result - -> Function Scan on generate_series + -> Result + -> Function Scan on generate_series Optimizer: Pivotal Optimizer (GPORCA) -(20 rows) +(17 rows) with cte as (insert into t1 @@ -3906,7 +3899,7 @@ where t2.i in (select i from cte join t3 using (i) where t3.j = t2.i) order by i; QUERY PLAN -------------------------------------------------------------------------------------------------- - Gather Motion 3:1 (slice3; segments: 3) + Gather Motion 3:1 (slice2; segments: 3) Merge Key: t2.i -> Sort Sort Key: t2.i @@ -3915,20 +3908,17 @@ order by i; -> Seq Scan on t2 Filter: (NOT (i IS NULL)) -> Hash - -> Redistribute Motion 3:3 (slice2; segments: 3) - Hash Key: generate_series.generate_series - -> Hash Join - Hash Cond: (generate_series.generate_series = t3.i) + -> Hash Join + Hash Cond: (generate_series.generate_series = t3.i) + -> Insert -> Result - -> Insert - -> Result - -> Result - -> Function Scan on generate_series - -> Hash - -> Broadcast Motion 3:3 (slice1; segments: 3) - -> Seq Scan on t3 + -> Result + -> Function Scan on generate_series + -> Hash + -> Broadcast Motion 3:3 (slice1; segments: 3) + -> Seq Scan on t3 Optimizer: Pivotal Optimizer (GPORCA) -(22 rows) +(19 rows) with cte as (insert into t1 @@ -3959,7 +3949,7 @@ where t_repl.i in (select i from cte join t3 using (i) where t3.j = t_repl.i) order by i; QUERY PLAN -------------------------------------------------------------------------------------------------- - Gather Motion 3:1 (slice3; segments: 3) + Gather Motion 3:1 (slice2; segments: 3) Merge Key: t_repl.i -> Sort Sort Key: t_repl.i @@ -3969,20 +3959,17 @@ order by i; -> Seq Scan on t_repl Filter: (NOT (i IS NULL)) -> Hash - -> Redistribute Motion 3:3 (slice2; segments: 3) - Hash Key: t3.j, generate_series.generate_series - -> Hash Join - Hash Cond: (generate_series.generate_series = t3.i) + -> Hash Join + Hash Cond: (generate_series.generate_series = t3.i) + -> Insert -> Result - -> Insert - -> Result - -> Result - -> Function Scan on generate_series - -> Hash - -> Broadcast Motion 3:3 (slice1; segments: 3) - -> Seq Scan on t3 + -> Result + -> Function Scan on generate_series + -> Hash + -> Broadcast Motion 3:3 (slice1; segments: 3) + -> Seq Scan on t3 Optimizer: Pivotal Optimizer (GPORCA) -(23 rows) +(20 rows) with cte as (insert into t1 diff --git a/src/test/regress/expected/updatable_views_optimizer.out b/src/test/regress/expected/updatable_views_optimizer.out index ae34c850cd95..7252187a3c56 100644 --- a/src/test/regress/expected/updatable_views_optimizer.out +++ b/src/test/regress/expected/updatable_views_optimizer.out @@ -914,14 +914,13 @@ UPDATE rw_view1 v SET bb='Updated row 2' WHERE rw_view1_aa(v)=2 QUERY PLAN ------------------------------------------ Gather Motion 3:1 (slice1; segments: 3) - -> Result - -> Update - -> Split - -> Result - -> Index Scan using base_tbl_pkey on base_tbl - Index Cond: (a = 2) + -> Update + -> Split + -> Result + -> Index Scan using base_tbl_pkey on base_tbl + Index Cond: (a = 2) Optimizer: Pivotal Optimizer (GPORCA) -(8 rows) +(7 rows) DROP TABLE base_tbl CASCADE; NOTICE: drop cascades to 2 other objects @@ -1116,18 +1115,16 @@ EXPLAIN (verbose, costs off) UPDATE rw_view1 SET b = b + 1 RETURNING *; ------------------------------------------------------------------------------------------- Gather Motion 3:1 (slice1; segments: 3) Output: base_tbl.a, base_tbl.b - -> Result - Output: base_tbl.a, base_tbl.b - -> Update - Output: base_tbl.a, base_tbl.b, (DMLAction), base_tbl.ctid - -> Split - Output: base_tbl.a, base_tbl.b, base_tbl.ctid, base_tbl.gp_segment_id, DMLAction - -> Result - Output: base_tbl.a, base_tbl.b, (base_tbl.b + 1), base_tbl.ctid, base_tbl.gp_segment_id - -> Seq Scan on public.base_tbl - Output: base_tbl.a, base_tbl.b, base_tbl.ctid, base_tbl.gp_segment_id + -> Update + Output: base_tbl.a, base_tbl.b, (DMLAction), base_tbl.ctid + -> Split + Output: base_tbl.a, base_tbl.b, base_tbl.ctid, base_tbl.gp_segment_id, DMLAction + -> Result + Output: base_tbl.a, base_tbl.b, (base_tbl.b + 1), base_tbl.ctid, base_tbl.gp_segment_id + -> Seq Scan on public.base_tbl + Output: base_tbl.a, base_tbl.b, base_tbl.ctid, base_tbl.gp_segment_id Optimizer: Pivotal Optimizer (GPORCA) -(14 rows) +(12 rows) UPDATE rw_view1 SET b = b + 1 RETURNING *; a | b diff --git a/src/test/regress/expected/update_gp_optimizer.out b/src/test/regress/expected/update_gp_optimizer.out index fe27f93e5fc5..d0048a3fa5f6 100644 --- a/src/test/regress/expected/update_gp_optimizer.out +++ b/src/test/regress/expected/update_gp_optimizer.out @@ -258,25 +258,20 @@ WITH CTE AS (DELETE FROM t1 RETURNING *) SELECT count(*) AS a FROM t_strewn JOIN cte USING (i); QUERY PLAN --------------------------------------------------------------------------- - Gather Motion 1:1 (slice4; segments: 1) + Gather Motion 1:1 (slice3; segments: 1) -> Aggregate - -> Gather Motion 3:1 (slice3; segments: 3) - -> Aggregate - -> Hash Join - Hash Cond: (t_strewn.i = "outer".ColRef_0049) - -> Redistribute Motion 3:3 (slice1; segments: 3) - Hash Key: t_strewn.i - -> Seq Scan on t_strewn - -> Hash - -> Redistribute Motion 3:3 (slice2; segments: 3) - Hash Key: "outer".ColRef_0049 - -> Result - -> Result - -> Delete - -> Result - -> Seq Scan on t1 + -> Gather Motion 3:1 (slice2; segments: 3) + -> Hash Join + Hash Cond: (t_strewn.i = "outer".ColRef_0045) + -> Redistribute Motion 3:3 (slice1; segments: 3) + Hash Key: t_strewn.i + -> Seq Scan on t_strewn + -> Hash + -> Delete + -> Result + -> Seq Scan on t1 Optimizer: Pivotal Optimizer (GPORCA) -(18 rows) +(13 rows) WITH CTE AS (DELETE FROM t1 RETURNING *) SELECT count(*) AS a FROM t_strewn JOIN cte USING (i); diff --git a/src/test/regress/expected/with_clause_optimizer.out b/src/test/regress/expected/with_clause_optimizer.out index c92f94e37418..889f71182d9f 100644 --- a/src/test/regress/expected/with_clause_optimizer.out +++ b/src/test/regress/expected/with_clause_optimizer.out @@ -2309,13 +2309,12 @@ with cte as ( -> Aggregate -> Result Filter: (generate_series.generate_series > 2) - -> Result - -> Insert + -> Insert + -> Result -> Result - -> Result - -> Function Scan on generate_series + -> Function Scan on generate_series Optimizer: Pivotal Optimizer (GPORCA) -(12 rows) +(11 rows) with cte as ( insert into with_dml select i, i * 100 from generate_series(1,5) i @@ -2345,11 +2344,10 @@ with cte as ( -> Sequence -> Shared Scan (share slice:id 5:0) -> Materialize - -> Result - -> Insert + -> Insert + -> Result -> Result - -> Result - -> Function Scan on generate_series + -> Function Scan on generate_series -> Redistribute Motion 1:3 (slice4; segments: 1) -> Aggregate -> Gather Motion 3:1 (slice3; segments: 3) @@ -2364,7 +2362,7 @@ with cte as ( -> Materialize -> Shared Scan (share slice:id 3:0) Optimizer: Pivotal Optimizer (GPORCA) -(23 rows) +(22 rows) explain (costs off) with cte as ( @@ -2377,11 +2375,10 @@ with cte as ( -> Sequence -> Shared Scan (share slice:id 4:0) -> Materialize - -> Result - -> Update - -> Split - -> Result - -> Seq Scan on with_dml + -> Update + -> Split + -> Result + -> Seq Scan on with_dml -> Redistribute Motion 1:3 (slice3; segments: 1) -> Aggregate -> Nested Loop @@ -2394,7 +2391,7 @@ with cte as ( -> Gather Motion 3:1 (slice1; segments: 3) -> Shared Scan (share slice:id 1:0) Optimizer: Pivotal Optimizer (GPORCA) -(21 rows) +(20 rows) explain (costs off) with cte as ( @@ -2407,11 +2404,10 @@ with cte as ( -> Sequence -> Shared Scan (share slice:id 4:0) -> Materialize - -> Result - -> Delete - -> Result - -> Seq Scan on with_dml - Filter: (i > 0) + -> Delete + -> Result + -> Seq Scan on with_dml + Filter: (i > 0) -> Redistribute Motion 1:3 (slice3; segments: 1) -> Aggregate -> Nested Loop @@ -2424,7 +2420,7 @@ with cte as ( -> Gather Motion 3:1 (slice1; segments: 3) -> Shared Scan (share slice:id 1:0) Optimizer: Pivotal Optimizer (GPORCA) -(21 rows) +(20 rows) -- Greenplum fails to execute SELECT INTO and CREATE TABLE AS statements, whose -- queries contain modifying CTEs, because Greenplum cannot have two writer @@ -2485,12 +2481,11 @@ with cte as ( ------------------------------------------------------ Explicit Gather Motion 3:1 (slice1; segments: 3) -> Aggregate - -> Result - -> Insert - -> Result - -> Function Scan on generate_series + -> Insert + -> Result + -> Function Scan on generate_series Optimizer: Pivotal Optimizer (GPORCA) -(7 rows) +(6 rows) with cte as ( insert into with_dml_dr @@ -2564,9 +2559,9 @@ with cte as ( ------------------------------------------------------ Explicit Gather Motion 3:1 (slice1; segments: 3) Merge Key: generate_series.generate_series - -> Sort - Sort Key: generate_series.generate_series - -> Result + -> Result + -> Sort + Sort Key: generate_series.generate_series -> Insert -> Result -> Function Scan on generate_series @@ -2609,14 +2604,13 @@ with cte as ( -> Aggregate -> Hash Join Hash Cond: (generate_series.generate_series = t_repl.i) - -> Result - -> Insert - -> Result - -> Function Scan on generate_series + -> Insert + -> Result + -> Function Scan on generate_series -> Hash -> Seq Scan on t_repl Optimizer: Pivotal Optimizer (GPORCA) -(11 rows) +(10 rows) with cte as ( insert into with_dml_dr @@ -2791,15 +2785,14 @@ select count(*) from cte join -> Hash Join Hash Cond: (generate_series.generate_series = generate_series_1.generate_series) -> Result - -> Result - -> Insert - -> Result - -> Function Scan on generate_series + -> Insert + -> Result + -> Function Scan on generate_series -> Hash -> Result -> Function Scan on generate_series generate_series_1 Optimizer: Pivotal Optimizer (GPORCA) -(15 rows) +(14 rows) with cte as ( insert into with_dml_dr @@ -2839,14 +2832,13 @@ with cte as ( -> Hash Join Hash Cond: (generate_series.generate_series = t_hashed.i) -> Result - -> Result - -> Insert - -> Result - -> Function Scan on generate_series + -> Insert + -> Result + -> Function Scan on generate_series -> Hash -> Seq Scan on t_hashed Optimizer: Pivotal Optimizer (GPORCA) -(14 rows) +(13 rows) with cte as ( insert into with_dml_dr @@ -2873,14 +2865,13 @@ with cte as ( -> Hash Left Join Hash Cond: (generate_series.generate_series = t_hashed.i) -> Result - -> Result - -> Insert - -> Result - -> Function Scan on generate_series + -> Insert + -> Result + -> Function Scan on generate_series -> Hash -> Seq Scan on t_hashed Optimizer: Pivotal Optimizer (GPORCA) -(14 rows) +(13 rows) with cte as ( insert into with_dml_dr @@ -2907,16 +2898,15 @@ with cte as ( -> Hash Join Hash Cond: (generate_series.generate_series = t_strewn.i) -> Result - -> Result - -> Insert - -> Result - -> Function Scan on generate_series + -> Insert + -> Result + -> Function Scan on generate_series -> Hash -> Redistribute Motion 3:3 (slice1; segments: 3) Hash Key: t_strewn.i -> Seq Scan on t_strewn Optimizer: Pivotal Optimizer (GPORCA) -(16 rows) +(15 rows) with cte as ( insert into with_dml_dr @@ -2943,16 +2933,15 @@ with cte as ( -> Hash Left Join Hash Cond: (generate_series.generate_series = t_strewn.i) -> Result - -> Result - -> Insert - -> Result - -> Function Scan on generate_series + -> Insert + -> Result + -> Function Scan on generate_series -> Hash -> Redistribute Motion 3:3 (slice1; segments: 3) Hash Key: t_strewn.i -> Seq Scan on t_strewn Optimizer: Pivotal Optimizer (GPORCA) -(16 rows) +(15 rows) with cte as ( insert into with_dml_dr @@ -3058,18 +3047,30 @@ with cte as ( ) select count(*) from cte a join cte b using (i); QUERY PLAN ------------------------------------------------------------------------------ - Explicit Gather Motion 3:1 (slice1; segments: 3) - -> Aggregate - -> Hash Join - Hash Cond: (share0_ref2.i = share0_ref1.i) - -> Shared Scan (share slice:id 1:0) - -> Hash - -> Shared Scan (share slice:id 1:0) - -> Materialize - -> Insert on with_dml_dr - -> Function Scan on generate_series i - Optimizer: Postgres query optimizer -(11 rows) + Gather Motion 3:1 (slice5; segments: 3) + -> Sequence + -> Shared Scan (share slice:id 5:0) + -> Materialize + -> Result + One-Time Filter: (gp_execution_segment() = 1) + -> Insert + -> Result + -> Function Scan on generate_series + -> Redistribute Motion 1:3 (slice4; segments: 1) + -> Aggregate + -> Gather Motion 3:1 (slice3; segments: 3) + -> Aggregate + -> Hash Join + Hash Cond: (share0_ref3.i = share0_ref2.i) + -> Redistribute Motion 3:3 (slice1; segments: 3) + Hash Key: share0_ref3.i + -> Shared Scan (share slice:id 1:0) + -> Hash + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: share0_ref2.i + -> Shared Scan (share slice:id 2:0) + Optimizer: Pivotal Optimizer (GPORCA) +(23 rows) with cte as ( insert into with_dml_dr @@ -3179,16 +3180,14 @@ order by 1; -> HashAggregate Group Key: generate_series.generate_series -> Result - One-Time Filter: (gp_execution_segment() = 2) - -> Result + One-Time Filter: (gp_execution_segment() = 1) + -> Insert -> Result - -> Insert - -> Result - -> Function Scan on generate_series + -> Function Scan on generate_series -> Hash -> Seq Scan on t1 Optimizer: Pivotal Optimizer (GPORCA) -(22 rows) +(20 rows) with cte as ( insert into with_dml_dr @@ -3236,13 +3235,11 @@ order by 1; Group Key: generate_series.generate_series -> Result One-Time Filter: (gp_execution_segment() = 0) - -> Result + -> Insert -> Result - -> Insert - -> Result - -> Function Scan on generate_series + -> Function Scan on generate_series Optimizer: Pivotal Optimizer (GPORCA) -(25 rows) +(23 rows) with cte as ( insert into with_dml_dr From eeeb8d9872cc9dd84a6fc905fdad8b903f93194f Mon Sep 17 00:00:00 2001 From: kotb Date: Sun, 16 Mar 2025 01:14:50 +0300 Subject: [PATCH 25/74] divide "with" regress test to planner and orca expectance files --- src/test/regress/expected/with.out | 2 - src/test/regress/expected/with_optimizer.out | 2411 ++++++++++++++++++ src/test/regress/sql/with.sql | 2 - 3 files changed, 2411 insertions(+), 4 deletions(-) create mode 100644 src/test/regress/expected/with_optimizer.out diff --git a/src/test/regress/expected/with.out b/src/test/regress/expected/with.out index f65239de1e71..029f2910300c 100644 --- a/src/test/regress/expected/with.out +++ b/src/test/regress/expected/with.out @@ -2213,7 +2213,6 @@ DROP TABLE IF EXISTS t1; NOTICE: table "t1" does not exist, skipping --end_ignore CREATE TABLE t1 (c1 int, c2 int) DISTRIBUTED RANDOMLY; -SET optimizer = off; EXPLAIN (VERBOSE, COSTS OFF) WITH cte1 AS ( INSERT INTO t1 VALUES ( 1, 2 ) RETURNING * @@ -2262,7 +2261,6 @@ SELECT * FROM cte1 a JOIN cte1 b USING (c1); (1 row) DROP TABLE t1; -RESET optimizer; -- Ensure that prefetch is not disabled for HashJoin in case of join at single segment. -- Test Shared Scan producer is executed under inner part of join first and the -- deadlock between Shared Scans does not occur diff --git a/src/test/regress/expected/with_optimizer.out b/src/test/regress/expected/with_optimizer.out new file mode 100644 index 000000000000..ccb48709df9d --- /dev/null +++ b/src/test/regress/expected/with_optimizer.out @@ -0,0 +1,2411 @@ +-- +-- Tests for common table expressions (WITH query, ... SELECT ...) +-- +-- Basic WITH +WITH q1(x,y) AS (SELECT 1,2) +SELECT * FROM q1, q1 AS q2; + x | y | x | y +---+---+---+--- + 1 | 2 | 1 | 2 +(1 row) + +-- Multiple uses are evaluated only once +SELECT count(*) FROM ( + WITH q1(x) AS (SELECT random() FROM generate_series(1, 5)) + SELECT * FROM q1 + UNION + SELECT * FROM q1 +) ss; + count +------- + 5 +(1 row) + +-- WITH RECURSIVE +-- sum of 1..100 +WITH RECURSIVE t(n) AS ( + VALUES (1) +UNION ALL + SELECT n+1 FROM t WHERE n < 100 +) +SELECT sum(n) FROM t; + sum +------ + 5050 +(1 row) + +WITH RECURSIVE t(n) AS ( + SELECT (VALUES(1)) +UNION ALL + SELECT n+1 FROM t WHERE n < 5 +) +SELECT * FROM t; + n +--- + 1 + 2 + 3 + 4 + 5 +(5 rows) + +-- recursive view +CREATE RECURSIVE VIEW nums (n) AS + VALUES (1) +UNION ALL + SELECT n+1 FROM nums WHERE n < 5; +SELECT * FROM nums; + n +--- + 1 + 2 + 3 + 4 + 5 +(5 rows) + +CREATE OR REPLACE RECURSIVE VIEW nums (n) AS + VALUES (1) +UNION ALL + SELECT n+1 FROM nums WHERE n < 6; +SELECT * FROM nums; + n +--- + 1 + 2 + 3 + 4 + 5 + 6 +(6 rows) + +-- This is an infinite loop with UNION ALL, but not with UNION +WITH RECURSIVE t(n) AS ( + SELECT 1 +UNION + SELECT 10-n FROM t) +SELECT * FROM t; + n +--- + 1 + 9 +(2 rows) + +-- This'd be an infinite loop, but outside query reads only as much as needed +WITH RECURSIVE t(n) AS ( + VALUES (1) +UNION ALL + SELECT n+1 FROM t) +SELECT * FROM t LIMIT 10; + n +---- + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 +(10 rows) + +-- UNION case should have same property +WITH RECURSIVE t(n) AS ( + SELECT 1 +UNION + SELECT n+1 FROM t) +SELECT * FROM t LIMIT 10; + n +---- + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 +(10 rows) + +-- Test behavior with an unknown-type literal in the WITH +WITH q AS (SELECT 'foo' AS x) +SELECT x, x IS OF (unknown) as is_unknown FROM q; + x | is_unknown +-----+------------ + foo | t +(1 row) + +WITH RECURSIVE t(n) AS ( + SELECT 'foo' +UNION ALL + SELECT n || ' bar' FROM t WHERE length(n) < 20 +) +SELECT n, n IS OF (text) as is_text FROM t; + n | is_text +-------------------------+--------- + foo | t + foo bar | t + foo bar bar | t + foo bar bar bar | t + foo bar bar bar bar | t + foo bar bar bar bar bar | t +(6 rows) + +-- In a perfect world, this would work and resolve the literal as int ... +-- but for now, we have to be content with resolving to text too soon. +WITH RECURSIVE t(n) AS ( + SELECT '7' +UNION ALL + SELECT n+1 FROM t WHERE n < 10 +) +SELECT n, n IS OF (int) AS is_int FROM t; +ERROR: operator does not exist: text + integer +LINE 4: SELECT n+1 FROM t WHERE n < 10 + ^ +HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. +-- +-- Some examples with a tree +-- +-- department structure represented here is as follows: +-- +-- ROOT-+->A-+->B-+->C +-- | | +-- | +->D-+->F +-- +->E-+->G +CREATE TEMP TABLE department ( + id INTEGER PRIMARY KEY, -- department ID + parent_department INTEGER REFERENCES department, -- upper department ID + name TEXT -- department name +); +INSERT INTO department VALUES (0, NULL, 'ROOT'); +INSERT INTO department VALUES (1, 0, 'A'); +INSERT INTO department VALUES (2, 1, 'B'); +INSERT INTO department VALUES (3, 2, 'C'); +INSERT INTO department VALUES (4, 2, 'D'); +INSERT INTO department VALUES (5, 0, 'E'); +INSERT INTO department VALUES (6, 4, 'F'); +INSERT INTO department VALUES (7, 5, 'G'); +-- GPDB: Some of the queries below will return non-deterministic results +-- because of moving rows across segments. This table is the same, except that +-- all the rows reside on a single segment, so that you get consistent results. +CREATE TEMP TABLE department_oneseg AS SELECT 1 AS distkey, * FROM department DISTRIBUTED BY (distkey); +-- extract all departments under 'A'. Result should be A, B, C, D and F +WITH RECURSIVE subdepartment AS +( + -- non recursive term + SELECT name as root_name, * FROM department WHERE name = 'A' + UNION ALL + -- recursive term + SELECT sd.root_name, d.* FROM department AS d, subdepartment AS sd + WHERE d.parent_department = sd.id +) +SELECT * FROM subdepartment ORDER BY name; + root_name | id | parent_department | name +-----------+----+-------------------+------ + A | 1 | 0 | A + A | 2 | 1 | B + A | 3 | 2 | C + A | 4 | 2 | D + A | 6 | 4 | F +(5 rows) + +-- extract all departments under 'A' with "level" number +WITH RECURSIVE subdepartment(level, id, parent_department, name) AS +( + -- non recursive term + SELECT 1, * FROM department WHERE name = 'A' + UNION ALL + -- recursive term + SELECT sd.level + 1, d.* FROM department AS d, subdepartment AS sd + WHERE d.parent_department = sd.id +) +SELECT * FROM subdepartment ORDER BY name; + level | id | parent_department | name +-------+----+-------------------+------ + 1 | 1 | 0 | A + 2 | 2 | 1 | B + 3 | 3 | 2 | C + 3 | 4 | 2 | D + 4 | 6 | 4 | F +(5 rows) + +-- extract all departments under 'A' with "level" number. +-- Only shows level 2 or more +WITH RECURSIVE subdepartment(level, id, parent_department, name) AS +( + -- non recursive term + SELECT 1, * FROM department WHERE name = 'A' + UNION ALL + -- recursive term + SELECT sd.level + 1, d.* FROM department AS d, subdepartment AS sd + WHERE d.parent_department = sd.id +) +SELECT * FROM subdepartment WHERE level >= 2 ORDER BY name; + level | id | parent_department | name +-------+----+-------------------+------ + 2 | 2 | 1 | B + 3 | 3 | 2 | C + 3 | 4 | 2 | D + 4 | 6 | 4 | F +(4 rows) + +-- "RECURSIVE" is ignored if the query has no self-reference +WITH RECURSIVE subdepartment AS +( + -- note lack of recursive UNION structure + SELECT * FROM department WHERE name = 'A' +) +SELECT * FROM subdepartment ORDER BY name; + id | parent_department | name +----+-------------------+------ + 1 | 0 | A +(1 row) + +-- inside subqueries +SELECT count(*) FROM ( + WITH RECURSIVE t(n) AS ( + SELECT 1 UNION ALL SELECT n + 1 FROM t WHERE n < 500 + ) + SELECT * FROM t) AS t WHERE n < ( + SELECT count(*) FROM ( + WITH RECURSIVE t(n) AS ( + SELECT 1 UNION ALL SELECT n + 1 FROM t WHERE n < 100 + ) + SELECT * FROM t WHERE n < 50000 + ) AS t WHERE n < 100); + count +------- + 98 +(1 row) + +-- use same CTE twice at different subquery levels +WITH q1(x,y) AS ( + SELECT hundred, sum(ten) FROM tenk1 GROUP BY hundred + ) +SELECT count(*) FROM q1 WHERE y > (SELECT sum(y)/100 FROM q1 qsub); + count +------- + 50 +(1 row) + +-- via a VIEW +CREATE TEMPORARY VIEW vsubdepartment AS + WITH RECURSIVE subdepartment AS + ( + -- non recursive term + SELECT * FROM department WHERE name = 'A' + UNION ALL + -- recursive term + SELECT d.* FROM department AS d, subdepartment AS sd + WHERE d.parent_department = sd.id + ) + SELECT * FROM subdepartment; +SELECT * FROM vsubdepartment ORDER BY name; + id | parent_department | name +----+-------------------+------ + 1 | 0 | A + 2 | 1 | B + 3 | 2 | C + 4 | 2 | D + 6 | 4 | F +(5 rows) + +-- Check reverse listing +SELECT pg_get_viewdef('vsubdepartment'::regclass); + pg_get_viewdef +----------------------------------------------- + WITH RECURSIVE subdepartment AS ( + + SELECT department.id, + + department.parent_department, + + department.name + + FROM department + + WHERE (department.name = 'A'::text)+ + UNION ALL + + SELECT d.id, + + d.parent_department, + + d.name + + FROM department d, + + subdepartment sd + + WHERE (d.parent_department = sd.id)+ + ) + + SELECT subdepartment.id, + + subdepartment.parent_department, + + subdepartment.name + + FROM subdepartment; +(1 row) + +SELECT pg_get_viewdef('vsubdepartment'::regclass, true); + pg_get_viewdef +--------------------------------------------- + WITH RECURSIVE subdepartment AS ( + + SELECT department.id, + + department.parent_department, + + department.name + + FROM department + + WHERE department.name = 'A'::text+ + UNION ALL + + SELECT d.id, + + d.parent_department, + + d.name + + FROM department d, + + subdepartment sd + + WHERE d.parent_department = sd.id+ + ) + + SELECT subdepartment.id, + + subdepartment.parent_department, + + subdepartment.name + + FROM subdepartment; +(1 row) + +-- Another reverse-listing example +CREATE VIEW sums_1_100 AS +WITH RECURSIVE t(n) AS ( + VALUES (1) +UNION ALL + SELECT n+1 FROM t WHERE n < 100 +) +SELECT sum(n) FROM t; +\d+ sums_1_100 + View "public.sums_1_100" + Column | Type | Modifiers | Storage | Description +--------+--------+-----------+---------+------------- + sum | bigint | | plain | +View definition: + WITH RECURSIVE t(n) AS ( + VALUES (1) + UNION ALL + SELECT t_1.n + 1 + FROM t t_1 + WHERE t_1.n < 100 + ) + SELECT sum(t.n) AS sum + FROM t; + +-- corner case in which sub-WITH gets initialized first +with recursive q as ( + select * from department_oneseg + union all + (with x as (select * from q) + select * from x) + ) +select id, parent_department, name from q limit 24; + id | parent_department | name +----+-------------------+------ + 0 | | ROOT + 1 | 0 | A + 2 | 1 | B + 3 | 2 | C + 4 | 2 | D + 5 | 0 | E + 6 | 4 | F + 7 | 5 | G + 0 | | ROOT + 1 | 0 | A + 2 | 1 | B + 3 | 2 | C + 4 | 2 | D + 5 | 0 | E + 6 | 4 | F + 7 | 5 | G + 0 | | ROOT + 1 | 0 | A + 2 | 1 | B + 3 | 2 | C + 4 | 2 | D + 5 | 0 | E + 6 | 4 | F + 7 | 5 | G +(24 rows) + +with recursive q as ( + select * from department_oneseg + union all + (with recursive x as ( + select * from department_oneseg + union all + (select * from q union all select * from x) + ) + select * from x) + ) +select id, parent_department, name from q limit 32; + id | parent_department | name +----+-------------------+------ + 0 | | ROOT + 1 | 0 | A + 2 | 1 | B + 3 | 2 | C + 4 | 2 | D + 5 | 0 | E + 6 | 4 | F + 7 | 5 | G + 0 | | ROOT + 1 | 0 | A + 2 | 1 | B + 3 | 2 | C + 4 | 2 | D + 5 | 0 | E + 6 | 4 | F + 7 | 5 | G + 0 | | ROOT + 1 | 0 | A + 2 | 1 | B + 3 | 2 | C + 4 | 2 | D + 5 | 0 | E + 6 | 4 | F + 7 | 5 | G + 0 | | ROOT + 1 | 0 | A + 2 | 1 | B + 3 | 2 | C + 4 | 2 | D + 5 | 0 | E + 6 | 4 | F + 7 | 5 | G +(32 rows) + +-- recursive term has sub-UNION +WITH RECURSIVE t(i,j) AS ( + VALUES (1,2) + UNION ALL + SELECT t2.i, t.j+1 FROM + (SELECT 2 AS i UNION ALL SELECT 3 AS i) AS t2 + JOIN t ON (t2.i = t.i+1)) + SELECT * FROM t; + i | j +---+--- + 1 | 2 + 2 | 3 + 3 | 4 +(3 rows) + +-- +-- different tree example +-- +CREATE TEMPORARY TABLE tree( + id INTEGER PRIMARY KEY, + parent_id INTEGER REFERENCES tree(id) +); +INSERT INTO tree +VALUES (1, NULL), (2, 1), (3,1), (4,2), (5,2), (6,2), (7,3), (8,3), + (9,4), (10,4), (11,7), (12,7), (13,7), (14, 9), (15,11), (16,11); +-- +-- get all paths from "second level" nodes to leaf nodes +-- +WITH RECURSIVE t(id, path) AS ( + VALUES(1,ARRAY[]::integer[]) +UNION ALL + SELECT tree.id, t.path || tree.id + FROM tree JOIN t ON (tree.parent_id = t.id) +) +SELECT t1.*, t2.* FROM t AS t1 JOIN t AS t2 ON + (t1.path[1] = t2.path[1] AND + array_upper(t1.path,1) = 1 AND + array_upper(t2.path,1) > 1) + ORDER BY t1.id, t2.id; + id | path | id | path +----+------+----+------------- + 2 | {2} | 4 | {2,4} + 2 | {2} | 5 | {2,5} + 2 | {2} | 6 | {2,6} + 2 | {2} | 9 | {2,4,9} + 2 | {2} | 10 | {2,4,10} + 2 | {2} | 14 | {2,4,9,14} + 3 | {3} | 7 | {3,7} + 3 | {3} | 8 | {3,8} + 3 | {3} | 11 | {3,7,11} + 3 | {3} | 12 | {3,7,12} + 3 | {3} | 13 | {3,7,13} + 3 | {3} | 15 | {3,7,11,15} + 3 | {3} | 16 | {3,7,11,16} +(13 rows) + +-- just count 'em +WITH RECURSIVE t(id, path) AS ( + VALUES(1,ARRAY[]::integer[]) +UNION ALL + SELECT tree.id, t.path || tree.id + FROM tree JOIN t ON (tree.parent_id = t.id) +) +SELECT t1.id, count(t2.*) FROM t AS t1 JOIN t AS t2 ON + (t1.path[1] = t2.path[1] AND + array_upper(t1.path,1) = 1 AND + array_upper(t2.path,1) > 1) + GROUP BY t1.id + ORDER BY t1.id; + id | count +----+------- + 2 | 6 + 3 | 7 +(2 rows) + +-- this variant tickled a whole-row-variable bug in 8.4devel +WITH RECURSIVE t(id, path) AS ( + VALUES(1,ARRAY[]::integer[]) +UNION ALL + SELECT tree.id, t.path || tree.id + FROM tree JOIN t ON (tree.parent_id = t.id) +) +SELECT t1.id, t2.path, t2 FROM t AS t1 JOIN t AS t2 ON +(t1.id=t2.id); + id | path | t2 +----+-------------+-------------------- + 1 | {} | (1,{}) + 2 | {2} | (2,{2}) + 3 | {3} | (3,{3}) + 4 | {2,4} | (4,"{2,4}") + 5 | {2,5} | (5,"{2,5}") + 6 | {2,6} | (6,"{2,6}") + 7 | {3,7} | (7,"{3,7}") + 8 | {3,8} | (8,"{3,8}") + 9 | {2,4,9} | (9,"{2,4,9}") + 10 | {2,4,10} | (10,"{2,4,10}") + 11 | {3,7,11} | (11,"{3,7,11}") + 12 | {3,7,12} | (12,"{3,7,12}") + 13 | {3,7,13} | (13,"{3,7,13}") + 14 | {2,4,9,14} | (14,"{2,4,9,14}") + 15 | {3,7,11,15} | (15,"{3,7,11,15}") + 16 | {3,7,11,16} | (16,"{3,7,11,16}") +(16 rows) + +-- +-- test cycle detection +-- +create temp table graph( f int, t int, label text ); +insert into graph values + (1, 2, 'arc 1 -> 2'), + (1, 3, 'arc 1 -> 3'), + (2, 3, 'arc 2 -> 3'), + (1, 4, 'arc 1 -> 4'), + (4, 5, 'arc 4 -> 5'), + (5, 1, 'arc 5 -> 1'); +with recursive search_graph(f, t, label, path, cycle) as ( + select *, array[row(g.f, g.t)], false from graph g + union all + select g.*, path || row(g.f, g.t), row(g.f, g.t) = any(path) + from graph g, search_graph sg + where g.f = sg.t and not cycle +) +select * from search_graph; + f | t | label | path | cycle +---+---+------------+-------------------------------------------+------- + 1 | 2 | arc 1 -> 2 | {"(1,2)"} | f + 1 | 3 | arc 1 -> 3 | {"(1,3)"} | f + 2 | 3 | arc 2 -> 3 | {"(2,3)"} | f + 1 | 4 | arc 1 -> 4 | {"(1,4)"} | f + 4 | 5 | arc 4 -> 5 | {"(4,5)"} | f + 5 | 1 | arc 5 -> 1 | {"(5,1)"} | f + 1 | 2 | arc 1 -> 2 | {"(5,1)","(1,2)"} | f + 1 | 3 | arc 1 -> 3 | {"(5,1)","(1,3)"} | f + 1 | 4 | arc 1 -> 4 | {"(5,1)","(1,4)"} | f + 2 | 3 | arc 2 -> 3 | {"(1,2)","(2,3)"} | f + 4 | 5 | arc 4 -> 5 | {"(1,4)","(4,5)"} | f + 5 | 1 | arc 5 -> 1 | {"(4,5)","(5,1)"} | f + 1 | 2 | arc 1 -> 2 | {"(4,5)","(5,1)","(1,2)"} | f + 1 | 3 | arc 1 -> 3 | {"(4,5)","(5,1)","(1,3)"} | f + 1 | 4 | arc 1 -> 4 | {"(4,5)","(5,1)","(1,4)"} | f + 2 | 3 | arc 2 -> 3 | {"(5,1)","(1,2)","(2,3)"} | f + 4 | 5 | arc 4 -> 5 | {"(5,1)","(1,4)","(4,5)"} | f + 5 | 1 | arc 5 -> 1 | {"(1,4)","(4,5)","(5,1)"} | f + 1 | 2 | arc 1 -> 2 | {"(1,4)","(4,5)","(5,1)","(1,2)"} | f + 1 | 3 | arc 1 -> 3 | {"(1,4)","(4,5)","(5,1)","(1,3)"} | f + 1 | 4 | arc 1 -> 4 | {"(1,4)","(4,5)","(5,1)","(1,4)"} | t + 2 | 3 | arc 2 -> 3 | {"(4,5)","(5,1)","(1,2)","(2,3)"} | f + 4 | 5 | arc 4 -> 5 | {"(4,5)","(5,1)","(1,4)","(4,5)"} | t + 5 | 1 | arc 5 -> 1 | {"(5,1)","(1,4)","(4,5)","(5,1)"} | t + 2 | 3 | arc 2 -> 3 | {"(1,4)","(4,5)","(5,1)","(1,2)","(2,3)"} | f +(25 rows) + +-- ordering by the path column has same effect as SEARCH DEPTH FIRST +with recursive search_graph(f, t, label, path, cycle) as ( + select *, array[row(g.f, g.t)], false from graph g + union all + select g.*, path || row(g.f, g.t), row(g.f, g.t) = any(path) + from graph g, search_graph sg + where g.f = sg.t and not cycle +) +select * from search_graph order by path; + f | t | label | path | cycle +---+---+------------+-------------------------------------------+------- + 1 | 2 | arc 1 -> 2 | {"(1,2)"} | f + 2 | 3 | arc 2 -> 3 | {"(1,2)","(2,3)"} | f + 1 | 3 | arc 1 -> 3 | {"(1,3)"} | f + 1 | 4 | arc 1 -> 4 | {"(1,4)"} | f + 4 | 5 | arc 4 -> 5 | {"(1,4)","(4,5)"} | f + 5 | 1 | arc 5 -> 1 | {"(1,4)","(4,5)","(5,1)"} | f + 1 | 2 | arc 1 -> 2 | {"(1,4)","(4,5)","(5,1)","(1,2)"} | f + 2 | 3 | arc 2 -> 3 | {"(1,4)","(4,5)","(5,1)","(1,2)","(2,3)"} | f + 1 | 3 | arc 1 -> 3 | {"(1,4)","(4,5)","(5,1)","(1,3)"} | f + 1 | 4 | arc 1 -> 4 | {"(1,4)","(4,5)","(5,1)","(1,4)"} | t + 2 | 3 | arc 2 -> 3 | {"(2,3)"} | f + 4 | 5 | arc 4 -> 5 | {"(4,5)"} | f + 5 | 1 | arc 5 -> 1 | {"(4,5)","(5,1)"} | f + 1 | 2 | arc 1 -> 2 | {"(4,5)","(5,1)","(1,2)"} | f + 2 | 3 | arc 2 -> 3 | {"(4,5)","(5,1)","(1,2)","(2,3)"} | f + 1 | 3 | arc 1 -> 3 | {"(4,5)","(5,1)","(1,3)"} | f + 1 | 4 | arc 1 -> 4 | {"(4,5)","(5,1)","(1,4)"} | f + 4 | 5 | arc 4 -> 5 | {"(4,5)","(5,1)","(1,4)","(4,5)"} | t + 5 | 1 | arc 5 -> 1 | {"(5,1)"} | f + 1 | 2 | arc 1 -> 2 | {"(5,1)","(1,2)"} | f + 2 | 3 | arc 2 -> 3 | {"(5,1)","(1,2)","(2,3)"} | f + 1 | 3 | arc 1 -> 3 | {"(5,1)","(1,3)"} | f + 1 | 4 | arc 1 -> 4 | {"(5,1)","(1,4)"} | f + 4 | 5 | arc 4 -> 5 | {"(5,1)","(1,4)","(4,5)"} | f + 5 | 1 | arc 5 -> 1 | {"(5,1)","(1,4)","(4,5)","(5,1)"} | t +(25 rows) + +-- +-- test multiple WITH queries +-- +WITH RECURSIVE + y (id) AS (VALUES (1)), + x (id) AS (SELECT * FROM y UNION ALL SELECT id+1 FROM x WHERE id < 5) +SELECT * FROM x; + id +---- + 1 + 2 + 3 + 4 + 5 +(5 rows) + +-- forward reference OK +WITH RECURSIVE + x(id) AS (SELECT * FROM y UNION ALL SELECT id+1 FROM x WHERE id < 5), + y(id) AS (values (1)) + SELECT * FROM x; + id +---- + 1 + 2 + 3 + 4 + 5 +(5 rows) + +WITH RECURSIVE + x(id) AS + (VALUES (1) UNION ALL SELECT id+1 FROM x WHERE id < 5), + y(id) AS + (VALUES (1) UNION ALL SELECT id+1 FROM y WHERE id < 10) + SELECT y.*, x.* FROM y LEFT JOIN x USING (id); + id | id +----+---- + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | + 7 | + 8 | + 9 | + 10 | +(10 rows) + +WITH RECURSIVE + x(id) AS + (VALUES (1) UNION ALL SELECT id+1 FROM x WHERE id < 5), + y(id) AS + (VALUES (1) UNION ALL SELECT id+1 FROM x WHERE id < 10) + SELECT y.*, x.* FROM y LEFT JOIN x USING (id); + id | id +----+---- + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | +(6 rows) + +WITH RECURSIVE + x(id) AS + (SELECT 1 UNION ALL SELECT id+1 FROM x WHERE id < 3 ), + y(id) AS + (SELECT * FROM x UNION ALL SELECT * FROM x), + z(id) AS + (SELECT * FROM x UNION ALL SELECT id+1 FROM z WHERE id < 10) + SELECT * FROM z; + id +---- + 1 + 2 + 3 + 2 + 3 + 4 + 3 + 4 + 5 + 4 + 5 + 6 + 5 + 6 + 7 + 6 + 7 + 8 + 7 + 8 + 9 + 8 + 9 + 10 + 9 + 10 + 10 +(27 rows) + +WITH RECURSIVE + x(id) AS + (SELECT 1 UNION ALL SELECT id+1 FROM x WHERE id < 3 ), + y(id) AS + (SELECT * FROM x UNION ALL SELECT * FROM x), + z(id) AS + (SELECT * FROM y UNION ALL SELECT id+1 FROM z WHERE id < 10) + SELECT * FROM z; + id +---- + 1 + 2 + 3 + 1 + 2 + 3 + 2 + 3 + 4 + 2 + 3 + 4 + 3 + 4 + 5 + 3 + 4 + 5 + 4 + 5 + 6 + 4 + 5 + 6 + 5 + 6 + 7 + 5 + 6 + 7 + 6 + 7 + 8 + 6 + 7 + 8 + 7 + 8 + 9 + 7 + 8 + 9 + 8 + 9 + 10 + 8 + 9 + 10 + 9 + 10 + 9 + 10 + 10 + 10 +(54 rows) + +-- +-- Test WITH attached to a data-modifying statement +-- +CREATE TEMPORARY TABLE y (a INTEGER) DISTRIBUTED RANDOMLY; +INSERT INTO y SELECT generate_series(1, 10); +WITH t AS ( + SELECT a FROM y +) +INSERT INTO y +SELECT a+20 FROM t RETURNING *; + a +---- + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 +(10 rows) + +SELECT * FROM y; + a +---- + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 +(20 rows) + +WITH t AS ( + SELECT a FROM y +) +UPDATE y SET a = y.a-10 FROM t WHERE y.a > 20 AND t.a = y.a RETURNING y.a; + a +---- + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 +(10 rows) + +SELECT * FROM y; + a +---- + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 +(20 rows) + +WITH RECURSIVE t(a) AS ( + SELECT 11 + UNION ALL + SELECT a+1 FROM t WHERE a < 50 +) +DELETE FROM y USING t WHERE t.a = y.a RETURNING y.a; + a +---- + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 +(10 rows) + +SELECT * FROM y; + a +---- + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 +(10 rows) + +DROP TABLE y; +-- +-- error cases +-- +-- INTERSECT +WITH RECURSIVE x(n) AS (SELECT 1 INTERSECT SELECT n+1 FROM x) + SELECT * FROM x; +ERROR: recursive query "x" does not have the form non-recursive-term UNION [ALL] recursive-term +LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 INTERSECT SELECT n+1 FROM x... + ^ +WITH RECURSIVE x(n) AS (SELECT 1 INTERSECT ALL SELECT n+1 FROM x) + SELECT * FROM x; +ERROR: recursive query "x" does not have the form non-recursive-term UNION [ALL] recursive-term +LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 INTERSECT ALL SELECT n+1 FR... + ^ +-- EXCEPT +WITH RECURSIVE x(n) AS (SELECT 1 EXCEPT SELECT n+1 FROM x) + SELECT * FROM x; +ERROR: recursive query "x" does not have the form non-recursive-term UNION [ALL] recursive-term +LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 EXCEPT SELECT n+1 FROM x) + ^ +WITH RECURSIVE x(n) AS (SELECT 1 EXCEPT ALL SELECT n+1 FROM x) + SELECT * FROM x; +ERROR: recursive query "x" does not have the form non-recursive-term UNION [ALL] recursive-term +LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 EXCEPT ALL SELECT n+1 FROM ... + ^ +-- GPDB Specific Error Cases +-- Set operations within the recursive term with a self-reference. +-- Currently set operations in the recursive term involving the cte itself must +-- be prevented. The reason for this is that such a query may lead to a plan +-- where there is a motion between the RecursiveUnion node and the +-- WorkTableScan node. +CREATE TEMPORARY TABLE z(x int primary key); +WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM (SELECT * FROM x UNION SELECT * FROM z)foo) + SELECT * FROM x; +ERROR: recursive reference to query "x" must not appear within a subquery +LINE 1: ...SELECT 1 UNION ALL SELECT n+1 FROM (SELECT * FROM x UNION SE... + ^ +-- Set operation in recursive term that does not have a self-reference +-- This is supported +CREATE TEMPORARY TABLE u(x int primary key); +WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM (SELECT * from z UNION SELECT * FROM u)foo, x where foo.x = x.n) + SELECT * FROM x; + n +--- + 1 +(1 row) + +-- no non-recursive term +WITH RECURSIVE x(n) AS (SELECT n FROM x) + SELECT * FROM x; +ERROR: recursive query "x" does not have the form non-recursive-term UNION [ALL] recursive-term +LINE 1: WITH RECURSIVE x(n) AS (SELECT n FROM x) + ^ +-- recursive term in the left hand side (strictly speaking, should allow this) +WITH RECURSIVE x(n) AS (SELECT n FROM x UNION ALL SELECT 1) + SELECT * FROM x; +ERROR: recursive reference to query "x" must not appear within its non-recursive term +LINE 1: WITH RECURSIVE x(n) AS (SELECT n FROM x UNION ALL SELECT 1) + ^ +-- recursive term with a self-reference within a subquery is not allowed +WITH RECURSIVE cte(level, id) as ( + SELECT 1, 2 + UNION ALL + SELECT level+1, c FROM (SELECT * FROM cte OFFSET 0) foo, bar) +SELECT * FROM cte LIMIT 10; +ERROR: recursive reference to query "cte" must not appear within a subquery +LINE 4: SELECT level+1, c FROM (SELECT * FROM cte OFFSET 0) foo, ba... + ^ +-- recursive term with a distinct operation is not allowed +WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT distinct(n+1) FROM x) + SELECT * FROM x; +ERROR: DISTINCT in a recursive query is not implemented +-- recursive term with a group by operation is not allowed +CREATE TEMPORARY TABLE bar(c int); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'c' as the Greenplum Database data distribution key for this table. +HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. +WITH RECURSIVE x(n) AS ( + SELECT 1,2 + UNION ALL + SELECT level+1, c FROM x, bar GROUP BY 1,2) + SELECT * FROM x LIMIT 10; +ERROR: GROUP BY in a recursive query is not implemented +LINE 4: SELECT level+1, c FROM x, bar GROUP BY 1,2) + ^ +WITH RECURSIVE x(n) AS ( + SELECT 1,2 + UNION ALL + SELECT level+1, row_number() over() FROM x, bar) + SELECT * FROM x LIMIT 10; +ERROR: window functions in the target list of a recursive query is not supported in Greenplum +LINE 4: SELECT level+1, row_number() over() FROM x, bar) + ^ +CREATE TEMPORARY TABLE y (a INTEGER) DISTRIBUTED RANDOMLY; +INSERT INTO y SELECT generate_series(1, 10); +-- LEFT JOIN +WITH RECURSIVE x(n) AS (SELECT a FROM y WHERE a = 1 + UNION ALL + SELECT x.n+1 FROM y LEFT JOIN x ON x.n = y.a WHERE n < 10) +SELECT * FROM x; +ERROR: recursive reference to query "x" must not appear within an outer join +LINE 3: SELECT x.n+1 FROM y LEFT JOIN x ON x.n = y.a WHERE n < 10) + ^ +-- RIGHT JOIN +WITH RECURSIVE x(n) AS (SELECT a FROM y WHERE a = 1 + UNION ALL + SELECT x.n+1 FROM x RIGHT JOIN y ON x.n = y.a WHERE n < 10) +SELECT * FROM x; +ERROR: recursive reference to query "x" must not appear within an outer join +LINE 3: SELECT x.n+1 FROM x RIGHT JOIN y ON x.n = y.a WHERE n < 10) + ^ +-- FULL JOIN +WITH RECURSIVE x(n) AS (SELECT a FROM y WHERE a = 1 + UNION ALL + SELECT x.n+1 FROM x FULL JOIN y ON x.n = y.a WHERE n < 10) +SELECT * FROM x; +ERROR: recursive reference to query "x" must not appear within an outer join +LINE 3: SELECT x.n+1 FROM x FULL JOIN y ON x.n = y.a WHERE n < 10) + ^ +-- subquery +WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM x + WHERE n IN (SELECT * FROM x)) + SELECT * FROM x; +ERROR: recursive reference to query "x" must not appear within a subquery +LINE 2: WHERE n IN (SELECT * FROM x)) + ^ +-- aggregate functions +WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT count(*) FROM x) + SELECT * FROM x; +ERROR: aggregate functions are not allowed in a recursive query's recursive term +LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT count(*) F... + ^ +WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT sum(n) FROM x) + SELECT * FROM x; +ERROR: aggregate functions are not allowed in a recursive query's recursive term +LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT sum(n) FRO... + ^ +-- ORDER BY +WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM x ORDER BY 1) + SELECT * FROM x; +ERROR: ORDER BY in a recursive query is not implemented +LINE 1: ...VE x(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM x ORDER BY 1) + ^ +-- LIMIT/OFFSET +WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM x LIMIT 10 OFFSET 1) + SELECT * FROM x; +ERROR: OFFSET in a recursive query is not implemented +LINE 1: ... AS (SELECT 1 UNION ALL SELECT n+1 FROM x LIMIT 10 OFFSET 1) + ^ +-- FOR UPDATE +WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM x FOR UPDATE) + SELECT * FROM x; +ERROR: FOR UPDATE/SHARE in a recursive query is not implemented +-- target list has a recursive query name +WITH RECURSIVE x(id) AS (values (1) + UNION ALL + SELECT (SELECT * FROM x) FROM x WHERE id < 5 +) SELECT * FROM x; +ERROR: recursive reference to query "x" must not appear within a subquery +LINE 3: SELECT (SELECT * FROM x) FROM x WHERE id < 5 + ^ +-- mutual recursive query (not implemented) +WITH RECURSIVE + x (id) AS (SELECT 1 UNION ALL SELECT id+1 FROM y WHERE id < 5), + y (id) AS (SELECT 1 UNION ALL SELECT id+1 FROM x WHERE id < 5) +SELECT * FROM x; +ERROR: mutual recursion between WITH items is not implemented +LINE 2: x (id) AS (SELECT 1 UNION ALL SELECT id+1 FROM y WHERE id ... + ^ +-- non-linear recursion is not allowed +WITH RECURSIVE foo(i) AS + (values (1) + UNION ALL + (SELECT i+1 FROM foo WHERE i < 10 + UNION ALL + SELECT i+1 FROM foo WHERE i < 5) +) SELECT * FROM foo; +ERROR: recursive reference to query "foo" must not appear more than once +LINE 6: SELECT i+1 FROM foo WHERE i < 5) + ^ +WITH RECURSIVE foo(i) AS + (values (1) + UNION ALL + SELECT * FROM + (SELECT i+1 FROM foo WHERE i < 10 + UNION ALL + SELECT i+1 FROM foo WHERE i < 5) AS t +) SELECT * FROM foo; +ERROR: recursive reference to query "foo" must not appear within a subquery +LINE 5: (SELECT i+1 FROM foo WHERE i < 10 + ^ +WITH RECURSIVE foo(i) AS + (values (1) + UNION ALL + (SELECT i+1 FROM foo WHERE i < 10 + EXCEPT + SELECT i+1 FROM foo WHERE i < 5) +) SELECT * FROM foo; +ERROR: recursive reference to query "foo" must not appear within EXCEPT +LINE 6: SELECT i+1 FROM foo WHERE i < 5) + ^ +WITH RECURSIVE foo(i) AS + (values (1) + UNION ALL + (SELECT i+1 FROM foo WHERE i < 10 + INTERSECT + SELECT i+1 FROM foo WHERE i < 5) +) SELECT * FROM foo; +ERROR: recursive reference to query "foo" must not appear more than once +LINE 6: SELECT i+1 FROM foo WHERE i < 5) + ^ +-- Wrong type induced from non-recursive term +WITH RECURSIVE foo(i) AS + (SELECT i FROM (VALUES(1),(2)) t(i) + UNION ALL + SELECT (i+1)::numeric(10,0) FROM foo WHERE i < 10) +SELECT * FROM foo; +ERROR: recursive query "foo" column 1 has type integer in non-recursive term but type numeric overall +LINE 2: (SELECT i FROM (VALUES(1),(2)) t(i) + ^ +HINT: Cast the output of the non-recursive term to the correct type. +-- rejects different typmod, too (should we allow this?) +WITH RECURSIVE foo(i) AS + (SELECT i::numeric(3,0) FROM (VALUES(1),(2)) t(i) + UNION ALL + SELECT (i+1)::numeric(10,0) FROM foo WHERE i < 10) +SELECT * FROM foo; +ERROR: recursive query "foo" column 1 has type numeric(3,0) in non-recursive term but type numeric overall +LINE 2: (SELECT i::numeric(3,0) FROM (VALUES(1),(2)) t(i) + ^ +HINT: Cast the output of the non-recursive term to the correct type. +-- disallow OLD/NEW reference in CTE +CREATE TEMPORARY TABLE x (n integer); +CREATE RULE r2 AS ON UPDATE TO x DO INSTEAD + WITH t AS (SELECT OLD.*) UPDATE y SET a = t.n FROM t; +ERROR: cannot refer to OLD within WITH query +-- +-- test for bug #4902 +-- +with cte(foo) as ( values(42) ) values((select foo from cte)); + column1 +--------- + 42 +(1 row) + +with cte(foo) as ( select 42 ) select * from ((select foo from cte)) q; + foo +----- + 42 +(1 row) + +-- test CTE referencing an outer-level variable (to see that changed-parameter +-- signaling still works properly after fixing this bug) +select ( with cte(foo) as ( values(f1) ) + select (select foo from cte) ) +from int4_tbl; + foo +------------- + 0 + 123456 + -123456 + 2147483647 + -2147483647 +(5 rows) + +select ( with cte(foo) as ( values(f1) ) + values((select foo from cte)) ) +from int4_tbl; + column1 +------------- + 0 + 123456 + -123456 + 2147483647 + -2147483647 +(5 rows) + +-- +-- test Nested CTE +-- +WITH outermost(x) AS ( + SELECT 1 + UNION (WITH innermost as (SELECT 2) + SELECT * FROM innermost + UNION SELECT 3) +) +SELECT * FROM outermost; + x +--- + 1 + 2 + 3 +(3 rows) + +-- +-- test for nested-recursive-WITH bug +-- +WITH RECURSIVE t(j) AS ( + WITH RECURSIVE s(i) AS ( + VALUES (1) + UNION ALL + SELECT i+1 FROM s WHERE i < 10 + ) + SELECT i FROM s + UNION ALL + SELECT j+1 FROM t WHERE j < 10 +) +SELECT * FROM t; + j +---- + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 5 + 6 + 7 + 8 + 9 + 10 + 6 + 7 + 8 + 9 + 10 + 7 + 8 + 9 + 10 + 8 + 9 + 10 + 9 + 10 + 10 +(55 rows) + +-- +-- test WITH attached to intermediate-level set operation +-- +WITH outermost(x) AS ( + SELECT 1 + UNION (WITH innermost as (SELECT 2) + SELECT * FROM innermost + UNION SELECT 3) +) +SELECT * FROM outermost; + x +--- + 1 + 2 + 3 +(3 rows) + +WITH outermost(x) AS ( + SELECT 1 + UNION (WITH innermost as (SELECT 2) + SELECT * FROM outermost -- fail + UNION SELECT * FROM innermost) +) +SELECT * FROM outermost; +ERROR: relation "outermost" does not exist +LINE 4: SELECT * FROM outermost + ^ +DETAIL: There is a WITH item named "outermost", but it cannot be referenced from this part of the query. +HINT: Use WITH RECURSIVE, or re-order the WITH items to remove forward references. +WITH RECURSIVE outermost(x) AS ( + SELECT 1 + UNION (WITH innermost as (SELECT 2) + SELECT * FROM outermost + UNION SELECT * FROM innermost) +) +SELECT * FROM outermost; + x +--- + 1 + 2 +(2 rows) + +WITH RECURSIVE outermost(x) AS ( + WITH innermost as (SELECT 2 FROM outermost) -- fail + SELECT * FROM innermost + UNION SELECT * from outermost +) +SELECT * FROM outermost; +ERROR: recursive reference to query "outermost" must not appear within a subquery +LINE 2: WITH innermost as (SELECT 2 FROM outermost) + ^ +-- +-- This test will fail with the old implementation of PARAM_EXEC parameter +-- assignment, because the "q1" Var passed down to A's targetlist subselect +-- looks exactly like the "A.id" Var passed down to C's subselect, causing +-- the old code to give them the same runtime PARAM_EXEC slot. But the +-- lifespans of the two parameters overlap, thanks to B also reading A. +-- +with +A as ( select q2 as id, (select q1) as x from int8_tbl ), +B as ( select id, row_number() over (partition by id) as r from A ), +C as ( select A.id, array(select B.id from B where B.id = A.id) from A ) +select * from C; + id | array +-------------------+------------------------------------- + 456 | {456} + 4567890123456789 | {4567890123456789,4567890123456789} + 123 | {123} + 4567890123456789 | {4567890123456789,4567890123456789} + -4567890123456789 | {-4567890123456789} +(5 rows) + +-- +-- Test CTEs read in non-initialization orders +-- gpdb +-- Remove window funtions from Recursive CTE's test case. +-- Currently Recursive CTE's do not support the Window Functions, +-- So we remove it from the test cases. +-- +WITH RECURSIVE + tab(id_key,link) AS (VALUES (1,17), (2,17), (3,17), (4,17), (6,17), (5,17)), + iter (id_key, row_type, link) AS ( + SELECT 0, 'base', 17 + UNION ALL ( + WITH remaining(id_key, row_type, link, min) AS ( + SELECT tab.id_key, 'true'::text, iter.link, tab.id_key + FROM tab INNER JOIN iter USING (link) + WHERE tab.id_key > iter.id_key + ), + first_remaining AS ( + SELECT id_key, row_type, link + FROM remaining + WHERE id_key=min + ), + effect AS ( + SELECT tab.id_key, 'new'::text, tab.link + FROM first_remaining e INNER JOIN tab ON e.id_key=tab.id_key + WHERE e.row_type = 'false' + ) + SELECT * FROM first_remaining + UNION ALL SELECT * FROM effect + ) + ) +SELECT * FROM iter; + id_key | row_type | link +--------+----------+------ + 0 | base | 17 + 5 | true | 17 + 6 | true | 17 + 4 | true | 17 + 3 | true | 17 + 2 | true | 17 + 1 | true | 17 + 6 | true | 17 + 5 | true | 17 + 6 | true | 17 + 5 | true | 17 + 6 | true | 17 + 4 | true | 17 + 5 | true | 17 + 6 | true | 17 + 4 | true | 17 + 3 | true | 17 + 5 | true | 17 + 6 | true | 17 + 4 | true | 17 + 3 | true | 17 + 2 | true | 17 + 6 | true | 17 + 6 | true | 17 + 5 | true | 17 + 6 | true | 17 + 6 | true | 17 + 5 | true | 17 + 6 | true | 17 + 5 | true | 17 + 6 | true | 17 + 4 | true | 17 + 6 | true | 17 + 5 | true | 17 + 6 | true | 17 + 5 | true | 17 + 6 | true | 17 + 4 | true | 17 + 5 | true | 17 + 6 | true | 17 + 4 | true | 17 + 3 | true | 17 + 6 | true | 17 + 6 | true | 17 + 6 | true | 17 + 5 | true | 17 + 6 | true | 17 + 6 | true | 17 + 6 | true | 17 + 5 | true | 17 + 6 | true | 17 + 6 | true | 17 + 5 | true | 17 + 6 | true | 17 + 5 | true | 17 + 6 | true | 17 + 4 | true | 17 + 6 | true | 17 + 6 | true | 17 + 6 | true | 17 + 6 | true | 17 + 5 | true | 17 + 6 | true | 17 + 6 | true | 17 +(64 rows) + +WITH RECURSIVE + tab(id_key,link) AS (VALUES (1,17), (2,17), (3,17), (4,17), (6,17), (5,17)), + iter (id_key, row_type, link) AS ( + SELECT 0, 'base', 17 + UNION ( + WITH remaining(id_key, row_type, link, min) AS ( + SELECT tab.id_key, 'true'::text, iter.link, tab.id_key + FROM tab INNER JOIN iter USING (link) + WHERE tab.id_key > iter.id_key + ), + first_remaining AS ( + SELECT id_key, row_type, link + FROM remaining + WHERE id_key=min + ), + effect AS ( + SELECT tab.id_key, 'new'::text, tab.link + FROM first_remaining e INNER JOIN tab ON e.id_key=tab.id_key + WHERE e.row_type = 'false' + ) + SELECT * FROM first_remaining + UNION ALL SELECT * FROM effect + ) + ) +SELECT * FROM iter; + id_key | row_type | link +--------+----------+------ + 0 | base | 17 + 1 | true | 17 + 2 | true | 17 + 3 | true | 17 + 4 | true | 17 + 5 | true | 17 + 6 | true | 17 +(7 rows) + +-- +-- Data-modifying statements in WITH +-- +-- INSERT ... RETURNING +WITH t AS ( + INSERT INTO y + VALUES + (11), + (12), + (13), + (14), + (15), + (16), + (17), + (18), + (19), + (20) + RETURNING * +) +SELECT * FROM t; + a +---- + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 +(10 rows) + +SELECT * FROM y; + a +---- + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 +(20 rows) + +-- UPDATE ... RETURNING +WITH t AS ( + UPDATE y + SET a=a+1 + RETURNING * +) +SELECT * FROM t; + a +---- + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 +(20 rows) + +SELECT * FROM y; + a +---- + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 +(20 rows) + +-- DELETE ... RETURNING +WITH t AS ( + DELETE FROM y + WHERE a <= 10 + RETURNING * +) +SELECT * FROM t; + a +---- + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 +(9 rows) + +SELECT * FROM y; + a +---- + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 +(11 rows) + +-- forward reference +WITH RECURSIVE t AS ( + INSERT INTO y + SELECT a+5 FROM t2 WHERE a > 5 + RETURNING * +), t2 AS ( + UPDATE y SET a=a-11 RETURNING * +) +SELECT * FROM t +UNION ALL +SELECT * FROM t2; +ERROR: only one modifying WITH clause allowed per query +DETAIL: Greenplum Database currently only support CTEs with one writable clause. +HINT: Rewrite the query to only include one writable CTE clause. +SELECT * FROM y; + a +---- + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 +(11 rows) + +-- unconditional DO INSTEAD rule +CREATE RULE y_rule AS ON DELETE TO y DO INSTEAD + INSERT INTO y VALUES(42) RETURNING *; +WITH t AS ( + DELETE FROM y RETURNING * +) +SELECT * FROM t; + a +---- + 42 +(1 row) + +SELECT * FROM y; + a +---- + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 42 +(12 rows) + +DROP RULE y_rule ON y; +-- check merging of outer CTE with CTE in a rule action +CREATE TEMP TABLE bug6051 AS + select i from generate_series(1,3) as t(i); +SELECT * FROM bug6051; + i +--- + 1 + 2 + 3 +(3 rows) + +WITH t1 AS ( DELETE FROM bug6051 RETURNING * ) +INSERT INTO bug6051 SELECT * FROM t1; +ERROR: writable CTE queries cannot be themselves writable +DETAIL: Greenplum Database currently only support CTEs with one writable clause, called in a non-writable context. +HINT: Rewrite the query to only include one writable clause. +SELECT * FROM bug6051; + i +--- + 1 + 2 + 3 +(3 rows) + +CREATE TEMP TABLE bug6051_2 (i int); +CREATE RULE bug6051_ins AS ON INSERT TO bug6051 DO INSTEAD + INSERT INTO bug6051_2 + SELECT NEW.i; +WITH t1 AS ( DELETE FROM bug6051 RETURNING * ) +INSERT INTO bug6051 SELECT * FROM t1; +ERROR: writable CTE queries cannot be themselves writable +DETAIL: Greenplum Database currently only support CTEs with one writable clause, called in a non-writable context. +HINT: Rewrite the query to only include one writable clause. +SELECT * FROM bug6051; + i +--- + 1 + 2 + 3 +(3 rows) + +SELECT * FROM bug6051_2; + i +--- +(0 rows) + +-- a truly recursive CTE in the same list +WITH RECURSIVE t(a) AS ( + SELECT 0 + UNION ALL + SELECT a+1 FROM t WHERE a+1 < 5 +), t2 as ( + INSERT INTO y + SELECT * FROM t RETURNING * +) +SELECT * FROM t2 JOIN y USING (a) ORDER BY a; + a +--- +(0 rows) + +SELECT * FROM y; + a +---- + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 42 + 0 + 1 + 2 + 3 + 4 +(17 rows) + +-- data-modifying WITH in a modifying statement +WITH t AS ( + DELETE FROM y + WHERE a <= 10 + RETURNING * +) +INSERT INTO y SELECT -a FROM t RETURNING *; +ERROR: writable CTE queries cannot be themselves writable +DETAIL: Greenplum Database currently only support CTEs with one writable clause, called in a non-writable context. +HINT: Rewrite the query to only include one writable clause. +SELECT * FROM y; + a +---- + 0 + 1 + 2 + 3 + 4 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 42 +(17 rows) + +-- check that WITH query is run to completion even if outer query isn't +WITH t AS ( + UPDATE y SET a = a * 100 RETURNING * +) +SELECT a BETWEEN 0 AND 4200 FROM t LIMIT 10; + ?column? +---------- + t + t + t + t + t + t + t + t + t + t +(10 rows) + +SELECT * FROM y; + a +------ + 0 + 100 + 200 + 300 + 400 + 1100 + 1200 + 1300 + 1400 + 1500 + 1600 + 1700 + 1800 + 1900 + 2000 + 2100 + 4200 +(17 rows) + +-- check that run to completion happens in proper ordering +TRUNCATE TABLE y; +INSERT INTO y SELECT generate_series(1, 3); +CREATE TEMPORARY TABLE yy (a INTEGER); +WITH RECURSIVE t1 AS ( + INSERT INTO y SELECT * FROM y RETURNING * +), t2 AS ( + INSERT INTO yy SELECT * FROM t1 RETURNING * +) +SELECT 1; +ERROR: only one modifying WITH clause allowed per query +DETAIL: Greenplum Database currently only support CTEs with one writable clause. +HINT: Rewrite the query to only include one writable CTE clause. +SELECT * FROM y; + a +--- + 1 + 2 + 3 +(3 rows) + +SELECT * FROM yy; + a +--- +(0 rows) + +WITH RECURSIVE t1 AS ( + INSERT INTO yy SELECT * FROM t2 RETURNING * +), t2 AS ( + INSERT INTO y SELECT * FROM y RETURNING * +) +SELECT 1; +ERROR: only one modifying WITH clause allowed per query +DETAIL: Greenplum Database currently only support CTEs with one writable clause. +HINT: Rewrite the query to only include one writable CTE clause. +SELECT * FROM y; + a +--- + 1 + 2 + 3 +(3 rows) + +SELECT * FROM yy; + a +--- +(0 rows) + +-- start_ignore +-- These tests actually seem to work, but they have unstable return order +-- in an MPP environment so they are ignored until atmsort can handle this +-- triggers +TRUNCATE TABLE y; +INSERT INTO y SELECT generate_series(1, 10); +CREATE FUNCTION y_trigger() RETURNS trigger AS $$ +begin + raise notice 'y_trigger: a = %', new.a; + return new; +end; +$$ LANGUAGE plpgsql; +CREATE TRIGGER y_trig BEFORE INSERT ON y FOR EACH ROW + EXECUTE PROCEDURE y_trigger(); +WITH t AS ( + INSERT INTO y + VALUES + (21), + (22), + (23) + RETURNING * +) +SELECT * FROM t; +NOTICE: y_trigger: a = 21 +NOTICE: y_trigger: a = 22 +NOTICE: y_trigger: a = 23 + a +---- + 21 + 22 + 23 +(3 rows) + +SELECT * FROM y; + a +---- + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 21 + 22 + 23 +(13 rows) + +DROP TRIGGER y_trig ON y; +CREATE TRIGGER y_trig AFTER INSERT ON y FOR EACH ROW + EXECUTE PROCEDURE y_trigger(); +WITH t AS ( + INSERT INTO y + VALUES + (31), + (32), + (33) + RETURNING * +) +SELECT * FROM t LIMIT 1; +NOTICE: y_trigger: a = 31 +NOTICE: y_trigger: a = 32 +NOTICE: y_trigger: a = 33 + a +---- + 31 +(1 row) + +SELECT * FROM y; + a +---- + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 21 + 22 + 23 + 31 + 32 + 33 +(16 rows) + +DROP TRIGGER y_trig ON y; +CREATE OR REPLACE FUNCTION y_trigger() RETURNS trigger AS $$ +begin + raise notice 'y_trigger'; + return null; +end; +$$ LANGUAGE plpgsql; +CREATE TRIGGER y_trig AFTER INSERT ON y FOR EACH STATEMENT + EXECUTE PROCEDURE y_trigger(); +WITH t AS ( + INSERT INTO y + VALUES + (41), + (42), + (43) + RETURNING * +) +SELECT * FROM t; +NOTICE: y_trigger + a +---- + 41 + 42 + 43 +(3 rows) + +SELECT * FROM y; + a +---- + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 21 + 22 + 23 + 31 + 32 + 33 + 41 + 42 + 43 +(19 rows) + +DROP TRIGGER y_trig ON y; +DROP FUNCTION y_trigger(); +-- end_ignore +-- WITH attached to inherited UPDATE or DELETE +CREATE TEMP TABLE parent ( id int, val text ); +CREATE TEMP TABLE child1 ( ) INHERITS ( parent ); +CREATE TEMP TABLE child2 ( ) INHERITS ( parent ); +INSERT INTO parent VALUES ( 1, 'p1' ); +INSERT INTO child1 VALUES ( 11, 'c11' ),( 12, 'c12' ); +INSERT INTO child2 VALUES ( 23, 'c21' ),( 24, 'c22' ); +-- start_ignore +-- This query fails due to the 2 stage agg having issues with inherited tables: +-- ERROR: incompatible loci in target inheritance set (planner.c:1426) +WITH rcte AS ( SELECT sum(id) AS totalid FROM parent ) +UPDATE parent SET id = id + totalid FROM rcte; +SELECT * FROM parent; + id | val +----+----- + 72 | p1 + 82 | c11 + 83 | c12 + 94 | c21 + 95 | c22 +(5 rows) + +-- end_ignore +WITH wcte AS ( INSERT INTO child1 VALUES ( 42, 'new' ) RETURNING id AS newid ) +UPDATE parent SET id = id + newid FROM wcte; +ERROR: writable CTE queries cannot be themselves writable +DETAIL: Greenplum Database currently only support CTEs with one writable clause, called in a non-writable context. +HINT: Rewrite the query to only include one writable clause. +SELECT * FROM parent; + id | val +----+----- + 1 | p1 + 11 | c11 + 12 | c12 + 23 | c21 + 24 | c22 +(5 rows) + +WITH rcte AS ( SELECT max(id) AS maxid FROM parent ) +DELETE FROM parent USING rcte WHERE id = maxid; +SELECT * FROM parent; + id | val +----+----- + 1 | p1 + 11 | c11 + 12 | c12 + 23 | c21 +(4 rows) + +WITH wcte AS ( INSERT INTO child2 VALUES ( 42, 'new2' ) RETURNING id AS newid ) +DELETE FROM parent USING wcte WHERE id = newid; +ERROR: writable CTE queries cannot be themselves writable +DETAIL: Greenplum Database currently only support CTEs with one writable clause, called in a non-writable context. +HINT: Rewrite the query to only include one writable clause. +SELECT * FROM parent; + id | val +----+----- + 1 | p1 + 11 | c11 + 12 | c12 + 23 | c21 +(4 rows) + +-- check EXPLAIN VERBOSE for a wCTE with RETURNING +EXPLAIN (VERBOSE, COSTS OFF) +WITH wcte AS ( INSERT INTO int8_tbl VALUES ( 42, 47 ) RETURNING q2 ) +DELETE FROM a USING wcte WHERE aa = q2; +ERROR: writable CTE queries cannot be themselves writable +DETAIL: Greenplum Database currently only support CTEs with one writable clause, called in a non-writable context. +HINT: Rewrite the query to only include one writable clause. +-- error cases +-- data-modifying WITH tries to use its own output +WITH RECURSIVE t AS ( + INSERT INTO y + SELECT * FROM t +) +VALUES(FALSE); +ERROR: recursive query "t" must not contain data-modifying statements +LINE 1: WITH RECURSIVE t AS ( + ^ +-- no RETURNING in a referenced data-modifying WITH +WITH t AS ( + INSERT INTO y VALUES(0) +) +SELECT * FROM t; +ERROR: WITH query "t" does not have a RETURNING clause +LINE 4: SELECT * FROM t; + ^ +-- data-modifying WITH allowed only at the top level +SELECT * FROM ( + WITH t AS (UPDATE y SET a=a+1 RETURNING *) + SELECT * FROM t +) ss; +ERROR: WITH clause containing a data-modifying statement must be at the top level +LINE 2: WITH t AS (UPDATE y SET a=a+1 RETURNING *) + ^ +-- most variants of rules aren't allowed +CREATE RULE y_rule AS ON INSERT TO y WHERE a=0 DO INSTEAD DELETE FROM y; +WITH t AS ( + INSERT INTO y VALUES(0) +) +VALUES(FALSE); +ERROR: conditional DO INSTEAD rules are not supported for data-modifying statements in WITH +DROP RULE y_rule ON y; +CREATE TABLE rank_tbl (id int, rank int) DISTRIBUTED BY (id); +insert into rank_tbl select i, i % 11 from generate_series(1, 100)i; +-- this used to raise ERROR: INSERT/UPDATE/DELETE must be executed by a writer segworker group +-- case we assign write gang to read slice +WITH updated AS ( + update rank_tbl set rank = 6 where id = 5 returning rank +) +select count(*) from rank_tbl where rank in (select rank from updated); + count +------- + 9 +(1 row) + +-- Test that the planner can build a plan with non-select CTE sharing. +--start_ignore +DROP TABLE IF EXISTS t1; +NOTICE: table "t1" does not exist, skipping +--end_ignore +CREATE TABLE t1 (c1 int, c2 int) DISTRIBUTED RANDOMLY; +EXPLAIN (VERBOSE, COSTS OFF) +WITH cte1 AS ( + INSERT INTO t1 VALUES ( 1, 2 ) RETURNING * +) +SELECT * FROM cte1 a JOIN cte1 b USING (c1); + QUERY PLAN +------------------------------------------------------------------------------------------------ + Gather Motion 3:1 (slice3; segments: 3) + Output: share0_ref3.c1, share0_ref3.c2, share0_ref2.c2 + -> Sequence + Output: share0_ref3.c1, share0_ref3.c2, share0_ref2.c2 + -> Shared Scan (share slice:id 3:0) + Output: share0_ref1.c1, share0_ref1.c2 + -> Materialize + Output: "outer".c1, "outer".c2 + -> Insert + Output: "outer".c1, "outer".c2, "outer".ColRef_0036 + -> Redistribute Motion 3:3 (slice2; segments: 3) + Output: "outer".c1, "outer".c2, "outer".ColRef_0036 + -> Result + Output: 1, 2, 1 + -> Result + One-Time Filter: (gp_execution_segment() = 1) + -> Result + -> Result + Output: true + -> Hash Join + Output: share0_ref3.c1, share0_ref3.c2, share0_ref2.c2 + Hash Cond: (share0_ref3.c1 = share0_ref2.c1) + -> Shared Scan (share slice:id 3:0) + Output: share0_ref3.c1, share0_ref3.c2 + -> Hash + Output: share0_ref2.c1, share0_ref2.c2 + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: share0_ref2.c1, share0_ref2.c2 + -> Shared Scan (share slice:id 1:0) + Output: share0_ref2.c1, share0_ref2.c2 + Optimizer: Pivotal Optimizer (GPORCA) +(31 rows) + +WITH cte1 AS ( + INSERT INTO t1 VALUES ( 1, 2 ) RETURNING * +) +SELECT * FROM cte1 a JOIN cte1 b USING (c1); + c1 | c2 | c2 +----+----+---- + 1 | 2 | 2 +(1 row) + +DROP TABLE t1; +-- Ensure that prefetch is not disabled for HashJoin in case of join at single segment. +-- Test Shared Scan producer is executed under inner part of join first and the +-- deadlock between Shared Scans does not occur +SET optimizer = off; +--start_ignore +DROP TABLE IF EXISTS d; +--end_ignore +CREATE TABLE d (c1 int, c2 int) DISTRIBUTED BY (c1); +INSERT INTO d VALUES ( 2, 0 ),( 2, 0 ); +WITH cte AS ( + SELECT count(*) c1 FROM d +) SELECT * FROM cte a JOIN (SELECT * FROM d JOIN cte USING (c1) LIMIT 1) b USING (c1); + c1 | c2 +----+---- + 2 | 0 +(1 row) + +-- Test cross slice Shared Scan with consumer in slice 0. +-- The consumer should be in slice 0 +EXPLAIN (COSTS OFF) WITH cte AS ( + SELECT c1 FROM d LIMIT 2 +) +SELECT * FROM cte a JOIN (SELECT * FROM d JOIN cte USING (c1) LIMIT 1) b USING (c1); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------ + Hash Join + Hash Cond: (share0_ref2.c1 = b.c1) + -> Shared Scan (share slice:id 0:0) + -> Hash + -> Subquery Scan on b + -> Limit + -> Gather Motion 3:1 (slice3; segments: 3) + -> Limit + -> Hash Join + Hash Cond: (d.c1 = share0_ref1.c1) + -> Seq Scan on d + -> Hash + -> Redistribute Motion 1:3 (slice2) + Hash Key: share0_ref1.c1 + -> Shared Scan (share slice:id 2:0) + -> Materialize + -> Limit + -> Gather Motion 3:1 (slice1; segments: 3) + -> Limit + -> Seq Scan on d d_1 + Optimizer: Postgres query optimizer +(21 rows) + +-- Deadlock shouldn't happen +WITH cte AS ( + SELECT c1 FROM d LIMIT 2 +) +SELECT * FROM cte a JOIN (SELECT * FROM d JOIN cte USING (c1) LIMIT 1) b USING (c1); + c1 | c2 +----+---- + 2 | 0 + 2 | 0 +(2 rows) + +RESET optimizer; +DROP TABLE d; +-- Test if sharing is disabled for a SegmentGeneral CTE to avoid deadlock if CTE is +-- executed with 1-gang and joined with n-gang +SET optimizer = off; +--start_ignore +DROP TABLE IF EXISTS d; +NOTICE: table "d" does not exist, skipping +DROP TABLE IF EXISTS r; +NOTICE: table "r" does not exist, skipping +--end_ignore +CREATE TABLE d (a int, b int) DISTRIBUTED BY (a); +INSERT INTO d VALUES ( 1, 2 ),( 2, 3 ); +CREATE TABLE r (a int, b int) DISTRIBUTED REPLICATED; +INSERT INTO r VALUES ( 1, 2 ),( 3, 4 ); +EXPLAIN (COSTS off) +WITH cte AS ( + SELECT count(*) a FROM r +) SELECT * FROM cte JOIN (SELECT * FROM d JOIN cte USING (a) LIMIT 1) d_join_cte USING (a); + QUERY PLAN +--------------------------------------------------------------- + Hash Join + Hash Cond: (d_join_cte.a = (count(*))) + -> Subquery Scan on d_join_cte + -> Limit + -> Gather Motion 3:1 (slice1; segments: 3) + -> Limit + -> Hash Join + Hash Cond: (d.a = (count(*))) + -> Seq Scan on d + -> Hash + -> Aggregate + -> Seq Scan on r + -> Hash + -> Gather Motion 1:1 (slice2; segments: 1) + -> Aggregate + -> Seq Scan on r r_1 + Optimizer: Postgres query optimizer +(17 rows) + +WITH cte AS ( + SELECT count(*) a FROM r +) SELECT * FROM cte JOIN (SELECT * FROM d JOIN cte USING (a) LIMIT 1) d_join_cte USING (a); + a | b +---+--- + 2 | 3 +(1 row) + +-- Test if sharing is disabled for a General CTE to avoid deadlock if CTE is +-- executed with coordinator gang and joined with n-gang +EXPLAIN (COSTS OFF) +WITH cte AS ( + SELECT count(*) a FROM (VALUES ( 1, 2 ),( 3, 4 )) v +) +SELECT * FROM cte JOIN (SELECT * FROM d JOIN cte USING (a) LIMIT 1) d_join_cte USING (a); + QUERY PLAN +--------------------------------------------------------------------------- + Hash Join + Hash Cond: (d_join_cte.a = (count(*))) + -> Subquery Scan on d_join_cte + -> Limit + -> Gather Motion 3:1 (slice1; segments: 3) + -> Limit + -> Hash Join + Hash Cond: (d.a = (count(*))) + -> Seq Scan on d + -> Hash + -> Aggregate + -> Values Scan on "*VALUES*" + -> Hash + -> Aggregate + -> Values Scan on "*VALUES*_1" + Optimizer: Postgres query optimizer +(16 rows) + +WITH cte AS ( + SELECT count(*) a FROM (VALUES ( 1, 2 ),( 3, 4 )) v +) +SELECT * FROM cte JOIN (SELECT * FROM d JOIN cte USING (a) LIMIT 1) d_join_cte USING (a); + a | b +---+--- + 2 | 3 +(1 row) + +RESET optimizer; +DROP TABLE d; +DROP TABLE r; diff --git a/src/test/regress/sql/with.sql b/src/test/regress/sql/with.sql index e4b3ff91be1f..5b0028f5b9e0 100644 --- a/src/test/regress/sql/with.sql +++ b/src/test/regress/sql/with.sql @@ -1052,7 +1052,6 @@ select count(*) from rank_tbl where rank in (select rank from updated); DROP TABLE IF EXISTS t1; --end_ignore CREATE TABLE t1 (c1 int, c2 int) DISTRIBUTED RANDOMLY; -SET optimizer = off; EXPLAIN (VERBOSE, COSTS OFF) WITH cte1 AS ( @@ -1066,7 +1065,6 @@ WITH cte1 AS ( SELECT * FROM cte1 a JOIN cte1 b USING (c1); DROP TABLE t1; -RESET optimizer; -- Ensure that prefetch is not disabled for HashJoin in case of join at single segment. -- Test Shared Scan producer is executed under inner part of join first and the From 8ba5b19589bd604ef5577979698b3918cee11223 Mon Sep 17 00:00:00 2001 From: kotb Date: Sun, 16 Mar 2025 12:57:26 +0300 Subject: [PATCH 26/74] fix parsing after reordering --- .../gporca/data/dxl/parse_tests/q57-DMLDelete.xml | 2 +- .../gporca/data/dxl/parse_tests/q58-DMLInsert.xml | 2 +- .../gporca/data/dxl/parse_tests/q60-DMLUpdate.xml | 2 +- .../src/parser/CParseHandlerPhysicalDML.cpp | 12 ++++++------ 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/backend/gporca/data/dxl/parse_tests/q57-DMLDelete.xml b/src/backend/gporca/data/dxl/parse_tests/q57-DMLDelete.xml index 3d3bc00350d8..f7c7cca57496 100644 --- a/src/backend/gporca/data/dxl/parse_tests/q57-DMLDelete.xml +++ b/src/backend/gporca/data/dxl/parse_tests/q57-DMLDelete.xml @@ -6,6 +6,7 @@ + @@ -14,7 +15,6 @@ - diff --git a/src/backend/gporca/data/dxl/parse_tests/q58-DMLInsert.xml b/src/backend/gporca/data/dxl/parse_tests/q58-DMLInsert.xml index 3ecc9607d996..dd121facafba 100644 --- a/src/backend/gporca/data/dxl/parse_tests/q58-DMLInsert.xml +++ b/src/backend/gporca/data/dxl/parse_tests/q58-DMLInsert.xml @@ -28,6 +28,7 @@ + @@ -39,7 +40,6 @@ - diff --git a/src/backend/gporca/data/dxl/parse_tests/q60-DMLUpdate.xml b/src/backend/gporca/data/dxl/parse_tests/q60-DMLUpdate.xml index 65157473d473..83ab9390b69f 100644 --- a/src/backend/gporca/data/dxl/parse_tests/q60-DMLUpdate.xml +++ b/src/backend/gporca/data/dxl/parse_tests/q60-DMLUpdate.xml @@ -6,6 +6,7 @@ + @@ -17,7 +18,6 @@ - diff --git a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerPhysicalDML.cpp b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerPhysicalDML.cpp index 96ead8df8057..9229627763bf 100644 --- a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerPhysicalDML.cpp +++ b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerPhysicalDML.cpp @@ -145,19 +145,19 @@ CParseHandlerPhysicalDML::StartElement(const XMLCh *const, // element_uri, m_parse_handler_mgr, this); m_parse_handler_mgr->ActivateParseHandler(table_descr_parse_handler); - // parse handler for the returning proj list - CParseHandlerBase *proj_list_output_parse_handler = + // parse handler for the proj list + CParseHandlerBase *proj_list_parse_handler = CParseHandlerFactory::GetParseHandler( m_mp, CDXLTokens::XmlstrToken(EdxltokenScalarProjList), m_parse_handler_mgr, this); - m_parse_handler_mgr->ActivateParseHandler(proj_list_output_parse_handler); + m_parse_handler_mgr->ActivateParseHandler(proj_list_parse_handler); - // parse handler for the proj list - CParseHandlerBase *proj_list_parse_handler = + // parse handler for the returning proj list + CParseHandlerBase *proj_list_output_parse_handler = CParseHandlerFactory::GetParseHandler( m_mp, CDXLTokens::XmlstrToken(EdxltokenScalarProjList), m_parse_handler_mgr, this); - m_parse_handler_mgr->ActivateParseHandler(proj_list_parse_handler); + m_parse_handler_mgr->ActivateParseHandler(proj_list_output_parse_handler); //parse handler for the direct dispatch info CParseHandlerBase *direct_dispatch_parse_handler = From 37f29bbcedb2942d13654d565edd62e0e1da53f2 Mon Sep 17 00:00:00 2001 From: kotb Date: Sun, 16 Mar 2025 13:12:51 +0300 Subject: [PATCH 27/74] actualize gporca test after reordering proj lists --- .../DML-ComputeScalar-With-Outerref.mdp | 2 +- .../dxl/minidump/DML-Filter-With-OuterRef.mdp | 2 +- .../dxl/minidump/DML-Replicated-Input.mdp | 2 +- .../minidump/DML-UnionAll-With-OuterRef.mdp | 2 +- .../DML-UnionAll-With-Universal-Child.mdp | 2 +- .../dxl/minidump/DML-Volatile-Function.mdp | 2 +- ...ith-CorrelatedNLJ-With-Universal-Child.mdp | 2 +- .../DML-With-Join-With-Universal-Child.mdp | 2 +- .../gporca/data/dxl/minidump/DeleteInCTE.mdp | 2 +- .../data/dxl/minidump/DeleteReturning.mdp | 147 +++++----- ...nsert-Parquet-Partitioned-SortDisabled.mdp | 2 +- .../data/dxl/minidump/Insert-Parquet.mdp | 2 +- .../dxl/minidump/Insert-With-HJ-CTE-Agg.mdp | 2 +- .../gporca/data/dxl/minidump/Insert.mdp | 2 +- .../data/dxl/minidump/InsertAssertSort.mdp | 2 +- .../dxl/minidump/InsertCheckConstraint.mdp | 2 +- .../data/dxl/minidump/InsertConstTuple.mdp | 2 +- .../InsertConstTupleRandomDistribution.mdp | 2 +- .../InsertConstTupleVolatileFunction.mdp | 2 +- ...nsertConstTupleVolatileFunctionMOTable.mdp | 2 +- .../gporca/data/dxl/minidump/InsertInCTE.mdp | 16 +- .../data/dxl/minidump/InsertIntoReturning.mdp | 102 ++----- .../dxl/minidump/InsertMasterOnlyTable.mdp | 2 +- .../InsertMasterOnlyTableConstTuple.mdp | 2 +- .../InsertMismatchedDistrubution-2.mdp | 2 +- .../minidump/InsertMismatchedDistrubution.mdp | 2 +- .../minidump/InsertNULLNotNULLConstraint.mdp | 2 +- .../minidump/InsertNoEnforceConstraints.mdp | 2 +- .../data/dxl/minidump/InsertNotNullCols.mdp | 2 +- .../minidump/InsertPrimaryKeyFromMOTable.mdp | 2 +- .../data/dxl/minidump/InsertProjectSort.mdp | 2 +- .../data/dxl/minidump/InsertRandomDistr.mdp | 2 +- .../gporca/data/dxl/minidump/InsertSort.mdp | 2 +- .../InsertSortDistributed2MasterOnly.mdp | 2 +- .../dxl/minidump/InsertWithDroppedCol.mdp | 2 +- .../MultipleUpdateWithJoinOnDistCol.mdp | 2 +- .../data/dxl/minidump/PartitionedInsert.mdp | 2 +- .../data/dxl/minidump/PartitionedUpdate.mdp | 2 +- .../gporca/data/dxl/minidump/SelfUpdate.mdp | 2 +- .../dxl/minidump/UpdateCardinalityAssert.mdp | 2 +- .../dxl/minidump/UpdateCheckConstraint.mdp | 2 +- .../UpdateDistKeyMismatchedDistribution.mdp | 2 +- .../minidump/UpdateDistKeyWithNestedJoin.mdp | 2 +- .../data/dxl/minidump/UpdateDistrKey.mdp | 2 +- .../data/dxl/minidump/UpdateDroppedCols.mdp | 2 +- .../gporca/data/dxl/minidump/UpdateInCTE.mdp | 16 +- .../minidump/UpdateNoCardinalityAssert.mdp | 2 +- .../UpdateNoDistKeyMismatchedDistribution.mdp | 2 +- .../minidump/UpdateNoEnforceConstraints.mdp | 2 +- .../data/dxl/minidump/UpdateNotNullCols.mdp | 2 +- .../data/dxl/minidump/UpdatePartTable.mdp | 2 +- .../data/dxl/minidump/UpdateRandomDistr.mdp | 2 +- .../data/dxl/minidump/UpdateReturning.mdp | 257 ++++++++---------- .../dxl/minidump/UpdateUniqueConstraint-2.mdp | 2 +- .../dxl/minidump/UpdateUniqueConstraint.mdp | 2 +- .../dxl/minidump/UpdateVolatileFunction.mdp | 2 +- .../dxl/minidump/UpdateWindowGatherMerge.mdp | 2 +- .../data/dxl/minidump/UpdateWithHashJoin.mdp | 2 +- .../data/dxl/minidump/UpdateWithOids.mdp | 2 +- .../data/dxl/minidump/UpdateWithTriggers.mdp | 12 +- .../data/dxl/minidump/UpdateZeroRows.mdp | 2 +- .../minidump/UpdatingDistributionColumn.mdp | 2 +- .../dxl/minidump/UpdatingMultipleColumn.mdp | 2 +- .../minidump/UpdatingNonDistColSameTable.mdp | 2 +- .../UpdatingNonDistributionColumnFunc.mdp | 2 +- 65 files changed, 293 insertions(+), 375 deletions(-) diff --git a/src/backend/gporca/data/dxl/minidump/DML-ComputeScalar-With-Outerref.mdp b/src/backend/gporca/data/dxl/minidump/DML-ComputeScalar-With-Outerref.mdp index 85fb2b4368f9..007fd1db1896 100644 --- a/src/backend/gporca/data/dxl/minidump/DML-ComputeScalar-With-Outerref.mdp +++ b/src/backend/gporca/data/dxl/minidump/DML-ComputeScalar-With-Outerref.mdp @@ -322,12 +322,12 @@ + - diff --git a/src/backend/gporca/data/dxl/minidump/DML-Filter-With-OuterRef.mdp b/src/backend/gporca/data/dxl/minidump/DML-Filter-With-OuterRef.mdp index f8fe38d54e5b..58dce1e53a92 100644 --- a/src/backend/gporca/data/dxl/minidump/DML-Filter-With-OuterRef.mdp +++ b/src/backend/gporca/data/dxl/minidump/DML-Filter-With-OuterRef.mdp @@ -343,12 +343,12 @@ + - diff --git a/src/backend/gporca/data/dxl/minidump/DML-Replicated-Input.mdp b/src/backend/gporca/data/dxl/minidump/DML-Replicated-Input.mdp index 34807789dc6a..1b74d0f25f54 100644 --- a/src/backend/gporca/data/dxl/minidump/DML-Replicated-Input.mdp +++ b/src/backend/gporca/data/dxl/minidump/DML-Replicated-Input.mdp @@ -344,6 +344,7 @@ WHERE sach_vsnr = 465132477; + @@ -355,7 +356,6 @@ WHERE sach_vsnr = 465132477; - diff --git a/src/backend/gporca/data/dxl/minidump/DML-UnionAll-With-OuterRef.mdp b/src/backend/gporca/data/dxl/minidump/DML-UnionAll-With-OuterRef.mdp index af3cc95e63a0..cf6730e1e209 100644 --- a/src/backend/gporca/data/dxl/minidump/DML-UnionAll-With-OuterRef.mdp +++ b/src/backend/gporca/data/dxl/minidump/DML-UnionAll-With-OuterRef.mdp @@ -390,12 +390,12 @@ + - diff --git a/src/backend/gporca/data/dxl/minidump/DML-UnionAll-With-Universal-Child.mdp b/src/backend/gporca/data/dxl/minidump/DML-UnionAll-With-Universal-Child.mdp index e54aaafd068e..5cf7bf756773 100644 --- a/src/backend/gporca/data/dxl/minidump/DML-UnionAll-With-Universal-Child.mdp +++ b/src/backend/gporca/data/dxl/minidump/DML-UnionAll-With-Universal-Child.mdp @@ -273,12 +273,12 @@ + - diff --git a/src/backend/gporca/data/dxl/minidump/DML-Volatile-Function.mdp b/src/backend/gporca/data/dxl/minidump/DML-Volatile-Function.mdp index 7bb05904ad79..0ca5cc05ff86 100644 --- a/src/backend/gporca/data/dxl/minidump/DML-Volatile-Function.mdp +++ b/src/backend/gporca/data/dxl/minidump/DML-Volatile-Function.mdp @@ -252,12 +252,12 @@ + - diff --git a/src/backend/gporca/data/dxl/minidump/DML-With-CorrelatedNLJ-With-Universal-Child.mdp b/src/backend/gporca/data/dxl/minidump/DML-With-CorrelatedNLJ-With-Universal-Child.mdp index 863d6f461994..5ba8d79fd3ea 100644 --- a/src/backend/gporca/data/dxl/minidump/DML-With-CorrelatedNLJ-With-Universal-Child.mdp +++ b/src/backend/gporca/data/dxl/minidump/DML-With-CorrelatedNLJ-With-Universal-Child.mdp @@ -290,12 +290,12 @@ + - diff --git a/src/backend/gporca/data/dxl/minidump/DML-With-Join-With-Universal-Child.mdp b/src/backend/gporca/data/dxl/minidump/DML-With-Join-With-Universal-Child.mdp index 61af032c2c14..91fa9c36533a 100644 --- a/src/backend/gporca/data/dxl/minidump/DML-With-Join-With-Universal-Child.mdp +++ b/src/backend/gporca/data/dxl/minidump/DML-With-Join-With-Universal-Child.mdp @@ -241,12 +241,12 @@ + - diff --git a/src/backend/gporca/data/dxl/minidump/DeleteInCTE.mdp b/src/backend/gporca/data/dxl/minidump/DeleteInCTE.mdp index 687b04441f92..19bcca02d808 100644 --- a/src/backend/gporca/data/dxl/minidump/DeleteInCTE.mdp +++ b/src/backend/gporca/data/dxl/minidump/DeleteInCTE.mdp @@ -299,7 +299,6 @@ explain with cte as ( - @@ -329,6 +328,7 @@ explain with cte as ( + diff --git a/src/backend/gporca/data/dxl/minidump/DeleteReturning.mdp b/src/backend/gporca/data/dxl/minidump/DeleteReturning.mdp index 516857ac8aab..84c414ad3aca 100644 --- a/src/backend/gporca/data/dxl/minidump/DeleteReturning.mdp +++ b/src/backend/gporca/data/dxl/minidump/DeleteReturning.mdp @@ -22,7 +22,6 @@ delete from ttt returning id, *, ctid; - @@ -157,15 +156,13 @@ delete from ttt returning id, *, ctid; - - - - + + - + @@ -197,109 +194,90 @@ delete from ttt returning id, *, ctid; + - - - - + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - + - - - - + - + - + - - + + - + - @@ -311,10 +289,11 @@ delete from ttt returning id, *, ctid; - + + - + @@ -335,7 +314,7 @@ delete from ttt returning id, *, ctid; - + @@ -354,10 +333,10 @@ delete from ttt returning id, *, ctid; - + - + @@ -370,8 +349,8 @@ delete from ttt returning id, *, ctid; - - + + \ No newline at end of file diff --git a/src/backend/gporca/data/dxl/minidump/Insert-Parquet-Partitioned-SortDisabled.mdp b/src/backend/gporca/data/dxl/minidump/Insert-Parquet-Partitioned-SortDisabled.mdp index ed4743c7d00d..efa3b4db8047 100644 --- a/src/backend/gporca/data/dxl/minidump/Insert-Parquet-Partitioned-SortDisabled.mdp +++ b/src/backend/gporca/data/dxl/minidump/Insert-Parquet-Partitioned-SortDisabled.mdp @@ -231,6 +231,7 @@ + @@ -239,7 +240,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/Insert-Parquet.mdp b/src/backend/gporca/data/dxl/minidump/Insert-Parquet.mdp index 86dadf4f46e4..f59e13d45ba8 100644 --- a/src/backend/gporca/data/dxl/minidump/Insert-Parquet.mdp +++ b/src/backend/gporca/data/dxl/minidump/Insert-Parquet.mdp @@ -212,6 +212,7 @@ + @@ -220,7 +221,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/Insert-With-HJ-CTE-Agg.mdp b/src/backend/gporca/data/dxl/minidump/Insert-With-HJ-CTE-Agg.mdp index d8347adb195a..16e4cfca39d3 100644 --- a/src/backend/gporca/data/dxl/minidump/Insert-With-HJ-CTE-Agg.mdp +++ b/src/backend/gporca/data/dxl/minidump/Insert-With-HJ-CTE-Agg.mdp @@ -508,6 +508,7 @@ + @@ -525,7 +526,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/Insert.mdp b/src/backend/gporca/data/dxl/minidump/Insert.mdp index 5d32bb85f3a7..f99e9ca05059 100644 --- a/src/backend/gporca/data/dxl/minidump/Insert.mdp +++ b/src/backend/gporca/data/dxl/minidump/Insert.mdp @@ -184,6 +184,7 @@ + @@ -192,7 +193,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/InsertAssertSort.mdp b/src/backend/gporca/data/dxl/minidump/InsertAssertSort.mdp index 058f349e9067..c6d10bf5e445 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertAssertSort.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertAssertSort.mdp @@ -367,6 +367,7 @@ explain insert into tbl_cds_buysell_orders_new (a,b,c) + @@ -390,7 +391,6 @@ explain insert into tbl_cds_buysell_orders_new (a,b,c) - diff --git a/src/backend/gporca/data/dxl/minidump/InsertCheckConstraint.mdp b/src/backend/gporca/data/dxl/minidump/InsertCheckConstraint.mdp index 946975b340cb..ec9ece7aae38 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertCheckConstraint.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertCheckConstraint.mdp @@ -289,6 +289,7 @@ + @@ -303,7 +304,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/InsertConstTuple.mdp b/src/backend/gporca/data/dxl/minidump/InsertConstTuple.mdp index 6ac932fb71af..ee66d005c3bf 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertConstTuple.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertConstTuple.mdp @@ -202,6 +202,7 @@ + @@ -210,7 +211,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/InsertConstTupleRandomDistribution.mdp b/src/backend/gporca/data/dxl/minidump/InsertConstTupleRandomDistribution.mdp index ef134dae13e9..6261027d8fb6 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertConstTupleRandomDistribution.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertConstTupleRandomDistribution.mdp @@ -211,6 +211,7 @@ + @@ -219,7 +220,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/InsertConstTupleVolatileFunction.mdp b/src/backend/gporca/data/dxl/minidump/InsertConstTupleVolatileFunction.mdp index 71e869fceda1..5941e87d359b 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertConstTupleVolatileFunction.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertConstTupleVolatileFunction.mdp @@ -233,6 +233,7 @@ + @@ -241,7 +242,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/InsertConstTupleVolatileFunctionMOTable.mdp b/src/backend/gporca/data/dxl/minidump/InsertConstTupleVolatileFunctionMOTable.mdp index 01fc6eb03cb8..859a37cad689 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertConstTupleVolatileFunctionMOTable.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertConstTupleVolatileFunctionMOTable.mdp @@ -223,6 +223,7 @@ + @@ -231,7 +232,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/InsertInCTE.mdp b/src/backend/gporca/data/dxl/minidump/InsertInCTE.mdp index 00b4f838e4a7..23e71ff27b6c 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertInCTE.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertInCTE.mdp @@ -491,14 +491,6 @@ where t1.i in (select i from cte); - - - - - - - - @@ -528,6 +520,14 @@ where t1.i in (select i from cte); + + + + + + + + diff --git a/src/backend/gporca/data/dxl/minidump/InsertIntoReturning.mdp b/src/backend/gporca/data/dxl/minidump/InsertIntoReturning.mdp index a1079db7a879..e265c16609c6 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertIntoReturning.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertIntoReturning.mdp @@ -124,38 +124,6 @@ insert into ttt values (123, 'daad') returning id+length(data); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -166,29 +134,17 @@ insert into ttt values (123, 'daad') returning id+length(data); - + - + - - - - - - - - - - - - @@ -206,12 +162,12 @@ insert into ttt values (123, 'daad') returning id+length(data); - + - + @@ -221,17 +177,13 @@ insert into ttt values (123, 'daad') returning id+length(data); - + - + - - - - - - + + @@ -261,8 +213,8 @@ insert into ttt values (123, 'daad') returning id+length(data); - - + + @@ -272,7 +224,7 @@ insert into ttt values (123, 'daad') returning id+length(data); - + @@ -283,7 +235,7 @@ insert into ttt values (123, 'daad') returning id+length(data); - + @@ -292,14 +244,6 @@ insert into ttt values (123, 'daad') returning id+length(data); - - - - - - - - @@ -308,17 +252,21 @@ insert into ttt values (123, 'daad') returning id+length(data); - + + + + + + + + + - + - - - - - - + + @@ -332,7 +280,7 @@ insert into ttt values (123, 'daad') returning id+length(data); - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertMasterOnlyTable.mdp b/src/backend/gporca/data/dxl/minidump/InsertMasterOnlyTable.mdp index 65d364d88cf4..27eb4d2e9179 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertMasterOnlyTable.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertMasterOnlyTable.mdp @@ -236,6 +236,7 @@ + @@ -244,7 +245,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/InsertMasterOnlyTableConstTuple.mdp b/src/backend/gporca/data/dxl/minidump/InsertMasterOnlyTableConstTuple.mdp index 99fc96d3939e..f29e0d1c90d9 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertMasterOnlyTableConstTuple.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertMasterOnlyTableConstTuple.mdp @@ -177,6 +177,7 @@ + @@ -185,7 +186,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/InsertMismatchedDistrubution-2.mdp b/src/backend/gporca/data/dxl/minidump/InsertMismatchedDistrubution-2.mdp index ddfcb7662959..28680674e7d5 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertMismatchedDistrubution-2.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertMismatchedDistrubution-2.mdp @@ -266,6 +266,7 @@ explain insert into pt2 select * from r; + @@ -277,7 +278,6 @@ explain insert into pt2 select * from r; - diff --git a/src/backend/gporca/data/dxl/minidump/InsertMismatchedDistrubution.mdp b/src/backend/gporca/data/dxl/minidump/InsertMismatchedDistrubution.mdp index 86f60a655e9a..358a2adff453 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertMismatchedDistrubution.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertMismatchedDistrubution.mdp @@ -266,6 +266,7 @@ explain insert into pt2 select * from r; + @@ -277,7 +278,6 @@ explain insert into pt2 select * from r; - diff --git a/src/backend/gporca/data/dxl/minidump/InsertNULLNotNULLConstraint.mdp b/src/backend/gporca/data/dxl/minidump/InsertNULLNotNULLConstraint.mdp index 50cecb044c38..4c9e0ee29ea4 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertNULLNotNULLConstraint.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertNULLNotNULLConstraint.mdp @@ -174,12 +174,12 @@ + - diff --git a/src/backend/gporca/data/dxl/minidump/InsertNoEnforceConstraints.mdp b/src/backend/gporca/data/dxl/minidump/InsertNoEnforceConstraints.mdp index 4d6626819d67..8448beb5926e 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertNoEnforceConstraints.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertNoEnforceConstraints.mdp @@ -209,6 +209,7 @@ insert into constraints_tab values (NULL, -1); + @@ -217,7 +218,6 @@ insert into constraints_tab values (NULL, -1); - diff --git a/src/backend/gporca/data/dxl/minidump/InsertNotNullCols.mdp b/src/backend/gporca/data/dxl/minidump/InsertNotNullCols.mdp index 8aee983f188b..0cd3dd708282 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertNotNullCols.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertNotNullCols.mdp @@ -218,6 +218,7 @@ + @@ -226,7 +227,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/InsertPrimaryKeyFromMOTable.mdp b/src/backend/gporca/data/dxl/minidump/InsertPrimaryKeyFromMOTable.mdp index c52933adcc18..bf8d59806a88 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertPrimaryKeyFromMOTable.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertPrimaryKeyFromMOTable.mdp @@ -238,6 +238,7 @@ + @@ -246,7 +247,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/InsertProjectSort.mdp b/src/backend/gporca/data/dxl/minidump/InsertProjectSort.mdp index a55e6139e508..8db83ecbd83b 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertProjectSort.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertProjectSort.mdp @@ -295,6 +295,7 @@ explain insert into tbl_cds_buysell_orders_new (a,b,c) + @@ -318,7 +319,6 @@ explain insert into tbl_cds_buysell_orders_new (a,b,c) - diff --git a/src/backend/gporca/data/dxl/minidump/InsertRandomDistr.mdp b/src/backend/gporca/data/dxl/minidump/InsertRandomDistr.mdp index 15c7f3d1de52..91f1645a644c 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertRandomDistr.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertRandomDistr.mdp @@ -234,6 +234,7 @@ + @@ -242,7 +243,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/InsertSort.mdp b/src/backend/gporca/data/dxl/minidump/InsertSort.mdp index f2275a970b60..e3e3cbf5432d 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertSort.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertSort.mdp @@ -361,12 +361,12 @@ explain insert into nim1 select * from nim order by 1; + - diff --git a/src/backend/gporca/data/dxl/minidump/InsertSortDistributed2MasterOnly.mdp b/src/backend/gporca/data/dxl/minidump/InsertSortDistributed2MasterOnly.mdp index 7f511bf01dc2..b8bba0e041cf 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertSortDistributed2MasterOnly.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertSortDistributed2MasterOnly.mdp @@ -286,6 +286,7 @@ explain insert into masteronly select * from distributedtable order by 1; + @@ -297,7 +298,6 @@ explain insert into masteronly select * from distributedtable order by 1; - diff --git a/src/backend/gporca/data/dxl/minidump/InsertWithDroppedCol.mdp b/src/backend/gporca/data/dxl/minidump/InsertWithDroppedCol.mdp index 67d75e9738da..a158d691dbd0 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertWithDroppedCol.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertWithDroppedCol.mdp @@ -247,6 +247,7 @@ + @@ -255,7 +256,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/MultipleUpdateWithJoinOnDistCol.mdp b/src/backend/gporca/data/dxl/minidump/MultipleUpdateWithJoinOnDistCol.mdp index c9d11dd7792f..7cebead5d885 100644 --- a/src/backend/gporca/data/dxl/minidump/MultipleUpdateWithJoinOnDistCol.mdp +++ b/src/backend/gporca/data/dxl/minidump/MultipleUpdateWithJoinOnDistCol.mdp @@ -304,6 +304,7 @@ + @@ -312,7 +313,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/PartitionedInsert.mdp b/src/backend/gporca/data/dxl/minidump/PartitionedInsert.mdp index 1cacfed9626d..7e5fa4b19314 100644 --- a/src/backend/gporca/data/dxl/minidump/PartitionedInsert.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartitionedInsert.mdp @@ -219,6 +219,7 @@ + @@ -227,7 +228,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/PartitionedUpdate.mdp b/src/backend/gporca/data/dxl/minidump/PartitionedUpdate.mdp index 1ba9d2796b31..60a0662d7f4c 100644 --- a/src/backend/gporca/data/dxl/minidump/PartitionedUpdate.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartitionedUpdate.mdp @@ -249,6 +249,7 @@ + @@ -257,7 +258,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/SelfUpdate.mdp b/src/backend/gporca/data/dxl/minidump/SelfUpdate.mdp index b101ef64571f..47ab30ae0fb9 100644 --- a/src/backend/gporca/data/dxl/minidump/SelfUpdate.mdp +++ b/src/backend/gporca/data/dxl/minidump/SelfUpdate.mdp @@ -219,6 +219,7 @@ update t1 set b = c; + @@ -230,7 +231,6 @@ update t1 set b = c; - diff --git a/src/backend/gporca/data/dxl/minidump/UpdateCardinalityAssert.mdp b/src/backend/gporca/data/dxl/minidump/UpdateCardinalityAssert.mdp index 6b208aca8332..5263cb84d408 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateCardinalityAssert.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateCardinalityAssert.mdp @@ -278,6 +278,7 @@ + @@ -286,7 +287,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/UpdateCheckConstraint.mdp b/src/backend/gporca/data/dxl/minidump/UpdateCheckConstraint.mdp index d1e8035edeb6..24344ff05d26 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateCheckConstraint.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateCheckConstraint.mdp @@ -299,6 +299,7 @@ + @@ -313,7 +314,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/UpdateDistKeyMismatchedDistribution.mdp b/src/backend/gporca/data/dxl/minidump/UpdateDistKeyMismatchedDistribution.mdp index 80573d1b7b0c..7422bf0dcbe8 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateDistKeyMismatchedDistribution.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateDistKeyMismatchedDistribution.mdp @@ -305,6 +305,7 @@ + @@ -316,7 +317,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/UpdateDistKeyWithNestedJoin.mdp b/src/backend/gporca/data/dxl/minidump/UpdateDistKeyWithNestedJoin.mdp index 80f6cdcf9fe8..642a028f0345 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateDistKeyWithNestedJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateDistKeyWithNestedJoin.mdp @@ -683,6 +683,7 @@ WHERE t1.id1 = t2.id1; + @@ -691,7 +692,6 @@ WHERE t1.id1 = t2.id1; - diff --git a/src/backend/gporca/data/dxl/minidump/UpdateDistrKey.mdp b/src/backend/gporca/data/dxl/minidump/UpdateDistrKey.mdp index ed407018f10f..24a02103d822 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateDistrKey.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateDistrKey.mdp @@ -273,6 +273,7 @@ + @@ -281,7 +282,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/UpdateDroppedCols.mdp b/src/backend/gporca/data/dxl/minidump/UpdateDroppedCols.mdp index 1980af473399..0f232f6eaf80 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateDroppedCols.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateDroppedCols.mdp @@ -250,6 +250,7 @@ + @@ -258,7 +259,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/UpdateInCTE.mdp b/src/backend/gporca/data/dxl/minidump/UpdateInCTE.mdp index 3474112dff99..a6a28fcee59e 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateInCTE.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateInCTE.mdp @@ -299,14 +299,6 @@ explain with cte as ( - - - - - - - - @@ -336,6 +328,14 @@ explain with cte as ( + + + + + + + + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateNoCardinalityAssert.mdp b/src/backend/gporca/data/dxl/minidump/UpdateNoCardinalityAssert.mdp index 1c05805f97b0..b5384c6547c0 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateNoCardinalityAssert.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateNoCardinalityAssert.mdp @@ -396,6 +396,7 @@ + @@ -404,7 +405,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/UpdateNoDistKeyMismatchedDistribution.mdp b/src/backend/gporca/data/dxl/minidump/UpdateNoDistKeyMismatchedDistribution.mdp index cd30c13a9f48..ddf01da09f00 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateNoDistKeyMismatchedDistribution.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateNoDistKeyMismatchedDistribution.mdp @@ -306,6 +306,7 @@ + @@ -317,7 +318,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/UpdateNoEnforceConstraints.mdp b/src/backend/gporca/data/dxl/minidump/UpdateNoEnforceConstraints.mdp index 3a16d0c4195a..03e1e4cae250 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateNoEnforceConstraints.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateNoEnforceConstraints.mdp @@ -241,6 +241,7 @@ update constraints_tab SET notnullcol = NULL, positivecol =-1; + @@ -252,7 +253,6 @@ update constraints_tab SET notnullcol = NULL, positivecol =-1; - diff --git a/src/backend/gporca/data/dxl/minidump/UpdateNotNullCols.mdp b/src/backend/gporca/data/dxl/minidump/UpdateNotNullCols.mdp index f7f6b567bf23..1e2afe996581 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateNotNullCols.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateNotNullCols.mdp @@ -333,6 +333,7 @@ + @@ -341,7 +342,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/UpdatePartTable.mdp b/src/backend/gporca/data/dxl/minidump/UpdatePartTable.mdp index c9bc12c55994..395d4577acb5 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdatePartTable.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdatePartTable.mdp @@ -250,6 +250,7 @@ + @@ -258,7 +259,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/UpdateRandomDistr.mdp b/src/backend/gporca/data/dxl/minidump/UpdateRandomDistr.mdp index 02b5a3e16440..f7877ec5cfb4 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateRandomDistr.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateRandomDistr.mdp @@ -201,6 +201,7 @@ + @@ -209,7 +210,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/UpdateReturning.mdp b/src/backend/gporca/data/dxl/minidump/UpdateReturning.mdp index ae88e46cd062..5cb091c1be17 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateReturning.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateReturning.mdp @@ -156,14 +156,14 @@ update ttt set id = 1 returning data; - - - + + + - + @@ -198,82 +198,94 @@ update ttt set id = 1 returning data; - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - + - + + - + - - - + + + + + + + + + + + + + + + + + + + + + + - + - @@ -281,28 +293,26 @@ update ttt set id = 1 returning data; - - - - + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + - + @@ -317,20 +327,13 @@ update ttt set id = 1 returning data; - - + + - - - - - - - - + - + @@ -339,19 +342,21 @@ update ttt set id = 1 returning data; + + + - - - - + + + - + @@ -360,9 +365,6 @@ update ttt set id = 1 returning data; - - - @@ -371,45 +373,24 @@ update ttt set id = 1 returning data; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateUniqueConstraint-2.mdp b/src/backend/gporca/data/dxl/minidump/UpdateUniqueConstraint-2.mdp index 6861ac0695ea..96e743c856ee 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateUniqueConstraint-2.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateUniqueConstraint-2.mdp @@ -768,6 +768,7 @@ + @@ -776,7 +777,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/UpdateUniqueConstraint.mdp b/src/backend/gporca/data/dxl/minidump/UpdateUniqueConstraint.mdp index abc6b8052e95..088daabd29d1 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateUniqueConstraint.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateUniqueConstraint.mdp @@ -201,6 +201,7 @@ + @@ -209,7 +210,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/UpdateVolatileFunction.mdp b/src/backend/gporca/data/dxl/minidump/UpdateVolatileFunction.mdp index 0907b745d581..3b59bfc0f46a 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateVolatileFunction.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateVolatileFunction.mdp @@ -416,6 +416,7 @@ + @@ -424,7 +425,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/UpdateWindowGatherMerge.mdp b/src/backend/gporca/data/dxl/minidump/UpdateWindowGatherMerge.mdp index e05a7a4d2a15..5502c0a3cac2 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateWindowGatherMerge.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateWindowGatherMerge.mdp @@ -712,6 +712,7 @@ + @@ -720,7 +721,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/UpdateWithHashJoin.mdp b/src/backend/gporca/data/dxl/minidump/UpdateWithHashJoin.mdp index 1c8ad1c4268b..3f5f1fb65c70 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateWithHashJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateWithHashJoin.mdp @@ -304,6 +304,7 @@ + @@ -312,7 +313,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/UpdateWithOids.mdp b/src/backend/gporca/data/dxl/minidump/UpdateWithOids.mdp index 17358b21e0bb..0f8161342c09 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateWithOids.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateWithOids.mdp @@ -211,6 +211,7 @@ + @@ -219,7 +220,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/UpdateWithTriggers.mdp b/src/backend/gporca/data/dxl/minidump/UpdateWithTriggers.mdp index 4ddc9357d783..09e41d931102 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateWithTriggers.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateWithTriggers.mdp @@ -220,7 +220,17 @@ - + + + + + + + + + + + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateZeroRows.mdp b/src/backend/gporca/data/dxl/minidump/UpdateZeroRows.mdp index 54d79c26d7bc..83ad08c75077 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateZeroRows.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateZeroRows.mdp @@ -413,6 +413,7 @@ + @@ -424,7 +425,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/UpdatingDistributionColumn.mdp b/src/backend/gporca/data/dxl/minidump/UpdatingDistributionColumn.mdp index 90bdae67b35d..9a241eff7a37 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdatingDistributionColumn.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdatingDistributionColumn.mdp @@ -273,6 +273,7 @@ + @@ -281,7 +282,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/UpdatingMultipleColumn.mdp b/src/backend/gporca/data/dxl/minidump/UpdatingMultipleColumn.mdp index 64f478dd8359..4f2c3a8e6559 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdatingMultipleColumn.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdatingMultipleColumn.mdp @@ -586,6 +586,7 @@ + @@ -594,7 +595,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/UpdatingNonDistColSameTable.mdp b/src/backend/gporca/data/dxl/minidump/UpdatingNonDistColSameTable.mdp index 461a2e91fd95..3ff155a899f1 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdatingNonDistColSameTable.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdatingNonDistColSameTable.mdp @@ -237,6 +237,7 @@ + @@ -248,7 +249,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/UpdatingNonDistributionColumnFunc.mdp b/src/backend/gporca/data/dxl/minidump/UpdatingNonDistributionColumnFunc.mdp index faa17ed7e34c..f96568bff261 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdatingNonDistributionColumnFunc.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdatingNonDistributionColumnFunc.mdp @@ -242,6 +242,7 @@ + @@ -250,7 +251,6 @@ - From c1bf55130a9b363139240ccbbaebdd831d93ac9a Mon Sep 17 00:00:00 2001 From: kotb Date: Sun, 16 Mar 2025 13:21:55 +0300 Subject: [PATCH 28/74] add gporca tests for DML with returning projection --- .../minidump/DeleteReturningProjection.mdp | 363 +++++++++++++++ .../data/dxl/minidump/InsertIntoReturning.mdp | 215 ++++----- .../InsertIntoReturningProjection.mdp | 342 ++++++++++++++ .../minidump/UpdateReturningProjection.mdp | 439 ++++++++++++++++++ .../src/unittest/gpopt/minidump/CDMLTest.cpp | 3 + 5 files changed, 1233 insertions(+), 129 deletions(-) create mode 100644 src/backend/gporca/data/dxl/minidump/DeleteReturningProjection.mdp create mode 100644 src/backend/gporca/data/dxl/minidump/InsertIntoReturningProjection.mdp create mode 100644 src/backend/gporca/data/dxl/minidump/UpdateReturningProjection.mdp diff --git a/src/backend/gporca/data/dxl/minidump/DeleteReturningProjection.mdp b/src/backend/gporca/data/dxl/minidump/DeleteReturningProjection.mdp new file mode 100644 index 000000000000..9b889e32b55b --- /dev/null +++ b/src/backend/gporca/data/dxl/minidump/DeleteReturningProjection.mdp @@ -0,0 +1,363 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/backend/gporca/data/dxl/minidump/InsertIntoReturning.mdp b/src/backend/gporca/data/dxl/minidump/InsertIntoReturning.mdp index e265c16609c6..5c6c84bd2724 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertIntoReturning.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertIntoReturning.mdp @@ -3,7 +3,7 @@ set optimizer=on; create table ttt(id bigint, data text) with (appendonly=true) distributed by (id); -insert into ttt values (123, 'daad') returning id+length(data); +insert into ttt values (123, 'daad') returning id; --> @@ -124,17 +124,7 @@ insert into ttt values (123, 'daad') returning id+length(data); - - - - - - - - - - - + @@ -162,96 +152,85 @@ insert into ttt values (123, 'daad') returning id+length(data); - + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - - - + - - - - - - - - - - - - - - - - - - - - - + + + + + + - + - + - - + + - + - + + + + + + - - - - - - - + + - - - + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - @@ -259,19 +238,15 @@ insert into ttt values (123, 'daad') returning id+length(data); + + + - - - - - - - - - - + + + - + @@ -280,62 +255,44 @@ insert into ttt values (123, 'daad') returning id+length(data); - - - - - + + + + + + + - + - + - + - - - - - - + - + - - - - - + + - - - - - - - - - - - - - - - - + + + + diff --git a/src/backend/gporca/data/dxl/minidump/InsertIntoReturningProjection.mdp b/src/backend/gporca/data/dxl/minidump/InsertIntoReturningProjection.mdp new file mode 100644 index 000000000000..e265c16609c6 --- /dev/null +++ b/src/backend/gporca/data/dxl/minidump/InsertIntoReturningProjection.mdp @@ -0,0 +1,342 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/backend/gporca/data/dxl/minidump/UpdateReturningProjection.mdp b/src/backend/gporca/data/dxl/minidump/UpdateReturningProjection.mdp new file mode 100644 index 000000000000..99d81f9c483b --- /dev/null +++ b/src/backend/gporca/data/dxl/minidump/UpdateReturningProjection.mdp @@ -0,0 +1,439 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/backend/gporca/server/src/unittest/gpopt/minidump/CDMLTest.cpp b/src/backend/gporca/server/src/unittest/gpopt/minidump/CDMLTest.cpp index f71a57e6b710..a1abc64a814e 100644 --- a/src/backend/gporca/server/src/unittest/gpopt/minidump/CDMLTest.cpp +++ b/src/backend/gporca/server/src/unittest/gpopt/minidump/CDMLTest.cpp @@ -31,6 +31,9 @@ const CHAR *rgszDMLFileNames[] = { "../data/dxl/minidump/InsertIntoReturning.mdp", "../data/dxl/minidump/DeleteReturning.mdp", "../data/dxl/minidump/UpdateReturning.mdp", + "../data/dxl/minidump/InsertIntoReturningProjection.mdp", + "../data/dxl/minidump/DeleteReturningProjection.mdp", + "../data/dxl/minidump/UpdateReturningProjection.mdp", "../data/dxl/minidump/InsertInCTE.mdp", "../data/dxl/minidump/DeleteInCTE.mdp", "../data/dxl/minidump/UpdateInCTE.mdp", From 3d92813a08ee91a0a7894eb5be19495a9c66a68b Mon Sep 17 00:00:00 2001 From: kotb Date: Sun, 16 Mar 2025 13:52:54 +0300 Subject: [PATCH 29/74] actualize gporca test after reordering proj lists --- .../gporca/data/dxl/minidump/AddRedistributeBeforeInsert-1.mdp | 2 +- .../gporca/data/dxl/minidump/AddRedistributeBeforeInsert-2.mdp | 2 +- .../gporca/data/dxl/minidump/AddRedistributeBeforeInsert-3.mdp | 2 +- .../gporca/data/dxl/minidump/AddRedistributeBeforeInsert-4.mdp | 2 +- .../gporca/data/dxl/minidump/AddRedistributeBeforeInsert-5.mdp | 2 +- .../CPhysicalParallelUnionAllTest/ParallelAppend-Insert.mdp | 2 +- .../gporca/data/dxl/minidump/ConvertHashToRandomInsert.mdp | 2 +- src/backend/gporca/data/dxl/minidump/DMLCollapseProject.mdp | 2 +- .../data/dxl/minidump/DontAddRedistributeBeforeInsert-1.mdp | 2 +- .../data/dxl/minidump/DontAddRedistributeBeforeInsert-2.mdp | 2 +- .../gporca/data/dxl/minidump/InnerJoinOverJoinExcept.mdp | 2 +- .../gporca/data/dxl/minidump/InnerJoinOverJoinExceptAll.mdp | 2 +- .../data/dxl/minidump/InsertDirectedDispatchNullValue.mdp | 2 +- .../data/dxl/minidump/InsertIntoNonNullAfterDroppingColumn.mdp | 2 +- src/backend/gporca/data/dxl/minidump/InsertNonSingleton.mdp | 2 +- .../minidump/InsertReplicatedIntoSerialHashDistributedTable.mdp | 2 +- src/backend/gporca/data/dxl/minidump/ProjectSetFunction.mdp | 2 +- src/backend/gporca/data/dxl/minidump/ReplicatedTableInsert.mdp | 2 +- .../gporca/data/dxl/minidump/ReplicatedTableSequenceInsert.mdp | 2 +- .../gporca/data/dxl/minidump/ReplicatedTableWithAggNoMotion.mdp | 2 +- src/backend/gporca/data/dxl/minidump/SqlFuncDmlScalar.mdp | 2 +- src/backend/gporca/data/dxl/minidump/SqlFuncDmlTvf.mdp | 2 +- src/backend/gporca/data/dxl/minidump/TaintedReplicatedAgg.mdp | 2 +- .../gporca/data/dxl/minidump/TaintedReplicatedFilter.mdp | 2 +- src/backend/gporca/data/dxl/minidump/TaintedReplicatedLimit.mdp | 2 +- .../gporca/data/dxl/minidump/TaintedReplicatedWindowAgg.mdp | 2 +- .../data/dxl/minidump/VolatileFunctionsBelowScalarAgg.mdp | 2 +- 27 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-1.mdp b/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-1.mdp index b8870a0ae449..1f65b9c99246 100644 --- a/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-1.mdp +++ b/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-1.mdp @@ -246,6 +246,7 @@ + @@ -254,7 +255,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-2.mdp b/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-2.mdp index 843693d89d4e..843c2cd47fbd 100644 --- a/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-2.mdp +++ b/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-2.mdp @@ -253,6 +253,7 @@ + @@ -261,7 +262,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-3.mdp b/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-3.mdp index 406721faec97..a086c796e473 100644 --- a/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-3.mdp +++ b/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-3.mdp @@ -283,6 +283,7 @@ + @@ -291,7 +292,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-4.mdp b/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-4.mdp index c71abd37984f..17d6e96ba7ea 100644 --- a/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-4.mdp +++ b/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-4.mdp @@ -337,6 +337,7 @@ + @@ -345,7 +346,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-5.mdp b/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-5.mdp index fa0a8958c6bd..54b89404c80a 100644 --- a/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-5.mdp +++ b/src/backend/gporca/data/dxl/minidump/AddRedistributeBeforeInsert-5.mdp @@ -253,6 +253,7 @@ + @@ -261,7 +262,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/CPhysicalParallelUnionAllTest/ParallelAppend-Insert.mdp b/src/backend/gporca/data/dxl/minidump/CPhysicalParallelUnionAllTest/ParallelAppend-Insert.mdp index cbf383d50d86..05297ab7ec54 100644 --- a/src/backend/gporca/data/dxl/minidump/CPhysicalParallelUnionAllTest/ParallelAppend-Insert.mdp +++ b/src/backend/gporca/data/dxl/minidump/CPhysicalParallelUnionAllTest/ParallelAppend-Insert.mdp @@ -194,12 +194,12 @@ INSERT INTO t VALUES (11),(12),(13); + - diff --git a/src/backend/gporca/data/dxl/minidump/ConvertHashToRandomInsert.mdp b/src/backend/gporca/data/dxl/minidump/ConvertHashToRandomInsert.mdp index bb1d6aa840d5..77262d6ea606 100644 --- a/src/backend/gporca/data/dxl/minidump/ConvertHashToRandomInsert.mdp +++ b/src/backend/gporca/data/dxl/minidump/ConvertHashToRandomInsert.mdp @@ -645,6 +645,7 @@ explain analyze insert into t1 select t2.a,t3.b from t2, t3 where t2.a = t3.a; + @@ -653,7 +654,6 @@ explain analyze insert into t1 select t2.a,t3.b from t2, t3 where t2.a = t3.a; - diff --git a/src/backend/gporca/data/dxl/minidump/DMLCollapseProject.mdp b/src/backend/gporca/data/dxl/minidump/DMLCollapseProject.mdp index 399b4daedbb1..fa0a8c3a5ee6 100644 --- a/src/backend/gporca/data/dxl/minidump/DMLCollapseProject.mdp +++ b/src/backend/gporca/data/dxl/minidump/DMLCollapseProject.mdp @@ -364,6 +364,7 @@ + @@ -378,7 +379,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/DontAddRedistributeBeforeInsert-1.mdp b/src/backend/gporca/data/dxl/minidump/DontAddRedistributeBeforeInsert-1.mdp index d997793fca6b..ef558d4f4c7b 100644 --- a/src/backend/gporca/data/dxl/minidump/DontAddRedistributeBeforeInsert-1.mdp +++ b/src/backend/gporca/data/dxl/minidump/DontAddRedistributeBeforeInsert-1.mdp @@ -357,6 +357,7 @@ Physical plan: + @@ -365,7 +366,6 @@ Physical plan: - diff --git a/src/backend/gporca/data/dxl/minidump/DontAddRedistributeBeforeInsert-2.mdp b/src/backend/gporca/data/dxl/minidump/DontAddRedistributeBeforeInsert-2.mdp index 70cfa98457af..dead8bc5f687 100644 --- a/src/backend/gporca/data/dxl/minidump/DontAddRedistributeBeforeInsert-2.mdp +++ b/src/backend/gporca/data/dxl/minidump/DontAddRedistributeBeforeInsert-2.mdp @@ -224,12 +224,12 @@ + - diff --git a/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExcept.mdp b/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExcept.mdp index 9a72b0948836..dcc00ede0925 100644 --- a/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExcept.mdp +++ b/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExcept.mdp @@ -299,12 +299,12 @@ ON (a.col = b.col); + - diff --git a/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExceptAll.mdp b/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExceptAll.mdp index 1dc95f988779..2a010f80027a 100644 --- a/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExceptAll.mdp +++ b/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExceptAll.mdp @@ -337,12 +337,12 @@ ON (a.col = b.col); + - diff --git a/src/backend/gporca/data/dxl/minidump/InsertDirectedDispatchNullValue.mdp b/src/backend/gporca/data/dxl/minidump/InsertDirectedDispatchNullValue.mdp index 23de0bea2f87..83603077172a 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertDirectedDispatchNullValue.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertDirectedDispatchNullValue.mdp @@ -217,6 +217,7 @@ + @@ -228,7 +229,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/InsertIntoNonNullAfterDroppingColumn.mdp b/src/backend/gporca/data/dxl/minidump/InsertIntoNonNullAfterDroppingColumn.mdp index 29a5bdfd64c3..5d0d4b08f392 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertIntoNonNullAfterDroppingColumn.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertIntoNonNullAfterDroppingColumn.mdp @@ -190,12 +190,12 @@ EXPLAIN INSERT INTO ColumnMapping VALUES (NULL); + - diff --git a/src/backend/gporca/data/dxl/minidump/InsertNonSingleton.mdp b/src/backend/gporca/data/dxl/minidump/InsertNonSingleton.mdp index dd39207da320..4e2f5d9f023e 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertNonSingleton.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertNonSingleton.mdp @@ -305,12 +305,12 @@ EXPLAIN INSERT INTO snackbox SELECT a FROM (SELECT c FROM hottoast LIMIT 3) hott + - diff --git a/src/backend/gporca/data/dxl/minidump/InsertReplicatedIntoSerialHashDistributedTable.mdp b/src/backend/gporca/data/dxl/minidump/InsertReplicatedIntoSerialHashDistributedTable.mdp index 214481151326..81dd333ef59a 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertReplicatedIntoSerialHashDistributedTable.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertReplicatedIntoSerialHashDistributedTable.mdp @@ -321,6 +321,7 @@ EXPLAIN (COSTS OFF) INSERT INTO distributed_table (val1, val2) SELECT val1, val2 + @@ -332,7 +333,6 @@ EXPLAIN (COSTS OFF) INSERT INTO distributed_table (val1, val2) SELECT val1, val2 - diff --git a/src/backend/gporca/data/dxl/minidump/ProjectSetFunction.mdp b/src/backend/gporca/data/dxl/minidump/ProjectSetFunction.mdp index 9b86bc007438..2f338bb6b281 100644 --- a/src/backend/gporca/data/dxl/minidump/ProjectSetFunction.mdp +++ b/src/backend/gporca/data/dxl/minidump/ProjectSetFunction.mdp @@ -232,6 +232,7 @@ + @@ -240,7 +241,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/ReplicatedTableInsert.mdp b/src/backend/gporca/data/dxl/minidump/ReplicatedTableInsert.mdp index 0706c7e72760..9f0c87fbc721 100644 --- a/src/backend/gporca/data/dxl/minidump/ReplicatedTableInsert.mdp +++ b/src/backend/gporca/data/dxl/minidump/ReplicatedTableInsert.mdp @@ -180,6 +180,7 @@ + @@ -188,7 +189,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/ReplicatedTableSequenceInsert.mdp b/src/backend/gporca/data/dxl/minidump/ReplicatedTableSequenceInsert.mdp index b9b452d00361..15b0bc04f0d9 100644 --- a/src/backend/gporca/data/dxl/minidump/ReplicatedTableSequenceInsert.mdp +++ b/src/backend/gporca/data/dxl/minidump/ReplicatedTableSequenceInsert.mdp @@ -302,6 +302,7 @@ + @@ -310,7 +311,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/ReplicatedTableWithAggNoMotion.mdp b/src/backend/gporca/data/dxl/minidump/ReplicatedTableWithAggNoMotion.mdp index f40c35c9b3f0..2300987fa5f3 100644 --- a/src/backend/gporca/data/dxl/minidump/ReplicatedTableWithAggNoMotion.mdp +++ b/src/backend/gporca/data/dxl/minidump/ReplicatedTableWithAggNoMotion.mdp @@ -286,12 +286,12 @@ + - diff --git a/src/backend/gporca/data/dxl/minidump/SqlFuncDmlScalar.mdp b/src/backend/gporca/data/dxl/minidump/SqlFuncDmlScalar.mdp index 17700129bc45..1fb80cc3a3cb 100644 --- a/src/backend/gporca/data/dxl/minidump/SqlFuncDmlScalar.mdp +++ b/src/backend/gporca/data/dxl/minidump/SqlFuncDmlScalar.mdp @@ -298,12 +298,12 @@ LIMIT 999 + - diff --git a/src/backend/gporca/data/dxl/minidump/SqlFuncDmlTvf.mdp b/src/backend/gporca/data/dxl/minidump/SqlFuncDmlTvf.mdp index 1dc4af70fb3d..cb221dad297e 100644 --- a/src/backend/gporca/data/dxl/minidump/SqlFuncDmlTvf.mdp +++ b/src/backend/gporca/data/dxl/minidump/SqlFuncDmlTvf.mdp @@ -308,6 +308,7 @@ LIMIT 999 + @@ -316,7 +317,6 @@ LIMIT 999 - diff --git a/src/backend/gporca/data/dxl/minidump/TaintedReplicatedAgg.mdp b/src/backend/gporca/data/dxl/minidump/TaintedReplicatedAgg.mdp index b588b4ce9f96..1e6bb12152da 100644 --- a/src/backend/gporca/data/dxl/minidump/TaintedReplicatedAgg.mdp +++ b/src/backend/gporca/data/dxl/minidump/TaintedReplicatedAgg.mdp @@ -271,12 +271,12 @@ + - diff --git a/src/backend/gporca/data/dxl/minidump/TaintedReplicatedFilter.mdp b/src/backend/gporca/data/dxl/minidump/TaintedReplicatedFilter.mdp index 3516fbaf308d..d01ba048ca9e 100644 --- a/src/backend/gporca/data/dxl/minidump/TaintedReplicatedFilter.mdp +++ b/src/backend/gporca/data/dxl/minidump/TaintedReplicatedFilter.mdp @@ -253,6 +253,7 @@ + @@ -261,7 +262,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/TaintedReplicatedLimit.mdp b/src/backend/gporca/data/dxl/minidump/TaintedReplicatedLimit.mdp index 120811732fbb..140861caaaac 100644 --- a/src/backend/gporca/data/dxl/minidump/TaintedReplicatedLimit.mdp +++ b/src/backend/gporca/data/dxl/minidump/TaintedReplicatedLimit.mdp @@ -259,12 +259,12 @@ + - diff --git a/src/backend/gporca/data/dxl/minidump/TaintedReplicatedWindowAgg.mdp b/src/backend/gporca/data/dxl/minidump/TaintedReplicatedWindowAgg.mdp index 542b0f228b37..db11251d92ad 100644 --- a/src/backend/gporca/data/dxl/minidump/TaintedReplicatedWindowAgg.mdp +++ b/src/backend/gporca/data/dxl/minidump/TaintedReplicatedWindowAgg.mdp @@ -274,12 +274,12 @@ + - diff --git a/src/backend/gporca/data/dxl/minidump/VolatileFunctionsBelowScalarAgg.mdp b/src/backend/gporca/data/dxl/minidump/VolatileFunctionsBelowScalarAgg.mdp index bfae7ced91e4..358f00c38bc7 100644 --- a/src/backend/gporca/data/dxl/minidump/VolatileFunctionsBelowScalarAgg.mdp +++ b/src/backend/gporca/data/dxl/minidump/VolatileFunctionsBelowScalarAgg.mdp @@ -254,12 +254,12 @@ + - From 23bfff31638cd5d6abaab6718ea75cb6ad69ec6f Mon Sep 17 00:00:00 2001 From: kotb Date: Thu, 20 Mar 2025 11:24:22 +0300 Subject: [PATCH 30/74] fix indent --- src/backend/executor/nodeDML.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/backend/executor/nodeDML.c b/src/backend/executor/nodeDML.c index 74e9e1c63f18..759efe97acbf 100644 --- a/src/backend/executor/nodeDML.c +++ b/src/backend/executor/nodeDML.c @@ -45,10 +45,10 @@ RemapProjection(ProjectionInfo *projInfo, AttrMap *map) int *varNumbers = projInfo->pi_varNumbers; int numSimpleVars = projInfo->pi_numSimpleVars; - for (int i = 0; i < numSimpleVars;++i) - { + for (int i = 0; i < numSimpleVars;++i) + { varNumbers[i] = attrMap(map, varNumbers[i]); - } + } if (projInfo->pi_lastInnerVar > 0) projInfo->pi_lastInnerVar = attrMap(map, projInfo->pi_lastInnerVar); From 50425904a0ee624994e707352ea4cfee1c8c9830 Mon Sep 17 00:00:00 2001 From: kotb Date: Thu, 20 Mar 2025 21:53:51 +0300 Subject: [PATCH 31/74] add tracing fallback to planner in returning_gp test --- src/test/regress/expected/returning_gp.out | 1 + src/test/regress/expected/returning_gp_optimizer.out | 5 +++++ src/test/regress/sql/returning_gp.sql | 2 ++ 3 files changed, 8 insertions(+) diff --git a/src/test/regress/expected/returning_gp.out b/src/test/regress/expected/returning_gp.out index 5eb99a7ceeab..c347ebd7de86 100644 --- a/src/test/regress/expected/returning_gp.out +++ b/src/test/regress/expected/returning_gp.out @@ -1,6 +1,7 @@ -- -- Extra GPDB tests on INSERT/UPDATE/DELETE RETURNING -- +SET optimizer_trace_fallback=ON; CREATE TABLE returning_parttab (distkey int4, partkey int4, i int, t text) DISTRIBUTED BY (distkey) PARTITION BY RANGE (partkey) (START (1) END (10)); diff --git a/src/test/regress/expected/returning_gp_optimizer.out b/src/test/regress/expected/returning_gp_optimizer.out index 84737d1b1221..dae0fd2cd690 100644 --- a/src/test/regress/expected/returning_gp_optimizer.out +++ b/src/test/regress/expected/returning_gp_optimizer.out @@ -1,6 +1,7 @@ -- -- Extra GPDB tests on INSERT/UPDATE/DELETE RETURNING -- +SET optimizer_trace_fallback=ON; CREATE TABLE returning_parttab (distkey int4, partkey int4, i int, t text) DISTRIBUTED BY (distkey) PARTITION BY RANGE (partkey) (START (1) END (10)); @@ -132,6 +133,8 @@ FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate(); CREATE TRIGGER -- Check returning sys attribute on insert INSERT INTO returning_ctid(f2) VALUES ('test') RETURNING ctid; +INFO: GPORCA failed to produce a plan, falling back to planner +DETAIL: Feature not supported: INSERT with triggers ctid ------- (0,1) @@ -170,6 +173,8 @@ FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate(); CREATE TRIGGER -- Check returning sys attribute on insert INSERT INTO returning_ctid_aoco(f2) VALUES ('test') RETURNING ctid; +INFO: GPORCA failed to produce a plan, falling back to planner +DETAIL: Feature not supported: INSERT with triggers ctid -------------- (33554432,2) diff --git a/src/test/regress/sql/returning_gp.sql b/src/test/regress/sql/returning_gp.sql index 8dca66969d82..0e101f2d22c6 100644 --- a/src/test/regress/sql/returning_gp.sql +++ b/src/test/regress/sql/returning_gp.sql @@ -2,6 +2,8 @@ -- Extra GPDB tests on INSERT/UPDATE/DELETE RETURNING -- +SET optimizer_trace_fallback=ON; + CREATE TABLE returning_parttab (distkey int4, partkey int4, i int, t text) DISTRIBUTED BY (distkey) PARTITION BY RANGE (partkey) (START (1) END (10)); From 07bbb643ab95d60a799ee9aa243d5f6c54250a47 Mon Sep 17 00:00:00 2001 From: kotb Date: Fri, 21 Mar 2025 18:30:37 +0300 Subject: [PATCH 32/74] reduplicate deleting output cols in query2dxl --- src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp b/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp index 9405432b5a0b..572528b1d695 100644 --- a/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp +++ b/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp @@ -815,8 +815,6 @@ CTranslatorQueryToDXL::TranslateInsertQueryToDXL() CDXLNode *log_insert_dxlnode = GPOS_NEW(m_mp) CDXLNode(m_mp, insert_dxlnode, query_dxlnode); - CRefCount::SafeRelease(m_dxl_query_output_cols); - log_insert_dxlnode = ProcessReturningList(log_insert_dxlnode, table_descr); return log_insert_dxlnode; @@ -1281,8 +1279,6 @@ CTranslatorQueryToDXL::TranslateDeleteQueryToDXL() CDXLNode *log_delete_dxlnode = GPOS_NEW(m_mp) CDXLNode(m_mp, delete_dxlop, query_dxlnode); - CRefCount::SafeRelease(m_dxl_query_output_cols); - log_delete_dxlnode = ProcessReturningList(log_delete_dxlnode, table_descr); return log_delete_dxlnode; @@ -1402,8 +1398,6 @@ CTranslatorQueryToDXL::TranslateUpdateQueryToDXL() CDXLNode *log_update_dxlnode = GPOS_NEW(m_mp) CDXLNode(m_mp, pdxlopupdate, query_dxlnode); - CRefCount::SafeRelease(m_dxl_query_output_cols); - log_update_dxlnode = ProcessReturningList(log_update_dxlnode, table_descr); return log_update_dxlnode; From b1432403320dda8b517f0ac195325db2ddfd0788 Mon Sep 17 00:00:00 2001 From: kotb Date: Fri, 21 Mar 2025 18:38:06 +0300 Subject: [PATCH 33/74] remove unused methods --- .../gpopt/translate/CTranslatorQueryToDXL.cpp | 39 ++----------------- .../gpopt/translate/CTranslatorQueryToDXL.h | 9 ----- 2 files changed, 4 insertions(+), 44 deletions(-) diff --git a/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp b/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp index 572528b1d695..ee348411beff 100644 --- a/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp +++ b/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp @@ -1160,6 +1160,8 @@ CTranslatorQueryToDXL::ProcessReturningList(CDXLNode *dml_dxlnode, { GPOS_ASSERT(dml_dxlnode != NULL); + CRefCount::SafeRelease(m_dxl_query_output_cols); + if (m_query->returningList != NULL) { IntToUlongMap *sort_group_attno_to_colid_mapping = @@ -3963,24 +3965,9 @@ CTranslatorQueryToDXL::TranslateDerivedTablesToDXL(const RangeTblEntry *rte, //--------------------------------------------------------------------------- CDXLNode * CTranslatorQueryToDXL::TranslateExprToDXL(Expr *expr) -{ - return TranslateExprToDXL(expr, m_var_to_colid_map); -} - -//--------------------------------------------------------------------------- -// @function: -// CTranslatorQueryToDXL::TranslateExprToDXL -// -// @doc: -// Translate the Expr into a CDXLScalar node with specified mapping -// -//--------------------------------------------------------------------------- -CDXLNode * -CTranslatorQueryToDXL::TranslateExprToDXL(Expr *expr, - CMappingVarColId *var_to_colid_map) { CDXLNode *scalar_dxlnode = - m_scalar_translator->TranslateScalarToDXL(expr, var_to_colid_map); + m_scalar_translator->TranslateScalarToDXL(expr, m_var_to_colid_map); GPOS_ASSERT(NULL != scalar_dxlnode); return scalar_dxlnode; @@ -4532,29 +4519,11 @@ CDXLNode * CTranslatorQueryToDXL::TranslateExprToDXLProject(Expr *expr, const CHAR *alias_name, BOOL insist_new_colids) -{ - return TranslateExprToDXLProject(expr, alias_name, m_var_to_colid_map, - insist_new_colids); -} - -//--------------------------------------------------------------------------- -// @function: -// CTranslatorQueryToDXL::TranslateExprToDXLProject -// -// @doc: -// Create a DXL project element node from the target list entry or var. -// The function allocates memory in the translator memory pool, and the caller -// is responsible for freeing it. -//--------------------------------------------------------------------------- -CDXLNode * -CTranslatorQueryToDXL::TranslateExprToDXLProject( - Expr *expr, const CHAR *alias_name, CMappingVarColId *var_to_colid_map, - BOOL insist_new_colids) { GPOS_ASSERT(NULL != expr); // construct a scalar operator - CDXLNode *child_dxlnode = TranslateExprToDXL(expr, var_to_colid_map); + CDXLNode *child_dxlnode = TranslateExprToDXL(expr, m_var_to_colid_map); // get the id and alias for the proj elem ULONG project_elem_id; diff --git a/src/include/gpopt/translate/CTranslatorQueryToDXL.h b/src/include/gpopt/translate/CTranslatorQueryToDXL.h index 0b5154bacf49..3355d510c674 100644 --- a/src/include/gpopt/translate/CTranslatorQueryToDXL.h +++ b/src/include/gpopt/translate/CTranslatorQueryToDXL.h @@ -211,10 +211,6 @@ class CTranslatorQueryToDXL // translate an Expr into CDXLNode CDXLNode *TranslateExprToDXL(Expr *expr); - // translate an Expr into CDXLNode with specified mapping - CDXLNode *TranslateExprToDXL(Expr *expr, - CMappingVarColId *var_to_colid_map); - // translate the JoinExpr (inside FromExpr) into a CDXLLogicalJoin node CDXLNode *TranslateJoinExprInFromToDXL(JoinExpr *join_expr); @@ -302,11 +298,6 @@ class CTranslatorQueryToDXL CDXLNode *TranslateExprToDXLProject(Expr *expr, const CHAR *alias_name, BOOL insist_new_colids = false); - // translate a target list entry or a join alias entry into a project element using specified mapping - CDXLNode *TranslateExprToDXLProject(Expr *expr, const CHAR *alias_name, - CMappingVarColId *var_to_colid_map, - BOOL insist_new_colids = false); - // translate a CTE into a DXL logical CTE operator CDXLNode *TranslateCTEToDXL(const RangeTblEntry *rte, ULONG rti, ULONG current_query_level); From 0ff3182e47ae23e6b063a913f3d2d4a437a98da0 Mon Sep 17 00:00:00 2001 From: kotb Date: Fri, 21 Mar 2025 23:49:51 +0300 Subject: [PATCH 34/74] some leftovers --- src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp b/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp index ee348411beff..3f6028687668 100644 --- a/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp +++ b/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp @@ -4523,7 +4523,7 @@ CTranslatorQueryToDXL::TranslateExprToDXLProject(Expr *expr, GPOS_ASSERT(NULL != expr); // construct a scalar operator - CDXLNode *child_dxlnode = TranslateExprToDXL(expr, m_var_to_colid_map); + CDXLNode *child_dxlnode = TranslateExprToDXL(expr); // get the id and alias for the proj elem ULONG project_elem_id; From 6b6d45b833fe7cb6e1e80360d492d60c733535d8 Mon Sep 17 00:00:00 2001 From: kotb Date: Sat, 22 Mar 2025 01:03:35 +0300 Subject: [PATCH 35/74] copy columns with their usage, this will reduced unused columns in ctes, only for optimization, not critical --- src/backend/gporca/libgpopt/include/gpopt/base/CColRef.h | 6 ++++++ src/backend/gporca/libgpopt/src/base/CUtils.cpp | 1 + 2 files changed, 7 insertions(+) diff --git a/src/backend/gporca/libgpopt/include/gpopt/base/CColRef.h b/src/backend/gporca/libgpopt/include/gpopt/base/CColRef.h index e7686ed27e3e..352a75e4a961 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/base/CColRef.h +++ b/src/backend/gporca/libgpopt/include/gpopt/base/CColRef.h @@ -197,6 +197,12 @@ class CColRef : public gpos::DbgPrintMixin m_used = EUsed; } + void + MarkUsage(EUsedStatus used) + { + m_used = used; + } + void MarkAsUnknown() { diff --git a/src/backend/gporca/libgpopt/src/base/CUtils.cpp b/src/backend/gporca/libgpopt/src/base/CUtils.cpp index 99bcb4b1e520..8942ba6b7f5e 100644 --- a/src/backend/gporca/libgpopt/src/base/CUtils.cpp +++ b/src/backend/gporca/libgpopt/src/base/CUtils.cpp @@ -3489,6 +3489,7 @@ CUtils::PdrgpcrRemapAndCreate(CMemoryPool *mp, CColRefArray *colref_array, { // not found in hashmap, so create a new colref and add to hashmap pcrMapped = col_factory->PcrCopy(colref); + pcrMapped->MarkUsage(colref->GetUsage(true, true)); #ifdef GPOS_DEBUG BOOL result = From c3ae187f31cc8fb5e923ba62389e079e2ea6727e Mon Sep 17 00:00:00 2001 From: kotb Date: Sat, 22 Mar 2025 01:04:17 +0300 Subject: [PATCH 36/74] set result tuple slot to returning after exeecinit because sort node checks it before executing dml node --- src/backend/executor/nodeDML.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/backend/executor/nodeDML.c b/src/backend/executor/nodeDML.c index 759efe97acbf..95410c4c8f0c 100644 --- a/src/backend/executor/nodeDML.c +++ b/src/backend/executor/nodeDML.c @@ -94,6 +94,12 @@ ExecDML(DMLState *node) Assert(action == DML_INSERT || action == DML_DELETE); + /* + * Temporary restore result tuple slot for use in next projection + */ + TupleTableSlot *savedResultTuple = node->ps.ps_ResultTupleSlot; + node->ps.ps_ResultTupleSlot = node->resultTupleSlot; + node->resultTupleSlot = NULL; /* * Reset per-tuple memory context to free any expression evaluation @@ -110,8 +116,7 @@ ExecDML(DMLState *node) node->cleanedUpSlot = ExecFilterJunk(node->junkfilter, projectedSlot); /* restore returning projection result tuple */ - node->ps.ps_ResultTupleSlot = node->resultTupleSlot; - node->resultTupleSlot = NULL; + node->ps.ps_ResultTupleSlot = savedResultTuple; /* * If we are modifying a leaf partition we have to ensure that partition @@ -332,13 +337,16 @@ ExecInitDML(DML *node, EState *estate, int eflags) dmlstate->ps.state->es_result_relation_info->ri_RelationDesc->rd_att->tdhasoid, dmlstate->cleanedUpSlot); + // Sort node reads this slot before dml gets executed, fill it in returning block or leave empty + dmlstate->resultTupleSlot = dmlstate->ps.ps_ResultTupleSlot; + dmlstate->ps.ps_ResultTupleSlot = NULL; + /* * Initialize RETURNING projections if needed. */ if (node->returningList) { TupleTableSlot *slot; - TupleTableSlot *savedResultTuple = dmlstate->ps.ps_ResultTupleSlot; /* Initialize result tuple slot and assign its rowtype */ TupleDesc tupDesc = ExecTypeFromTL(node->returningList, false); @@ -356,10 +364,6 @@ ExecInitDML(DML *node, EState *estate, int eflags) /* Set up a tuple table slot for use for trigger output tuples */ if (estate->es_trig_tuple_slot == NULL) estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate); - - /* temporary store created tuple in dedicated state field and restore saved */ - dmlstate->resultTupleSlot = slot; - dmlstate->ps.ps_ResultTupleSlot = savedResultTuple; } /* From f1a53af5689cbea6235f18960816e5c6d709bf62 Mon Sep 17 00:00:00 2001 From: kotb Date: Sat, 22 Mar 2025 15:09:20 +0300 Subject: [PATCH 37/74] store returning projection in DML plan node's targetlist, save previously stored targetlist in separate field Parent nodes and explain logic is looking into plan node's target list to find out which tuples will be returned by node, so we store in DML targetlist targetentries which will be outputted Currently targetlist stores projection for applying projections on child's results, so we store this targetlist in separate field and shuffle it with returning targetlist when needed --- src/backend/executor/nodeDML.c | 84 ++++++++++--------- src/backend/executor/nodeMaterial.c | 9 +- .../translate/CTranslatorDXLToPlStmt.cpp | 23 ++--- src/backend/nodes/copyfuncs.c | 2 +- src/backend/nodes/outfuncs.c | 2 +- src/backend/nodes/readfast.c | 2 +- src/include/nodes/plannodes.h | 2 +- 7 files changed, 59 insertions(+), 65 deletions(-) diff --git a/src/backend/executor/nodeDML.c b/src/backend/executor/nodeDML.c index 95410c4c8f0c..ea8ff83383eb 100644 --- a/src/backend/executor/nodeDML.c +++ b/src/backend/executor/nodeDML.c @@ -74,6 +74,14 @@ ExecDML(DMLState *node) Assert(outerNode != NULL); + /* Temporary restore result tuple slot for use in next projection */ + TupleTableSlot *returningResultTuple = node->ps.ps_ResultTupleSlot; + node->ps.ps_ResultTupleSlot = node->resultTupleSlot; + + /* Set target list for projection */ + List *returningTargetList = plannode->plan.targetlist; + plannode->plan.targetlist = plannode->projTargetList; + TupleTableSlot *slot = ExecProcNode(outerNode); TupleTableSlot *resultSlot = NULL; @@ -94,13 +102,6 @@ ExecDML(DMLState *node) Assert(action == DML_INSERT || action == DML_DELETE); - /* - * Temporary restore result tuple slot for use in next projection - */ - TupleTableSlot *savedResultTuple = node->ps.ps_ResultTupleSlot; - node->ps.ps_ResultTupleSlot = node->resultTupleSlot; - node->resultTupleSlot = NULL; - /* * Reset per-tuple memory context to free any expression evaluation * storage allocated in the previous tuple cycle. @@ -115,8 +116,9 @@ ExecDML(DMLState *node) /* remove 'junk' columns from tuple */ node->cleanedUpSlot = ExecFilterJunk(node->junkfilter, projectedSlot); - /* restore returning projection result tuple */ - node->ps.ps_ResultTupleSlot = savedResultTuple; + /* restore returning result tuple and taregt list*/ + node->ps.ps_ResultTupleSlot = returningResultTuple; + plannode->plan.targetlist = returningTargetList; /* * If we are modifying a leaf partition we have to ensure that partition @@ -284,6 +286,10 @@ ExecInitDML(DML *node, EState *estate, int eflags) CmdType operation = estate->es_plannedstmt->commandType; ResultRelInfo *resultRelInfo = estate->es_result_relation_info; + /* set target list with projection and save returning target list */ + List *returningTargetList = node->plan.targetlist; + node->plan.targetlist = node->projTargetList; + ExecInitResultTupleSlot(estate, &dmlstate->ps); dmlstate->ps.targetlist = (List *) @@ -337,35 +343,6 @@ ExecInitDML(DML *node, EState *estate, int eflags) dmlstate->ps.state->es_result_relation_info->ri_RelationDesc->rd_att->tdhasoid, dmlstate->cleanedUpSlot); - // Sort node reads this slot before dml gets executed, fill it in returning block or leave empty - dmlstate->resultTupleSlot = dmlstate->ps.ps_ResultTupleSlot; - dmlstate->ps.ps_ResultTupleSlot = NULL; - - /* - * Initialize RETURNING projections if needed. - */ - if (node->returningList) - { - TupleTableSlot *slot; - - /* Initialize result tuple slot and assign its rowtype */ - TupleDesc tupDesc = ExecTypeFromTL(node->returningList, false); - - /* Set up a slot for the output of the RETURNING projection(s) */ - ExecInitResultTupleSlot(estate, &dmlstate->ps); - ExecAssignResultType(&dmlstate->ps, tupDesc); - slot = dmlstate->ps.ps_ResultTupleSlot; - - List *rliststate = (List *) ExecInitExpr((Expr *) node->returningList, &dmlstate->ps); - resultRelInfo->ri_projectReturning = - ExecBuildProjectionInfo(rliststate, dmlstate->ps.ps_ExprContext, slot, - resultRelInfo->ri_RelationDesc->rd_att); - - /* Set up a tuple table slot for use for trigger output tuples */ - if (estate->es_trig_tuple_slot == NULL) - estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate); - } - /* * The comment below is related to ExecInsert(). The code works correctly, * because insert operations always translate full set of attrs to @@ -428,6 +405,37 @@ ExecInitDML(DML *node, EState *estate, int eflags) } } + /* Sort node reads this slot before dml gets executed, fill it here or leave empty */ + dmlstate->resultTupleSlot = dmlstate->ps.ps_ResultTupleSlot; + + /* + * Initialize RETURNING projections if needed. + */ + if (returningTargetList) + { + TupleTableSlot *slot; + + /* Initialize result tuple slot and assign its rowtype */ + TupleDesc tupDesc = ExecTypeFromTL(returningTargetList, false); + + /* Set up a slot for the output of the RETURNING projection(s) */ + ExecInitResultTupleSlot(estate, &dmlstate->ps); + ExecAssignResultType(&dmlstate->ps, tupDesc); + slot = dmlstate->ps.ps_ResultTupleSlot; + + List *rliststate = (List *) ExecInitExpr((Expr *) returningTargetList, &dmlstate->ps); + resultRelInfo->ri_projectReturning = + ExecBuildProjectionInfo(rliststate, dmlstate->ps.ps_ExprContext, slot, + resultRelInfo->ri_RelationDesc->rd_att); + + /* Set up a tuple table slot for use for trigger output tuples */ + if (estate->es_trig_tuple_slot == NULL) + estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate); + } + + /* restore returning target list */ + node->plan.targetlist = returningTargetList; + return dmlstate; } diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c index 77c4ea2f07fc..f9b65aca4622 100644 --- a/src/backend/executor/nodeMaterial.c +++ b/src/backend/executor/nodeMaterial.c @@ -358,14 +358,7 @@ ExecInitMaterial(Material *node, EState *estate, int eflags) * index into range table, while the material may refer to the same relation as "outer" varno) * [JIRA: MPP-25365] */ - List *outerPlanTargetList = outerPlan->targetlist; - if (IsA(outerPlan, DML)) - { - // DML node output is located in returningList - DML *dmlPlan = (DML *) outerPlan; - outerPlanTargetList = dmlPlan->returningList; - } - if (list_length(node->plan.targetlist) != list_length(outerPlanTargetList)) + if (list_length(node->plan.targetlist) != list_length(outerPlan->targetlist)) elog(ERROR, "Material operator does not support projection"); outerPlanState(matstate) = ExecInitNode(outerPlan, estate, eflags); diff --git a/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp b/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp index 7feec1fc6cb0..46ac5f0bd9aa 100644 --- a/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp +++ b/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp @@ -3632,14 +3632,6 @@ CTranslatorDXLToPlStmt::TranslateDXLCTEProducerToSharedScan( child_dxlnode, &child_context, ctxt_translation_prev_siblings); GPOS_ASSERT(NULL != child_plan && "child plan cannot be NULL"); - List *child_plan_target_list = child_plan->targetlist; - if (IsA(child_plan, DML)) - { - // DML node output is located in returningList - DML *dml_plan = (DML *) child_plan; - child_plan_target_list = dml_plan->returningList; - } - CDXLTranslationContextArray *child_contexts = GPOS_NEW(m_mp) CDXLTranslationContextArray(m_mp); child_contexts->Append(&child_context); @@ -3670,7 +3662,7 @@ CTranslatorDXLToPlStmt::TranslateDXLCTEProducerToSharedScan( // materialize does not project, so it must use the child's target list ListCell *lc_target_entry = NULL; materialize_plan->targetlist = NIL; - ForEach(lc_target_entry, child_plan_target_list) + ForEach(lc_target_entry, child_plan->targetlist) { TargetEntry *te = (TargetEntry *) lfirst(lc_target_entry); Var *var_new = gpdb::MakeVar( @@ -3688,13 +3680,12 @@ CTranslatorDXLToPlStmt::TranslateDXLCTEProducerToSharedScan( materialize_plan->nMotionNodes = child_plan->nMotionNodes; child_plan = materialize_plan; - child_plan_target_list = child_plan->targetlist; } // Targetlist mismatch leads to different tuple bindings, see #12796. // We assume targetlist's equivalence. In case of inequality one list // is a subset of another, so it safe to compare only length. - if (list_length(child_plan_target_list) != list_length(plan->targetlist)) + if (list_length(child_plan->targetlist) != list_length(plan->targetlist)) GPOS_RAISE( gpdxl::ExmaDXL, gpdxl::ExmiDXL2PlStmtConversion, GPOS_WSZ_LIT("Shared Scan and child plan targetlist mismatch.")); @@ -4210,13 +4201,14 @@ CTranslatorDXLToPlStmt::TranslateDXLDml( NULL, // translate context for the base table child_contexts, output_context); - dml->returningList = + // set targetlist as list of target entries to be computed for parent nodes + plan->targetlist = TranslateDXLProjList(project_list_output_dxlnode, &base_table_context, child_contexts, output_context); - m_has_returning = m_has_returning || dml->returningList != NIL; + m_has_returning = m_has_returning || plan->targetlist != NIL; - if (dml->returningList != NIL && + if (plan->targetlist != NIL && md_rel->GetRelDistribution() == IMDRelation::EreldistrReplicated) { m_returning_dml_on_replicated = true; @@ -4271,7 +4263,8 @@ CTranslatorDXLToPlStmt::TranslateDXLDml( GPOS_ASSERT(0 != dml->actionColIdx); - plan->targetlist = dml_target_list; + // save targetlist for projection of results from outer nodes + dml->projTargetList = dml_target_list; plan->lefttree = child_plan; plan->nMotionNodes = child_plan->nMotionNodes; diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 232b797d210a..8eb40b8c2f8f 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -1339,7 +1339,7 @@ _copyDML(const DML *from) COPY_SCALAR_FIELD(tupleoidColIdx); COPY_SCALAR_FIELD(tableoidColIdx); COPY_SCALAR_FIELD(canSetTag); - COPY_NODE_FIELD(returningList); + COPY_NODE_FIELD(projTargetList); return newnode; } diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 365f6c7e5bc8..023210377f12 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -1219,7 +1219,7 @@ _outDML(StringInfo str, const DML *node) WRITE_INT_FIELD(tupleoidColIdx); WRITE_INT_FIELD(tableoidColIdx); WRITE_BOOL_FIELD(canSetTag); - WRITE_NODE_FIELD(returningList); + WRITE_NODE_FIELD(projTargetList); _outPlanInfo(str, (Plan *) node); } diff --git a/src/backend/nodes/readfast.c b/src/backend/nodes/readfast.c index 20f7828e62e3..5584e29b41c7 100644 --- a/src/backend/nodes/readfast.c +++ b/src/backend/nodes/readfast.c @@ -2240,7 +2240,7 @@ _readDML(void) READ_INT_FIELD(tupleoidColIdx); READ_INT_FIELD(tableoidColIdx); READ_BOOL_FIELD(canSetTag); - READ_NODE_FIELD(returningList); + READ_NODE_FIELD(projTargetList); readPlanInfo((Plan *)local_node); diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index b162e9c11bc4..3bc58c801c24 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -1330,7 +1330,7 @@ typedef struct DML AttrNumber tupleoidColIdx; /* index of tuple oid column into the target list */ AttrNumber tableoidColIdx; /* index of table oid column into the target list */ bool canSetTag; /* calculate processed tuples */ - List *returningList; /* return-values list (of TargetEntry) */ + List *projTargetList; /* target list for projection of outer node */ } DML; /* From ee5d4e52299aef7e0cd44981c94127b214443e49 Mon Sep 17 00:00:00 2001 From: kotb Date: Sat, 22 Mar 2025 15:09:45 +0300 Subject: [PATCH 38/74] adapt with_clause test --- .../expected/with_clause_optimizer.out | 88 +++++++++++-------- 1 file changed, 51 insertions(+), 37 deletions(-) diff --git a/src/test/regress/expected/with_clause_optimizer.out b/src/test/regress/expected/with_clause_optimizer.out index a2d24028425a..b47630cf54bc 100644 --- a/src/test/regress/expected/with_clause_optimizer.out +++ b/src/test/regress/expected/with_clause_optimizer.out @@ -2431,7 +2431,24 @@ with cte as ( cte2 as ( select * from cte) select * from cte2 a join cte2 b using (i); -ERROR: Too much references to non-SELECT CTE (allpaths.c:2043) + QUERY PLAN +---------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + -> Sequence + -> Shared Scan (share slice:id 1:1) + -> Materialize + -> Insert + -> Result + -> Result + -> Function Scan on generate_series + -> Hash Join + Hash Cond: (share1_ref3.i = share1_ref2.i) + -> Shared Scan (share slice:id 1:1) + -> Hash + -> Shared Scan (share slice:id 1:1) + Optimizer: Pivotal Optimizer (GPORCA) +(14 rows) + create table with_dml_repl (i int, j int) distributed replicated; explain (costs off) with cte as ( @@ -2448,11 +2465,10 @@ select * from cte2 a join cte2 b using (i); -> Shared Scan (share slice:id 3:1) -> Materialize -> Result - -> Result - One-Time Filter: (gp_execution_segment() = 2) - -> Insert - -> Result - -> Function Scan on generate_series + One-Time Filter: (gp_execution_segment() = 0) + -> Insert + -> Result + -> Function Scan on generate_series -> Hash Join Hash Cond: (share1_ref3.i = share1_ref2.i) -> Redistribute Motion 3:3 (slice1; segments: 3) @@ -2463,7 +2479,7 @@ select * from cte2 a join cte2 b using (i); Hash Key: share1_ref2.i -> Shared Scan (share slice:id 2:1) Optimizer: Pivotal Optimizer (GPORCA) -(20 rows) +(19 rows) explain (costs off) with recursive cte as ( @@ -2609,18 +2625,17 @@ with cte as ( select i, i * 100 from generate_series(1,5) i returning i ) select * from cte order by i; - QUERY PLAN ------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------- Explicit Gather Motion 3:1 (slice1; segments: 3) - Merge Key: generate_series.generate_series - -> Result - -> Sort - Sort Key: generate_series.generate_series - -> Insert - -> Result - -> Function Scan on generate_series + Merge Key: i + -> Sort + Sort Key: i + -> Insert + -> Result + -> Function Scan on generate_series Optimizer: Pivotal Optimizer (GPORCA) -(9 rows) +(8 rows) with cte as ( insert into with_dml_dr @@ -2657,7 +2672,7 @@ with cte as ( Explicit Gather Motion 3:1 (slice1; segments: 3) -> Aggregate -> Hash Join - Hash Cond: (generate_series.generate_series = t_repl.i) + Hash Cond: (i = t_repl.i) -> Insert -> Result -> Function Scan on generate_series @@ -2837,7 +2852,7 @@ select count(*) from cte join -> Gather Motion 3:1 (slice1; segments: 3) -> Aggregate -> Hash Join - Hash Cond: (generate_series.generate_series = generate_series_1.generate_series) + Hash Cond: (i = generate_series_1.generate_series) -> Result -> Insert -> Result @@ -2884,7 +2899,7 @@ with cte as ( -> Gather Motion 3:1 (slice1; segments: 3) -> Aggregate -> Hash Join - Hash Cond: (generate_series.generate_series = t_hashed.i) + Hash Cond: (i = t_hashed.i) -> Result -> Insert -> Result @@ -2917,7 +2932,7 @@ with cte as ( -> Gather Motion 3:1 (slice1; segments: 3) -> Aggregate -> Hash Left Join - Hash Cond: (generate_series.generate_series = t_hashed.i) + Hash Cond: (i = t_hashed.i) -> Result -> Insert -> Result @@ -2950,7 +2965,7 @@ with cte as ( -> Gather Motion 3:1 (slice2; segments: 3) -> Aggregate -> Hash Join - Hash Cond: (generate_series.generate_series = t_strewn.i) + Hash Cond: (i = t_strewn.i) -> Result -> Insert -> Result @@ -2985,7 +3000,7 @@ with cte as ( -> Gather Motion 3:1 (slice2; segments: 3) -> Aggregate -> Hash Left Join - Hash Cond: (generate_series.generate_series = t_strewn.i) + Hash Cond: (i = t_strewn.i) -> Result -> Insert -> Result @@ -3226,13 +3241,13 @@ order by 1; -> Sort Sort Key: t1.i -> Hash Join - Hash Cond: (generate_series.generate_series = t1.i) + Hash Cond: (i = t1.i) -> HashAggregate - Group Key: generate_series.generate_series + Group Key: i -> Redistribute Motion 3:3 (slice1; segments: 3) - Hash Key: generate_series.generate_series + Hash Key: i -> HashAggregate - Group Key: generate_series.generate_series + Group Key: i -> Result One-Time Filter: (gp_execution_segment() = 1) -> Insert @@ -3275,18 +3290,18 @@ order by 1; -> Sort Sort Key: t1.i -> Hash Join - Hash Cond: ((t1.j = generate_series.generate_series) AND (t1.i = generate_series.generate_series)) + Hash Cond: ((t1.j = i) AND (t1.i = i)) -> Redistribute Motion 3:3 (slice1; segments: 3) Hash Key: t1.j -> Seq Scan on t1 Filter: (NOT (j IS NULL)) -> Hash -> HashAggregate - Group Key: generate_series.generate_series + Group Key: i -> Redistribute Motion 3:3 (slice2; segments: 3) - Hash Key: generate_series.generate_series + Hash Key: i -> HashAggregate - Group Key: generate_series.generate_series + Group Key: i -> Result One-Time Filter: (gp_execution_segment() = 0) -> Insert @@ -3382,17 +3397,16 @@ order by 1; QUERY PLAN --------------------------------------------------- Explicit Gather Motion 3:1 (slice1; segments: 3) - Merge Key: "outer".i + Merge Key: i -> Sort - Sort Key: "outer".i + Sort Key: i -> Append - -> Result - -> Insert + -> Insert + -> Result -> Result - -> Result -> Seq Scan on t_repl Optimizer: Pivotal Optimizer (GPORCA) -(11 rows) +(10 rows) with cte as ( insert into with_dml_dr From 3748719afd33c7a4bc418efcf039224ea1f0ae07 Mon Sep 17 00:00:00 2001 From: kotb Date: Sat, 22 Mar 2025 16:09:22 +0300 Subject: [PATCH 39/74] add test case to with_clause - order by system column --- src/test/regress/expected/with_clause.out | 33 +++++++++++++++++++ .../expected/with_clause_optimizer.out | 33 +++++++++++++++++++ src/test/regress/sql/with_clause.sql | 11 +++++++ 3 files changed, 77 insertions(+) diff --git a/src/test/regress/expected/with_clause.out b/src/test/regress/expected/with_clause.out index ffbf1a8a8935..cccc0c411349 100644 --- a/src/test/regress/expected/with_clause.out +++ b/src/test/regress/expected/with_clause.out @@ -2417,6 +2417,39 @@ create table t_new as (with cte as (delete from with_dml where i > 0 returning *) select * from cte); ERROR: cannot create plan with several writing gangs +-- Test order by system column returned from modifying CTE on hash distributed table +explain (costs off) +with cte as ( + insert into with_dml select i, i * 100 from generate_series(1,5) i + returning i, gp_segment_id +) select i from cte order by gp_segment_id; + QUERY PLAN +------------------------------------------------------------------------ + Gather Motion 3:1 (slice2; segments: 3) + Merge Key: cte.gp_segment_id + -> Sort + Sort Key: cte.gp_segment_id + -> Subquery Scan on cte + -> Insert on with_dml + -> Redistribute Motion 1:3 (slice1; segments: 1) + Hash Key: i.i + -> Function Scan on generate_series i + Optimizer: Postgres query optimizer +(10 rows) + +with cte as ( + insert into with_dml select i, i * 100 from generate_series(1,5) i + returning i, gp_segment_id +) select i from cte order by gp_segment_id; + i +--- + 3 + 4 + 2 + 1 + 5 +(5 rows) + drop table with_dml; -- Test various SELECT statements from CTE with -- modifying DML operations over replicated tables diff --git a/src/test/regress/expected/with_clause_optimizer.out b/src/test/regress/expected/with_clause_optimizer.out index b47630cf54bc..86a6dc6fa7cd 100644 --- a/src/test/regress/expected/with_clause_optimizer.out +++ b/src/test/regress/expected/with_clause_optimizer.out @@ -2531,6 +2531,39 @@ create table t_new as (with cte as (delete from with_dml where i > 0 returning *) select * from cte); ERROR: cannot create plan with several writing gangs +-- Test order by system column returned from modifying CTE on hash distributed table +explain (costs off) +with cte as ( + insert into with_dml select i, i * 100 from generate_series(1,5) i + returning i, gp_segment_id +) select i from cte order by gp_segment_id; + QUERY PLAN +---------------------------------------------------------------------- + Result + -> Gather Motion 3:1 (slice1; segments: 3) + Merge Key: gp_segment_id + -> Sort + Sort Key: gp_segment_id + -> Insert + -> Result + -> Result + -> Function Scan on generate_series + Optimizer: Pivotal Optimizer (GPORCA) +(10 rows) + +with cte as ( + insert into with_dml select i, i * 100 from generate_series(1,5) i + returning i, gp_segment_id +) select i from cte order by gp_segment_id; + i +--- + 3 + 4 + 2 + 1 + 5 +(5 rows) + drop table with_dml; -- Test various SELECT statements from CTE with -- modifying DML operations over replicated tables diff --git a/src/test/regress/sql/with_clause.sql b/src/test/regress/sql/with_clause.sql index e163ec78c1ab..0ae157db7433 100644 --- a/src/test/regress/sql/with_clause.sql +++ b/src/test/regress/sql/with_clause.sql @@ -520,6 +520,17 @@ explain (costs off) create table t_new as (with cte as (delete from with_dml where i > 0 returning *) select * from cte); + +-- Test order by system column returned from modifying CTE on hash distributed table +explain (costs off) +with cte as ( + insert into with_dml select i, i * 100 from generate_series(1,5) i + returning i, gp_segment_id +) select i from cte order by gp_segment_id; +with cte as ( + insert into with_dml select i, i * 100 from generate_series(1,5) i + returning i, gp_segment_id +) select i from cte order by gp_segment_id; drop table with_dml; -- Test various SELECT statements from CTE with From d894fde481a764ba59aa6114461b404865bf9500 Mon Sep 17 00:00:00 2001 From: kotb Date: Sat, 22 Mar 2025 23:37:02 +0300 Subject: [PATCH 40/74] fix gporca unit test dumps after copying columns with their usage --- .../gporca/data/dxl/minidump/CTE-Preds2.mdp | 1 - .../data/dxl/minidump/CTE15HAReplicated.mdp | 1 - .../data/dxl/minidump/CTE15Replicated.mdp | 1 - .../dxl/minidump/CannotPullGrpColAboveAgg.mdp | 43 ------------ .../gporca/data/dxl/minidump/DeleteInCTE.mdp | 21 ------ .../data/dxl/minidump/ExpandFullOuterJoin.mdp | 2 - .../minidump/IndexApply-Heterogeneous-DTS.mdp | 2 - .../IndexApply-Heterogeneous-NoDTS.mdp | 2 - ...dexApply-InnerSelect-Heterogeneous-DTS.mdp | 2 - .../dxl/minidump/Insert-With-HJ-CTE-Agg.mdp | 1 - .../gporca/data/dxl/minidump/InsertInCTE.mdp | 21 ------ ...tOuter2InnerUnionAllAntiSemiJoin-Tpcds.mdp | 70 ------------------- .../minidump/OrderedAgg_multiple_diffcol.mdp | 6 -- .../minidump/OrderedAgg_multiple_samecol.mdp | 3 - ...redAgg_multiple_samecol_difforderespec.mdp | 6 -- .../data/dxl/minidump/OrderedAgg_single.mdp | 3 - .../OrderedAgg_with_nonOrderedAgg.mdp | 6 -- .../OrderedAgg_with_nonconst_fraction.mdp | 4 -- .../dxl/minidump/TVF-With-Deep-Subq-Args.mdp | 8 --- .../data/dxl/minidump/Union-On-HJNs.mdp | 13 ---- .../gporca/data/dxl/minidump/UpdateInCTE.mdp | 21 ------ 21 files changed, 237 deletions(-) diff --git a/src/backend/gporca/data/dxl/minidump/CTE-Preds2.mdp b/src/backend/gporca/data/dxl/minidump/CTE-Preds2.mdp index 4ca0b999e5d2..5fd7b4e18c73 100644 --- a/src/backend/gporca/data/dxl/minidump/CTE-Preds2.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTE-Preds2.mdp @@ -537,7 +537,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/CTE15HAReplicated.mdp b/src/backend/gporca/data/dxl/minidump/CTE15HAReplicated.mdp index 045b35906fc4..c3854d359d48 100644 --- a/src/backend/gporca/data/dxl/minidump/CTE15HAReplicated.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTE15HAReplicated.mdp @@ -660,7 +660,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/CTE15Replicated.mdp b/src/backend/gporca/data/dxl/minidump/CTE15Replicated.mdp index de05b6cc2743..2bff029224f9 100644 --- a/src/backend/gporca/data/dxl/minidump/CTE15Replicated.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTE15Replicated.mdp @@ -689,7 +689,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/CannotPullGrpColAboveAgg.mdp b/src/backend/gporca/data/dxl/minidump/CannotPullGrpColAboveAgg.mdp index 244cd8480c86..cdc56a8ecdbe 100644 --- a/src/backend/gporca/data/dxl/minidump/CannotPullGrpColAboveAgg.mdp +++ b/src/backend/gporca/data/dxl/minidump/CannotPullGrpColAboveAgg.mdp @@ -4452,28 +4452,6 @@ The SQL along with the DDL are in TINC repo. In the aggregates directory under q - - - - - - - - - - - - - - - - - - - - - - @@ -4571,27 +4549,6 @@ The SQL along with the DDL are in TINC repo. In the aggregates directory under q - - - - - - - - - - - - - - - - - - - - - diff --git a/src/backend/gporca/data/dxl/minidump/DeleteInCTE.mdp b/src/backend/gporca/data/dxl/minidump/DeleteInCTE.mdp index 19bcca02d808..ebb437f415c3 100644 --- a/src/backend/gporca/data/dxl/minidump/DeleteInCTE.mdp +++ b/src/backend/gporca/data/dxl/minidump/DeleteInCTE.mdp @@ -306,27 +306,6 @@ explain with cte as ( - - - - - - - - - - - - - - - - - - - - - diff --git a/src/backend/gporca/data/dxl/minidump/ExpandFullOuterJoin.mdp b/src/backend/gporca/data/dxl/minidump/ExpandFullOuterJoin.mdp index 669c876297da..61555de1f6c1 100644 --- a/src/backend/gporca/data/dxl/minidump/ExpandFullOuterJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/ExpandFullOuterJoin.mdp @@ -332,7 +332,6 @@ select * from t full join s on t1 = s1; - @@ -428,7 +427,6 @@ select * from t full join s on t1 = s1; - diff --git a/src/backend/gporca/data/dxl/minidump/IndexApply-Heterogeneous-DTS.mdp b/src/backend/gporca/data/dxl/minidump/IndexApply-Heterogeneous-DTS.mdp index 69929c639448..6723f7796710 100644 --- a/src/backend/gporca/data/dxl/minidump/IndexApply-Heterogeneous-DTS.mdp +++ b/src/backend/gporca/data/dxl/minidump/IndexApply-Heterogeneous-DTS.mdp @@ -628,8 +628,6 @@ WHERE tt.event_ts >= tq.ets AND - - diff --git a/src/backend/gporca/data/dxl/minidump/IndexApply-Heterogeneous-NoDTS.mdp b/src/backend/gporca/data/dxl/minidump/IndexApply-Heterogeneous-NoDTS.mdp index 7048d28b8497..56725a5297a8 100644 --- a/src/backend/gporca/data/dxl/minidump/IndexApply-Heterogeneous-NoDTS.mdp +++ b/src/backend/gporca/data/dxl/minidump/IndexApply-Heterogeneous-NoDTS.mdp @@ -721,8 +721,6 @@ ORDER BY 1 asc ; - - diff --git a/src/backend/gporca/data/dxl/minidump/IndexApply-InnerSelect-Heterogeneous-DTS.mdp b/src/backend/gporca/data/dxl/minidump/IndexApply-InnerSelect-Heterogeneous-DTS.mdp index 39a1300e9c27..e3e2627b6535 100644 --- a/src/backend/gporca/data/dxl/minidump/IndexApply-InnerSelect-Heterogeneous-DTS.mdp +++ b/src/backend/gporca/data/dxl/minidump/IndexApply-InnerSelect-Heterogeneous-DTS.mdp @@ -667,8 +667,6 @@ WHERE tt.event_ts >= tq.ets AND - - diff --git a/src/backend/gporca/data/dxl/minidump/Insert-With-HJ-CTE-Agg.mdp b/src/backend/gporca/data/dxl/minidump/Insert-With-HJ-CTE-Agg.mdp index 16e4cfca39d3..a2388fe5232b 100644 --- a/src/backend/gporca/data/dxl/minidump/Insert-With-HJ-CTE-Agg.mdp +++ b/src/backend/gporca/data/dxl/minidump/Insert-With-HJ-CTE-Agg.mdp @@ -747,7 +747,6 @@ - diff --git a/src/backend/gporca/data/dxl/minidump/InsertInCTE.mdp b/src/backend/gporca/data/dxl/minidump/InsertInCTE.mdp index 23e71ff27b6c..80ced1dc18ea 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertInCTE.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertInCTE.mdp @@ -498,27 +498,6 @@ where t1.i in (select i from cte); - - - - - - - - - - - - - - - - - - - - - diff --git a/src/backend/gporca/data/dxl/minidump/LeftOuter2InnerUnionAllAntiSemiJoin-Tpcds.mdp b/src/backend/gporca/data/dxl/minidump/LeftOuter2InnerUnionAllAntiSemiJoin-Tpcds.mdp index 9f7bf474084d..b1317acb6562 100644 --- a/src/backend/gporca/data/dxl/minidump/LeftOuter2InnerUnionAllAntiSemiJoin-Tpcds.mdp +++ b/src/backend/gporca/data/dxl/minidump/LeftOuter2InnerUnionAllAntiSemiJoin-Tpcds.mdp @@ -11731,29 +11731,8 @@ select * from v2 left outer join v1 on v2.i_item_sk = v1.ss_item_sk limit 5; - - - - - - - - - - - - - - - - - - - - - @@ -11786,34 +11765,6 @@ select * from v2 left outer join v1 on v2.i_item_sk = v1.ss_item_sk limit 5; - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -11841,27 +11792,6 @@ select * from v2 left outer join v1 on v2.i_item_sk = v1.ss_item_sk limit 5; - - - - - - - - - - - - - - - - - - - - - diff --git a/src/backend/gporca/data/dxl/minidump/OrderedAgg_multiple_diffcol.mdp b/src/backend/gporca/data/dxl/minidump/OrderedAgg_multiple_diffcol.mdp index 2b29a828df9c..e2d0f5d2f8a7 100644 --- a/src/backend/gporca/data/dxl/minidump/OrderedAgg_multiple_diffcol.mdp +++ b/src/backend/gporca/data/dxl/minidump/OrderedAgg_multiple_diffcol.mdp @@ -541,9 +541,6 @@ EXPLAIN SELECT percentile_cont(0.5) WITHIN GROUP(ORDER BY a1), percentile_cont(0 - - - @@ -664,9 +661,6 @@ EXPLAIN SELECT percentile_cont(0.5) WITHIN GROUP(ORDER BY a1), percentile_cont(0 - - - diff --git a/src/backend/gporca/data/dxl/minidump/OrderedAgg_multiple_samecol.mdp b/src/backend/gporca/data/dxl/minidump/OrderedAgg_multiple_samecol.mdp index b99595f541f8..c4e315ec7943 100644 --- a/src/backend/gporca/data/dxl/minidump/OrderedAgg_multiple_samecol.mdp +++ b/src/backend/gporca/data/dxl/minidump/OrderedAgg_multiple_samecol.mdp @@ -541,9 +541,6 @@ EXPLAIN SELECT percentile_cont(0.5) WITHIN GROUP(ORDER BY a2), percentile_disc(0 - - - diff --git a/src/backend/gporca/data/dxl/minidump/OrderedAgg_multiple_samecol_difforderespec.mdp b/src/backend/gporca/data/dxl/minidump/OrderedAgg_multiple_samecol_difforderespec.mdp index a91acbc71c57..26ddecd518d6 100644 --- a/src/backend/gporca/data/dxl/minidump/OrderedAgg_multiple_samecol_difforderespec.mdp +++ b/src/backend/gporca/data/dxl/minidump/OrderedAgg_multiple_samecol_difforderespec.mdp @@ -553,9 +553,6 @@ EXPLAIN SELECT percentile_cont(0.5) WITHIN GROUP(ORDER BY a2), percentile_cont(0 - - - @@ -677,9 +674,6 @@ EXPLAIN SELECT percentile_cont(0.5) WITHIN GROUP(ORDER BY a2), percentile_cont(0 - - - diff --git a/src/backend/gporca/data/dxl/minidump/OrderedAgg_single.mdp b/src/backend/gporca/data/dxl/minidump/OrderedAgg_single.mdp index 95e60be9f7ee..eb2ec7e5fba2 100644 --- a/src/backend/gporca/data/dxl/minidump/OrderedAgg_single.mdp +++ b/src/backend/gporca/data/dxl/minidump/OrderedAgg_single.mdp @@ -499,9 +499,6 @@ EXPLAIN SELECT percentile_cont(0.5) WITHIN GROUP(ORDER BY a2) FROM foo; - - - diff --git a/src/backend/gporca/data/dxl/minidump/OrderedAgg_with_nonOrderedAgg.mdp b/src/backend/gporca/data/dxl/minidump/OrderedAgg_with_nonOrderedAgg.mdp index d6ab31fed4a1..80a9a76037e4 100644 --- a/src/backend/gporca/data/dxl/minidump/OrderedAgg_with_nonOrderedAgg.mdp +++ b/src/backend/gporca/data/dxl/minidump/OrderedAgg_with_nonOrderedAgg.mdp @@ -596,9 +596,6 @@ EXPLAIN SELECT percentile_cont(0.5) WITHIN GROUP(ORDER BY a1), percentile_disc(0 - - - @@ -722,9 +719,6 @@ EXPLAIN SELECT percentile_cont(0.5) WITHIN GROUP(ORDER BY a1), percentile_disc(0 - - - diff --git a/src/backend/gporca/data/dxl/minidump/OrderedAgg_with_nonconst_fraction.mdp b/src/backend/gporca/data/dxl/minidump/OrderedAgg_with_nonconst_fraction.mdp index 1f999454b3c6..fa4690a3c9e2 100644 --- a/src/backend/gporca/data/dxl/minidump/OrderedAgg_with_nonconst_fraction.mdp +++ b/src/backend/gporca/data/dxl/minidump/OrderedAgg_with_nonconst_fraction.mdp @@ -526,10 +526,6 @@ EXPLAIN SELECT percentile_cont(floor(random()*0.1)+0.5) WITHIN GROUP(ORDER BY a1 - - - - diff --git a/src/backend/gporca/data/dxl/minidump/TVF-With-Deep-Subq-Args.mdp b/src/backend/gporca/data/dxl/minidump/TVF-With-Deep-Subq-Args.mdp index 63532f9c7b9e..9ba6c5a5de5b 100644 --- a/src/backend/gporca/data/dxl/minidump/TVF-With-Deep-Subq-Args.mdp +++ b/src/backend/gporca/data/dxl/minidump/TVF-With-Deep-Subq-Args.mdp @@ -430,8 +430,6 @@ SELECT generate_series(( - - @@ -488,8 +486,6 @@ SELECT generate_series(( - - @@ -643,8 +639,6 @@ SELECT generate_series(( - - @@ -701,8 +695,6 @@ SELECT generate_series(( - - diff --git a/src/backend/gporca/data/dxl/minidump/Union-On-HJNs.mdp b/src/backend/gporca/data/dxl/minidump/Union-On-HJNs.mdp index ca4ac97176f1..ccdbe8d87f44 100644 --- a/src/backend/gporca/data/dxl/minidump/Union-On-HJNs.mdp +++ b/src/backend/gporca/data/dxl/minidump/Union-On-HJNs.mdp @@ -1031,8 +1031,6 @@ - - @@ -1279,9 +1277,7 @@ - - @@ -1364,8 +1360,6 @@ - - @@ -2424,8 +2418,6 @@ - - @@ -2577,7 +2569,6 @@ - @@ -2663,9 +2654,7 @@ - - @@ -2748,8 +2737,6 @@ - - diff --git a/src/backend/gporca/data/dxl/minidump/UpdateInCTE.mdp b/src/backend/gporca/data/dxl/minidump/UpdateInCTE.mdp index a6a28fcee59e..afd46d4a9606 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateInCTE.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateInCTE.mdp @@ -306,27 +306,6 @@ explain with cte as ( - - - - - - - - - - - - - - - - - - - - - From 3ecc55acfe37884cf6d01896e16232f7104a5930 Mon Sep 17 00:00:00 2001 From: kotb Date: Sun, 23 Mar 2025 00:10:32 +0300 Subject: [PATCH 41/74] reindent new gporca minidumps --- .../gporca/data/dxl/minidump/DeleteInCTE.mdp | 700 +++++------ .../data/dxl/minidump/DeleteReturning.mdp | 678 +++++----- .../minidump/DeleteReturningProjection.mdp | 696 +++++------ .../gporca/data/dxl/minidump/InsertInCTE.mdp | 1092 ++++++++--------- .../data/dxl/minidump/InsertIntoReturning.mdp | 568 ++++----- .../InsertIntoReturningProjection.mdp | 636 +++++----- .../gporca/data/dxl/minidump/UpdateInCTE.mdp | 734 +++++------ .../data/dxl/minidump/UpdateReturning.mdp | 764 ++++++------ .../minidump/UpdateReturningProjection.mdp | 832 ++++++------- 9 files changed, 3350 insertions(+), 3350 deletions(-) diff --git a/src/backend/gporca/data/dxl/minidump/DeleteInCTE.mdp b/src/backend/gporca/data/dxl/minidump/DeleteInCTE.mdp index ebb437f415c3..e4f0ccde6e14 100644 --- a/src/backend/gporca/data/dxl/minidump/DeleteInCTE.mdp +++ b/src/backend/gporca/data/dxl/minidump/DeleteInCTE.mdp @@ -14,361 +14,361 @@ explain with cte as ( --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/backend/gporca/data/dxl/minidump/DeleteReturning.mdp b/src/backend/gporca/data/dxl/minidump/DeleteReturning.mdp index 84c414ad3aca..b6191cdec8d1 100644 --- a/src/backend/gporca/data/dxl/minidump/DeleteReturning.mdp +++ b/src/backend/gporca/data/dxl/minidump/DeleteReturning.mdp @@ -7,350 +7,350 @@ delete from ttt returning id, *, ctid; --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - + + + + + \ No newline at end of file diff --git a/src/backend/gporca/data/dxl/minidump/DeleteReturningProjection.mdp b/src/backend/gporca/data/dxl/minidump/DeleteReturningProjection.mdp index 9b889e32b55b..c400d72167e5 100644 --- a/src/backend/gporca/data/dxl/minidump/DeleteReturningProjection.mdp +++ b/src/backend/gporca/data/dxl/minidump/DeleteReturningProjection.mdp @@ -7,357 +7,357 @@ delete from ttt returning id+length(data); --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/backend/gporca/data/dxl/minidump/InsertInCTE.mdp b/src/backend/gporca/data/dxl/minidump/InsertInCTE.mdp index 80ced1dc18ea..ad2b193dbb99 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertInCTE.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertInCTE.mdp @@ -15,567 +15,567 @@ where t1.i in (select i from cte); --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - + + + + + + + + + \ No newline at end of file diff --git a/src/backend/gporca/data/dxl/minidump/InsertIntoReturning.mdp b/src/backend/gporca/data/dxl/minidump/InsertIntoReturning.mdp index 5c6c84bd2724..76f59a69ccf4 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertIntoReturning.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertIntoReturning.mdp @@ -7,293 +7,293 @@ insert into ttt values (123, 'daad') returning id; --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/backend/gporca/data/dxl/minidump/InsertIntoReturningProjection.mdp b/src/backend/gporca/data/dxl/minidump/InsertIntoReturningProjection.mdp index e265c16609c6..92b077e42f44 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertIntoReturningProjection.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertIntoReturningProjection.mdp @@ -7,336 +7,336 @@ insert into ttt values (123, 'daad') returning id+length(data); --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - + + + + + + + \ No newline at end of file diff --git a/src/backend/gporca/data/dxl/minidump/UpdateInCTE.mdp b/src/backend/gporca/data/dxl/minidump/UpdateInCTE.mdp index afd46d4a9606..6f4238702826 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateInCTE.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateInCTE.mdp @@ -14,378 +14,378 @@ explain with cte as ( --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/backend/gporca/data/dxl/minidump/UpdateReturning.mdp b/src/backend/gporca/data/dxl/minidump/UpdateReturning.mdp index 5cb091c1be17..d45885a90dab 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateReturning.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateReturning.mdp @@ -7,391 +7,391 @@ update ttt set id = 1 returning data; --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/backend/gporca/data/dxl/minidump/UpdateReturningProjection.mdp b/src/backend/gporca/data/dxl/minidump/UpdateReturningProjection.mdp index 99d81f9c483b..803accc20f9c 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateReturningProjection.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateReturningProjection.mdp @@ -7,433 +7,433 @@ update ttt set id = 1 returning id+length(data); --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - + + + + + + + \ No newline at end of file From 76674789c3391aea3fb92fb9a3718f4109efd58b Mon Sep 17 00:00:00 2001 From: kotb Date: Sun, 23 Mar 2025 12:14:50 +0300 Subject: [PATCH 42/74] fix output of DML nodes in plan in regress tests after fixing targetlist --- .../expected/explain_analyze_optimizer.out | 37 +++++++++---------- .../expected/partition_pruning_optimizer.out | 12 ++---- .../expected/qp_dropped_cols_optimizer.out | 36 ++++++------------ .../expected/subselect_gp_optimizer.out | 18 ++++----- .../expected/updatable_views_optimizer.out | 4 +- .../regress/expected/update_gp_optimizer.out | 2 +- .../expected/with_clause_optimizer.out | 2 +- src/test/regress/expected/with_optimizer.out | 6 +-- 8 files changed, 49 insertions(+), 68 deletions(-) diff --git a/src/test/regress/expected/explain_analyze_optimizer.out b/src/test/regress/expected/explain_analyze_optimizer.out index e36f5ab363b4..adcd65939847 100644 --- a/src/test/regress/expected/explain_analyze_optimizer.out +++ b/src/test/regress/expected/explain_analyze_optimizer.out @@ -108,19 +108,18 @@ WITH cte AS ( ) SELECT * FROM cte; QUERY PLAN ------------------------------------------------------------------------------------ - Result (actual rows=5 loops=1) - -> Gather Motion 3:1 (slice1; segments: 3) (actual rows=5 loops=1) - -> Insert (actual rows=3 loops=1) + Gather Motion 3:1 (slice1; segments: 3) (actual rows=5 loops=1) + -> Insert (actual rows=3 loops=1) + -> Result (actual rows=3 loops=1) -> Result (actual rows=3 loops=1) - -> Result (actual rows=3 loops=1) - -> Function Scan on generate_series (actual rows=5 loops=1) + -> Function Scan on generate_series (actual rows=5 loops=1) Planning time: 20.649 ms (slice0) Executor memory: 59K bytes. (slice1) Executor memory: 90K bytes avg x 3 workers, 90K bytes max (seg0). Work_mem: 17K bytes max. Memory used: 128000kB Optimizer: Pivotal Optimizer (GPORCA) Execution time: 21.314 ms -(12 rows) +(11 rows) EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF) WITH cte AS ( @@ -129,19 +128,18 @@ WITH cte AS ( ) SELECT * FROM cte; QUERY PLAN --------------------------------------------------------------------------------- - Result (actual rows=5 loops=1) - -> Gather Motion 3:1 (slice1; segments: 3) (actual rows=5 loops=1) - -> Update (actual rows=3 loops=1) - -> Split (actual rows=6 loops=1) - -> Result (actual rows=3 loops=1) - -> Seq Scan on with_dml (actual rows=3 loops=1) + Gather Motion 3:1 (slice1; segments: 3) (actual rows=5 loops=1) + -> Update (actual rows=3 loops=1) + -> Split (actual rows=6 loops=1) + -> Result (actual rows=3 loops=1) + -> Seq Scan on with_dml (actual rows=3 loops=1) Planning time: 13.933 ms (slice0) Executor memory: 59K bytes. (slice1) Executor memory: 58K bytes avg x 3 workers, 58K bytes max (seg0). Memory used: 128000kB Optimizer: Pivotal Optimizer (GPORCA) Execution time: 4.397 ms -(12 rows) +(11 rows) EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF) WITH cte AS ( @@ -150,19 +148,18 @@ WITH cte AS ( ) SELECT * FROM cte; QUERY PLAN --------------------------------------------------------------------------------- - Result (actual rows=5 loops=1) - -> Gather Motion 3:1 (slice1; segments: 3) (actual rows=5 loops=1) - -> Delete (actual rows=3 loops=1) - -> Result (actual rows=3 loops=1) - -> Seq Scan on with_dml (actual rows=3 loops=1) - Filter: (i > 0) + Gather Motion 3:1 (slice1; segments: 3) (actual rows=5 loops=1) + -> Delete (actual rows=3 loops=1) + -> Result (actual rows=3 loops=1) + -> Seq Scan on with_dml (actual rows=3 loops=1) + Filter: (i > 0) Planning time: 8.322 ms (slice0) Executor memory: 59K bytes. (slice1) Executor memory: 57K bytes avg x 3 workers, 57K bytes max (seg0). Memory used: 128000kB Optimizer: Pivotal Optimizer (GPORCA) Execution time: 9.462 ms -(10 rows) +(11 rows) DROP TABLE with_dml; -- diff --git a/src/test/regress/expected/partition_pruning_optimizer.out b/src/test/regress/expected/partition_pruning_optimizer.out index 00c2f2d735d2..6d9e2099f1f1 100644 --- a/src/test/regress/expected/partition_pruning_optimizer.out +++ b/src/test/regress/expected/partition_pruning_optimizer.out @@ -3492,7 +3492,6 @@ explain (verbose, costs off) delete from test_1_prt_extra where j = 2; QUERY PLAN --------------------------------------------------------------------------------------------------------------------- Delete - Output: "outer".ColRef_0018, test_1_prt_extra.ctid -> Result Output: test_1_prt_extra.ctid, test_1_prt_extra.gp_segment_id, 0 -> Seq Scan on partition_pruning.test_1_prt_extra @@ -3500,7 +3499,7 @@ explain (verbose, costs off) delete from test_1_prt_extra where j = 2; Filter: (test_1_prt_extra.j = 2) Optimizer: Pivotal Optimizer (GPORCA) Settings: enable_bitmapscan=on, enable_hashjoin=off, enable_indexscan=on, enable_mergejoin=on, enable_seqscan=off -(9 rows) +(8 rows) delete from test_1_prt_extra where j = 2; -- Check that deletion performed correctly @@ -3558,7 +3557,6 @@ HINT: For non-partitioned tables, run analyze (). For QUERY PLAN ------------------------------------------------------------------------------------------------------------------- Delete - Output: "outer".ColRef_0034, test.ctid, test.tableoid -> Result Output: test.ctid, test.tableoid, test.gp_segment_id, 0 -> Hash Anti Join @@ -3578,7 +3576,7 @@ HINT: For non-partitioned tables, run analyze (). For Output: test_in_predicate.i, test_in_predicate.j Optimizer: Pivotal Optimizer (GPORCA) Settings: enable_bitmapscan=on, enable_hashjoin=off, enable_indexscan=on, enable_mergejoin=on, enable_seqscan=off -(21 rows) +(20 rows) delete from test where not exists( select 1 from test_in_predicate where test.i = test_in_predicate.i and test.j = test_in_predicate.j @@ -3635,7 +3633,6 @@ explain (verbose, costs off) update test_1_prt_extra set k = 10 where j = 2; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------- Update - Output: test_1_prt_extra.i, test_1_prt_extra.j, test_1_prt_extra.k, (DMLAction), test_1_prt_extra.ctid -> Split Output: test_1_prt_extra.i, test_1_prt_extra.j, test_1_prt_extra.k, test_1_prt_extra.ctid, test_1_prt_extra.gp_segment_id, DMLAction -> Result @@ -3645,7 +3642,7 @@ explain (verbose, costs off) update test_1_prt_extra set k = 10 where j = 2; Filter: (test_1_prt_extra.j = 2) Optimizer: Pivotal Optimizer (GPORCA) Settings: enable_bitmapscan=on, enable_hashjoin=off, enable_indexscan=on, enable_mergejoin=on, enable_seqscan=off -(11 rows) +(10 rows) update test_1_prt_extra set k = 10 where j = 2; -- Check that update performed correctly and tuple moved to correct partition @@ -3704,7 +3701,6 @@ HINT: For non-partitioned tables, run analyze (). For QUERY PLAN ------------------------------------------------------------------------------------------------------------------- Update - Output: test.i, test.j, test.k, (DMLAction), test.ctid, test.tableoid -> Split Output: test.i, test.j, test.k, test.ctid, test.tableoid, test.gp_segment_id, DMLAction -> Result @@ -3726,7 +3722,7 @@ HINT: For non-partitioned tables, run analyze (). For Output: test_in_predicate.i, test_in_predicate.j Optimizer: Pivotal Optimizer (GPORCA) Settings: enable_bitmapscan=on, enable_hashjoin=off, enable_indexscan=on, enable_mergejoin=on, enable_seqscan=off -(23 rows) +(22 rows) update test set k = 10 where not exists( select 1 from test_in_predicate where test.i = test_in_predicate.i and test.j = test_in_predicate.j diff --git a/src/test/regress/expected/qp_dropped_cols_optimizer.out b/src/test/regress/expected/qp_dropped_cols_optimizer.out index bf6b1b200b3d..61d15f7325ef 100644 --- a/src/test/regress/expected/qp_dropped_cols_optimizer.out +++ b/src/test/regress/expected/qp_dropped_cols_optimizer.out @@ -16290,7 +16290,6 @@ EXPLAIN (COSTS OFF, VERBOSE) INSERT INTO t_part_dropped VALUES (1, 2, 4); QUERY PLAN -------------------------------------------------- Insert - Output: c1, NULL::integer, c3, c4, ColRef_0014 -> Result Output: c1, c3, c4, 1 -> Result @@ -16300,14 +16299,13 @@ EXPLAIN (COSTS OFF, VERBOSE) INSERT INTO t_part_dropped VALUES (1, 2, 4); -> Result Output: true Optimizer: Pivotal Optimizer (GPORCA) -(11 rows) +(10 rows) INSERT INTO t_part_dropped VALUES (1, 2, 4); EXPLAIN (COSTS OFF, VERBOSE) INSERT INTO t_part_dropped_1_prt_p2 VALUES (1, 2, 4); QUERY PLAN ---------------------------------------- Insert - Output: c1, c3, c4, ColRef_0014 -> Result Output: c1, c3, c4, 1 -> Result @@ -16317,7 +16315,7 @@ EXPLAIN (COSTS OFF, VERBOSE) INSERT INTO t_part_dropped_1_prt_p2 VALUES (1, 2, 4 -> Result Output: true Optimizer: Pivotal Optimizer (GPORCA) -(11 rows) +(10 rows) INSERT INTO t_part_dropped_1_prt_p2 VALUES (1, 2, 4); INSERT INTO t_part_dropped_1_prt_p2 VALUES (1, 2, 0); @@ -16327,7 +16325,6 @@ EXPLAIN (COSTS OFF, VERBOSE) UPDATE t_part_dropped_1_prt_p2 SET c1 = 2; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Update - Output: t_part_dropped_1_prt_p2.c1, t_part_dropped_1_prt_p2.c3, t_part_dropped_1_prt_p2.c4, (DMLAction), t_part_dropped_1_prt_p2.ctid -> Redistribute Motion 3:3 (slice1; segments: 3) Output: t_part_dropped_1_prt_p2.c1, t_part_dropped_1_prt_p2.c3, t_part_dropped_1_prt_p2.c4, t_part_dropped_1_prt_p2.ctid, t_part_dropped_1_prt_p2.gp_segment_id, (DMLAction) Hash Key: t_part_dropped_1_prt_p2.c1 @@ -16338,14 +16335,13 @@ EXPLAIN (COSTS OFF, VERBOSE) UPDATE t_part_dropped_1_prt_p2 SET c1 = 2; -> Seq Scan on public.t_part_dropped_1_prt_p2 Output: t_part_dropped_1_prt_p2.c1, t_part_dropped_1_prt_p2.c3, t_part_dropped_1_prt_p2.c4, t_part_dropped_1_prt_p2.ctid, t_part_dropped_1_prt_p2.gp_segment_id Optimizer: Pivotal Optimizer (GPORCA) -(12 rows) +(11 rows) UPDATE t_part_dropped_1_prt_p2 SET c1 = 2; EXPLAIN (COSTS OFF, VERBOSE) UPDATE t_part_dropped SET c1 = 3; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Update - Output: t_part_dropped.c1, NULL::integer, t_part_dropped.c3, t_part_dropped.c4, (DMLAction), t_part_dropped.ctid, t_part_dropped.tableoid -> Redistribute Motion 3:3 (slice1; segments: 3) Output: t_part_dropped.c1, t_part_dropped.c3, t_part_dropped.c4, t_part_dropped.ctid, t_part_dropped.tableoid, t_part_dropped.gp_segment_id, (DMLAction) Hash Key: t_part_dropped.c1 @@ -16360,7 +16356,7 @@ EXPLAIN (COSTS OFF, VERBOSE) UPDATE t_part_dropped SET c1 = 3; -> Dynamic Seq Scan on public.t_part_dropped (dynamic scan id: 1) Output: t_part_dropped.c1, t_part_dropped.c3, t_part_dropped.c4, t_part_dropped.ctid, t_part_dropped.tableoid, t_part_dropped.gp_segment_id Optimizer: Pivotal Optimizer (GPORCA) -(16 rows) +(15 rows) UPDATE t_part_dropped SET c1 = 3; -- Ensure that split update on leaf partition does not throw constraint error @@ -16380,7 +16376,6 @@ EXPLAIN (COSTS OFF, VERBOSE) UPDATE t_part_dropped SET c1 = 3 WHERE c4 = 0; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Update - Output: t_part_dropped.c1, NULL::integer, t_part_dropped.c3, t_part_dropped.c4, (DMLAction), t_part_dropped.ctid, t_part_dropped.tableoid -> Redistribute Motion 3:3 (slice1; segments: 3) Output: t_part_dropped.c1, t_part_dropped.c3, t_part_dropped.c4, t_part_dropped.ctid, t_part_dropped.tableoid, t_part_dropped.gp_segment_id, (DMLAction) Hash Key: t_part_dropped.c1 @@ -16396,7 +16391,7 @@ EXPLAIN (COSTS OFF, VERBOSE) UPDATE t_part_dropped SET c1 = 3 WHERE c4 = 0; Output: t_part_dropped.c1, t_part_dropped.c3, t_part_dropped.c4, t_part_dropped.ctid, t_part_dropped.tableoid, t_part_dropped.gp_segment_id Filter: (t_part_dropped.c4 = 0) Optimizer: Pivotal Optimizer (GPORCA) -(17 rows) +(16 rows) UPDATE t_part_dropped SET c1 = 3 WHERE c4 = 0; SELECT count(*) FROM t_part_dropped_1_prt_p2; @@ -16415,13 +16410,12 @@ EXPLAIN (COSTS OFF, VERBOSE) DELETE FROM t_part_dropped_1_prt_p2; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Delete - Output: "outer".ColRef_0020, t_part_dropped_1_prt_p2.ctid -> Result Output: t_part_dropped_1_prt_p2.ctid, t_part_dropped_1_prt_p2.gp_segment_id, 0 -> Seq Scan on public.t_part_dropped_1_prt_p2 Output: t_part_dropped_1_prt_p2.ctid, t_part_dropped_1_prt_p2.gp_segment_id Optimizer: Pivotal Optimizer (GPORCA) -(7 rows) +(6 rows) DELETE FROM t_part_dropped_1_prt_p2; DROP TABLE t_part_dropped; @@ -16442,7 +16436,6 @@ EXPLAIN (COSTS OFF, VERBOSE) INSERT INTO t_part VALUES (1, 5, 2, 5); QUERY PLAN ---------------------------------------- Insert - Output: c1, c2, c3, c4, ColRef_0016 -> Result Output: c1, c2, c3, c4, 1 -> Result @@ -16452,14 +16445,13 @@ EXPLAIN (COSTS OFF, VERBOSE) INSERT INTO t_part VALUES (1, 5, 2, 5); -> Result Output: true Optimizer: Pivotal Optimizer (GPORCA) -(11 rows) +(10 rows) INSERT INTO t_part VALUES (1, 5, 2, 5); EXPLAIN (COSTS OFF, VERBOSE) INSERT INTO t_part_1_prt_p2 VALUES (1, 5, 2, 5); QUERY PLAN ------------------------------------------------------ Insert - Output: c1, NULL::integer, c2, c3, c4, ColRef_0016 -> Result Output: c1, c2, c3, c4, 1 -> Result @@ -16469,7 +16461,7 @@ EXPLAIN (COSTS OFF, VERBOSE) INSERT INTO t_part_1_prt_p2 VALUES (1, 5, 2, 5); -> Result Output: true Optimizer: Pivotal Optimizer (GPORCA) -(11 rows) +(10 rows) INSERT INTO t_part_1_prt_p2 VALUES (1, 5, 2, 5); -- Ensure that split update on leaf and root partitions does not @@ -16478,7 +16470,6 @@ EXPLAIN (COSTS OFF, VERBOSE) UPDATE t_part_1_prt_p2 SET c1 = 2; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- Update - Output: t_part_1_prt_p2.c1, NULL::integer, t_part_1_prt_p2.c2, t_part_1_prt_p2.c3, t_part_1_prt_p2.c4, (DMLAction), t_part_1_prt_p2.ctid -> Redistribute Motion 3:3 (slice1; segments: 3) Output: t_part_1_prt_p2.c1, t_part_1_prt_p2.c2, t_part_1_prt_p2.c3, t_part_1_prt_p2.c4, t_part_1_prt_p2.ctid, t_part_1_prt_p2.gp_segment_id, (DMLAction) Hash Key: t_part_1_prt_p2.c1 @@ -16489,14 +16480,13 @@ EXPLAIN (COSTS OFF, VERBOSE) UPDATE t_part_1_prt_p2 SET c1 = 2; -> Seq Scan on public.t_part_1_prt_p2 Output: t_part_1_prt_p2.c1, t_part_1_prt_p2.c2, t_part_1_prt_p2.c3, t_part_1_prt_p2.c4, t_part_1_prt_p2.ctid, t_part_1_prt_p2.gp_segment_id Optimizer: Pivotal Optimizer (GPORCA) -(12 rows) +(11 rows) UPDATE t_part_1_prt_p2 SET c1 = 2; EXPLAIN (COSTS OFF, VERBOSE) UPDATE t_part SET c1 = 3; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------- Update - Output: t_part.c1, t_part.c2, t_part.c3, t_part.c4, (DMLAction), t_part.ctid, t_part.tableoid -> Redistribute Motion 3:3 (slice1; segments: 3) Output: t_part.c1, t_part.c2, t_part.c3, t_part.c4, t_part.ctid, t_part.tableoid, t_part.gp_segment_id, (DMLAction) Hash Key: t_part.c1 @@ -16511,7 +16501,7 @@ EXPLAIN (COSTS OFF, VERBOSE) UPDATE t_part SET c1 = 3; -> Dynamic Seq Scan on public.t_part (dynamic scan id: 1) Output: t_part.c1, t_part.c2, t_part.c3, t_part.c4, t_part.ctid, t_part.tableoid, t_part.gp_segment_id Optimizer: Pivotal Optimizer (GPORCA) -(16 rows) +(15 rows) UPDATE t_part SET c1 = 3; -- Ensure that split update on leaf partition does not throw constraint error @@ -16529,13 +16519,12 @@ EXPLAIN (COSTS OFF, VERBOSE) DELETE FROM t_part_1_prt_p2; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------- Delete - Output: "outer".ColRef_0022, t_part_1_prt_p2.ctid -> Result Output: t_part_1_prt_p2.ctid, t_part_1_prt_p2.gp_segment_id, 0 -> Seq Scan on public.t_part_1_prt_p2 Output: t_part_1_prt_p2.ctid, t_part_1_prt_p2.gp_segment_id Optimizer: Pivotal Optimizer (GPORCA) -(7 rows) +(6 rows) DELETE FROM t_part_1_prt_p2; DROP TABLE t_part; @@ -16572,7 +16561,6 @@ EXPLAIN (COSTS OFF, VERBOSE) UPDATE t_part SET c1 = 3; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------- Update - Output: t_part.c1, t_part.c2, t_part.c3, t_part.c4, (DMLAction), t_part.ctid, t_part.tableoid -> Redistribute Motion 3:3 (slice1; segments: 3) Output: t_part.c1, t_part.c2, t_part.c3, t_part.c4, t_part.ctid, t_part.tableoid, t_part.gp_segment_id, (DMLAction) Hash Key: t_part.c1 @@ -16587,7 +16575,7 @@ EXPLAIN (COSTS OFF, VERBOSE) UPDATE t_part SET c1 = 3; -> Dynamic Seq Scan on public.t_part (dynamic scan id: 1) Output: t_part.c1, t_part.c2, t_part.c3, t_part.c4, t_part.ctid, t_part.tableoid, t_part.gp_segment_id Optimizer: Pivotal Optimizer (GPORCA) -(16 rows) +(15 rows) UPDATE t_part SET c1 = 3; SELECT * FROM t_part_1_prt_p2; diff --git a/src/test/regress/expected/subselect_gp_optimizer.out b/src/test/regress/expected/subselect_gp_optimizer.out index 1bf71d2fb1c6..22fa78ed143a 100644 --- a/src/test/regress/expected/subselect_gp_optimizer.out +++ b/src/test/regress/expected/subselect_gp_optimizer.out @@ -3735,7 +3735,7 @@ where 0 = (select i from cte); -> Nested Loop Join Filter: true -> Result - Filter: (0 = t1.i) + Filter: (0 = i) -> Assert Assert Cond: ((row_number() OVER (?)) = 1) -> WindowAgg @@ -3797,12 +3797,12 @@ order by i; -> Sort Sort Key: t2.i -> Hash Semi Join - Hash Cond: ((t2.i = generate_series.generate_series) AND (t2.i = generate_series.generate_series)) + Hash Cond: ((t2.i = i) AND (t2.i = i)) -> Seq Scan on t2 Filter: (i > 0) -> Hash -> Result - Filter: (generate_series.generate_series > 0) + Filter: (i > 0) -> Insert -> Result -> Result @@ -3850,13 +3850,13 @@ order by i; -> Sort Sort Key: t_repl.i -> Hash Semi Join - Hash Cond: ((t_repl.i = generate_series.generate_series) AND (t_repl.i = generate_series.generate_series)) + Hash Cond: ((t_repl.i = i) AND (t_repl.i = i)) -> Result -> Seq Scan on t_repl Filter: (i > 0) -> Hash -> Result - Filter: (generate_series.generate_series > 0) + Filter: (i > 0) -> Insert -> Result -> Result @@ -3904,12 +3904,12 @@ order by i; -> Sort Sort Key: t2.i -> Hash Semi Join - Hash Cond: ((t2.i = t3.j) AND (t2.i = generate_series.generate_series)) + Hash Cond: ((t2.i = t3.j) AND (t2.i = i)) -> Seq Scan on t2 Filter: (NOT (i IS NULL)) -> Hash -> Hash Join - Hash Cond: (generate_series.generate_series = t3.i) + Hash Cond: (i = t3.i) -> Insert -> Result -> Result @@ -3954,13 +3954,13 @@ order by i; -> Sort Sort Key: t_repl.i -> Hash Semi Join - Hash Cond: ((t_repl.i = t3.j) AND (t_repl.i = generate_series.generate_series)) + Hash Cond: ((t_repl.i = t3.j) AND (t_repl.i = i)) -> Result -> Seq Scan on t_repl Filter: (NOT (i IS NULL)) -> Hash -> Hash Join - Hash Cond: (generate_series.generate_series = t3.i) + Hash Cond: (i = t3.i) -> Insert -> Result -> Result diff --git a/src/test/regress/expected/updatable_views_optimizer.out b/src/test/regress/expected/updatable_views_optimizer.out index 7252187a3c56..00274e305895 100644 --- a/src/test/regress/expected/updatable_views_optimizer.out +++ b/src/test/regress/expected/updatable_views_optimizer.out @@ -1114,9 +1114,9 @@ EXPLAIN (verbose, costs off) UPDATE rw_view1 SET b = b + 1 RETURNING *; QUERY PLAN ------------------------------------------------------------------------------------------- Gather Motion 3:1 (slice1; segments: 3) - Output: base_tbl.a, base_tbl.b + Output: a, b -> Update - Output: base_tbl.a, base_tbl.b, (DMLAction), base_tbl.ctid + Output: a, b -> Split Output: base_tbl.a, base_tbl.b, base_tbl.ctid, base_tbl.gp_segment_id, DMLAction -> Result diff --git a/src/test/regress/expected/update_gp_optimizer.out b/src/test/regress/expected/update_gp_optimizer.out index d0048a3fa5f6..90fab208e190 100644 --- a/src/test/regress/expected/update_gp_optimizer.out +++ b/src/test/regress/expected/update_gp_optimizer.out @@ -262,7 +262,7 @@ SELECT count(*) AS a FROM t_strewn JOIN cte USING (i); -> Aggregate -> Gather Motion 3:1 (slice2; segments: 3) -> Hash Join - Hash Cond: (t_strewn.i = "outer".ColRef_0045) + Hash Cond: (t_strewn.i = i) -> Redistribute Motion 3:3 (slice1; segments: 3) Hash Key: t_strewn.i -> Seq Scan on t_strewn diff --git a/src/test/regress/expected/with_clause_optimizer.out b/src/test/regress/expected/with_clause_optimizer.out index 86a6dc6fa7cd..8d18299cb6e2 100644 --- a/src/test/regress/expected/with_clause_optimizer.out +++ b/src/test/regress/expected/with_clause_optimizer.out @@ -2309,7 +2309,7 @@ with cte as ( -> Gather Motion 3:1 (slice1; segments: 3) -> Aggregate -> Result - Filter: (generate_series.generate_series > 2) + Filter: (i > 2) -> Insert -> Result -> Result diff --git a/src/test/regress/expected/with_optimizer.out b/src/test/regress/expected/with_optimizer.out index ccb48709df9d..c23f56106073 100644 --- a/src/test/regress/expected/with_optimizer.out +++ b/src/test/regress/expected/with_optimizer.out @@ -2227,15 +2227,15 @@ SELECT * FROM cte1 a JOIN cte1 b USING (c1); -> Shared Scan (share slice:id 3:0) Output: share0_ref1.c1, share0_ref1.c2 -> Materialize - Output: "outer".c1, "outer".c2 + Output: c1, c2 -> Insert - Output: "outer".c1, "outer".c2, "outer".ColRef_0036 + Output: c1, c2 -> Redistribute Motion 3:3 (slice2; segments: 3) Output: "outer".c1, "outer".c2, "outer".ColRef_0036 -> Result Output: 1, 2, 1 -> Result - One-Time Filter: (gp_execution_segment() = 1) + One-Time Filter: (gp_execution_segment() = 0) -> Result -> Result Output: true From f8085737161d93169f136cf2667329b12c6eaddc Mon Sep 17 00:00:00 2001 From: kotb Date: Mon, 24 Mar 2025 09:37:27 +0300 Subject: [PATCH 43/74] fix comment --- src/include/gpopt/translate/CTranslatorDXLToPlStmt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/gpopt/translate/CTranslatorDXLToPlStmt.h b/src/include/gpopt/translate/CTranslatorDXLToPlStmt.h index 5c6518e46d1a..8db17485fff2 100644 --- a/src/include/gpopt/translate/CTranslatorDXLToPlStmt.h +++ b/src/include/gpopt/translate/CTranslatorDXLToPlStmt.h @@ -137,7 +137,7 @@ class CTranslatorDXLToPlStmt // command type CmdType m_cmd_type; - // is dml operation requiring returning + // does dml operation require returning BOOL m_has_returning; // has dml operation with returning on replicated table From fe029d8b70995237af9808403bf13a4176379753 Mon Sep 17 00:00:00 2001 From: kotb Date: Mon, 24 Mar 2025 23:34:56 +0300 Subject: [PATCH 44/74] separate returning functionality in CLogicalReturning --- .../include/gpopt/operators/CLogicalDML.h | 15 +-- .../include/gpopt/operators/CLogicalDelete.h | 23 +--- .../include/gpopt/operators/CLogicalInsert.h | 21 +--- .../gpopt/operators/CLogicalReturning.h | 74 ++++++++++++ .../include/gpopt/operators/CLogicalUpdate.h | 24 +--- .../libgpopt/src/operators/CLogicalDML.cpp | 46 ++------ .../libgpopt/src/operators/CLogicalDelete.cpp | 91 ++------------ .../libgpopt/src/operators/CLogicalInsert.cpp | 85 ++------------ .../src/operators/CLogicalReturning.cpp | 111 ++++++++++++++++++ .../libgpopt/src/operators/CLogicalUpdate.cpp | 104 ++-------------- .../gporca/libgpopt/src/operators/Makefile | 1 + 11 files changed, 233 insertions(+), 362 deletions(-) create mode 100644 src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h create mode 100644 src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDML.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDML.h index ffeca0f89239..ece135a88a22 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDML.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDML.h @@ -13,7 +13,7 @@ #include "gpos/base.h" -#include "gpopt/operators/CLogical.h" +#include "gpopt/operators/CLogicalReturning.h" namespace gpopt { @@ -28,7 +28,7 @@ class CTableDescriptor; // Logical DML operator // //--------------------------------------------------------------------------- -class CLogicalDML : public CLogical +class CLogicalDML : public CLogicalReturning { public: // enum of DML operators @@ -52,9 +52,6 @@ class CLogicalDML : public CLogical // source columns CColRefArray *m_pdrgpcrSource; - // returning columns - CColRefArray *m_pdrgpcrOutput; - // set of modified columns from the target table CBitSet *m_pbsModified; @@ -119,14 +116,6 @@ class CLogicalDML : public CLogical return m_pdrgpcrSource; } - // output columns - CColRefArray * - PdrgpcrOutput() const - { - return m_pdrgpcrOutput; - } - - // modified columns set CBitSet * PbsModified() const diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h index 1771beb98584..91b8ca4c260c 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h @@ -13,7 +13,7 @@ #include "gpos/base.h" -#include "gpopt/operators/CLogical.h" +#include "gpopt/operators/CLogicalReturning.h" namespace gpopt { @@ -28,18 +28,12 @@ class CTableDescriptor; // Logical Delete operator // //--------------------------------------------------------------------------- -class CLogicalDelete : public CLogical +class CLogicalDelete : public CLogicalReturning { private: - // table descriptor - CTableDescriptor *m_ptabdesc; - // columns to delete CColRefArray *m_pdrgpcr; - // returning columns - CColRefArray *m_pdrgpcrOutput; - // ctid column CColRef *m_pcrCtid; @@ -61,12 +55,6 @@ class CLogicalDelete : public CLogical CColRefArray *colref_array, CColRef *pcrCtid, CColRef *pcrSegmentId, CColRef *pcrTableOid); - // ctor - CLogicalDelete(CMemoryPool *mp, CTableDescriptor *ptabdesc, - CColRefArray *colref_array, CColRefArray *pdrgpcrOutput, - CColRef *pcrCtid, CColRef *pcrSegmentId, - CColRef *pcrTableOid); - // dtor virtual ~CLogicalDelete(); @@ -91,13 +79,6 @@ class CLogicalDelete : public CLogical return m_pdrgpcr; } - // output columns - CColRefArray * - PdrgpcrOutput() const - { - return m_pdrgpcrOutput; - } - // ctid column CColRef * PcrCtid() const diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalInsert.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalInsert.h index 2dff0a204ec2..1bfc56d424e8 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalInsert.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalInsert.h @@ -13,7 +13,7 @@ #include "gpos/base.h" -#include "gpopt/operators/CLogical.h" +#include "gpopt/operators/CLogicalReturning.h" namespace gpopt { @@ -28,18 +28,12 @@ class CTableDescriptor; // Logical Insert operator // //--------------------------------------------------------------------------- -class CLogicalInsert : public CLogical +class CLogicalInsert : public CLogicalReturning { private: - // table descriptor - CTableDescriptor *m_ptabdesc; - // source columns CColRefArray *m_pdrgpcrSource; - // returning columns - CColRefArray *m_pdrgpcrOutput; - // private copy ctor CLogicalInsert(const CLogicalInsert &); @@ -51,10 +45,6 @@ class CLogicalInsert : public CLogical CLogicalInsert(CMemoryPool *mp, CTableDescriptor *ptabdesc, CColRefArray *colref_array); - // ctor - CLogicalInsert(CMemoryPool *mp, CTableDescriptor *ptabdesc, - CColRefArray *colref_array, CColRefArray *pdrgpcrOutput); - // dtor virtual ~CLogicalInsert(); @@ -79,13 +69,6 @@ class CLogicalInsert : public CLogical return m_pdrgpcrSource; } - // output columns - CColRefArray * - PdrgpcrOutput() const - { - return m_pdrgpcrOutput; - } - // return table's descriptor CTableDescriptor * Ptabdesc() const diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h new file mode 100644 index 000000000000..eb6fdb74c0d5 --- /dev/null +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h @@ -0,0 +1,74 @@ +//--------------------------------------------------------------------------- +// Greenplum Database +// Copyright (C) 2012 EMC Corp. +// +// @filename: +// CLogicalReturning.h +// +// @doc: +// Base class of operators that have returning columns +//--------------------------------------------------------------------------- +#ifndef GPOS_CLogicalReturning_H +#define GPOS_CLogicalReturning_H + +#include "gpos/base.h" + +#include "gpopt/operators/CExpressionHandle.h" +#include "gpopt/operators/CLogical.h" +#include "naucrates/base/IDatum.h" + +namespace gpopt +{ +using namespace gpnaucrates; + +//--------------------------------------------------------------------------- +// @class: +// CLogicalReturning +// +// @doc: +// Base class of logical operators that have returning columns +// +//--------------------------------------------------------------------------- +class CLogicalReturning : public CLogical +{ +private: + // private copy ctor + CLogicalReturning(const CLogicalReturning &); + +protected: + // table descriptor + CTableDescriptor *m_ptabdesc; + + // returning columns + CColRefArray *m_pdrgpcrOutput; + +public: + // ctor + CLogicalReturning(CMemoryPool *mp); + + // ctor + CLogicalReturning(CMemoryPool *mp, CTableDescriptor *ptabdesc); + + // ctor + CLogicalReturning(CMemoryPool *mp, CTableDescriptor *ptabdesc, CColRefArray *pdrgpcrOutput); + + // dtor + virtual ~CLogicalReturning(); + + // output columns + CColRefArray * + PdrgpcrOutput() const + { + return m_pdrgpcrOutput; + } + + // debug print + virtual IOstream &OsPrint(IOstream &) const; + +}; // class CLogicalReturning + +} // namespace gpopt + +#endif // !GPOS_CLogicalReturning_H + +// EOF diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalUpdate.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalUpdate.h index c65ee61a92e5..51b7430cb54b 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalUpdate.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalUpdate.h @@ -13,7 +13,7 @@ #include "gpos/base.h" -#include "gpopt/operators/CLogical.h" +#include "gpopt/operators/CLogicalReturning.h" namespace gpopt { @@ -28,21 +28,15 @@ class CTableDescriptor; // Logical Update operator // //--------------------------------------------------------------------------- -class CLogicalUpdate : public CLogical +class CLogicalUpdate : public CLogicalReturning { private: - // table descriptor - CTableDescriptor *m_ptabdesc; - // columns to delete CColRefArray *m_pdrgpcrDelete; // columns to insert CColRefArray *m_pdrgpcrInsert; - // returning columns - CColRefArray *m_pdrgpcrOutput; - // ctid column CColRef *m_pcrCtid; @@ -68,13 +62,6 @@ class CLogicalUpdate : public CLogical CColRef *pcrCtid, CColRef *pcrSegmentId, CColRef *pcrTupleOid, CColRef *pcrTableOid); - // ctor - CLogicalUpdate(CMemoryPool *mp, CTableDescriptor *ptabdesc, - CColRefArray *pdrgpcrDelete, CColRefArray *pdrgpcrInsert, - CColRefArray *pdrgpcrOutput, CColRef *pcrCtid, - CColRef *pcrSegmentId, CColRef *pcrTupleOid, - CColRef *pcrTableOid); - // dtor virtual ~CLogicalUpdate(); @@ -106,13 +93,6 @@ class CLogicalUpdate : public CLogical return m_pdrgpcrInsert; } - // output columns - CColRefArray * - PdrgpcrOutput() const - { - return m_pdrgpcrOutput; - } - // ctid column CColRef * PcrCtid() const diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp index 15e8a12b2fd7..7a4362ba31da 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp @@ -34,10 +34,9 @@ const WCHAR CLogicalDML::m_rgwszDml[EdmlSentinel][10] = { // //--------------------------------------------------------------------------- CLogicalDML::CLogicalDML(CMemoryPool *mp) - : CLogical(mp), + : CLogicalReturning(mp), m_ptabdesc(NULL), m_pdrgpcrSource(NULL), - m_pdrgpcrOutput(NULL), m_pbsModified(NULL), m_pcrAction(NULL), m_pcrTableOid(NULL), @@ -63,11 +62,10 @@ CLogicalDML::CLogicalDML(CMemoryPool *mp, EDMLOperator edmlop, CColRef *pcrAction, CColRef *pcrCtid, CColRef *pcrSegmentId, CColRef *pcrTupleOid, CColRef *pcrTableOid) - : CLogical(mp), + : CLogicalReturning(mp, ptabdesc, pdrgpcrOutput), m_edmlop(edmlop), m_ptabdesc(ptabdesc), m_pdrgpcrSource(pdrgpcrSource), - m_pdrgpcrOutput(pdrgpcrOutput), m_pbsModified(pbsModified), m_pcrAction(pcrAction), m_pcrTableOid(pcrTableOid), @@ -84,7 +82,6 @@ CLogicalDML::CLogicalDML(CMemoryPool *mp, EDMLOperator edmlop, NULL != pcrCtid && NULL != pcrSegmentId); m_pcrsLocalUsed->Include(m_pdrgpcrSource); - m_pcrsLocalUsed->Include(m_pdrgpcrOutput); m_pcrsLocalUsed->Include(m_pcrAction); if (NULL != m_pcrTableOid) { @@ -120,7 +117,6 @@ CLogicalDML::~CLogicalDML() { CRefCount::SafeRelease(m_ptabdesc); CRefCount::SafeRelease(m_pdrgpcrSource); - CRefCount::SafeRelease(m_pdrgpcrOutput); CRefCount::SafeRelease(m_pbsModified); } @@ -245,9 +241,11 @@ CLogicalDML::PopCopyWithRemappedColumns(CMemoryPool *mp, m_ptabdesc->AddRef(); - return GPOS_NEW(mp) CLogicalDML( + CLogicalDML *result = GPOS_NEW(mp) CLogicalDML( mp, m_edmlop, m_ptabdesc, colref_array, pdrgpcrOutput, m_pbsModified, pcrAction, pcrCtid, pcrSegmentId, pcrTupleOid, pcrTableOid); + + return result; } //--------------------------------------------------------------------------- @@ -411,39 +409,9 @@ CLogicalDML::OsPrint(IOstream &os) const m_pcrSegmentId->OsPrint(os); } - os << ", Output Columns: ["; - CUtils::OsPrintDrgPcr(os, m_pdrgpcrOutput); - os << "] Key sets: {"; - - const ULONG ulColumns = m_pdrgpcrOutput->Size(); - const CBitSetArray *pdrgpbsKeys = m_ptabdesc->PdrgpbsKeys(); - for (ULONG ul = 0; ul < pdrgpbsKeys->Size(); ul++) - { - CBitSet *pbs = (*pdrgpbsKeys)[ul]; - if (0 < ul) - { - os << ", "; - } - os << "["; - ULONG ulPrintedKeys = 0; - for (ULONG ulKey = 0; ulKey < ulColumns; ulKey++) - { - if (pbs->Get(ulKey)) - { - if (0 < ulPrintedKeys) - { - os << ","; - } - os << ulKey; - ulPrintedKeys++; - } - } - os << "]"; - } - os << "}"; - + os << ", "; - return os; + return CLogicalReturning::OsPrint(os); } // EOF diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp index 61ff88c558d9..4b2e2186b515 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp @@ -30,10 +30,8 @@ using namespace gpopt; // //--------------------------------------------------------------------------- CLogicalDelete::CLogicalDelete(CMemoryPool *mp) - : CLogical(mp), - m_ptabdesc(NULL), + : CLogicalReturning(mp), m_pdrgpcr(NULL), - m_pdrgpcrOutput(NULL), m_pcrCtid(NULL), m_pcrSegmentId(NULL), m_pcrTableOid(NULL) @@ -52,59 +50,17 @@ CLogicalDelete::CLogicalDelete(CMemoryPool *mp) CLogicalDelete::CLogicalDelete(CMemoryPool *mp, CTableDescriptor *ptabdesc, CColRefArray *colref_array, CColRef *pcrCtid, CColRef *pcrSegmentId, CColRef *pcrTableOid) - : CLogical(mp), - m_ptabdesc(ptabdesc), + : CLogicalReturning(mp, ptabdesc), m_pdrgpcr(colref_array), - m_pdrgpcrOutput(NULL), m_pcrCtid(pcrCtid), m_pcrSegmentId(pcrSegmentId), m_pcrTableOid(pcrTableOid) { - GPOS_ASSERT(NULL != ptabdesc); GPOS_ASSERT(NULL != colref_array); GPOS_ASSERT(NULL != pcrCtid); GPOS_ASSERT(NULL != pcrSegmentId); - m_pdrgpcrOutput = - PdrgpcrCreateMapping(mp, ptabdesc->Pdrgpcoldesc(), UlOpId()); - m_pcrsLocalUsed->Include(m_pdrgpcr); - m_pcrsLocalUsed->Include(m_pdrgpcrOutput); - m_pcrsLocalUsed->Include(m_pcrCtid); - m_pcrsLocalUsed->Include(m_pcrSegmentId); - if (NULL != m_pcrTableOid) - { - m_pcrsLocalUsed->Include(m_pcrTableOid); - } -} - -//--------------------------------------------------------------------------- -// @function: -// CLogicalDelete::CLogicalDelete -// -// @doc: -// Ctor -// -//--------------------------------------------------------------------------- -CLogicalDelete::CLogicalDelete(CMemoryPool *mp, CTableDescriptor *ptabdesc, - CColRefArray *colref_array, - CColRefArray *pdrgpcrOutput, CColRef *pcrCtid, - CColRef *pcrSegmentId, CColRef *pcrTableOid) - : CLogical(mp), - m_ptabdesc(ptabdesc), - m_pdrgpcr(colref_array), - m_pdrgpcrOutput(pdrgpcrOutput), - m_pcrCtid(pcrCtid), - m_pcrSegmentId(pcrSegmentId), - m_pcrTableOid(pcrTableOid) -{ - GPOS_ASSERT(NULL != ptabdesc); - GPOS_ASSERT(NULL != colref_array); - GPOS_ASSERT(NULL != pcrCtid); - GPOS_ASSERT(NULL != pcrSegmentId); - - m_pcrsLocalUsed->Include(m_pdrgpcr); - m_pcrsLocalUsed->Include(m_pdrgpcrOutput); m_pcrsLocalUsed->Include(m_pcrCtid); m_pcrsLocalUsed->Include(m_pcrSegmentId); if (NULL != m_pcrTableOid) @@ -125,7 +81,6 @@ CLogicalDelete::~CLogicalDelete() { CRefCount::SafeRelease(m_ptabdesc); CRefCount::SafeRelease(m_pdrgpcr); - CRefCount::SafeRelease(m_pdrgpcrOutput); } //--------------------------------------------------------------------------- @@ -218,9 +173,14 @@ CLogicalDelete::PopCopyWithRemappedColumns(CMemoryPool *mp, } m_ptabdesc->AddRef(); - return GPOS_NEW(mp) - CLogicalDelete(mp, m_ptabdesc, colref_array, pdrgpcrOutput, pcrCtid, + CLogicalDelete * result = GPOS_NEW(mp) + CLogicalDelete(mp, m_ptabdesc, colref_array, pcrCtid, pcrSegmentId, pcrTableOid); + + result->m_pdrgpcrOutput = pdrgpcrOutput; + result->m_pcrsLocalUsed->Include(result->m_pdrgpcrOutput); + + return result; } //--------------------------------------------------------------------------- @@ -341,38 +301,7 @@ CLogicalDelete::OsPrint(IOstream &os) const os << ", "; } - os << "Output Columns: ["; - CUtils::OsPrintDrgPcr(os, m_pdrgpcrOutput); - os << "] Key sets: {"; - - const ULONG ulColumns = m_pdrgpcrOutput->Size(); - const CBitSetArray *pdrgpbsKeys = m_ptabdesc->PdrgpbsKeys(); - for (ULONG ul = 0; ul < pdrgpbsKeys->Size(); ul++) - { - CBitSet *pbs = (*pdrgpbsKeys)[ul]; - if (0 < ul) - { - os << ", "; - } - os << "["; - ULONG ulPrintedKeys = 0; - for (ULONG ulKey = 0; ulKey < ulColumns; ulKey++) - { - if (pbs->Get(ulKey)) - { - if (0 < ulPrintedKeys) - { - os << ","; - } - os << ulKey; - ulPrintedKeys++; - } - } - os << "]"; - } - os << "}"; - - return os; + return CLogicalReturning::OsPrint(os); } // EOF diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp index a6366a2fa498..5b49c9e05f7e 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp @@ -30,10 +30,8 @@ using namespace gpopt; // //--------------------------------------------------------------------------- CLogicalInsert::CLogicalInsert(CMemoryPool *mp) - : CLogical(mp), - m_ptabdesc(NULL), - m_pdrgpcrSource(NULL), - m_pdrgpcrOutput(NULL) + : CLogicalReturning(mp), + m_pdrgpcrSource(NULL) { m_fPattern = true; @@ -49,45 +47,14 @@ CLogicalInsert::CLogicalInsert(CMemoryPool *mp) //--------------------------------------------------------------------------- CLogicalInsert::CLogicalInsert(CMemoryPool *mp, CTableDescriptor *ptabdesc, CColRefArray *pdrgpcrSource) - : CLogical(mp), - m_ptabdesc(ptabdesc), - m_pdrgpcrSource(pdrgpcrSource), - m_pdrgpcrOutput(NULL) + : CLogicalReturning(mp, ptabdesc), + m_pdrgpcrSource(pdrgpcrSource) { GPOS_ASSERT(NULL != ptabdesc); GPOS_ASSERT(NULL != pdrgpcrSource); - m_pdrgpcrOutput = - PdrgpcrCreateMapping(mp, ptabdesc->Pdrgpcoldesc(), UlOpId()); - m_pcrsLocalUsed->Include(m_pdrgpcrSource); - m_pcrsLocalUsed->Include(m_pdrgpcrOutput); -} - - -//--------------------------------------------------------------------------- -// @function: -// CLogicalInsert::CLogicalInsert -// -// @doc: -// Ctor -// -//--------------------------------------------------------------------------- -CLogicalInsert::CLogicalInsert(CMemoryPool *mp, CTableDescriptor *ptabdesc, - CColRefArray *pdrgpcrSource, - CColRefArray *pdrgpcrOutput) - : CLogical(mp), - m_ptabdesc(ptabdesc), - m_pdrgpcrSource(pdrgpcrSource), - m_pdrgpcrOutput(pdrgpcrOutput) - -{ - GPOS_ASSERT(NULL != ptabdesc); - GPOS_ASSERT(NULL != pdrgpcrSource); - - m_pcrsLocalUsed->Include(m_pdrgpcrSource); - m_pcrsLocalUsed->Include(m_pdrgpcrOutput); } //--------------------------------------------------------------------------- @@ -102,7 +69,6 @@ CLogicalInsert::~CLogicalInsert() { CRefCount::SafeRelease(m_ptabdesc); CRefCount::SafeRelease(m_pdrgpcrSource); - CRefCount::SafeRelease(m_pdrgpcrOutput); } //--------------------------------------------------------------------------- @@ -179,8 +145,13 @@ CLogicalInsert::PopCopyWithRemappedColumns(CMemoryPool *mp, } m_ptabdesc->AddRef(); - return GPOS_NEW(mp) - CLogicalInsert(mp, m_ptabdesc, colref_array, pdrgpcrOutput); + CLogicalInsert *result = GPOS_NEW(mp) + CLogicalInsert(mp, m_ptabdesc, colref_array); + + result->m_pdrgpcrOutput = pdrgpcrOutput; + result->m_pcrsLocalUsed->Include(result->m_pdrgpcrOutput); + + return result; } //--------------------------------------------------------------------------- @@ -290,39 +261,9 @@ CLogicalInsert::OsPrint(IOstream &os) const m_ptabdesc->Name().OsPrint(os); os << "), Source Columns: ["; CUtils::OsPrintDrgPcr(os, m_pdrgpcrSource); - os << "]"; - os << ", Output Columns: ["; - CUtils::OsPrintDrgPcr(os, m_pdrgpcrOutput); - os << "] Key sets: {"; - - const ULONG ulColumns = m_pdrgpcrOutput->Size(); - const CBitSetArray *pdrgpbsKeys = m_ptabdesc->PdrgpbsKeys(); - for (ULONG ul = 0; ul < pdrgpbsKeys->Size(); ul++) - { - CBitSet *pbs = (*pdrgpbsKeys)[ul]; - if (0 < ul) - { - os << ", "; - } - os << "["; - ULONG ulPrintedKeys = 0; - for (ULONG ulKey = 0; ulKey < ulColumns; ulKey++) - { - if (pbs->Get(ulKey)) - { - if (0 < ulPrintedKeys) - { - os << ","; - } - os << ulKey; - ulPrintedKeys++; - } - } - os << "]"; - } - os << "}"; + os << "], "; - return os; + return CLogicalReturning::OsPrint(os); } // EOF diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp new file mode 100644 index 000000000000..e3011704823f --- /dev/null +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp @@ -0,0 +1,111 @@ +//--------------------------------------------------------------------------- +// Greenplum Database +// Copyright (C) 2013 EMC Corp. +// +// @filename: +// CLogicalReturning.cpp +// +// @doc: +//--------------------------------------------------------------------------- + +#include "gpopt/operators/CLogicalReturning.h" + +#include "gpos/base.h" + +#include "gpopt/xforms/CXformUtils.h" +#include "naucrates/statistics/CProjectStatsProcessor.h" + +using namespace gpopt; + +CLogicalReturning::CLogicalReturning(CMemoryPool *mp) + : CLogical(mp), + m_ptabdesc(NULL), + m_pdrgpcrOutput(NULL) +{ +} + +//--------------------------------------------------------------------------- +// @function: +// CLogicalDML::CLogicalDML +// +// @doc: +// Ctor +// +//--------------------------------------------------------------------------- +CLogicalReturning::CLogicalReturning(CMemoryPool *mp, + CTableDescriptor *ptabdesc) + : CLogical(mp), + m_ptabdesc(ptabdesc), + m_pdrgpcrOutput(NULL) +{ + GPOS_ASSERT(NULL != ptabdesc); + + m_pdrgpcrOutput = + PdrgpcrCreateMapping(mp, ptabdesc->Pdrgpcoldesc(), UlOpId()); + + m_pcrsLocalUsed->Include(m_pdrgpcrOutput); +} + +//--------------------------------------------------------------------------- +// @function: +// CLogicalDML::CLogicalDML +// +// @doc: +// Ctor +// +//--------------------------------------------------------------------------- +CLogicalReturning::CLogicalReturning(CMemoryPool *mp, + CTableDescriptor *ptabdesc, + CColRefArray *pdrgpcrOutput) + : CLogical(mp), m_ptabdesc(ptabdesc), m_pdrgpcrOutput(pdrgpcrOutput) +{ + GPOS_ASSERT(NULL != ptabdesc); + GPOS_ASSERT(NULL != pdrgpcrOutput); + + m_pcrsLocalUsed->Include(m_pdrgpcrOutput); +} + +CLogicalReturning::~CLogicalReturning() +{ + CRefCount::SafeRelease(m_pdrgpcrOutput); +} + + +IOstream & +CLogicalReturning::OsPrint(IOstream &os) const +{ + os << "Output Columns: ["; + CUtils::OsPrintDrgPcr(os, m_pdrgpcrOutput); + os << "] Key sets: {"; + + const ULONG ulColumns = m_pdrgpcrOutput->Size(); + const CBitSetArray *pdrgpbsKeys = m_ptabdesc->PdrgpbsKeys(); + for (ULONG ul = 0; ul < pdrgpbsKeys->Size(); ul++) + { + CBitSet *pbs = (*pdrgpbsKeys)[ul]; + if (0 < ul) + { + os << ", "; + } + os << "["; + ULONG ulPrintedKeys = 0; + for (ULONG ulKey = 0; ulKey < ulColumns; ulKey++) + { + if (pbs->Get(ulKey)) + { + if (0 < ulPrintedKeys) + { + os << ","; + } + os << ulKey; + ulPrintedKeys++; + } + } + os << "]"; + } + os << "}"; + + return os; +} + +// EOF diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp index 5fed6926e7de..25e4864f67f6 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp @@ -30,11 +30,9 @@ using namespace gpopt; // //--------------------------------------------------------------------------- CLogicalUpdate::CLogicalUpdate(CMemoryPool *mp) - : CLogical(mp), - m_ptabdesc(NULL), + : CLogicalReturning(mp), m_pdrgpcrDelete(NULL), m_pdrgpcrInsert(NULL), - m_pdrgpcrOutput(NULL), m_pcrCtid(NULL), m_pcrSegmentId(NULL), m_pcrTupleOid(NULL), @@ -56,68 +54,14 @@ CLogicalUpdate::CLogicalUpdate(CMemoryPool *mp, CTableDescriptor *ptabdesc, CColRefArray *pdrgpcrInsert, CColRef *pcrCtid, CColRef *pcrSegmentId, CColRef *pcrTupleOid, CColRef *pcrTableOid) - : CLogical(mp), - m_ptabdesc(ptabdesc), + : CLogicalReturning(mp, ptabdesc), m_pdrgpcrDelete(pdrgpcrDelete), m_pdrgpcrInsert(pdrgpcrInsert), - m_pdrgpcrOutput(NULL), m_pcrCtid(pcrCtid), m_pcrSegmentId(pcrSegmentId), m_pcrTupleOid(pcrTupleOid), m_pcrTableOid(pcrTableOid) { - GPOS_ASSERT(NULL != ptabdesc); - GPOS_ASSERT(NULL != pdrgpcrDelete); - GPOS_ASSERT(NULL != pdrgpcrInsert); - GPOS_ASSERT(pdrgpcrDelete->Size() == pdrgpcrInsert->Size()); - GPOS_ASSERT(NULL != pcrCtid); - GPOS_ASSERT(NULL != pcrSegmentId); - - m_pdrgpcrOutput = - PdrgpcrCreateMapping(mp, ptabdesc->Pdrgpcoldesc(), UlOpId()); - - m_pcrsLocalUsed->Include(m_pdrgpcrDelete); - m_pcrsLocalUsed->Include(m_pdrgpcrInsert); - m_pcrsLocalUsed->Include(m_pdrgpcrOutput); - m_pcrsLocalUsed->Include(m_pcrCtid); - m_pcrsLocalUsed->Include(m_pcrSegmentId); - - if (NULL != m_pcrTupleOid) - { - m_pcrsLocalUsed->Include(m_pcrTupleOid); - } - - if (NULL != m_pcrTableOid) - { - m_pcrsLocalUsed->Include(m_pcrTableOid); - } -} - -//--------------------------------------------------------------------------- -// @function: -// CLogicalUpdate::CLogicalUpdate -// -// @doc: -// Ctor -// -//--------------------------------------------------------------------------- -CLogicalUpdate::CLogicalUpdate(CMemoryPool *mp, CTableDescriptor *ptabdesc, - CColRefArray *pdrgpcrDelete, - CColRefArray *pdrgpcrInsert, - CColRefArray *pdrgpcrOutput, CColRef *pcrCtid, - CColRef *pcrSegmentId, CColRef *pcrTupleOid, - CColRef *pcrTableOid) - : CLogical(mp), - m_ptabdesc(ptabdesc), - m_pdrgpcrDelete(pdrgpcrDelete), - m_pdrgpcrInsert(pdrgpcrInsert), - m_pdrgpcrOutput(pdrgpcrOutput), - m_pcrCtid(pcrCtid), - m_pcrSegmentId(pcrSegmentId), - m_pcrTupleOid(pcrTupleOid), - m_pcrTableOid(pcrTableOid) -{ - GPOS_ASSERT(NULL != ptabdesc); GPOS_ASSERT(NULL != pdrgpcrDelete); GPOS_ASSERT(NULL != pdrgpcrInsert); GPOS_ASSERT(pdrgpcrDelete->Size() == pdrgpcrInsert->Size()); @@ -126,7 +70,6 @@ CLogicalUpdate::CLogicalUpdate(CMemoryPool *mp, CTableDescriptor *ptabdesc, m_pcrsLocalUsed->Include(m_pdrgpcrDelete); m_pcrsLocalUsed->Include(m_pdrgpcrInsert); - m_pcrsLocalUsed->Include(m_pdrgpcrOutput); m_pcrsLocalUsed->Include(m_pcrCtid); m_pcrsLocalUsed->Include(m_pcrSegmentId); @@ -141,7 +84,6 @@ CLogicalUpdate::CLogicalUpdate(CMemoryPool *mp, CTableDescriptor *ptabdesc, } } - //--------------------------------------------------------------------------- // @function: // CLogicalUpdate::~CLogicalUpdate @@ -155,7 +97,6 @@ CLogicalUpdate::~CLogicalUpdate() CRefCount::SafeRelease(m_ptabdesc); CRefCount::SafeRelease(m_pdrgpcrDelete); CRefCount::SafeRelease(m_pdrgpcrInsert); - CRefCount::SafeRelease(m_pdrgpcrOutput); } //--------------------------------------------------------------------------- @@ -261,9 +202,13 @@ CLogicalUpdate::PopCopyWithRemappedColumns(CMemoryPool *mp, pcrTableOid = CUtils::PcrRemap(m_pcrTableOid, colref_mapping, must_exist); } - return GPOS_NEW(mp) CLogicalUpdate(mp, m_ptabdesc, pdrgpcrDelete, - pdrgpcrInsert, pdrgpcrOutput, pcrCtid, + CLogicalUpdate * result = GPOS_NEW(mp) CLogicalUpdate(mp, m_ptabdesc, pdrgpcrDelete, + pdrgpcrInsert, pcrCtid, pcrSegmentId, pcrTupleOid, pcrTableOid); + + result->m_pdrgpcrOutput = pdrgpcrOutput; + result->m_pcrsLocalUsed->Include(result->m_pdrgpcrOutput); + return result; } //--------------------------------------------------------------------------- @@ -396,38 +341,7 @@ CLogicalUpdate::OsPrint(IOstream &os) const os << ", "; } - os << "Output Columns: ["; - CUtils::OsPrintDrgPcr(os, m_pdrgpcrOutput); - os << "] Key sets: {"; - - const ULONG ulColumns = m_pdrgpcrOutput->Size(); - const CBitSetArray *pdrgpbsKeys = m_ptabdesc->PdrgpbsKeys(); - for (ULONG ul = 0; ul < pdrgpbsKeys->Size(); ul++) - { - CBitSet *pbs = (*pdrgpbsKeys)[ul]; - if (0 < ul) - { - os << ", "; - } - os << "["; - ULONG ulPrintedKeys = 0; - for (ULONG ulKey = 0; ulKey < ulColumns; ulKey++) - { - if (pbs->Get(ulKey)) - { - if (0 < ulPrintedKeys) - { - os << ","; - } - os << ulKey; - ulPrintedKeys++; - } - } - os << "]"; - } - os << "}"; - - return os; + return CLogicalReturning::OsPrint(os); } // EOF diff --git a/src/backend/gporca/libgpopt/src/operators/Makefile b/src/backend/gporca/libgpopt/src/operators/Makefile index 12c645bc7ccf..123945392c36 100644 --- a/src/backend/gporca/libgpopt/src/operators/Makefile +++ b/src/backend/gporca/libgpopt/src/operators/Makefile @@ -66,6 +66,7 @@ OBJS = CExpression.o \ CLogicalNAryJoin.o \ CLogicalPartitionSelector.o \ CLogicalProject.o \ + CLogicalReturning.o \ CLogicalRightOuterJoin.o \ CLogicalRowTrigger.o \ CLogicalSelect.o \ From 174f7dcf70cc7ae47026851e952b6b0de12061e0 Mon Sep 17 00:00:00 2001 From: kotb Date: Tue, 25 Mar 2025 00:30:02 +0300 Subject: [PATCH 45/74] fixes CLogicalReturning --- .../include/gpopt/operators/CLogicalDML.h | 3 - .../include/gpopt/operators/CLogicalDelete.h | 9 ++ .../include/gpopt/operators/CLogicalInsert.h | 7 ++ .../include/gpopt/operators/CLogicalUpdate.h | 10 +++ .../libgpopt/src/operators/CLogicalDML.cpp | 4 - .../libgpopt/src/operators/CLogicalDelete.cpp | 65 +++++++++++---- .../libgpopt/src/operators/CLogicalInsert.cpp | 42 ++++++++-- .../src/operators/CLogicalReturning.cpp | 18 +++- .../libgpopt/src/operators/CLogicalUpdate.cpp | 82 ++++++++++++++----- 9 files changed, 185 insertions(+), 55 deletions(-) diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDML.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDML.h index ece135a88a22..e8a528091c34 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDML.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDML.h @@ -46,9 +46,6 @@ class CLogicalDML : public CLogicalReturning // dml operator EDMLOperator m_edmlop; - // table descriptor - CTableDescriptor *m_ptabdesc; - // source columns CColRefArray *m_pdrgpcrSource; diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h index 91b8ca4c260c..29d9f02e2787 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h @@ -45,6 +45,9 @@ class CLogicalDelete : public CLogicalReturning // private copy ctor CLogicalDelete(const CLogicalDelete &); + + // initialize locally used columns + void InitUsedColumns(); public: // ctor @@ -55,6 +58,12 @@ class CLogicalDelete : public CLogicalReturning CColRefArray *colref_array, CColRef *pcrCtid, CColRef *pcrSegmentId, CColRef *pcrTableOid); + // ctor + CLogicalDelete(CMemoryPool *mp, CTableDescriptor *ptabdesc, + CColRefArray *colref_array, CColRef *pcrCtid, + CColRef *pcrSegmentId, CColRef *pcrTableOid, + CColRefArray *pdrgpcrOutput); + // dtor virtual ~CLogicalDelete(); diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalInsert.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalInsert.h index 1bfc56d424e8..31b81c5c8132 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalInsert.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalInsert.h @@ -37,6 +37,9 @@ class CLogicalInsert : public CLogicalReturning // private copy ctor CLogicalInsert(const CLogicalInsert &); + // initialize locally used columns + void InitUsedColumns(); + public: // ctor explicit CLogicalInsert(CMemoryPool *mp); @@ -45,6 +48,10 @@ class CLogicalInsert : public CLogicalReturning CLogicalInsert(CMemoryPool *mp, CTableDescriptor *ptabdesc, CColRefArray *colref_array); + // ctor + CLogicalInsert(CMemoryPool *mp, CTableDescriptor *ptabdesc, + CColRefArray *colref_array, CColRefArray *pdrgpcrOutput); + // dtor virtual ~CLogicalInsert(); diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalUpdate.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalUpdate.h index 51b7430cb54b..4c8aa34435b8 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalUpdate.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalUpdate.h @@ -52,6 +52,9 @@ class CLogicalUpdate : public CLogicalReturning // private copy ctor CLogicalUpdate(const CLogicalUpdate &); + // initialize locally used columns + void InitUsedColumns(); + public: // ctor explicit CLogicalUpdate(CMemoryPool *mp); @@ -62,6 +65,13 @@ class CLogicalUpdate : public CLogicalReturning CColRef *pcrCtid, CColRef *pcrSegmentId, CColRef *pcrTupleOid, CColRef *pcrTableOid); + // ctor + CLogicalUpdate(CMemoryPool *mp, CTableDescriptor *ptabdesc, + CColRefArray *pdrgpcrDelete, CColRefArray *pdrgpcrInsert, + CColRef *pcrCtid, CColRef *pcrSegmentId, + CColRef *pcrTupleOid, CColRef *pcrTableOid, + CColRefArray *pdrgpcrOutput); + // dtor virtual ~CLogicalUpdate(); diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp index 7a4362ba31da..d05241e4e315 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp @@ -35,7 +35,6 @@ const WCHAR CLogicalDML::m_rgwszDml[EdmlSentinel][10] = { //--------------------------------------------------------------------------- CLogicalDML::CLogicalDML(CMemoryPool *mp) : CLogicalReturning(mp), - m_ptabdesc(NULL), m_pdrgpcrSource(NULL), m_pbsModified(NULL), m_pcrAction(NULL), @@ -64,7 +63,6 @@ CLogicalDML::CLogicalDML(CMemoryPool *mp, EDMLOperator edmlop, CColRef *pcrTableOid) : CLogicalReturning(mp, ptabdesc, pdrgpcrOutput), m_edmlop(edmlop), - m_ptabdesc(ptabdesc), m_pdrgpcrSource(pdrgpcrSource), m_pbsModified(pbsModified), m_pcrAction(pcrAction), @@ -74,7 +72,6 @@ CLogicalDML::CLogicalDML(CMemoryPool *mp, EDMLOperator edmlop, m_pcrTupleOid(pcrTupleOid) { GPOS_ASSERT(EdmlSentinel != edmlop); - GPOS_ASSERT(NULL != ptabdesc); GPOS_ASSERT(NULL != pdrgpcrSource); GPOS_ASSERT(NULL != pbsModified); GPOS_ASSERT(NULL != pcrAction); @@ -115,7 +112,6 @@ CLogicalDML::CLogicalDML(CMemoryPool *mp, EDMLOperator edmlop, //--------------------------------------------------------------------------- CLogicalDML::~CLogicalDML() { - CRefCount::SafeRelease(m_ptabdesc); CRefCount::SafeRelease(m_pdrgpcrSource); CRefCount::SafeRelease(m_pbsModified); } diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp index 4b2e2186b515..ad80bf1fc211 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp @@ -56,17 +56,28 @@ CLogicalDelete::CLogicalDelete(CMemoryPool *mp, CTableDescriptor *ptabdesc, m_pcrSegmentId(pcrSegmentId), m_pcrTableOid(pcrTableOid) { - GPOS_ASSERT(NULL != colref_array); - GPOS_ASSERT(NULL != pcrCtid); - GPOS_ASSERT(NULL != pcrSegmentId); + InitUsedColumns(); +} - m_pcrsLocalUsed->Include(m_pdrgpcr); - m_pcrsLocalUsed->Include(m_pcrCtid); - m_pcrsLocalUsed->Include(m_pcrSegmentId); - if (NULL != m_pcrTableOid) - { - m_pcrsLocalUsed->Include(m_pcrTableOid); - } +//--------------------------------------------------------------------------- +// @function: +// CLogicalDelete::CLogicalDelete +// +// @doc: +// Ctor +// +//--------------------------------------------------------------------------- +CLogicalDelete::CLogicalDelete(CMemoryPool *mp, CTableDescriptor *ptabdesc, + CColRefArray *colref_array, CColRef *pcrCtid, + CColRef *pcrSegmentId, CColRef *pcrTableOid, + CColRefArray *pdrgpcrOutput) + : CLogicalReturning(mp, ptabdesc, pdrgpcrOutput), + m_pdrgpcr(colref_array), + m_pcrCtid(pcrCtid), + m_pcrSegmentId(pcrSegmentId), + m_pcrTableOid(pcrTableOid) +{ + InitUsedColumns(); } //--------------------------------------------------------------------------- @@ -79,10 +90,33 @@ CLogicalDelete::CLogicalDelete(CMemoryPool *mp, CTableDescriptor *ptabdesc, //--------------------------------------------------------------------------- CLogicalDelete::~CLogicalDelete() { - CRefCount::SafeRelease(m_ptabdesc); CRefCount::SafeRelease(m_pdrgpcr); } +//--------------------------------------------------------------------------- +// @function: +// CLogicalDelete::InitUsedColumns +// +// @doc: +// Initialize locally used columns +// +//--------------------------------------------------------------------------- +void CLogicalDelete::InitUsedColumns() +{ + GPOS_ASSERT(NULL != m_pdrgpcr); + GPOS_ASSERT(NULL != m_pcrCtid); + GPOS_ASSERT(NULL != m_pcrSegmentId); + + m_pcrsLocalUsed->Include(m_pdrgpcr); + m_pcrsLocalUsed->Include(m_pcrCtid); + m_pcrsLocalUsed->Include(m_pcrSegmentId); + if (NULL != m_pcrTableOid) + { + m_pcrsLocalUsed->Include(m_pcrTableOid); + } + +} + //--------------------------------------------------------------------------- // @function: // CLogicalDelete::Matches @@ -173,12 +207,9 @@ CLogicalDelete::PopCopyWithRemappedColumns(CMemoryPool *mp, } m_ptabdesc->AddRef(); - CLogicalDelete * result = GPOS_NEW(mp) - CLogicalDelete(mp, m_ptabdesc, colref_array, pcrCtid, - pcrSegmentId, pcrTableOid); - - result->m_pdrgpcrOutput = pdrgpcrOutput; - result->m_pcrsLocalUsed->Include(result->m_pdrgpcrOutput); + CLogicalDelete *result = + GPOS_NEW(mp) CLogicalDelete(mp, m_ptabdesc, colref_array, pcrCtid, + pcrSegmentId, pcrTableOid, pdrgpcrOutput); return result; } diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp index 5b49c9e05f7e..aa01a2e2a518 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp @@ -51,10 +51,25 @@ CLogicalInsert::CLogicalInsert(CMemoryPool *mp, CTableDescriptor *ptabdesc, m_pdrgpcrSource(pdrgpcrSource) { - GPOS_ASSERT(NULL != ptabdesc); - GPOS_ASSERT(NULL != pdrgpcrSource); + InitUsedColumns(); +} - m_pcrsLocalUsed->Include(m_pdrgpcrSource); +//--------------------------------------------------------------------------- +// @function: +// CLogicalInsert::CLogicalInsert +// +// @doc: +// Ctor +// +//--------------------------------------------------------------------------- +CLogicalInsert::CLogicalInsert(CMemoryPool *mp, CTableDescriptor *ptabdesc, + CColRefArray *pdrgpcrSource, + CColRefArray *pdrgpcrOutput) + : CLogicalReturning(mp, ptabdesc, pdrgpcrOutput), + m_pdrgpcrSource(pdrgpcrSource) + +{ + InitUsedColumns(); } //--------------------------------------------------------------------------- @@ -67,10 +82,24 @@ CLogicalInsert::CLogicalInsert(CMemoryPool *mp, CTableDescriptor *ptabdesc, //--------------------------------------------------------------------------- CLogicalInsert::~CLogicalInsert() { - CRefCount::SafeRelease(m_ptabdesc); CRefCount::SafeRelease(m_pdrgpcrSource); } +//--------------------------------------------------------------------------- +// @function: +// CLogicalInsert::InitUsedColumns +// +// @doc: +// Initialize locally used columns +// +//--------------------------------------------------------------------------- +void CLogicalInsert::InitUsedColumns() +{ + GPOS_ASSERT(NULL != m_pdrgpcrSource); + + m_pcrsLocalUsed->Include(m_pdrgpcrSource); +} + //--------------------------------------------------------------------------- // @function: // CLogicalInsert::Matches @@ -146,10 +175,7 @@ CLogicalInsert::PopCopyWithRemappedColumns(CMemoryPool *mp, m_ptabdesc->AddRef(); CLogicalInsert *result = GPOS_NEW(mp) - CLogicalInsert(mp, m_ptabdesc, colref_array); - - result->m_pdrgpcrOutput = pdrgpcrOutput; - result->m_pcrsLocalUsed->Include(result->m_pdrgpcrOutput); + CLogicalInsert(mp, m_ptabdesc, colref_array, pdrgpcrOutput); return result; } diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp index e3011704823f..e5e430887916 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp @@ -65,12 +65,28 @@ CLogicalReturning::CLogicalReturning(CMemoryPool *mp, m_pcrsLocalUsed->Include(m_pdrgpcrOutput); } +//--------------------------------------------------------------------------- +// @function: +// CLogicalReturning::~CLogicalReturning +// +// @doc: +// Dtor +// +//--------------------------------------------------------------------------- CLogicalReturning::~CLogicalReturning() { + CRefCount::SafeRelease(m_ptabdesc); CRefCount::SafeRelease(m_pdrgpcrOutput); } - +//--------------------------------------------------------------------------- +// @function: +// CLogicalReturning::OsPrint +// +// @doc: +// debug print +// +//--------------------------------------------------------------------------- IOstream & CLogicalReturning::OsPrint(IOstream &os) const { diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp index 25e4864f67f6..8ad8991a9841 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp @@ -62,26 +62,36 @@ CLogicalUpdate::CLogicalUpdate(CMemoryPool *mp, CTableDescriptor *ptabdesc, m_pcrTupleOid(pcrTupleOid), m_pcrTableOid(pcrTableOid) { - GPOS_ASSERT(NULL != pdrgpcrDelete); - GPOS_ASSERT(NULL != pdrgpcrInsert); GPOS_ASSERT(pdrgpcrDelete->Size() == pdrgpcrInsert->Size()); - GPOS_ASSERT(NULL != pcrCtid); - GPOS_ASSERT(NULL != pcrSegmentId); - m_pcrsLocalUsed->Include(m_pdrgpcrDelete); - m_pcrsLocalUsed->Include(m_pdrgpcrInsert); - m_pcrsLocalUsed->Include(m_pcrCtid); - m_pcrsLocalUsed->Include(m_pcrSegmentId); + InitUsedColumns(); +} - if (NULL != m_pcrTupleOid) - { - m_pcrsLocalUsed->Include(m_pcrTupleOid); - } +//--------------------------------------------------------------------------- +// @function: +// CLogicalUpdate::CLogicalUpdate +// +// @doc: +// Ctor +// +//--------------------------------------------------------------------------- +CLogicalUpdate::CLogicalUpdate(CMemoryPool *mp, CTableDescriptor *ptabdesc, + CColRefArray *pdrgpcrDelete, + CColRefArray *pdrgpcrInsert, CColRef *pcrCtid, + CColRef *pcrSegmentId, CColRef *pcrTupleOid, + CColRef *pcrTableOid, + CColRefArray *pdrgpcrOutput) + : CLogicalReturning(mp, ptabdesc, pdrgpcrOutput), + m_pdrgpcrDelete(pdrgpcrDelete), + m_pdrgpcrInsert(pdrgpcrInsert), + m_pcrCtid(pcrCtid), + m_pcrSegmentId(pcrSegmentId), + m_pcrTupleOid(pcrTupleOid), + m_pcrTableOid(pcrTableOid) +{ + GPOS_ASSERT(pdrgpcrDelete->Size() == pdrgpcrInsert->Size()); - if (NULL != m_pcrTableOid) - { - m_pcrsLocalUsed->Include(m_pcrTableOid); - } + InitUsedColumns(); } //--------------------------------------------------------------------------- @@ -94,11 +104,41 @@ CLogicalUpdate::CLogicalUpdate(CMemoryPool *mp, CTableDescriptor *ptabdesc, //--------------------------------------------------------------------------- CLogicalUpdate::~CLogicalUpdate() { - CRefCount::SafeRelease(m_ptabdesc); CRefCount::SafeRelease(m_pdrgpcrDelete); CRefCount::SafeRelease(m_pdrgpcrInsert); } +//--------------------------------------------------------------------------- +// @function: +// CLogicalUpdate::InitUsedColumns +// +// @doc: +// Initialize locally used columns +// +//--------------------------------------------------------------------------- +void CLogicalUpdate::InitUsedColumns() +{ + GPOS_ASSERT(NULL != m_pdrgpcrDelete); + GPOS_ASSERT(NULL != m_pdrgpcrInsert); + GPOS_ASSERT(NULL != m_pcrCtid); + GPOS_ASSERT(NULL != m_pcrSegmentId); + + m_pcrsLocalUsed->Include(m_pdrgpcrDelete); + m_pcrsLocalUsed->Include(m_pdrgpcrInsert); + m_pcrsLocalUsed->Include(m_pcrCtid); + m_pcrsLocalUsed->Include(m_pcrSegmentId); + + if (NULL != m_pcrTupleOid) + { + m_pcrsLocalUsed->Include(m_pcrTupleOid); + } + + if (NULL != m_pcrTableOid) + { + m_pcrsLocalUsed->Include(m_pcrTableOid); + } +} + //--------------------------------------------------------------------------- // @function: // CLogicalUpdate::Matches @@ -202,12 +242,10 @@ CLogicalUpdate::PopCopyWithRemappedColumns(CMemoryPool *mp, pcrTableOid = CUtils::PcrRemap(m_pcrTableOid, colref_mapping, must_exist); } - CLogicalUpdate * result = GPOS_NEW(mp) CLogicalUpdate(mp, m_ptabdesc, pdrgpcrDelete, - pdrgpcrInsert, pcrCtid, - pcrSegmentId, pcrTupleOid, pcrTableOid); + CLogicalUpdate *result = GPOS_NEW(mp) + CLogicalUpdate(mp, m_ptabdesc, pdrgpcrDelete, pdrgpcrInsert, pcrCtid, + pcrSegmentId, pcrTupleOid, pcrTableOid, pdrgpcrOutput); - result->m_pdrgpcrOutput = pdrgpcrOutput; - result->m_pcrsLocalUsed->Include(result->m_pdrgpcrOutput); return result; } From af87fe0d5c93ad3c8df82470149a87b066f2b03c Mon Sep 17 00:00:00 2001 From: kotb Date: Tue, 25 Mar 2025 10:19:18 +0300 Subject: [PATCH 46/74] fix linter --- .../libgpopt/include/gpopt/operators/CLogicalDelete.h | 2 +- .../include/gpopt/operators/CLogicalReturning.h | 3 ++- .../gporca/libgpopt/src/operators/CLogicalDelete.cpp | 4 ++-- .../gporca/libgpopt/src/operators/CLogicalInsert.cpp | 9 ++++----- .../libgpopt/src/operators/CLogicalReturning.cpp | 10 +++------- .../gporca/libgpopt/src/operators/CLogicalUpdate.cpp | 3 ++- 6 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h index 29d9f02e2787..4858fff7e476 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h @@ -45,7 +45,7 @@ class CLogicalDelete : public CLogicalReturning // private copy ctor CLogicalDelete(const CLogicalDelete &); - + // initialize locally used columns void InitUsedColumns(); diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h index eb6fdb74c0d5..cfde0e0b14aa 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h @@ -50,7 +50,8 @@ class CLogicalReturning : public CLogical CLogicalReturning(CMemoryPool *mp, CTableDescriptor *ptabdesc); // ctor - CLogicalReturning(CMemoryPool *mp, CTableDescriptor *ptabdesc, CColRefArray *pdrgpcrOutput); + CLogicalReturning(CMemoryPool *mp, CTableDescriptor *ptabdesc, + CColRefArray *pdrgpcrOutput); // dtor virtual ~CLogicalReturning(); diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp index ad80bf1fc211..a2fe150033ad 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp @@ -101,7 +101,8 @@ CLogicalDelete::~CLogicalDelete() // Initialize locally used columns // //--------------------------------------------------------------------------- -void CLogicalDelete::InitUsedColumns() +void +CLogicalDelete::InitUsedColumns() { GPOS_ASSERT(NULL != m_pdrgpcr); GPOS_ASSERT(NULL != m_pcrCtid); @@ -114,7 +115,6 @@ void CLogicalDelete::InitUsedColumns() { m_pcrsLocalUsed->Include(m_pcrTableOid); } - } //--------------------------------------------------------------------------- diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp index aa01a2e2a518..d46fe6cfcd14 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp @@ -30,8 +30,7 @@ using namespace gpopt; // //--------------------------------------------------------------------------- CLogicalInsert::CLogicalInsert(CMemoryPool *mp) - : CLogicalReturning(mp), - m_pdrgpcrSource(NULL) + : CLogicalReturning(mp), m_pdrgpcrSource(NULL) { m_fPattern = true; @@ -47,8 +46,7 @@ CLogicalInsert::CLogicalInsert(CMemoryPool *mp) //--------------------------------------------------------------------------- CLogicalInsert::CLogicalInsert(CMemoryPool *mp, CTableDescriptor *ptabdesc, CColRefArray *pdrgpcrSource) - : CLogicalReturning(mp, ptabdesc), - m_pdrgpcrSource(pdrgpcrSource) + : CLogicalReturning(mp, ptabdesc), m_pdrgpcrSource(pdrgpcrSource) { InitUsedColumns(); @@ -93,7 +91,8 @@ CLogicalInsert::~CLogicalInsert() // Initialize locally used columns // //--------------------------------------------------------------------------- -void CLogicalInsert::InitUsedColumns() +void +CLogicalInsert::InitUsedColumns() { GPOS_ASSERT(NULL != m_pdrgpcrSource); diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp index e5e430887916..b4e5b00ab1e4 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp @@ -18,9 +18,7 @@ using namespace gpopt; CLogicalReturning::CLogicalReturning(CMemoryPool *mp) - : CLogical(mp), - m_ptabdesc(NULL), - m_pdrgpcrOutput(NULL) + : CLogical(mp), m_ptabdesc(NULL), m_pdrgpcrOutput(NULL) { } @@ -33,10 +31,8 @@ CLogicalReturning::CLogicalReturning(CMemoryPool *mp) // //--------------------------------------------------------------------------- CLogicalReturning::CLogicalReturning(CMemoryPool *mp, - CTableDescriptor *ptabdesc) - : CLogical(mp), - m_ptabdesc(ptabdesc), - m_pdrgpcrOutput(NULL) + CTableDescriptor *ptabdesc) + : CLogical(mp), m_ptabdesc(ptabdesc), m_pdrgpcrOutput(NULL) { GPOS_ASSERT(NULL != ptabdesc); diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp index 8ad8991a9841..825831584b8f 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp @@ -116,7 +116,8 @@ CLogicalUpdate::~CLogicalUpdate() // Initialize locally used columns // //--------------------------------------------------------------------------- -void CLogicalUpdate::InitUsedColumns() +void +CLogicalUpdate::InitUsedColumns() { GPOS_ASSERT(NULL != m_pdrgpcrDelete); GPOS_ASSERT(NULL != m_pdrgpcrInsert); From a02471ea95a4e21414cd707bfd6fb5f2edfa6852 Mon Sep 17 00:00:00 2001 From: kotb Date: Wed, 26 Mar 2025 09:27:21 +0300 Subject: [PATCH 47/74] move empty line --- src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp index a2fe150033ad..acd3d66882ac 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp @@ -142,8 +142,8 @@ CLogicalDelete::Matches(COperator *pop) const m_pdrgpcr->Equals(popDelete->Pdrgpcr()) && m_pdrgpcrOutput->Equals(popDelete->PdrgpcrOutput()); } -//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- // @function: // CLogicalDelete::HashValue // From 85adab150fe8f2ec956164fa0fc46725bdca826f Mon Sep 17 00:00:00 2001 From: kotb Date: Wed, 26 Mar 2025 09:28:32 +0300 Subject: [PATCH 48/74] FHasLogicalDML get last from RemoveLast --- src/backend/gporca/libgpopt/src/base/CUtils.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/backend/gporca/libgpopt/src/base/CUtils.cpp b/src/backend/gporca/libgpopt/src/base/CUtils.cpp index 8942ba6b7f5e..ce231e0eabf0 100644 --- a/src/backend/gporca/libgpopt/src/base/CUtils.cpp +++ b/src/backend/gporca/libgpopt/src/base/CUtils.cpp @@ -3305,8 +3305,7 @@ CUtils::FHasLogicalDML(CMemoryPool *mp, CExpression *pexpr) while (exprsToCheck->Size() > 0) { - CExpression *pexprCurrent = (*exprsToCheck)[exprsToCheck->Size() - 1]; - exprsToCheck->RemoveLast(); + CExpression *pexprCurrent = exprsToCheck->RemoveLast(); if (FLogicalDML(pexprCurrent->Pop())) { From 8dd13570e395f81b19a9a246ba0047dc43e7d36a Mon Sep 17 00:00:00 2001 From: kotb Date: Wed, 26 Mar 2025 09:31:15 +0300 Subject: [PATCH 49/74] descriptor getter to base class --- .../libgpopt/include/gpopt/operators/CLogicalDelete.h | 7 ------- .../libgpopt/include/gpopt/operators/CLogicalInsert.h | 7 ------- .../libgpopt/include/gpopt/operators/CLogicalReturning.h | 7 +++++++ .../libgpopt/include/gpopt/operators/CLogicalUpdate.h | 7 ------- 4 files changed, 7 insertions(+), 21 deletions(-) diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h index 4858fff7e476..54c7f897d740 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h @@ -109,13 +109,6 @@ class CLogicalDelete : public CLogicalReturning return m_pcrTableOid; } - // return table's descriptor - CTableDescriptor * - Ptabdesc() const - { - return m_ptabdesc; - } - // operator specific hash function virtual ULONG HashValue() const; diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalInsert.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalInsert.h index 31b81c5c8132..092e1f437ee6 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalInsert.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalInsert.h @@ -76,13 +76,6 @@ class CLogicalInsert : public CLogicalReturning return m_pdrgpcrSource; } - // return table's descriptor - CTableDescriptor * - Ptabdesc() const - { - return m_ptabdesc; - } - // operator specific hash function virtual ULONG HashValue() const; diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h index cfde0e0b14aa..99866f5b0b82 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h @@ -63,6 +63,13 @@ class CLogicalReturning : public CLogical return m_pdrgpcrOutput; } + // return table's descriptor + CTableDescriptor * + Ptabdesc() const + { + return m_ptabdesc; + } + // debug print virtual IOstream &OsPrint(IOstream &) const; diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalUpdate.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalUpdate.h index 4c8aa34435b8..c70bd0fbb482 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalUpdate.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalUpdate.h @@ -131,13 +131,6 @@ class CLogicalUpdate : public CLogicalReturning return m_pcrTableOid; } - // return table's descriptor - CTableDescriptor * - Ptabdesc() const - { - return m_ptabdesc; - } - // operator specific hash function virtual ULONG HashValue() const; From d021717b2240da687b7bdb07467d79aef0cb1d80 Mon Sep 17 00:00:00 2001 From: kotb Date: Wed, 26 Mar 2025 09:43:36 +0300 Subject: [PATCH 50/74] hash value and matches to base class --- .../gpopt/operators/CLogicalReturning.h | 6 ++++ .../libgpopt/src/operators/CLogicalDelete.cpp | 13 +++---- .../libgpopt/src/operators/CLogicalInsert.cpp | 12 +++---- .../src/operators/CLogicalReturning.cpp | 36 +++++++++++++++++++ .../libgpopt/src/operators/CLogicalUpdate.cpp | 13 +++---- 5 files changed, 56 insertions(+), 24 deletions(-) diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h index 99866f5b0b82..48ce56b57298 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h @@ -70,6 +70,12 @@ class CLogicalReturning : public CLogical return m_ptabdesc; } + // operator specific hash function + virtual ULONG HashValue() const; + + // match function + virtual BOOL MatchesReturning(CLogicalReturning *popReturning) const; + // debug print virtual IOstream &OsPrint(IOstream &) const; diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp index acd3d66882ac..1c3dbc34f4b6 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp @@ -135,12 +135,11 @@ CLogicalDelete::Matches(COperator *pop) const CLogicalDelete *popDelete = CLogicalDelete::PopConvert(pop); - return m_pcrCtid == popDelete->PcrCtid() && + return CLogicalReturning::MatchesReturning(popDelete) && + m_pcrCtid == popDelete->PcrCtid() && m_pcrSegmentId == popDelete->PcrSegmentId() && m_pcrTableOid == popDelete->PcrTableOid() && - m_ptabdesc->MDId()->Equals(popDelete->Ptabdesc()->MDId()) && - m_pdrgpcr->Equals(popDelete->Pdrgpcr()) && - m_pdrgpcrOutput->Equals(popDelete->PdrgpcrOutput()); + m_pdrgpcr->Equals(popDelete->Pdrgpcr()); } //--------------------------------------------------------------------------- @@ -154,11 +153,9 @@ CLogicalDelete::Matches(COperator *pop) const ULONG CLogicalDelete::HashValue() const { - ULONG ulHash = gpos::CombineHashes(COperator::HashValue(), - m_ptabdesc->MDId()->HashValue()); + ULONG ulHash = CLogicalReturning::HashValue(); + ulHash = gpos::CombineHashes(ulHash, CUtils::UlHashColArray(m_pdrgpcr)); - ulHash = - gpos::CombineHashes(ulHash, CUtils::UlHashColArray(m_pdrgpcrOutput)); ulHash = gpos::CombineHashes(ulHash, gpos::HashPtr(m_pcrCtid)); ulHash = gpos::CombineHashes(ulHash, gpos::HashPtr(m_pcrSegmentId)); diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp index d46fe6cfcd14..aa17f1ef47ad 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp @@ -117,9 +117,8 @@ CLogicalInsert::Matches(COperator *pop) const CLogicalInsert *popInsert = CLogicalInsert::PopConvert(pop); - return m_ptabdesc->MDId()->Equals(popInsert->Ptabdesc()->MDId()) && - m_pdrgpcrSource->Equals(popInsert->PdrgpcrSource()) && - m_pdrgpcrOutput->Equals(popInsert->PdrgpcrOutput()); + return CLogicalReturning::MatchesReturning(popInsert) && + m_pdrgpcrSource->Equals(popInsert->PdrgpcrSource()); } //--------------------------------------------------------------------------- @@ -133,14 +132,11 @@ CLogicalInsert::Matches(COperator *pop) const ULONG CLogicalInsert::HashValue() const { - ULONG ulHash = gpos::CombineHashes(COperator::HashValue(), - m_ptabdesc->MDId()->HashValue()); + ULONG ulHash = CLogicalReturning::HashValue(); + ulHash = gpos::CombineHashes(ulHash, CUtils::UlHashColArray(m_pdrgpcrSource)); - ulHash = - gpos::CombineHashes(ulHash, CUtils::UlHashColArray(m_pdrgpcrOutput)); - return ulHash; } diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp index b4e5b00ab1e4..9cf8703bdc27 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp @@ -75,6 +75,42 @@ CLogicalReturning::~CLogicalReturning() CRefCount::SafeRelease(m_pdrgpcrOutput); } +//--------------------------------------------------------------------------- +// @function: +// CLogicalReturning::Matches +// +// @doc: +// Match function +// +//--------------------------------------------------------------------------- +BOOL +CLogicalReturning::MatchesReturning(CLogicalReturning *popReturning) const +{ + return m_ptabdesc->MDId()->Equals(popReturning->Ptabdesc()->MDId()) && + m_pdrgpcrOutput->Equals(popReturning->PdrgpcrOutput()); +} + +//--------------------------------------------------------------------------- +// @function: +// CLogicalReturning::HashValue +// +// @doc: +// Hash function +// +//--------------------------------------------------------------------------- +ULONG +CLogicalReturning::HashValue() const +{ + ULONG ulHash = gpos::CombineHashes(COperator::HashValue(), + m_ptabdesc->MDId()->HashValue()); + + ulHash = + gpos::CombineHashes(ulHash, CUtils::UlHashColArray(m_pdrgpcrOutput)); + + return ulHash; +} + + //--------------------------------------------------------------------------- // @function: // CLogicalReturning::OsPrint diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp index 825831584b8f..b3866f4703e8 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp @@ -158,14 +158,13 @@ CLogicalUpdate::Matches(COperator *pop) const CLogicalUpdate *popUpdate = CLogicalUpdate::PopConvert(pop); - return m_pcrCtid == popUpdate->PcrCtid() && + return CLogicalReturning::MatchesReturning(popUpdate) && + m_pcrCtid == popUpdate->PcrCtid() && m_pcrSegmentId == popUpdate->PcrSegmentId() && m_pcrTupleOid == popUpdate->PcrTupleOid() && m_pcrTableOid == popUpdate->PcrTableOid() && - m_ptabdesc->MDId()->Equals(popUpdate->Ptabdesc()->MDId()) && m_pdrgpcrDelete->Equals(popUpdate->PdrgpcrDelete()) && - m_pdrgpcrInsert->Equals(popUpdate->PdrgpcrInsert()) && - m_pdrgpcrOutput->Equals(popUpdate->PdrgpcrOutput()); + m_pdrgpcrInsert->Equals(popUpdate->PdrgpcrInsert()); } //--------------------------------------------------------------------------- @@ -179,14 +178,12 @@ CLogicalUpdate::Matches(COperator *pop) const ULONG CLogicalUpdate::HashValue() const { - ULONG ulHash = gpos::CombineHashes(COperator::HashValue(), - m_ptabdesc->MDId()->HashValue()); + ULONG ulHash = CLogicalReturning::HashValue(); + ulHash = gpos::CombineHashes(ulHash, CUtils::UlHashColArray(m_pdrgpcrDelete)); ulHash = gpos::CombineHashes(ulHash, CUtils::UlHashColArray(m_pdrgpcrInsert)); - ulHash = - gpos::CombineHashes(ulHash, CUtils::UlHashColArray(m_pdrgpcrOutput)); ulHash = gpos::CombineHashes(ulHash, gpos::HashPtr(m_pcrCtid)); ulHash = gpos::CombineHashes(ulHash, gpos::HashPtr(m_pcrSegmentId)); From 73df536e00123b836f5e4d09b33be4dad13e9c76 Mon Sep 17 00:00:00 2001 From: kotb Date: Wed, 26 Mar 2025 09:46:33 +0300 Subject: [PATCH 51/74] forgot CLogicalDML --- .../libgpopt/include/gpopt/operators/CLogicalDML.h | 7 ------- .../gporca/libgpopt/src/operators/CLogicalDML.cpp | 13 +++++-------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDML.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDML.h index e8a528091c34..234fd3f4991d 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDML.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDML.h @@ -148,13 +148,6 @@ class CLogicalDML : public CLogicalReturning return m_pcrSegmentId; } - // return table's descriptor - CTableDescriptor * - Ptabdesc() const - { - return m_ptabdesc; - } - // tuple oid column CColRef * PcrTupleOid() const diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp index d05241e4e315..d08de4b604b5 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp @@ -134,14 +134,13 @@ CLogicalDML::Matches(COperator *pop) const CLogicalDML *popDML = CLogicalDML::PopConvert(pop); - return m_pcrAction == popDML->PcrAction() && + return CLogicalReturning::MatchesReturning(popDML) && + m_pcrAction == popDML->PcrAction() && m_pcrTableOid == popDML->PcrTableOid() && m_pcrCtid == popDML->PcrCtid() && m_pcrSegmentId == popDML->PcrSegmentId() && m_pcrTupleOid == popDML->PcrTupleOid() && - m_ptabdesc->MDId()->Equals(popDML->Ptabdesc()->MDId()) && - m_pdrgpcrSource->Equals(popDML->PdrgpcrSource()) && - m_pdrgpcrOutput->Equals(popDML->PdrgpcrOutput()); + m_pdrgpcrSource->Equals(popDML->PdrgpcrSource()); } //--------------------------------------------------------------------------- @@ -155,13 +154,11 @@ CLogicalDML::Matches(COperator *pop) const ULONG CLogicalDML::HashValue() const { - ULONG ulHash = gpos::CombineHashes(COperator::HashValue(), - m_ptabdesc->MDId()->HashValue()); + ULONG ulHash = CLogicalReturning::HashValue(); + ulHash = gpos::CombineHashes(ulHash, gpos::HashPtr(m_pcrAction)); ulHash = gpos::CombineHashes(ulHash, CUtils::UlHashColArray(m_pdrgpcrSource)); - ulHash = - gpos::CombineHashes(ulHash, CUtils::UlHashColArray(m_pdrgpcrOutput)); ulHash = gpos::CombineHashes(ulHash, gpos::HashPtr(m_pcrTableOid)); if (EdmlDelete == m_edmlop || EdmlUpdate == m_edmlop) From f8369e1d03aa9f638853acb042ab28c2a666f887 Mon Sep 17 00:00:00 2001 From: kotb Date: Wed, 26 Mar 2025 09:50:15 +0300 Subject: [PATCH 52/74] deriveketcollection to base class --- .../include/gpopt/operators/CLogicalDML.h | 4 ---- .../include/gpopt/operators/CLogicalDelete.h | 4 ---- .../include/gpopt/operators/CLogicalInsert.h | 4 ---- .../gpopt/operators/CLogicalReturning.h | 4 ++++ .../include/gpopt/operators/CLogicalUpdate.h | 4 ---- .../libgpopt/src/operators/CLogicalDML.cpp | 18 ------------------ .../libgpopt/src/operators/CLogicalDelete.cpp | 18 ------------------ .../libgpopt/src/operators/CLogicalInsert.cpp | 18 ------------------ .../src/operators/CLogicalReturning.cpp | 17 +++++++++++++++++ .../libgpopt/src/operators/CLogicalUpdate.cpp | 18 ------------------ 10 files changed, 21 insertions(+), 88 deletions(-) diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDML.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDML.h index 234fd3f4991d..df3b3e2ce679 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDML.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDML.h @@ -214,10 +214,6 @@ class CLogicalDML : public CLogicalReturning // candidate set of xforms virtual CXformSet *PxfsCandidates(CMemoryPool *mp) const; - // derive key collections - virtual CKeyCollection *DeriveKeyCollection( - CMemoryPool *mp, CExpressionHandle &exprhdl) const; - // derive statistics virtual IStatistics *PstatsDerive(CMemoryPool *mp, CExpressionHandle &exprhdl, diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h index 54c7f897d740..4e5b6fa93073 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalDelete.h @@ -173,10 +173,6 @@ class CLogicalDelete : public CLogicalReturning // candidate set of xforms virtual CXformSet *PxfsCandidates(CMemoryPool *mp) const; - // derive key collections - virtual CKeyCollection *DeriveKeyCollection( - CMemoryPool *mp, CExpressionHandle &exprhdl) const; - // derive statistics virtual IStatistics *PstatsDerive(CMemoryPool *mp, CExpressionHandle &exprhdl, diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalInsert.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalInsert.h index 092e1f437ee6..43a5c3db7075 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalInsert.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalInsert.h @@ -140,10 +140,6 @@ class CLogicalInsert : public CLogicalReturning // candidate set of xforms virtual CXformSet *PxfsCandidates(CMemoryPool *mp) const; - // derive key collections - virtual CKeyCollection *DeriveKeyCollection( - CMemoryPool *mp, CExpressionHandle &exprhdl) const; - // derive statistics virtual IStatistics *PstatsDerive(CMemoryPool *mp, CExpressionHandle &exprhdl, diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h index 48ce56b57298..fbaaf422a535 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h @@ -76,6 +76,10 @@ class CLogicalReturning : public CLogical // match function virtual BOOL MatchesReturning(CLogicalReturning *popReturning) const; + // derive key collections + virtual CKeyCollection *DeriveKeyCollection( + CMemoryPool *mp, CExpressionHandle &exprhdl) const; + // debug print virtual IOstream &OsPrint(IOstream &) const; diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalUpdate.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalUpdate.h index c70bd0fbb482..b2953ad7531e 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalUpdate.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalUpdate.h @@ -195,10 +195,6 @@ class CLogicalUpdate : public CLogicalReturning // candidate set of xforms virtual CXformSet *PxfsCandidates(CMemoryPool *mp) const; - // derive key collections - virtual CKeyCollection *DeriveKeyCollection( - CMemoryPool *mp, CExpressionHandle &exprhdl) const; - // derive statistics virtual IStatistics *PstatsDerive(CMemoryPool *mp, CExpressionHandle &exprhdl, diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp index d08de4b604b5..c6354ded991f 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp @@ -295,24 +295,6 @@ CLogicalDML::DerivePropertyConstraint(CMemoryPool *mp, return ppc; } -//--------------------------------------------------------------------------- -// @function: -// CLogicalDML::PkcDeriveKeys -// -// @doc: -// Derive key collection -// -//--------------------------------------------------------------------------- -CKeyCollection * -CLogicalDML::DeriveKeyCollection(CMemoryPool *mp, - CExpressionHandle & // exprhdl -) const -{ - const CBitSetArray *pdrgpbs = m_ptabdesc->PdrgpbsKeys(); - - return CLogical::PkcKeysBaseTable(mp, pdrgpbs, m_pdrgpcrOutput); -} - //--------------------------------------------------------------------------- // @function: // CLogicalDML::DeriveMaxCard diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp index 1c3dbc34f4b6..ecdd2777300e 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp @@ -231,24 +231,6 @@ CLogicalDelete::DeriveOutputColumns(CMemoryPool *mp, return pcrsOutput; } -//--------------------------------------------------------------------------- -// @function: -// CLogicalDelete::PkcDeriveKeys -// -// @doc: -// Derive key collection -// -//--------------------------------------------------------------------------- -CKeyCollection * -CLogicalDelete::DeriveKeyCollection(CMemoryPool *mp, - CExpressionHandle & // exprhdl -) const -{ - const CBitSetArray *pdrgpbs = m_ptabdesc->PdrgpbsKeys(); - - return CLogical::PkcKeysBaseTable(mp, pdrgpbs, m_pdrgpcrOutput); -} - //--------------------------------------------------------------------------- // @function: // CLogicalDelete::DeriveMaxCard diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp index aa17f1ef47ad..fc82e04f3475 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp @@ -195,24 +195,6 @@ CLogicalInsert::DeriveOutputColumns(CMemoryPool *mp, return pcrsOutput; } -//--------------------------------------------------------------------------- -// @function: -// CLogicalInsert::PkcDeriveKeys -// -// @doc: -// Derive key collection -// -//--------------------------------------------------------------------------- -CKeyCollection * -CLogicalInsert::DeriveKeyCollection(CMemoryPool *mp, - CExpressionHandle & // exprhdl -) const -{ - const CBitSetArray *pdrgpbs = m_ptabdesc->PdrgpbsKeys(); - - return CLogical::PkcKeysBaseTable(mp, pdrgpbs, m_pdrgpcrOutput); -} - //--------------------------------------------------------------------------- // @function: // CLogicalInsert::DeriveMaxCard diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp index 9cf8703bdc27..d9dbcc4a24d6 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp @@ -110,6 +110,23 @@ CLogicalReturning::HashValue() const return ulHash; } +//--------------------------------------------------------------------------- +// @function: +// CLogicalReturning::DeriveKeyCollection +// +// @doc: +// Derive key collection +// +//--------------------------------------------------------------------------- +CKeyCollection * +CLogicalReturning::DeriveKeyCollection(CMemoryPool *mp, + CExpressionHandle & // exprhdl +) const +{ + const CBitSetArray *pdrgpbs = m_ptabdesc->PdrgpbsKeys(); + + return CLogical::PkcKeysBaseTable(mp, pdrgpbs, m_pdrgpcrOutput); +} //--------------------------------------------------------------------------- // @function: diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp index b3866f4703e8..5ee3e819919d 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp @@ -277,24 +277,6 @@ CLogicalUpdate::DeriveOutputColumns(CMemoryPool *mp, return pcrsOutput; } -//--------------------------------------------------------------------------- -// @function: -// CLogicalUpdate::PkcDeriveKeys -// -// @doc: -// Derive key collection -// -//--------------------------------------------------------------------------- -CKeyCollection * -CLogicalUpdate::DeriveKeyCollection(CMemoryPool *mp, - CExpressionHandle & // exprhdl -) const -{ - const CBitSetArray *pdrgpbs = m_ptabdesc->PdrgpbsKeys(); - - return CLogical::PkcKeysBaseTable(mp, pdrgpbs, m_pdrgpcrOutput); -} - //--------------------------------------------------------------------------- // @function: // CLogicalUpdate::DeriveMaxCard From 5b348eac39677caa86e5aa55f04c07d98a0af048 Mon Sep 17 00:00:00 2001 From: kotb Date: Wed, 26 Mar 2025 09:58:36 +0300 Subject: [PATCH 53/74] add asserts for popInsert->Ptabdesc()->MDId() --- src/backend/gporca/libgpopt/src/base/CUtils.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/backend/gporca/libgpopt/src/base/CUtils.cpp b/src/backend/gporca/libgpopt/src/base/CUtils.cpp index ce231e0eabf0..7d2451989d4d 100644 --- a/src/backend/gporca/libgpopt/src/base/CUtils.cpp +++ b/src/backend/gporca/libgpopt/src/base/CUtils.cpp @@ -3289,6 +3289,9 @@ CUtils::FCTAS(COperator *pop) CLogicalInsert *popInsert = CLogicalInsert::PopConvert(pop); + GPOS_ASSERT(NULL != popInsert->Ptabdesc()); + GPOS_ASSERT(NULL != popInsert->Ptabdesc()->MDId()); + return IMDId::EmdidGPDBCtas == popInsert->Ptabdesc()->MDId()->MdidType(); } From 77e49d9d7c5a1200111d836372da8ed07851d1f6 Mon Sep 17 00:00:00 2001 From: kotb Date: Wed, 26 Mar 2025 10:06:25 +0300 Subject: [PATCH 54/74] copy columns to base class --- .../gpopt/operators/CLogicalReturning.h | 5 ++++ .../libgpopt/src/operators/CLogicalDML.cpp | 13 ++------ .../libgpopt/src/operators/CLogicalDelete.cpp | 13 ++------ .../libgpopt/src/operators/CLogicalInsert.cpp | 15 ++-------- .../src/operators/CLogicalReturning.cpp | 30 ++++++++++++++++++- .../libgpopt/src/operators/CLogicalUpdate.cpp | 13 ++------ 6 files changed, 43 insertions(+), 46 deletions(-) diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h index fbaaf422a535..ef84c5a5d355 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h @@ -76,6 +76,11 @@ class CLogicalReturning : public CLogical // match function virtual BOOL MatchesReturning(CLogicalReturning *popReturning) const; + // return a copy of output columns + virtual CColRefArray *CopyRemappedColumns(CMemoryPool *mp, + UlongToColRefMap *colref_mapping, + BOOL must_exist); + // derive key collections virtual CKeyCollection *DeriveKeyCollection( CMemoryPool *mp, CExpressionHandle &exprhdl) const; diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp index c6354ded991f..febeda6cd7bf 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalDML.cpp @@ -187,17 +187,8 @@ CLogicalDML::PopCopyWithRemappedColumns(CMemoryPool *mp, CColRefArray *colref_array = CUtils::PdrgpcrRemap(mp, m_pdrgpcrSource, colref_mapping, must_exist); - CColRefArray *pdrgpcrOutput = NULL; - if (must_exist) - { - pdrgpcrOutput = - CUtils::PdrgpcrRemapAndCreate(mp, m_pdrgpcrOutput, colref_mapping); - } - else - { - pdrgpcrOutput = CUtils::PdrgpcrRemap(mp, m_pdrgpcrOutput, - colref_mapping, must_exist); - } + CColRefArray *pdrgpcrOutput = + CLogicalReturning::CopyRemappedColumns(mp, colref_mapping, must_exist); CColRef *pcrAction = CUtils::PcrRemap(m_pcrAction, colref_mapping, must_exist); diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp index ecdd2777300e..e6fe179af29c 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalDelete.cpp @@ -180,17 +180,8 @@ CLogicalDelete::PopCopyWithRemappedColumns(CMemoryPool *mp, CColRefArray *colref_array = CUtils::PdrgpcrRemap(mp, m_pdrgpcr, colref_mapping, must_exist); - CColRefArray *pdrgpcrOutput = NULL; - if (must_exist) - { - pdrgpcrOutput = - CUtils::PdrgpcrRemapAndCreate(mp, m_pdrgpcrOutput, colref_mapping); - } - else - { - pdrgpcrOutput = CUtils::PdrgpcrRemap(mp, m_pdrgpcrOutput, - colref_mapping, must_exist); - } + CColRefArray *pdrgpcrOutput = + CLogicalReturning::CopyRemappedColumns(mp, colref_mapping, must_exist); CColRef *pcrCtid = CUtils::PcrRemap(m_pcrCtid, colref_mapping, must_exist); CColRef *pcrSegmentId = diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp index fc82e04f3475..9d145e7218f3 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalInsert.cpp @@ -133,7 +133,7 @@ ULONG CLogicalInsert::HashValue() const { ULONG ulHash = CLogicalReturning::HashValue(); - + ulHash = gpos::CombineHashes(ulHash, CUtils::UlHashColArray(m_pdrgpcrSource)); @@ -156,17 +156,8 @@ CLogicalInsert::PopCopyWithRemappedColumns(CMemoryPool *mp, CColRefArray *colref_array = CUtils::PdrgpcrRemap(mp, m_pdrgpcrSource, colref_mapping, must_exist); - CColRefArray *pdrgpcrOutput = NULL; - if (must_exist) - { - pdrgpcrOutput = - CUtils::PdrgpcrRemapAndCreate(mp, m_pdrgpcrOutput, colref_mapping); - } - else - { - pdrgpcrOutput = CUtils::PdrgpcrRemap(mp, m_pdrgpcrOutput, - colref_mapping, must_exist); - } + CColRefArray *pdrgpcrOutput = + CLogicalReturning::CopyRemappedColumns(mp, colref_mapping, must_exist); m_ptabdesc->AddRef(); CLogicalInsert *result = GPOS_NEW(mp) diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp index d9dbcc4a24d6..53c73ac48c15 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp @@ -110,6 +110,34 @@ CLogicalReturning::HashValue() const return ulHash; } +//--------------------------------------------------------------------------- +// @function: +// CLogicalReturning::CopyRemappedColumns +// +// @doc: +// return a copy of output columns +// +//--------------------------------------------------------------------------- +CColRefArray * +CLogicalReturning::CopyRemappedColumns(CMemoryPool *mp, + UlongToColRefMap *colref_mapping, + BOOL must_exist) +{ + CColRefArray *pdrgpcrOutput = NULL; + if (must_exist) + { + pdrgpcrOutput = + CUtils::PdrgpcrRemapAndCreate(mp, m_pdrgpcrOutput, colref_mapping); + } + else + { + pdrgpcrOutput = CUtils::PdrgpcrRemap(mp, m_pdrgpcrOutput, + colref_mapping, must_exist); + } + + return pdrgpcrOutput; +} + //--------------------------------------------------------------------------- // @function: // CLogicalReturning::DeriveKeyCollection @@ -120,7 +148,7 @@ CLogicalReturning::HashValue() const //--------------------------------------------------------------------------- CKeyCollection * CLogicalReturning::DeriveKeyCollection(CMemoryPool *mp, - CExpressionHandle & // exprhdl + CExpressionHandle & // exprhdl ) const { const CBitSetArray *pdrgpbs = m_ptabdesc->PdrgpbsKeys(); diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp index 5ee3e819919d..9bb877c94557 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalUpdate.cpp @@ -210,17 +210,8 @@ CLogicalUpdate::PopCopyWithRemappedColumns(CMemoryPool *mp, CColRefArray *pdrgpcrInsert = CUtils::PdrgpcrRemap(mp, m_pdrgpcrInsert, colref_mapping, must_exist); - CColRefArray *pdrgpcrOutput = NULL; - if (must_exist) - { - pdrgpcrOutput = - CUtils::PdrgpcrRemapAndCreate(mp, m_pdrgpcrOutput, colref_mapping); - } - else - { - pdrgpcrOutput = CUtils::PdrgpcrRemap(mp, m_pdrgpcrOutput, - colref_mapping, must_exist); - } + CColRefArray *pdrgpcrOutput = + CLogicalReturning::CopyRemappedColumns(mp, colref_mapping, must_exist); CColRef *pcrCtid = CUtils::PcrRemap(m_pcrCtid, colref_mapping, must_exist); CColRef *pcrSegmentId = From f214e4a13fc4d796eb729f0a7160f4b4b0906f8e Mon Sep 17 00:00:00 2001 From: kotb Date: Thu, 27 Mar 2025 04:40:52 +0300 Subject: [PATCH 55/74] calc arity on place --- src/backend/gporca/libgpopt/src/base/CUtils.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/backend/gporca/libgpopt/src/base/CUtils.cpp b/src/backend/gporca/libgpopt/src/base/CUtils.cpp index 7d2451989d4d..60bb8922177d 100644 --- a/src/backend/gporca/libgpopt/src/base/CUtils.cpp +++ b/src/backend/gporca/libgpopt/src/base/CUtils.cpp @@ -3316,8 +3316,7 @@ CUtils::FHasLogicalDML(CMemoryPool *mp, CExpression *pexpr) return true; } - const ULONG arity = pexprCurrent->Arity(); - for (ULONG ul = 0; ul < arity; ++ul) + for (ULONG ul = 0; ul < pexprCurrent->Arity(); ++ul) { exprsToCheck->Append((*pexprCurrent)[ul]); } From 4410cc3173ce9beb8458d8525cceb4e08baf6e36 Mon Sep 17 00:00:00 2001 From: kotb Date: Thu, 27 Mar 2025 04:45:44 +0300 Subject: [PATCH 56/74] calc size in place --- src/backend/gporca/libgpopt/src/base/CQueryContext.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp b/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp index 3c9a6885a22f..cffe56cbe0ce 100644 --- a/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp +++ b/src/backend/gporca/libgpopt/src/base/CQueryContext.cpp @@ -246,8 +246,7 @@ CQueryContext::PqcGenerate(CMemoryPool *mp, CExpression *pexpr, // also check all required CTEs CExpressionArray *pdrgpexpr = poptctxt->Pcteinfo()->PdrgPexpr(mp); - const ULONG size = pdrgpexpr->Size(); - for (ULONG ul = 0; ul < size; ul++) + for (ULONG ul = 0; ul < pdrgpexpr->Size(); ul++) { CExpression *pCteExpr = (*pdrgpexpr)[ul]; if (CUtils::FHasLogicalDML(mp, pCteExpr)) From 5a7cbf98f04ba1d78f69c8b84ae2435f447ce39d Mon Sep 17 00:00:00 2001 From: kotb Date: Thu, 27 Mar 2025 04:58:10 +0300 Subject: [PATCH 57/74] nodeDML braces --- src/backend/executor/nodeDML.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/backend/executor/nodeDML.c b/src/backend/executor/nodeDML.c index ea8ff83383eb..5008245f91f7 100644 --- a/src/backend/executor/nodeDML.c +++ b/src/backend/executor/nodeDML.c @@ -46,9 +46,7 @@ RemapProjection(ProjectionInfo *projInfo, AttrMap *map) int numSimpleVars = projInfo->pi_numSimpleVars; for (int i = 0; i < numSimpleVars;++i) - { varNumbers[i] = attrMap(map, varNumbers[i]); - } if (projInfo->pi_lastInnerVar > 0) projInfo->pi_lastInnerVar = attrMap(map, projInfo->pi_lastInnerVar); From e2d94e8abf4954f81abbbe170c99d254babacf9f Mon Sep 17 00:00:00 2001 From: kotb Date: Thu, 27 Mar 2025 04:58:36 +0300 Subject: [PATCH 58/74] nodeDML braces --- src/backend/executor/nodeDML.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/backend/executor/nodeDML.c b/src/backend/executor/nodeDML.c index 5008245f91f7..50f2f036e441 100644 --- a/src/backend/executor/nodeDML.c +++ b/src/backend/executor/nodeDML.c @@ -446,9 +446,7 @@ ExecEndDML(DMLState *node) ExecFreeExprContext(&node->ps); if (node->ps.ps_ResultTupleSlot != NULL) - { ExecClearTuple(node->ps.ps_ResultTupleSlot); - } ExecClearTuple(node->cleanedUpSlot); ExecEndNode(outerPlanState(node)); EndPlanStateGpmonPkt(&node->ps); From 96a4a36c73ed938c2f496e1e57d3618da0b21afa Mon Sep 17 00:00:00 2001 From: kotb Date: Thu, 27 Mar 2025 05:08:31 +0300 Subject: [PATCH 59/74] common FTriggersExist logic in FTriggersExistInner --- .../include/gpopt/xforms/CXformUtils.h | 18 +++-- .../libgpopt/src/xforms/CXformUtils.cpp | 79 ++++++++++--------- 2 files changed, 52 insertions(+), 45 deletions(-) diff --git a/src/backend/gporca/libgpopt/include/gpopt/xforms/CXformUtils.h b/src/backend/gporca/libgpopt/include/gpopt/xforms/CXformUtils.h index f417f5d2d8aa..ddf9adddc9db 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/xforms/CXformUtils.h +++ b/src/backend/gporca/libgpopt/include/gpopt/xforms/CXformUtils.h @@ -126,12 +126,12 @@ class CXformUtils CMemoryPool *mp, const IMDIndex *pmdindex, CTableDescriptor *ptabdesc, ULONG ulOriginOpId, CName *pname, CColRefArray *pdrgpcrOutput); - typedef CExpression *(PRewrittenIndexPath)(CMemoryPool *mp, - CExpression *pexprIndexCond, - CExpression *pexprResidualCond, - const IMDIndex *pmdindex, - CTableDescriptor *ptabdesc, - COperator *popLogical); + typedef CExpression *(PRewrittenIndexPath) (CMemoryPool *mp, + CExpression *pexprIndexCond, + CExpression *pexprResidualCond, + const IMDIndex *pmdindex, + CTableDescriptor *ptabdesc, + COperator *popLogical); // private copy ctor CXformUtils(const CXformUtils &); @@ -351,6 +351,12 @@ class CXformUtils // comparator used in sorting arrays of project elements based on the column id of the first entry static INT ICmpPrjElemsArr(const void *pvFst, const void *pvSnd); + // private warehouse for checking triggers on the + // given table that match the given DML operation + static BOOL FTriggersExistInner(CLogicalDML::EDMLOperator edmlop, + CTableDescriptor *ptabdesc, + BOOL shouldCheck, BOOL fBefore); + public: // helper function for implementation xforms on binary operators // with predicates (e.g. joins) diff --git a/src/backend/gporca/libgpopt/src/xforms/CXformUtils.cpp b/src/backend/gporca/libgpopt/src/xforms/CXformUtils.cpp index 7a0d6ff5cef9..40de80e9fa6e 100644 --- a/src/backend/gporca/libgpopt/src/xforms/CXformUtils.cpp +++ b/src/backend/gporca/libgpopt/src/xforms/CXformUtils.cpp @@ -1385,27 +1385,7 @@ BOOL CXformUtils::FTriggersExist(CLogicalDML::EDMLOperator edmlop, CTableDescriptor *ptabdesc, BOOL fBefore) { - CMDAccessor *md_accessor = COptCtxt::PoctxtFromTLS()->Pmda(); - const IMDRelation *pmdrel = md_accessor->RetrieveRel(ptabdesc->MDId()); - const ULONG ulTriggers = pmdrel->TriggerCount(); - - for (ULONG ul = 0; ul < ulTriggers; ul++) - { - const IMDTrigger *pmdtrigger = - md_accessor->RetrieveTrigger(pmdrel->TriggerMDidAt(ul)); - if (!pmdtrigger->IsEnabled() || !pmdtrigger->ExecutesOnRowLevel() || - !FTriggerApplies(edmlop, pmdtrigger)) - { - continue; - } - - if (pmdtrigger->IsBefore() == fBefore) - { - return true; - } - } - - return false; + return FTriggersExistInner(edmlop, ptabdesc, true, fBefore); } //--------------------------------------------------------------------------- @@ -1421,24 +1401,7 @@ BOOL CXformUtils::FTriggersExist(CLogicalDML::EDMLOperator edmlop, CTableDescriptor *ptabdesc) { - CMDAccessor *md_accessor = COptCtxt::PoctxtFromTLS()->Pmda(); - const IMDRelation *pmdrel = md_accessor->RetrieveRel(ptabdesc->MDId()); - const ULONG ulTriggers = pmdrel->TriggerCount(); - - for (ULONG ul = 0; ul < ulTriggers; ul++) - { - const IMDTrigger *pmdtrigger = - md_accessor->RetrieveTrigger(pmdrel->TriggerMDidAt(ul)); - if (!pmdtrigger->IsEnabled() || !pmdtrigger->ExecutesOnRowLevel() || - !FTriggerApplies(edmlop, pmdtrigger)) - { - continue; - } - - return true; - } - - return false; + return FTriggersExistInner(edmlop, ptabdesc, false, false); } //--------------------------------------------------------------------------- @@ -4521,6 +4484,44 @@ CXformUtils::ICmpPrjElemsArr(const void *pvFst, const void *pvSnd) } +//--------------------------------------------------------------------------- +// @function: +// CXformUtils::FTriggersExistInner +// +// @doc: +// Private warehouse for checking triggers on the +// given table that match the given DML operation +// +//--------------------------------------------------------------------------- +BOOL +CXformUtils::FTriggersExistInner(CLogicalDML::EDMLOperator edmlop, + CTableDescriptor *ptabdesc, BOOL shouldCheck, + BOOL fBefore) +{ + CMDAccessor *md_accessor = COptCtxt::PoctxtFromTLS()->Pmda(); + const IMDRelation *pmdrel = md_accessor->RetrieveRel(ptabdesc->MDId()); + const ULONG ulTriggers = pmdrel->TriggerCount(); + + for (ULONG ul = 0; ul < ulTriggers; ul++) + { + const IMDTrigger *pmdtrigger = + md_accessor->RetrieveTrigger(pmdrel->TriggerMDidAt(ul)); + if (!pmdtrigger->IsEnabled() || !pmdtrigger->ExecutesOnRowLevel() || + !FTriggerApplies(edmlop, pmdtrigger)) + { + continue; + } + + if (shouldCheck && pmdtrigger->IsBefore() == fBefore) + { + return true; + } + } + + return false; +} + + //--------------------------------------------------------------------------- // @function: // CXformUtils::PdrgpdrgpexprSortedPrjElemsArray From 1b60ad5bb514a20ad0a757a604c1e73c37c7c881 Mon Sep 17 00:00:00 2001 From: kotb Date: Sun, 30 Mar 2025 22:44:56 +0300 Subject: [PATCH 60/74] dont check logical dml that used columns are subset of input columns --- src/backend/gporca/libgpopt/src/operators/CNormalizer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/backend/gporca/libgpopt/src/operators/CNormalizer.cpp b/src/backend/gporca/libgpopt/src/operators/CNormalizer.cpp index 41bc99a79898..385fe3b2afa2 100644 --- a/src/backend/gporca/libgpopt/src/operators/CNormalizer.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CNormalizer.cpp @@ -1499,7 +1499,8 @@ CNormalizer::FLocalColsSubsetOfInputCols(CMemoryPool *mp, CExpression *pexpr) BOOL fValid = true; if (pexpr->Pop()->FLogical()) { - if (0 == exprhdl.UlNonScalarChildren()) + if (0 == exprhdl.UlNonScalarChildren() || + CUtils::FLogicalDML(pexpr->Pop())) { return true; } From 71279d773a043dfc6ca6140d49d3aeb9d02af2f7 Mon Sep 17 00:00:00 2001 From: kotb Date: Mon, 31 Mar 2025 00:35:17 +0300 Subject: [PATCH 61/74] typo --- src/backend/executor/nodeDML.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/executor/nodeDML.c b/src/backend/executor/nodeDML.c index 50f2f036e441..3ba59ffabafd 100644 --- a/src/backend/executor/nodeDML.c +++ b/src/backend/executor/nodeDML.c @@ -114,7 +114,7 @@ ExecDML(DMLState *node) /* remove 'junk' columns from tuple */ node->cleanedUpSlot = ExecFilterJunk(node->junkfilter, projectedSlot); - /* restore returning result tuple and taregt list*/ + /* restore returning result tuple and target list*/ node->ps.ps_ResultTupleSlot = returningResultTuple; plannode->plan.targetlist = returningTargetList; From 6e4c6d6acc45278ad62e204fa1b6a2fc42ac13c7 Mon Sep 17 00:00:00 2001 From: kotb Date: Mon, 31 Mar 2025 00:36:20 +0300 Subject: [PATCH 62/74] linter --- .../libgpopt/include/gpopt/xforms/CXformUtils.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/backend/gporca/libgpopt/include/gpopt/xforms/CXformUtils.h b/src/backend/gporca/libgpopt/include/gpopt/xforms/CXformUtils.h index ddf9adddc9db..7493d84475e7 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/xforms/CXformUtils.h +++ b/src/backend/gporca/libgpopt/include/gpopt/xforms/CXformUtils.h @@ -126,12 +126,12 @@ class CXformUtils CMemoryPool *mp, const IMDIndex *pmdindex, CTableDescriptor *ptabdesc, ULONG ulOriginOpId, CName *pname, CColRefArray *pdrgpcrOutput); - typedef CExpression *(PRewrittenIndexPath) (CMemoryPool *mp, - CExpression *pexprIndexCond, - CExpression *pexprResidualCond, - const IMDIndex *pmdindex, - CTableDescriptor *ptabdesc, - COperator *popLogical); + typedef CExpression *(PRewrittenIndexPath)(CMemoryPool *mp, + CExpression *pexprIndexCond, + CExpression *pexprResidualCond, + const IMDIndex *pmdindex, + CTableDescriptor *ptabdesc, + COperator *popLogical); // private copy ctor CXformUtils(const CXformUtils &); From 389d0f65b04623908f4bc151f2971d54ad34e34c Mon Sep 17 00:00:00 2001 From: kotb Date: Tue, 1 Apr 2025 00:46:20 +0300 Subject: [PATCH 63/74] copyright header --- .../libgpopt/include/gpopt/operators/CLogicalReturning.h | 3 +-- .../gporca/libgpopt/src/operators/CLogicalReturning.cpp | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h index ef84c5a5d355..bf9b879d8db1 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CLogicalReturning.h @@ -1,6 +1,5 @@ //--------------------------------------------------------------------------- -// Greenplum Database -// Copyright (C) 2012 EMC Corp. +// Copyright (c) 2025 Greengage Community // // @filename: // CLogicalReturning.h diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp index 53c73ac48c15..a043325f47c1 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp @@ -1,6 +1,5 @@ //--------------------------------------------------------------------------- -// Greenplum Database -// Copyright (C) 2013 EMC Corp. +// Copyright (c) 2025 Greengage Community // // @filename: // CLogicalReturning.cpp From c8631c0231d5360b55b4ce993c597f4854c7df5e Mon Sep 17 00:00:00 2001 From: kotb Date: Fri, 2 May 2025 12:53:11 +0300 Subject: [PATCH 64/74] fix subplans: add intermediate Result node if subplan-join's child node doesn't return enougn columns problem occurs in case DML returns modified columns with replicated distribution and columns from subplan, which selects data from other table Subplan inside ORCA is planned as NLJoin On Expr2DXL stage subplan is pushed to projlist of nearest Result node above join node, join node itself is not needed so it is not added to DXL tree Problem is that GatherMotion is added above DML with replicated distribution to return data to qdir But this motion is under nearest Result node so when subplan is executed, its data has replicated distribution and there is no other motion to gather it This commit adds intermediate Result node right before motion, after join, in case when join requires more columns than child node can derive This will cause subplan to execute where is was meant to be executed while planning in ORCA --- .../src/translate/CTranslatorExprToDXL.cpp | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp b/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp index 602ba11e24a7..25e1ff747d5e 100644 --- a/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp +++ b/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp @@ -4554,6 +4554,43 @@ CTranslatorExprToDXL::PdxlnMotion(CExpression *pexprMotion, CTranslatorExprToDXLUtils::PdxlnProjListFromChildProjList( m_mp, m_pcf, m_phmcrdxln, pdxlnProjListChild); + // load unhandled subplans required by child to motion them too + CDXLNode *pdxlnPrLstSplan = NULL; + CColRefSetIter reqColRefIter(*pexprMotion->Prpp()->PcrsRequired()); + while (reqColRefIter.Advance()) + { + CColRef *colref = reqColRefIter.Pcr(); + CDXLNode *dxlnode = m_phmcrdxln->Find(colref); + + if (NULL != dxlnode && EdxlopScalarSubPlan == dxlnode->GetOperator()->GetDXLOperator()) + { + if (pdxlnPrLstSplan == NULL) + { + // make a copy of motion's proj list + pdxlnPrLstSplan = + CTranslatorExprToDXLUtils::PdxlnProjListFromChildProjList( + m_mp, m_pcf, m_phmcrdxln, pdxlnProjListChild); + } + + CDXLNode *pdxlnPrElSplan = CTranslatorExprToDXLUtils::PdxlnProjElem( + m_mp, m_phmcrdxln, colref); + pdxlnPrLstSplan->AddChild(pdxlnPrElSplan); + + // also add new proj elem referencing created subplan to motion's proj list + CDXLNode *pdxlnPrEl = CTranslatorExprToDXLUtils::PdxlnProjElem( + m_mp, m_phmcrdxln, colref); + proj_list_dxlnode->AddChild(pdxlnPrEl); + } + } + + // if there are any leftover subplans wrap them in extra Result node + if (pdxlnPrLstSplan != NULL) + { + child_dxlnode = PdxlnResult( + CTranslatorExprToDXLUtils::PdxlpropCopy(m_mp, child_dxlnode), + pdxlnPrLstSplan, child_dxlnode); + } + // set input and output segment information motion->SetSegmentInfo(GetInputSegIdsArray(pexprMotion), GetOutputSegIdsArray(pexprMotion)); From 2bd417d9e38d799253ff08bd4dcd75ceea3599a3 Mon Sep 17 00:00:00 2001 From: kotb Date: Fri, 2 May 2025 22:40:53 +0300 Subject: [PATCH 65/74] linter --- .../gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp b/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp index 25e1ff747d5e..79bd59ec6f1a 100644 --- a/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp +++ b/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp @@ -4562,7 +4562,8 @@ CTranslatorExprToDXL::PdxlnMotion(CExpression *pexprMotion, CColRef *colref = reqColRefIter.Pcr(); CDXLNode *dxlnode = m_phmcrdxln->Find(colref); - if (NULL != dxlnode && EdxlopScalarSubPlan == dxlnode->GetOperator()->GetDXLOperator()) + if (NULL != dxlnode && + EdxlopScalarSubPlan == dxlnode->GetOperator()->GetDXLOperator()) { if (pdxlnPrLstSplan == NULL) { From 876a969f366b4699e6e113f55d4ad663f20d5f75 Mon Sep 17 00:00:00 2001 From: kotb Date: Fri, 2 May 2025 22:42:05 +0300 Subject: [PATCH 66/74] fix logical error in triggers --- src/backend/gporca/libgpopt/src/xforms/CXformUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/gporca/libgpopt/src/xforms/CXformUtils.cpp b/src/backend/gporca/libgpopt/src/xforms/CXformUtils.cpp index 40de80e9fa6e..1c45d5d43687 100644 --- a/src/backend/gporca/libgpopt/src/xforms/CXformUtils.cpp +++ b/src/backend/gporca/libgpopt/src/xforms/CXformUtils.cpp @@ -4512,7 +4512,7 @@ CXformUtils::FTriggersExistInner(CLogicalDML::EDMLOperator edmlop, continue; } - if (shouldCheck && pmdtrigger->IsBefore() == fBefore) + if (!shouldCheck || pmdtrigger->IsBefore() == fBefore) { return true; } From 2e3dbf8a72a01350b4a5dde36c12d26171de274e Mon Sep 17 00:00:00 2001 From: kotb Date: Fri, 2 May 2025 23:31:10 +0300 Subject: [PATCH 67/74] add test DML on partitioned table with RETURNING subquery with cte --- src/test/regress/expected/returning_gp.out | 28 ++++++++++++++++ .../expected/returning_gp_optimizer.out | 32 +++++++++++++++++++ src/test/regress/sql/returning_gp.sql | 10 ++++++ 3 files changed, 70 insertions(+) diff --git a/src/test/regress/expected/returning_gp.out b/src/test/regress/expected/returning_gp.out index c347ebd7de86..7c8d7c8a7a36 100644 --- a/src/test/regress/expected/returning_gp.out +++ b/src/test/regress/expected/returning_gp.out @@ -92,6 +92,34 @@ select * from returning_parttab; 2 | 19 | multi2 3 (11 rows) +-- Test DML on partitioned table with RETURNING subquery with cte +explain (costs off) +with cte as ( + select distkey from returning_parttab limit 1 +) insert into returning_parttab values (1, 5, 'test') returning (select * from cte); + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + -> Insert on returning_parttab + InitPlan 1 (returns $0) (slice3) + -> Limit + -> Gather Motion 3:1 (slice1; segments: 3) + -> Limit + -> Append + -> Seq Scan on returning_parttab_1_prt_1 + -> Seq Scan on returning_parttab_1_prt_newpart + -> Result + Optimizer: Postgres query optimizer +(11 rows) + +with cte as ( + select distkey from returning_parttab limit 1 +) insert into returning_parttab values (1, 5, 'test') returning (select * from cte); + distkey +--------- + 2 +(1 row) + -- -- Test UPDATE RETURNING with a split update, i.e. an update of the distribution -- key. diff --git a/src/test/regress/expected/returning_gp_optimizer.out b/src/test/regress/expected/returning_gp_optimizer.out index dae0fd2cd690..10446f914456 100644 --- a/src/test/regress/expected/returning_gp_optimizer.out +++ b/src/test/regress/expected/returning_gp_optimizer.out @@ -96,6 +96,38 @@ select * from returning_parttab; 2 | 19 | multi2 3 (11 rows) +-- Test DML on partitioned table with RETURNING subquery with cte +explain (costs off) +with cte as ( + select distkey from returning_parttab limit 1 +) insert into returning_parttab values (1, 5, 'test') returning (select * from cte); +INFO: GPORCA failed to produce a plan, falling back to planner +DETAIL: No plan has been computed for required properties + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + -> Insert on returning_parttab + InitPlan 1 (returns $0) (slice3) + -> Limit + -> Gather Motion 3:1 (slice1; segments: 3) + -> Limit + -> Append + -> Seq Scan on returning_parttab_1_prt_1 + -> Seq Scan on returning_parttab_1_prt_newpart + -> Result + Optimizer: Postgres query optimizer +(11 rows) + +with cte as ( + select distkey from returning_parttab limit 1 +) insert into returning_parttab values (1, 5, 'test') returning (select * from cte); +INFO: GPORCA failed to produce a plan, falling back to planner +DETAIL: No plan has been computed for required properties + distkey +--------- + 2 +(1 row) + -- -- Test UPDATE RETURNING with a split update, i.e. an update of the distribution -- key. diff --git a/src/test/regress/sql/returning_gp.sql b/src/test/regress/sql/returning_gp.sql index 0e101f2d22c6..54ca86399d22 100644 --- a/src/test/regress/sql/returning_gp.sql +++ b/src/test/regress/sql/returning_gp.sql @@ -43,6 +43,16 @@ delete from returning_parttab where partkey = 14 returning *; -- Check table contents, to be sure that all the commands did what they claimed. select * from returning_parttab; +-- Test DML on partitioned table with RETURNING subquery with cte +explain (costs off) +with cte as ( + select distkey from returning_parttab limit 1 +) insert into returning_parttab values (1, 5, 'test') returning (select * from cte); + +with cte as ( + select distkey from returning_parttab limit 1 +) insert into returning_parttab values (1, 5, 'test') returning (select * from cte); + -- -- Test UPDATE RETURNING with a split update, i.e. an update of the distribution -- key. From 7a6b1d3e9515eb3fc4dae4b7d4d9a8adcdabd763 Mon Sep 17 00:00:00 2001 From: kotb Date: Mon, 5 May 2025 23:00:16 +0300 Subject: [PATCH 68/74] fix regress: add sort in test query --- src/test/regress/expected/returning_gp.out | 17 ++++++++++------- .../regress/expected/returning_gp_optimizer.out | 17 ++++++++++------- src/test/regress/sql/returning_gp.sql | 4 ++-- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/test/regress/expected/returning_gp.out b/src/test/regress/expected/returning_gp.out index 7c8d7c8a7a36..2359a67c02c1 100644 --- a/src/test/regress/expected/returning_gp.out +++ b/src/test/regress/expected/returning_gp.out @@ -95,7 +95,7 @@ select * from returning_parttab; -- Test DML on partitioned table with RETURNING subquery with cte explain (costs off) with cte as ( - select distkey from returning_parttab limit 1 + select distkey from returning_parttab order by distkey limit 1 ) insert into returning_parttab values (1, 5, 'test') returning (select * from cte); QUERY PLAN ----------------------------------------------------------------------------------- @@ -104,20 +104,23 @@ with cte as ( InitPlan 1 (returns $0) (slice3) -> Limit -> Gather Motion 3:1 (slice1; segments: 3) + Merge Key: returning_parttab_1_prt_1.distkey -> Limit - -> Append - -> Seq Scan on returning_parttab_1_prt_1 - -> Seq Scan on returning_parttab_1_prt_newpart + -> Sort + Sort Key: returning_parttab_1_prt_1.distkey + -> Append + -> Seq Scan on returning_parttab_1_prt_1 + -> Seq Scan on returning_parttab_1_prt_newpart -> Result Optimizer: Postgres query optimizer -(11 rows) +(14 rows) with cte as ( - select distkey from returning_parttab limit 1 + select distkey from returning_parttab order by distkey limit 1 ) insert into returning_parttab values (1, 5, 'test') returning (select * from cte); distkey --------- - 2 + 1 (1 row) -- diff --git a/src/test/regress/expected/returning_gp_optimizer.out b/src/test/regress/expected/returning_gp_optimizer.out index 10446f914456..c9f8d5680d0a 100644 --- a/src/test/regress/expected/returning_gp_optimizer.out +++ b/src/test/regress/expected/returning_gp_optimizer.out @@ -99,7 +99,7 @@ select * from returning_parttab; -- Test DML on partitioned table with RETURNING subquery with cte explain (costs off) with cte as ( - select distkey from returning_parttab limit 1 + select distkey from returning_parttab order by distkey limit 1 ) insert into returning_parttab values (1, 5, 'test') returning (select * from cte); INFO: GPORCA failed to produce a plan, falling back to planner DETAIL: No plan has been computed for required properties @@ -110,22 +110,25 @@ DETAIL: No plan has been computed for required properties InitPlan 1 (returns $0) (slice3) -> Limit -> Gather Motion 3:1 (slice1; segments: 3) + Merge Key: returning_parttab_1_prt_1.distkey -> Limit - -> Append - -> Seq Scan on returning_parttab_1_prt_1 - -> Seq Scan on returning_parttab_1_prt_newpart + -> Sort + Sort Key: returning_parttab_1_prt_1.distkey + -> Append + -> Seq Scan on returning_parttab_1_prt_1 + -> Seq Scan on returning_parttab_1_prt_newpart -> Result Optimizer: Postgres query optimizer -(11 rows) +(14 rows) with cte as ( - select distkey from returning_parttab limit 1 + select distkey from returning_parttab order by distkey limit 1 ) insert into returning_parttab values (1, 5, 'test') returning (select * from cte); INFO: GPORCA failed to produce a plan, falling back to planner DETAIL: No plan has been computed for required properties distkey --------- - 2 + 1 (1 row) -- diff --git a/src/test/regress/sql/returning_gp.sql b/src/test/regress/sql/returning_gp.sql index 54ca86399d22..3397ea2c5a4b 100644 --- a/src/test/regress/sql/returning_gp.sql +++ b/src/test/regress/sql/returning_gp.sql @@ -46,11 +46,11 @@ select * from returning_parttab; -- Test DML on partitioned table with RETURNING subquery with cte explain (costs off) with cte as ( - select distkey from returning_parttab limit 1 + select distkey from returning_parttab order by distkey limit 1 ) insert into returning_parttab values (1, 5, 'test') returning (select * from cte); with cte as ( - select distkey from returning_parttab limit 1 + select distkey from returning_parttab order by distkey limit 1 ) insert into returning_parttab values (1, 5, 'test') returning (select * from cte); -- From c561a789ec403ffac414c0e3a8128d512a954e3e Mon Sep 17 00:00:00 2001 From: kotb Date: Tue, 20 May 2025 14:57:42 +0300 Subject: [PATCH 69/74] review fixes --- src/backend/executor/nodeDML.c | 4 ++-- src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp | 2 +- src/backend/gporca/libgpopt/src/operators/CPhysicalDML.cpp | 4 ++-- src/backend/nodes/copyfuncs.c | 2 +- src/backend/nodes/outfuncs.c | 2 +- src/backend/nodes/readfast.c | 2 +- src/include/nodes/plannodes.h | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/backend/executor/nodeDML.c b/src/backend/executor/nodeDML.c index 3ba59ffabafd..fcb5f2a973de 100644 --- a/src/backend/executor/nodeDML.c +++ b/src/backend/executor/nodeDML.c @@ -78,7 +78,7 @@ ExecDML(DMLState *node) /* Set target list for projection */ List *returningTargetList = plannode->plan.targetlist; - plannode->plan.targetlist = plannode->projTargetList; + plannode->plan.targetlist = plannode->childTargetList; TupleTableSlot *slot = ExecProcNode(outerNode); TupleTableSlot *resultSlot = NULL; @@ -286,7 +286,7 @@ ExecInitDML(DML *node, EState *estate, int eflags) /* set target list with projection and save returning target list */ List *returningTargetList = node->plan.targetlist; - node->plan.targetlist = node->projTargetList; + node->plan.targetlist = node->childTargetList; ExecInitResultTupleSlot(estate, &dmlstate->ps); diff --git a/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp b/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp index 46ac5f0bd9aa..d9059c3eb6ba 100644 --- a/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp +++ b/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp @@ -4264,7 +4264,7 @@ CTranslatorDXLToPlStmt::TranslateDXLDml( GPOS_ASSERT(0 != dml->actionColIdx); // save targetlist for projection of results from outer nodes - dml->projTargetList = dml_target_list; + dml->childTargetList = dml_target_list; plan->lefttree = child_plan; plan->nMotionNodes = child_plan->nMotionNodes; diff --git a/src/backend/gporca/libgpopt/src/operators/CPhysicalDML.cpp b/src/backend/gporca/libgpopt/src/operators/CPhysicalDML.cpp index 28425b0390ac..ea5bd2617a5e 100644 --- a/src/backend/gporca/libgpopt/src/operators/CPhysicalDML.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CPhysicalDML.cpp @@ -401,13 +401,13 @@ CPhysicalDML::FProvidesReqdCols(CExpressionHandle &exprhdl, ULONG // ulOptReq ) const { + GPOS_ASSERT(NULL != pcrsRequired); + if (m_isCTAS) { return FUnaryProvidesReqdCols(exprhdl, pcrsRequired); } - GPOS_ASSERT(NULL != pcrsRequired); - CColRefSet *pcrs = GPOS_NEW(m_mp) CColRefSet(m_mp); pcrs->Include(m_pdrgpcrOutput); diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 8eb40b8c2f8f..8b738615871c 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -1339,7 +1339,7 @@ _copyDML(const DML *from) COPY_SCALAR_FIELD(tupleoidColIdx); COPY_SCALAR_FIELD(tableoidColIdx); COPY_SCALAR_FIELD(canSetTag); - COPY_NODE_FIELD(projTargetList); + COPY_NODE_FIELD(childTargetList); return newnode; } diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 023210377f12..46ed584f3414 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -1219,7 +1219,7 @@ _outDML(StringInfo str, const DML *node) WRITE_INT_FIELD(tupleoidColIdx); WRITE_INT_FIELD(tableoidColIdx); WRITE_BOOL_FIELD(canSetTag); - WRITE_NODE_FIELD(projTargetList); + WRITE_NODE_FIELD(childTargetList); _outPlanInfo(str, (Plan *) node); } diff --git a/src/backend/nodes/readfast.c b/src/backend/nodes/readfast.c index 5584e29b41c7..d5127d933180 100644 --- a/src/backend/nodes/readfast.c +++ b/src/backend/nodes/readfast.c @@ -2240,7 +2240,7 @@ _readDML(void) READ_INT_FIELD(tupleoidColIdx); READ_INT_FIELD(tableoidColIdx); READ_BOOL_FIELD(canSetTag); - READ_NODE_FIELD(projTargetList); + READ_NODE_FIELD(childTargetList); readPlanInfo((Plan *)local_node); diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 3bc58c801c24..108d1598c1e1 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -1330,7 +1330,7 @@ typedef struct DML AttrNumber tupleoidColIdx; /* index of tuple oid column into the target list */ AttrNumber tableoidColIdx; /* index of table oid column into the target list */ bool canSetTag; /* calculate processed tuples */ - List *projTargetList; /* target list for projection of outer node */ + List *childTargetList;/* target list for projection of child node */ } DML; /* From 4a4b234fa69e774007fb2facc63dfd88289722f2 Mon Sep 17 00:00:00 2001 From: kotb Date: Fri, 23 May 2025 00:01:52 +0300 Subject: [PATCH 70/74] change field name to targetListProj --- src/backend/executor/nodeDML.c | 4 ++-- src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp | 2 +- src/backend/nodes/copyfuncs.c | 2 +- src/backend/nodes/outfuncs.c | 2 +- src/backend/nodes/readfast.c | 2 +- src/include/nodes/plannodes.h | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/backend/executor/nodeDML.c b/src/backend/executor/nodeDML.c index fcb5f2a973de..a4f721eaecdc 100644 --- a/src/backend/executor/nodeDML.c +++ b/src/backend/executor/nodeDML.c @@ -78,7 +78,7 @@ ExecDML(DMLState *node) /* Set target list for projection */ List *returningTargetList = plannode->plan.targetlist; - plannode->plan.targetlist = plannode->childTargetList; + plannode->plan.targetlist = plannode->targetListProj; TupleTableSlot *slot = ExecProcNode(outerNode); TupleTableSlot *resultSlot = NULL; @@ -286,7 +286,7 @@ ExecInitDML(DML *node, EState *estate, int eflags) /* set target list with projection and save returning target list */ List *returningTargetList = node->plan.targetlist; - node->plan.targetlist = node->childTargetList; + node->plan.targetlist = node->targetListProj; ExecInitResultTupleSlot(estate, &dmlstate->ps); diff --git a/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp b/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp index d9059c3eb6ba..ae1f51404d51 100644 --- a/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp +++ b/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp @@ -4264,7 +4264,7 @@ CTranslatorDXLToPlStmt::TranslateDXLDml( GPOS_ASSERT(0 != dml->actionColIdx); // save targetlist for projection of results from outer nodes - dml->childTargetList = dml_target_list; + dml->targetListProj = dml_target_list; plan->lefttree = child_plan; plan->nMotionNodes = child_plan->nMotionNodes; diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 8b738615871c..3e1db5a14bf1 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -1339,7 +1339,7 @@ _copyDML(const DML *from) COPY_SCALAR_FIELD(tupleoidColIdx); COPY_SCALAR_FIELD(tableoidColIdx); COPY_SCALAR_FIELD(canSetTag); - COPY_NODE_FIELD(childTargetList); + COPY_NODE_FIELD(targetListProj); return newnode; } diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 46ed584f3414..bdb52de16146 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -1219,7 +1219,7 @@ _outDML(StringInfo str, const DML *node) WRITE_INT_FIELD(tupleoidColIdx); WRITE_INT_FIELD(tableoidColIdx); WRITE_BOOL_FIELD(canSetTag); - WRITE_NODE_FIELD(childTargetList); + WRITE_NODE_FIELD(targetListProj); _outPlanInfo(str, (Plan *) node); } diff --git a/src/backend/nodes/readfast.c b/src/backend/nodes/readfast.c index d5127d933180..c89f2efb7e47 100644 --- a/src/backend/nodes/readfast.c +++ b/src/backend/nodes/readfast.c @@ -2240,7 +2240,7 @@ _readDML(void) READ_INT_FIELD(tupleoidColIdx); READ_INT_FIELD(tableoidColIdx); READ_BOOL_FIELD(canSetTag); - READ_NODE_FIELD(childTargetList); + READ_NODE_FIELD(targetListProj); readPlanInfo((Plan *)local_node); diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 108d1598c1e1..933720126a33 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -1330,7 +1330,7 @@ typedef struct DML AttrNumber tupleoidColIdx; /* index of tuple oid column into the target list */ AttrNumber tableoidColIdx; /* index of table oid column into the target list */ bool canSetTag; /* calculate processed tuples */ - List *childTargetList;/* target list for projection of child node */ + List *targetListProj; /* projection of target list of child node */ } DML; /* From 27bdace55d52dcb4922956ed4598cf10e7326409 Mon Sep 17 00:00:00 2001 From: kotb Date: Fri, 23 May 2025 00:03:18 +0300 Subject: [PATCH 71/74] reformulate test dedscription --- src/test/regress/expected/with_clause.out | 2 +- src/test/regress/expected/with_clause_optimizer.out | 2 +- src/test/regress/sql/with_clause.sql | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/regress/expected/with_clause.out b/src/test/regress/expected/with_clause.out index cccc0c411349..b75531a79e78 100644 --- a/src/test/regress/expected/with_clause.out +++ b/src/test/regress/expected/with_clause.out @@ -2417,7 +2417,7 @@ create table t_new as (with cte as (delete from with_dml where i > 0 returning *) select * from cte); ERROR: cannot create plan with several writing gangs --- Test order by system column returned from modifying CTE on hash distributed table +-- Test usage of system columns returned from DML operations explain (costs off) with cte as ( insert into with_dml select i, i * 100 from generate_series(1,5) i diff --git a/src/test/regress/expected/with_clause_optimizer.out b/src/test/regress/expected/with_clause_optimizer.out index 8d18299cb6e2..c278ab93d77c 100644 --- a/src/test/regress/expected/with_clause_optimizer.out +++ b/src/test/regress/expected/with_clause_optimizer.out @@ -2531,7 +2531,7 @@ create table t_new as (with cte as (delete from with_dml where i > 0 returning *) select * from cte); ERROR: cannot create plan with several writing gangs --- Test order by system column returned from modifying CTE on hash distributed table +-- Test usage of system columns returned from DML operations explain (costs off) with cte as ( insert into with_dml select i, i * 100 from generate_series(1,5) i diff --git a/src/test/regress/sql/with_clause.sql b/src/test/regress/sql/with_clause.sql index 0ae157db7433..d87ad44a52f1 100644 --- a/src/test/regress/sql/with_clause.sql +++ b/src/test/regress/sql/with_clause.sql @@ -521,7 +521,7 @@ create table t_new as (with cte as (delete from with_dml where i > 0 returning *) select * from cte); --- Test order by system column returned from modifying CTE on hash distributed table +-- Test usage of system columns returned from DML operations explain (costs off) with cte as ( insert into with_dml select i, i * 100 from generate_series(1,5) i From be1706451311ac97e14d61c5b1959d926b576fab Mon Sep 17 00:00:00 2001 From: kotb Date: Fri, 23 May 2025 00:04:46 +0300 Subject: [PATCH 72/74] fix comment CLogicalDML in CLogicalReturning --- .../gporca/libgpopt/src/operators/CLogicalReturning.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp index a043325f47c1..357b8a766e2a 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp @@ -23,7 +23,7 @@ CLogicalReturning::CLogicalReturning(CMemoryPool *mp) //--------------------------------------------------------------------------- // @function: -// CLogicalDML::CLogicalDML +// CLogicalReturning::CLogicalReturning // // @doc: // Ctor @@ -43,7 +43,7 @@ CLogicalReturning::CLogicalReturning(CMemoryPool *mp, //--------------------------------------------------------------------------- // @function: -// CLogicalDML::CLogicalDML +// CCLogicalReturning::CLogicalReturning // // @doc: // Ctor From 5605ada6fe9671b262cc49be4b0db1dec54788c0 Mon Sep 17 00:00:00 2001 From: kotb Date: Fri, 23 May 2025 00:05:38 +0300 Subject: [PATCH 73/74] fix odd assignment --- src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp index 357b8a766e2a..847e62a3a3f1 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalReturning.cpp @@ -31,7 +31,7 @@ CLogicalReturning::CLogicalReturning(CMemoryPool *mp) //--------------------------------------------------------------------------- CLogicalReturning::CLogicalReturning(CMemoryPool *mp, CTableDescriptor *ptabdesc) - : CLogical(mp), m_ptabdesc(ptabdesc), m_pdrgpcrOutput(NULL) + : CLogical(mp), m_ptabdesc(ptabdesc) { GPOS_ASSERT(NULL != ptabdesc); From d105736bbda0e86fe498127fbd6a95470f79cb7a Mon Sep 17 00:00:00 2001 From: kotb Date: Fri, 23 May 2025 00:07:20 +0300 Subject: [PATCH 74/74] shorten Squelch function in nodeDML --- src/backend/executor/nodeDML.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/backend/executor/nodeDML.c b/src/backend/executor/nodeDML.c index a4f721eaecdc..fb5f76b5c766 100644 --- a/src/backend/executor/nodeDML.c +++ b/src/backend/executor/nodeDML.c @@ -461,14 +461,7 @@ ExecSquelchDML(DMLState *node) * regardless of any LIMIT's or other forms for projections which could * end up causing a squelch to happen. */ - for (;;) - { - TupleTableSlot *result; - - result = ExecDML(node); - if (!result) - break; - } + while (ExecDML(node) != NULL); } /* EOF */