| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| //--------------------------------------------------------------------------- |
| // @filename: |
| // CTranslatorPlStmtToDXL.cpp |
| // |
| // @doc: |
| // Implementation of the methods for translating GPDB's PlannedStmt into DXL Tree. |
| // All translator methods allocate memory in the provided memory pool, and |
| // the caller is responsible for freeing it |
| // |
| // @test: |
| // |
| // |
| //--------------------------------------------------------------------------- |
| |
| #include "postgres.h" |
| |
| #include "nodes/plannodes.h" |
| #include "nodes/parsenodes.h" |
| #include "access/sysattr.h" |
| #include "optimizer/walkers.h" |
| |
| #include "gpos/base.h" |
| #include "gpos/string/CWStringDynamic.h" |
| |
| #include "gpopt/mdcache/CMDAccessor.h" |
| #include "gpopt/translate/CTranslatorPlStmtToDXL.h" |
| #include "gpopt/translate/CTranslatorUtils.h" |
| #include "gpopt/translate/CMappingVarColId.h" |
| |
| #include "naucrates/dxl/CDXLUtils.h" |
| #include "naucrates/dxl/xml/dxltokens.h" |
| #include "naucrates/dxl/operators/CDXLNode.h" |
| #include "naucrates/dxl/gpdb_types.h" |
| |
| #include "naucrates/md/IMDScalarOp.h" |
| #include "naucrates/md/IMDRelation.h" |
| #include "naucrates/md/IMDIndex.h" |
| |
| #include "gpopt/gpdbwrappers.h" |
| |
| using namespace gpdxl; |
| using namespace gpos; |
| using namespace gpopt; |
| |
| #define DEFAULT_QUERY_LEVEL 0 |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::CTranslatorPlStmtToDXL |
| // |
| // @doc: |
| // Constructor |
| // |
| //--------------------------------------------------------------------------- |
| CTranslatorPlStmtToDXL::CTranslatorPlStmtToDXL |
| ( |
| IMemoryPool *pmp, |
| CMDAccessor *pmda, |
| CIdGenerator *pulIdGenerator, |
| PlannedStmt *pplstmt, |
| CMappingParamIdScalarId *pmapps |
| ) |
| : |
| m_pmp(pmp), |
| m_pmda(pmda), |
| m_pidgtor(pulIdGenerator), |
| m_pplstmt(pplstmt), |
| m_pparammapping(pmapps) |
| { |
| GPOS_ASSERT(NULL != m_pplstmt); |
| m_psctranslator = GPOS_NEW(m_pmp) |
| CTranslatorScalarToDXL |
| ( |
| m_pmp, |
| m_pmda, |
| pulIdGenerator, |
| NULL, // cte id generator |
| 0, // m_ulQueryLevel |
| false, // m_fQuery |
| m_pplstmt, |
| m_pparammapping, |
| NULL, // CTE Mapping |
| NULL // pdrgpdxlnCTE |
| ); |
| m_phmuldxlnSharedScanProjLists = GPOS_NEW(m_pmp) HMUlPdxln(m_pmp); |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::~CTranslatorPlStmtToDXL |
| // |
| // @doc: |
| // Destructor |
| // |
| //--------------------------------------------------------------------------- |
| CTranslatorPlStmtToDXL::~CTranslatorPlStmtToDXL() |
| { |
| m_phmuldxlnSharedScanProjLists->Release(); |
| GPOS_DELETE(m_psctranslator); |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnFromPlstmt |
| // |
| // @doc: |
| // Translates a PlannedStmt into a DXL tree. |
| // The function allocates memory in the translator memory pool, and the caller |
| // is responsible for freeing it. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnFromPlstmt |
| () |
| { |
| if (CMD_SELECT != m_pplstmt->commandType) |
| { |
| GPOS_RAISE |
| ( |
| gpdxl::ExmaDXL, |
| gpdxl::ExmiPlStmt2DXLConversion, |
| GPOS_WSZ_LIT("DML operations") |
| ); |
| } |
| |
| if (NULL != m_pplstmt->intoClause) |
| { |
| GPOS_RAISE |
| ( |
| gpdxl::ExmaDXL, |
| gpdxl::ExmiPlStmt2DXLConversion, |
| GPOS_WSZ_LIT("Select into") |
| ); |
| } |
| |
| return PdxlnFromPlan(m_pplstmt->planTree); |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnFromPlan |
| // |
| // @doc: |
| // Translates a Plan operator tree into a DXL tree. |
| // The function allocates memory in the translator memory pool, and the caller |
| // is responsible for freeing it. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnFromPlan |
| ( |
| const Plan *pplan |
| ) |
| { |
| GPOS_ASSERT(NULL != pplan); |
| |
| STranslatorElem rgTranslators[] = |
| { |
| {T_Scan, &CTranslatorPlStmtToDXL::PdxlnTblScanFromPlan}, |
| {T_IndexScan, &CTranslatorPlStmtToDXL::PdxlnIndexScanFromPlan}, |
| // {T_IndexOnlyScan, &CTranslatorPlStmtToDXL::PdxlnIndexOnlyScanFromPlan}, |
| {T_SeqScan, &CTranslatorPlStmtToDXL::PdxlnTblScanFromPlan}, |
| {T_HashJoin, &CTranslatorPlStmtToDXL::PdxlnHashjoinFromPlan}, |
| {T_Hash, &CTranslatorPlStmtToDXL::PdxlnHashFromPlan}, |
| {T_NestLoop, &CTranslatorPlStmtToDXL::PdxlnNLJoinFromPlan}, |
| {T_MergeJoin, &CTranslatorPlStmtToDXL::PdxlnMergeJoinFromPlan}, |
| {T_Motion, &CTranslatorPlStmtToDXL::PdxlnMotionFromPlan}, |
| {T_Limit, &CTranslatorPlStmtToDXL::PdxlnLimitFromPlan}, |
| {T_Agg, &CTranslatorPlStmtToDXL::PdxlnAggFromPlan}, |
| {T_Window, &CTranslatorPlStmtToDXL::PdxlnWindowFromPlan}, |
| {T_Unique, &CTranslatorPlStmtToDXL::PdxlnUniqueFromPlan}, |
| {T_Sort, &CTranslatorPlStmtToDXL::PdxlnSortFromPlan}, |
| {T_SubqueryScan, &CTranslatorPlStmtToDXL::PdxlnSubqueryScanFromPlan}, |
| {T_Append, &CTranslatorPlStmtToDXL::PdxlnAppendFromPlan}, |
| {T_Result, &CTranslatorPlStmtToDXL::PdxlnResultFromPlan}, |
| {T_Material, &CTranslatorPlStmtToDXL::PdxlnMaterializeFromPlan}, |
| {T_ShareInputScan, &CTranslatorPlStmtToDXL::PdxlnSharedScanFromPlan}, |
| {T_Sequence, &CTranslatorPlStmtToDXL::PdxlnSequence}, |
| {T_DynamicTableScan, &CTranslatorPlStmtToDXL::PdxlnDynamicTableScan}, |
| {T_FunctionScan, &CTranslatorPlStmtToDXL::PdxlnFunctionScanFromPlan}, |
| }; |
| |
| const ULONG ulTranslators = GPOS_ARRAY_SIZE(rgTranslators); |
| |
| NodeTag ent = pplan->type; |
| |
| // find translator for the expression type |
| PfPdxln pf = NULL; |
| for (ULONG ul = 0; ul < ulTranslators; ul++) |
| { |
| STranslatorElem elem = rgTranslators[ul]; |
| if (ent == elem.ent) |
| { |
| pf = elem.pf; |
| break; |
| } |
| } |
| |
| if (NULL == pf) |
| { |
| CHAR *sz = (CHAR*) gpdb::SzNodeToString(const_cast<Plan*>(pplan)); |
| CWStringDynamic *pstr = CDXLUtils::PstrFromSz(m_pmp, sz); |
| |
| GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiPlStmt2DXLConversion, pstr->Wsz()); |
| } |
| |
| return (this->*pf)(pplan); |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnHashFromPlan |
| // |
| // @doc: |
| // Create a DXL hash node from a GPDB hash plan node. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnHashFromPlan |
| ( |
| const Plan *pplan |
| ) |
| { |
| return PdxlnFromPlan(pplan->lefttree); |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnHashjoinFromPlan |
| // |
| // @doc: |
| // Create a DXL hash join node from a GPDB hash join plan node. |
| // The function allocates memory in the translator memory pool, and the caller |
| // is responsible for freeing it. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnHashjoinFromPlan |
| ( |
| const Plan *pplan |
| ) |
| { |
| GPOS_ASSERT(NULL != pplan); |
| GPOS_ASSERT(IsA(pplan, HashJoin)); |
| const HashJoin *phj = (HashJoin *) pplan; |
| |
| // extract plan properties |
| CDXLPhysicalProperties *pdxlprop = PdxlpropFromPlan(pplan); |
| |
| GPOS_ASSERT(NULL != pdxlprop); |
| |
| EdxlJoinType edxljt = CTranslatorUtils::EdxljtFromJoinType((phj->join).jointype); |
| |
| // construct hash join operator |
| CDXLPhysicalHashJoin *pdxlopHj = GPOS_NEW(m_pmp) CDXLPhysicalHashJoin(m_pmp, edxljt); |
| |
| // construct hash join operator node |
| CDXLNode *pdxlnHJ = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlopHj); |
| pdxlnHJ->SetProperties(pdxlprop); |
| |
| // translate left and right child |
| Plan *pplanLeft = outerPlan(phj); |
| Plan *pplanRight = innerPlan(phj); |
| |
| GPOS_ASSERT(NULL != pplanLeft); |
| GPOS_ASSERT(NULL != pplanRight); |
| |
| CDXLNode *pdxlnLeft = PdxlnFromPlan(pplanLeft); |
| CDXLNode *pdxlnRight = PdxlnFromPlan(pplanRight); |
| |
| GPOS_ASSERT(1 <= pdxlnLeft->UlArity()); |
| GPOS_ASSERT(1 <= pdxlnRight->UlArity()); |
| |
| // get left and right projection lists |
| CDXLNode *pdxlnPrLLeft = (*pdxlnLeft)[0]; |
| CDXLNode *pdxlnPrLRight = (*pdxlnRight)[0]; |
| |
| GPOS_ASSERT(pdxlnPrLLeft->Pdxlop()->Edxlop() == EdxlopScalarProjectList); |
| GPOS_ASSERT(pdxlnPrLRight->Pdxlop()->Edxlop() == EdxlopScalarProjectList); |
| |
| // translate hash condition |
| CDXLNode *pdxlnHashCondList = GPOS_NEW(m_pmp) CDXLNode(m_pmp, GPOS_NEW(m_pmp) CDXLScalarHashCondList(m_pmp)); |
| |
| List *plHashClauses = NIL; |
| |
| m_psctranslator->SetCallingPhysicalOpType(EpspotHashjoin); |
| |
| // if all hash conditions are equality tests, hashclauses contain them; |
| // if there are is not distinct from (INDF) tests, the conditions are in hashqualclauses |
| if (NIL != phj->hashqualclauses) |
| { |
| // there are INDF conditions |
| plHashClauses = phj->hashqualclauses; |
| } |
| else |
| { |
| // all clauses are equality checks |
| plHashClauses = phj->hashclauses; |
| } |
| |
| const ULONG ulLen = gpdb::UlListLength(plHashClauses); |
| for (ULONG ul = 0; ul < ulLen; ul++) |
| { |
| Expr *pexpr = (Expr *) gpdb::PvListNth(plHashClauses, ul); |
| |
| CMappingVarColId mapvarcolid(m_pmp); |
| |
| mapvarcolid.LoadProjectElements(DEFAULT_QUERY_LEVEL, OUTER, pdxlnPrLLeft); |
| |
| mapvarcolid.LoadProjectElements(DEFAULT_QUERY_LEVEL, INNER, pdxlnPrLRight); |
| |
| CDXLNode *pdxlnHashCond = m_psctranslator->PdxlnScOpFromExpr |
| ( |
| pexpr, |
| &mapvarcolid |
| ); |
| |
| pdxlnHashCondList->AddChild(pdxlnHashCond); |
| } |
| |
| // translate target list and additional join condition |
| CDXLNode *pdxlnPrL = NULL; |
| CDXLNode *pdxlnFilter = NULL; |
| |
| TranslateTListAndQual( |
| (phj->join).plan.targetlist, |
| (phj->join).plan.qual, |
| 0, //ulRTEIndex |
| NULL, //pdxltabdesc |
| NULL, //pmdindex |
| pdxlnPrLLeft, |
| pdxlnPrLRight, |
| &pdxlnPrL, |
| &pdxlnFilter |
| ); |
| |
| |
| GPOS_ASSERT(NULL != pdxlnPrL); |
| |
| CMappingVarColId mapvarcolid(m_pmp); |
| mapvarcolid.LoadProjectElements(DEFAULT_QUERY_LEVEL, OUTER, pdxlnPrLLeft); |
| |
| mapvarcolid.LoadProjectElements(DEFAULT_QUERY_LEVEL, INNER, pdxlnPrLRight); |
| |
| CDXLNode *pdxlnJoinFilter = m_psctranslator->PdxlnFilterFromQual |
| ( |
| (phj->join).joinqual, |
| &mapvarcolid, |
| EdxlopScalarJoinFilter |
| ); |
| |
| // add children in the right order |
| pdxlnHJ->AddChild(pdxlnPrL); // proj list |
| pdxlnHJ->AddChild(pdxlnFilter); // filter |
| pdxlnHJ->AddChild(pdxlnJoinFilter); // additional join filter |
| pdxlnHJ->AddChild(pdxlnHashCondList); // hash join condition |
| pdxlnHJ->AddChild(pdxlnLeft); // left child |
| pdxlnHJ->AddChild(pdxlnRight); // right child |
| |
| return pdxlnHJ; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnNLJoinFromPlan |
| // |
| // @doc: |
| // Create a DXL nested loop join node from a GPDB NestLoop plan node. |
| // The function allocates memory in the translator memory pool, and the caller |
| // is responsible for freeing it. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnNLJoinFromPlan |
| ( |
| const Plan *pplan |
| ) |
| { |
| GPOS_ASSERT(NULL != pplan); |
| GPOS_ASSERT(IsA(pplan, NestLoop)); |
| const NestLoop *pnlj = (NestLoop *) pplan; |
| |
| // extract plan properties |
| CDXLPhysicalProperties *pdxlprop = PdxlpropFromPlan(pplan); |
| |
| GPOS_ASSERT(NULL != pdxlprop); |
| |
| EdxlJoinType edxljt = CTranslatorUtils::EdxljtFromJoinType((pnlj->join).jointype); |
| |
| BOOL fIndexNLJ = IsA(pplan->righttree, IndexScan); |
| |
| // construct nested loop join operator |
| CDXLPhysicalNLJoin *pdxlnlj = GPOS_NEW(m_pmp) CDXLPhysicalNLJoin(m_pmp, edxljt, fIndexNLJ); |
| |
| // construct nested loop join operator node |
| CDXLNode *pdxlnNLJ = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlnlj); |
| pdxlnNLJ->SetProperties(pdxlprop); |
| |
| // translate left and right child |
| Plan *pplanLeft = outerPlan(pnlj); |
| Plan *pplanRight = innerPlan(pnlj); |
| |
| GPOS_ASSERT(NULL != pplanLeft); |
| GPOS_ASSERT(NULL != pplanRight); |
| |
| CDXLNode *pdxlnLeft = PdxlnFromPlan(pplanLeft); |
| CDXLNode *pdxlnRight = PdxlnFromPlan(pplanRight); |
| |
| GPOS_ASSERT(1 <= pdxlnLeft->UlArity()); |
| GPOS_ASSERT(1 <= pdxlnRight->UlArity()); |
| |
| // get left and right projection lists |
| CDXLNode *pdxlnPrLLeft = (*pdxlnLeft)[0]; |
| CDXLNode *pdxlnPrLRight = (*pdxlnRight)[0]; |
| |
| GPOS_ASSERT(pdxlnPrLLeft->Pdxlop()->Edxlop() == EdxlopScalarProjectList); |
| GPOS_ASSERT(pdxlnPrLRight->Pdxlop()->Edxlop() == EdxlopScalarProjectList); |
| |
| // translate target list and join filter |
| CDXLNode *pdxlnPrL = NULL; |
| CDXLNode *pdxlnFilter = NULL; |
| |
| m_psctranslator->SetCallingPhysicalOpType(EpspotNLJoin); |
| |
| TranslateTListAndQual( |
| (pnlj->join).plan.targetlist, |
| (pnlj->join).plan.qual, |
| 0, //ulRTEIndex |
| NULL, //pdxltabdesc |
| NULL, //pmdindex |
| pdxlnPrLLeft, |
| pdxlnPrLRight, |
| &pdxlnPrL, |
| &pdxlnFilter |
| ); |
| |
| CMappingVarColId mapvarcolid(m_pmp); |
| mapvarcolid.LoadProjectElements(DEFAULT_QUERY_LEVEL, OUTER, pdxlnPrLLeft); |
| mapvarcolid.LoadProjectElements(DEFAULT_QUERY_LEVEL, INNER, pdxlnPrLRight); |
| |
| CDXLNode *pdxlnJoinFilter = m_psctranslator->PdxlnFilterFromQual((pnlj->join).joinqual, &mapvarcolid, EdxlopScalarJoinFilter); |
| |
| // add children in the right order |
| pdxlnNLJ->AddChild(pdxlnPrL); // proj list |
| pdxlnNLJ->AddChild(pdxlnFilter); // plan filter |
| pdxlnNLJ->AddChild(pdxlnJoinFilter); // additional join filter |
| pdxlnNLJ->AddChild(pdxlnLeft); // left child |
| pdxlnNLJ->AddChild(pdxlnRight); // right child |
| |
| return pdxlnNLJ; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnMergeJoinFromPlan |
| // |
| // @doc: |
| // Create a DXL merge join node from a GPDB merge join plan node. |
| // The function allocates memory in the translator memory pool, and the caller |
| // is responsible for freeing it. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnMergeJoinFromPlan |
| ( |
| const Plan *pplan |
| ) |
| { |
| GPOS_ASSERT(NULL != pplan); |
| GPOS_ASSERT(IsA(pplan, MergeJoin)); |
| const MergeJoin *pmj = (MergeJoin *) pplan; |
| |
| // extract plan properties |
| CDXLPhysicalProperties *pdxlprop = PdxlpropFromPlan(pplan); |
| |
| GPOS_ASSERT(NULL != pdxlprop); |
| |
| EdxlJoinType edxljt = CTranslatorUtils::EdxljtFromJoinType((pmj->join).jointype); |
| |
| // construct hash join operator |
| CDXLPhysicalMergeJoin *pdxlopMj = GPOS_NEW(m_pmp) CDXLPhysicalMergeJoin(m_pmp, edxljt, pmj->unique_outer); |
| |
| // construct merge join operator node |
| CDXLNode *pdxlnMJ = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlopMj); |
| pdxlnMJ->SetProperties(pdxlprop); |
| |
| // translate left and right child |
| Plan *pplanLeft = outerPlan(pmj); |
| Plan *pplanRight = innerPlan(pmj); |
| |
| GPOS_ASSERT(NULL != pplanLeft); |
| GPOS_ASSERT(NULL != pplanRight); |
| |
| CDXLNode *pdxlnLeft = PdxlnFromPlan(pplanLeft); |
| CDXLNode *pdxlnRight = PdxlnFromPlan(pplanRight); |
| |
| GPOS_ASSERT(1 <= pdxlnLeft->UlArity()); |
| GPOS_ASSERT(1 <= pdxlnRight->UlArity()); |
| |
| // get left and right projection lists |
| CDXLNode *pdxlnPrLLeft = (*pdxlnLeft)[0]; |
| CDXLNode *pdxlnPrLRight = (*pdxlnRight)[0]; |
| |
| GPOS_ASSERT(pdxlnPrLLeft->Pdxlop()->Edxlop() == EdxlopScalarProjectList); |
| GPOS_ASSERT(pdxlnPrLRight->Pdxlop()->Edxlop() == EdxlopScalarProjectList); |
| |
| // translate hash condition |
| CDXLNode *pdxlnMergeCondList = GPOS_NEW(m_pmp) CDXLNode(m_pmp, GPOS_NEW(m_pmp) CDXLScalarMergeCondList(m_pmp)); |
| |
| m_psctranslator->SetCallingPhysicalOpType(EpspotMergeJoin); |
| |
| List *plMergeClauses = pmj->mergeclauses; |
| |
| const ULONG ulLength = (ULONG) gpdb::UlListLength(plMergeClauses); |
| for (ULONG ul = 0; ul < ulLength; ul++) |
| { |
| Expr *pexpr = (Expr *) gpdb::PvListNth(plMergeClauses, ul); |
| |
| CMappingVarColId mapvarcolid(m_pmp); |
| mapvarcolid.LoadProjectElements(DEFAULT_QUERY_LEVEL, OUTER, pdxlnPrLLeft); |
| mapvarcolid.LoadProjectElements(DEFAULT_QUERY_LEVEL, INNER, pdxlnPrLRight); |
| |
| CDXLNode *pdxlnMergeCond = m_psctranslator->PdxlnScOpFromExpr |
| ( |
| pexpr, |
| &mapvarcolid |
| ); |
| |
| pdxlnMergeCondList->AddChild(pdxlnMergeCond); |
| } |
| |
| // translate target list and additional join condition |
| CDXLNode *pdxlnPrL = NULL; |
| |
| CDXLNode *pdxlnFilter = NULL; |
| |
| TranslateTListAndQual( |
| (pmj->join).plan.targetlist, |
| (pmj->join).plan.qual, |
| 0, //ulRTEIndex |
| NULL, //pdxltabdesc |
| NULL, //pmdindex |
| pdxlnPrLLeft, |
| pdxlnPrLRight, |
| &pdxlnPrL, |
| &pdxlnFilter |
| ); |
| |
| |
| GPOS_ASSERT(NULL != pdxlnPrL); |
| |
| CMappingVarColId mapvarcolid(m_pmp); |
| mapvarcolid.LoadProjectElements(DEFAULT_QUERY_LEVEL, OUTER, pdxlnPrLLeft); |
| mapvarcolid.LoadProjectElements(DEFAULT_QUERY_LEVEL, INNER, pdxlnPrLRight); |
| |
| CDXLNode *pdxlnJoinFilter = m_psctranslator->PdxlnFilterFromQual |
| ( |
| (pmj->join).joinqual, |
| &mapvarcolid, |
| EdxlopScalarJoinFilter |
| ); |
| |
| // add children in the right order |
| pdxlnMJ->AddChild(pdxlnPrL); // proj list |
| pdxlnMJ->AddChild(pdxlnFilter); // filter |
| pdxlnMJ->AddChild(pdxlnJoinFilter); // additional join filter |
| pdxlnMJ->AddChild(pdxlnMergeCondList); // merge join condition |
| pdxlnMJ->AddChild(pdxlnLeft); // left child |
| pdxlnMJ->AddChild(pdxlnRight); // right child |
| |
| return pdxlnMJ; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnResultFromPlan |
| // |
| // @doc: |
| // Create a DXL result node from a GPDB result node. |
| // The function allocates memory in the translator memory pool, and the caller |
| // is responsible for freeing it. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnResultFromPlan |
| ( |
| const Plan *pplan |
| ) |
| { |
| GPOS_ASSERT(NULL != pplan); |
| GPOS_ASSERT(IsA(pplan, Result)); |
| const Result *pnresult = (Result *) pplan; |
| |
| // extract plan properties |
| CDXLPhysicalProperties *pdxlprop = PdxlpropFromPlan(pplan); |
| |
| GPOS_ASSERT(NULL != pdxlprop); |
| |
| // construct result operator |
| CDXLPhysicalResult *pdxlopResult = GPOS_NEW(m_pmp) CDXLPhysicalResult(m_pmp); |
| |
| GPOS_ASSERT(innerPlan(pnresult) == NULL && "Result node cannot have right child"); |
| |
| // translate child if there is one |
| Plan *pplanChild = outerPlan(pnresult); |
| CDXLNode *pdxlnChild = NULL; |
| CDXLNode *pdxlnPrLChild = NULL; |
| |
| if (NULL != pplanChild) |
| { |
| pdxlnChild = PdxlnFromPlan(pplanChild); |
| GPOS_ASSERT(1 <= pdxlnChild->UlArity()); |
| |
| // get child's projection lists |
| pdxlnPrLChild = (*pdxlnChild)[0]; |
| GPOS_ASSERT(pdxlnPrLChild->Pdxlop()->Edxlop() == EdxlopScalarProjectList); |
| } |
| |
| // translate target list and filters |
| CDXLNode *pdxlnPrL = NULL; |
| CDXLNode *pdxlnFilter = NULL; |
| |
| // assert that resconstantqual is actually a list |
| GPOS_ASSERT_IMP(NULL != pnresult->resconstantqual, nodeTag(pnresult->resconstantqual) == T_List); |
| |
| m_psctranslator->SetCallingPhysicalOpType(EpspotResult); |
| |
| TranslateTListAndQual |
| ( |
| (pnresult->plan).targetlist, |
| (pnresult->plan).qual, |
| 0, //ulRTEIndex |
| NULL, |
| NULL, //pmdindex |
| pdxlnPrLChild, |
| NULL, |
| &pdxlnPrL, |
| &pdxlnFilter |
| ); |
| |
| CMappingVarColId mapvarcolid(m_pmp); |
| mapvarcolid.LoadProjectElements(DEFAULT_QUERY_LEVEL, OUTER, pdxlnPrL); |
| |
| CDXLNode *pdxlnOneTimeFilter = m_psctranslator->PdxlnFilterFromQual |
| ( |
| (List *) (pnresult->resconstantqual), |
| &mapvarcolid, |
| EdxlopScalarOneTimeFilter |
| ); |
| |
| // construct motion operator node |
| CDXLNode *pdxln = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlopResult); |
| pdxln->SetProperties(pdxlprop); |
| |
| // add children in the right order |
| pdxln->AddChild(pdxlnPrL); // proj list |
| pdxln->AddChild(pdxlnFilter); // plan filter |
| pdxln->AddChild(pdxlnOneTimeFilter); // one time filter |
| |
| if (NULL != pdxlnChild) |
| { |
| pdxln->AddChild(pdxlnChild); |
| } |
| |
| return pdxln; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnMotionFromPlan |
| // |
| // @doc: |
| // Create a DXL motion node from a GPDB Motion plan node. |
| // The function allocates memory in the translator memory pool, and the caller |
| // is responsible for freeing it. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnMotionFromPlan |
| ( |
| const Plan *pplan |
| ) |
| { |
| GPOS_ASSERT(NULL != pplan); |
| GPOS_ASSERT(IsA(pplan, Motion)); |
| const Motion *pmotion = (Motion *) pplan; |
| |
| CDXLPhysicalMotion *pdxlopMotion = NULL; |
| |
| // extract plan properties |
| CDXLPhysicalProperties *pdxlprop = PdxlpropFromPlan(pplan); |
| |
| GPOS_ASSERT(NULL != pdxlprop); |
| |
| // construct DXL motion operator |
| GPOS_ASSERT(MOTIONTYPE_FIXED == pmotion->motionType || |
| MOTIONTYPE_HASH == pmotion->motionType); |
| |
| if (MOTIONTYPE_FIXED == pmotion->motionType) |
| { |
| if (0 == pmotion->numOutputSegs) |
| { |
| pdxlopMotion = GPOS_NEW(m_pmp) CDXLPhysicalBroadcastMotion(m_pmp); |
| } |
| else |
| { |
| pdxlopMotion = GPOS_NEW(m_pmp) CDXLPhysicalGatherMotion(m_pmp); |
| } |
| } |
| else |
| { |
| pdxlopMotion = GPOS_NEW(m_pmp) CDXLPhysicalRedistributeMotion(m_pmp, false /*fDuplicateSensitive*/); |
| } |
| |
| DrgPi *pdrgpiInputSegIds = GPOS_NEW(m_pmp) DrgPi(m_pmp); |
| DrgPi *pdrgpiOutputSegIds = GPOS_NEW(m_pmp) DrgPi(m_pmp); |
| |
| TranslateMotionSegmentInfo(pmotion, pdrgpiInputSegIds, pdrgpiOutputSegIds); |
| |
| pdxlopMotion->SetInputSegIds(pdrgpiInputSegIds); |
| pdxlopMotion->SetOutputSegIds(pdrgpiOutputSegIds); |
| |
| // construct motion operator node |
| CDXLNode *pdxln = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlopMotion); |
| pdxln->SetProperties(pdxlprop); |
| |
| // translate child of motion node |
| Plan *pplanChild = (pmotion->plan).lefttree; |
| |
| GPOS_ASSERT(NULL != pplanChild); |
| |
| CDXLNode *pdxlnChild = PdxlnFromPlan(pplanChild); |
| |
| GPOS_ASSERT(1 <= pdxlnChild->UlArity()); |
| |
| // get child projection lists |
| CDXLNode *pdxlnPrLChild = (*pdxlnChild)[0]; |
| |
| GPOS_ASSERT(pdxlnPrLChild->Pdxlop()->Edxlop() == EdxlopScalarProjectList); |
| |
| // construct projection list and filter |
| CDXLNode *pdxlnPrL = NULL; |
| CDXLNode *pdxlnFilter = NULL; |
| |
| m_psctranslator->SetCallingPhysicalOpType(EpspotMotion); |
| |
| TranslateTListAndQual( |
| (pmotion->plan).targetlist, |
| (pmotion->plan).qual, |
| 0, //ulRTEIndex |
| NULL, //pdxltabdesc |
| NULL, //pmdindex |
| pdxlnPrLChild, |
| NULL, //pdxlnPrLRight |
| &pdxlnPrL, |
| &pdxlnFilter |
| ); |
| |
| // construct sorting column info |
| CDXLNode *pdxlnSortColList = PdxlnSortingColListFromPlan(pmotion->sortColIdx, pmotion->sortOperators, pmotion->numSortCols, pdxlnPrL); |
| |
| // add children in the right order |
| pdxln->AddChild(pdxlnPrL); // proj list |
| pdxln->AddChild(pdxlnFilter); // filter |
| pdxln->AddChild(pdxlnSortColList); // sorting column list |
| |
| if (pdxlopMotion->Edxlop() == EdxlopPhysicalMotionRedistribute) |
| { |
| // redistribute is a motion: translate hash expr list |
| CDXLNode *pdxlnHashExprList = PdxlnHashExprLFromList |
| ( |
| pmotion->hashExpr, |
| pmotion->hashDataTypes, |
| pdxlnPrLChild |
| ); |
| |
| pdxln->AddChild(pdxlnHashExprList); |
| } |
| |
| pdxln->AddChild(pdxlnChild); // child |
| |
| return pdxln; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnAggFromPlan |
| // |
| // @doc: |
| // Create a DXL aggregate node from a GPDB Agg plan node. |
| // The function allocates memory in the translator memory pool, and the caller |
| // is responsible for freeing it. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnAggFromPlan |
| ( |
| const Plan *pplan |
| ) |
| { |
| GPOS_ASSERT(NULL != pplan); |
| GPOS_ASSERT(IsA(pplan, Agg)); |
| const Agg *pagg = (Agg *) pplan; |
| |
| // extract plan properties |
| CDXLPhysicalProperties *pdxlprop = PdxlpropFromPlan(pplan); |
| |
| GPOS_ASSERT(NULL != pdxlprop); |
| |
| // construct DXL aggregate operator |
| EdxlAggStrategy edxlaggstr = EdxlaggstrategySentinel; |
| switch (pagg->aggstrategy) |
| { |
| case AGG_PLAIN: |
| edxlaggstr = EdxlaggstrategyPlain; |
| break; |
| case AGG_SORTED: |
| edxlaggstr = EdxlaggstrategySorted; |
| break; |
| case AGG_HASHED: |
| edxlaggstr = EdxlaggstrategyHashed; |
| break; |
| default: |
| GPOS_ASSERT(!"Invalid aggregation strategy"); |
| } |
| |
| BOOL fStreamSafe = pagg->streaming; |
| CDXLPhysicalAgg *pdxlopAgg = GPOS_NEW(m_pmp) CDXLPhysicalAgg(m_pmp, edxlaggstr, fStreamSafe); |
| |
| // translate child of aggregate operator |
| Plan *pplanChild = (pagg->plan).lefttree; |
| GPOS_ASSERT(NULL != pplanChild); |
| CDXLNode *pdxlnChild = PdxlnFromPlan(pplanChild); |
| |
| #ifdef GPOS_DEBUG |
| pdxlnChild->Pdxlop()->AssertValid(pdxlnChild, false /* fValidateChildren */); |
| #endif |
| |
| // get child projection lists |
| CDXLNode *pdxlnPrLChild = (*pdxlnChild)[0]; |
| |
| // construct projection list and filter |
| CDXLNode *pdxlnPrL = NULL; |
| CDXLNode *pdxlnFilter = NULL; |
| |
| m_psctranslator->SetCallingPhysicalOpType(EpspotAgg); |
| |
| TranslateTListAndQual( |
| (pagg->plan).targetlist, |
| (pagg->plan).qual, |
| 0, //ulRTEIndex |
| NULL, //pdxltabdesc |
| NULL, //pmdindex |
| pdxlnPrLChild, |
| NULL, //pdxlnPrLRight |
| &pdxlnPrL, |
| &pdxlnFilter |
| ); |
| |
| // translate grouping column list |
| GPOS_ASSERT( (0 == pagg->numCols && NULL == pagg->grpColIdx) || |
| (0 < pagg->numCols && NULL != pagg->grpColIdx)); |
| |
| // translate output segment cols |
| DrgPul *pdrgpulGroupingCols = GPOS_NEW(m_pmp) DrgPul(m_pmp); |
| |
| for(ULONG ul = 0; ul < (ULONG) pagg->numCols; ul++) |
| { |
| ULONG ulColIdx = pagg->grpColIdx[ul]; |
| |
| // find grouping column in the project list of the child node |
| CDXLNode *pdxlnGroupingCol = (*pdxlnPrLChild)[ulColIdx-1]; |
| CDXLScalarProjElem *pdxlopPrEl = (CDXLScalarProjElem *) pdxlnGroupingCol->Pdxlop(); |
| |
| ULONG *pulGroupingColId = GPOS_NEW(m_pmp) ULONG(pdxlopPrEl->UlId()); |
| pdrgpulGroupingCols->Append(pulGroupingColId); |
| } |
| |
| pdxlopAgg->SetGroupingCols(pdrgpulGroupingCols); |
| |
| // construct aggregate operator node |
| CDXLNode *pdxln = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlopAgg); |
| pdxln->SetProperties(pdxlprop); |
| |
| // add children in the right order |
| pdxln->AddChild(pdxlnPrL); // proj list |
| pdxln->AddChild(pdxlnFilter); // filter |
| pdxln->AddChild(pdxlnChild); // child |
| |
| return pdxln; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnWindowFromPlan |
| // |
| // @doc: |
| // Create a DXL window node from a GPDB window plan node. |
| // The function allocates memory in the translator memory pool, |
| // and the caller is responsible for freeing it. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnWindowFromPlan |
| ( |
| const Plan *pplan |
| ) |
| { |
| GPOS_ASSERT(NULL != pplan); |
| GPOS_ASSERT(IsA(pplan, Window)); |
| const Window *pwindow = (Window *) pplan; |
| |
| // translate child of window operator |
| Plan *pplanChild = (pwindow->plan).lefttree; |
| GPOS_ASSERT(NULL != pplanChild); |
| CDXLNode *pdxlnChild = PdxlnFromPlan(pplanChild); |
| |
| #ifdef GPOS_DEBUG |
| pdxlnChild->Pdxlop()->AssertValid(pdxlnChild, false /* fValidateChildren */); |
| #endif |
| |
| // get child projection lists |
| CDXLNode *pdxlnPrLChild = (*pdxlnChild)[0]; |
| |
| // construct projection list and filter |
| CDXLNode *pdxlnPrL = NULL; |
| CDXLNode *pdxlnFilter = NULL; |
| |
| m_psctranslator->SetCallingPhysicalOpType(EpspotWindow); |
| |
| TranslateTListAndQual |
| ( |
| (pwindow->plan).targetlist, |
| (pwindow->plan).qual, |
| 0, //ulRTEIndex |
| NULL, //pdxltabdesc |
| NULL, //pmdindex |
| pdxlnPrLChild, |
| NULL, //pdxlnPrLRight |
| &pdxlnPrL, |
| &pdxlnFilter |
| ); |
| |
| const ULONG ulSize = (ULONG) pwindow->numPartCols; |
| // translate partition columns |
| DrgPul *pdrgpulPartCols = GPOS_NEW(m_pmp) DrgPul(m_pmp); |
| for(ULONG ul = 0; ul < ulSize; ul++) |
| { |
| ULONG ulColIdx = (ULONG) pwindow->partColIdx[ul]; |
| |
| // find partition column in the project list of the child node |
| CDXLNode *pdxlnPartCol = (*pdxlnPrLChild)[ulColIdx-1]; |
| CDXLScalarProjElem *pdxlopPrEl = (CDXLScalarProjElem *) pdxlnPartCol->Pdxlop(); |
| |
| ULONG *pulPartColId = GPOS_NEW(m_pmp) ULONG(pdxlopPrEl->UlId()); |
| pdrgpulPartCols->Append(pulPartColId); |
| } |
| |
| // add the window keys |
| DrgPdxlwk *pdrgpdxlwk = GPOS_NEW(m_pmp) DrgPdxlwk(m_pmp); |
| ListCell *plcWindowKey = NULL; |
| ForEach (plcWindowKey, pwindow->windowKeys) |
| { |
| WindowKey *pwindowkey = (WindowKey *) lfirst(plcWindowKey); |
| CDXLWindowKey *pdxlWindowKey = GPOS_NEW(m_pmp) CDXLWindowKey(m_pmp); |
| |
| CDXLNode *pdxlnSortColList = PdxlnSortingColListFromPlan |
| ( |
| pwindowkey->sortColIdx, |
| pwindowkey->sortOperators, |
| pwindowkey->numSortCols, |
| pdxlnPrLChild |
| ); |
| |
| pdxlWindowKey->SetSortColList(pdxlnSortColList); |
| |
| if (NULL != pwindowkey->frame) |
| { |
| CMappingVarColId mapvarcolid(m_pmp); |
| mapvarcolid.LoadProjectElements(DEFAULT_QUERY_LEVEL, OUTER, pdxlnPrLChild); |
| |
| CDXLWindowFrame *pdxlwf = m_psctranslator->Pdxlwf |
| ( |
| (Expr *) pwindowkey->frame, |
| &mapvarcolid, |
| NULL |
| ); |
| pdxlWindowKey->SetWindowFrame(pdxlwf); |
| } |
| pdrgpdxlwk->Append(pdxlWindowKey); |
| } |
| |
| // construct window operator node |
| CDXLPhysicalWindow *pdxlopWindow = GPOS_NEW(m_pmp) CDXLPhysicalWindow(m_pmp, pdrgpulPartCols, pdrgpdxlwk); |
| CDXLNode *pdxln = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlopWindow); |
| |
| // extract plan properties |
| CDXLPhysicalProperties *pdxlprop = PdxlpropFromPlan(pplan); |
| GPOS_ASSERT(NULL != pdxlprop); |
| pdxln->SetProperties(pdxlprop); |
| |
| // add children in the right order |
| pdxln->AddChild(pdxlnPrL); // proj list |
| pdxln->AddChild(pdxlnFilter); // filter |
| pdxln->AddChild(pdxlnChild); // child |
| |
| return pdxln; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CPlStmtTranslator::PdxlnAggFromPlan |
| // |
| // @doc: |
| // Create a DXL Aggregate node from a GPDB Unique plan node. |
| // We do not support a separate Unique node in DXL. Instead, we convert the |
| // Unique operator into an Aggregate node, which groups on the unique columns. |
| // |
| // The function allocates memory in the translator memory pool, and the caller |
| // is responsible for freeing it. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnUniqueFromPlan |
| ( |
| const Plan *pplan |
| ) |
| { |
| GPOS_ASSERT(NULL != pplan); |
| GPOS_ASSERT(IsA(pplan, Unique)); |
| const Unique *punique = (Unique *) pplan; |
| |
| Agg *pagg = MakeNode(Agg); |
| Plan *pplanAgg = &(pagg->plan); |
| const Plan *pplanUnique = &(punique->plan); |
| |
| // copy basic plan properties |
| pplanAgg->plan_node_id = pplanUnique->plan_node_id; |
| pplanAgg->plan_parent_node_id = pplanUnique->plan_parent_node_id; |
| |
| pplanAgg->startup_cost = pplanUnique->startup_cost; |
| pplanAgg->total_cost = pplanUnique->total_cost; |
| pplanAgg->plan_rows = pplanUnique->plan_rows; |
| pplanAgg->plan_width = pplanUnique->plan_width; |
| |
| pplanAgg->nMotionNodes = pplanUnique->nMotionNodes; |
| |
| pplanAgg->targetlist = pplanUnique->targetlist; |
| pplanAgg->qual = pplanUnique->qual; |
| |
| pplanAgg->lefttree = pplanUnique->lefttree; |
| |
| // copy unique-specific fields |
| // execution of unique always assumes sorted input |
| pagg->aggstrategy = AGG_SORTED; |
| |
| pagg->grpColIdx = punique->uniqColIdx; |
| pagg->numCols = punique->numCols; |
| |
| return PdxlnAggFromPlan((Plan *)pagg); |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnSortFromPlan |
| // |
| // @doc: |
| // Create a DXL sort node from a GPDB Sort plan node. |
| // The function allocates memory in the translator memory pool, and the caller |
| // is responsible for freeing it. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnSortFromPlan |
| ( |
| const Plan *pplan |
| ) |
| { |
| GPOS_ASSERT(NULL != pplan); |
| GPOS_ASSERT(IsA(pplan, Sort)); |
| const Sort *psort = (Sort *) pplan; |
| |
| // extract plan properties |
| CDXLPhysicalProperties *pdxlprop = PdxlpropFromPlan(pplan); |
| |
| GPOS_ASSERT(NULL != pdxlprop); |
| |
| // construct DXL sort operator |
| // TODO: antovl - Jan 19, 2011; currently GPDB supports only nullsLast behavior |
| GPOS_ASSERT(NULL == psort->nullsFirst); |
| |
| CDXLPhysicalSort *pdxlopSort = GPOS_NEW(m_pmp) CDXLPhysicalSort(m_pmp, psort->noduplicates); |
| |
| // translate child of sort operator |
| Plan *pplanChild = (psort->plan).lefttree; |
| GPOS_ASSERT(NULL != pplanChild); |
| CDXLNode *pdxlnChild = PdxlnFromPlan(pplanChild); |
| |
| #ifdef GPOS_DEBUG |
| pdxlnChild->Pdxlop()->AssertValid(pdxlnChild, false /* fValidateChildren */); |
| #endif |
| |
| // get child projection lists |
| CDXLNode *pdxlnPrLChild = (*pdxlnChild)[0]; |
| |
| // construct projection list and filter |
| CDXLNode *pdxlnPrL = NULL; |
| CDXLNode *pdxlnFilter = NULL; |
| |
| m_psctranslator->SetCallingPhysicalOpType(EpspotSort); |
| |
| TranslateTListAndQual( |
| (psort->plan).targetlist, |
| (psort->plan).qual, |
| 0, //ulRTEIndex |
| NULL, //pdxltabdesc |
| NULL, //pmdindex |
| pdxlnPrLChild, |
| NULL, //pdxlnPrLRight |
| &pdxlnPrL, |
| &pdxlnFilter |
| ); |
| |
| // translate sorting column list |
| GPOS_ASSERT(0 < psort->numCols && NULL!= psort->sortColIdx); |
| |
| CDXLNode *pdxlnSortColList = PdxlnSortingColListFromPlan(psort->sortColIdx, psort->sortOperators, psort->numCols, pdxlnPrLChild); |
| |
| // translate limit information |
| |
| CDXLNode *pdxlnLimitCount = GPOS_NEW(m_pmp) CDXLNode(m_pmp, GPOS_NEW(m_pmp) CDXLScalarLimitCount(m_pmp)); |
| CDXLNode *pdxlnLimitOffset = GPOS_NEW(m_pmp) CDXLNode(m_pmp, GPOS_NEW(m_pmp) CDXLScalarLimitOffset(m_pmp)); |
| |
| if (NULL != psort->limitCount) |
| { |
| CMappingVarColId mapvarcolid(m_pmp); |
| mapvarcolid.LoadProjectElements(DEFAULT_QUERY_LEVEL, OUTER, pdxlnPrLChild); |
| pdxlnLimitCount->AddChild(m_psctranslator->PdxlnScOpFromExpr |
| ( |
| (Expr *) (psort->limitCount), |
| &mapvarcolid |
| ) |
| ); |
| } |
| |
| if (NULL != psort->limitOffset) |
| { |
| CMappingVarColId mapvarcolid(m_pmp); |
| mapvarcolid.LoadProjectElements(DEFAULT_QUERY_LEVEL, OUTER, pdxlnPrLChild); |
| |
| pdxlnLimitOffset->AddChild |
| ( |
| m_psctranslator->PdxlnScOpFromExpr |
| ( |
| (Expr *) (psort->limitOffset), |
| &mapvarcolid |
| ) |
| ); |
| } |
| |
| |
| // construct sort operator node |
| CDXLNode *pdxln = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlopSort); |
| pdxln->SetProperties(pdxlprop); |
| |
| // add children in the right order |
| pdxln->AddChild(pdxlnPrL); // proj list |
| pdxln->AddChild(pdxlnFilter); // filter |
| pdxln->AddChild(pdxlnSortColList); // sorting columns |
| pdxln->AddChild(pdxlnLimitCount); // limit count |
| pdxln->AddChild(pdxlnLimitOffset); // limit offset |
| pdxln->AddChild(pdxlnChild); // child |
| |
| return pdxln; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnSubqueryScanFromPlan |
| // |
| // @doc: |
| // Create a DXL SubqueryScan node from a GPDB SubqueryScan plan node. |
| // The function allocates memory in the translator memory pool, and the caller |
| // is responsible for freeing it. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnSubqueryScanFromPlan |
| ( |
| const Plan *pplan |
| ) |
| { |
| GPOS_ASSERT(NULL != pplan); |
| GPOS_ASSERT(IsA(pplan, SubqueryScan)); |
| const SubqueryScan *psubqscan = (SubqueryScan *) pplan; |
| |
| // extract plan properties |
| CDXLPhysicalProperties *pdxlprop = PdxlpropFromPlan(pplan); |
| |
| GPOS_ASSERT(NULL != pdxlprop); |
| |
| // get name for the subquery scan node from the range table |
| RangeTblEntry *prte = (RangeTblEntry *) gpdb::PvListNth(m_pplstmt->rtable, (psubqscan->scan).scanrelid - 1); |
| CHAR *szSubqName = prte->eref->aliasname; |
| |
| CWStringDynamic *pstrSubqName = CDXLUtils::PstrFromSz(m_pmp, szSubqName); |
| // copy table name |
| CMDName *pmdnameSubqScan = GPOS_NEW(m_pmp) CMDName(m_pmp, pstrSubqName); |
| GPOS_DELETE(pstrSubqName); |
| |
| // construct DXL subquery scan operator |
| CDXLPhysicalSubqueryScan *pdxlopSubqScan = GPOS_NEW(m_pmp) CDXLPhysicalSubqueryScan(m_pmp, pmdnameSubqScan); |
| |
| // translate child of subquery operator |
| Plan *pplanChild = psubqscan->subplan; |
| GPOS_ASSERT(NULL != pplanChild); |
| CDXLNode *pdxlnChild = PdxlnFromPlan(pplanChild); |
| |
| #ifdef GPOS_DEBUG |
| pdxlnChild->Pdxlop()->AssertValid(pdxlnChild, false /* fValidateChildren */); |
| #endif |
| |
| // get child projection lists |
| CDXLNode *pdxlnPrLChild = (*pdxlnChild)[0]; |
| |
| // construct a fake table descriptor for the subquery scan |
| // since the project list and filter refer to the rtable rather than OUTER |
| // construct projection list and filter |
| CDXLTableDescr *pdxltabdesc = GPOS_NEW(m_pmp) CDXLTableDescr |
| ( |
| m_pmp, |
| GPOS_NEW(m_pmp) CMDIdGPDB(CMDIdGPDB::m_mdidInvalidKey.OidObjectId()), |
| GPOS_NEW(m_pmp) CMDName(pmdnameSubqScan->Pstr()), |
| prte->checkAsUser |
| ); |
| |
| ListCell *plcCol = NULL; |
| ULONG ulAttno = 1; |
| |
| // add columns from RangeTableEntry to table descriptor |
| ForEach (plcCol, prte->eref->colnames) |
| { |
| Value *pvalue = (Value *) lfirst(plcCol); |
| CHAR *szColName = strVal(pvalue); |
| |
| BOOL fColDropped = false; |
| |
| if ('\0' == szColName[0]) |
| { |
| fColDropped = true; |
| } |
| |
| // column is not dropped |
| CWStringDynamic *pstrColName = CDXLUtils::PstrFromSz(m_pmp, szColName); |
| |
| // copy string into column name |
| CMDName *pmdnameColName = GPOS_NEW(m_pmp) CMDName(m_pmp, pstrColName); |
| |
| GPOS_DELETE(pstrColName); |
| |
| // get column id from the subplan's target list |
| CDXLNode *pdxlnPrEl = (*pdxlnPrLChild)[ulAttno-1]; |
| ULONG ulId = ((CDXLScalarProjElem *) pdxlnPrEl->Pdxlop())->UlId(); |
| |
| // create a column descriptor for the column |
| CDXLColDescr *pdxlcd = GPOS_NEW(m_pmp) CDXLColDescr |
| ( |
| m_pmp, |
| pmdnameColName, |
| ulId, |
| ulAttno, |
| GPOS_NEW(m_pmp) CMDIdGPDB(CMDIdGPDB::m_mdidInvalidKey.OidObjectId()), |
| fColDropped |
| ); |
| |
| pdxltabdesc->AddColumnDescr(pdxlcd); |
| |
| ulAttno++; |
| } |
| |
| CDXLNode *pdxlnPrL = NULL; |
| CDXLNode *pdxlnFilter = NULL; |
| |
| m_psctranslator->SetCallingPhysicalOpType(EpspotSubqueryScan); |
| |
| TranslateTListAndQual( |
| (psubqscan->scan.plan).targetlist, |
| (psubqscan->scan.plan).qual, |
| ULONG((psubqscan->scan).scanrelid), |
| pdxltabdesc, |
| NULL, // pmdindex |
| NULL, // pdxlnPrLChild |
| NULL, //pdxlnPrLRight |
| &pdxlnPrL, |
| &pdxlnFilter |
| ); |
| |
| // construct sort operator node |
| CDXLNode *pdxln = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlopSubqScan); |
| pdxln->SetProperties(pdxlprop); |
| |
| // add children in the right order |
| pdxln->AddChild(pdxlnPrL); // proj list |
| pdxln->AddChild(pdxlnFilter); // filter |
| pdxln->AddChild(pdxlnChild); // child |
| |
| // cleanup |
| pdxltabdesc->Release(); |
| |
| return pdxln; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnAppendFromPlan |
| // |
| // @doc: |
| // Create a DXL Append node from a GPDB Append plan node. |
| // The function allocates memory in the translator memory pool, and the caller |
| // is responsible for freeing it. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnAppendFromPlan |
| ( |
| const Plan *pplan |
| ) |
| { |
| GPOS_ASSERT(NULL != pplan); |
| GPOS_ASSERT(IsA(pplan, Append)); |
| const Append *pappend = (Append *) pplan; |
| |
| GPOS_ASSERT(NULL != pappend->appendplans); |
| |
| // extract plan properties |
| CDXLPhysicalProperties *pdxlprop = PdxlpropFromPlan(pplan); |
| |
| |
| GPOS_ASSERT(NULL != pdxlprop); |
| |
| // construct DXL Append operator |
| CDXLPhysicalAppend *pdxlopAppend = GPOS_NEW(m_pmp) CDXLPhysicalAppend(m_pmp, pappend->isTarget, pappend->isZapped); |
| |
| CDXLNode *pdxln = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlopAppend); |
| pdxln->SetProperties(pdxlprop); |
| |
| // translate first child of append operator so we can translate the project list |
| // and the filter |
| Plan *pplanFirstChild = (Plan*) LInitial(pappend->appendplans); |
| |
| GPOS_ASSERT(NULL != pplanFirstChild); |
| CDXLNode *pdxlnFirstChild = PdxlnFromPlan(pplanFirstChild); |
| #ifdef GPOS_DEBUG |
| pdxlnFirstChild->Pdxlop()->AssertValid(pdxlnFirstChild, false /* fValidateChildren */); |
| #endif |
| |
| // get first child projection list |
| CDXLNode *pdxlnPrLFirstChild = (*pdxlnFirstChild)[0]; |
| CDXLNode *pdxlnPrL = NULL; |
| CDXLNode *pdxlnFilter = NULL; |
| |
| m_psctranslator->SetCallingPhysicalOpType(EpspotAppend); |
| |
| TranslateTListAndQual( |
| (pappend->plan).targetlist, |
| (pappend->plan).qual, |
| 0, //ulRTEIndex |
| NULL, //table descr |
| NULL, //pmdindex |
| pdxlnPrLFirstChild, |
| NULL, //pdxlnPrLRight |
| &pdxlnPrL, |
| &pdxlnFilter |
| ); |
| |
| // add children in the right order |
| pdxln->AddChild(pdxlnPrL); // proj list |
| pdxln->AddChild(pdxlnFilter); // filter |
| pdxln->AddChild(pdxlnFirstChild); // first child |
| |
| // translate the rest of the append child plans |
| const ULONG ulLen = gpdb::UlListLength(pappend->appendplans); |
| for (ULONG ul = 1; ul < ulLen; ul++) |
| { |
| Plan *pplanChild = (Plan*) gpdb::PvListNth(pappend->appendplans, ul); |
| GPOS_ASSERT(NULL != pplanChild); |
| CDXLNode *pdxlnChild = PdxlnFromPlan(pplanChild); |
| pdxln->AddChild(pdxlnChild); |
| } |
| |
| return pdxln; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnResultFromFoldedFuncExpr |
| // |
| // @doc: |
| // Create a DXL physical Result node from a folded function expression |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnResultFromFoldedFuncExpr |
| ( |
| const Expr *pexpr, |
| CWStringDynamic *pstrAlias, |
| CDXLPhysicalProperties *pdxlprop, |
| CMappingVarColId *pmapvarcolid |
| ) |
| { |
| CDXLNode *pdxlnPrL = GPOS_NEW(m_pmp) CDXLNode(m_pmp, GPOS_NEW(m_pmp) CDXLScalarProjList(m_pmp)); |
| |
| // construct a scalar operator for the expression |
| CDXLNode *pdxlnChild = m_psctranslator->PdxlnScOpFromExpr(pexpr, pmapvarcolid); |
| |
| ULONG ulPrElId = m_pidgtor->UlNextId(); |
| CMDName *pmdnameAlias = GPOS_NEW(m_pmp) CMDName(m_pmp, pstrAlias); |
| |
| CDXLNode *pdxlnPrEl = GPOS_NEW(m_pmp) CDXLNode |
| ( |
| m_pmp, |
| GPOS_NEW(m_pmp) CDXLScalarProjElem(m_pmp, ulPrElId, pmdnameAlias) |
| ); |
| pdxlnPrEl->AddChild(pdxlnChild); |
| |
| // add proj elem to proj list |
| pdxlnPrL->AddChild(pdxlnPrEl); |
| |
| CDXLPhysicalResult *pdxlopResult = GPOS_NEW(m_pmp) CDXLPhysicalResult(m_pmp); |
| |
| CDXLNode *pdxlnFilter = GPOS_NEW(m_pmp) CDXLNode(m_pmp, GPOS_NEW(m_pmp) CDXLScalarFilter(m_pmp)); |
| |
| pmapvarcolid->LoadProjectElements(DEFAULT_QUERY_LEVEL, OUTER, pdxlnPrL); |
| |
| CDXLNode *pdxlnOneTimeFilter = GPOS_NEW(m_pmp) CDXLNode(m_pmp, GPOS_NEW(m_pmp) CDXLScalarOneTimeFilter(m_pmp)); |
| |
| CDXLNode *pdxln = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlopResult); |
| pdxln->SetProperties(pdxlprop); |
| |
| pdxln->AddChild(pdxlnPrL); |
| pdxln->AddChild(pdxlnFilter); |
| pdxln->AddChild(pdxlnOneTimeFilter); |
| |
| return pdxln; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnFunctionScanFromPlan |
| // |
| // @doc: |
| // Create a DXL physical TVF node from a GPDB function scan node. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnFunctionScanFromPlan |
| ( |
| const Plan *pplan |
| ) |
| { |
| GPOS_ASSERT(NULL != pplan); |
| GPOS_ASSERT(IsA(pplan, FunctionScan)); |
| const FunctionScan *pfuncscan = (FunctionScan *) pplan; |
| |
| Index iRel = pfuncscan->scan.scanrelid; |
| GPOS_ASSERT(0 < iRel); |
| |
| RangeTblEntry *prte = (RangeTblEntry *) gpdb::PvListNth(m_pplstmt->rtable, (iRel) - 1); |
| |
| GPOS_ASSERT(NULL != prte); |
| GPOS_ASSERT(RTE_FUNCTION == prte->rtekind); |
| |
| Alias *palias = prte->eref; |
| CWStringDynamic *pstrAlias = CDXLUtils::PstrFromSz(m_pmp, palias->aliasname); |
| |
| // get properties |
| CDXLPhysicalProperties *pdxlprop = PdxlpropFromPlan(pplan); |
| |
| CMappingVarColId mapvarcolid(m_pmp); |
| |
| if (!IsA(prte->funcexpr, FuncExpr)) |
| { |
| // for folded function expressions, construct a result node |
| CDXLNode *pdxln = PdxlnResultFromFoldedFuncExpr |
| ( |
| (Expr *)prte->funcexpr, |
| pstrAlias, |
| pdxlprop, |
| &mapvarcolid |
| ); |
| GPOS_DELETE(pstrAlias); |
| |
| return pdxln; |
| } |
| |
| FuncExpr *pfuncexpr = (FuncExpr *) prte->funcexpr; |
| CMDIdGPDB *pmdidFunc = CTranslatorUtils::PmdidWithVersion(m_pmp, pfuncexpr->funcid); |
| CMDIdGPDB *pmdidRetType = CTranslatorUtils::PmdidWithVersion(m_pmp, pfuncexpr->funcresulttype); |
| |
| CWStringConst *pstrFunc = GPOS_NEW(m_pmp) CWStringConst(m_pmp, pstrAlias->Wsz()); |
| GPOS_DELETE(pstrAlias); |
| CDXLPhysicalTVF *pdxlop = GPOS_NEW(m_pmp) CDXLPhysicalTVF(m_pmp, pmdidFunc, pmdidRetType, pstrFunc); |
| |
| CDXLNode *pdxlnTVF = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlop); |
| // add properties |
| pdxlnTVF->SetProperties(pdxlprop); |
| |
| // construct and add projection list |
| mapvarcolid.Load(DEFAULT_QUERY_LEVEL, iRel, m_pidgtor, palias->colnames); |
| |
| CDXLNode *pdxlnPrL = PdxlnPrLFromTL(pfuncscan->scan.plan.targetlist, &mapvarcolid); |
| |
| pdxlnTVF->AddChild(pdxlnPrL); |
| |
| // translate scalar children |
| ListCell *plcArg = NULL; |
| |
| ForEach (plcArg, pfuncexpr->args) |
| { |
| Expr *pexpr = (Expr *) lfirst(plcArg); |
| |
| CDXLNode *pdxlnChild = m_psctranslator->PdxlnScOpFromExpr |
| ( |
| pexpr, |
| &mapvarcolid |
| ); |
| |
| pdxlnTVF->AddChild(pdxlnChild); |
| } |
| |
| return pdxlnTVF; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnTblScanFromPlan |
| // |
| // @doc: |
| // Create a DXL table scan node from a GPDB sequential scan node. |
| // The function allocates memory in the translator memory pool, and the caller |
| // is responsible for freeing it. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnTblScanFromPlan |
| ( |
| const Plan *pplan |
| ) |
| { |
| GPOS_ASSERT(NULL != pplan); |
| GPOS_ASSERT(IsA(pplan, SeqScan)); |
| const SeqScan *psscan = (SeqScan *) pplan; |
| |
| GPOS_ASSERT(0 < psscan->scanrelid); |
| |
| // construct table descriptor for the scan node from the range table entry |
| RangeTblEntry *prte = (RangeTblEntry *) gpdb::PvListNth(m_pplstmt->rtable, (psscan->scanrelid) - 1); |
| |
| GPOS_ASSERT(NULL != prte); |
| GPOS_ASSERT(RTE_RELATION == prte->rtekind); |
| |
| CDXLTableDescr *pdxltabdesc = CTranslatorUtils::Pdxltabdesc(m_pmp, m_pmda, m_pidgtor, prte); |
| // get plan costs |
| CDXLPhysicalProperties *pdxlprop = PdxlpropFromPlan(pplan); |
| |
| CDXLPhysicalTableScan *pdxlopTS = GPOS_NEW(m_pmp) CDXLPhysicalTableScan(m_pmp, pdxltabdesc); |
| |
| CDXLNode *pdxlnTblScan = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlopTS); |
| pdxlnTblScan->SetProperties(pdxlprop); |
| |
| // construct projection list and filter |
| CDXLNode *pdxlnPrL = NULL; |
| CDXLNode *pdxlnFilter = NULL; |
| |
| m_psctranslator->SetCallingPhysicalOpType(EpspotTblScan); |
| |
| TranslateTListAndQual( |
| (psscan->plan).targetlist, |
| (psscan->plan).qual, |
| ULONG(psscan->scanrelid), |
| pdxltabdesc, |
| NULL, // pmdindex |
| NULL, // pdxlnPrLLeft |
| NULL, // pdxlnPrLRight |
| &pdxlnPrL, |
| &pdxlnFilter |
| ); |
| |
| // add children in the right order |
| pdxlnTblScan->AddChild(pdxlnPrL); |
| pdxlnTblScan->AddChild(pdxlnFilter); |
| |
| return pdxlnTblScan; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnIndexScanFromPlan |
| // |
| // @doc: |
| // Create a DXL index scan node from a GPDB index scan node. |
| // The function allocates memory in the translator memory pool, and the caller |
| // is responsible for freeing it. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnIndexScanFromPlan |
| ( |
| const Plan *pplan |
| ) |
| { |
| GPOS_ASSERT(NULL != pplan); |
| GPOS_ASSERT(IsA(pplan, IndexScan)); |
| const IndexScan *pindexscan = (IndexScan *) pplan; |
| |
| EPlStmtPhysicalOpType eplstmtphoptype = m_psctranslator->Eplsphoptype(); |
| m_psctranslator->SetCallingPhysicalOpType(EpspotIndexScan); |
| |
| CDXLNode *pdxln = PdxlnIndexScanFromGPDBIndexScan(pindexscan, false /*fIndexOnlyScan*/); |
| |
| m_psctranslator->SetCallingPhysicalOpType(eplstmtphoptype); |
| |
| return pdxln; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnIndexScanFromGPDBIndexScan |
| // |
| // @doc: |
| // Create a DXL index (only) scan node from a GPDB index (only) scan node. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnIndexScanFromGPDBIndexScan |
| ( |
| const IndexScan *pindexscan, |
| BOOL fIndexOnlyScan |
| ) |
| { |
| GPOS_ASSERT(0 < pindexscan->scan.scanrelid); |
| GPOS_ASSERT(0 < pindexscan->indexid); |
| |
| // construct table descriptor for the scan node from the range table entry |
| RangeTblEntry *prte = |
| (RangeTblEntry *) gpdb::PvListNth(m_pplstmt->rtable, (pindexscan->scan.scanrelid) - 1); |
| |
| GPOS_ASSERT(NULL != prte); |
| GPOS_ASSERT(RTE_RELATION == prte->rtekind); |
| CDXLTableDescr *pdxltabdesc = CTranslatorUtils::Pdxltabdesc(m_pmp, m_pmda, m_pidgtor, prte); |
| |
| // create the index descriptor |
| CMDIdGPDB *pmdid = CTranslatorUtils::PmdidWithVersion(m_pmp, pindexscan->indexid); |
| CDXLIndexDescr *pdxlid = CTranslatorUtils::Pdxlid(m_pmp, m_pmda, pmdid); |
| const IMDIndex *pmdindex = m_pmda->Pmdindex(pmdid); |
| |
| EdxlIndexScanDirection edxlissd = CTranslatorUtils::EdxlIndexDirection(pindexscan->indexorderdir); |
| |
| CDXLPhysicalIndexScan *pdxlop = NULL; |
| |
| GPOS_ASSERT(!fIndexOnlyScan); |
| //{ |
| // pdxlop = GPOS_NEW(m_pmp) CDXLPhysicalIndexOnlyScan(m_pmp, pdxltabdesc, pdxlid, edxlissd); |
| //} |
| //else |
| //{ |
| pdxlop = GPOS_NEW(m_pmp) CDXLPhysicalIndexScan(m_pmp, pdxltabdesc, pdxlid, edxlissd); |
| //} |
| |
| CDXLNode *pdxlnIndexScan = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlop); |
| |
| // get plan costs |
| CDXLPhysicalProperties *pdxlprop = PdxlpropFromPlan((Plan *)pindexscan); |
| pdxlnIndexScan->SetProperties(pdxlprop); |
| |
| // translate the index condition |
| CMappingVarColId mapvarcolidForIndex(m_pmp); |
| |
| if (NULL != pdxltabdesc) |
| { |
| mapvarcolidForIndex.LoadIndexColumns(DEFAULT_QUERY_LEVEL, ULONG(pindexscan->scan.scanrelid), pmdindex, pdxltabdesc); |
| } |
| |
| // translate index condition |
| CDXLNode *pdxlnIdxCondList = GPOS_NEW(m_pmp) CDXLNode(m_pmp, GPOS_NEW(m_pmp) CDXLScalarIndexCondList(m_pmp)); |
| |
| ListCell *plcQual = NULL; |
| ForEach (plcQual, pindexscan->indexqual) |
| { |
| Expr *pexpr = (Expr *) lfirst(plcQual); |
| CDXLNode *pdxlnIdxQual = m_psctranslator->PdxlnScOpFromExpr(pexpr, &mapvarcolidForIndex); |
| pdxlnIdxCondList->AddChild(pdxlnIdxQual); |
| } |
| |
| // construct projection list and filter |
| CDXLNode *pdxlnPrL = NULL; |
| CDXLNode *pdxlnFilter = NULL; |
| |
| const IMDIndex *pmdindexProjList = NULL; |
| if (fIndexOnlyScan) |
| { |
| pmdindexProjList = pmdindex; |
| } |
| |
| TranslateTListAndQual |
| ( |
| (pindexscan->scan.plan).targetlist, |
| (pindexscan->scan.plan).qual, |
| ULONG(pindexscan->scan.scanrelid), |
| pdxltabdesc, |
| pmdindexProjList, |
| NULL, // pdxlnPrLLeft |
| NULL, // pdxlnPrLRight |
| &pdxlnPrL, |
| &pdxlnFilter |
| ); |
| |
| // add children in the right order |
| pdxlnIndexScan->AddChild(pdxlnPrL); |
| pdxlnIndexScan->AddChild(pdxlnFilter); |
| pdxlnIndexScan->AddChild(pdxlnIdxCondList); |
| |
| return pdxlnIndexScan; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnLimitFromPlan |
| // |
| // @doc: |
| // Create a DXL Limit node from a GPDB LIMIT node. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnLimitFromPlan |
| ( |
| const Plan *pplan |
| ) |
| { |
| GPOS_ASSERT(NULL != pplan); |
| GPOS_ASSERT(IsA(pplan, Limit)); |
| const Limit *plimit = (Limit *) pplan; |
| |
| // get plan costs |
| CDXLPhysicalProperties *pdxlprop = PdxlpropFromPlan(pplan); |
| |
| CDXLPhysicalLimit *pdxlopLimit = GPOS_NEW(m_pmp) CDXLPhysicalLimit(m_pmp); |
| CDXLNode *pdxlnLimit = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlopLimit); |
| pdxlnLimit->SetProperties(pdxlprop); |
| |
| Plan *pplanChildPlan = outerPlan(plimit); |
| |
| GPOS_ASSERT(NULL != pplanChildPlan); |
| CDXLNode *pdxlnChildPlan = PdxlnFromPlan(pplanChildPlan); |
| GPOS_ASSERT(1 <= pdxlnChildPlan->UlArity()); |
| |
| CDXLNode *pdxlnPrLLeft = (*pdxlnChildPlan)[0]; |
| GPOS_ASSERT(pdxlnPrLLeft->Pdxlop()->Edxlop() == EdxlopScalarProjectList); |
| |
| CMappingVarColId mapvarcolid(m_pmp); |
| m_psctranslator->SetCallingPhysicalOpType(EpspotLimit); |
| mapvarcolid.LoadProjectElements(DEFAULT_QUERY_LEVEL, OUTER, pdxlnPrLLeft); |
| |
| // construct projection list |
| CDXLNode *pdxlnPrL = PdxlnPrLFromTL((plimit->plan).targetlist, &mapvarcolid); |
| |
| // add children in the right order |
| pdxlnLimit->AddChild(pdxlnPrL); // project list |
| pdxlnLimit->AddChild(pdxlnChildPlan); |
| |
| CDXLScalarLimitCount *pdxlopLimitCount = GPOS_NEW(m_pmp) CDXLScalarLimitCount(m_pmp); |
| CDXLNode *pdxlnLimitCount = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlopLimitCount); |
| |
| if(NULL != plimit->limitCount) |
| { |
| pdxlnLimitCount->AddChild(m_psctranslator->PdxlnScOpFromExpr |
| ( |
| (Expr *) (plimit->limitCount), |
| &mapvarcolid |
| ) |
| ); |
| } |
| pdxlnLimit->AddChild(pdxlnLimitCount); |
| |
| CDXLScalarLimitOffset *pdxlopLimitOffset = GPOS_NEW(m_pmp) CDXLScalarLimitOffset(m_pmp); |
| CDXLNode *pdxlnLimitOffset = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlopLimitOffset); |
| |
| if(NULL != plimit->limitOffset) |
| { |
| pdxlnLimitOffset->AddChild(m_psctranslator->PdxlnScOpFromExpr |
| ( |
| (Expr *) (plimit->limitOffset), |
| &mapvarcolid |
| ) |
| ); |
| } |
| |
| pdxlnLimit->AddChild(pdxlnLimitOffset); |
| |
| return pdxlnLimit; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnMaterializeFromPlan |
| // |
| // @doc: |
| // Create a DXL Materialize node from a GPDB MATERIAL node. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnMaterializeFromPlan |
| ( |
| const Plan *pplan |
| ) |
| { |
| GPOS_ASSERT(NULL != pplan); |
| GPOS_ASSERT(IsA(pplan, Material)); |
| const Material *pmat = (Material *) pplan; |
| // get plan costs |
| CDXLPhysicalProperties *pdxlprop = PdxlpropFromPlan(pplan); |
| CDXLPhysicalMaterialize *pdxlopMat = NULL; |
| |
| if (SHARE_NOTSHARED == pmat->share_type) |
| { |
| // materialize node is not shared |
| pdxlopMat = GPOS_NEW(m_pmp) CDXLPhysicalMaterialize(m_pmp, pmat->cdb_strict); |
| } |
| else |
| { |
| // create a shared materialize node |
| pdxlopMat = GPOS_NEW(m_pmp) CDXLPhysicalMaterialize(m_pmp, pmat->cdb_strict, pmat->share_id, pmat->driver_slice, pmat->nsharer_xslice); |
| } |
| |
| CDXLNode *pdxlnMaterialize = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlopMat); |
| pdxlnMaterialize->SetProperties(pdxlprop); |
| |
| Plan *pplanChildPlan = outerPlan(pmat); |
| GPOS_ASSERT(NULL != pplanChildPlan); |
| CDXLNode *pdxlnChildPlan = PdxlnFromPlan(pplanChildPlan); |
| GPOS_ASSERT(1 <= pdxlnChildPlan->UlArity()); |
| |
| CDXLNode *pdxlnPrLLeft = (*pdxlnChildPlan)[0]; |
| GPOS_ASSERT(pdxlnPrLLeft->Pdxlop()->Edxlop() == EdxlopScalarProjectList); |
| |
| // construct projection list and filter |
| CDXLNode *pdxlnPrL = NULL; |
| CDXLNode *pdxlnFilter = NULL; |
| |
| m_psctranslator->SetCallingPhysicalOpType(EpspotMaterialize); |
| |
| TranslateTListAndQual( |
| (pmat->plan).targetlist, |
| (pmat->plan).qual, |
| 0, //ulRTEIndex |
| NULL, // table descr |
| NULL, // pmdindex |
| pdxlnPrLLeft, // pdxlnPrLLeft |
| NULL, // pdxlnPrLRight |
| &pdxlnPrL, |
| &pdxlnFilter |
| ); |
| |
| pdxlnMaterialize->AddChild(pdxlnPrL); |
| pdxlnMaterialize->AddChild(pdxlnFilter); |
| pdxlnMaterialize->AddChild(pdxlnChildPlan); |
| |
| return pdxlnMaterialize; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnSharedScanFromPlan |
| // |
| // @doc: |
| // Create a DXL SharedScan node from a GPDB SHAREINPUTSCAN node. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnSharedScanFromPlan |
| ( |
| const Plan *pplan |
| ) |
| { |
| GPOS_ASSERT(NULL != pplan); |
| GPOS_ASSERT(IsA(pplan, ShareInputScan)); |
| const ShareInputScan *pshscan = (ShareInputScan *) pplan; |
| |
| // get plan costs |
| CDXLPhysicalProperties *pdxlprop = PdxlpropFromPlan(pplan); |
| CDXLPhysicalSharedScan *pdxlopShScan = NULL; |
| |
| CDXLSpoolInfo *pspoolinfo = PspoolinfoFromSharedScan(pshscan); |
| pdxlopShScan = GPOS_NEW(m_pmp) CDXLPhysicalSharedScan(m_pmp, pspoolinfo); |
| CDXLNode *pdxlnSharedScan = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlopShScan); |
| pdxlnSharedScan->SetProperties(pdxlprop); |
| |
| Plan *pplanChildPlan = outerPlan(pshscan); |
| |
| // project list of child operator |
| const CDXLNode *pdxlnPrLChild = NULL; |
| CDXLNode *pdxlnChildPlan = NULL; |
| if (NULL != pplanChildPlan) |
| { |
| // translate shared scan child |
| pdxlnChildPlan = PdxlnFromPlan(pplanChildPlan); |
| GPOS_ASSERT(1 <= pdxlnChildPlan->UlArity()); |
| pdxlnPrLChild = (*pdxlnChildPlan)[0]; |
| } |
| else |
| { |
| // input for shared scan node has already been translated elsewhere: |
| // fetch the corresponding project list |
| ULONG ulSharedScanId = (ULONG) pshscan->share_id; |
| pdxlnPrLChild = m_phmuldxlnSharedScanProjLists->PtLookup(&ulSharedScanId); |
| } |
| |
| GPOS_ASSERT(NULL != pdxlnPrLChild); |
| GPOS_ASSERT(pdxlnPrLChild->Pdxlop()->Edxlop() == EdxlopScalarProjectList); |
| |
| // construct projection list and filter |
| CDXLNode *pdxlnPrL = NULL; |
| CDXLNode *pdxlnFilter = NULL; |
| |
| m_psctranslator->SetCallingPhysicalOpType(EpspotSharedScan); |
| |
| TranslateTListAndQual( |
| (pshscan->plan).targetlist, |
| (pshscan->plan).qual, |
| 0, //ulRTEIndex |
| NULL, // table descr |
| NULL, // pmdindex |
| pdxlnPrLChild, // pdxlnPrLLeft |
| NULL, // pdxlnPrLRight |
| &pdxlnPrL, |
| &pdxlnFilter |
| ); |
| |
| if (NULL != pplanChildPlan) |
| { |
| // first encounter of this shared scan id: store the translated proj list |
| ULONG *pulSharedScanId = GPOS_NEW(m_pmp) ULONG(pshscan->share_id); |
| |
| pdxlnPrL->AddRef(); |
| #ifdef GPOS_DEBUG |
| BOOL fInserted = |
| #endif |
| m_phmuldxlnSharedScanProjLists->FInsert(pulSharedScanId, pdxlnPrL); |
| GPOS_ASSERT(fInserted); |
| } |
| |
| // add children in the right order |
| pdxlnSharedScan->AddChild(pdxlnPrL); // project list |
| pdxlnSharedScan->AddChild(pdxlnFilter); // filter |
| |
| if (NULL != pdxlnChildPlan) |
| { |
| pdxlnSharedScan->AddChild(pdxlnChildPlan); |
| } |
| |
| return pdxlnSharedScan; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnSequence |
| // |
| // @doc: |
| // Create a DXL Sequnce node from a GPDB Sequence plan node. |
| // The function allocates memory in the translator memory pool, and the caller |
| // is responsible for freeing it. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnSequence |
| ( |
| const Plan *pplan |
| ) |
| { |
| GPOS_ASSERT(NULL != pplan); |
| GPOS_ASSERT(IsA(pplan, Sequence)); |
| const Sequence *psequence = (Sequence *) pplan; |
| GPOS_ASSERT(NULL != psequence->subplans); |
| |
| // extract plan properties |
| CDXLPhysicalProperties *pdxlprop = PdxlpropFromPlan(pplan); |
| |
| GPOS_ASSERT(NULL != pdxlprop); |
| |
| // construct DXL sequence operator |
| CDXLPhysicalSequence *pdxlop = GPOS_NEW(m_pmp) CDXLPhysicalSequence(m_pmp); |
| |
| CDXLNode *pdxln = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlop); |
| pdxln->SetProperties(pdxlprop); |
| |
| // translate last child of sequence operator so we can translate the project list |
| // and the filter |
| const ULONG ulSubplans = gpdb::UlListLength(psequence->subplans); |
| |
| GPOS_ASSERT(0 < ulSubplans); |
| |
| Plan *pplanLastChild = (Plan*) gpdb::PvListNth(psequence->subplans, ulSubplans - 1); |
| |
| GPOS_ASSERT(NULL != pplanLastChild); |
| |
| CDXLNode *pdxlnLastChild = PdxlnFromPlan(pplanLastChild); |
| |
| // get last child projection list |
| CDXLNode *pdxlnPrLLastChild = (*pdxlnLastChild)[0]; |
| |
| CMappingVarColId mapvarcolid(m_pmp); |
| mapvarcolid.LoadProjectElements(DEFAULT_QUERY_LEVEL, OUTER, pdxlnPrLLastChild); |
| |
| // construct projection list |
| CDXLNode *pdxlnPrL = PdxlnPrLFromTL((psequence->plan).targetlist, &mapvarcolid); |
| |
| // add children in the right order |
| pdxln->AddChild(pdxlnPrL); // proj list |
| |
| // translate the rest of the sequence subplans |
| for (ULONG ul = 0; ul < ulSubplans - 1; ul++) |
| { |
| Plan *pplanChild = (Plan*) gpdb::PvListNth(psequence->subplans, ul); |
| CDXLNode *pdxlnChild = PdxlnFromPlan(pplanChild); |
| pdxln->AddChild(pdxlnChild); |
| } |
| |
| pdxln->AddChild(pdxlnLastChild); // last child |
| |
| return pdxln; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnDynamicTableScan |
| // |
| // @doc: |
| // Create a DXL Dynamic Table Scan node from the corresponding GPDB plan node. |
| // The function allocates memory in the translator memory pool, and the caller |
| // is responsible for freeing it. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnDynamicTableScan |
| ( |
| const Plan *pplan |
| ) |
| { |
| GPOS_ASSERT(NULL != pplan); |
| GPOS_ASSERT(IsA(pplan, DynamicTableScan)); |
| const DynamicTableScan *pdts = (DynamicTableScan *) pplan; |
| |
| // extract plan properties |
| CDXLPhysicalProperties *pdxlprop = PdxlpropFromPlan(pplan); |
| |
| // construct DXL dynamic table scan operator |
| |
| // construct table descriptor for the scan node from the range table entry |
| RangeTblEntry *prte = (RangeTblEntry *) gpdb::PvListNth(m_pplstmt->rtable, (pdts->scanrelid) - 1); |
| |
| GPOS_ASSERT(NULL != prte); |
| GPOS_ASSERT(RTE_RELATION == prte->rtekind); |
| |
| CDXLTableDescr *pdxltabdesc = CTranslatorUtils::Pdxltabdesc(m_pmp, m_pmda, m_pidgtor, prte); |
| |
| CDXLPhysicalDynamicTableScan *pdxlop = GPOS_NEW(m_pmp) CDXLPhysicalDynamicTableScan(m_pmp, pdxltabdesc, pdts->partIndex, pdts->partIndexPrintable); |
| |
| CDXLNode *pdxln = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlop); |
| pdxln->SetProperties(pdxlprop); |
| |
| // construct projection list |
| |
| CMappingVarColId mapvarcolid(m_pmp); |
| mapvarcolid.LoadTblColumns(DEFAULT_QUERY_LEVEL, ULONG(pdts->scanrelid), pdxltabdesc); |
| |
| // construct projection list |
| CDXLNode *pdxlnPrL = PdxlnPrLFromTL((pdts->plan).targetlist, &mapvarcolid); |
| |
| pdxln->AddChild(pdxlnPrL); // project list |
| |
| return pdxln; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::TranslateTListAndQual |
| // |
| // @doc: |
| // Translate GPDB translate target and qual lists into DXL project list and |
| // filter, respectively. |
| // This function can be used for constructing the projection list and filter of a |
| // base node (e.g. a scan node), in which case the the table descriptor is |
| // not null and is used for resolving the column references, or in an intermediate |
| // plan nodes, where pdxlnprlLeft and pldxlnprlRight are the projection lists |
| // for the left and right child, respectively. |
| // The function allocates memory in the translator memory pool, and the caller |
| // is responsible for freeing it. |
| // |
| //--------------------------------------------------------------------------- |
| void |
| CTranslatorPlStmtToDXL::TranslateTListAndQual |
| ( |
| List *plTargetList, |
| List *plQual, |
| ULONG ulRTEIndex, |
| const CDXLTableDescr *pdxltabdesc, |
| const IMDIndex *pmdindex, |
| const CDXLNode *pdxlnPrLLeft, |
| const CDXLNode *pdxlnPrLRight, |
| CDXLNode **ppdxlnPrLOut, |
| CDXLNode **ppdxlnFilterOut |
| ) |
| { |
| GPOS_ASSERT_IMP(NULL != pmdindex, NULL != pdxltabdesc); |
| |
| CMappingVarColId mapvarcolid(m_pmp); |
| if (NULL != pdxlnPrLLeft) |
| { |
| mapvarcolid.LoadProjectElements(DEFAULT_QUERY_LEVEL, OUTER, pdxlnPrLLeft); |
| } |
| |
| if (NULL != pdxlnPrLRight) |
| { |
| mapvarcolid.LoadProjectElements(DEFAULT_QUERY_LEVEL, INNER, pdxlnPrLRight); |
| } |
| |
| if (NULL != pdxltabdesc) |
| { |
| GPOS_ASSERT(ulRTEIndex > 0); |
| if (NULL != pmdindex) |
| { |
| mapvarcolid.LoadIndexColumns(DEFAULT_QUERY_LEVEL, ulRTEIndex, pmdindex, pdxltabdesc); |
| } |
| else |
| { |
| mapvarcolid.LoadTblColumns(DEFAULT_QUERY_LEVEL, ulRTEIndex, pdxltabdesc); |
| } |
| } |
| |
| // construct projection list |
| *ppdxlnPrLOut = PdxlnPrLFromTL(plTargetList, &mapvarcolid); |
| *ppdxlnFilterOut = m_psctranslator->PdxlnFilterFromQual |
| ( |
| plQual, |
| &mapvarcolid, |
| EdxlopScalarFilter |
| ); |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnPrLFromTL |
| // |
| // @doc: |
| // Create a DXL projection list node table descriptor from a GPDB target list. |
| // This function can be used for constructing the projection list of a |
| // base node (e.g. a scan node), in which case the the table descriptor is |
| // not null and is used for resolving the column references, or in an intermediate |
| // plan nodes, where pdxlnprlLeft and pldxlnprlRight are the projection lists |
| // for the left and right child, respectively. |
| // The function allocates memory in the translator memory pool, and the caller |
| // is responsible for freeing it. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnPrLFromTL |
| ( |
| List *plTargetList, |
| CMappingVarColId *pmapvarcolid |
| ) |
| { |
| CDXLNode *pdxlnPrL = GPOS_NEW(m_pmp) CDXLNode(m_pmp, GPOS_NEW(m_pmp) CDXLScalarProjList(m_pmp)); |
| ListCell *plcte = NULL; |
| |
| // construct a proj list node for each entry in the target list |
| ForEach (plcte, plTargetList) |
| { |
| TargetEntry *pte = (TargetEntry *) lfirst(plcte); |
| GPOS_ASSERT(IsA(pte, TargetEntry)); |
| |
| // construct a scalar operator for the the Var's expression |
| CDXLNode *pdxlnChild = m_psctranslator->PdxlnScOpFromExpr(pte->expr, pmapvarcolid); |
| // construct a projection element |
| CDXLScalarProjElem *pdxlopPrEl = NULL; |
| // get the id and alias for the proj elem |
| ULONG ulPrElId; |
| CMDName *pmdnameAlias = NULL; |
| |
| if (NULL != pte->resname) |
| { |
| CWStringDynamic *pstrAlias = CDXLUtils::PstrFromSz(m_pmp, pte->resname); |
| pmdnameAlias = GPOS_NEW(m_pmp) CMDName(m_pmp, pstrAlias); |
| // CName constructor copies string |
| GPOS_DELETE(pstrAlias); |
| } |
| |
| if (IsA(pte->expr, Var)) |
| { |
| // project elem is a a reference to a column - use the colref id |
| GPOS_ASSERT(EdxlopScalarIdent == pdxlnChild->Pdxlop()->Edxlop()); |
| CDXLScalarIdent *pdxlopIdent = (CDXLScalarIdent *) pdxlnChild->Pdxlop(); |
| ulPrElId = pdxlopIdent->Pdxlcr()->UlID(); |
| |
| if (NULL == pte->resname) |
| { |
| // no alias provided - create a copy of the original column name |
| pmdnameAlias = GPOS_NEW(m_pmp) CMDName |
| ( |
| m_pmp, |
| pdxlopIdent->Pdxlcr()->Pmdname()->Pstr() |
| ); |
| } |
| } |
| else |
| { |
| // project elem is a defined column - get a new id |
| ulPrElId = m_pidgtor->UlNextId(); |
| // GPOS_ASSERT(NULL != pte->resname); |
| if (NULL == pte->resname) |
| { |
| // no column name - make up one |
| CWStringConst strUnnamedCol(GPOS_WSZ_LIT("?column?")); |
| pmdnameAlias = GPOS_NEW(m_pmp) CMDName(m_pmp, &strUnnamedCol); |
| } |
| } |
| |
| GPOS_ASSERT(NULL != pmdnameAlias); |
| |
| // construct a projection element operator |
| pdxlopPrEl = GPOS_NEW(m_pmp) CDXLScalarProjElem(m_pmp, ulPrElId, pmdnameAlias); |
| |
| // create the DXL node holding the proj elem |
| CDXLNode *pdxlnPrEl = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlopPrEl); |
| pdxlnPrEl->AddChild(pdxlnChild); |
| |
| // add proj elem to proj list |
| pdxlnPrL->AddChild(pdxlnPrEl); |
| } |
| |
| return pdxlnPrL; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlpropFromPlan |
| // |
| // @doc: |
| // Extract cost estimates from Plan structures and store them in a |
| // DXL properties container. |
| // The function allocates memory in the translator memory pool, and the caller |
| // is responsible for freeing it. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLPhysicalProperties * |
| CTranslatorPlStmtToDXL::PdxlpropFromPlan |
| ( |
| const Plan *pplan |
| ) |
| { |
| CWStringDynamic *pstrTotalCost = GPOS_NEW(m_pmp) CWStringDynamic(m_pmp); |
| CWStringDynamic *pstrStartupCost = GPOS_NEW(m_pmp) CWStringDynamic(m_pmp); |
| CWStringDynamic *pstrRows = GPOS_NEW(m_pmp) CWStringDynamic(m_pmp); |
| CWStringDynamic *pstrWidth = GPOS_NEW(m_pmp) CWStringDynamic(m_pmp); |
| |
| const WCHAR wszFormat[] = GPOS_WSZ_LIT("%.2f"); |
| pstrTotalCost->AppendFormat(wszFormat, pplan->total_cost); |
| pstrWidth->AppendFormat(GPOS_WSZ_LIT("%d"), pplan->plan_width); |
| pstrStartupCost->AppendFormat(wszFormat, pplan->startup_cost); |
| pstrRows->AppendFormat(wszFormat, pplan->plan_rows); |
| |
| CDXLOperatorCost *pdxlopcost = GPOS_NEW(m_pmp) CDXLOperatorCost |
| ( |
| pstrStartupCost, |
| pstrTotalCost, |
| pstrRows, |
| pstrWidth |
| ); |
| CDXLPhysicalProperties *pdxlprop = GPOS_NEW(m_pmp) CDXLPhysicalProperties(pdxlopcost); |
| |
| return pdxlprop; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnHashExprLFromList |
| // |
| // @doc: |
| // Translate the list of hash expressions in a RedistributeMotion plan node. |
| // The function allocates memory in the translator memory pool, and the caller |
| // is responsible for freeing it. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnHashExprLFromList |
| ( |
| List *plHashExpr, |
| List *plHashExprTypes, |
| const CDXLNode *pdxlnPrLChild |
| ) |
| { |
| GPOS_ASSERT(NULL != plHashExpr); |
| GPOS_ASSERT(NULL != plHashExprTypes); |
| GPOS_ASSERT(gpdb::UlListLength(plHashExpr) == gpdb::UlListLength(plHashExprTypes)); |
| |
| CDXLNode *pdxlnHashExprList = GPOS_NEW(m_pmp) CDXLNode(m_pmp, GPOS_NEW(m_pmp) CDXLScalarHashExprList(m_pmp)); |
| |
| ListCell *plcHashExpr = NULL; |
| ListCell *plcHashExprType = NULL; |
| |
| // construct a list of DXL hash expressions |
| ForBoth (plcHashExpr, plHashExpr, |
| plcHashExprType, plHashExprTypes) |
| { |
| Expr *pexpr = (Expr *) lfirst(plcHashExpr); |
| OID oid = lfirst_oid(plcHashExprType); |
| |
| // construct a DXL hash expression node from the hash expression type id and the translated expression |
| CMDIdGPDB *pmdidExprType = CTranslatorUtils::PmdidWithVersion(m_pmp, oid); |
| CDXLNode *pdxlnHashExpr = GPOS_NEW(m_pmp) CDXLNode(m_pmp, GPOS_NEW(m_pmp) CDXLScalarHashExpr(m_pmp, pmdidExprType)); |
| |
| CMappingVarColId mapvarcolid(m_pmp); |
| |
| mapvarcolid.LoadProjectElements(DEFAULT_QUERY_LEVEL, OUTER, pdxlnPrLChild); |
| |
| // translate expression |
| CDXLNode *pdxlnExpr = m_psctranslator->PdxlnScOpFromExpr(pexpr,&mapvarcolid); |
| GPOS_ASSERT(NULL != pdxlnExpr); |
| |
| pdxlnHashExpr->AddChild(pdxlnExpr); |
| pdxlnHashExprList->AddChild(pdxlnHashExpr); |
| } |
| |
| return pdxlnHashExprList; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PdxlnSortingColListFromPlan |
| // |
| // @doc: |
| // Translate the list of hash expressions in a RedistributeMotion plan node. |
| // The function allocates memory in the translator memory pool, and the caller |
| // is responsible for freeing it. |
| // |
| //--------------------------------------------------------------------------- |
| CDXLNode * |
| CTranslatorPlStmtToDXL::PdxlnSortingColListFromPlan |
| ( |
| AttrNumber *pattnoSortColIds, |
| OID *poidSortOpIds, |
| ULONG ulNumCols, |
| const CDXLNode *pdxlnPrL |
| ) |
| { |
| CDXLScalarSortColList *pdxlopSortColList = GPOS_NEW(m_pmp) CDXLScalarSortColList(m_pmp); |
| CDXLNode *pdxlnSortColList = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlopSortColList); |
| |
| if (0 == ulNumCols) |
| { |
| // no sorting columns present - return the empty list |
| return pdxlnSortColList; |
| } |
| |
| GPOS_ASSERT(NULL != pattnoSortColIds && NULL != poidSortOpIds); |
| |
| // construct a list of DXL sorting columns |
| for (ULONG ul = 0; ul < ulNumCols; ul++) |
| { |
| // find col id for the current sorting column |
| AttrNumber attnoSortColId = pattnoSortColIds[ul]; |
| |
| // find sorting column in the project list |
| CDXLNode *pdxlnPrEl = (*pdxlnPrL)[attnoSortColId-1]; |
| CDXLScalarProjElem *pdxlopPrEl = (CDXLScalarProjElem *) pdxlnPrEl->Pdxlop(); |
| ULONG ulSortColId = pdxlopPrEl->UlId(); |
| |
| // retrieve sorting operator oid and name |
| OID oidSortOpId = poidSortOpIds[ul]; |
| |
| CMDIdGPDB *pmdidSortOp = CTranslatorUtils::PmdidWithVersion(m_pmp, oidSortOpId); |
| const IMDScalarOp *pmdscop = m_pmda->Pmdscop(pmdidSortOp); |
| |
| const CWStringConst *pstrSortOpName = pmdscop->Mdname().Pstr();; |
| GPOS_ASSERT(NULL != pstrSortOpName); |
| |
| // TODO: antovl - Jan 19, 2011; read nullsFirst from the plan node; |
| // currently GPDB does not support this |
| CDXLScalarSortCol *pdxlopSortCol = GPOS_NEW(m_pmp) CDXLScalarSortCol |
| ( |
| m_pmp, |
| ulSortColId, |
| pmdidSortOp, |
| GPOS_NEW(m_pmp) CWStringConst(pstrSortOpName->Wsz()), |
| false // nullsFirst |
| ); |
| |
| CDXLNode *pdxlnSortCol = GPOS_NEW(m_pmp) CDXLNode(m_pmp, pdxlopSortCol); |
| pdxlnSortColList->AddChild(pdxlnSortCol); |
| } |
| |
| return pdxlnSortColList; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::TranslateMotionSegmentInfo |
| // |
| // @doc: |
| // Populate the input and output segments id lists from a Motion node |
| // |
| //--------------------------------------------------------------------------- |
| void |
| CTranslatorPlStmtToDXL::TranslateMotionSegmentInfo |
| ( |
| const Motion *pmotion, |
| DrgPi *pdrgpiInputSegIds, |
| DrgPi *pdrgpiOutputSegIds |
| ) |
| { |
| GPOS_ASSERT(NULL != pdrgpiInputSegIds); |
| GPOS_ASSERT(NULL != pdrgpiOutputSegIds); |
| |
| const ULONG ulSegmentCount = gpdb::UlSegmentCountGP(); |
| |
| // populate input segment ids |
| Flow *pChildFlow = (pmotion->plan).lefttree->flow; |
| |
| if (pChildFlow->flotype == FLOW_SINGLETON) |
| { |
| // only one segment sends data |
| INT *piInputSegId = GPOS_NEW(m_pmp) INT(pChildFlow->segindex); |
| pdrgpiInputSegIds->Append(piInputSegId); |
| } |
| else |
| { |
| // all segments send data |
| for (ULONG ul = 0; ul < ulSegmentCount; ul++) |
| { |
| INT *piInputSegId = GPOS_NEW(m_pmp) INT(ul); |
| pdrgpiInputSegIds->Append(piInputSegId ); |
| } |
| } |
| |
| // populate output segment ids |
| if (pmotion->motionType == MOTIONTYPE_HASH) |
| { |
| // redistribute motion |
| GPOS_ASSERT(0 < pmotion->numOutputSegs && NULL!= pmotion->outputSegIdx); |
| |
| for(ULONG ul = 0; ul < (ULONG) pmotion->numOutputSegs; ul++) |
| { |
| INT *piSegId = GPOS_NEW(m_pmp) INT(pmotion->outputSegIdx[ul]); |
| pdrgpiOutputSegIds->Append(piSegId); |
| } |
| } |
| else if (pmotion->motionType == MOTIONTYPE_FIXED && pmotion->numOutputSegs > 0) |
| { |
| // gather motion |
| GPOS_ASSERT(1 == pmotion->numOutputSegs); |
| |
| INT *piOutputSegId = GPOS_NEW(m_pmp) INT(pmotion->outputSegIdx[0]); |
| pdrgpiOutputSegIds->Append(piOutputSegId); |
| } |
| else |
| { |
| // broadcast motion |
| for (ULONG ul = 0; ul < ulSegmentCount; ul++) |
| { |
| INT *piOutputSegId = GPOS_NEW(m_pmp) INT(ul); |
| pdrgpiOutputSegIds->Append(piOutputSegId); |
| } |
| } |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // CTranslatorPlStmtToDXL::PspoolinfoFromSharedScan |
| // |
| // @doc: |
| // Creates a spool info structure for a shared scan from a GPDB shared scan node |
| // |
| //--------------------------------------------------------------------------- |
| CDXLSpoolInfo * |
| CTranslatorPlStmtToDXL::PspoolinfoFromSharedScan |
| ( |
| const ShareInputScan *pshscan |
| ) |
| { |
| GPOS_ASSERT(NULL != pshscan); |
| GPOS_ASSERT(SHARE_NOTSHARED != pshscan->share_type); |
| |
| Edxlspooltype edxlsptype = EdxlspoolSentinel; |
| |
| switch (pshscan->share_type) |
| { |
| case SHARE_MATERIAL: |
| case SHARE_MATERIAL_XSLICE: |
| edxlsptype = EdxlspoolMaterialize; |
| break; |
| |
| case SHARE_SORT: |
| case SHARE_SORT_XSLICE: |
| edxlsptype = EdxlspoolSort; |
| break; |
| |
| default: |
| GPOS_ASSERT(!"Invalid sharing type"); |
| } |
| |
| // is scan shared across slices |
| BOOL fMultiSlice = false; |
| |
| if (SHARE_MATERIAL_XSLICE == pshscan->share_type || SHARE_SORT_XSLICE == pshscan->share_type) |
| { |
| fMultiSlice = true; |
| } |
| |
| CDXLSpoolInfo *pspoolinfo = GPOS_NEW(m_pmp) CDXLSpoolInfo(pshscan->share_id, edxlsptype, fMultiSlice, pshscan->driver_slice); |
| return pspoolinfo; |
| } |
| |
| // EOF |