This is an automated email from the ASF dual-hosted git repository. reshke pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/cloudberry.git
commit 08e0b7489ca4083b7f232ab16a9e972ff9ff0b30 Author: Hari krishna <[email protected]> AuthorDate: Thu Aug 31 14:53:07 2023 +0530 Support FIELDSELECT node from ORCA (#16265) * Support FIELDSELECT node from ORCA Currently, ORCA does not support to handle FIELDSELECT nodes. Consequently, when a query involves a FIELDSELECT node, the query fallsback to planner. Solution: In order to facilitate FieldSelect nodes within ORCA, several additions have been made. This includes introducing the ScalardxlFieldSelect operator to translate Query's fieldselect nodes to DXLscalarFieldNodes nodes, and the ScalarFieldSelect operator to accommodate fieldSelect nodes during optimization. Additionally, a parse handler (ParseHandlerScalarFieldSelect) is implemented to support the parsing of mdp files containing fieldselect nodes. --- .../gpopt/translate/CTranslatorDXLToScalar.cpp | 36 +++ .../gpopt/translate/CTranslatorQueryToDXL.cpp | 1 - .../gpopt/translate/CTranslatorScalarToDXL.cpp | 39 +++ .../gporca/data/dxl/minidump/FieldSelect.mdp | 323 +++++++++++++++++++++ .../libgpopt/include/gpopt/operators/COperator.h | 2 + .../include/gpopt/operators/CScalarFieldSelect.h | 138 +++++++++ .../include/gpopt/translate/CTranslatorDXLToExpr.h | 3 + .../include/gpopt/translate/CTranslatorExprToDXL.h | 3 + .../libgpopt/src/operators/CScalarFieldSelect.cpp | 96 ++++++ src/backend/gporca/libgpopt/src/operators/Makefile | 1 + .../src/translate/CTranslatorDXLToExpr.cpp | 33 +++ .../src/translate/CTranslatorExprToDXL.cpp | 34 +++ .../include/naucrates/dxl/operators/CDXLOperator.h | 1 + .../naucrates/dxl/operators/CDXLOperatorFactory.h | 4 + .../dxl/operators/CDXLScalarFieldSelect.h | 109 +++++++ .../naucrates/dxl/parser/CParseHandlerFactory.h | 5 + .../dxl/parser/CParseHandlerScalarFieldSelect.h | 66 +++++ .../include/naucrates/dxl/parser/parsehandlers.h | 1 + .../include/naucrates/dxl/xml/dxltokens.h | 7 + .../src/operators/CDXLOperatorFactory.cpp | 32 ++ .../src/operators/CDXLScalarFieldSelect.cpp | 205 +++++++++++++ .../gporca/libnaucrates/src/operators/Makefile | 1 + .../src/parser/CParseHandlerFactory.cpp | 11 + .../src/parser/CParseHandlerScalarFieldSelect.cpp | 129 ++++++++ .../gporca/libnaucrates/src/parser/Makefile | 1 + .../gporca/libnaucrates/src/xml/dxltokens.cpp | 8 +- src/backend/gporca/server/CMakeLists.txt | 3 + .../gpopt/translate/CTranslatorDXLToScalar.h | 3 + .../gpopt/translate/CTranslatorScalarToDXL.h | 4 + src/test/regress/expected/gporca.out | 207 +++++++++++++ src/test/regress/expected/gporca_optimizer.out | 213 +++++++++++++- ...nal_table_persistent_error_log_optimizer.source | 4 +- src/test/regress/sql/gporca.sql | 50 ++++ 33 files changed, 1759 insertions(+), 14 deletions(-) diff --git a/src/backend/gpopt/translate/CTranslatorDXLToScalar.cpp b/src/backend/gpopt/translate/CTranslatorDXLToScalar.cpp index 13f626c561..d9e002992c 100644 --- a/src/backend/gpopt/translate/CTranslatorDXLToScalar.cpp +++ b/src/backend/gpopt/translate/CTranslatorDXLToScalar.cpp @@ -56,6 +56,7 @@ extern "C" { #include "naucrates/dxl/operators/CDXLScalarCoerceToDomain.h" #include "naucrates/dxl/operators/CDXLScalarCoerceViaIO.h" #include "naucrates/dxl/operators/CDXLScalarDistinctComp.h" +#include "naucrates/dxl/operators/CDXLScalarFieldSelect.h" #include "naucrates/dxl/operators/CDXLScalarFuncExpr.h" #include "naucrates/dxl/operators/CDXLScalarIfStmt.h" #include "naucrates/dxl/operators/CDXLScalarMinMax.h" @@ -216,6 +217,10 @@ CTranslatorDXLToScalar::TranslateDXLToScalar(const CDXLNode *dxlnode, { return TranslateDXLScalarArrayRefToScalar(dxlnode, colid_var); } + case EdxlopScalarFieldSelect: + { + return TranslateDXLFieldSelectToScalar(dxlnode, colid_var); + } case EdxlopScalarDMLAction: { return TranslateDXLScalarDMLActionToScalar(dxlnode, colid_var); @@ -2123,6 +2128,37 @@ CTranslatorDXLToScalar::TranslateDXLScalarArrayRefToScalar( return (Expr *) array_ref; } +//--------------------------------------------------------------------------- +// @function: +// CTranslatorDXLToScalar::TranslateDXLFieldSelectToScalar +// +// @doc: +// Translates a DXL Scalar FieldSelect into a GPDB FieldSelect node +// +//--------------------------------------------------------------------------- +Expr * +CTranslatorDXLToScalar::TranslateDXLFieldSelectToScalar( + const CDXLNode *scalar_field_select, CMappingColIdVar *colid_var) +{ + GPOS_ASSERT(nullptr != scalar_field_select); + + CDXLScalarFieldSelect *dxlop = + CDXLScalarFieldSelect::Cast(scalar_field_select->GetOperator()); + + FieldSelect *fieldSelect = MakeNode(FieldSelect); + + fieldSelect->arg = + TranslateDXLToScalar((*scalar_field_select)[0], colid_var); + fieldSelect->fieldnum = dxlop->GetDXLFieldNumber(); + fieldSelect->resulttype = + CMDIdGPDB::CastMdid(dxlop->GetDXLFieldType())->Oid(); + fieldSelect->resulttypmod = dxlop->GetDXLTypeModifier(); + fieldSelect->resultcollid = + CMDIdGPDB::CastMdid(dxlop->GetDXLFieldCollation())->Oid(); + + return (Expr *) fieldSelect; +} + //--------------------------------------------------------------------------- // @function: // CTranslatorDXLToScalar::TranslateDXLArrayRefIndexListToScalar diff --git a/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp b/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp index 4e58884fe9..48e34a3119 100644 --- a/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp +++ b/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp @@ -295,7 +295,6 @@ CTranslatorQueryToDXL::CheckUnsupportedNodeTypes(Query *query) static const SUnsupportedFeature unsupported_features[] = { {T_RowExpr, GPOS_WSZ_LIT("ROW EXPRESSION")}, {T_RowCompareExpr, GPOS_WSZ_LIT("ROW COMPARE")}, - {T_FieldSelect, GPOS_WSZ_LIT("FIELDSELECT")}, {T_FieldStore, GPOS_WSZ_LIT("FIELDSTORE")}, {T_CoerceToDomainValue, GPOS_WSZ_LIT("COERCETODOMAINVALUE")}, {T_GroupId, GPOS_WSZ_LIT("GROUPID")}, diff --git a/src/backend/gpopt/translate/CTranslatorScalarToDXL.cpp b/src/backend/gpopt/translate/CTranslatorScalarToDXL.cpp index c934cab4e1..5a7a7f94e5 100644 --- a/src/backend/gpopt/translate/CTranslatorScalarToDXL.cpp +++ b/src/backend/gpopt/translate/CTranslatorScalarToDXL.cpp @@ -55,6 +55,7 @@ extern "C" { #include "naucrates/dxl/operators/CDXLScalarCoerceToDomain.h" #include "naucrates/dxl/operators/CDXLScalarCoerceViaIO.h" #include "naucrates/dxl/operators/CDXLScalarDistinctComp.h" +#include "naucrates/dxl/operators/CDXLScalarFieldSelect.h" #include "naucrates/dxl/operators/CDXLScalarFilter.h" #include "naucrates/dxl/operators/CDXLScalarFuncExpr.h" #include "naucrates/dxl/operators/CDXLScalarIdent.h" @@ -419,6 +420,11 @@ CTranslatorScalarToDXL::TranslateScalarToDXL( return CTranslatorScalarToDXL::TranslateSortGroupClauseToDXL( expr, var_colid_mapping); } + case T_FieldSelect: + { + return CTranslatorScalarToDXL::TranslateFieldSelectToDXL( + expr, var_colid_mapping); + } } } @@ -1299,6 +1305,39 @@ CTranslatorScalarToDXL::TranslateArrayCoerceExprToDXL( return dxlnode; } +//--------------------------------------------------------------------------- +// @function: +// CTranslatorScalarToDXL::TranslateFieldSelectToDXL +// +// @doc: +// Create a DXL node for a scalar FieldSelect from a GPDB FieldSelect +//--------------------------------------------------------------------------- +CDXLNode * +CTranslatorScalarToDXL::TranslateFieldSelectToDXL( + const Expr *expr, const CMappingVarColId *var_colid_mapping) +{ + GPOS_ASSERT(IsA(expr, FieldSelect)); + + const FieldSelect *fieldselect = (FieldSelect *) expr; + GPOS_ASSERT(nullptr != fieldselect->arg); + + CDXLNode *child_node = + TranslateScalarToDXL(fieldselect->arg, var_colid_mapping); + GPOS_ASSERT(nullptr != child_node); + + // create the DXL node holding the scalar boolean operator + CDXLNode *dxlnode = GPOS_NEW(m_mp) CDXLNode( + m_mp, GPOS_NEW(m_mp) CDXLScalarFieldSelect( + m_mp, + GPOS_NEW(m_mp) + CMDIdGPDB(IMDId::EmdidGeneral, fieldselect->resulttype), + GPOS_NEW(m_mp) + CMDIdGPDB(IMDId::EmdidGeneral, fieldselect->resultcollid), + fieldselect->resulttypmod, fieldselect->fieldnum)); + + dxlnode->AddChild(child_node); + return dxlnode; +} //--------------------------------------------------------------------------- diff --git a/src/backend/gporca/data/dxl/minidump/FieldSelect.mdp b/src/backend/gporca/data/dxl/minidump/FieldSelect.mdp new file mode 100644 index 0000000000..1edd3f9a32 --- /dev/null +++ b/src/backend/gporca/data/dxl/minidump/FieldSelect.mdp @@ -0,0 +1,323 @@ +<?xml version="1.0" encoding="UTF-8"?> +<dxl:DXLMessage xmlns:dxl="http://greenplum.com/dxl/2010/12/"> + <dxl:Comment><![CDATA[ + Objective:Orca should generate a plan when extracting a field from a composite datatype + setup: + CREATE TYPE inventory_item AS (name text, supplier_id integer, price numeric); + CREATE TABLE foo (item inventory_item, count integer); + INSERT INTO foo VALUES (ROW('fuzzy dice', 42, 1.99), 1000); + explain select (item).name from foo where (item).price > 0; + QUERY PLAN + ------------------------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=8) + -> Seq Scan on foo (cost=0.00..431.00 rows=1 width=8) + Filter: ((item).price > '0'::numeric) + Optimizer: Pivotal Optimizer (GPORCA) + ]]> + </dxl:Comment> + <dxl:Thread Id="0"> + <dxl:OptimizerConfig> + <dxl:EnumeratorConfig Id="0" PlanSamples="0" CostThreshold="0"/> + <dxl:StatisticsConfig DampingFactorFilter="0.750000" DampingFactorJoin="0.000000" DampingFactorGroupBy="0.750000" MaxStatsBuckets="100"/> + <dxl:CTEConfig CTEInliningCutoff="0"/> + <dxl:WindowOids RowNumber="3100" Rank="3101"/> + <dxl:CostModelConfig CostModelType="1" SegmentsForCosting="3"> + <dxl:CostParams> + <dxl:CostParam Name="NLJFactor" Value="1024.000000" LowerBound="1023.500000" UpperBound="1024.500000"/> + </dxl:CostParams> + </dxl:CostModelConfig> + <dxl:Hint JoinArityForAssociativityCommutativity="18" ArrayExpansionThreshold="20" JoinOrderDynamicProgThreshold="10" BroadcastThreshold="100000" EnforceConstraintsOnDML="false" PushGroupByBelowSetopThreshold="10" XformBindThreshold="0" SkewFactor="0"/> + <dxl:TraceFlags Value="101013,102001,102002,102003,102043,102074,102120,102144,102162,102163,103001,103014,103022,103026,103027,103029,103033,103038,103040,104002,104003,104004,104005,106000"/> + </dxl:OptimizerConfig> + <dxl:Metadata SystemIds="0.GPDB"> + <dxl:Type Mdid="0.16.1.0" Name="bool" IsRedistributable="true" IsHashable="true" IsMergeJoinable="true" IsComposite="false" IsTextRelated="false" IsFixedLength="true" Length="1" PassByValue="true"> + <dxl:DistrOpfamily Mdid="0.2222.1.0"/> + <dxl:LegacyDistrOpfamily Mdid="0.7124.1.0"/> + <dxl:PartOpfamily Mdid="0.424.1.0"/> + <dxl:EqualityOp Mdid="0.91.1.0"/> + <dxl:InequalityOp Mdid="0.85.1.0"/> + <dxl:LessThanOp Mdid="0.58.1.0"/> + <dxl:LessThanEqualsOp Mdid="0.1694.1.0"/> + <dxl:GreaterThanOp Mdid="0.59.1.0"/> + <dxl:GreaterThanEqualsOp Mdid="0.1695.1.0"/> + <dxl:ComparisonOp Mdid="0.1693.1.0"/> + <dxl:ArrayType Mdid="0.1000.1.0"/> + <dxl:MinAgg Mdid="0.0.0.0"/> + <dxl:MaxAgg Mdid="0.0.0.0"/> + <dxl:AvgAgg Mdid="0.0.0.0"/> + <dxl:SumAgg Mdid="0.0.0.0"/> + <dxl:CountAgg Mdid="0.2147.1.0"/> + </dxl:Type> + <dxl:Type Mdid="0.23.1.0" Name="int4" IsRedistributable="true" IsHashable="true" IsMergeJoinable="true" IsComposite="false" IsTextRelated="false" IsFixedLength="true" Length="4" PassByValue="true"> + <dxl:DistrOpfamily Mdid="0.1977.1.0"/> + <dxl:LegacyDistrOpfamily Mdid="0.7100.1.0"/> + <dxl:PartOpfamily Mdid="0.1976.1.0"/> + <dxl:EqualityOp Mdid="0.96.1.0"/> + <dxl:InequalityOp Mdid="0.518.1.0"/> + <dxl:LessThanOp Mdid="0.97.1.0"/> + <dxl:LessThanEqualsOp Mdid="0.523.1.0"/> + <dxl:GreaterThanOp Mdid="0.521.1.0"/> + <dxl:GreaterThanEqualsOp Mdid="0.525.1.0"/> + <dxl:ComparisonOp Mdid="0.351.1.0"/> + <dxl:ArrayType Mdid="0.1007.1.0"/> + <dxl:MinAgg Mdid="0.2132.1.0"/> + <dxl:MaxAgg Mdid="0.2116.1.0"/> + <dxl:AvgAgg Mdid="0.2101.1.0"/> + <dxl:SumAgg Mdid="0.2108.1.0"/> + <dxl:CountAgg Mdid="0.2147.1.0"/> + </dxl:Type> + <dxl:Type Mdid="0.25.1.0" Name="text" IsRedistributable="true" IsHashable="true" IsMergeJoinable="true" IsComposite="false" IsTextRelated="true" IsFixedLength="false" Length="-1" PassByValue="false"> + <dxl:DistrOpfamily Mdid="0.1995.1.0"/> + <dxl:LegacyDistrOpfamily Mdid="0.7105.1.0"/> + <dxl:PartOpfamily Mdid="0.1994.1.0"/> + <dxl:EqualityOp Mdid="0.98.1.0"/> + <dxl:InequalityOp Mdid="0.531.1.0"/> + <dxl:LessThanOp Mdid="0.664.1.0"/> + <dxl:LessThanEqualsOp Mdid="0.665.1.0"/> + <dxl:GreaterThanOp Mdid="0.666.1.0"/> + <dxl:GreaterThanEqualsOp Mdid="0.667.1.0"/> + <dxl:ComparisonOp Mdid="0.360.1.0"/> + <dxl:ArrayType Mdid="0.1009.1.0"/> + <dxl:MinAgg Mdid="0.2145.1.0"/> + <dxl:MaxAgg Mdid="0.2129.1.0"/> + <dxl:AvgAgg Mdid="0.0.0.0"/> + <dxl:SumAgg Mdid="0.0.0.0"/> + <dxl:CountAgg Mdid="0.2147.1.0"/> + </dxl:Type> + <dxl:Type Mdid="0.26.1.0" Name="oid" IsRedistributable="true" IsHashable="true" IsMergeJoinable="true" IsComposite="false" IsTextRelated="false" IsFixedLength="true" Length="4" PassByValue="true"> + <dxl:DistrOpfamily Mdid="0.1990.1.0"/> + <dxl:LegacyDistrOpfamily Mdid="0.7109.1.0"/> + <dxl:PartOpfamily Mdid="0.1989.1.0"/> + <dxl:EqualityOp Mdid="0.607.1.0"/> + <dxl:InequalityOp Mdid="0.608.1.0"/> + <dxl:LessThanOp Mdid="0.609.1.0"/> + <dxl:LessThanEqualsOp Mdid="0.611.1.0"/> + <dxl:GreaterThanOp Mdid="0.610.1.0"/> + <dxl:GreaterThanEqualsOp Mdid="0.612.1.0"/> + <dxl:ComparisonOp Mdid="0.356.1.0"/> + <dxl:ArrayType Mdid="0.1028.1.0"/> + <dxl:MinAgg Mdid="0.2134.1.0"/> + <dxl:MaxAgg Mdid="0.2118.1.0"/> + <dxl:AvgAgg Mdid="0.0.0.0"/> + <dxl:SumAgg Mdid="0.0.0.0"/> + <dxl:CountAgg Mdid="0.2147.1.0"/> + </dxl:Type> + <dxl:Type Mdid="0.27.1.0" Name="tid" IsRedistributable="true" IsHashable="true" IsMergeJoinable="true" IsComposite="false" IsTextRelated="false" IsFixedLength="true" Length="6" PassByValue="false"> + <dxl:DistrOpfamily Mdid="0.2227.1.0"/> + <dxl:LegacyDistrOpfamily Mdid="0.7110.1.0"/> + <dxl:PartOpfamily Mdid="0.2789.1.0"/> + <dxl:EqualityOp Mdid="0.387.1.0"/> + <dxl:InequalityOp Mdid="0.402.1.0"/> + <dxl:LessThanOp Mdid="0.2799.1.0"/> + <dxl:LessThanEqualsOp Mdid="0.2801.1.0"/> + <dxl:GreaterThanOp Mdid="0.2800.1.0"/> + <dxl:GreaterThanEqualsOp Mdid="0.2802.1.0"/> + <dxl:ComparisonOp Mdid="0.2794.1.0"/> + <dxl:ArrayType Mdid="0.1010.1.0"/> + <dxl:MinAgg Mdid="0.2798.1.0"/> + <dxl:MaxAgg Mdid="0.2797.1.0"/> + <dxl:AvgAgg Mdid="0.0.0.0"/> + <dxl:SumAgg Mdid="0.0.0.0"/> + <dxl:CountAgg Mdid="0.2147.1.0"/> + </dxl:Type> + <dxl:Type Mdid="0.29.1.0" Name="cid" IsRedistributable="true" IsHashable="true" IsMergeJoinable="false" IsComposite="false" IsTextRelated="false" IsFixedLength="true" Length="4" PassByValue="true"> + <dxl:DistrOpfamily Mdid="0.2226.1.0"/> + <dxl:EqualityOp Mdid="0.385.1.0"/> + <dxl:InequalityOp Mdid="0.0.0.0"/> + <dxl:LessThanOp Mdid="0.0.0.0"/> + <dxl:LessThanEqualsOp Mdid="0.0.0.0"/> + <dxl:GreaterThanOp Mdid="0.0.0.0"/> + <dxl:GreaterThanEqualsOp Mdid="0.0.0.0"/> + <dxl:ComparisonOp Mdid="0.0.0.0"/> + <dxl:ArrayType Mdid="0.1012.1.0"/> + <dxl:MinAgg Mdid="0.0.0.0"/> + <dxl:MaxAgg Mdid="0.0.0.0"/> + <dxl:AvgAgg Mdid="0.0.0.0"/> + <dxl:SumAgg Mdid="0.0.0.0"/> + <dxl:CountAgg Mdid="0.2147.1.0"/> + </dxl:Type> + <dxl:Type Mdid="0.28.1.0" Name="xid" IsRedistributable="true" IsHashable="true" IsMergeJoinable="false" IsComposite="false" IsTextRelated="false" IsFixedLength="true" Length="4" PassByValue="true"> + <dxl:DistrOpfamily Mdid="0.2225.1.0"/> + <dxl:EqualityOp Mdid="0.352.1.0"/> + <dxl:InequalityOp Mdid="0.3315.1.0"/> + <dxl:LessThanOp Mdid="0.0.0.0"/> + <dxl:LessThanEqualsOp Mdid="0.0.0.0"/> + <dxl:GreaterThanOp Mdid="0.0.0.0"/> + <dxl:GreaterThanEqualsOp Mdid="0.0.0.0"/> + <dxl:ComparisonOp Mdid="0.0.0.0"/> + <dxl:ArrayType Mdid="0.1011.1.0"/> + <dxl:MinAgg Mdid="0.0.0.0"/> + <dxl:MaxAgg Mdid="0.0.0.0"/> + <dxl:AvgAgg Mdid="0.0.0.0"/> + <dxl:SumAgg Mdid="0.0.0.0"/> + <dxl:CountAgg Mdid="0.2147.1.0"/> + </dxl:Type> + <dxl:Type Mdid="0.17310.1.0" Name="inventory_item" IsRedistributable="false" IsHashable="false" IsMergeJoinable="true" IsComposite="true" BaseRelationMdid="6.17308.1.0" IsTextRelated="false" IsFixedLength="false" Length="-1" PassByValue="false"> + <dxl:PartOpfamily Mdid="0.2994.1.0"/> + <dxl:EqualityOp Mdid="0.2988.1.0"/> + <dxl:InequalityOp Mdid="0.2989.1.0"/> + <dxl:LessThanOp Mdid="0.2990.1.0"/> + <dxl:LessThanEqualsOp Mdid="0.2992.1.0"/> + <dxl:GreaterThanOp Mdid="0.2991.1.0"/> + <dxl:GreaterThanEqualsOp Mdid="0.2993.1.0"/> + <dxl:ComparisonOp Mdid="0.2987.1.0"/> + <dxl:ArrayType Mdid="0.17309.1.0"/> + <dxl:MinAgg Mdid="0.0.0.0"/> + <dxl:MaxAgg Mdid="0.0.0.0"/> + <dxl:AvgAgg Mdid="0.0.0.0"/> + <dxl:SumAgg Mdid="0.0.0.0"/> + <dxl:CountAgg Mdid="0.2147.1.0"/> + </dxl:Type> + <dxl:Type Mdid="0.1700.1.0" Name="numeric" IsRedistributable="true" IsHashable="true" IsMergeJoinable="true" IsComposite="false" IsTextRelated="false" IsFixedLength="false" Length="-1" PassByValue="false"> + <dxl:DistrOpfamily Mdid="0.1998.1.0"/> + <dxl:LegacyDistrOpfamily Mdid="0.7103.1.0"/> + <dxl:PartOpfamily Mdid="0.1988.1.0"/> + <dxl:EqualityOp Mdid="0.1752.1.0"/> + <dxl:InequalityOp Mdid="0.1753.1.0"/> + <dxl:LessThanOp Mdid="0.1754.1.0"/> + <dxl:LessThanEqualsOp Mdid="0.1755.1.0"/> + <dxl:GreaterThanOp Mdid="0.1756.1.0"/> + <dxl:GreaterThanEqualsOp Mdid="0.1757.1.0"/> + <dxl:ComparisonOp Mdid="0.1769.1.0"/> + <dxl:ArrayType Mdid="0.1231.1.0"/> + <dxl:MinAgg Mdid="0.2146.1.0"/> + <dxl:MaxAgg Mdid="0.2130.1.0"/> + <dxl:AvgAgg Mdid="0.2103.1.0"/> + <dxl:SumAgg Mdid="0.2114.1.0"/> + <dxl:CountAgg Mdid="0.2147.1.0"/> + </dxl:Type> + <dxl:RelationStatistics Mdid="2.17311.1.0" Name="foo" Rows="0.000000" RelPages="0" RelAllVisible="0" EmptyRelation="true"/> + <dxl:Relation Mdid="6.17311.1.0" Name="foo" IsTemporary="false" StorageType="Heap" DistributionPolicy="Hash" DistributionColumns="1" Keys="8,2"> + <dxl:Columns> + <dxl:Column Name="item" Attno="1" Mdid="0.17310.1.0" Nullable="true" ColWidth="8"/> + <dxl:Column Name="count" Attno="2" Mdid="0.23.1.0" Nullable="true" ColWidth="4"/> + <dxl:Column Name="ctid" Attno="-1" Mdid="0.27.1.0" Nullable="false" ColWidth="6"/> + <dxl:Column Name="xmin" Attno="-2" Mdid="0.28.1.0" Nullable="false" ColWidth="4"/> + <dxl:Column Name="cmin" Attno="-3" Mdid="0.29.1.0" Nullable="false" ColWidth="4"/> + <dxl:Column Name="xmax" Attno="-4" Mdid="0.28.1.0" Nullable="false" ColWidth="4"/> + <dxl:Column Name="cmax" Attno="-5" Mdid="0.29.1.0" Nullable="false" ColWidth="4"/> + <dxl:Column Name="tableoid" Attno="-6" Mdid="0.26.1.0" Nullable="false" ColWidth="4"/> + <dxl:Column Name="gp_segment_id" Attno="-7" Mdid="0.23.1.0" Nullable="false" ColWidth="4"/> + </dxl:Columns> + <dxl:IndexInfoList/> + <dxl:CheckConstraints/> + <dxl:DistrOpfamilies> + <dxl:DistrOpfamily Mdid="0.1977.1.0"/> + </dxl:DistrOpfamilies> + </dxl:Relation> + <dxl:ColumnStatistics Mdid="1.17311.1.0.1" Name="count" Width="4.000000" NullFreq="0.000000" NdvRemain="0.000000" FreqRemain="0.000000" ColStatsMissing="true"/> + <dxl:ColumnStatistics Mdid="1.17311.1.0.0" Name="item" Width="8.000000" NullFreq="0.000000" NdvRemain="0.000000" FreqRemain="0.000000" ColStatsMissing="true"/> + <dxl:RelationExtendedStatistics Mdid="10.17311.1.0" Name="foo"/> + <dxl:GPDBScalarOp Mdid="0.1756.1.0" Name=">" ComparisonType="GT" ReturnsNullOnNullInput="true" IsNDVPreserving="false"> + <dxl:LeftType Mdid="0.1700.1.0"/> + <dxl:RightType Mdid="0.1700.1.0"/> + <dxl:ResultType Mdid="0.16.1.0"/> + <dxl:OpFunc Mdid="0.1720.1.0"/> + <dxl:Commutator Mdid="0.1754.1.0"/> + <dxl:InverseOp Mdid="0.1755.1.0"/> + <dxl:Opfamilies> + <dxl:Opfamily Mdid="0.1988.1.0"/> + <dxl:Opfamily Mdid="0.4055.1.0"/> + <dxl:Opfamily Mdid="0.10013.1.0"/> + </dxl:Opfamilies> + </dxl:GPDBScalarOp> + </dxl:Metadata> + <dxl:Query> + <dxl:OutputColumns> + <dxl:Ident ColId="10" ColName="name" TypeMdid="0.25.1.0"/> + </dxl:OutputColumns> + <dxl:CTEList/> + <dxl:LogicalProject> + <dxl:ProjList> + <dxl:ProjElem ColId="10" Alias="name"> + <dxl:FIELDSELECT FieldType="0.25.1.0" FieldCollation="0.100.1.0" TypeModifier="-1" FieldNumber="1"> + <dxl:Ident ColId="1" ColName="item" TypeMdid="0.17310.1.0"/> + </dxl:FIELDSELECT> + </dxl:ProjElem> + </dxl:ProjList> + <dxl:LogicalSelect> + <dxl:Comparison ComparisonOperator=">" OperatorMdid="0.1756.1.0"> + <dxl:FIELDSELECT FieldType="0.1700.1.0" FieldCollation="0.0.0.0" TypeModifier="-1" FieldNumber="3"> + <dxl:Ident ColId="1" ColName="item" TypeMdid="0.17310.1.0"/> + </dxl:FIELDSELECT> + <dxl:ConstValue TypeMdid="0.1700.1.0" Value="AAAABgCA" DoubleValue="0.000000"/> + </dxl:Comparison> + <dxl:LogicalGet> + <dxl:TableDescriptor Mdid="6.17311.1.0" TableName="foo" LockMode="1" AclMode="2"> + <dxl:Columns> + <dxl:Column ColId="1" Attno="1" ColName="item" TypeMdid="0.17310.1.0" ColWidth="8"/> + <dxl:Column ColId="2" Attno="2" ColName="count" TypeMdid="0.23.1.0" ColWidth="4"/> + <dxl:Column ColId="3" Attno="-1" ColName="ctid" TypeMdid="0.27.1.0" ColWidth="6"/> + <dxl:Column ColId="4" Attno="-2" ColName="xmin" TypeMdid="0.28.1.0" ColWidth="4"/> + <dxl:Column ColId="5" Attno="-3" ColName="cmin" TypeMdid="0.29.1.0" ColWidth="4"/> + <dxl:Column ColId="6" Attno="-4" ColName="xmax" TypeMdid="0.28.1.0" ColWidth="4"/> + <dxl:Column ColId="7" Attno="-5" ColName="cmax" TypeMdid="0.29.1.0" ColWidth="4"/> + <dxl:Column ColId="8" Attno="-6" ColName="tableoid" TypeMdid="0.26.1.0" ColWidth="4"/> + <dxl:Column ColId="9" Attno="-7" ColName="gp_segment_id" TypeMdid="0.23.1.0" ColWidth="4"/> + </dxl:Columns> + </dxl:TableDescriptor> + </dxl:LogicalGet> + </dxl:LogicalSelect> + </dxl:LogicalProject> + </dxl:Query> + <dxl:Plan Id="0" SpaceSize="2"> + <dxl:GatherMotion InputSegments="0,1,2" OutputSegments="-1"> + <dxl:Properties> + <dxl:Cost StartupCost="0" TotalCost="431.000056" Rows="1.000000" Width="8"/> + </dxl:Properties> + <dxl:ProjList> + <dxl:ProjElem ColId="9" Alias="name"> + <dxl:Ident ColId="9" ColName="name" TypeMdid="0.25.1.0"/> + </dxl:ProjElem> + </dxl:ProjList> + <dxl:Filter/> + <dxl:SortingColumnList/> + <dxl:Result> + <dxl:Properties> + <dxl:Cost StartupCost="0" TotalCost="431.000026" Rows="1.000000" Width="8"/> + </dxl:Properties> + <dxl:ProjList> + <dxl:ProjElem ColId="9" Alias="name"> + <dxl:FIELDSELECT FieldType="0.25.1.0" FieldCollation="0.100.1.0" TypeModifier="-1" FieldNumber="1"> + <dxl:Ident ColId="0" ColName="item" TypeMdid="0.17310.1.0"/> + </dxl:FIELDSELECT> + </dxl:ProjElem> + </dxl:ProjList> + <dxl:Filter/> + <dxl:OneTimeFilter/> + <dxl:TableScan> + <dxl:Properties> + <dxl:Cost StartupCost="0" TotalCost="431.000024" Rows="1.000000" Width="8"/> + </dxl:Properties> + <dxl:ProjList> + <dxl:ProjElem ColId="0" Alias="item"> + <dxl:Ident ColId="0" ColName="item" TypeMdid="0.17310.1.0"/> + </dxl:ProjElem> + </dxl:ProjList> + <dxl:Filter> + <dxl:Comparison ComparisonOperator=">" OperatorMdid="0.1756.1.0"> + <dxl:FIELDSELECT FieldType="0.1700.1.0" FieldCollation="0.0.0.0" TypeModifier="-1" FieldNumber="3"> + <dxl:Ident ColId="0" ColName="item" TypeMdid="0.17310.1.0"/> + </dxl:FIELDSELECT> + <dxl:ConstValue TypeMdid="0.1700.1.0" Value="AAAABgCA" DoubleValue="0.000000"/> + </dxl:Comparison> + </dxl:Filter> + <dxl:TableDescriptor Mdid="6.17311.1.0" TableName="foo" LockMode="1" AclMode="2"> + <dxl:Columns> + <dxl:Column ColId="0" Attno="1" ColName="item" TypeMdid="0.17310.1.0" ColWidth="8"/> + <dxl:Column ColId="1" Attno="2" ColName="count" TypeMdid="0.23.1.0" ColWidth="4"/> + <dxl:Column ColId="2" Attno="-1" ColName="ctid" TypeMdid="0.27.1.0" ColWidth="6"/> + <dxl:Column ColId="3" Attno="-2" ColName="xmin" TypeMdid="0.28.1.0" ColWidth="4"/> + <dxl:Column ColId="4" Attno="-3" ColName="cmin" TypeMdid="0.29.1.0" ColWidth="4"/> + <dxl:Column ColId="5" Attno="-4" ColName="xmax" TypeMdid="0.28.1.0" ColWidth="4"/> + <dxl:Column ColId="6" Attno="-5" ColName="cmax" TypeMdid="0.29.1.0" ColWidth="4"/> + <dxl:Column ColId="7" Attno="-6" ColName="tableoid" TypeMdid="0.26.1.0" ColWidth="4"/> + <dxl:Column ColId="8" Attno="-7" ColName="gp_segment_id" TypeMdid="0.23.1.0" ColWidth="4"/> + </dxl:Columns> + </dxl:TableDescriptor> + </dxl:TableScan> + </dxl:Result> + </dxl:GatherMotion> + </dxl:Plan> + </dxl:Thread> +</dxl:DXLMessage> diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/COperator.h b/src/backend/gporca/libgpopt/include/gpopt/operators/COperator.h index 0ec9dd213c..51ac8ddd8a 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/COperator.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/COperator.h @@ -183,6 +183,8 @@ public: EopScalarBitmapIndexProbe, EopScalarBitmapBoolOp, + EopScalarFieldSelect, + EopPhysicalTableScan, EopPhysicalForeignScan, EopPhysicalIndexScan, diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CScalarFieldSelect.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CScalarFieldSelect.h new file mode 100644 index 0000000000..d5c7955b5f --- /dev/null +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CScalarFieldSelect.h @@ -0,0 +1,138 @@ +//--------------------------------------------------------------------------- +// Greenplum Database +// Copyright (C) 2023 VMware, Inc. or its affiliates. All Rights Reserved. +// +// @filename: +// CScalarFieldSelect.h +// +// @doc: +// Class for representing FIELDSELECT +//--------------------------------------------------------------------------- + +#ifndef GPOPT_CSCALARFIELDSELECT_H +#define GPOPT_CSCALARFIELDSELECT_H + +#include "gpos/base.h" + +#include "gpopt/operators/CScalar.h" +#include "naucrates/md/IMDId.h" + +namespace gpopt +{ +using namespace gpos; +using namespace gpmd; + +//--------------------------------------------------------------------------- +// @class: +// CScalarFieldSelect +// +// @doc: +// Class for representing scalar FieldSelect +// +//--------------------------------------------------------------------------- +class CScalarFieldSelect : public CScalar +{ +private: + // type of the field + IMDId *m_field_type; + + // collation OID of the field + IMDId *m_field_collation; + + // output typmod (usually -1) + INT m_type_modifier; + + // attribute number of field to extract + SINT m_field_number; + +public: + CScalarFieldSelect(const CScalarFieldSelect &) = delete; + + // ctor/dtor + CScalarFieldSelect(CMemoryPool *mp, IMDId *field_type, + IMDId *field_collation, INT type_modifier, + SINT field_number); + + ~CScalarFieldSelect() override; + + // ident accessors + EOperatorId + Eopid() const override + { + return EopScalarFieldSelect; + } + + // operator name + const CHAR * + SzId() const override + { + return "CScalarFieldSelect"; + } + + // operator specific hash function + ULONG HashValue() const override; + + // match function + BOOL Matches(COperator *pop) const override; + + + // mdid of the field + IMDId * + MdidType() const override + { + return m_field_type; + } + + // field collation mdid + IMDId * + FieldCollation() const + { + return m_field_collation; + } + + // output mode type + INT + TypeModifier() const override + { + return m_type_modifier; + } + + // attribute number of field + SINT + FieldNumber() const + { + return m_field_number; + } + + // conversion function + static CScalarFieldSelect * + PopConvert(COperator *pop) + { + GPOS_ASSERT(nullptr != pop); + GPOS_ASSERT(EopScalarFieldSelect == pop->Eopid()); + + return dynamic_cast<CScalarFieldSelect *>(pop); + } + + // sensitivity to order of inputs + BOOL + FInputOrderSensitive() const override + { + return true; + } + + // return a copy of the operator with remapped columns + COperator * + PopCopyWithRemappedColumns(CMemoryPool *, //mp, + UlongToColRefMap *, //colref_mapping, + BOOL //must_exist + ) override + { + return PopCopyDefault(); + } +}; +} // namespace gpopt + +#endif // !GPDB_CSCALARFIELDSELECT_H + +// EOF diff --git a/src/backend/gporca/libgpopt/include/gpopt/translate/CTranslatorDXLToExpr.h b/src/backend/gporca/libgpopt/include/gpopt/translate/CTranslatorDXLToExpr.h index f1563a5014..71b073335c 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/translate/CTranslatorDXLToExpr.h +++ b/src/backend/gporca/libgpopt/include/gpopt/translate/CTranslatorDXLToExpr.h @@ -321,6 +321,9 @@ private: CExpression *PexprSortGroupClause(const CDXLNode *pdxlnSortGroupClause); + // translate a DXL FieldSelect node into a FieldSelect expression + CExpression *PexprFieldSelect(const CDXLNode *pdxlnConst); + // translate a DXL project list node into a project list expression CExpression *PexprScalarProjList(const CDXLNode *proj_list_dxlnode); diff --git a/src/backend/gporca/libgpopt/include/gpopt/translate/CTranslatorExprToDXL.h b/src/backend/gporca/libgpopt/include/gpopt/translate/CTranslatorExprToDXL.h index 89846a91b7..2b29de28d6 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/translate/CTranslatorExprToDXL.h +++ b/src/backend/gporca/libgpopt/include/gpopt/translate/CTranslatorExprToDXL.h @@ -511,6 +511,9 @@ private: // translate an arrayref CDXLNode *PdxlnArrayRef(CExpression *pexpr); + // translate a FieldSelect expr + CDXLNode *PdxlnFieldSelect(CExpression *pexpr); + // translate an arrayref index list CDXLNode *PdxlnArrayRefIndexList(CExpression *pexpr); diff --git a/src/backend/gporca/libgpopt/src/operators/CScalarFieldSelect.cpp b/src/backend/gporca/libgpopt/src/operators/CScalarFieldSelect.cpp new file mode 100644 index 0000000000..d3fd3e1d34 --- /dev/null +++ b/src/backend/gporca/libgpopt/src/operators/CScalarFieldSelect.cpp @@ -0,0 +1,96 @@ +//--------------------------------------------------------------------------- +// Greenplum Database +// Copyright (C) 2023 VMware, Inc. or its affiliates. All Rights Reserved. +// +// @filename: +// CScalarFieldSelect.cpp +// +// @doc: +// Implementation of scalar FIELDSELECT +//--------------------------------------------------------------------------- + +#include "gpopt/operators/CScalarFieldSelect.h" + +#include "gpos/base.h" + +using namespace gpopt; +using namespace gpmd; + + +//--------------------------------------------------------------------------- +// @function: +// CScalarFieldSelect::CScalarFieldSelect +// +// @doc: +// Ctor +// +//--------------------------------------------------------------------------- +CScalarFieldSelect::CScalarFieldSelect(CMemoryPool *mp, IMDId *field_type, + IMDId *field_collation, + INT type_modifier, SINT field_number) + : CScalar(mp), + m_field_type(field_type), + m_field_collation(field_collation), + m_type_modifier(type_modifier), + m_field_number(field_number) +{ + GPOS_ASSERT(m_field_type->IsValid()); +} + +//--------------------------------------------------------------------------- +// @function: +// CScalarFieldSelect::~CScalarFieldSelect +// +// @doc: +// Dtor +// +//--------------------------------------------------------------------------- +CScalarFieldSelect::~CScalarFieldSelect() +{ + m_field_type->Release(); + m_field_collation->Release(); +} + +//--------------------------------------------------------------------------- +// @function: +// CScalarFieldSelect::HashValue +// +// @doc: +// Operator specific hash function +// +//--------------------------------------------------------------------------- +ULONG +CScalarFieldSelect::HashValue() const +{ + return gpos::CombineHashes( + COperator::HashValue(), + CombineHashes(CombineHashes(m_field_type->HashValue(), + m_field_collation->HashValue()), + gpos::HashValue<SINT>(&m_field_number))); +} + +//--------------------------------------------------------------------------- +// @function: +// CScalarFieldSelect::Matches +// +// @doc: +// Match function on operator level +// +//--------------------------------------------------------------------------- +BOOL +CScalarFieldSelect::Matches(COperator *pop) const +{ + if (pop->Eopid() != Eopid()) + { + return false; + } + CScalarFieldSelect *popFieldSelect = CScalarFieldSelect::PopConvert(pop); + + // match attribute field number and type of the field + return popFieldSelect->MdidType()->Equals(MdidType()) && + popFieldSelect->FieldCollation()->Equals(FieldCollation()) && + popFieldSelect->FieldNumber() == FieldNumber(); +} + + +// EOF diff --git a/src/backend/gporca/libgpopt/src/operators/Makefile b/src/backend/gporca/libgpopt/src/operators/Makefile index 28bf1f9e6b..97218fe075 100644 --- a/src/backend/gporca/libgpopt/src/operators/Makefile +++ b/src/backend/gporca/libgpopt/src/operators/Makefile @@ -163,6 +163,7 @@ OBJS = CExpression.o \ CScalarCoerceViaIO.o \ CScalarConst.o \ CScalarDMLAction.o \ + CScalarFieldSelect.o \ CScalarFunc.o \ CScalarIdent.o \ CScalarIf.o \ diff --git a/src/backend/gporca/libgpopt/src/translate/CTranslatorDXLToExpr.cpp b/src/backend/gporca/libgpopt/src/translate/CTranslatorDXLToExpr.cpp index 778b801f1c..347ae4227b 100644 --- a/src/backend/gporca/libgpopt/src/translate/CTranslatorDXLToExpr.cpp +++ b/src/backend/gporca/libgpopt/src/translate/CTranslatorDXLToExpr.cpp @@ -58,6 +58,7 @@ #include "gpopt/operators/CScalarCoalesce.h" #include "gpopt/operators/CScalarCoerceToDomain.h" #include "gpopt/operators/CScalarCoerceViaIO.h" +#include "gpopt/operators/CScalarFieldSelect.h" #include "gpopt/operators/CScalarIdent.h" #include "gpopt/operators/CScalarIf.h" #include "gpopt/operators/CScalarIsDistinctFrom.h" @@ -105,6 +106,7 @@ #include "naucrates/dxl/operators/CDXLScalarCoerceToDomain.h" #include "naucrates/dxl/operators/CDXLScalarCoerceViaIO.h" #include "naucrates/dxl/operators/CDXLScalarDistinctComp.h" +#include "naucrates/dxl/operators/CDXLScalarFieldSelect.h" #include "naucrates/dxl/operators/CDXLScalarFuncExpr.h" #include "naucrates/dxl/operators/CDXLScalarIdent.h" #include "naucrates/dxl/operators/CDXLScalarIfStmt.h" @@ -2660,6 +2662,8 @@ CTranslatorDXLToExpr::PexprScalar(const CDXLNode *dxlnode) return CTranslatorDXLToExpr::PexprValuesList(dxlnode); case EdxlopScalarSortGroupClause: return CTranslatorDXLToExpr::PexprSortGroupClause(dxlnode); + case EdxlopScalarFieldSelect: + return CTranslatorDXLToExpr::PexprFieldSelect(dxlnode); default: GPOS_RAISE(gpopt::ExmaGPOPT, gpopt::ExmiUnsupportedOp, dxl_op->GetOpNameStr()->GetBuffer()); @@ -3330,6 +3334,35 @@ CTranslatorDXLToExpr::PexprValuesList(const CDXLNode *dxlnode) CExpression(m_mp, popScalarValuesList, pdrgpexprChildren); } + +//--------------------------------------------------------------------------- +// @function: +// CTranslatorDXLToExpr::PexprFieldSelect +// +// @doc: +// Create a scalar FieldSelect operator expression from a DXL FieldSelect node +// +//--------------------------------------------------------------------------- +CExpression * +CTranslatorDXLToExpr::PexprFieldSelect(const CDXLNode *dxlnode) +{ + CDXLScalarFieldSelect *dxl_op = + CDXLScalarFieldSelect::Cast(dxlnode->GetOperator()); + + IMDId *field_type = dxl_op->GetDXLFieldType(); + field_type->AddRef(); + IMDId *field_collation = dxl_op->GetDXLFieldCollation(); + field_collation->AddRef(); + INT type_modifier = dxl_op->GetDXLTypeModifier(); + SINT field_number = dxl_op->GetDXLFieldNumber(); + + CScalarFieldSelect *popFieldSelect = GPOS_NEW(m_mp) CScalarFieldSelect( + m_mp, field_type, field_collation, type_modifier, field_number); + CExpressionArray *pdrgpexprChildren = PdrgpexprChildren(dxlnode); + + return GPOS_NEW(m_mp) CExpression(m_mp, popFieldSelect, pdrgpexprChildren); +} + //--------------------------------------------------------------------------- // @function: // CTranslatorDXLToExpr::PexprArrayRefIndexList diff --git a/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp b/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp index 6105af847c..0d757f0f77 100644 --- a/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp +++ b/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp @@ -80,6 +80,7 @@ #include "gpopt/operators/CScalarCoalesce.h" #include "gpopt/operators/CScalarCoerceToDomain.h" #include "gpopt/operators/CScalarCoerceViaIO.h" +#include "gpopt/operators/CScalarFieldSelect.h" #include "gpopt/operators/CScalarIdent.h" #include "gpopt/operators/CScalarIf.h" #include "gpopt/operators/CScalarIsDistinctFrom.h" @@ -145,6 +146,7 @@ #include "naucrates/dxl/operators/CDXLScalarComp.h" #include "naucrates/dxl/operators/CDXLScalarDMLAction.h" #include "naucrates/dxl/operators/CDXLScalarDistinctComp.h" +#include "naucrates/dxl/operators/CDXLScalarFieldSelect.h" #include "naucrates/dxl/operators/CDXLScalarFuncExpr.h" #include "naucrates/dxl/operators/CDXLScalarHashCondList.h" #include "naucrates/dxl/operators/CDXLScalarHashExpr.h" @@ -645,6 +647,8 @@ CTranslatorExprToDXL::PdxlnScalar(CExpression *pexpr) return CTranslatorExprToDXL::PdxlnArrayCmp(pexpr); case COperator::EopScalarArrayRef: return CTranslatorExprToDXL::PdxlnArrayRef(pexpr); + case COperator::EopScalarFieldSelect: + return CTranslatorExprToDXL::PdxlnFieldSelect(pexpr); case COperator::EopScalarArrayRefIndexList: return CTranslatorExprToDXL::PdxlnArrayRefIndexList(pexpr); case COperator::EopScalarAssertConstraintList: @@ -6548,6 +6552,36 @@ CTranslatorExprToDXL::PdxlnArrayRef(CExpression *pexpr) return pdxlnArrayref; } +//--------------------------------------------------------------------------- +// @function: +// CTranslatorExprToDXL::PdxlnFieldSelect +// +// @doc: +// Create a DXL FieldSelect node from an optimizer FieldSelect expression +// +//--------------------------------------------------------------------------- +CDXLNode * +CTranslatorExprToDXL::PdxlnFieldSelect(CExpression *pexpr) +{ + GPOS_ASSERT(nullptr != pexpr); + CScalarFieldSelect *pop = CScalarFieldSelect::PopConvert(pexpr->Pop()); + + IMDId *field_type = pop->MdidType(); + field_type->AddRef(); + IMDId *field_collation = pop->FieldCollation(); + field_collation->AddRef(); + INT type_modifier = pop->TypeModifier(); + SINT field_number = pop->FieldNumber(); + + CDXLNode *pdxlnFieldSelect = GPOS_NEW(m_mp) CDXLNode( + m_mp, + GPOS_NEW(m_mp) CDXLScalarFieldSelect(m_mp, field_type, field_collation, + type_modifier, field_number)); + TranslateScalarChildren(pexpr, pdxlnFieldSelect); + + return pdxlnFieldSelect; +} + //--------------------------------------------------------------------------- // @function: // CTranslatorExprToDXL::PdxlnArrayRefIndexList diff --git a/src/backend/gporca/libnaucrates/include/naucrates/dxl/operators/CDXLOperator.h b/src/backend/gporca/libnaucrates/include/naucrates/dxl/operators/CDXLOperator.h index f168329935..220ad08437 100644 --- a/src/backend/gporca/libnaucrates/include/naucrates/dxl/operators/CDXLOperator.h +++ b/src/backend/gporca/libnaucrates/include/naucrates/dxl/operators/CDXLOperator.h @@ -68,6 +68,7 @@ enum Edxlopid EdxlopScalarHashCondList, EdxlopScalarArray, EdxlopScalarArrayRef, + EdxlopScalarFieldSelect, EdxlopScalarArrayRefIndexList, EdxlopScalarAssertConstraintList, diff --git a/src/backend/gporca/libnaucrates/include/naucrates/dxl/operators/CDXLOperatorFactory.h b/src/backend/gporca/libnaucrates/include/naucrates/dxl/operators/CDXLOperatorFactory.h index e515c69b01..6ece3ce380 100644 --- a/src/backend/gporca/libnaucrates/include/naucrates/dxl/operators/CDXLOperatorFactory.h +++ b/src/backend/gporca/libnaucrates/include/naucrates/dxl/operators/CDXLOperatorFactory.h @@ -251,6 +251,10 @@ public: static CDXLScalar *MakeDXLArrayCoerceExpr( CDXLMemoryManager *dxl_memory_manager, const Attributes &attrs); + // create a FieldSelectExpr + static CDXLScalar *MakeDXLFieldSelect(CDXLMemoryManager *dxl_memory_manager, + const Attributes &attrs); + // create a scalar identifier operator static CDXLScalar *MakeDXLScalarIdent(CDXLMemoryManager *dxl_memory_manager, const Attributes &attrs); diff --git a/src/backend/gporca/libnaucrates/include/naucrates/dxl/operators/CDXLScalarFieldSelect.h b/src/backend/gporca/libnaucrates/include/naucrates/dxl/operators/CDXLScalarFieldSelect.h new file mode 100644 index 0000000000..cd9996f952 --- /dev/null +++ b/src/backend/gporca/libnaucrates/include/naucrates/dxl/operators/CDXLScalarFieldSelect.h @@ -0,0 +1,109 @@ +//--------------------------------------------------------------------------- +// Greenplum Database +// Copyright (C) 2023 VMware, Inc. or its affiliates. All Rights Reserved. +// +// @filename: +// CDXLScalarFieldSelect.cpp +// +// @doc: +// Implementation of DXL Scalar FIELDSELECT operator +//--------------------------------------------------------------------------- + +#ifndef GPDXL_CDXLSCALARFIELDSELECT_H +#define GPDXL_CDXLSCALARFIELDSELECT_H + +#include "gpos/base.h" + +#include "naucrates/dxl/operators/CDXLScalar.h" +#include "naucrates/md/IMDId.h" + +namespace gpdxl +{ +using namespace gpos; +using namespace gpmd; + +//--------------------------------------------------------------------------- +// @class: +// CDXLScalarAggref +// +// @doc: +// Class for representing DXL FIELDSELECT +// +//--------------------------------------------------------------------------- +class CDXLScalarFieldSelect : public CDXLScalar +{ +private: + // type of the field + IMDId *m_dxl_field_type; + + // collation OID of the field + IMDId *m_dxl_field_collation; + + // output typmod (usually -1) + INT m_dxl_type_modifier; + + // attribute number of field to extract + SINT m_dxl_field_number; + +public: + CDXLScalarFieldSelect(const CDXLScalarFieldSelect &) = delete; + + // ctor/dtor + CDXLScalarFieldSelect(CMemoryPool *mp, IMDId *field_type, + IMDId *field_collation, INT type_modifier, + SINT field_number); + + ~CDXLScalarFieldSelect() override; + + // ident accessors + Edxlopid GetDXLOperator() const override; + + // DXL operator name + const CWStringConst *GetOpNameStr() const override; + + // serialize operator in DXL format + void SerializeToDXL(CXMLSerializer *xml_serializer, + const CDXLNode *dxlnode) const override; + + // mdid of the field + IMDId *GetDXLFieldType() const; + + // collation mdid of the field + IMDId *GetDXLFieldCollation() const; + + // output type mode + INT GetDXLTypeModifier() const; + + // attribute number of the field + SINT GetDXLFieldNumber() const; + + // conversion function + static CDXLScalarFieldSelect * + Cast(CDXLOperator *dxl_op) + { + GPOS_ASSERT(nullptr != dxl_op); + GPOS_ASSERT(EdxlopScalarFieldSelect == dxl_op->GetDXLOperator()); + + return dynamic_cast<CDXLScalarFieldSelect *>(dxl_op); + } + + // does the operator return a boolean result + BOOL + HasBoolResult(CMDAccessor * //md_accessor + ) const override + { + return true; + } + +#ifdef GPOS_DEBUG + // checks whether the operator has valid structure, i.e. number and + // types of child nodes + void AssertValid(const CDXLNode *dxlnode, + BOOL validate_children) const override; +#endif // GPOS_DEBUG +}; +} // namespace gpdxl + +#endif // !GPDB_CDXLSCALARFIELDSELECT_H + +// EOF diff --git a/src/backend/gporca/libnaucrates/include/naucrates/dxl/parser/CParseHandlerFactory.h b/src/backend/gporca/libnaucrates/include/naucrates/dxl/parser/CParseHandlerFactory.h index e322008906..c90ffedf16 100644 --- a/src/backend/gporca/libnaucrates/include/naucrates/dxl/parser/CParseHandlerFactory.h +++ b/src/backend/gporca/libnaucrates/include/naucrates/dxl/parser/CParseHandlerFactory.h @@ -401,6 +401,11 @@ private: CMemoryPool *mp, CParseHandlerManager *parse_handler_mgr, CParseHandlerBase *parse_handler_root); + // construct an FieldSelect parse handler + static CParseHandlerBase *CreateScalarFieldSelectParseHandler( + CMemoryPool *mp, CParseHandlerManager *parse_handler_mgr, + CParseHandlerBase *parse_handler_root); + // construct an arrayref index list parse handler static CParseHandlerBase *CreateScArrayRefIdxListParseHandler( CMemoryPool *mp, CParseHandlerManager *parse_handler_mgr, diff --git a/src/backend/gporca/libnaucrates/include/naucrates/dxl/parser/CParseHandlerScalarFieldSelect.h b/src/backend/gporca/libnaucrates/include/naucrates/dxl/parser/CParseHandlerScalarFieldSelect.h new file mode 100644 index 0000000000..86b14d9ce9 --- /dev/null +++ b/src/backend/gporca/libnaucrates/include/naucrates/dxl/parser/CParseHandlerScalarFieldSelect.h @@ -0,0 +1,66 @@ +//--------------------------------------------------------------------------- +// Greenplum Database +// Copyright (C) 2023 VMware, Inc. or its affiliates. All Rights Reserved. +// +// @filename: +// CParseHandlerScalarFieldSelect.h +// +// @doc: +// SAX parse handler class for parsing scalar FieldSelect operator nodes +//--------------------------------------------------------------------------- + +#ifndef GPDXL_CParseHandlerScalarFieldSelect_H +#define GPDXL_CParseHandlerScalarFieldSelect_H + +#include "gpos/base.h" + +#include "naucrates/dxl/operators/CDXLScalarFieldSelect.h" +#include "naucrates/dxl/parser/CParseHandlerScalarOp.h" + +namespace gpdxl +{ +using namespace gpos; + +XERCES_CPP_NAMESPACE_USE + +//--------------------------------------------------------------------------- +// @class: +// CParseHandlerScalarFieldSelect +// +// @doc: +// Parse handler class for parsing scalar FieldSelect +// +//--------------------------------------------------------------------------- +class CParseHandlerScalarFieldSelect : public CParseHandlerScalarOp +{ +private: + // process the start of an element + void StartElement( + const XMLCh *const element_uri, // URI of element's namespace + const XMLCh *const element_local_name, // local part of element's name + const XMLCh *const element_qname, // element's qname + const Attributes &attr // element's attributes + ) override; + + // process the end of an element + void EndElement( + const XMLCh *const element_uri, // URI of element's namespace + const XMLCh *const element_local_name, // local part of element's name + const XMLCh *const element_qname // element's qname + ) override; + +public: + CParseHandlerScalarFieldSelect(const CParseHandlerScalarFieldSelect &) = + delete; + + // ctor/dtor + CParseHandlerScalarFieldSelect(CMemoryPool *mp, + CParseHandlerManager *parse_handler_mgr, + CParseHandlerBase *parse_handler_root); + ~CParseHandlerScalarFieldSelect() override = default; +}; +} // namespace gpdxl + +#endif // !GPDXL_CParseHandlerScalarFieldSelect_H + +// EOF diff --git a/src/backend/gporca/libnaucrates/include/naucrates/dxl/parser/parsehandlers.h b/src/backend/gporca/libnaucrates/include/naucrates/dxl/parser/parsehandlers.h index b53f3bce15..909bc3cae3 100644 --- a/src/backend/gporca/libnaucrates/include/naucrates/dxl/parser/parsehandlers.h +++ b/src/backend/gporca/libnaucrates/include/naucrates/dxl/parser/parsehandlers.h @@ -140,6 +140,7 @@ #include "naucrates/dxl/parser/CParseHandlerScalarConstValue.h" #include "naucrates/dxl/parser/CParseHandlerScalarDMLAction.h" #include "naucrates/dxl/parser/CParseHandlerScalarExpr.h" +#include "naucrates/dxl/parser/CParseHandlerScalarFieldSelect.h" #include "naucrates/dxl/parser/CParseHandlerScalarFuncExpr.h" #include "naucrates/dxl/parser/CParseHandlerScalarIdent.h" #include "naucrates/dxl/parser/CParseHandlerScalarIfStmt.h" diff --git a/src/backend/gporca/libnaucrates/include/naucrates/dxl/xml/dxltokens.h b/src/backend/gporca/libnaucrates/include/naucrates/dxl/xml/dxltokens.h index b7485b28d4..8812a65170 100644 --- a/src/backend/gporca/libnaucrates/include/naucrates/dxl/xml/dxltokens.h +++ b/src/backend/gporca/libnaucrates/include/naucrates/dxl/xml/dxltokens.h @@ -268,6 +268,13 @@ enum Edxltoken EdxltokenWindowrefStageRowKey, EdxltokenWindowrefWinSpecPos, + // FIELDSELECT + EdxltokenScalarFieldSelect, + EdxltokenScalarFieldSelectFieldType, + EdxltokenScalarFieldSelectFieldCollation, + EdxltokenScalarFieldSelectFieldNumber, + EdxltokenScalarFieldSelectTypeModifier, + EdxltokenValue, EdxltokenTypeId, EdxltokenTypeIds, diff --git a/src/backend/gporca/libnaucrates/src/operators/CDXLOperatorFactory.cpp b/src/backend/gporca/libnaucrates/src/operators/CDXLOperatorFactory.cpp index 22ca4ac142..e787b192ab 100644 --- a/src/backend/gporca/libnaucrates/src/operators/CDXLOperatorFactory.cpp +++ b/src/backend/gporca/libnaucrates/src/operators/CDXLOperatorFactory.cpp @@ -52,6 +52,7 @@ #include "naucrates/dxl/operators/CDXLScalarCoerceViaIO.h" #include "naucrates/dxl/operators/CDXLScalarComp.h" #include "naucrates/dxl/operators/CDXLScalarDistinctComp.h" +#include "naucrates/dxl/operators/CDXLScalarFieldSelect.h" #include "naucrates/dxl/operators/CDXLScalarFuncExpr.h" #include "naucrates/dxl/operators/CDXLScalarHashExpr.h" #include "naucrates/dxl/operators/CDXLScalarIdent.h" @@ -965,6 +966,37 @@ CDXLOperatorFactory::MakeDXLArrayCoerceExpr( (EdxlCoercionForm) coercion_form, location); } +//--------------------------------------------------------------------------- +// @function: +// CDXLOperatorFactory::MakeDXLFieldSelectExpr +// +// @doc: +// Construct a scalar FieldSelect expression +// +//--------------------------------------------------------------------------- +CDXLScalar * +CDXLOperatorFactory::MakeDXLFieldSelect(CDXLMemoryManager *dxl_memory_manager, + const Attributes &attrs) +{ + CMemoryPool *mp = dxl_memory_manager->Pmp(); + + IMDId *field_type = ExtractConvertAttrValueToMdId( + dxl_memory_manager, attrs, EdxltokenScalarFieldSelectFieldType, + EdxltokenScalarFieldSelect); + IMDId *field_collation = ExtractConvertAttrValueToMdId( + dxl_memory_manager, attrs, EdxltokenScalarFieldSelectFieldCollation, + EdxltokenScalarFieldSelect); + INT type_modifier = ExtractConvertAttrValueToInt( + dxl_memory_manager, attrs, EdxltokenScalarFieldSelectTypeModifier, + EdxltokenScalarFieldSelect); + SINT field_number = ExtractConvertAttrValueToInt( + dxl_memory_manager, attrs, EdxltokenScalarFieldSelectFieldNumber, + EdxltokenScalarFieldSelect); + + return GPOS_NEW(mp) CDXLScalarFieldSelect(mp, field_type, field_collation, + type_modifier, field_number); +} + //--------------------------------------------------------------------------- // @function: // CDXLOperatorFactory::MakeDXLConstValue diff --git a/src/backend/gporca/libnaucrates/src/operators/CDXLScalarFieldSelect.cpp b/src/backend/gporca/libnaucrates/src/operators/CDXLScalarFieldSelect.cpp new file mode 100644 index 0000000000..91dc0313db --- /dev/null +++ b/src/backend/gporca/libnaucrates/src/operators/CDXLScalarFieldSelect.cpp @@ -0,0 +1,205 @@ +//--------------------------------------------------------------------------- +// Greenplum Database +// Copyright (C) 2023 VMware, Inc. or its affiliates. All Rights Reserved. +// +// @filename: +// CDXLScalarFieldSelect.cpp +// +// @doc: +// Implementation of DXL Scalar FIELDSELECT operator +//--------------------------------------------------------------------------- + +#include "naucrates/dxl/operators/CDXLScalarFieldSelect.h" + +#include "gpopt/mdcache/CMDAccessor.h" +#include "naucrates/dxl/operators/CDXLNode.h" +#include "naucrates/dxl/xml/CXMLSerializer.h" + +using namespace gpos; +using namespace gpdxl; + +//--------------------------------------------------------------------------- +// @function: +// CDXLScalarFieldSelect::CDXLScalarFieldSelect +// +// @doc: +// Ctor +// +//--------------------------------------------------------------------------- +CDXLScalarFieldSelect::CDXLScalarFieldSelect(CMemoryPool *mp, IMDId *field_type, + IMDId *field_collation, + INT type_modifier, + SINT field_number) + : CDXLScalar(mp), + m_dxl_field_type(field_type), + m_dxl_field_collation(field_collation), + m_dxl_type_modifier(type_modifier), + m_dxl_field_number(field_number) +{ + GPOS_ASSERT(m_dxl_field_type->IsValid()); +} + +//--------------------------------------------------------------------------- +// @function: +// CDXLScalarFieldSelect::~CDXLScalarFieldSelect +// +// @doc: +// Dtor +// +//--------------------------------------------------------------------------- +CDXLScalarFieldSelect::~CDXLScalarFieldSelect() +{ + m_dxl_field_type->Release(); + m_dxl_field_collation->Release(); +} + +//--------------------------------------------------------------------------- +// @function: +// CDXLScalarFieldSelect::GetDXLOperator +// +// @doc: +// Operator type +// +//--------------------------------------------------------------------------- +Edxlopid +CDXLScalarFieldSelect::GetDXLOperator() const +{ + return EdxlopScalarFieldSelect; +} + +//--------------------------------------------------------------------------- +// @function: +// CDXLScalarFieldSelect::GetDXLFieldType +// +// @doc: +// Returns mdid of the field +// +//--------------------------------------------------------------------------- +IMDId * +CDXLScalarFieldSelect::GetDXLFieldType() const +{ + return m_dxl_field_type; +} + +//--------------------------------------------------------------------------- +// @function: +// CDXLScalarFieldSelect::GetDXLFieldCollation +// +// @doc: +// Returns collation mdid of the field +// +//--------------------------------------------------------------------------- +IMDId * +CDXLScalarFieldSelect::GetDXLFieldCollation() const +{ + return m_dxl_field_collation; +} + +//--------------------------------------------------------------------------- +// @function: +// CDXLScalarFieldSelect::GetDXLFieldTypeModifier +// +// @doc: +// Returns output type mode +// +//--------------------------------------------------------------------------- +INT +CDXLScalarFieldSelect::GetDXLTypeModifier() const +{ + return m_dxl_type_modifier; +} + +//--------------------------------------------------------------------------- +// @function: +// CDXLScalarFieldSelect::GetDXLFieldNumber() +// +// @doc: +// Returns attribute number of the field to extract +// +//--------------------------------------------------------------------------- +SINT +CDXLScalarFieldSelect::GetDXLFieldNumber() const +{ + return m_dxl_field_number; +} + +//--------------------------------------------------------------------------- +// @function: +// CDXLScalarFieldSelect::GetOpNameStr +// +// @doc: +// Operator name +// +//--------------------------------------------------------------------------- +const CWStringConst * +CDXLScalarFieldSelect::GetOpNameStr() const +{ + return CDXLTokens::GetDXLTokenStr(EdxltokenScalarFieldSelect); +} + +//--------------------------------------------------------------------------- +// @function: +// CDXLScalarFieldSelect::SerializeToDXL +// +// @doc: +// Serialize operator in DXL format +// +//--------------------------------------------------------------------------- +void +CDXLScalarFieldSelect::SerializeToDXL(CXMLSerializer *xml_serializer, + const CDXLNode *dxlnode) const +{ + const CWStringConst *element_name = GetOpNameStr(); + + xml_serializer->OpenElement( + CDXLTokens::GetDXLTokenStr(EdxltokenNamespacePrefix), element_name); + + m_dxl_field_type->Serialize( + xml_serializer, + CDXLTokens::GetDXLTokenStr(EdxltokenScalarFieldSelectFieldType)); + m_dxl_field_collation->Serialize( + xml_serializer, + CDXLTokens::GetDXLTokenStr(EdxltokenScalarFieldSelectFieldCollation)); + xml_serializer->AddAttribute( + CDXLTokens::GetDXLTokenStr(EdxltokenScalarFieldSelectTypeModifier), + m_dxl_type_modifier); + xml_serializer->AddAttribute( + CDXLTokens::GetDXLTokenStr(EdxltokenScalarFieldSelectFieldNumber), + m_dxl_field_number); + + dxlnode->SerializeChildrenToDXL(xml_serializer); + + xml_serializer->CloseElement( + CDXLTokens::GetDXLTokenStr(EdxltokenNamespacePrefix), element_name); +} + +#ifdef GPOS_DEBUG +//--------------------------------------------------------------------------- +// @function: +// CDXLScalarFieldSelect::AssertValid +// +// @doc: +// Checks whether operator node is well-structured +// +//--------------------------------------------------------------------------- +void +CDXLScalarFieldSelect::AssertValid(const CDXLNode *dxlnode, + BOOL validate_children) const +{ + const ULONG arity = dxlnode->Arity(); + for (ULONG ul = 0; ul < arity; ++ul) + { + CDXLNode *child_dxlnode = (*dxlnode)[ul]; + GPOS_ASSERT(EdxloptypeScalar == + child_dxlnode->GetOperator()->GetDXLOperatorType()); + + if (validate_children) + { + child_dxlnode->GetOperator()->AssertValid(child_dxlnode, + validate_children); + } + } +} +#endif // GPOS_DEBUG + +// EOF diff --git a/src/backend/gporca/libnaucrates/src/operators/Makefile b/src/backend/gporca/libnaucrates/src/operators/Makefile index ace5344d52..aa89bd295a 100644 --- a/src/backend/gporca/libnaucrates/src/operators/Makefile +++ b/src/backend/gporca/libnaucrates/src/operators/Makefile @@ -112,6 +112,7 @@ OBJS = CDXLColDescr.o \ CDXLScalarConstValue.o \ CDXLScalarDMLAction.o \ CDXLScalarDistinctComp.o \ + CDXLScalarFieldSelect.o \ CDXLScalarFilter.o \ CDXLScalarFuncExpr.o \ CDXLScalarHashCondList.o \ diff --git a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerFactory.cpp b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerFactory.cpp index 26cc898d01..01be8a12a5 100644 --- a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerFactory.cpp +++ b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerFactory.cpp @@ -178,6 +178,7 @@ CParseHandlerFactory::Init(CMemoryPool *mp) {EdxltokenScalarCoerceToDomain, CreateScCoerceToDomainParseHandler}, {EdxltokenScalarCoerceViaIO, CreateScCoerceViaIOParseHandler}, {EdxltokenScalarArrayCoerceExpr, CreateScArrayCoerceExprParseHandler}, + {EdxltokenScalarFieldSelect, &CreateScalarFieldSelectParseHandler}, {EdxltokenScalarHashExpr, &CreateHashExprParseHandler}, {EdxltokenScalarHashCondList, &CreateCondListParseHandler}, {EdxltokenScalarMergeCondList, &CreateCondListParseHandler}, @@ -1240,6 +1241,16 @@ CParseHandlerFactory::CreateScArrayCoerceExprParseHandler( mp, parse_handler_mgr, parse_handler_root); } +// creates a parse handler for parsing FIELDSELECT operator +CParseHandlerBase * +CParseHandlerFactory::CreateScalarFieldSelectParseHandler( + CMemoryPool *mp, CParseHandlerManager *parse_handler_mgr, + CParseHandlerBase *parse_handler_root) +{ + return GPOS_NEW(mp) CParseHandlerScalarFieldSelect(mp, parse_handler_mgr, + parse_handler_root); +} + // creates a parse handler for parsing a SubPlan. CParseHandlerBase * CParseHandlerFactory::CreateScSubPlanParseHandler( diff --git a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerScalarFieldSelect.cpp b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerScalarFieldSelect.cpp new file mode 100644 index 0000000000..8e588b2788 --- /dev/null +++ b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerScalarFieldSelect.cpp @@ -0,0 +1,129 @@ +//--------------------------------------------------------------------------- +// Greenplum Database +// Copyright (C) 2023 VMware, Inc. or its affiliates. All Rights Reserved. +// +// @filename: +// CParseHandlerScalarFieldSelect.cpp +// +// @doc: +// Implementation of the SAX parse handler class for FieldSelect +// operators +//--------------------------------------------------------------------------- + +#include "naucrates/dxl/parser/CParseHandlerScalarFieldSelect.h" + +#include "naucrates/dxl/CDXLUtils.h" +#include "naucrates/dxl/operators/CDXLOperatorFactory.h" +#include "naucrates/dxl/parser/CParseHandlerFactory.h" +#include "naucrates/dxl/parser/CParseHandlerScalarOp.h" + + +using namespace gpdxl; + + +XERCES_CPP_NAMESPACE_USE + +//--------------------------------------------------------------------------- +// @function: +// CParseHandlerScalarFieldSelect::CParseHandlerScalarFieldSelect +// +// @doc: +// Ctor +// +//--------------------------------------------------------------------------- +CParseHandlerScalarFieldSelect::CParseHandlerScalarFieldSelect( + CMemoryPool *mp, CParseHandlerManager *parse_handler_mgr, + CParseHandlerBase *parse_handler_root) + : CParseHandlerScalarOp(mp, parse_handler_mgr, parse_handler_root) +{ +} + +//--------------------------------------------------------------------------- +// @function: +// CParseHandlerScalarFieldSelect::StartElement +// +// @doc: +// Processes a Xerces start element event +// +//--------------------------------------------------------------------------- +void +CParseHandlerScalarFieldSelect::StartElement( + const XMLCh *const, // element_uri, + const XMLCh *const element_local_name, + const XMLCh *const, // element_qname + const Attributes &attrs) +{ + if (0 == XMLString::compareString( + CDXLTokens::XmlstrToken(EdxltokenScalarFieldSelect), + element_local_name)) + { + if (nullptr != m_dxl_node) + { + CWStringDynamic *str = CDXLUtils::CreateDynamicStringFromXMLChArray( + m_parse_handler_mgr->GetDXLMemoryManager(), element_local_name); + GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXLUnexpectedTag, + str->GetBuffer()); + } + + // parse and create scalar fieldselect + CDXLScalarFieldSelect *dxl_op = + (CDXLScalarFieldSelect *) CDXLOperatorFactory::MakeDXLFieldSelect( + m_parse_handler_mgr->GetDXLMemoryManager(), attrs); + + m_dxl_node = GPOS_NEW(m_mp) CDXLNode(m_mp, dxl_op); + + // parse handler for child scalar node + CParseHandlerBase *child_parse_handler = + CParseHandlerFactory::GetParseHandler( + m_mp, CDXLTokens::XmlstrToken(EdxltokenScalar), + m_parse_handler_mgr, this); + m_parse_handler_mgr->ActivateParseHandler(child_parse_handler); + + // store parse handler + this->Append(child_parse_handler); + } + else + { + CWStringDynamic *str = CDXLUtils::CreateDynamicStringFromXMLChArray( + m_parse_handler_mgr->GetDXLMemoryManager(), element_local_name); + GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXLUnexpectedTag, + str->GetBuffer()); + } +} + +//--------------------------------------------------------------------------- +// @function: +// CParseHandlerScalarFieldSelect::EndElement +// +// @doc: +// Processes a Xerces end element event +// +//--------------------------------------------------------------------------- +void +CParseHandlerScalarFieldSelect::EndElement( + const XMLCh *const, // element_uri, + const XMLCh *const element_local_name, + const XMLCh *const // element_qname +) +{ + if (0 != XMLString::compareString( + CDXLTokens::XmlstrToken(EdxltokenScalarFieldSelect), + element_local_name)) + { + CWStringDynamic *str = CDXLUtils::CreateDynamicStringFromXMLChArray( + m_parse_handler_mgr->GetDXLMemoryManager(), element_local_name); + GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXLUnexpectedTag, + str->GetBuffer()); + } + GPOS_ASSERT(1 == this->Length()); + + // add constructed child from child parse handlers + CParseHandlerScalarOp *child_parse_handler = + dynamic_cast<CParseHandlerScalarOp *>((*this)[0]); + AddChildFromParseHandler(child_parse_handler); + + // deactivate handler + m_parse_handler_mgr->DeactivateHandler(); +} + +// EOF diff --git a/src/backend/gporca/libnaucrates/src/parser/Makefile b/src/backend/gporca/libnaucrates/src/parser/Makefile index 509a1c84a6..2a53a251af 100644 --- a/src/backend/gporca/libnaucrates/src/parser/Makefile +++ b/src/backend/gporca/libnaucrates/src/parser/Makefile @@ -144,6 +144,7 @@ OBJS = CParseHandlerAgg.o \ CParseHandlerScalarConstValue.o \ CParseHandlerScalarDMLAction.o \ CParseHandlerScalarExpr.o \ + CParseHandlerScalarFieldSelect.o \ CParseHandlerScalarFuncExpr.o \ CParseHandlerScalarIdent.o \ CParseHandlerScalarIfStmt.o \ diff --git a/src/backend/gporca/libnaucrates/src/xml/dxltokens.cpp b/src/backend/gporca/libnaucrates/src/xml/dxltokens.cpp index 22ff13dea6..0b147cc5c7 100644 --- a/src/backend/gporca/libnaucrates/src/xml/dxltokens.cpp +++ b/src/backend/gporca/libnaucrates/src/xml/dxltokens.cpp @@ -222,10 +222,16 @@ CDXLTokens::Init(CMemoryPool *mp) {EdxltokenScalarSortColList, GPOS_WSZ_LIT("SortingColumnList")}, {EdxltokenScalarGroupingColList, GPOS_WSZ_LIT("GroupingColumns")}, {EdxltokenScalarSortGroupClause, GPOS_WSZ_LIT("SortGroupClause")}, - {EdxltokenScalarBitmapAnd, GPOS_WSZ_LIT("BitmapAnd")}, {EdxltokenScalarBitmapOr, GPOS_WSZ_LIT("BitmapOr")}, + {EdxltokenScalarFieldSelect, GPOS_WSZ_LIT("FIELDSELECT")}, + {EdxltokenScalarFieldSelectFieldType, GPOS_WSZ_LIT("FieldType")}, + {EdxltokenScalarFieldSelectFieldCollation, + GPOS_WSZ_LIT("FieldCollation")}, + {EdxltokenScalarFieldSelectFieldNumber, GPOS_WSZ_LIT("FieldNumber")}, + {EdxltokenScalarFieldSelectTypeModifier, GPOS_WSZ_LIT("TypeModifier")}, + {EdxltokenScalarArray, GPOS_WSZ_LIT("Array")}, {EdxltokenScalarArrayRef, GPOS_WSZ_LIT("ArrayRef")}, {EdxltokenScalarArrayRefIndexList, GPOS_WSZ_LIT("ArrayIndexList")}, diff --git a/src/backend/gporca/server/CMakeLists.txt b/src/backend/gporca/server/CMakeLists.txt index 4bce67a677..8e4acdeba6 100644 --- a/src/backend/gporca/server/CMakeLists.txt +++ b/src/backend/gporca/server/CMakeLists.txt @@ -398,6 +398,9 @@ SqlFuncNullReject SqlFuncPredFactorize SqlFuncDmlScalar SqlFuncDmlTvf CompositeT CScalarFuncPushDownTest: ScalarFuncPushedBelowGather ConstScalarFuncNotPushedBelowGather; +CScalarTest: +FieldSelect; + COrderedAggTest: CTAS_OrderedAgg_multiple_cols OrderedAgg_multiple_diffcol OrderedAgg_with_groupby OrderedAgg_computed_col OrderedAggUsingGroupColumnInDirectArg OrderedAgg_multiple_samecol OrderedAgg_with_nonOrderedAgg OrderedAgg_single diff --git a/src/include/gpopt/translate/CTranslatorDXLToScalar.h b/src/include/gpopt/translate/CTranslatorDXLToScalar.h index db304388f8..e80a386731 100644 --- a/src/include/gpopt/translate/CTranslatorDXLToScalar.h +++ b/src/include/gpopt/translate/CTranslatorDXLToScalar.h @@ -113,6 +113,9 @@ private: Expr *TranslateDXLScalarArrayCoerceExprToScalar( const CDXLNode *coerce_node, CMappingColIdVar *colid_var); + Expr *TranslateDXLFieldSelectToScalar(const CDXLNode *field_select_node, + CMappingColIdVar *colid_var); + Expr *TranslateDXLScalarNullTestToScalar( const CDXLNode *scalar_null_test_node, CMappingColIdVar *colid_var); diff --git a/src/include/gpopt/translate/CTranslatorScalarToDXL.h b/src/include/gpopt/translate/CTranslatorScalarToDXL.h index d9a0c0cb24..4f9c6a3dd1 100644 --- a/src/include/gpopt/translate/CTranslatorScalarToDXL.h +++ b/src/include/gpopt/translate/CTranslatorScalarToDXL.h @@ -117,6 +117,10 @@ private: CDXLNode *TranslateScalarArrayOpExprToDXL( const Expr *expr, const CMappingVarColId *var_colid_mapping); + // create a DXL node for a fieldselect node from gpdb expression + CDXLNode *TranslateFieldSelectToDXL( + const Expr *expr, const CMappingVarColId *var_colid_mapping); + // create a DXL scalar array comparison node from a GPDB expression CDXLNode *CreateScalarArrayCompFromExpr( const Expr *expr, const CMappingVarColId *var_colid_mapping); diff --git a/src/test/regress/expected/gporca.out b/src/test/regress/expected/gporca.out index b0b43d6944..ab827b5ae4 100644 --- a/src/test/regress/expected/gporca.out +++ b/src/test/regress/expected/gporca.out @@ -14545,6 +14545,213 @@ select c from mix_func_cast(); t (1 row) +---------------------------------- +-- Test ORCA support for FIELDSELECT +---------------------------------- +create type comp_type as ( a text, b numeric, c int, d float, e int); +create table comp_table(id int, item comp_type) distributed by (id); +create table comp_part (id int, item comp_type) distributed by (id) partition by range(id) (start(1) end(4) every(1)); +insert into comp_table values (1, ROW('GP', 10.5, 10, 10.5, 20)), (2, ROW('VM',20.5, 20, 10.5, 20)), (3, ROW('DB',10.5, 10, 10.5, 10)); +insert into comp_part values (1, ROW('GP', 10.5, 10, 10.5, 20)), (2, ROW('VM',20.5, 20, 10.5, 20)), (3, ROW('DB',10.5, 10, 10.5, 10)); +analyze comp_table; +analyze comp_part; +select sum((item).b) from comp_table where (item).c=20; + sum +------ + 20.5 +(1 row) + +explain (costs off) select sum((item).b) from comp_table where (item).c=20; + QUERY PLAN +------------------------------------------------ + Aggregate + -> Gather Motion 3:1 (slice1; segments: 3) + -> Seq Scan on comp_table + Filter: ((item).c = 20) + Optimizer: Postgres-based planner +(5 rows) + +select distinct (item).b from comp_table where (item).c=20; + b +------ + 20.5 +(1 row) + +explain (costs off) select distinct (item).b from comp_table where (item).c=20; + QUERY PLAN +------------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Merge Key: ((item).b) + -> Unique + Group Key: ((item).b) + -> Sort + Sort Key: ((item).b) + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: ((item).b) + -> Seq Scan on comp_table + Filter: ((item).c = 20) + Optimizer: Postgres-based planner +(11 rows) + +-- verify the query output using predicate with the same composite type +select (item).a from comp_table where (item).c=20 and (item).e >10; + a +---- + VM +(1 row) + +explain (costs off) select (item).a from comp_table where (item).c=20 and (item).e >10; + QUERY PLAN +------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + -> Seq Scan on comp_table + Filter: (((item).e > 10) AND ((item).c = 20)) + Optimizer: Postgres-based planner +(4 rows) + +-- verify the query output using predicate with the different composite type +select * from comp_table where (item).c>(item).d; + id | item +----+---------------------- + 2 | (VM,20.5,20,10.5,20) +(1 row) + +explain (costs off) select * from comp_table where (item).c>(item).d ; + QUERY PLAN +----------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + -> Seq Scan on comp_table + Filter: (((item).c)::double precision > (item).d) + Optimizer: Postgres-based planner +(4 rows) + +-- verify the query output by using a composite type in a join query +select (x.item).a from comp_table x join comp_table y on (x.item).c=(y.item).c; + a +---- + DB + DB + GP + GP + VM +(5 rows) + +explain (costs off) select (x.item).a from comp_table x join comp_table y on (x.item).c=(y.item).c; + QUERY PLAN +------------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + -> Hash Join + Hash Cond: ((x.item).c = (y.item).c) + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: (x.item).c + -> Seq Scan on comp_table x + -> Hash + -> Redistribute Motion 3:3 (slice3; segments: 3) + Hash Key: (y.item).c + -> Seq Scan on comp_table y + Optimizer: Postgres-based planner +(11 rows) + +-- verify the query output by using a composite type in a TVF query +select (x.item).a, (select count(*) from generate_series(1, (x.item).c)) from comp_table x; + a | count +----+------- + GP | 10 + VM | 20 + DB | 10 +(3 rows) + +explain (costs off) select (x.item).a, (select count(*) from generate_series(1, (x.item).c)) from comp_table x; + QUERY PLAN +------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + -> Seq Scan on comp_table x + SubPlan 1 + -> Aggregate + -> Function Scan on generate_series + Optimizer: Postgres-based planner +(6 rows) + +-- verify the query output by using a composite type in a cte query +with cte1 as (select * from comp_table where (item).c>10) select id, (item).a, (item).b, (item).c, (item).e from cte1; + id | a | b | c | e +----+----+------+----+---- + 2 | VM | 20.5 | 20 | 20 +(1 row) + +explain (costs off) with cte1 as (select * from comp_table where (item).c>10) select id, (item).a, (item).b, (item).c, (item).e from cte1; + QUERY PLAN +------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + -> Subquery Scan on cte1 + -> Seq Scan on comp_table + Filter: ((item).c > 10) + Optimizer: Postgres-based planner +(5 rows) + +-- verify the query output by using a composite type in a subquery +select (item).a from comp_table where (item).c=10 and (item).e IN (SELECT (item).e FROM comp_table WHERE (item).c = 10); + a +---- + GP + DB +(2 rows) + +explain (costs off) select (item).a from comp_table where (item).c=10 and (item).e IN (SELECT (item).e FROM comp_table WHERE (item).c = 10); + QUERY PLAN +------------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + -> Hash Semi Join + Hash Cond: ((comp_table.item).e = (comp_table_1.item).e) + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: (comp_table.item).e + -> Seq Scan on comp_table + Filter: ((item).c = 10) + -> Hash + -> Redistribute Motion 3:3 (slice3; segments: 3) + Hash Key: (comp_table_1.item).e + -> Seq Scan on comp_table comp_table_1 + Filter: ((item).c = 10) + Optimizer: Postgres-based planner +(13 rows) + +-- verify the query output by using a composite type in a partition table query +select (x.item).a from comp_part x join comp_part y on (X.item).c=(Y.item).c; + a +---- + DB + DB + GP + GP + VM +(5 rows) + +explain (costs off) select (x.item).a from comp_part x join comp_part y on (X.item).c=(Y.item).c; + QUERY PLAN +------------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + -> Hash Join + Hash Cond: ((x.item).c = (y.item).c) + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: (x.item).c + -> Append + -> Seq Scan on comp_part_1_prt_1 x + -> Seq Scan on comp_part_1_prt_2 x_1 + -> Seq Scan on comp_part_1_prt_3 x_2 + -> Hash + -> Redistribute Motion 3:3 (slice3; segments: 3) + Hash Key: (y.item).c + -> Append + -> Seq Scan on comp_part_1_prt_1 y + -> Seq Scan on comp_part_1_prt_2 y_1 + -> Seq Scan on comp_part_1_prt_3 y_2 + Optimizer: Postgres-based planner +(17 rows) + +-- clean up +drop table comp_table; +drop table comp_part; +drop type comp_type; -- the query with empty CTE producer target list should fall back to Postgres -- optimizer without any error on build without asserts drop table if exists empty_cte_tl_test; diff --git a/src/test/regress/expected/gporca_optimizer.out b/src/test/regress/expected/gporca_optimizer.out index 74df1cd8d5..4d14cbbcde 100644 --- a/src/test/regress/expected/gporca_optimizer.out +++ b/src/test/regress/expected/gporca_optimizer.out @@ -14541,21 +14541,17 @@ explain select c2 from quad_func_cast(); (2 rows) explain select (c1).r from quad_func_cast(); -INFO: GPORCA failed to produce a plan, falling back to Postgres-based planner -DETAIL: Falling back to Postgres-based planner because GPORCA does not support the following feature: FIELDSELECT QUERY PLAN ------------------------------------------------------------------- - Function Scan on quad_func_cast (cost=0.00..0.01 rows=1 width=8) - Optimizer: Postgres query optimizer + Function Scan on quad_func_cast (cost=0.00..0.00 rows=1 width=8) + Optimizer: Pivotal Optimizer (GPORCA) (2 rows) explain select (c2).i from quad_func_cast(); -INFO: GPORCA failed to produce a plan, falling back to Postgres-based planner -DETAIL: Falling back to Postgres-based planner because GPORCA does not support the following feature: FIELDSELECT QUERY PLAN ------------------------------------------------------------------- - Function Scan on quad_func_cast (cost=0.00..0.01 rows=1 width=8) - Optimizer: Postgres query optimizer + Function Scan on quad_func_cast (cost=0.00..0.00 rows=1 width=8) + Optimizer: Pivotal Optimizer (GPORCA) (2 rows) select c1 from quad_func_cast(); @@ -14571,8 +14567,6 @@ select c2 from quad_func_cast(); (1 row) select (c1).r from quad_func_cast(); -INFO: GPORCA failed to produce a plan, falling back to Postgres-based planner -DETAIL: Falling back to Postgres-based planner because GPORCA does not support the following feature: FIELDSELECT r ----- 1.1 @@ -14627,6 +14621,205 @@ select c from mix_func_cast(); t (1 row) +---------------------------------- +-- Test ORCA support for FIELDSELECT +---------------------------------- +create type comp_type as ( a text, b numeric, c int, d float, e int); +create table comp_table(id int, item comp_type) distributed by (id); +create table comp_part (id int, item comp_type) distributed by (id) partition by range(id) (start(1) end(4) every(1)); +insert into comp_table values (1, ROW('GP', 10.5, 10, 10.5, 20)), (2, ROW('VM',20.5, 20, 10.5, 20)), (3, ROW('DB',10.5, 10, 10.5, 10)); +insert into comp_part values (1, ROW('GP', 10.5, 10, 10.5, 20)), (2, ROW('VM',20.5, 20, 10.5, 20)), (3, ROW('DB',10.5, 10, 10.5, 10)); +analyze comp_table; +analyze comp_part; +select sum((item).b) from comp_table where (item).c=20; + sum +------ + 20.5 +(1 row) + +explain (costs off) select sum((item).b) from comp_table where (item).c=20; + QUERY PLAN +------------------------------------------------ + Finalize Aggregate + -> Gather Motion 3:1 (slice1; segments: 3) + -> Partial Aggregate + -> Seq Scan on comp_table + Filter: ((item).c = 20) + Optimizer: GPORCA +(6 rows) + +select distinct (item).b from comp_table where (item).c=20; + b +------ + 20.5 +(1 row) + +explain (costs off) select distinct (item).b from comp_table where (item).c=20; + QUERY PLAN +------------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + -> GroupAggregate + Group Key: ((item).b) + -> Sort + Sort Key: ((item).b) + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: ((item).b) + -> Seq Scan on comp_table + Filter: ((item).c = 20) + Optimizer: GPORCA +(10 rows) + +-- verify the query output using predicate with the same composite type +select (item).a from comp_table where (item).c=20 and (item).e >10; + a +---- + VM +(1 row) + +explain (costs off) select (item).a from comp_table where (item).c=20 and (item).e >10; + QUERY PLAN +------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + -> Seq Scan on comp_table + Filter: (((item).c = 20) AND ((item).e > 10)) + Optimizer: GPORCA +(4 rows) + +-- verify the query output using predicate with the different composite type +select * from comp_table where (item).c>(item).d; + id | item +----+---------------------- + 2 | (VM,20.5,20,10.5,20) +(1 row) + +explain (costs off) select * from comp_table where (item).c>(item).d ; + QUERY PLAN +----------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + -> Seq Scan on comp_table + Filter: (((item).c)::double precision > (item).d) + Optimizer: GPORCA +(4 rows) + +-- verify the query output by using a composite type in a join query +select (x.item).a from comp_table x join comp_table y on (x.item).c=(y.item).c; + a +---- + DB + DB + GP + GP + VM +(5 rows) + +explain (costs off) select (x.item).a from comp_table x join comp_table y on (x.item).c=(y.item).c; + QUERY PLAN +------------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + -> Hash Join + Hash Cond: ((comp_table.item).c = (comp_table_1.item).c) + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: (comp_table.item).c + -> Seq Scan on comp_table + -> Hash + -> Redistribute Motion 3:3 (slice3; segments: 3) + Hash Key: (comp_table_1.item).c + -> Seq Scan on comp_table comp_table_1 + Optimizer: GPORCA +(11 rows) + +-- verify the query output by using a composite type in a TVF query +select (x.item).a, (select count(*) from generate_series(1, (x.item).c)) from comp_table x; + a | count +----+------- + GP | 10 + VM | 20 + DB | 10 +(3 rows) + +explain (costs off) select (x.item).a, (select count(*) from generate_series(1, (x.item).c)) from comp_table x; + QUERY PLAN +------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + -> Seq Scan on comp_table + SubPlan 1 + -> Aggregate + -> Function Scan on generate_series + Optimizer: GPORCA +(6 rows) + +-- verify the query output by using a composite type in a cte query +with cte1 as (select * from comp_table where (item).c>10) select id, (item).a, (item).b, (item).c, (item).e from cte1; + id | a | b | c | e +----+----+------+----+---- + 2 | VM | 20.5 | 20 | 20 +(1 row) + +explain (costs off) with cte1 as (select * from comp_table where (item).c>10) select id, (item).a, (item).b, (item).c, (item).e from cte1; + QUERY PLAN +------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + -> Seq Scan on comp_table + Filter: ((item).c > 10) + Optimizer: GPORCA +(4 rows) + +-- verify the query output by using a composite type in a subquery +select (item).a from comp_table where (item).c=10 and (item).e IN (SELECT (item).e FROM comp_table WHERE (item).c = 10); + a +---- + DB + GP +(2 rows) + +explain (costs off) select (item).a from comp_table where (item).c=10 and (item).e IN (SELECT (item).e FROM comp_table WHERE (item).c = 10); + QUERY PLAN +-------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + -> Hash Semi Join + Hash Cond: ((comp_table.item).e = ((comp_table_1.item).e)) + -> Seq Scan on comp_table + Filter: ((item).c = 10) + -> Hash + -> Broadcast Motion 3:3 (slice2; segments: 3) + -> Seq Scan on comp_table comp_table_1 + Filter: ((item).c = 10) + Optimizer: GPORCA +(10 rows) + +-- verify the query output by using a composite type in a partition table query +select (x.item).a from comp_part x join comp_part y on (X.item).c=(Y.item).c; + a +---- + GP + GP + VM + DB + DB +(5 rows) + +explain (costs off) select (x.item).a from comp_part x join comp_part y on (X.item).c=(Y.item).c; + QUERY PLAN +---------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + -> Hash Join + Hash Cond: ((comp_part.item).c = (comp_part_1.item).c) + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: (comp_part.item).c + -> Dynamic Seq Scan on comp_part + Number of partitions to scan: 3 (out of 3) + -> Hash + -> Redistribute Motion 3:3 (slice3; segments: 3) + Hash Key: (comp_part_1.item).c + -> Dynamic Seq Scan on comp_part comp_part_1 + Number of partitions to scan: 3 (out of 3) + Optimizer: GPORCA +(13 rows) + +-- clean up +drop table comp_table; +drop table comp_part; +drop type comp_type; -- the query with empty CTE producer target list should fall back to Postgres -- optimizer without any error on build without asserts drop table if exists empty_cte_tl_test; diff --git a/src/test/regress/output/external_table_persistent_error_log_optimizer.source b/src/test/regress/output/external_table_persistent_error_log_optimizer.source index b8004d088d..cb9249e6d0 100644 --- a/src/test/regress/output/external_table_persistent_error_log_optimizer.source +++ b/src/test/regress/output/external_table_persistent_error_log_optimizer.source @@ -40,7 +40,7 @@ NOTICE: found 2 data formatting errors (2 or more input rows), rejected related SELECT (gp_read_persistent_error_log('ext_error_persistent')).errmsg; INFO: GPORCA failed to produce a plan, falling back to Postgres-based planner -DETAIL: Falling back to Postgres-based planner because GPORCA does not support the following feature: FIELDSELECT +DETAIL: Falling back to Postgres-based planner because GPORCA does not support the following feature: unsupported exec location errmsg --------------------------------------- extra data after last expected column @@ -80,7 +80,7 @@ DETAIL: Falling back to Postgres-based planner because GPORCA does not support SELECT (gp_read_persistent_error_log('ext_error_persistent')).errmsg; INFO: GPORCA failed to produce a plan, falling back to Postgres-based planner -DETAIL: Falling back to Postgres-based planner because GPORCA does not support the following feature: FIELDSELECT +DETAIL: Falling back to Postgres-based planner because GPORCA does not support the following feature: unsupported exec location errmsg --------------------------------------- extra data after last expected column diff --git a/src/test/regress/sql/gporca.sql b/src/test/regress/sql/gporca.sql index 524ac0c788..ff08636b68 100644 --- a/src/test/regress/sql/gporca.sql +++ b/src/test/regress/sql/gporca.sql @@ -3555,6 +3555,56 @@ select a from mix_func_cast(); select b from mix_func_cast(); select c from mix_func_cast(); +---------------------------------- +-- Test ORCA support for FIELDSELECT +---------------------------------- +create type comp_type as ( a text, b numeric, c int, d float, e int); +create table comp_table(id int, item comp_type) distributed by (id); +create table comp_part (id int, item comp_type) distributed by (id) partition by range(id) (start(1) end(4) every(1)); +insert into comp_table values (1, ROW('GP', 10.5, 10, 10.5, 20)), (2, ROW('VM',20.5, 20, 10.5, 20)), (3, ROW('DB',10.5, 10, 10.5, 10)); +insert into comp_part values (1, ROW('GP', 10.5, 10, 10.5, 20)), (2, ROW('VM',20.5, 20, 10.5, 20)), (3, ROW('DB',10.5, 10, 10.5, 10)); +analyze comp_table; +analyze comp_part; + +select sum((item).b) from comp_table where (item).c=20; +explain (costs off) select sum((item).b) from comp_table where (item).c=20; + +select distinct (item).b from comp_table where (item).c=20; +explain (costs off) select distinct (item).b from comp_table where (item).c=20; + +-- verify the query output using predicate with the same composite type +select (item).a from comp_table where (item).c=20 and (item).e >10; +explain (costs off) select (item).a from comp_table where (item).c=20 and (item).e >10; + +-- verify the query output using predicate with the different composite type +select * from comp_table where (item).c>(item).d; +explain (costs off) select * from comp_table where (item).c>(item).d ; + +-- verify the query output by using a composite type in a join query +select (x.item).a from comp_table x join comp_table y on (x.item).c=(y.item).c; +explain (costs off) select (x.item).a from comp_table x join comp_table y on (x.item).c=(y.item).c; + +-- verify the query output by using a composite type in a TVF query +select (x.item).a, (select count(*) from generate_series(1, (x.item).c)) from comp_table x; +explain (costs off) select (x.item).a, (select count(*) from generate_series(1, (x.item).c)) from comp_table x; + +-- verify the query output by using a composite type in a cte query +with cte1 as (select * from comp_table where (item).c>10) select id, (item).a, (item).b, (item).c, (item).e from cte1; +explain (costs off) with cte1 as (select * from comp_table where (item).c>10) select id, (item).a, (item).b, (item).c, (item).e from cte1; + +-- verify the query output by using a composite type in a subquery +select (item).a from comp_table where (item).c=10 and (item).e IN (SELECT (item).e FROM comp_table WHERE (item).c = 10); +explain (costs off) select (item).a from comp_table where (item).c=10 and (item).e IN (SELECT (item).e FROM comp_table WHERE (item).c = 10); + +-- verify the query output by using a composite type in a partition table query +select (x.item).a from comp_part x join comp_part y on (X.item).c=(Y.item).c; +explain (costs off) select (x.item).a from comp_part x join comp_part y on (X.item).c=(Y.item).c; + +-- clean up +drop table comp_table; +drop table comp_part; +drop type comp_type; + -- the query with empty CTE producer target list should fall back to Postgres -- optimizer without any error on build without asserts drop table if exists empty_cte_tl_test; --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
