| /* |
| * 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: |
| // COptTasks.cpp |
| // |
| // @doc: |
| // Routines to perform optimization related tasks using the gpos framework |
| // |
| // @test: |
| // |
| // |
| //--------------------------------------------------------------------------- |
| |
| #include "gpopt/utils/gpdbdefs.h" |
| #include "gpopt/utils/CConstExprEvaluatorProxy.h" |
| #include "gpopt/utils/COptTasks.h" |
| #include "gpopt/relcache/CMDProviderRelcache.h" |
| #include "gpopt/config/CConfigParamMapping.h" |
| #include "gpopt/translate/CStateDXLToQuery.h" |
| #include "gpopt/translate/CTranslatorDXLToExpr.h" |
| #include "gpopt/translate/CTranslatorExprToDXL.h" |
| #include "gpopt/translate/CTranslatorUtils.h" |
| #include "gpopt/translate/CTranslatorQueryToDXL.h" |
| #include "gpopt/translate/CTranslatorDXLToPlStmt.h" |
| #include "gpopt/translate/CContextDXLToPlStmt.h" |
| #include "gpopt/translate/CTranslatorRelcacheToDXL.h" |
| #include "gpopt/eval/CConstExprEvaluatorDXL.h" |
| |
| #include "cdb/cdbvars.h" |
| #include "utils/guc.h" |
| |
| #include "gpos/base.h" |
| #include "gpos/error/CException.h" |
| #undef setstate |
| |
| #include "gpos/_api.h" |
| #include "gpos/common/CAutoP.h" |
| #include "gpos/error/CErrorHandlerStandard.h" |
| #include "gpos/error/CLoggerStream.h" |
| #include "gpos/io/COstreamFile.h" |
| #include "gpos/io/COstreamString.h" |
| #include "gpos/memory/CAutoMemoryPool.h" |
| #include "gpos/task/CWorkerPoolManager.h" |
| #include "gpos/task/CAutoTaskProxy.h" |
| #include "gpos/task/CTaskContext.h" |
| #include "gpos/task/CAutoTraceFlag.h" |
| #include "gpos/common/CAutoP.h" |
| |
| #include "gpopt/translate/CTranslatorDXLToExpr.h" |
| #include "gpopt/translate/CTranslatorExprToDXL.h" |
| |
| #include "gpopt/base/CAutoOptCtxt.h" |
| #include "gpopt/base/CQueryContext.h" |
| #include "gpopt/engine/CEngine.h" |
| #include "gpopt/engine/CEnumeratorConfig.h" |
| #include "gpopt/engine/CStatisticsConfig.h" |
| #include "gpopt/engine/CCTEConfig.h" |
| #include "gpopt/mdcache/CAutoMDAccessor.h" |
| #include "gpopt/mdcache/CMDCache.h" |
| #include "gpopt/minidump/CMiniDumperDXL.h" |
| #include "gpopt/minidump/CMinidumperUtils.h" |
| #include "gpopt/minidump/CSerializableStackTrace.h" |
| #include "gpopt/minidump/CSerializableQuery.h" |
| #include "gpopt/minidump/CSerializablePlan.h" |
| #include "gpopt/minidump/CSerializableMDAccessor.h" |
| #include "gpopt/optimizer/COptimizer.h" |
| #include "gpopt/optimizer/COptimizerConfig.h" |
| #include "gpopt/search/CSearchStage.h" |
| #include "gpopt/xforms/CXformFactory.h" |
| #include "gpopt/exception.h" |
| |
| #include "naucrates/init.h" |
| #include "naucrates/traceflags/traceflags.h" |
| |
| #include "naucrates/base/CQueryToDXLResult.h" |
| |
| #include "naucrates/md/IMDId.h" |
| #include "naucrates/md/CMDRelationGPDB.h" |
| #include "naucrates/md/CMDIdRelStats.h" |
| #include "naucrates/md/CMDIdColStats.h" |
| |
| #include "naucrates/md/CSystemId.h" |
| #include "naucrates/md/IMDRelStats.h" |
| #include "naucrates/md/IMDColStats.h" |
| #include "naucrates/md/IMDTypeInt8.h" |
| #include "naucrates/md/CMDIdCast.h" |
| #include "naucrates/md/CMDIdScCmp.h" |
| #include "naucrates/md/CMDTypeInt8GPDB.h" |
| |
| #include "naucrates/dxl/operators/CDXLNode.h" |
| #include "naucrates/dxl/parser/CParseHandlerDXL.h" |
| #include "naucrates/dxl/CDXLUtils.h" |
| #include "naucrates/dxl/CIdGenerator.h" |
| #include "naucrates/exception.h" |
| |
| #include "gpdbcost/CCostModelGPDB.h" |
| #include "gpdbcost/CCostModelGPDBLegacy.h" |
| |
| |
| #include "gpopt/gpdbwrappers.h" |
| |
| using namespace gpos; |
| using namespace gpopt; |
| using namespace gpdxl; |
| using namespace gpdbcost; |
| |
| // size of error buffer |
| #define GPOPT_ERROR_BUFFER_SIZE 10 * 1024 * 1024 |
| |
| // definition of default AutoMemoryPool |
| #define AUTO_MEM_POOL(amp) CAutoMemoryPool amp(CAutoMemoryPool::ElcExc, CMemoryPoolManager::EatTracker, false /* fThreadSafe */) |
| |
| // default id for the source system |
| const CSystemId sysidDefault(IMDId::EmdidGPDB, GPOS_WSZ_STR_LENGTH("GPDB")); |
| |
| // array of optimizer minor exception types that trigger expected fallback to the planner |
| const ULONG rgulExpectedOptFallback[] = |
| { |
| gpopt::ExmiInvalidPlanAlternative, // chosen plan id is outside range of possible plans |
| gpopt::ExmiUnsupportedOp, // unsupported operator |
| gpopt::ExmiUnsupportedPred, // unsupported predicate |
| gpopt::ExmiUnsupportedCompositePartKey // composite partitioning keys |
| }; |
| |
| // array of DXL minor exception types that trigger expected fallback to the planner |
| const ULONG rgulExpectedDXLFallback[] = |
| { |
| gpdxl::ExmiMDObjUnsupported, // unsupported metadata object |
| gpdxl::ExmiQuery2DXLUnsupportedFeature, // unsupported feature during algebrization |
| gpdxl::ExmiPlStmt2DXLConversion, // unsupported feature during plan freezing |
| gpdxl::ExmiDXL2PlStmtConversion // unsupported feature during planned statement translation |
| }; |
| |
| // array of DXL minor exception types that error out and NOT fallback to the planner |
| const ULONG rgulExpectedDXLErrors[] = |
| { |
| gpdxl::ExmiDXL2PlStmtExternalScanError, // external table error |
| gpdxl::ExmiQuery2DXLNotNullViolation, // not null violation |
| }; |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // SOptContext::SOptContext |
| // |
| // @doc: |
| // Ctor |
| // |
| //--------------------------------------------------------------------------- |
| SOptContext::SOptContext() |
| : |
| m_szQueryDXL(NULL), |
| m_pquery(NULL), |
| m_szPlanDXL(NULL), |
| m_pplstmt(NULL), |
| m_fGeneratePlStmt(false), |
| m_fSerializePlanDXL(false), |
| m_fUnexpectedFailure(false), |
| m_szErrorMsg(NULL) |
| {} |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // SOptContext::HandleError |
| // |
| // @doc: |
| // If there is an error print as warning and throw GPOS_EXCEPTION to abort |
| // plan generation. Calling elog::ERROR will result in longjump and hence |
| // a memory leak. |
| //--------------------------------------------------------------------------- |
| void |
| SOptContext::HandleError |
| ( |
| BOOL *pfUnexpectedFailure |
| ) |
| { |
| *pfUnexpectedFailure = m_fUnexpectedFailure; |
| if (NULL != m_szErrorMsg) |
| { |
| GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiOptimizerError); |
| } |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // SOptContext::Free |
| // |
| // @doc: |
| // Free all members except those pointed to by either epinInput or |
| // epinOutput |
| // |
| //--------------------------------------------------------------------------- |
| void |
| SOptContext::Free |
| ( |
| SOptContext::EPin epinInput, |
| SOptContext::EPin epinOutput |
| ) |
| { |
| if (NULL != m_szQueryDXL && epinQueryDXL != epinInput && epinQueryDXL != epinOutput) |
| { |
| gpdb::GPDBFree(m_szQueryDXL); |
| } |
| |
| if (NULL != m_pquery && epinQuery != epinInput && epinQuery != epinOutput) |
| { |
| gpdb::GPDBFree(m_pquery); |
| } |
| |
| if (NULL != m_szPlanDXL && epinPlanDXL != epinInput && epinPlanDXL != epinOutput) |
| { |
| gpdb::GPDBFree(m_szPlanDXL); |
| } |
| |
| if (NULL != m_pplstmt && epinPlStmt != epinInput && epinPlStmt != epinOutput) |
| { |
| gpdb::GPDBFree(m_pplstmt); |
| } |
| |
| if (NULL != m_szErrorMsg && epinErrorMsg != epinInput && epinErrorMsg != epinOutput) |
| { |
| gpdb::GPDBFree(m_szErrorMsg); |
| } |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // SOptContext::CloneErrorMsg |
| // |
| // @doc: |
| // Clone m_szErrorMsg to given memory context. Return NULL if there is no |
| // error message. |
| // |
| //--------------------------------------------------------------------------- |
| CHAR* |
| SOptContext::CloneErrorMsg |
| ( |
| MemoryContext context |
| ) |
| { |
| if (NULL == context || |
| NULL == m_szErrorMsg) |
| { |
| return NULL; |
| } |
| return gpdb::SzMemoryContextStrdup(context, m_szErrorMsg); |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // SOptContext::PoptctxtConvert |
| // |
| // @doc: |
| // Casting function |
| // |
| //--------------------------------------------------------------------------- |
| SOptContext * |
| SOptContext::PoptctxtConvert |
| ( |
| void *pv |
| ) |
| { |
| GPOS_ASSERT(NULL != pv); |
| |
| return reinterpret_cast<SOptContext*>(pv); |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::SContextRelcacheToDXL::SContextRelcacheToDXL |
| // |
| // @doc: |
| // Ctor |
| // |
| //--------------------------------------------------------------------------- |
| COptTasks::SContextRelcacheToDXL::SContextRelcacheToDXL |
| ( |
| List *plistOids, |
| ULONG ulCmpt, |
| const char *szFilename |
| ) |
| : |
| m_plistOids(plistOids), |
| m_ulCmpt(ulCmpt), |
| m_szFilename(szFilename) |
| { |
| GPOS_ASSERT(NULL != plistOids); |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::SContextRelcacheToDXL::PctxrelcacheConvert |
| // |
| // @doc: |
| // Casting function |
| // |
| //--------------------------------------------------------------------------- |
| COptTasks::SContextRelcacheToDXL * |
| COptTasks::SContextRelcacheToDXL::PctxrelcacheConvert |
| ( |
| void *pv |
| ) |
| { |
| GPOS_ASSERT(NULL != pv); |
| |
| return reinterpret_cast<SContextRelcacheToDXL*>(pv); |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::SEvalExprContext::PevalctxtConvert |
| // |
| // @doc: |
| // Casting function |
| // |
| //--------------------------------------------------------------------------- |
| COptTasks::SEvalExprContext * |
| COptTasks::SEvalExprContext::PevalctxtConvert |
| ( |
| void *pv |
| ) |
| { |
| GPOS_ASSERT(NULL != pv); |
| |
| return reinterpret_cast<SEvalExprContext*>(pv); |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::SOptimizeMinidumpContext::PexecmdpConvert |
| // |
| // @doc: |
| // Casting function |
| // |
| //--------------------------------------------------------------------------- |
| COptTasks::SOptimizeMinidumpContext * |
| COptTasks::SOptimizeMinidumpContext::PoptmdpConvert |
| ( |
| void *pv |
| ) |
| { |
| GPOS_ASSERT(NULL != pv); |
| |
| return reinterpret_cast<SOptimizeMinidumpContext*>(pv); |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // SzAllocate |
| // |
| // @doc: |
| // Allocate string buffer with protection against OOM |
| // |
| //--------------------------------------------------------------------------- |
| CHAR * |
| COptTasks::SzAllocate |
| ( |
| IMemoryPool *pmp, |
| ULONG ulSize |
| ) |
| { |
| CHAR *sz = NULL; |
| GPOS_TRY |
| { |
| // allocation of string buffer may happen outside gpos_exec() function, |
| // we must guard against system OOM here |
| #ifdef FAULT_INJECTOR |
| gpdb::OptTasksFaultInjector(OptTaskAllocateStringBuffer); |
| #endif // FAULT_INJECTOR |
| |
| if (NULL == pmp) |
| { |
| sz = (CHAR *) gpdb::GPDBAlloc(ulSize); |
| } |
| else |
| { |
| sz = GPOS_NEW_ARRAY(pmp, CHAR, ulSize); |
| } |
| } |
| GPOS_CATCH_EX(ex) |
| { |
| GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiNoAvailableMemory); |
| } |
| GPOS_CATCH_END; |
| |
| return sz; |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // SzFromWsz |
| // |
| // @doc: |
| // Return regular string from wide-character string |
| // |
| //--------------------------------------------------------------------------- |
| CHAR * |
| COptTasks::SzFromWsz |
| ( |
| const WCHAR *wsz |
| ) |
| { |
| GPOS_ASSERT(NULL != wsz); |
| |
| const ULONG ulInputLength = GPOS_WSZ_LENGTH(wsz); |
| const ULONG ulWCHARSize = GPOS_SIZEOF(WCHAR); |
| const ULONG ulMaxLength = (ulInputLength + 1) * ulWCHARSize; |
| |
| CHAR *sz = SzAllocate(NULL, ulMaxLength); |
| |
| gpos::clib::LWcsToMbs(sz, const_cast<WCHAR *>(wsz), ulMaxLength); |
| sz[ulMaxLength - 1] = '\0'; |
| |
| return sz; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::PvMDCast |
| // |
| // @doc: |
| // Task that dumps the relcache info for a cast object into DXL |
| // |
| //--------------------------------------------------------------------------- |
| void* |
| COptTasks::PvMDCast |
| ( |
| void *pv |
| ) |
| { |
| GPOS_ASSERT(NULL != pv); |
| |
| SContextRelcacheToDXL *pctxrelcache = SContextRelcacheToDXL::PctxrelcacheConvert(pv); |
| GPOS_ASSERT(NULL != pctxrelcache); |
| |
| GPOS_ASSERT(2 == gpdb::UlListLength(pctxrelcache->m_plistOids)); |
| Oid oidSrc = gpdb::OidListNth(pctxrelcache->m_plistOids, 0); |
| Oid oidDest = gpdb::OidListNth(pctxrelcache->m_plistOids, 1); |
| |
| CAutoMemoryPool amp(CAutoMemoryPool::ElcExc); |
| IMemoryPool *pmp = amp.Pmp(); |
| |
| DrgPimdobj *pdrgpmdobj = GPOS_NEW(pmp) DrgPimdobj(pmp); |
| |
| IMDId *pmdidCast = GPOS_NEW(pmp) CMDIdCast |
| ( |
| CTranslatorUtils::PmdidWithVersion(pmp, oidSrc), |
| CTranslatorUtils::PmdidWithVersion(pmp, oidDest) |
| ); |
| |
| // relcache MD provider |
| CMDProviderRelcache *pmdpr = GPOS_NEW(pmp) CMDProviderRelcache(pmp); |
| |
| { |
| CAutoMDAccessor amda(pmp, pmdpr, sysidDefault); |
| |
| IMDCacheObject *pmdobj = CTranslatorRelcacheToDXL::Pimdobj(pmp, amda.Pmda(), pmdidCast); |
| GPOS_ASSERT(NULL != pmdobj); |
| |
| pdrgpmdobj->Append(pmdobj); |
| pmdidCast->Release(); |
| |
| CWStringDynamic str(pmp); |
| COstreamString oss(&str); |
| |
| CDXLUtils::PstrSerializeMetadata(pmp, pdrgpmdobj, oss, true /*fSerializeHeaderFooter*/, true /*fIndent*/); |
| CHAR *sz = SzFromWsz(str.Wsz()); |
| GPOS_ASSERT(NULL != sz); |
| |
| pctxrelcache->m_szDXL = sz; |
| |
| // cleanup |
| pdrgpmdobj->Release(); |
| } |
| |
| return NULL; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::PvMDScCmp |
| // |
| // @doc: |
| // Task that dumps the relcache info for a scalar comparison object into DXL |
| // |
| //--------------------------------------------------------------------------- |
| void* |
| COptTasks::PvMDScCmp |
| ( |
| void *pv |
| ) |
| { |
| GPOS_ASSERT(NULL != pv); |
| |
| SContextRelcacheToDXL *pctxrelcache = SContextRelcacheToDXL::PctxrelcacheConvert(pv); |
| GPOS_ASSERT(NULL != pctxrelcache); |
| GPOS_ASSERT(CmptOther > pctxrelcache->m_ulCmpt && "Incorrect comparison type specified"); |
| |
| GPOS_ASSERT(2 == gpdb::UlListLength(pctxrelcache->m_plistOids)); |
| Oid oidLeft = gpdb::OidListNth(pctxrelcache->m_plistOids, 0); |
| Oid oidRight = gpdb::OidListNth(pctxrelcache->m_plistOids, 1); |
| CmpType cmpt = (CmpType) pctxrelcache->m_ulCmpt; |
| |
| CAutoMemoryPool amp(CAutoMemoryPool::ElcExc); |
| IMemoryPool *pmp = amp.Pmp(); |
| |
| DrgPimdobj *pdrgpmdobj = GPOS_NEW(pmp) DrgPimdobj(pmp); |
| |
| IMDId *pmdidScCmp = GPOS_NEW(pmp) CMDIdScCmp |
| ( |
| CTranslatorUtils::PmdidWithVersion(pmp, oidLeft), |
| CTranslatorUtils::PmdidWithVersion(pmp, oidRight), |
| CTranslatorRelcacheToDXL::Ecmpt(cmpt) |
| ); |
| |
| // relcache MD provider |
| CMDProviderRelcache *pmdpr = GPOS_NEW(pmp) CMDProviderRelcache(pmp); |
| |
| { |
| CAutoMDAccessor amda(pmp, pmdpr, sysidDefault); |
| |
| IMDCacheObject *pmdobj = CTranslatorRelcacheToDXL::Pimdobj(pmp, amda.Pmda(), pmdidScCmp); |
| GPOS_ASSERT(NULL != pmdobj); |
| |
| pdrgpmdobj->Append(pmdobj); |
| pmdidScCmp->Release(); |
| |
| CWStringDynamic str(pmp); |
| COstreamString oss(&str); |
| |
| CDXLUtils::PstrSerializeMetadata(pmp, pdrgpmdobj, oss, true /*fSerializeHeaderFooter*/, true /*fIndent*/); |
| CHAR *sz = SzFromWsz(str.Wsz()); |
| GPOS_ASSERT(NULL != sz); |
| |
| pctxrelcache->m_szDXL = sz; |
| |
| // cleanup |
| pdrgpmdobj->Release(); |
| } |
| |
| return NULL; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::Execute |
| // |
| // @doc: |
| // Execute a task using GPOS. TODO extend gpos to provide |
| // this functionality |
| // |
| //--------------------------------------------------------------------------- |
| void |
| COptTasks::Execute |
| ( |
| void *(*pfunc) (void *) , |
| void *pfuncArg |
| ) |
| { |
| Assert(pfunc); |
| |
| // initialize DXL support |
| InitDXL(); |
| |
| bool abort_flag = false; |
| |
| CAutoMemoryPool amp(CAutoMemoryPool::ElcNone, CMemoryPoolManager::EatTracker, false /* fThreadSafe */); |
| IMemoryPool *pmp = amp.Pmp(); |
| CHAR *err_buf = SzAllocate(pmp, GPOPT_ERROR_BUFFER_SIZE); |
| |
| gpos_exec_params params; |
| params.func = pfunc; |
| params.arg = pfuncArg; |
| params.stack_start = ¶ms; |
| params.error_buffer = err_buf; |
| params.error_buffer_size = GPOPT_ERROR_BUFFER_SIZE; |
| params.abort_requested = &abort_flag; |
| |
| // execute task and send log message to server log |
| GPOS_TRY |
| { |
| (void) gpos_exec(¶ms); |
| } |
| GPOS_CATCH_EX(ex) |
| { |
| LogErrorAndDelete(err_buf); |
| GPOS_RETHROW(ex); |
| } |
| GPOS_CATCH_END; |
| LogErrorAndDelete(err_buf); |
| } |
| |
| void |
| COptTasks::LogErrorAndDelete(CHAR* err_buf) { |
| |
| if ('\0' != err_buf[0]) |
| { |
| elog(LOG, "%s", SzFromWsz((WCHAR *)err_buf)); |
| } |
| |
| GPOS_DELETE_ARRAY(err_buf); |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::PvDXLFromQueryTask |
| // |
| // @doc: |
| // task that does the translation from query to XML |
| // |
| //--------------------------------------------------------------------------- |
| void* |
| COptTasks::PvDXLFromQueryTask |
| ( |
| void *pv |
| ) |
| { |
| GPOS_ASSERT(NULL != pv); |
| |
| SOptContext *poctx = SOptContext::PoptctxtConvert(pv); |
| |
| GPOS_ASSERT(NULL != poctx->m_pquery); |
| GPOS_ASSERT(NULL == poctx->m_szQueryDXL); |
| |
| AUTO_MEM_POOL(amp); |
| IMemoryPool *pmp = amp.Pmp(); |
| |
| // ColId generator |
| CIdGenerator *pidgtorCol = GPOS_NEW(pmp) CIdGenerator(GPDXL_COL_ID_START); |
| CIdGenerator *pidgtorCTE = GPOS_NEW(pmp) CIdGenerator(GPDXL_CTE_ID_START); |
| |
| // map that stores gpdb att to optimizer col mapping |
| CMappingVarColId *pmapvarcolid = GPOS_NEW(pmp) CMappingVarColId(pmp); |
| |
| // relcache MD provider |
| CMDProviderRelcache *pmdpr = GPOS_NEW(pmp) CMDProviderRelcache(pmp); |
| |
| { |
| CAutoMDAccessor amda(pmp, pmdpr, sysidDefault); |
| |
| CAutoP<CTranslatorQueryToDXL> ptrquerytodxl; |
| ptrquerytodxl = CTranslatorQueryToDXL::PtrquerytodxlInstance |
| ( |
| pmp, |
| amda.Pmda(), |
| pidgtorCol, |
| pidgtorCTE, |
| pmapvarcolid, |
| (Query*)poctx->m_pquery, |
| 0 /* ulQueryLevel */ |
| ); |
| CDXLNode *pdxlnQuery = ptrquerytodxl->PdxlnFromQuery(); |
| DrgPdxln *pdrgpdxlnQueryOutput = ptrquerytodxl->PdrgpdxlnQueryOutput(); |
| DrgPdxln *pdrgpdxlnCTE = ptrquerytodxl->PdrgpdxlnCTE(); |
| GPOS_ASSERT(NULL != pdrgpdxlnQueryOutput); |
| |
| GPOS_DELETE(pidgtorCol); |
| GPOS_DELETE(pidgtorCTE); |
| |
| CWStringDynamic str(pmp); |
| COstreamString oss(&str); |
| |
| CWStringDynamic *pstrDXL = |
| CDXLUtils::PstrSerializeQuery |
| ( |
| pmp, |
| pdxlnQuery, |
| pdrgpdxlnQueryOutput, |
| pdrgpdxlnCTE, |
| true, // fSerializeHeaderFooter |
| true // fIndent |
| ); |
| poctx->m_szQueryDXL = SzFromWsz(pstrDXL->Wsz()); |
| |
| // clean up |
| pdxlnQuery->Release(); |
| GPOS_DELETE(pstrDXL); |
| } |
| |
| return NULL; |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::Pplstmt |
| // |
| // @doc: |
| // Translate a DXL tree into a planned statement |
| // |
| //--------------------------------------------------------------------------- |
| PlannedStmt * |
| COptTasks::Pplstmt |
| ( |
| IMemoryPool *pmp, |
| CMDAccessor *pmda, |
| const CDXLNode *pdxln, |
| bool canSetTag |
| ) |
| { |
| |
| GPOS_ASSERT(NULL != pmda); |
| GPOS_ASSERT(NULL != pdxln); |
| |
| CIdGenerator idgtorPlanId(1 /* ulStartId */); |
| CIdGenerator idgtorMotionId(1 /* ulStartId */); |
| CIdGenerator idgtorParamId(0 /* ulStartId */); |
| |
| List *plRTable = NULL; |
| List *plSubplans = NULL; |
| |
| CContextDXLToPlStmt ctxdxltoplstmt |
| ( |
| pmp, |
| &idgtorPlanId, |
| &idgtorMotionId, |
| &idgtorParamId, |
| &plRTable, |
| &plSubplans |
| ); |
| |
| // translate DXL -> PlannedStmt |
| CTranslatorDXLToPlStmt trdxltoplstmt(pmp, pmda, &ctxdxltoplstmt, gpdb::UlSegmentCountGP()); |
| return trdxltoplstmt.PplstmtFromDXL(pdxln, canSetTag); |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::PdrgPssLoad |
| // |
| // @doc: |
| // Load search strategy from given file |
| // |
| //--------------------------------------------------------------------------- |
| DrgPss * |
| COptTasks::PdrgPssLoad |
| ( |
| IMemoryPool *pmp, |
| char *szPath |
| ) |
| { |
| DrgPss *pdrgpss = NULL; |
| CParseHandlerDXL *pphDXL = NULL; |
| |
| GPOS_TRY |
| { |
| if (NULL != szPath) |
| { |
| pphDXL = CDXLUtils::PphdxlParseDXLFile(pmp, szPath, NULL); |
| if (NULL != pphDXL) |
| { |
| elog(DEBUG2, "\n[OPT]: Using search strategy in (%s)", szPath); |
| |
| pdrgpss = pphDXL->Pdrgpss(); |
| pdrgpss->AddRef(); |
| } |
| } |
| } |
| GPOS_CATCH_EX(ex) |
| { |
| if (GPOS_MATCH_EX(ex, gpdxl::ExmaGPDB, gpdxl::ExmiGPDBError)) { |
| GPOS_RETHROW(ex); |
| } |
| elog(DEBUG2, "\n[OPT]: Using default search strategy"); |
| GPOS_RESET_EX; |
| } |
| GPOS_CATCH_END; |
| |
| GPOS_DELETE(pphDXL); |
| |
| return pdrgpss; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::PoconfCreate |
| // |
| // @doc: |
| // Create the optimizer configuration |
| // |
| //--------------------------------------------------------------------------- |
| COptimizerConfig * |
| COptTasks::PoconfCreate |
| ( |
| IMemoryPool *pmp, |
| ICostModel *pcm |
| ) |
| { |
| // get chosen plan number, cost threshold |
| ULLONG ullPlanId = (ULLONG) optimizer_plan_id; |
| ULLONG ullSamples = (ULLONG) optimizer_samples_number; |
| DOUBLE dCostThreshold = (DOUBLE) optimizer_cost_threshold; |
| |
| DOUBLE dDampingFactorFilter = (DOUBLE) optimizer_damping_factor_filter; |
| DOUBLE dDampingFactorJoin = (DOUBLE) optimizer_damping_factor_join; |
| DOUBLE dDampingFactorGroupBy = (DOUBLE) optimizer_damping_factor_groupby; |
| |
| ULONG ulCTEInliningCutoff = (ULONG) optimizer_cte_inlining_bound; |
| ULONG ulPartsToForceSortOnInsert = (ULONG) optimizer_parts_to_force_sort_on_insert; |
| ULONG ulJoinArityForAssociativityCommutativity = (ULONG) optimizer_join_arity_for_associativity_commutativity; |
| ULONG ulArrayExpansionThreshold = (ULONG) optimizer_array_expansion_threshold; |
| ULONG ulJoinOrderThreshold = (ULONG) optimizer_join_order_threshold; |
| |
| return GPOS_NEW(pmp) COptimizerConfig |
| ( |
| GPOS_NEW(pmp) CEnumeratorConfig(pmp, ullPlanId, ullSamples, dCostThreshold), |
| GPOS_NEW(pmp) CStatisticsConfig(pmp, dDampingFactorFilter, dDampingFactorJoin, dDampingFactorGroupBy), |
| GPOS_NEW(pmp) CCTEConfig(ulCTEInliningCutoff), |
| pcm, |
| GPOS_NEW(pmp) CHint |
| ( |
| ulPartsToForceSortOnInsert /* optimizer_parts_to_force_sort_on_insert */, |
| ulJoinArityForAssociativityCommutativity, |
| ulArrayExpansionThreshold, |
| ulJoinOrderThreshold |
| ) |
| ); |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::FExceptionFound |
| // |
| // @doc: |
| // Lookup given exception type in the given array |
| // |
| //--------------------------------------------------------------------------- |
| BOOL |
| COptTasks::FExceptionFound |
| ( |
| gpos::CException &exc, |
| const ULONG *pulExceptions, |
| ULONG ulSize |
| ) |
| { |
| GPOS_ASSERT(NULL != pulExceptions); |
| |
| ULONG ulMinor = exc.UlMinor(); |
| BOOL fFound = false; |
| for (ULONG ul = 0; !fFound && ul < ulSize; ul++) |
| { |
| fFound = (pulExceptions[ul] == ulMinor); |
| } |
| |
| return fFound; |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::FUnexpectedFailure |
| // |
| // @doc: |
| // Check if given exception is an unexpected reason for failing to |
| // produce a plan |
| // |
| //--------------------------------------------------------------------------- |
| BOOL |
| COptTasks::FUnexpectedFailure |
| ( |
| gpos::CException &exc |
| ) |
| { |
| ULONG ulMajor = exc.UlMajor(); |
| |
| BOOL fExpectedOptFailure = |
| gpopt::ExmaGPOPT == ulMajor && |
| FExceptionFound(exc, rgulExpectedOptFallback, GPOS_ARRAY_SIZE(rgulExpectedOptFallback)); |
| |
| BOOL fExpectedDXLFailure = |
| gpdxl::ExmaDXL == ulMajor && |
| FExceptionFound(exc, rgulExpectedDXLFallback, GPOS_ARRAY_SIZE(rgulExpectedDXLFallback)); |
| |
| return (!fExpectedOptFailure && !fExpectedDXLFailure); |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::FErrorOut |
| // |
| // @doc: |
| // Check if given exception should error out |
| // |
| //--------------------------------------------------------------------------- |
| BOOL |
| COptTasks::FErrorOut |
| ( |
| gpos::CException &exc |
| ) |
| { |
| return |
| gpdxl::ExmaDXL == exc.UlMajor() && |
| FExceptionFound(exc, rgulExpectedDXLErrors, GPOS_ARRAY_SIZE(rgulExpectedDXLErrors)); |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::SetCostModelParams |
| // |
| // @doc: |
| // Set cost model parameters |
| // |
| //--------------------------------------------------------------------------- |
| void |
| COptTasks::SetCostModelParams |
| ( |
| ICostModel *pcm |
| ) |
| { |
| GPOS_ASSERT(NULL != pcm); |
| |
| if (optimizer_nestloop_factor > 1.0) |
| { |
| // change NLJ cost factor |
| ICostModelParams::SCostParam *pcp = NULL; |
| if (OPTIMIZER_GPDB_CALIBRATED == optimizer_cost_model) |
| { |
| pcp = pcm->Pcp()->PcpLookup(CCostModelParamsGPDB::EcpNLJFactor); |
| } |
| else |
| { |
| pcp = pcm->Pcp()->PcpLookup(CCostModelParamsGPDBLegacy::EcpNLJFactor); |
| } |
| CDouble dNLJFactor(optimizer_nestloop_factor); |
| pcm->Pcp()->SetParam(pcp->UlId(), dNLJFactor, dNLJFactor - 0.5, dNLJFactor + 0.5); |
| } |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::Pcm |
| // |
| // @doc: |
| // Generate an instance of optimizer cost model |
| // |
| //--------------------------------------------------------------------------- |
| ICostModel * |
| COptTasks::Pcm |
| ( |
| IMemoryPool *pmp, |
| ULONG ulSegments |
| ) |
| { |
| ICostModel *pcm = NULL; |
| if (OPTIMIZER_GPDB_CALIBRATED == optimizer_cost_model) |
| { |
| pcm = GPOS_NEW(pmp) CCostModelGPDB(pmp, ulSegments); |
| } |
| else |
| { |
| pcm = GPOS_NEW(pmp) CCostModelGPDBLegacy(pmp, ulSegments); |
| } |
| |
| SetCostModelParams(pcm); |
| |
| return pcm; |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::PvOptimizeTask |
| // |
| // @doc: |
| // task that does the optimizes query to physical DXL |
| // |
| //--------------------------------------------------------------------------- |
| void* |
| COptTasks::PvOptimizeTask |
| ( |
| void *pv |
| ) |
| { |
| GPOS_ASSERT(NULL != pv); |
| SOptContext *poctx = SOptContext::PoptctxtConvert(pv); |
| |
| GPOS_ASSERT(NULL != poctx->m_pquery); |
| GPOS_ASSERT(NULL == poctx->m_szPlanDXL); |
| GPOS_ASSERT(NULL == poctx->m_pplstmt); |
| |
| // initially assume no unexpected failure |
| poctx->m_fUnexpectedFailure = false; |
| |
| AUTO_MEM_POOL(amp); |
| IMemoryPool *pmp = amp.Pmp(); |
| |
| // initialize metadata cache |
| if (!CMDCache::FInitialized()) |
| { |
| CMDCache::Init(); |
| } |
| |
| // load search strategy |
| DrgPss *pdrgpss = PdrgPssLoad(pmp, optimizer_search_strategy_path); |
| |
| CBitSet *pbsTraceFlags = NULL; |
| CBitSet *pbsEnabled = NULL; |
| CBitSet *pbsDisabled = NULL; |
| CDXLNode *pdxlnPlan = NULL; |
| |
| DrgPmdid *pdrgmdidCol = NULL; |
| HMMDIdMDId *phmmdidRel = NULL; |
| |
| GPOS_TRY |
| { |
| // set trace flags |
| pbsTraceFlags = CConfigParamMapping::PbsPack(pmp, CXform::ExfSentinel); |
| SetTraceflags(pmp, pbsTraceFlags, &pbsEnabled, &pbsDisabled); |
| |
| // set up relcache MD provider |
| CMDProviderRelcache *pmdpRelcache = GPOS_NEW(pmp) CMDProviderRelcache(pmp); |
| |
| { |
| // scope for MD accessor |
| CMDAccessor mda(pmp, CMDCache::Pcache(), sysidDefault, pmdpRelcache); |
| |
| // ColId generator |
| CIdGenerator idgtorColId(GPDXL_COL_ID_START); |
| CIdGenerator idgtorCTE(GPDXL_CTE_ID_START); |
| |
| // map that stores gpdb att to optimizer col mapping |
| CMappingVarColId *pmapvarcolid = GPOS_NEW(pmp) CMappingVarColId(pmp); |
| |
| ULONG ulSegments = gpdb::UlSegmentCountGP(); |
| ULONG ulSegmentsForCosting = optimizer_segments; |
| if (0 == ulSegmentsForCosting) |
| { |
| ulSegmentsForCosting = ulSegments; |
| } |
| |
| CAutoP<CTranslatorQueryToDXL> ptrquerytodxl; |
| ptrquerytodxl = CTranslatorQueryToDXL::PtrquerytodxlInstance |
| ( |
| pmp, |
| &mda, |
| &idgtorColId, |
| &idgtorCTE, |
| pmapvarcolid, |
| (Query*) poctx->m_pquery, |
| 0 /* ulQueryLevel */ |
| ); |
| |
| ICostModel *pcm = Pcm(pmp, ulSegmentsForCosting); |
| COptimizerConfig *pocconf = PoconfCreate(pmp, pcm); |
| CConstExprEvaluatorProxy ceevalproxy(pmp, &mda); |
| IConstExprEvaluator *pceeval = |
| GPOS_NEW(pmp) CConstExprEvaluatorDXL(pmp, &mda, &ceevalproxy); |
| |
| CDXLNode *pdxlnQuery = ptrquerytodxl->PdxlnFromQuery(); |
| DrgPdxln *pdrgpdxlnQueryOutput = ptrquerytodxl->PdrgpdxlnQueryOutput(); |
| DrgPdxln *pdrgpdxlnCTE = ptrquerytodxl->PdrgpdxlnCTE(); |
| GPOS_ASSERT(NULL != pdrgpdxlnQueryOutput); |
| |
| BOOL fMasterOnly = !optimizer_enable_motions || |
| (!optimizer_enable_motions_masteronly_queries && !ptrquerytodxl->FHasDistributedTables()); |
| CAutoTraceFlag atf(EopttraceDisableMotions, fMasterOnly); |
| |
| pdxlnPlan = COptimizer::PdxlnOptimize |
| ( |
| pmp, |
| &mda, |
| pdxlnQuery, |
| pdrgpdxlnQueryOutput, |
| pdrgpdxlnCTE, |
| pceeval, |
| ulSegments, |
| gp_session_id, |
| gp_command_count, |
| pdrgpss, |
| pocconf |
| ); |
| |
| if (poctx->m_fSerializePlanDXL) |
| { |
| // serialize DXL to xml |
| CWStringDynamic *pstrPlan = CDXLUtils::PstrSerializePlan(pmp, pdxlnPlan, pocconf->Pec()->UllPlanId(), pocconf->Pec()->UllPlanSpaceSize(), true /*fSerializeHeaderFooter*/, true /*fIndent*/); |
| poctx->m_szPlanDXL = SzFromWsz(pstrPlan->Wsz()); |
| GPOS_DELETE(pstrPlan); |
| } |
| |
| // translate DXL->PlStmt only when needed |
| if (poctx->m_fGeneratePlStmt) |
| { |
| // always use poctx->m_pquery->canSetTag as the ptrquerytodxl->Pquery() is a mutated Query object |
| // that may not have the correct canSetTag |
| poctx->m_pplstmt = (PlannedStmt *) gpdb::PvCopyObject(Pplstmt(pmp, &mda, pdxlnPlan, poctx->m_pquery->canSetTag)); |
| } |
| |
| CStatisticsConfig *pstatsconf = pocconf->Pstatsconf(); |
| pdrgmdidCol = GPOS_NEW(pmp) DrgPmdid(pmp); |
| pstatsconf->CollectMissingStatsColumns(pdrgmdidCol); |
| |
| phmmdidRel = GPOS_NEW(pmp) HMMDIdMDId(pmp); |
| PrintMissingStatsWarning(pmp, &mda, pdrgmdidCol, phmmdidRel); |
| |
| phmmdidRel->Release(); |
| pdrgmdidCol->Release(); |
| |
| pceeval->Release(); |
| pdxlnQuery->Release(); |
| pocconf->Release(); |
| pdxlnPlan->Release(); |
| } |
| } |
| GPOS_CATCH_EX(ex) |
| { |
| ResetTraceflags(pbsEnabled, pbsDisabled); |
| CRefCount::SafeRelease(phmmdidRel); |
| CRefCount::SafeRelease(pdrgmdidCol); |
| CRefCount::SafeRelease(pbsEnabled); |
| CRefCount::SafeRelease(pbsDisabled); |
| CRefCount::SafeRelease(pbsTraceFlags); |
| CRefCount::SafeRelease(pdxlnPlan); |
| CMDCache::Shutdown(); |
| |
| if (GPOS_MATCH_EX(ex, gpdxl::ExmaGPDB, gpdxl::ExmiGPDBError)) |
| { |
| elog(DEBUG1, "GPDB Exception. Please check log for more information."); |
| } |
| else if (FErrorOut(ex)) |
| { |
| IErrorContext *perrctxt = CTask::PtskSelf()->Perrctxt(); |
| poctx->m_szErrorMsg = SzFromWsz(perrctxt->WszMsg()); |
| } |
| else |
| { |
| poctx->m_fUnexpectedFailure = FUnexpectedFailure(ex); |
| } |
| GPOS_RETHROW(ex); |
| } |
| GPOS_CATCH_END; |
| |
| // cleanup |
| ResetTraceflags(pbsEnabled, pbsDisabled); |
| CRefCount::SafeRelease(pbsEnabled); |
| CRefCount::SafeRelease(pbsDisabled); |
| CRefCount::SafeRelease(pbsTraceFlags); |
| if (optimizer_release_mdcache) |
| { |
| CMDCache::Shutdown(); |
| } |
| |
| return NULL; |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::PrintMissingStatsWarning |
| // |
| // @doc: |
| // Print warning messages for columns with missing statistics |
| // |
| //--------------------------------------------------------------------------- |
| void |
| COptTasks::PrintMissingStatsWarning |
| ( |
| IMemoryPool *pmp, |
| CMDAccessor *pmda, |
| DrgPmdid *pdrgmdidCol, |
| HMMDIdMDId *phmmdidRel |
| ) |
| { |
| GPOS_ASSERT(NULL != pmda); |
| GPOS_ASSERT(NULL != pdrgmdidCol); |
| GPOS_ASSERT(NULL != phmmdidRel); |
| |
| CWStringDynamic str(pmp); |
| COstreamString oss(&str); |
| |
| const ULONG ulMissingColStats = pdrgmdidCol->UlLength(); |
| for (ULONG ul = 0; ul < ulMissingColStats; ul++) |
| { |
| IMDId *pmdid = (*pdrgmdidCol)[ul]; |
| CMDIdColStats *pmdidColStats = CMDIdColStats::PmdidConvert(pmdid); |
| |
| IMDId *pmdidRel = pmdidColStats->PmdidRel(); |
| const ULONG ulPos = pmdidColStats->UlPos(); |
| const IMDRelation *pmdrel = pmda->Pmdrel(pmdidRel); |
| |
| if (IMDRelation::ErelstorageExternal != pmdrel->Erelstorage()) |
| { |
| if (NULL == phmmdidRel->PtLookup(pmdidRel)) |
| { |
| if (0 != ul) |
| { |
| oss << ", "; |
| } |
| |
| pmdidRel->AddRef(); |
| pmdidRel->AddRef(); |
| phmmdidRel->FInsert(pmdidRel, pmdidRel); |
| oss << pmdrel->Mdname().Pstr()->Wsz(); |
| } |
| |
| CMDName mdname = pmdrel->Pmdcol(ulPos)->Mdname(); |
| elog(LOG, "Missing statistics for column: %s.%s", SzFromWsz(pmdrel->Mdname().Pstr()->Wsz()), SzFromWsz(mdname.Pstr()->Wsz())); |
| } |
| } |
| |
| if (0 < phmmdidRel->UlEntries()) |
| { |
| ereport(NOTICE, |
| (errcode(ERRCODE_SUCCESSFUL_COMPLETION), |
| errmsg("One or more columns in the following table(s) do not have statistics: %s", SzFromWsz(str.Wsz())), |
| errhint("For non-partitioned tables, run analyze <table_name>(<column_list>)." |
| " For partitioned tables, run analyze rootpartition <table_name>(<column_list>)." |
| " See log for columns missing statistics."), |
| errOmitLocation(true))); |
| } |
| |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::PvOptimizeMinidumpTask |
| // |
| // @doc: |
| // Task that loads and optimizes a minidump and returns the result as string-serialized DXL |
| // |
| //--------------------------------------------------------------------------- |
| void* |
| COptTasks::PvOptimizeMinidumpTask |
| ( |
| void *pv |
| ) |
| { |
| GPOS_ASSERT(NULL != pv); |
| |
| SOptimizeMinidumpContext *poptmdpctxt = SOptimizeMinidumpContext::PoptmdpConvert(pv); |
| GPOS_ASSERT(NULL != poptmdpctxt->m_szFileName); |
| GPOS_ASSERT(NULL == poptmdpctxt->m_szDXLResult); |
| |
| AUTO_MEM_POOL(amp); |
| IMemoryPool *pmp = amp.Pmp(); |
| |
| ULONG ulSegments = gpdb::UlSegmentCountGP(); |
| ULONG ulSegmentsForCosting = optimizer_segments; |
| if (0 == ulSegmentsForCosting) |
| { |
| ulSegmentsForCosting = ulSegments; |
| } |
| |
| ICostModel *pcm = Pcm(pmp, ulSegmentsForCosting); |
| COptimizerConfig *pocconf = PoconfCreate(pmp, pcm); |
| CDXLNode *pdxlnResult = NULL; |
| |
| GPOS_TRY |
| { |
| pdxlnResult = CMinidumperUtils::PdxlnExecuteMinidump(pmp, poptmdpctxt->m_szFileName, ulSegments, gp_session_id, gp_command_count, pocconf); |
| } |
| GPOS_CATCH_EX(ex) |
| { |
| CRefCount::SafeRelease(pdxlnResult); |
| CRefCount::SafeRelease(pocconf); |
| GPOS_RETHROW(ex); |
| } |
| GPOS_CATCH_END; |
| CWStringDynamic *pstrDXL = |
| CDXLUtils::PstrSerializePlan |
| ( |
| pmp, |
| pdxlnResult, |
| 0, // ullPlanId |
| 0, // ullPlanSpaceSize |
| true, // fSerializeHeaderFooter |
| true // fIndent |
| ); |
| poptmdpctxt->m_szDXLResult = SzFromWsz(pstrDXL->Wsz()); |
| GPOS_DELETE(pstrDXL); |
| CRefCount::SafeRelease(pdxlnResult); |
| pocconf->Release(); |
| |
| return NULL; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::PvPlstmtFromDXLTask |
| // |
| // @doc: |
| // task that does the translation from xml to dxl to pplstmt |
| // |
| //--------------------------------------------------------------------------- |
| void* |
| COptTasks::PvPlstmtFromDXLTask |
| ( |
| void *pv |
| ) |
| { |
| GPOS_ASSERT(NULL != pv); |
| |
| SOptContext *poctx = SOptContext::PoptctxtConvert(pv); |
| |
| GPOS_ASSERT(NULL == poctx->m_pquery); |
| GPOS_ASSERT(NULL != poctx->m_szPlanDXL); |
| |
| AUTO_MEM_POOL(amp); |
| IMemoryPool *pmp = amp.Pmp(); |
| |
| CWStringDynamic str(pmp); |
| COstreamString oss(&str); |
| |
| ULLONG ullPlanId = 0; |
| ULLONG ullPlanSpaceSize = 0; |
| CDXLNode *pdxlnOriginal = |
| CDXLUtils::PdxlnParsePlan(pmp, poctx->m_szPlanDXL, NULL /*XSD location*/, &ullPlanId, &ullPlanSpaceSize); |
| |
| CIdGenerator idgtorPlanId(1); |
| CIdGenerator idgtorMotionId(1); |
| CIdGenerator idgtorParamId(0); |
| |
| List *plRTable = NULL; |
| List *plSubplans = NULL; |
| |
| CContextDXLToPlStmt ctxdxlplstmt |
| ( |
| pmp, |
| &idgtorPlanId, |
| &idgtorMotionId, |
| &idgtorParamId, |
| &plRTable, |
| &plSubplans |
| ); |
| |
| // relcache MD provider |
| CMDProviderRelcache *pmdpr = GPOS_NEW(pmp) CMDProviderRelcache(pmp); |
| |
| { |
| CAutoMDAccessor amda(pmp, pmdpr, sysidDefault); |
| |
| // translate DXL -> PlannedStmt |
| CTranslatorDXLToPlStmt trdxltoplstmt(pmp, amda.Pmda(), &ctxdxlplstmt, gpdb::UlSegmentCountGP()); |
| PlannedStmt *pplstmt = trdxltoplstmt.PplstmtFromDXL(pdxlnOriginal, poctx->m_pquery->canSetTag); |
| if (optimizer_print_plan) |
| { |
| elog(NOTICE, "Plstmt: %s", gpdb::SzNodeToString(pplstmt)); |
| } |
| |
| GPOS_ASSERT(NULL != pplstmt); |
| GPOS_ASSERT(NULL != CurrentMemoryContext); |
| |
| poctx->m_pplstmt = (PlannedStmt *) gpdb::PvCopyObject(pplstmt); |
| } |
| |
| // cleanup |
| pdxlnOriginal->Release(); |
| |
| return NULL; |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::PvDXLFromMDObjsTask |
| // |
| // @doc: |
| // task that does dumps the relcache info for an object into DXL |
| // |
| //--------------------------------------------------------------------------- |
| void* |
| COptTasks::PvDXLFromMDObjsTask |
| ( |
| void *pv |
| ) |
| { |
| GPOS_ASSERT(NULL != pv); |
| |
| SContextRelcacheToDXL *pctxrelcache = SContextRelcacheToDXL::PctxrelcacheConvert(pv); |
| GPOS_ASSERT(NULL != pctxrelcache); |
| |
| AUTO_MEM_POOL(amp); |
| IMemoryPool *pmp = amp.Pmp(); |
| |
| DrgPimdobj *pdrgpmdobj = GPOS_NEW(pmp) DrgPimdobj(pmp, 1024, 1024); |
| |
| // relcache MD provider |
| CMDProviderRelcache *pmdp = GPOS_NEW(pmp) CMDProviderRelcache(pmp); |
| { |
| CAutoMDAccessor amda(pmp, pmdp, sysidDefault); |
| ListCell *plc = NULL; |
| ForEach (plc, pctxrelcache->m_plistOids) |
| { |
| Oid oid = lfirst_oid(plc); |
| // get object from relcache |
| CMDIdGPDB *pmdid = CTranslatorUtils::PmdidWithVersion(pmp, oid); |
| |
| IMDCacheObject *pimdobj = CTranslatorRelcacheToDXL::Pimdobj(pmp, amda.Pmda(), pmdid); |
| GPOS_ASSERT(NULL != pimdobj); |
| |
| pdrgpmdobj->Append(pimdobj); |
| pmdid->Release(); |
| } |
| |
| if (pctxrelcache->m_szFilename) |
| { |
| COstreamFile cofs(pctxrelcache->m_szFilename); |
| |
| CDXLUtils::PstrSerializeMetadata(pmp, pdrgpmdobj, cofs, true /*fSerializeHeaderFooter*/, true /*fIndent*/); |
| } |
| else |
| { |
| CWStringDynamic str(pmp); |
| COstreamString oss(&str); |
| |
| CDXLUtils::PstrSerializeMetadata(pmp, pdrgpmdobj, oss, true /*fSerializeHeaderFooter*/, true /*fIndent*/); |
| |
| CHAR *sz = SzFromWsz(str.Wsz()); |
| |
| GPOS_ASSERT(NULL != sz); |
| |
| pctxrelcache->m_szDXL = sz; |
| } |
| } |
| // cleanup |
| pdrgpmdobj->Release(); |
| |
| return NULL; |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::PvDXLFromRelStatsTask |
| // |
| // @doc: |
| // task that dumps relstats info for a table in DXL |
| // |
| //--------------------------------------------------------------------------- |
| void* |
| COptTasks::PvDXLFromRelStatsTask |
| ( |
| void *pv |
| ) |
| { |
| GPOS_ASSERT(NULL != pv); |
| |
| SContextRelcacheToDXL *pctxrelcache = SContextRelcacheToDXL::PctxrelcacheConvert(pv); |
| GPOS_ASSERT(NULL != pctxrelcache); |
| |
| AUTO_MEM_POOL(amp); |
| IMemoryPool *pmp = amp.Pmp(); |
| |
| // relcache MD provider |
| CMDProviderRelcache *pmdpr = GPOS_NEW(pmp) CMDProviderRelcache(pmp); |
| CAutoMDAccessor amda(pmp, pmdpr, sysidDefault); |
| ICostModel *pcm = Pcm(pmp, gpdb::UlSegmentCountGP()); |
| CAutoOptCtxt aoc(pmp, amda.Pmda(), NULL /*pceeval*/, pcm); |
| |
| DrgPimdobj *pdrgpmdobj = GPOS_NEW(pmp) DrgPimdobj(pmp); |
| |
| ListCell *plc = NULL; |
| ForEach (plc, pctxrelcache->m_plistOids) |
| { |
| Oid oidRelation = lfirst_oid(plc); |
| |
| // get object from relcache |
| CMDIdGPDB *pmdid = CTranslatorUtils::PmdidWithVersion(pmp, oidRelation); |
| |
| // generate mdid for relstats |
| CMDIdRelStats *pmdidRelStats = GPOS_NEW(pmp) CMDIdRelStats(pmdid); |
| IMDRelStats *pimdobjrelstats = const_cast<IMDRelStats *>(amda.Pmda()->Pmdrelstats(pmdidRelStats)); |
| pdrgpmdobj->Append(dynamic_cast<IMDCacheObject *>(pimdobjrelstats)); |
| |
| // extract out column stats for this relation |
| Relation rel = gpdb::RelGetRelation(oidRelation); |
| ULONG ulPosCounter = 0; |
| for (ULONG ul = 0; ul < ULONG(rel->rd_att->natts); ul++) |
| { |
| if (!rel->rd_att->attrs[ul]->attisdropped) |
| { |
| pmdid->AddRef(); |
| CMDIdColStats *pmdidColStats = GPOS_NEW(pmp) CMDIdColStats(pmdid, ulPosCounter); |
| ulPosCounter++; |
| IMDColStats *pimdobjcolstats = const_cast<IMDColStats *>(amda.Pmda()->Pmdcolstats(pmdidColStats)); |
| pdrgpmdobj->Append(dynamic_cast<IMDCacheObject *>(pimdobjcolstats)); |
| pmdidColStats->Release(); |
| } |
| } |
| gpdb::CloseRelation(rel); |
| pmdidRelStats->Release(); |
| } |
| |
| if (pctxrelcache->m_szFilename) |
| { |
| COstreamFile cofs(pctxrelcache->m_szFilename); |
| |
| CDXLUtils::PstrSerializeMetadata(pmp, pdrgpmdobj, cofs, true /*fSerializeHeaderFooter*/, true /*fIndent*/); |
| } |
| else |
| { |
| CWStringDynamic str(pmp); |
| COstreamString oss(&str); |
| |
| CDXLUtils::PstrSerializeMetadata(pmp, pdrgpmdobj, oss, true /*fSerializeHeaderFooter*/, true /*fIndent*/); |
| |
| CHAR *sz = SzFromWsz(str.Wsz()); |
| |
| GPOS_ASSERT(NULL != sz); |
| |
| pctxrelcache->m_szDXL = sz; |
| } |
| |
| // cleanup |
| pdrgpmdobj->Release(); |
| |
| return NULL; |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::PvEvalExprFromDXLTask |
| // |
| // @doc: |
| // Task that parses an XML representation of a DXL constant expression, |
| // evaluates it and returns the result as a serialized DXL document. |
| // |
| //--------------------------------------------------------------------------- |
| void* |
| COptTasks::PvEvalExprFromDXLTask |
| ( |
| void *pv |
| ) |
| { |
| GPOS_ASSERT(NULL != pv); |
| SEvalExprContext *pevalctxt = SEvalExprContext::PevalctxtConvert(pv); |
| |
| GPOS_ASSERT(NULL != pevalctxt->m_szDXL); |
| GPOS_ASSERT(NULL == pevalctxt->m_szDXLResult); |
| |
| AUTO_MEM_POOL(amp); |
| IMemoryPool *pmp = amp.Pmp(); |
| |
| CDXLNode *pdxlnInput = CDXLUtils::PdxlnParseScalarExpr(pmp, pevalctxt->m_szDXL, NULL /*szXSDPath*/); |
| GPOS_ASSERT(NULL != pdxlnInput); |
| |
| CDXLNode *pdxlnResult = NULL; |
| BOOL fReleaseCache = false; |
| // initialize metadata cache |
| if (!CMDCache::FInitialized()) |
| { |
| CMDCache::Init(); |
| fReleaseCache = true; |
| } |
| |
| GPOS_TRY |
| { |
| // set up relcache MD provider |
| CMDProviderRelcache *pmdpRelcache = GPOS_NEW(pmp) CMDProviderRelcache(pmp); |
| { |
| // scope for MD accessor |
| CMDAccessor mda(pmp, CMDCache::Pcache(), sysidDefault, pmdpRelcache); |
| |
| CConstExprEvaluatorProxy ceeval(pmp, &mda); |
| pdxlnResult = ceeval.PdxlnEvaluateExpr(pdxlnInput); |
| } |
| } |
| GPOS_CATCH_EX(ex) |
| { |
| CRefCount::SafeRelease(pdxlnResult); |
| CRefCount::SafeRelease(pdxlnInput); |
| if (fReleaseCache) |
| { |
| CMDCache::Shutdown(); |
| } |
| if (FErrorOut(ex)) |
| { |
| IErrorContext *perrctxt = CTask::PtskSelf()->Perrctxt(); |
| char *szErrorMsg = SzFromWsz(perrctxt->WszMsg()); |
| elog(DEBUG1, "%s", szErrorMsg); |
| gpdb::GPDBFree(szErrorMsg); |
| } |
| GPOS_RETHROW(ex); |
| } |
| GPOS_CATCH_END; |
| |
| CWStringDynamic *pstrDXL = |
| CDXLUtils::PstrSerializeScalarExpr |
| ( |
| pmp, |
| pdxlnResult, |
| true, // fSerializeHeaderFooter |
| true // fIndent |
| ); |
| pevalctxt->m_szDXLResult = SzFromWsz(pstrDXL->Wsz()); |
| GPOS_DELETE(pstrDXL); |
| CRefCount::SafeRelease(pdxlnResult); |
| pdxlnInput->Release(); |
| |
| if (fReleaseCache) |
| { |
| CMDCache::Shutdown(); |
| } |
| |
| return NULL; |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::SzOptimize |
| // |
| // @doc: |
| // optimizes a query to physical DXL |
| // |
| //--------------------------------------------------------------------------- |
| char * |
| COptTasks::SzOptimize |
| ( |
| Query *pquery |
| ) |
| { |
| Assert(pquery); |
| |
| SOptContext octx; |
| octx.m_pquery = pquery; |
| octx.m_fSerializePlanDXL = true; |
| Execute(&PvOptimizeTask, &octx); |
| |
| // clean up context |
| octx.Free(octx.epinQuery, octx.epinPlanDXL); |
| |
| return octx.m_szPlanDXL; |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::PplstmtOptimize |
| // |
| // @doc: |
| // optimizes a query to plannedstmt |
| // |
| //--------------------------------------------------------------------------- |
| PlannedStmt * |
| COptTasks::PplstmtOptimize |
| ( |
| Query *pquery, |
| SOptContext *octx, |
| BOOL *pfUnexpectedFailure // output : set to true if optimizer unexpectedly failed to produce plan |
| ) |
| { |
| Assert(pquery); |
| Assert(octx); |
| |
| octx->m_pquery = pquery; |
| octx->m_fGeneratePlStmt= true; |
| GPOS_TRY |
| { |
| Execute(&PvOptimizeTask, octx); |
| } |
| GPOS_CATCH_EX(ex) |
| { |
| *pfUnexpectedFailure = octx->m_fUnexpectedFailure; |
| GPOS_RETHROW(ex); |
| } |
| GPOS_CATCH_END; |
| octx->HandleError(pfUnexpectedFailure); |
| return octx->m_pplstmt; |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::SzDXL |
| // |
| // @doc: |
| // serializes query to DXL |
| // |
| //--------------------------------------------------------------------------- |
| char * |
| COptTasks::SzDXL |
| ( |
| Query *pquery |
| ) |
| { |
| Assert(pquery); |
| |
| SOptContext octx; |
| octx.m_pquery = pquery; |
| Execute(&PvDXLFromQueryTask, &octx); |
| |
| // clean up context |
| octx.Free(octx.epinQuery, octx.epinQueryDXL); |
| |
| return octx.m_szQueryDXL; |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::PplstmtFromXML |
| // |
| // @doc: |
| // deserializes planned stmt from DXL |
| // |
| //--------------------------------------------------------------------------- |
| PlannedStmt * |
| COptTasks::PplstmtFromXML |
| ( |
| char *szDXL |
| ) |
| { |
| Assert(NULL != szDXL); |
| |
| SOptContext octx; |
| octx.m_szPlanDXL = szDXL; |
| Execute(&PvPlstmtFromDXLTask, &octx); |
| |
| // clean up context |
| octx.Free(octx.epinPlanDXL, octx.epinPlStmt); |
| |
| return octx.m_pplstmt; |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::DumpMDObjs |
| // |
| // @doc: |
| // Dump relcache objects into DXL file |
| // |
| //--------------------------------------------------------------------------- |
| void |
| COptTasks::DumpMDObjs |
| ( |
| List *plistOids, |
| const char *szFilename |
| ) |
| { |
| SContextRelcacheToDXL ctxrelcache(plistOids, ULONG_MAX /*ulCmpt*/, szFilename); |
| Execute(&PvDXLFromMDObjsTask, &ctxrelcache); |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::SzMDObjs |
| // |
| // @doc: |
| // Dump relcache objects into DXL string |
| // |
| //--------------------------------------------------------------------------- |
| char * |
| COptTasks::SzMDObjs |
| ( |
| List *plistOids |
| ) |
| { |
| SContextRelcacheToDXL ctxrelcache(plistOids, ULONG_MAX /*ulCmpt*/, NULL /*szFilename*/); |
| Execute(&PvDXLFromMDObjsTask, &ctxrelcache); |
| |
| return ctxrelcache.m_szDXL; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::SzMDCast |
| // |
| // @doc: |
| // Dump cast object into DXL string |
| // |
| //--------------------------------------------------------------------------- |
| char * |
| COptTasks::SzMDCast |
| ( |
| List *plistOids |
| ) |
| { |
| SContextRelcacheToDXL ctxrelcache(plistOids, ULONG_MAX /*ulCmpt*/, NULL /*szFilename*/); |
| Execute(&PvMDCast, &ctxrelcache); |
| |
| return ctxrelcache.m_szDXL; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::SzMDScCmp |
| // |
| // @doc: |
| // Dump scalar comparison object into DXL string |
| // |
| //--------------------------------------------------------------------------- |
| char * |
| COptTasks::SzMDScCmp |
| ( |
| List *plistOids, |
| char *szCmpType |
| ) |
| { |
| SContextRelcacheToDXL ctxrelcache(plistOids, UlCmpt(szCmpType), NULL /*szFilename*/); |
| Execute(&PvMDScCmp, &ctxrelcache); |
| |
| return ctxrelcache.m_szDXL; |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::SzRelStats |
| // |
| // @doc: |
| // Dump statistics objects into DXL string |
| // |
| //--------------------------------------------------------------------------- |
| char * |
| COptTasks::SzRelStats |
| ( |
| List *plistOids |
| ) |
| { |
| SContextRelcacheToDXL ctxrelcache(plistOids, ULONG_MAX /*ulCmpt*/, NULL /*szFilename*/); |
| Execute(&PvDXLFromRelStatsTask, &ctxrelcache); |
| |
| return ctxrelcache.m_szDXL; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::FSetXform |
| // |
| // @doc: |
| // Enable/Disable a given xform |
| // |
| //--------------------------------------------------------------------------- |
| bool |
| COptTasks::FSetXform |
| ( |
| char *szXform, |
| bool fDisable |
| ) |
| { |
| CXform *pxform = CXformFactory::Pxff()->Pxf(szXform); |
| if (NULL != pxform) |
| { |
| optimizer_xforms[pxform->Exfid()] = fDisable; |
| |
| return true; |
| } |
| |
| return false; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::UlCmpt |
| // |
| // @doc: |
| // Find the comparison type code given its string representation |
| // |
| //--------------------------------------------------------------------------- |
| ULONG |
| COptTasks::UlCmpt |
| ( |
| char *szCmpType |
| ) |
| { |
| const ULONG ulCmpTypes = 6; |
| const CmpType rgcmpt[] = {CmptEq, CmptNEq, CmptLT, CmptGT, CmptLEq, CmptGEq}; |
| const CHAR *rgszCmpTypes[] = {"Eq", "NEq", "LT", "GT", "LEq", "GEq"}; |
| |
| for (ULONG ul = 0; ul < ulCmpTypes; ul++) |
| { |
| if (0 == strcasecmp(szCmpType, rgszCmpTypes[ul])) |
| { |
| return rgcmpt[ul]; |
| } |
| } |
| |
| GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiInvalidComparisonTypeCode); |
| return CmptOther; |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::SzEvalExprFromXML |
| // |
| // @doc: |
| // Converts XML string to DXL and evaluates the expression. Caller keeps |
| // ownership of 'szXmlString' and takes ownership of the returned result. |
| // |
| //--------------------------------------------------------------------------- |
| char * |
| COptTasks::SzEvalExprFromXML |
| ( |
| char *szXmlString |
| ) |
| { |
| GPOS_ASSERT(NULL != szXmlString); |
| |
| SEvalExprContext evalctxt; |
| evalctxt.m_szDXL = szXmlString; |
| evalctxt.m_szDXLResult = NULL; |
| |
| Execute(&PvEvalExprFromDXLTask, &evalctxt); |
| return evalctxt.m_szDXLResult; |
| } |
| |
| |
| //--------------------------------------------------------------------------- |
| // @function: |
| // COptTasks::SzOptimizeMinidumpFromFile |
| // |
| // @doc: |
| // Loads a minidump from the given file path, optimizes it and returns |
| // the serialized representation of the result as DXL. |
| // |
| //--------------------------------------------------------------------------- |
| char * |
| COptTasks::SzOptimizeMinidumpFromFile |
| ( |
| char *szFileName |
| ) |
| { |
| GPOS_ASSERT(NULL != szFileName); |
| SOptimizeMinidumpContext optmdpctxt; |
| optmdpctxt.m_szFileName = szFileName; |
| optmdpctxt.m_szDXLResult = NULL; |
| |
| Execute(&PvOptimizeMinidumpTask, &optmdpctxt); |
| return optmdpctxt.m_szDXLResult; |
| } |
| |
| // EOF |