diff --git a/dbcon/execplan/calpontselectexecutionplan.cpp b/dbcon/execplan/calpontselectexecutionplan.cpp index 186b64930..07622638d 100644 --- a/dbcon/execplan/calpontselectexecutionplan.cpp +++ b/dbcon/execplan/calpontselectexecutionplan.cpp @@ -173,6 +173,26 @@ CalpontSelectExecutionPlan::~CalpontSelectExecutionPlan() fFilters = NULL; fHaving = NULL; + + if (!fDynamicParseTreeVec.empty()) + { + for (auto& parseTree : fDynamicParseTreeVec) + { + if (parseTree) + { + // 'delete fFilters;' above has already deleted objects pointed + // to by parseTree->left()/right()/data(), so we set the + // pointers to NULL here before calling 'delete parseTree;' + parseTree->left((ParseTree*) (NULL)); + parseTree->right((ParseTree*) (NULL)); + parseTree->data((TreeNode*) (NULL)); + delete parseTree; + parseTree = NULL; + } + } + + fDynamicParseTreeVec.clear(); + } } /** @@ -537,6 +557,26 @@ void CalpontSelectExecutionPlan::unserialize(messageqcpp::ByteStream& b) fHaving = 0; } + if (!fDynamicParseTreeVec.empty()) + { + for (auto& parseTree : fDynamicParseTreeVec) + { + if (parseTree) + { + // 'delete fFilters;' above has already deleted objects pointed + // to by parseTree->left()/right()/data(), so we set the + // pointers to NULL here before calling 'delete parseTree;' + parseTree->left((ParseTree*) (NULL)); + parseTree->right((ParseTree*) (NULL)); + parseTree->data((TreeNode*) (NULL)); + delete parseTree; + parseTree = NULL; + } + } + + fDynamicParseTreeVec.clear(); + } + messageqcpp::ByteStream::quadbyte size; messageqcpp::ByteStream::quadbyte i; diff --git a/dbcon/execplan/calpontselectexecutionplan.h b/dbcon/execplan/calpontselectexecutionplan.h index 0e6689349..ecfa4aa4a 100644 --- a/dbcon/execplan/calpontselectexecutionplan.h +++ b/dbcon/execplan/calpontselectexecutionplan.h @@ -772,6 +772,12 @@ public: return ((fSessionID & 0x80000000) != 0); } + virtual void setDynamicParseTreeVec( + const std::vector& dynamicParseTreeVec) + { + fDynamicParseTreeVec = dynamicParseTreeVec; + } + /** * Protected stuff */ @@ -922,6 +928,8 @@ private: bool fIsDML; std::string fTimeZone; + + std::vector fDynamicParseTreeVec; }; /** diff --git a/dbcon/execplan/simplefilter.cpp b/dbcon/execplan/simplefilter.cpp index 4916a129c..e6d544b02 100644 --- a/dbcon/execplan/simplefilter.cpp +++ b/dbcon/execplan/simplefilter.cpp @@ -150,8 +150,14 @@ SimpleFilter::SimpleFilter(const SimpleFilter& rhs) : SimpleFilter::~SimpleFilter() { //delete fOp; - delete fLhs; - delete fRhs; + if (fLhs != NULL) + delete fLhs; + + if (fRhs != NULL) + delete fRhs; + + fLhs = NULL; + fRhs = NULL; } /** diff --git a/dbcon/joblist/jlf_common.h b/dbcon/joblist/jlf_common.h index fe6c477d9..582f81621 100644 --- a/dbcon/joblist/jlf_common.h +++ b/dbcon/joblist/jlf_common.h @@ -364,6 +364,11 @@ struct JobInfo bool isDML; std::string timeZone; + // This is for tracking any dynamically allocated ParseTree objects + // in simpleScalarFilterToParseTree() for later deletion in + // ~csep() or csep.unserialize() + std::vector dynamicParseTreeVec; + private: //defaults okay //JobInfo(const JobInfo& rhs); diff --git a/dbcon/joblist/jlf_execplantojoblist.cpp b/dbcon/joblist/jlf_execplantojoblist.cpp index 35f4110fa..8c86908af 100644 --- a/dbcon/joblist/jlf_execplantojoblist.cpp +++ b/dbcon/joblist/jlf_execplantojoblist.cpp @@ -3269,6 +3269,12 @@ void doOR(ParseTree* n, JobInfo& jobInfo, bool tryCombine) ccp->left(parseTree->left()); ccp->right(parseTree->right()); ccp->data(parseTree->data()); + jobInfo.dynamicParseTreeVec.push_back(parseTree); + } + else if (parseTree) + { + delete parseTree; + parseTree = NULL; } } diff --git a/dbcon/joblist/jlf_subquery.cpp b/dbcon/joblist/jlf_subquery.cpp index 008bdc758..27c0129e6 100644 --- a/dbcon/joblist/jlf_subquery.cpp +++ b/dbcon/joblist/jlf_subquery.cpp @@ -192,7 +192,10 @@ void ssfInHaving(ParseTree* pt, void* obj) pt->right(parseTree->right()); pt->data(parseTree->data()); + jobInfo->dynamicParseTreeVec.push_back(parseTree); // don't delete the parseTree, it has been placed in the plan. + // Instead, we use the dynamicParseTreeVec above for deletion + // in ~csep() or csep.unserialize(). // delete parseTree; } else @@ -627,7 +630,10 @@ void doSimpleScalarFilter(ParseTree* p, JobInfo& jobInfo) // create job steps for each simple filter JLF_ExecPlanToJobList::walkTree(parseTree, jobInfo); + jobInfo.dynamicParseTreeVec.push_back(parseTree); // don't delete the parseTree, it has been placed in the plan. + // Instead, we use the dynamicParseTreeVec above for deletion + // in ~csep() or csep.unserialize(). // delete parseTree; } else diff --git a/dbcon/joblist/joblistfactory.cpp b/dbcon/joblist/joblistfactory.cpp index d762d912c..43b70fdf2 100644 --- a/dbcon/joblist/joblistfactory.cpp +++ b/dbcon/joblist/joblistfactory.cpp @@ -2003,6 +2003,7 @@ SJLP makeJobList_( jl->addQuery(querySteps); jl->addProject(projectSteps); jl->addDelivery(deliverySteps); + csep->setDynamicParseTreeVec(jobInfo.dynamicParseTreeVec); dynamic_cast(jl)->setDeliveryFlag(true); } diff --git a/dbcon/joblist/subquerytransformer.cpp b/dbcon/joblist/subquerytransformer.cpp index cd5583c26..6ebd00602 100644 --- a/dbcon/joblist/subquerytransformer.cpp +++ b/dbcon/joblist/subquerytransformer.cpp @@ -169,6 +169,7 @@ SJSTEP& SubQueryTransformer::makeSubQueryStep(execplan::CalpontSelectExecutionPl fSubJobList->addQuery(querySteps); fSubJobList->addDelivery(deliverySteps); fSubJobList->putEngineComm(DistributedEngineComm::instance(fOutJobInfo->rm)); + csep->setDynamicParseTreeVec(fSubJobInfo->dynamicParseTreeVec); // Get the correlated steps fCorrelatedSteps = fSubJobInfo->correlateSteps;