From 3c6443053e1909f2b8e8a09309d3d828a18a4b8c Mon Sep 17 00:00:00 2001 From: david hill Date: Thu, 15 Mar 2018 16:24:26 -0500 Subject: [PATCH 01/10] MCOL-1217 - setup msqyl rep on addmodule --- oamapps/postConfigure/helpers.cpp | 1 - procmgr/main.cpp | 2 +- procmgr/processmanager.cpp | 181 +++++++++++++----------------- procmgr/processmanager.h | 2 +- procmon/processmonitor.cpp | 48 +++++++- 5 files changed, 122 insertions(+), 112 deletions(-) diff --git a/oamapps/postConfigure/helpers.cpp b/oamapps/postConfigure/helpers.cpp index b53a17302..ba97915a9 100644 --- a/oamapps/postConfigure/helpers.cpp +++ b/oamapps/postConfigure/helpers.cpp @@ -489,7 +489,6 @@ int sendReplicationRequest(int IserverTypeInstall, std::string password, bool pm } else { - cout << endl << "ERROR: Module not Active, replication not done on " << (*pt).DeviceName << endl; pt++; } } diff --git a/procmgr/main.cpp b/procmgr/main.cpp index 434902138..118ac0d73 100644 --- a/procmgr/main.cpp +++ b/procmgr/main.cpp @@ -1803,7 +1803,7 @@ void pingDeviceThread() DeviceNetworkConfig devicenetworkconfig; devicenetworkconfig.DeviceName = moduleName; devicenetworklist.push_back(devicenetworkconfig); - processManager.setMySQLReplication(devicenetworklist, oam::UnassignedName, false, true); + processManager.setMySQLReplication(devicenetworklist, oam::UnassignedName, true); } } diff --git a/procmgr/processmanager.cpp b/procmgr/processmanager.cpp index fdb3f76b1..7c18d6ed8 100755 --- a/procmgr/processmanager.cpp +++ b/procmgr/processmanager.cpp @@ -2546,7 +2546,7 @@ void processMSG(messageqcpp::IOSocket* cfIos) // target = root password oam::DeviceNetworkList devicenetworklist; - status = processManager.setMySQLReplication(devicenetworklist, oam::UnassignedName, false, true, target); + status = processManager.setMySQLReplication(devicenetworklist, oam::UnassignedName, true, target); log.writeLog(__LINE__, "Enable MySQL Replication status: " + oam.itoa(status) ); @@ -2568,7 +2568,7 @@ void processMSG(messageqcpp::IOSocket* cfIos) // target = root password oam::DeviceNetworkList devicenetworklist; - status = processManager.setMySQLReplication(devicenetworklist, oam::UnassignedName, false, false, target, false); + status = processManager.setMySQLReplication(devicenetworklist, oam::UnassignedName, false, target, false); log.writeLog(__LINE__, "Disable MySQL Replication status: " + oam.itoa(status) ); @@ -3621,18 +3621,21 @@ int ProcessManager::startProcess(string moduleName, string processName, { Oam oam; - //skip if module is DISABLED - int opState; - bool degraded; - try{ - oam.getModuleStatus(moduleName, opState, degraded); - } - catch(...) - {} + if ( actionIndicator != oam::STATUS_UPDATE ) + { + //skip if module is DISABLED + int opState; + bool degraded; + try{ + oam.getModuleStatus(moduleName, opState, degraded); + } + catch(...) + {} - //check if disabled - if (opState == oam::MAN_DISABLED || opState == oam::AUTO_DISABLED) - return API_SUCCESS; + //check if disabled + if (opState == oam::MAN_DISABLED || opState == oam::AUTO_DISABLED) + return API_SUCCESS; + } ByteStream msg; ByteStream::byte requestID = START; @@ -4190,8 +4193,8 @@ int ProcessManager::startProcessType( std::string processName ) if ( systemprocessstatus.processstatus[i].ProcessName == processName) { // found one, request restart of it int retStatus = processManager.startProcess(systemprocessstatus.processstatus[i].Module, - processName, - FORCEFUL); + processName, + FORCEFUL); log.writeLog(__LINE__, "StartProcessType: Start ACK received from Process-Monitor, return status = " + oam.itoa(retStatus), LOG_TYPE_DEBUG); } } @@ -5426,9 +5429,23 @@ int ProcessManager::addModule(oam::DeviceNetworkList devicenetworklist, std::str log.writeLog(__LINE__, "addModule - sleep 60 - give ProcMon time to CONFIGURE and restart", LOG_TYPE_DEBUG); sleep(60); + //start mysqld on the new modules so mysql replication can be setup + listPT = devicenetworklist.begin(); + for( ; listPT != devicenetworklist.end() ; listPT++) + { + processManager.startProcess((*listPT).DeviceName, "mysqld", oam::STATUS_UPDATE); + } + log.writeLog(__LINE__, "Setup MySQL Replication for new Modules being Added", LOG_TYPE_DEBUG); - processManager.setMySQLReplication(devicenetworklist, oam::UnassignedName, false, true, password ); + processManager.setMySQLReplication(devicenetworklist, oam::UnassignedName, true, password, true, true ); + //stop mysqld + listPT = devicenetworklist.begin(); + for( ; listPT != devicenetworklist.end() ; listPT++) + { + processManager.stopProcess((*listPT).DeviceName, "mysqld", oam::FORCEFUL, true ); + } + return API_SUCCESS; } @@ -8728,7 +8745,7 @@ int ProcessManager::switchParentOAMModule(std::string newActiveModuleName) //change master MySQL Replication setup log.writeLog(__LINE__, "Setup MySQL Replication for new Parent Module during switch-over", LOG_TYPE_DEBUG); oam::DeviceNetworkList devicenetworklist; - processManager.setMySQLReplication(devicenetworklist, newActiveModuleName, false, false, oam::UnassignedName); + processManager.setMySQLReplication(devicenetworklist, newActiveModuleName, false, oam::UnassignedName); } catch (exception& ex) @@ -9530,7 +9547,7 @@ int ProcessManager::OAMParentModuleChange() //change master MySQL Replication setup log.writeLog(__LINE__, "Setup this node as MySQL Replication Master", LOG_TYPE_DEBUG); oam::DeviceNetworkList devicenetworklist; - processManager.setMySQLReplication(devicenetworklist, config.moduleName(), true); + processManager.setMySQLReplication(devicenetworklist, config.moduleName()); } //set query system state not ready @@ -10207,7 +10224,7 @@ void ProcessManager::flushInodeCache() * * ******************************************************************************************/ -int ProcessManager::setMySQLReplication(oam::DeviceNetworkList devicenetworklist, std::string masterModule, bool failover, bool distributeDB, std::string password, bool enable) +int ProcessManager::setMySQLReplication(oam::DeviceNetworkList devicenetworklist, std::string masterModule, bool distributeDB, std::string password, bool enable, bool addModule) { Oam oam; @@ -10226,57 +10243,6 @@ int ProcessManager::setMySQLReplication(oam::DeviceNetworkList devicenetworklist return oam::API_SUCCESS; } - //also skip if single-server, multi-node seperate with 1 UM, multi-node combo with 1 PM - -/* string SingleServerInstall = "n"; - try { - oam.getSystemConfig("SingleServerInstall", SingleServerInstall); - } - catch(...) { - SingleServerInstall = "n"; - } - - //single server check - if ( SingleServerInstall == "y" ) - { - log.writeLog(__LINE__, "setMySQLReplication: Single-Server, exiting", LOG_TYPE_DEBUG); - return oam::API_SUCCESS; - } - - //combined system check - if ( config.ServerInstallType() == oam::INSTALL_COMBINE_DM_UM_PM && !failover ) { - try { - Config* sysConfig = Config::makeConfig(); - if ( sysConfig->getConfig("DBRM_Controller", "NumWorkers") == "1" ) { - log.writeLog(__LINE__, "setMySQLReplication: 1 configured module, exiting", LOG_TYPE_DEBUG); - return oam::API_SUCCESS; - } - } - catch(...) - { - log.writeLog(__LINE__, "setMySQLReplication: makeConfig exception, exiting", LOG_TYPE_DEBUG); - return oam::API_SUCCESS; - } - } - - //seperate system check - if ( ( config.ServerInstallType() != oam::INSTALL_COMBINE_DM_UM_PM ) && - (PMwithUM == "n" ) ) - { - ModuleTypeConfig moduletypeconfig; - try{ - oam.getSystemConfig("um", moduletypeconfig); - } - catch(...) - {} - - if ( moduletypeconfig.ModuleCount < 2 ) - { - log.writeLog(__LINE__, "setMySQLReplication: moduleCount = 1, exiting", LOG_TYPE_DEBUG); - return oam::API_SUCCESS; - } - } -*/ log.writeLog(__LINE__, "Setup MySQL Replication", LOG_TYPE_DEBUG); //get master info @@ -10329,18 +10295,21 @@ int ProcessManager::setMySQLReplication(oam::DeviceNetworkList devicenetworklist if ( remoteModuleName == masterModule ) continue; - // skip disabled modules - int opState = oam::ACTIVE; - bool degraded; - try { - oam.getModuleStatus(remoteModuleName, opState, degraded); + if ( !addModule ) + { + // skip disabled modules + int opState = oam::ACTIVE; + bool degraded; + try { + oam.getModuleStatus(remoteModuleName, opState, degraded); + } + catch(...) + {} + + if (opState == oam::MAN_DISABLED || opState == oam::AUTO_DISABLED) + continue; } - catch(...) - {} - - if (opState == oam::MAN_DISABLED || opState == oam::AUTO_DISABLED) - continue; - + // don't do PMs unless PMwithUM flag is set if ( config.ServerInstallType() != oam::INSTALL_COMBINE_DM_UM_PM ) { string moduleType = remoteModuleName.substr(0,MAX_MODULE_TYPE_SIZE); @@ -10418,18 +10387,21 @@ int ProcessManager::setMySQLReplication(oam::DeviceNetworkList devicenetworklist if ( remoteModuleName == masterModule ) continue; - // skip disabled modules - int opState = oam::ACTIVE; - bool degraded; - try { - oam.getModuleStatus(remoteModuleName, opState, degraded); + if ( !addModule ) + { + // skip disabled modules + int opState = oam::ACTIVE; + bool degraded; + try { + oam.getModuleStatus(remoteModuleName, opState, degraded); + } + catch(...) + {} + + if (opState == oam::MAN_DISABLED || opState == oam::AUTO_DISABLED) + continue; } - catch(...) - {} - - if (opState == oam::MAN_DISABLED || opState == oam::AUTO_DISABLED) - continue; - + // don't do PMs unless PMwithUM flag is set if ( config.ServerInstallType() != oam::INSTALL_COMBINE_DM_UM_PM ) { string moduleType = remoteModuleName.substr(0,MAX_MODULE_TYPE_SIZE); @@ -10477,18 +10449,21 @@ int ProcessManager::setMySQLReplication(oam::DeviceNetworkList devicenetworklist if ( remoteModuleName == masterModule ) continue; - // skip disabled modules - int opState = oam::ACTIVE; - bool degraded; - try { - oam.getModuleStatus(remoteModuleName, opState, degraded); + if ( !addModule ) + { + // skip disabled modules + int opState = oam::ACTIVE; + bool degraded; + try { + oam.getModuleStatus(remoteModuleName, opState, degraded); + } + catch(...) + {} + + if (opState == oam::MAN_DISABLED || opState == oam::AUTO_DISABLED) + continue; } - catch(...) - {} - - if (opState == oam::MAN_DISABLED || opState == oam::AUTO_DISABLED) - continue; - + log.writeLog(__LINE__, "Setup Slave MySQL Replication on " + remoteModuleName, LOG_TYPE_DEBUG); ByteStream msg1; diff --git a/procmgr/processmanager.h b/procmgr/processmanager.h index d60a9eaf2..55d291b23 100644 --- a/procmgr/processmanager.h +++ b/procmgr/processmanager.h @@ -545,7 +545,7 @@ public: /** @brief Set MySQL Replication */ - int setMySQLReplication(oam::DeviceNetworkList devicenetworklist, std::string masterModule = oam::UnassignedName, bool failover = false, bool distributeDB = false, std::string password = oam::UnassignedName, bool enable = true); + int setMySQLReplication(oam::DeviceNetworkList devicenetworklist, std::string masterModule = oam::UnassignedName, bool distributeDB = false, std::string password = oam::UnassignedName, bool enable = true, bool addModule = false); /** @brief Gluster Assign dbroot to a module */ diff --git a/procmon/processmonitor.cpp b/procmon/processmonitor.cpp index 8f51cccf1..aa10f2666 100644 --- a/procmon/processmonitor.cpp +++ b/procmon/processmonitor.cpp @@ -457,6 +457,24 @@ void ProcessMonitor::processMessage(messageqcpp::ByteStream msg, messageqcpp::IO log.writeLog(__LINE__, "MSG RECEIVED: Stop process request on " + processName); int requestStatus = API_SUCCESS; + // check for mysql + if ( processName == "mysqld" ) { + try { + oam.actionMysqlCalpont(MYSQL_STOP); + } + catch(...) + {} + + ackMsg << (ByteStream::byte) ACK; + ackMsg << (ByteStream::byte) STOP; + ackMsg << (ByteStream::byte) API_SUCCESS; + mq.write(ackMsg); + + log.writeLog(__LINE__, "STOP: ACK back to ProcMgr, return status = " + oam.itoa((int) API_SUCCESS)); + + break; + } + processList::iterator listPtr; processList* aPtr = config.monitoredListPtr(); listPtr = aPtr->begin(); @@ -502,6 +520,24 @@ void ProcessMonitor::processMessage(messageqcpp::ByteStream msg, messageqcpp::IO msg >> manualFlag; log.writeLog(__LINE__, "MSG RECEIVED: Start process request on: " + processName); + // check for mysql + if ( processName == "mysqld" ) { + try { + oam.actionMysqlCalpont(MYSQL_START); + } + catch(...) + {} + + ackMsg << (ByteStream::byte) ACK; + ackMsg << (ByteStream::byte) START; + ackMsg << (ByteStream::byte) API_SUCCESS; + mq.write(ackMsg); + + log.writeLog(__LINE__, "START: ACK back to ProcMgr, return status = " + oam.itoa((int) API_SUCCESS)); + + break; + } + ProcessConfig processconfig; ProcessStatus processstatus; try { @@ -605,7 +641,7 @@ void ProcessMonitor::processMessage(messageqcpp::ByteStream msg, messageqcpp::IO int requestStatus = API_SUCCESS; // check for mysql restart - if ( processName == "mysql" ) { + if ( processName == "mysqld" ) { try { oam.actionMysqlCalpont(MYSQL_RESTART); } @@ -4952,11 +4988,11 @@ int ProcessMonitor::runMasterRep(std::string& masterLogFile, std::string& master //skip if module is not ACTIVE - int opState = oam::ACTIVE; - bool degraded; - oam.getModuleStatus(moduleName, opState, degraded); - if (opState != oam::ACTIVE) - continue; +// int opState = oam::ACTIVE; +// bool degraded; +// oam.getModuleStatus(moduleName, opState, degraded); +// if (opState != oam::ACTIVE) +// continue; bool passwordError = false; From dbcbd6c7e74f0bf4e3d4f757f0b9bff7f2666e57 Mon Sep 17 00:00:00 2001 From: David Hall Date: Wed, 4 Apr 2018 12:34:17 -0500 Subject: [PATCH 02/10] MCOL-1323 cpimport Splitter has incorrect SIGPIPE mapping --- writeengine/splitter/we_splitterapp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/writeengine/splitter/we_splitterapp.cpp b/writeengine/splitter/we_splitterapp.cpp index 7ecbca854..0077ebd60 100644 --- a/writeengine/splitter/we_splitterapp.cpp +++ b/writeengine/splitter/we_splitterapp.cpp @@ -159,7 +159,7 @@ void WESplitterApp::setupSignalHandlers() sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, 0); sa.sa_handler = WESplitterApp::onSigHup; - sigaction(SIGPIPE, &sa, 0); + sigaction(SIGHUP, &sa, 0); sa.sa_handler = WESplitterApp::onSigInterrupt; sigaction(SIGUSR1, &sa, 0); /* From bd8387202fccaf90dcdd706b52bc56e58e296120 Mon Sep 17 00:00:00 2001 From: david hill Date: Mon, 9 Apr 2018 08:55:45 -0500 Subject: [PATCH 03/10] MCOL-912 - added code to restart dbrm/ddml process when enable module is done --- procmgr/processmanager.cpp | 19 +++++++++++++++++-- procmgr/processmanager.h | 2 +- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/procmgr/processmanager.cpp b/procmgr/processmanager.cpp index fdb3f76b1..2172b6153 100755 --- a/procmgr/processmanager.cpp +++ b/procmgr/processmanager.cpp @@ -3385,12 +3385,12 @@ int ProcessManager::disableModule(string target, bool manualFlag) * purpose: recyle process, generally after some disable module is run * ******************************************************************************************/ -void ProcessManager::recycleProcess(string module) +void ProcessManager::recycleProcess(string module, bool enableModule) { Oam oam; ModuleConfig moduleconfig; - log.writeLog(__LINE__, "recycleProcess request after module was disabled: " + module, LOG_TYPE_DEBUG); + log.writeLog(__LINE__, "recycleProcess request after module statsu update: " + module, LOG_TYPE_DEBUG); string moduleType = module.substr(0,MAX_MODULE_TYPE_SIZE); @@ -3399,11 +3399,23 @@ void ProcessManager::recycleProcess(string module) oam.getSystemConfig("PrimaryUMModuleName", PrimaryUMModuleName); } catch(...) {} + + // restart DMLProc and return if enable module is being done + if (enableModule) + { + //recycle DBRM processes in all cases + restartProcessType("DBRMControllerNode"); + restartProcessType("DBRMWorkerNode"); + + restartProcessType("DMLProc"); + return; + } //recycle DBRM processes in all cases restartProcessType("DBRMControllerNode", module); restartProcessType("DBRMWorkerNode"); + // only recycle dmlproc, if down/up module is non-parent UM if ( ( moduleType == "um" ) && ( PrimaryUMModuleName != module) ) @@ -3483,6 +3495,9 @@ int ProcessManager::enableModule(string target, int state) if ( newStandbyModule == target) setStandbyModule(newStandbyModule); + //set recycle process + recycleProcess(target); + log.writeLog(__LINE__, "enableModule request for " + target + " completed", LOG_TYPE_DEBUG); return API_SUCCESS; diff --git a/procmgr/processmanager.h b/procmgr/processmanager.h index d60a9eaf2..a9ba826eb 100644 --- a/procmgr/processmanager.h +++ b/procmgr/processmanager.h @@ -302,7 +302,7 @@ public: /** *@brief recycle Processes */ - void recycleProcess(std::string module); + void recycleProcess(std::string module, bool enableModule = false); /** *@brief Enable a specified module From afb8e4706d58fffbae0631add8c90cf21343d121 Mon Sep 17 00:00:00 2001 From: david hill Date: Mon, 9 Apr 2018 11:35:37 -0500 Subject: [PATCH 04/10] MCOL-912 - fix spelling error --- procmgr/processmanager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/procmgr/processmanager.cpp b/procmgr/processmanager.cpp index 2172b6153..6db1a1660 100755 --- a/procmgr/processmanager.cpp +++ b/procmgr/processmanager.cpp @@ -3390,7 +3390,7 @@ void ProcessManager::recycleProcess(string module, bool enableModule) Oam oam; ModuleConfig moduleconfig; - log.writeLog(__LINE__, "recycleProcess request after module statsu update: " + module, LOG_TYPE_DEBUG); + log.writeLog(__LINE__, "recycleProcess request after module status update: " + module, LOG_TYPE_DEBUG); string moduleType = module.substr(0,MAX_MODULE_TYPE_SIZE); @@ -3400,7 +3400,7 @@ void ProcessManager::recycleProcess(string module, bool enableModule) } catch(...) {} - // restart DMLProc and return if enable module is being done + // restart DBRM Process and DMLProc and return if enable module is being done if (enableModule) { //recycle DBRM processes in all cases From a80854c11f55be1882aaf798229f36e63353a966 Mon Sep 17 00:00:00 2001 From: Andrew Hutchings Date: Tue, 10 Apr 2018 14:14:22 +0100 Subject: [PATCH 05/10] MCOL-1182 Keep filters for cross engine step Cross engine step needs the filters for joining a constant with the cross engine table. Deleting them early causes a crash. --- dbcon/joblist/jlf_execplantojoblist.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/dbcon/joblist/jlf_execplantojoblist.cpp b/dbcon/joblist/jlf_execplantojoblist.cpp index 1ac770701..b6242ba77 100644 --- a/dbcon/joblist/jlf_execplantojoblist.cpp +++ b/dbcon/joblist/jlf_execplantojoblist.cpp @@ -1954,6 +1954,7 @@ const JobStepVector doOuterJoinOnFilter(OuterJoinOnFilter* oj, JobInfo& jobInfo) set doneNodes; // solved joins and simple filters map cpMap; // link for node removal JobStepVector join; // join step with its projection steps + bool keepFilters = false; // keep filters for cross engine step // To compromise the front end difficulty on setting outer attributes. set tablesInOuter; @@ -2162,6 +2163,14 @@ const JobStepVector doOuterJoinOnFilter(OuterJoinOnFilter* oj, JobInfo& jobInfo) jsv.insert(jsv.end(), sfv.begin(), sfv.end()); + // MCOL-1182 if we are doing a join between a cross engine + // step and a constant then keep the filter for the cross + // engine step instead of deleting it further down. + if (!sc->isInfiniDB()) + { + keepFilters = true; + } + doneNodes.insert(cn); } } @@ -2198,7 +2207,10 @@ const JobStepVector doOuterJoinOnFilter(OuterJoinOnFilter* oj, JobInfo& jobInfo) if (p == NULL) { filters = NULL; - delete c; + if (!keepFilters) + { + delete c; + } } else { @@ -2240,8 +2252,11 @@ const JobStepVector doOuterJoinOnFilter(OuterJoinOnFilter* oj, JobInfo& jobInfo) p->left(nullTree); p->right(nullTree); - delete p; - delete c; + if (!keepFilters) + { + delete p; + delete c; + } } } From 8220a5103fd77f9f89a94bbb84411292ab6ba1bb Mon Sep 17 00:00:00 2001 From: david hill Date: Fri, 13 Apr 2018 10:29:17 -0500 Subject: [PATCH 06/10] MCOL-1333 - changed addmodule to look for rpm/deb, not tar.gz packages --- procmgr/processmanager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/procmgr/processmanager.cpp b/procmgr/processmanager.cpp index fdb3f76b1..7343e6c7a 100755 --- a/procmgr/processmanager.cpp +++ b/procmgr/processmanager.cpp @@ -4530,10 +4530,10 @@ int ProcessManager::addModule(oam::DeviceNetworkList devicenetworklist, std::str } if ( packageType == "rpm") - calpontPackage = homedir + "/mariadb-columnstore*" + columnstore_version + "-" + columnstore_release + "*.rpm.tar.gz"; + calpontPackage = homedir + "/mariadb-columnstore*" + columnstore_version + "-" + columnstore_release + "*.rpm"; else if ( packageType == "deb") - calpontPackage = homedir + "/mariadb-columnstore*" + columnstore_version + "-" + columnstore_release + "*.deb.tar.gz"; + calpontPackage = homedir + "/mariadb-columnstore*" + columnstore_version + "-" + columnstore_release + "*.deb"; else calpontPackage = homedir + "/mariadb-columnstore*" + columnstore_version + "-" + columnstore_release + "*.bin.tar.gz"; From 0c6dc5e15c97061d72df291a8c33100d3b345cfb Mon Sep 17 00:00:00 2001 From: Andrew Hutchings Date: Mon, 16 Apr 2018 19:21:28 +0100 Subject: [PATCH 07/10] MCOL-1341 Fix CASE handling with 10.2.14 MariaDB Server 10.2.14 changed the order that CASE items are processed. This broke the engine's CASE handling. This patch uses the new order instead since this is what will be used in 10.2 and 10.3 going forward. --- dbcon/mysql/ha_calpont_execplan.cpp | 16 +++- utils/funcexp/func_case.cpp | 136 ++++++++++++++++++---------- 2 files changed, 105 insertions(+), 47 deletions(-) diff --git a/dbcon/mysql/ha_calpont_execplan.cpp b/dbcon/mysql/ha_calpont_execplan.cpp index da80366b8..0f54d8bdb 100755 --- a/dbcon/mysql/ha_calpont_execplan.cpp +++ b/dbcon/mysql/ha_calpont_execplan.cpp @@ -3201,6 +3201,20 @@ FunctionColumn* buildCaseFunction(Item_func* item, gp_walk_info& gwi, bool& nonS // and position. We can't tell which at this point, so we // rebuild the item from the arguments directly and then try to // figure what to pop, if anything, in order to sync the stacks. + // + // MCOL-1341 - With MariaDB 10.2.14 onwards CASE is now in the order: + // [case,]when1,when2,...,then1,then2,...[,else] + // See server commit bf1ca14ff3f3faa9f7a018097b25aa0f66d068cd for more + // information. + int32_t arg_offset = 0; + if ((item->argument_count() - 1) % 2) + { + arg_offset = (item->argument_count() - 1) / 2; + } + else + { + arg_offset = item->argument_count() / 2; + } for (int32_t i = item->argument_count()-1; i >=0; i--) { // For case_searched, we know the items for the WHEN clause will @@ -3209,7 +3223,7 @@ FunctionColumn* buildCaseFunction(Item_func* item, gp_walk_info& gwi, bool& nonS // Every even numbered arg is a WHEN. In between are the THEN. // An odd number of args indicates an ELSE residing in the last spot. if (funcName == "case_searched" && - i % 2 == 0 && uint(i) != item->argument_count()-1) + (i < arg_offset)) { sptp.reset(buildParseTree((Item_func*)(item->arguments()[i]), gwi, nonSupport)); if (!gwi.ptWorkStack.empty() && *gwi.ptWorkStack.top()->data() == sptp->data()) diff --git a/utils/funcexp/func_case.cpp b/utils/funcexp/func_case.cpp index 3787947ab..2b5ae58c2 100644 --- a/utils/funcexp/func_case.cpp +++ b/utils/funcexp/func_case.cpp @@ -52,9 +52,10 @@ inline uint64_t simple_case_cmp(Row& row, CalpontSystemCatalog::ColType& operationColType) { uint64_t i = 0; // index to the parm list - uint64_t n = parm.size() - 1; // remove expression from count of expression_i + result_i - uint64_t hasElse = n % 2; // if 1, then ELSE exist - n -= hasElse; // index to expression + uint64_t n = 0; // remove expression from count of expression_i + result_i + uint64_t hasElse = (parm.size()-1) % 2; // if 1, then ELSE exist + uint64_t whereCount = hasElse ? (parm.size() - 2) / 2 : (parm.size() - 1) / 2; + bool foundIt = false; switch (operationColType.colDataType) { @@ -70,10 +71,13 @@ inline uint64_t simple_case_cmp(Row& row, if (isNull) break; - for (; i < n; i += 2) + for (i = 1; i <= whereCount; i++) { if (ev == parm[i]->data()->getIntVal(row, isNull) && !isNull) + { + foundIt = true; break; + } else isNull = false; } @@ -90,10 +94,13 @@ inline uint64_t simple_case_cmp(Row& row, if (isNull) break; - for (; i < n; i += 2) + for (i = 1; i <= whereCount; i++) { if (ev == parm[i]->data()->getUintVal(row, isNull) && !isNull) + { + foundIt = true; break; + } else isNull = false; } @@ -108,11 +115,14 @@ inline uint64_t simple_case_cmp(Row& row, if (isNull) break; - for (; i < n; i += 2) + for (i = 1; i <= whereCount; i++) { //BUG 5362 if (utf8::idb_strcoll(ev.c_str(), parm[i]->data()->getStrVal(row, isNull).c_str()) == 0 && !isNull) + { + foundIt = true; break; + } else isNull = false; } @@ -126,10 +136,13 @@ inline uint64_t simple_case_cmp(Row& row, if (isNull) break; - for (; i < n; i += 2) + for (i = 1; i <= whereCount; i++) { if (ev == parm[i]->data()->getDecimalVal(row, isNull) && !isNull) + { + foundIt = true; break; + } else isNull = false; } @@ -143,10 +156,13 @@ inline uint64_t simple_case_cmp(Row& row, if (isNull) break; - for (; i < n; i += 2) + for (i = 1; i <= whereCount; i++) { if (ev == parm[i]->data()->getDoubleVal(row, isNull) && !isNull) + { + foundIt = true; break; + } else isNull = false; } @@ -160,10 +176,13 @@ inline uint64_t simple_case_cmp(Row& row, if (isNull) break; - for (; i < n; i += 2) + for (i = 1; i <= whereCount; i++) { if (ev == parm[i]->data()->getFloatVal(row, isNull) && !isNull) + { + foundIt = true; break; + } else isNull = false; } @@ -178,16 +197,24 @@ inline uint64_t simple_case_cmp(Row& row, } } - if (i == n && !hasElse) + if (!foundIt && !hasElse) isNull = true; + else if (!foundIt && hasElse && !isNull) + { + i = parm.size() - 1; + } else if (isNull && hasElse) // BUG 5110. Only way we can exit above with isNull == true is when ev is NULL - // if so and we have else condition we need to use it by setting i = n + // if so and we have else condition we need to use it by setting i = else { - i = n; + i = parm.size() - 1; isNull = false; } + if (foundIt) + { + i += whereCount; + } return i; } @@ -198,21 +225,33 @@ inline uint64_t searched_case_cmp(Row& row, bool& isNull) { uint64_t i = 0; // index to the parm list - uint64_t n = parm.size(); // count of boolean_expression_i + result_i - uint64_t hasElse = n % 2; // if 1, then ELSE exist - n -= hasElse; // index to expression + uint64_t hasElse = parm.size() % 2; // if 1, then ELSE exist + uint64_t whereCount = hasElse ? (parm.size() - 1) / 2 : parm.size() / 2; + bool foundIt = false; - for (; i < n; i += 2) + + for (i = 0; i < whereCount; i++) { if (parm[i]->getBoolVal(row, isNull)) + { + foundIt = true; break; + } } isNull = false; - if (i == n && !hasElse) + if (!foundIt && !hasElse) isNull = true; + else if (!foundIt && hasElse) + { + i = parm.size() - 1; + } + if (foundIt) + { + i += whereCount; + } - return (i == n ? i-1 : i); + return i; } @@ -220,7 +259,6 @@ CalpontSystemCatalog::ColType caseOperationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType, bool simpleCase) { - // ... expression_i + result_i + ... [[expression] + result_N] FunctionParm::size_type n = fp.size(); if (simpleCase) // simple case has an expression @@ -228,6 +266,9 @@ CalpontSystemCatalog::ColType caseOperationType(FunctionParm& fp, bool hasElse = ((n % 2) != 0); // if 1, then ELSE exist if (hasElse) --n; // n now is an even number + uint64_t parmCount = hasElse ? (fp.size() - 2) : (fp.size() - 1); + uint64_t whereCount = hasElse ? (fp.size() - 2 + simpleCase) / 2 : (fp.size() - 1) / 2 + simpleCase; + idbassert((n % 2) == 0); bool allStringO = true; @@ -238,10 +279,10 @@ CalpontSystemCatalog::ColType caseOperationType(FunctionParm& fp, CalpontSystemCatalog::ColType oct = fp[l]->data()->resultType(); CalpontSystemCatalog::ColType rct = resultType; bool operation = true; - for (uint64_t i = 0; i <= n; i++) + for (uint64_t i = 0; i <= parmCount; i++) { // operation or result type - operation = ((i % 2) == 0); + operation = ((i > 0) && (i <= whereCount)); // the result type of ELSE, if exists. if (i == n) @@ -334,8 +375,9 @@ namespace funcexp // END // // simple CASE parm order: -// expression1 result1 expression2 result2 ... expression [resultN] +// expression condition1 condition2 ... result1 result2 ... [resultN] // +// Note that this order changed in 10.2.14, see MCOL-1341 CalpontSystemCatalog::ColType Func_simple_case::operationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType) { @@ -353,7 +395,7 @@ bool Func_simple_case::getBoolVal(Row& row, if (isNull) return joblist::BIGINTNULL; - return parm[i+1]->data()->getBoolVal(row, isNull); + return parm[i]->data()->getBoolVal(row, isNull); } @@ -367,7 +409,7 @@ int64_t Func_simple_case::getIntVal(Row& row, if (isNull) return joblist::BIGINTNULL; - return parm[i+1]->data()->getIntVal(row, isNull); + return parm[i]->data()->getIntVal(row, isNull); } @@ -381,7 +423,7 @@ string Func_simple_case::getStrVal(Row& row, if (isNull) return string(""); - return parm[i+1]->data()->getStrVal(row, isNull); + return parm[i]->data()->getStrVal(row, isNull); } @@ -395,7 +437,7 @@ IDB_Decimal Func_simple_case::getDecimalVal(Row& row, if (isNull) return IDB_Decimal(); // need a null value for IDB_Decimal?? - return parm[i+1]->data()->getDecimalVal(row, isNull); + return parm[i]->data()->getDecimalVal(row, isNull); } @@ -409,7 +451,7 @@ double Func_simple_case::getDoubleVal(Row& row, if (isNull) return doubleNullVal(); - return parm[i+1]->data()->getDoubleVal(row, isNull); + return parm[i]->data()->getDoubleVal(row, isNull); } @@ -423,9 +465,9 @@ int32_t Func_simple_case::getDateIntVal(rowgroup::Row& row, if (isNull) return joblist::DATENULL; - return parm[i+1]->data()->getDateIntVal(row, isNull); -} - + return parm[i]->data()->getDateIntVal(row, isNull); +} + int64_t Func_simple_case::getDatetimeIntVal(rowgroup::Row& row, FunctionParm& parm, @@ -437,8 +479,8 @@ int64_t Func_simple_case::getDatetimeIntVal(rowgroup::Row& row, if (isNull) return joblist::DATETIMENULL; - return parm[i+1]->data()->getDatetimeIntVal(row, isNull); -} + return parm[i]->data()->getDatetimeIntVal(row, isNull); +} @@ -451,8 +493,10 @@ int64_t Func_simple_case::getDatetimeIntVal(rowgroup::Row& row, // END // // searched CASE parm order: -// boolean_expression1 result1 boolean_expression2 result2 ... [resultN] +// boolean_expression1 boolean_expression2 ... result1 result2 ... [resultN] // +// Note that this order changed in 10.2.14, see MCOL-1341 + CalpontSystemCatalog::ColType Func_searched_case::operationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType) { // operation type not used by this functor. @@ -470,14 +514,14 @@ bool Func_searched_case::getBoolVal(Row& row, if (isNull) return joblist::BIGINTNULL; - ParseTree* lop = parm[i+1]->left(); - ParseTree* rop = parm[i+1]->right(); + ParseTree* lop = parm[i]->left(); + ParseTree* rop = parm[i]->right(); if (lop && rop) { - return (reinterpret_cast(parm[i+1]->data()))->getBoolVal(row, isNull, lop, rop); + return (reinterpret_cast(parm[i]->data()))->getBoolVal(row, isNull, lop, rop); } - return parm[i+1]->data()->getBoolVal(row, isNull); + return parm[i]->data()->getBoolVal(row, isNull); } int64_t Func_searched_case::getIntVal(Row& row, @@ -490,7 +534,7 @@ int64_t Func_searched_case::getIntVal(Row& row, if (isNull) return joblist::BIGINTNULL; - return parm[i+1]->data()->getIntVal(row, isNull); + return parm[i]->data()->getIntVal(row, isNull); } @@ -504,7 +548,7 @@ string Func_searched_case::getStrVal(Row& row, if (isNull) return string(""); - return parm[i+1]->data()->getStrVal(row, isNull); + return parm[i]->data()->getStrVal(row, isNull); } @@ -518,7 +562,7 @@ IDB_Decimal Func_searched_case::getDecimalVal(Row& row, if (isNull) return IDB_Decimal(); // need a null value for IDB_Decimal?? - return parm[i+1]->data()->getDecimalVal(row, isNull); + return parm[i]->data()->getDecimalVal(row, isNull); } @@ -532,7 +576,7 @@ double Func_searched_case::getDoubleVal(Row& row, if (isNull) return doubleNullVal(); - return parm[i+1]->data()->getDoubleVal(row, isNull); + return parm[i]->data()->getDoubleVal(row, isNull); } @@ -546,10 +590,10 @@ int32_t Func_searched_case::getDateIntVal(rowgroup::Row& row, if (isNull) return joblist::DATENULL; - return parm[i+1]->data()->getDateIntVal(row, isNull); -} + return parm[i]->data()->getDateIntVal(row, isNull); +} + - int64_t Func_searched_case::getDatetimeIntVal(rowgroup::Row& row, FunctionParm& parm, bool& isNull, @@ -560,8 +604,8 @@ int64_t Func_searched_case::getDatetimeIntVal(rowgroup::Row& row, if (isNull) return joblist::DATETIMENULL; - return parm[i+1]->data()->getDatetimeIntVal(row, isNull); -} + return parm[i]->data()->getDatetimeIntVal(row, isNull); +} } // namespace funcexp From f2d748cff197656c7ae5d490d0298eabbabccc7d Mon Sep 17 00:00:00 2001 From: david hill Date: Mon, 16 Apr 2018 16:22:03 -0500 Subject: [PATCH 08/10] MCOL-1293 --- utils/clusterTester/columnstoreClusterTester.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/utils/clusterTester/columnstoreClusterTester.sh b/utils/clusterTester/columnstoreClusterTester.sh index 341e37748..9f8f3e9a3 100755 --- a/utils/clusterTester/columnstoreClusterTester.sh +++ b/utils/clusterTester/columnstoreClusterTester.sh @@ -736,7 +736,7 @@ checkPackages() echo "** Run MariaDB ColumnStore Dependent Package Check" echo "" - declare -a CENTOS_PKG=("expect" "perl" "perl-DBI" "openssl" "zlib" "file" "sudo" "libaio" "rsync" "snappy" "net-tools") + declare -a CENTOS_PKG=("expect" "perl" "perl-DBI" "openssl" "zlib" "file" "sudo" "libaio" "rsync" "snappy" "net-tools" "numactl-libs") declare -a CENTOS_PKG_NOT=("mariadb-libs") if [ "$OS" == "centos6" ] || [ "$OS" == "centos7" ]; then @@ -855,7 +855,7 @@ checkPackages() fi fi - declare -a SUSE_PKG=("boost-devel" "expect" "perl" "perl-DBI" "openssl" "file" "sudo" "libaio1" "rsync" "libsnappy1" "net-tools") + declare -a SUSE_PKG=("boost-devel" "expect" "perl" "perl-DBI" "openssl" "file" "sudo" "libaio1" "rsync" "libsnappy1" "net-tools" "libnuma1") declare -a SUSE_PKG_NOT=("mariadb" , "libmariadb18") if [ "$OS" == "suse12" ]; then @@ -946,7 +946,7 @@ checkPackages() fi fi - declare -a UBUNTU_PKG=("libboost-all-dev" "expect" "libdbi-perl" "perl" "openssl" "file" "sudo" "libreadline-dev" "rsync" "libsnappy1V5" "net-tools") + declare -a UBUNTU_PKG=("libboost-all-dev" "expect" "libdbi-perl" "perl" "openssl" "file" "sudo" "libreadline-dev" "rsync" "libsnappy1V5" "net-tools" "libnuma1" ) declare -a UBUNTU_PKG_NOT=("mariadb-server" "libmariadb18") if [ "$OS" == "ubuntu16" ] ; then @@ -1063,7 +1063,7 @@ checkPackages() fi fi - declare -a DEBIAN_PKG=("libboost-all-dev" "expect" "libdbi-perl" "perl" "openssl" "file" "sudo" "libreadline-dev" "rsync" "libsnappy1" "net-tools") + declare -a DEBIAN_PKG=("libboost-all-dev" "expect" "libdbi-perl" "perl" "openssl" "file" "sudo" "libreadline-dev" "rsync" "libsnappy1" "net-tools" "libnuma1") declare -a DEBIAN_PKG_NOT=("libmariadb18" "mariadb-server") if [ "$OS" == "debian8" ]; then @@ -1180,7 +1180,7 @@ checkPackages() fi fi - declare -a DEBIAN9_PKG=("libboost-all-dev" "expect" "libdbi-perl" "perl" "openssl" "file" "sudo" "libreadline5" "rsync" "libsnappy1V5" "net-tools" "libaio1") + declare -a DEBIAN9_PKG=("libboost-all-dev" "expect" "libdbi-perl" "perl" "openssl" "file" "sudo" "libreadline5" "rsync" "libsnappy1V5" "net-tools" "libaio1" "libnuma1") declare -a DEBIAN9_PKG_NOT=("libmariadb18" "mariadb-server") if [ "$OS" == "debian9" ]; then From 51715c76eee3992d59970e1b755f64c1cc7ff82d Mon Sep 17 00:00:00 2001 From: Roman Nozdrin Date: Tue, 24 Apr 2018 15:14:08 +0300 Subject: [PATCH 09/10] MCOL-1348 Add multiply UDAF calls support. --- dbcon/joblist/tupleaggregatestep.cpp | 134 +++++++++++++++++---------- 1 file changed, 85 insertions(+), 49 deletions(-) diff --git a/dbcon/joblist/tupleaggregatestep.cpp b/dbcon/joblist/tupleaggregatestep.cpp index b5cde967b..e68bc9f18 100755 --- a/dbcon/joblist/tupleaggregatestep.cpp +++ b/dbcon/joblist/tupleaggregatestep.cpp @@ -958,6 +958,7 @@ void TupleAggregateStep::prep1PhaseAggregate( vector functionVec; uint32_t bigIntWidth = sizeof(int64_t); uint32_t bigUintWidth = sizeof(uint64_t); + uint32_t projColsUDAFIndex = 0; mcsv1sdk::mcsv1_UDAF* pUDAFFunc = NULL; // for count column of average function @@ -1135,18 +1136,27 @@ void TupleAggregateStep::prep1PhaseAggregate( SP_ROWAGG_FUNC_t funct; if (aggOp == ROWAGG_UDAF) - { - UDAFColumn* udafc = dynamic_cast(jobInfo.projectionCols[i].get()); - if (udafc) - { - // Create a RowAggFunctionCol (UDAF subtype) with the context. - funct.reset(new RowUDAFFunctionCol(udafc->getContext(), colProj, i)); - } - else - { - throw logic_error("prep1PhasesAggregate: A UDAF function is called but there's no UDAFColumn"); - } - } + { + std::vector::iterator it = jobInfo.projectionCols.begin() + projColsUDAFIndex; + for (; it != jobInfo.projectionCols.end(); it++) + { + UDAFColumn* udafc = dynamic_cast((*it).get()); + projColsUDAFIndex++; + if (udafc) + { + pUDAFFunc = udafc->getContext().getFunction(); + // Create a RowAggFunctionCol (UDAF subtype) with the context. + funct.reset(new RowUDAFFunctionCol(udafc->getContext(), colProj, i)); + break; + } + + } + + if (it == jobInfo.projectionCols.end()) + { + throw logic_error("prep1PhaseAggregate: A UDAF function is called but there's no/not enough UDAFColumn/-s"); + } + } else { funct.reset(new RowAggFunctionCol(aggOp, stats, colProj, i)); @@ -1484,6 +1494,7 @@ void TupleAggregateStep::prep1PhaseDistinctAggregate( AGG_MAP aggFuncMap; mcsv1sdk::mcsv1_UDAF* pUDAFFunc = NULL; set avgSet; + uint32_t projColsUDAFIndex = 0; // for count column of average function map avgFuncMap, avgDistFuncMap; @@ -1636,19 +1647,27 @@ void TupleAggregateStep::prep1PhaseDistinctAggregate( SP_ROWAGG_FUNC_t funct; if (aggOp == ROWAGG_UDAF) - { - UDAFColumn* udafc = dynamic_cast(jobInfo.projectionCols[i].get()); - if (udafc) - { - pUDAFFunc = udafc->getContext().getFunction(); - // Create a RowAggFunctionCol (UDAF subtype) with the context. - funct.reset(new RowUDAFFunctionCol(udafc->getContext(), colProj, colAgg)); - } - else - { - throw logic_error("prep1PhaseDistinctAggregate: A UDAF function is called but there's no UDAFColumn"); - } - } + { + std::vector::iterator it = jobInfo.projectionCols.begin() + projColsUDAFIndex; + for (; it != jobInfo.projectionCols.end(); it++) + { + UDAFColumn* udafc = dynamic_cast((*it).get()); + projColsUDAFIndex++; + if (udafc) + { + pUDAFFunc = udafc->getContext().getFunction(); + // Create a RowAggFunctionCol (UDAF subtype) with the context. + funct.reset(new RowUDAFFunctionCol(udafc->getContext(), colProj, colAgg)); + break; + } + + } + + if (it == jobInfo.projectionCols.end()) + { + throw logic_error("prep1PhaseDistinctAggregate: A UDAF function is called but there's no/not enough UDAFColumn/-s"); + } + } else { funct.reset(new RowAggFunctionCol(aggOp, stats, colProj, colAgg)); @@ -2579,6 +2598,7 @@ void TupleAggregateStep::prep2PhasesAggregate( vector > aggColVec; set avgSet; vector >& returnedColVec = jobInfo.returnedColVec; + uint32_t projColsUDAFIndex = 0; for (uint64_t i = 0; i < returnedColVec.size(); i++) { // skip if not an aggregation column @@ -2746,18 +2766,26 @@ void TupleAggregateStep::prep2PhasesAggregate( SP_ROWAGG_FUNC_t funct; if (aggOp == ROWAGG_UDAF) { - UDAFColumn* udafc = dynamic_cast(jobInfo.projectionCols[i].get()); - if (udafc) - { - pUDAFFunc = udafc->getContext().getFunction(); - // Create a RowAggFunctionCol (UDAF subtype) with the context. - funct.reset(new RowUDAFFunctionCol(udafc->getContext(), colProj, colAggPm)); - } - else - { - throw logic_error("prep2PhasesAggregate: A UDAF function is called but there's no UDAFColumn"); - } - } + std::vector::iterator it = jobInfo.projectionCols.begin() + projColsUDAFIndex; + for (; it != jobInfo.projectionCols.end(); it++) + { + UDAFColumn* udafc = dynamic_cast((*it).get()); + projColsUDAFIndex++; + if (udafc) + { + pUDAFFunc = udafc->getContext().getFunction(); + // Create a RowAggFunctionCol (UDAF subtype) with the context. + funct.reset(new RowUDAFFunctionCol(udafc->getContext(), colProj, colAggPm)); + break; + } + + } + + if (it == jobInfo.projectionCols.end()) + { + throw logic_error("prep2PhasesAggregate: A UDAF function is called but there's no/not enough UDAFColumn/-s"); + } + } else { funct.reset(new RowAggFunctionCol(aggOp, stats, colProj, colAggPm)); @@ -3301,6 +3329,7 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( vector > aggColVec, aggNoDistColVec; set avgSet, avgDistSet; vector >& returnedColVec = jobInfo.returnedColVec; + uint32_t projColsUDAFIndex = 0; for (uint64_t i = 0; i < returnedColVec.size(); i++) { // col should be an aggregate or groupBy or window function @@ -3498,18 +3527,25 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( SP_ROWAGG_FUNC_t funct; if (aggOp == ROWAGG_UDAF) { - UDAFColumn* udafc = dynamic_cast(jobInfo.projectionCols[i].get()); - if (udafc) - { - pUDAFFunc = udafc->getContext().getFunction(); - // Create a RowAggFunctionCol (UDAF subtype) with the context. - funct.reset(new RowUDAFFunctionCol(udafc->getContext(), colProj, colAggPm)); - } - else - { - throw logic_error("prep2PhasesDistinctAggregate: A UDAF function is called but there's no UDAFColumn"); - } - } + std::vector::iterator it = jobInfo.projectionCols.begin() + projColsUDAFIndex; + for (; it != jobInfo.projectionCols.end(); it++) + { + UDAFColumn* udafc = dynamic_cast((*it).get()); + projColsUDAFIndex++; + if (udafc) + { + pUDAFFunc = udafc->getContext().getFunction(); + // Create a RowAggFunctionCol (UDAF subtype) with the context. + funct.reset(new RowUDAFFunctionCol(udafc->getContext(), colProj, colAggPm)); + break; + } + } + + if (it == jobInfo.projectionCols.end()) + { + throw logic_error("prep2PhasesDistinctAggregate: A UDAF function is called but there's no/not enough UDAFColumn/-s"); + } + } else { funct.reset(new RowAggFunctionCol(aggOp, stats, colProj, colAggPm)); From 863e18744bb2da10c881be21667e5bfef23b1dee Mon Sep 17 00:00:00 2001 From: david hill Date: Wed, 25 Apr 2018 14:07:18 -0500 Subject: [PATCH 10/10] update to 1.1.5 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 445a70a7a..aef96eefc 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ COLUMNSTORE_VERSION_MAJOR=1 COLUMNSTORE_VERSION_MINOR=1 -COLUMNSTORE_VERSION_PATCH=4 +COLUMNSTORE_VERSION_PATCH=5 COLUMNSTORE_VERSION_RELEASE=1