This is an automated email from the ASF dual-hosted git repository.

maxyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudberry.git

commit f0a6160d3ccc1290c3b733b633ff298d26707340
Author: David Kimura <[email protected]>
AuthorDate: Tue Sep 27 08:57:37 2022 -0700

    [ORCA] Allow empty target list (#14159)
    
    There were a lot of asserts on NULL != target_list in the translator,
    but most of them were unnecessary. Fix ORCA to handle empty target list.
    
    - Add trace fallback to union testcase
    - Fix up CXformDifference2LeftAntiSemiJoin to handle case of empty columns
    
    Following SQL works
    ```
    EXPLAIN (COSTS OFF) SELECT UNION SELECT;
    ```
---
 .../gpopt/translate/CTranslatorQueryToDXL.cpp      | 35 ---------
 src/backend/gpopt/translate/CTranslatorUtils.cpp   |  8 +-
 .../gporca/libgpopt/src/base/CKeyCollection.cpp    |  2 +-
 src/backend/gporca/libgpopt/src/base/CUtils.cpp    |  1 -
 .../xforms/CXformDifference2LeftAntiSemiJoin.cpp   | 32 +++++---
 .../gporca/libgpopt/src/xforms/CXformUtils.cpp     |  2 +-
 src/test/regress/expected/union.out                |  2 +
 src/test/regress/expected/union_optimizer.out      | 86 ++++++++++++++--------
 src/test/regress/sql/union.sql                     |  3 +
 9 files changed, 85 insertions(+), 86 deletions(-)

diff --git a/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp 
b/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp
index c4cfe8e22d..cacd2845f5 100644
--- a/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp
+++ b/src/backend/gpopt/translate/CTranslatorQueryToDXL.cpp
@@ -2720,7 +2720,6 @@ CTranslatorQueryToDXL::CreateDXLSetOpFromColumns(
        CDXLNodeArray *children_dxlnodes, BOOL is_cast_across_input,
        BOOL keep_res_junked) const
 {
-       GPOS_ASSERT(nullptr != output_target_list);
        GPOS_ASSERT(nullptr != output_colids);
        GPOS_ASSERT(nullptr != input_colids);
        GPOS_ASSERT(nullptr != children_dxlnodes);
@@ -2838,7 +2837,6 @@ CTranslatorQueryToDXL::SetOpNeedsCast(List *target_list,
                                                                          
IMdIdArray *input_col_mdids)
 {
        GPOS_ASSERT(nullptr != input_col_mdids);
-       GPOS_ASSERT(nullptr != target_list);
        GPOS_ASSERT(
                input_col_mdids->Size() <=
                gpdb::ListLength(target_list));  // there may be resjunked 
columns
@@ -2880,39 +2878,6 @@ CTranslatorQueryToDXL::TranslateSetOpChild(Node 
*child_node,
        GPOS_ASSERT(nullptr != colids);
        GPOS_ASSERT(nullptr != input_col_mdids);
 
-       // GPDB_12_MERGE_FIXME: We have to fallback here because otherwise we 
trip
-       // the following assert in ORCA:
-       //
-       // INFO:  GPORCA failed to produce a plan, falling back to planner
-       // DETAIL:  CKeyCollection.cpp:84: Failed assertion: __null != 
colref_array && 0 < colref_array->Size()
-       // Stack trace:
-       // 1    0x000055c239243b8a gpos::CException::Raise + 278
-       // 2    0x000055c2393ab075 gpopt::CKeyCollection::CKeyCollection + 221
-       // 3    0x000055c239449ab6 gpopt::CLogicalSetOp::DeriveKeyCollection + 
98
-       // 4    0x000055c2393a5a67 
gpopt::CDrvdPropRelational::DeriveKeyCollection + 135
-       // 5    0x000055c2393a4937 gpopt::CDrvdPropRelational::Derive + 197
-       // 6    0x000055c239405d9f gpopt::CExpression::PdpDerive + 703
-       // 7    0x000055c2394d1e14 gpopt::CMemo::PgroupInsert + 512
-       // 8    0x000055c2393dd734 gpopt::CEngine::PgroupInsert + 632
-       // 9    0x000055c2393dcd73 gpopt::CEngine::InitLogicalExpression + 225
-       // 10   0x000055c2393dd106 gpopt::CEngine::Init + 884
-       // 11   0x000055c23949da9f gpopt::COptimizer::PexprOptimize + 103
-       // 12   0x000055c23949d3d8 gpopt::COptimizer::PdxlnOptimize + 1414
-       // 13   0x000055c23960e55e COptTasks::OptimizeTask + 1530
-       // 14   0x000055c2392572b6 gpos::CTask::Execute + 196
-       // 15   0x000055c239259dbf gpos::CWorker::Execute + 191
-       // 16   0x000055c2392556b5 gpos::CAutoTaskProxy::Execute + 221
-       // 17   0x000055c23925c0c0 gpos_exec + 876
-       //
-       // Currently there are a lot of asserts on NULL != target_list in the
-       // translator, but most of them are unnecessary. We should instead fix 
ORCA
-       // to handle empty target list.
-       if (NIL == target_list)
-       {
-               GPOS_RAISE(gpdxl::ExmaDXL, 
gpdxl::ExmiQuery2DXLUnsupportedFeature,
-                                  GPOS_WSZ_LIT("Empty target list"));
-       }
-
        if (IsA(child_node, RangeTblRef))
        {
                RangeTblRef *range_tbl_ref = (RangeTblRef *) child_node;
diff --git a/src/backend/gpopt/translate/CTranslatorUtils.cpp 
b/src/backend/gpopt/translate/CTranslatorUtils.cpp
index bf5698d2f2..c5cac56e35 100644
--- a/src/backend/gpopt/translate/CTranslatorUtils.cpp
+++ b/src/backend/gpopt/translate/CTranslatorUtils.cpp
@@ -1146,7 +1146,6 @@ CTranslatorUtils::GenerateColIds(
                is_outer_ref,  // array of flags indicating if input columns 
are outer references
        CIdGenerator *colid_generator)
 {
-       GPOS_ASSERT(nullptr != target_list);
        GPOS_ASSERT(nullptr != input_mdid_arr);
        GPOS_ASSERT(nullptr != input_colids);
        GPOS_ASSERT(nullptr != is_outer_ref);
@@ -1206,7 +1205,10 @@ CTranslatorUtils::FixUnknownTypeConstant(Query 
*old_query,
                                                                                
 List *output_target_list)
 {
        GPOS_ASSERT(nullptr != old_query);
-       GPOS_ASSERT(nullptr != output_target_list);
+       if (nullptr == output_target_list)
+       {
+               return old_query;
+       }
 
        Query *new_query = nullptr;
 
@@ -1346,8 +1348,6 @@ ULongPtrArray *
 CTranslatorUtils::GetPosInTargetList(CMemoryPool *mp, List *target_list,
                                                                         BOOL 
keep_res_junked)
 {
-       GPOS_ASSERT(nullptr != target_list);
-
        ListCell *target_entry_cell = nullptr;
        ULongPtrArray *positions = GPOS_NEW(mp) ULongPtrArray(mp);
        ULONG ul = 0;
diff --git a/src/backend/gporca/libgpopt/src/base/CKeyCollection.cpp 
b/src/backend/gporca/libgpopt/src/base/CKeyCollection.cpp
index dc39b41550..07a8124d00 100644
--- a/src/backend/gporca/libgpopt/src/base/CKeyCollection.cpp
+++ b/src/backend/gporca/libgpopt/src/base/CKeyCollection.cpp
@@ -67,7 +67,7 @@ CKeyCollection::CKeyCollection(CMemoryPool *mp, CColRefArray 
*colref_array)
        : m_pdrgpcrs(nullptr)
 {
        GPOS_ASSERT(nullptr != mp);
-       GPOS_ASSERT(nullptr != colref_array && 0 < colref_array->Size());
+       GPOS_ASSERT(nullptr != colref_array);
 
        m_pdrgpcrs = GPOS_NEW(mp) CColRefSetArray(mp);
 
diff --git a/src/backend/gporca/libgpopt/src/base/CUtils.cpp 
b/src/backend/gporca/libgpopt/src/base/CUtils.cpp
index 536e7c0606..5d18422106 100644
--- a/src/backend/gporca/libgpopt/src/base/CUtils.cpp
+++ b/src/backend/gporca/libgpopt/src/base/CUtils.cpp
@@ -3708,7 +3708,6 @@ CUtils::PexprConjINDFCond(CMemoryPool *mp, CColRef2dArray 
*pdrgpdrgpcrInput)
        // assemble the new scalar condition
        CExpression *pexprScCond = nullptr;
        const ULONG length = (*pdrgpdrgpcrInput)[0]->Size();
-       GPOS_ASSERT(0 != length);
        GPOS_ASSERT(length == (*pdrgpdrgpcrInput)[1]->Size());
 
        CExpressionArray *pdrgpexprInput =
diff --git 
a/src/backend/gporca/libgpopt/src/xforms/CXformDifference2LeftAntiSemiJoin.cpp 
b/src/backend/gporca/libgpopt/src/xforms/CXformDifference2LeftAntiSemiJoin.cpp
index c2dc3c74ab..f4a0daf028 100644
--- 
a/src/backend/gporca/libgpopt/src/xforms/CXformDifference2LeftAntiSemiJoin.cpp
+++ 
b/src/backend/gporca/libgpopt/src/xforms/CXformDifference2LeftAntiSemiJoin.cpp
@@ -83,18 +83,26 @@ CXformDifference2LeftAntiSemiJoin::Transform(CXformContext 
*pxfctxt,
                GPOS_NEW(mp) CExpression(mp, GPOS_NEW(mp) 
CLogicalLeftAntiSemiJoin(mp),
                                                                 
pexprLeftChild, pexprRightChild, pexprScCond);
 
-       // assemble the aggregate operator
-       pdrgpcrOutput->AddRef();
-
-       CExpression *pexprProjList =
-               GPOS_NEW(mp) CExpression(mp, GPOS_NEW(mp) 
CScalarProjectList(mp),
-                                                                GPOS_NEW(mp) 
CExpressionArray(mp));
-
-       CExpression *pexprAgg = CUtils::PexprLogicalGbAggGlobal(
-               mp, pdrgpcrOutput, pexprLASJ, pexprProjList);
-
-       // add alternative to results
-       pxfres->Add(pexprAgg);
+       if (pdrgpcrOutput->Size() > 0)
+       {
+               // assemble the aggregate operator
+               pdrgpcrOutput->AddRef();
+
+               CExpression *pexprProjList =
+                       GPOS_NEW(mp) CExpression(mp, GPOS_NEW(mp) 
CScalarProjectList(mp),
+                                                                        
GPOS_NEW(mp) CExpressionArray(mp));
+
+               CExpression *pexprAgg = CUtils::PexprLogicalGbAggGlobal(
+                       mp, pdrgpcrOutput, pexprLASJ, pexprProjList);
+
+               // add alternative to results
+               pxfres->Add(pexprAgg);
+       }
+       else
+       {
+               // skip the aggregate operator if output columns is empty
+               pxfres->Add(pexprLASJ);
+       }
 }
 
 // EOF
diff --git a/src/backend/gporca/libgpopt/src/xforms/CXformUtils.cpp 
b/src/backend/gporca/libgpopt/src/xforms/CXformUtils.cpp
index bf2d321802..04ebf2c13a 100644
--- a/src/backend/gporca/libgpopt/src/xforms/CXformUtils.cpp
+++ b/src/backend/gporca/libgpopt/src/xforms/CXformUtils.cpp
@@ -2211,7 +2211,7 @@ CXformUtils::PexprWindowWithRowNumber(CMemoryPool *mp,
 {
        // partitioning information
        CDistributionSpec *pds = nullptr;
-       if (nullptr != pdrgpcrInput)
+       if (nullptr != pdrgpcrInput && 0 < pdrgpcrInput->Size())
        {
                CExpressionArray *pdrgpexprInput =
                        CUtils::PdrgpexprScalarIdents(mp, pdrgpcrInput);
diff --git a/src/test/regress/expected/union.out 
b/src/test/regress/expected/union.out
index dca88da8de..a952417fcc 100644
--- a/src/test/regress/expected/union.out
+++ b/src/test/regress/expected/union.out
@@ -1,3 +1,4 @@
+set optimizer_trace_fallback = on;
 --
 -- UNION (also INTERSECT, EXCEPT)
 --
@@ -1527,3 +1528,4 @@ where (x = 0) or (q1 >= q2 and q1 <= q2);
  4567890123456789 |  4567890123456789 | 1
 (6 rows)
 
+reset optimizer_trace_fallback;
diff --git a/src/test/regress/expected/union_optimizer.out 
b/src/test/regress/expected/union_optimizer.out
index f439f9dd59..42de63f9b7 100644
--- a/src/test/regress/expected/union_optimizer.out
+++ b/src/test/regress/expected/union_optimizer.out
@@ -1,3 +1,4 @@
+set optimizer_trace_fallback = on;
 --
 -- UNION (also INTERSECT, EXCEPT)
 --
@@ -1020,25 +1021,29 @@ set enable_hashagg = true;
 set enable_sort = false;
 explain (costs off)
 select from generate_series(1,5) union select from generate_series(1,3);
-                           QUERY PLAN                           
-----------------------------------------------------------------
- HashAggregate
-   ->  Append
-         ->  Function Scan on generate_series
-         ->  Function Scan on generate_series generate_series_1
-(4 rows)
-
-explain (costs off)
-select from generate_series(1,5) intersect select from generate_series(1,3);
                               QUERY PLAN                              
 ----------------------------------------------------------------------
- HashSetOp Intersect
+ Aggregate
    ->  Append
-         ->  Subquery Scan on "*SELECT* 1"
+         ->  Aggregate
                ->  Function Scan on generate_series
-         ->  Subquery Scan on "*SELECT* 2"
+         ->  Aggregate
                ->  Function Scan on generate_series generate_series_1
-(6 rows)
+ Optimizer: Pivotal Optimizer (GPORCA)
+(7 rows)
+
+explain (costs off)
+select from generate_series(1,5) intersect select from generate_series(1,3);
+                           QUERY PLAN                           
+----------------------------------------------------------------
+ Nested Loop
+   Join Filter: true
+   ->  Aggregate
+         ->  Function Scan on generate_series generate_series_1
+   ->  Aggregate
+         ->  Function Scan on generate_series
+ Optimizer: Pivotal Optimizer (GPORCA)
+(7 rows)
 
 select from generate_series(1,5) union select from generate_series(1,3);
 --
@@ -1069,25 +1074,29 @@ set enable_hashagg = false;
 set enable_sort = true;
 explain (costs off)
 select from generate_series(1,5) union select from generate_series(1,3);
-                           QUERY PLAN                           
-----------------------------------------------------------------
- Unique
-   ->  Append
-         ->  Function Scan on generate_series
-         ->  Function Scan on generate_series generate_series_1
-(4 rows)
-
-explain (costs off)
-select from generate_series(1,5) intersect select from generate_series(1,3);
                               QUERY PLAN                              
 ----------------------------------------------------------------------
- SetOp Intersect
+ Aggregate
    ->  Append
-         ->  Subquery Scan on "*SELECT* 1"
+         ->  Aggregate
                ->  Function Scan on generate_series
-         ->  Subquery Scan on "*SELECT* 2"
+         ->  Aggregate
                ->  Function Scan on generate_series generate_series_1
-(6 rows)
+ Optimizer: Pivotal Optimizer (GPORCA)
+(7 rows)
+
+explain (costs off)
+select from generate_series(1,5) intersect select from generate_series(1,3);
+                           QUERY PLAN                           
+----------------------------------------------------------------
+ Nested Loop
+   Join Filter: true
+   ->  Aggregate
+         ->  Function Scan on generate_series generate_series_1
+   ->  Aggregate
+         ->  Function Scan on generate_series
+ Optimizer: Pivotal Optimizer (GPORCA)
+(7 rows)
 
 select from generate_series(1,5) union select from generate_series(1,3);
 --
@@ -1213,8 +1222,10 @@ explain (costs off)
    UNION ALL
    SELECT ab FROM t2) t
   ORDER BY 1 LIMIT 8;
-                           QUERY PLAN                            
------------------------------------------------------------------
+INFO:  GPORCA failed to produce a plan, falling back to planner
+DETAIL:  Feature not supported: Inherited tables
+                         QUERY PLAN                         
+------------------------------------------------------------
  Limit
    ->  Gather Motion 3:1  (slice1; segments: 3)
          Merge Key: ((t1.a || t1.b))
@@ -1233,6 +1244,8 @@ explain (costs off)
    UNION ALL
    SELECT ab FROM t2) t
   ORDER BY 1 LIMIT 8;
+INFO:  GPORCA failed to produce a plan, falling back to planner
+DETAIL:  Feature not supported: Inherited tables
  ab 
 ----
  ab
@@ -1261,6 +1274,8 @@ select event_id
        union all
        select event_id from other_events) ss
  order by event_id;
+INFO:  GPORCA failed to produce a plan, falling back to planner
+DETAIL:  Feature not supported: Inherited tables
                            QUERY PLAN                           
 ----------------------------------------------------------------
  Gather Motion 3:1  (slice1; segments: 3)
@@ -1285,6 +1300,8 @@ explain (costs off)
    UNION ALL
    SELECT 2 AS t, * FROM tenk1 b) c
  WHERE t = 2;
+INFO:  GPORCA failed to produce a plan, falling back to planner
+DETAIL:  Feature not supported: Non-default collation
                 QUERY PLAN                
 ------------------------------------------
  Gather Motion 3:1  (slice1; segments: 3)
@@ -1369,8 +1386,10 @@ SELECT * FROM
    SELECT 2 AS t, 4 AS x) ss
 WHERE x > 3
 ORDER BY x;
-                                  QUERY PLAN                                  
-------------------------------------------------------------------------------
+INFO:  GPORCA failed to produce a plan, falling back to planner
+DETAIL:  Feature not supported: SIRV functions
+                               QUERY PLAN                                
+-------------------------------------------------------------------------
  Sort
    Sort Key: ss.x
    ->  Subquery Scan on ss
@@ -1393,6 +1412,8 @@ SELECT * FROM
    SELECT 2 AS t, 4 AS x) ss
 WHERE x > 3
 ORDER BY x;
+INFO:  GPORCA failed to produce a plan, falling back to planner
+DETAIL:  Feature not supported: SIRV functions
  t | x 
 ---+---
  2 | 4
@@ -1551,3 +1572,4 @@ where (x = 0) or (q1 >= q2 and q1 <= q2);
  4567890123456789 |  4567890123456789 | 1
 (6 rows)
 
+reset optimizer_trace_fallback;
diff --git a/src/test/regress/sql/union.sql b/src/test/regress/sql/union.sql
index f673a2e049..3edcd9fdac 100644
--- a/src/test/regress/sql/union.sql
+++ b/src/test/regress/sql/union.sql
@@ -1,3 +1,4 @@
+set optimizer_trace_fallback = on;
 --
 -- UNION (also INTERSECT, EXCEPT)
 --
@@ -550,3 +551,5 @@ select * from
    union all
    select *, 1 as x from int8_tbl b) ss
 where (x = 0) or (q1 >= q2 and q1 <= q2);
+
+reset optimizer_trace_fallback;


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to