You've already forked mariadb-columnstore-engine
							
							
				mirror of
				https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
				synced 2025-11-03 17:13:17 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			1173 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1173 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* Copyright (C) 2014 InfiniDB, Inc.
 | 
						|
   Copyright (C) 2016-2022 MariaDB Corporation
 | 
						|
 | 
						|
   This program is free software; you can redistribute it and/or
 | 
						|
   modify it under the terms of the GNU General Public License
 | 
						|
   as published by the Free Software Foundation; version 2 of
 | 
						|
   the License.
 | 
						|
 | 
						|
   This program is distributed in the hope that it will be useful,
 | 
						|
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
   GNU General Public License for more details.
 | 
						|
 | 
						|
   You should have received a copy of the GNU General Public License
 | 
						|
   along with this program; if not, write to the Free Software
 | 
						|
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 | 
						|
   MA 02110-1301, USA. */
 | 
						|
 | 
						|
#define NEED_CALPONT_INTERFACE
 | 
						|
#define PREFER_MY_CONFIG_H 1
 | 
						|
#include "ha_mcs_impl.h"
 | 
						|
 | 
						|
#include "ha_mcs_impl_if.h"
 | 
						|
using namespace cal_impl_if;
 | 
						|
 | 
						|
#include "configcpp.h"
 | 
						|
using namespace config;
 | 
						|
#include "brmtypes.h"
 | 
						|
using namespace BRM;
 | 
						|
#include "bytestream.h"
 | 
						|
using namespace messageqcpp;
 | 
						|
#include "liboamcpp.h"
 | 
						|
using namespace oam;
 | 
						|
#include "cacheutils.h"
 | 
						|
 | 
						|
#include "errorcodes.h"
 | 
						|
#include "idberrorinfo.h"
 | 
						|
#include "errorids.h"
 | 
						|
using namespace logging;
 | 
						|
 | 
						|
#include "ddlpkg.h"
 | 
						|
#include "calpontsystemcatalog.h"
 | 
						|
 | 
						|
// #include "resourcemanager.h"
 | 
						|
 | 
						|
#include "columnstoreversion.h"
 | 
						|
#include "ha_mcs_sysvars.h"
 | 
						|
#include "basic/string_utils.h"
 | 
						|
 | 
						|
extern "C"
 | 
						|
{
 | 
						|
#define MAXSTRINGLENGTH 50
 | 
						|
 | 
						|
  const char* PmSmallSideMaxMemory = "pmmaxmemorysmallside";
 | 
						|
 | 
						|
  const char* SetParmsPrelude = "Updated ";
 | 
						|
  const char* SetParmsError = "Invalid parameter: ";
 | 
						|
  const char* InvalidParmSize = "Invalid parameter size: Input value cannot be larger than ";
 | 
						|
  const char* MsgEMIndexSizeInitErrMsg = "mcs_emindex_size() takes no arguments";
 | 
						|
  const char* MsgEMIndexFreeInitErrMsg = "mcs_emindex_free() takes no arguments";
 | 
						|
 | 
						|
  const size_t Plen = strlen(SetParmsPrelude);
 | 
						|
  const size_t Elen = strlen(SetParmsError);
 | 
						|
 | 
						|
  const char* invalidParmSizeMessage(uint64_t size, size_t& len)
 | 
						|
  {
 | 
						|
    static char str[sizeof(InvalidParmSize) + 12] = {0};
 | 
						|
    std::ostringstream os;
 | 
						|
    os << InvalidParmSize << size;
 | 
						|
    len = os.str().length();
 | 
						|
    strcpy(str, os.str().c_str());
 | 
						|
    return str;
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool setparms_init(UDF_INIT* initid, UDF_ARGS* args, char* message, const char* funcname)
 | 
						|
  {
 | 
						|
    if (args->arg_count != 2 || args->arg_type[0] != STRING_RESULT || args->arg_type[1] != STRING_RESULT)
 | 
						|
    {
 | 
						|
      sprintf(message, "%s() requires two string arguments", funcname);
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    initid->max_length = MAXSTRINGLENGTH;
 | 
						|
 | 
						|
    char valuestr[MAXSTRINGLENGTH];
 | 
						|
    size_t vlen = args->lengths[1];
 | 
						|
 | 
						|
    memcpy(valuestr, args->args[1], vlen--);
 | 
						|
 | 
						|
    for (size_t i = 0; i < vlen; ++i)
 | 
						|
      if (!isdigit(valuestr[i]))
 | 
						|
      {
 | 
						|
        sprintf(message, "%s() second argument must be numeric or end in G, M or K", funcname);
 | 
						|
        return 1;
 | 
						|
      }
 | 
						|
 | 
						|
    if (!isdigit(valuestr[vlen]))
 | 
						|
    {
 | 
						|
      switch (valuestr[vlen])
 | 
						|
      {
 | 
						|
        case 'G':
 | 
						|
        case 'g':
 | 
						|
        case 'M':
 | 
						|
        case 'm':
 | 
						|
        case 'K':
 | 
						|
        case 'k':
 | 
						|
        case '\0': break;
 | 
						|
 | 
						|
        default:
 | 
						|
          sprintf(message, "%s() second argument must be numeric or end in G, M or K", funcname);
 | 
						|
          return 1;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  const char* mcssetparms(UDF_INIT* /*initid*/, UDF_ARGS* args, char* result, unsigned long* length,
 | 
						|
                          char* /*is_null*/, char* /*error*/)
 | 
						|
  {
 | 
						|
    char parameter[MAXSTRINGLENGTH];
 | 
						|
    char valuestr[MAXSTRINGLENGTH];
 | 
						|
    size_t plen = args->lengths[0];
 | 
						|
    size_t vlen = args->lengths[1];
 | 
						|
 | 
						|
    memcpy(parameter, args->args[0], plen);
 | 
						|
    memcpy(valuestr, args->args[1], vlen);
 | 
						|
 | 
						|
    parameter[plen] = '\0';
 | 
						|
    valuestr[vlen] = '\0';
 | 
						|
 | 
						|
    uint64_t value = Config::uFromText(valuestr);
 | 
						|
 | 
						|
    THD* thd = current_thd;
 | 
						|
    uint32_t sessionID = execplan::CalpontSystemCatalog::idb_tid2sid(thd->thread_id);
 | 
						|
 | 
						|
    const char* msg = SetParmsError;
 | 
						|
    size_t mlen = Elen;
 | 
						|
    bool includeInput = true;
 | 
						|
 | 
						|
    std::string pstr(parameter);
 | 
						|
    boost::algorithm::to_lower(pstr);
 | 
						|
 | 
						|
    if (get_fe_conn_info_ptr() == NULL)
 | 
						|
    {
 | 
						|
      set_fe_conn_info_ptr((void*)new cal_connection_info());
 | 
						|
      thd_set_ha_data(thd, mcs_hton, get_fe_conn_info_ptr());
 | 
						|
    }
 | 
						|
 | 
						|
    cal_connection_info* ci = reinterpret_cast<cal_connection_info*>(get_fe_conn_info_ptr());
 | 
						|
    idbassert(ci != 0);
 | 
						|
 | 
						|
    if (pstr == PmSmallSideMaxMemory)
 | 
						|
    {
 | 
						|
      joblist::ResourceManager* rm = joblist::ResourceManager::instance();
 | 
						|
 | 
						|
      if (rm->getHjTotalUmMaxMemorySmallSide() >= value)
 | 
						|
      {
 | 
						|
        ci->rmParms.push_back(execplan::RMParam(sessionID, execplan::PMSMALLSIDEMEMORY, value));
 | 
						|
 | 
						|
        msg = SetParmsPrelude;
 | 
						|
        mlen = Plen;
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        msg = invalidParmSizeMessage(rm->getHjTotalUmMaxMemorySmallSide(), mlen);
 | 
						|
        includeInput = false;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    memcpy(result, msg, mlen);
 | 
						|
 | 
						|
    if (includeInput)
 | 
						|
    {
 | 
						|
      memcpy(result + mlen, parameter, plen);
 | 
						|
      mlen += plen;
 | 
						|
      memcpy(result + mlen++, " ", 1);
 | 
						|
      memcpy(result + mlen, valuestr, vlen);
 | 
						|
      *length = mlen + vlen;
 | 
						|
    }
 | 
						|
    else
 | 
						|
      *length = mlen;
 | 
						|
 | 
						|
    return result;
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool mcssetparms_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    return setparms_init(initid, args, message, "MCSSETPARMS");
 | 
						|
  }
 | 
						|
 | 
						|
  void mcssetparms_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  const char* calsetparms(UDF_INIT* initid, UDF_ARGS* args, char* result, unsigned long* length,
 | 
						|
                          char* is_null, char* error)
 | 
						|
  {
 | 
						|
    return mcssetparms(initid, args, result, length, is_null, error);
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool calsetparms_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    return setparms_init(initid, args, message, "CALSETPARMS");
 | 
						|
  }
 | 
						|
 | 
						|
  void calsetparms_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool getstats_init(UDF_INIT* initid, UDF_ARGS* args, char* message, const char* funcname)
 | 
						|
  {
 | 
						|
    if (args->arg_count != 0)
 | 
						|
    {
 | 
						|
      sprintf(message, "%s() takes no arguments", funcname);
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    initid->maybe_null = 1;
 | 
						|
    initid->max_length = 255;
 | 
						|
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  const char* mcsgetstats(UDF_INIT* /*initid*/, UDF_ARGS* /*args*/, char* result, unsigned long* length,
 | 
						|
                          char* is_null, char* /*error*/)
 | 
						|
  {
 | 
						|
    if (get_fe_conn_info_ptr() == NULL)
 | 
						|
    {
 | 
						|
      set_fe_conn_info_ptr((void*)new cal_connection_info());
 | 
						|
      thd_set_ha_data(current_thd, mcs_hton, get_fe_conn_info_ptr());
 | 
						|
    }
 | 
						|
 | 
						|
    cal_connection_info* ci = reinterpret_cast<cal_connection_info*>(get_fe_conn_info_ptr());
 | 
						|
 | 
						|
    unsigned long l = ci->queryStats.size();
 | 
						|
 | 
						|
    if (l == 0)
 | 
						|
    {
 | 
						|
      *is_null = 1;
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    if (l > 255)
 | 
						|
      l = 255;
 | 
						|
 | 
						|
    memcpy(result, ci->queryStats.c_str(), l);
 | 
						|
    *length = l;
 | 
						|
    return result;
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool mcsgetstats_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    return getstats_init(initid, args, message, "MCSGETSTATS");
 | 
						|
  }
 | 
						|
 | 
						|
  void mcsgetstats_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  const char* calgetstats(UDF_INIT* initid, UDF_ARGS* args, char* result, unsigned long* length,
 | 
						|
                          char* is_null, char* error)
 | 
						|
  {
 | 
						|
    return mcsgetstats(initid, args, result, length, is_null, error);
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool calgetstats_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    return getstats_init(initid, args, message, "CALGETSTATS");
 | 
						|
  }
 | 
						|
 | 
						|
  void calgetstats_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool settrace_init(UDF_INIT* /*initid*/, UDF_ARGS* args, char* message, const char* funcname)
 | 
						|
  {
 | 
						|
    if (args->arg_count != 1 || args->arg_type[0] != INT_RESULT)
 | 
						|
    {
 | 
						|
      sprintf(message, "%s() requires one INTEGER argument", funcname);
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  long long mcssettrace(UDF_INIT* /*initid*/, UDF_ARGS* args, char* /*is_null*/, char* /*error*/)
 | 
						|
  {
 | 
						|
    if (get_fe_conn_info_ptr() == NULL)
 | 
						|
    {
 | 
						|
      set_fe_conn_info_ptr((void*)new cal_connection_info());
 | 
						|
      thd_set_ha_data(current_thd, mcs_hton, get_fe_conn_info_ptr());
 | 
						|
    }
 | 
						|
 | 
						|
    cal_connection_info* ci = reinterpret_cast<cal_connection_info*>(get_fe_conn_info_ptr());
 | 
						|
 | 
						|
    long long oldTrace = ci->traceFlags;
 | 
						|
    ci->traceFlags = (uint32_t)(*((long long*)args->args[0]));
 | 
						|
    // keep the vtablemode bit
 | 
						|
    ci->traceFlags |= (oldTrace & execplan::CalpontSelectExecutionPlan::TRACE_TUPLE_OFF);
 | 
						|
    ci->traceFlags |= (oldTrace & execplan::CalpontSelectExecutionPlan::TRACE_TUPLE_AUTOSWITCH);
 | 
						|
    return oldTrace;
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool mcssettrace_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    return settrace_init(initid, args, message, "MCSSETTRACE");
 | 
						|
  }
 | 
						|
 | 
						|
  void mcssettrace_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  long long calsettrace(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
 | 
						|
  {
 | 
						|
    return mcssettrace(initid, args, is_null, error);
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool calsettrace_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    return settrace_init(initid, args, message, "CALSETTRACE");
 | 
						|
  }
 | 
						|
 | 
						|
  void calsettrace_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  // Return 1 if system is ready for reads or 0 if not.
 | 
						|
  long long mcssystemready(UDF_INIT* /*initid*/, UDF_ARGS* /*args*/, char* /*is_null*/, char* error)
 | 
						|
  {
 | 
						|
    long long rtn = 0;
 | 
						|
    Oam oam;
 | 
						|
    DBRM dbrm(true);
 | 
						|
 | 
						|
    try
 | 
						|
    {
 | 
						|
      if (dbrm.getSystemReady() > 0 && dbrm.getSystemQueryReady() > 0)
 | 
						|
      {
 | 
						|
        return 1;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    catch (...)
 | 
						|
    {
 | 
						|
      *error = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    return rtn;
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool mcssystemready_init(UDF_INIT* /*initid*/, UDF_ARGS* /*args*/, char* /*message*/)
 | 
						|
  {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  void mcssystemready_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  // Return non-zero if system is read only; 0 if writeable
 | 
						|
  long long mcssystemreadonly(UDF_INIT* /*initid*/, UDF_ARGS* /*args*/, char* /*is_null*/, char* error)
 | 
						|
  {
 | 
						|
    long long rtn = 0;
 | 
						|
    DBRM dbrm(true);
 | 
						|
 | 
						|
    try
 | 
						|
    {
 | 
						|
      if (dbrm.getSystemSuspended())
 | 
						|
      {
 | 
						|
        rtn = 1;
 | 
						|
      }
 | 
						|
 | 
						|
      if (dbrm.isReadWrite() > 0)  // Returns 0 for writable, 5 for read only
 | 
						|
      {
 | 
						|
        rtn = 2;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    catch (...)
 | 
						|
    {
 | 
						|
      *error = 1;
 | 
						|
      rtn = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    return rtn;
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool mcssystemreadonly_init(UDF_INIT* /*initid*/, UDF_ARGS* /*args*/, char* /*message*/)
 | 
						|
  {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  void mcssystemreadonly_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  // Return non-zero if this is the primary UM; 0 if not primary
 | 
						|
  long long mcssystemprimary(UDF_INIT* /*initid*/, UDF_ARGS* /*args*/, char* /*is_null*/, char* error)
 | 
						|
  {
 | 
						|
    long long rtn = 0;
 | 
						|
    Oam oam;
 | 
						|
    std::string PrimaryUMModuleName;
 | 
						|
    std::string localModule;
 | 
						|
    oamModuleInfo_t st;
 | 
						|
 | 
						|
    try
 | 
						|
    {
 | 
						|
      st = oam.getModuleInfo();
 | 
						|
      localModule = boost::get<0>(st);
 | 
						|
      PrimaryUMModuleName = config::Config::makeConfig()->getConfig("SystemConfig", "PrimaryUMModuleName");
 | 
						|
 | 
						|
      if (datatypes::ASCIIStringCaseInsensetiveEquals(localModule, PrimaryUMModuleName))
 | 
						|
        rtn = 1;
 | 
						|
      if (PrimaryUMModuleName == "unassigned")
 | 
						|
        rtn = 1;
 | 
						|
    }
 | 
						|
    catch (std::runtime_error& e)
 | 
						|
    {
 | 
						|
      // It's difficult to return an error message from a numerical UDF
 | 
						|
      // string msg = string("ERROR: Problem getting Primary UM Module Name. ") + e.what();
 | 
						|
      *error = 1;
 | 
						|
    }
 | 
						|
    catch (...)
 | 
						|
    {
 | 
						|
      *error = 1;
 | 
						|
    }
 | 
						|
    return rtn;
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool mcssystemprimary_init(UDF_INIT* /*initid*/, UDF_ARGS* /*args*/, char* /*message*/)
 | 
						|
  {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  void mcssystemprimary_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool viewtablelock_init(UDF_INIT* initid, UDF_ARGS* args, char* message, const char* funcname)
 | 
						|
  {
 | 
						|
    if (args->arg_count == 2 && (args->arg_type[0] != STRING_RESULT || args->arg_type[1] != STRING_RESULT))
 | 
						|
    {
 | 
						|
      sprintf(message, "%s() requires two string arguments", funcname);
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
    else if ((args->arg_count == 1) && (args->arg_type[0] != STRING_RESULT))
 | 
						|
    {
 | 
						|
      sprintf(message, "%s() requires one string argument", funcname);
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
    else if (args->arg_count > 2)
 | 
						|
    {
 | 
						|
      sprintf(message, "%s() takes one or two arguments only", funcname);
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
    else if (args->arg_count == 0)
 | 
						|
    {
 | 
						|
      sprintf(message, "%s() requires at least one argument", funcname);
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    initid->maybe_null = 1;
 | 
						|
    initid->max_length = 255;
 | 
						|
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool mcsviewtablelock_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    return viewtablelock_init(initid, args, message, "MCSVIEWTABLELOCK");
 | 
						|
  }
 | 
						|
 | 
						|
  const char* mcsviewtablelock(UDF_INIT* /*initid*/, UDF_ARGS* args, char* result, unsigned long* length,
 | 
						|
                               char* /*is_null*/, char* /*error*/)
 | 
						|
  {
 | 
						|
    THD* thd = current_thd;
 | 
						|
 | 
						|
    if (get_fe_conn_info_ptr() == NULL)
 | 
						|
    {
 | 
						|
      set_fe_conn_info_ptr((void*)new cal_connection_info());
 | 
						|
      thd_set_ha_data(thd, mcs_hton, get_fe_conn_info_ptr());
 | 
						|
    }
 | 
						|
 | 
						|
    cal_connection_info* ci = reinterpret_cast<cal_connection_info*>(get_fe_conn_info_ptr());
 | 
						|
    execplan::CalpontSystemCatalog::TableName tableName;
 | 
						|
 | 
						|
    if (args->arg_count == 2)
 | 
						|
    {
 | 
						|
      tableName.schema = args->args[0];
 | 
						|
      tableName.table = args->args[1];
 | 
						|
    }
 | 
						|
    else if (args->arg_count == 1)
 | 
						|
    {
 | 
						|
      tableName.table = args->args[0];
 | 
						|
 | 
						|
      if (thd->db.length)
 | 
						|
      {
 | 
						|
        tableName.schema = thd->db.str;
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        std::string msg("No schema information provided");
 | 
						|
        memcpy(result, msg.c_str(), msg.length());
 | 
						|
        *length = msg.length();
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if (lower_case_table_names)
 | 
						|
    {
 | 
						|
      boost::algorithm::to_lower(tableName.schema);
 | 
						|
      boost::algorithm::to_lower(tableName.table);
 | 
						|
    }
 | 
						|
 | 
						|
    if (!ci->dmlProc)
 | 
						|
    {
 | 
						|
      ci->dmlProc = new MessageQueueClient("DMLProc");
 | 
						|
      // cout << "viewtablelock starts a new client " << ci->dmlProc << " for session " << thd->thread_id <<
 | 
						|
      // endl;
 | 
						|
    }
 | 
						|
 | 
						|
    std::string lockinfo = ha_mcs_impl_viewtablelock(*ci, tableName);
 | 
						|
 | 
						|
    memcpy(result, lockinfo.c_str(), lockinfo.length());
 | 
						|
    *length = lockinfo.length();
 | 
						|
    return result;
 | 
						|
  }
 | 
						|
 | 
						|
  void mcsviewtablelock_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool calviewtablelock_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    return viewtablelock_init(initid, args, message, "CALVIEWTABLELOCK");
 | 
						|
  }
 | 
						|
 | 
						|
  const char* calviewtablelock(UDF_INIT* initid, UDF_ARGS* args, char* result, unsigned long* length,
 | 
						|
                               char* is_null, char* error)
 | 
						|
  {
 | 
						|
    return mcsviewtablelock(initid, args, result, length, is_null, error);
 | 
						|
  }
 | 
						|
 | 
						|
  void calviewtablelock_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool cleartablelock_init(UDF_INIT* initid, UDF_ARGS* args, char* message, const char* funcname)
 | 
						|
  {
 | 
						|
    if ((args->arg_count != 1) || (args->arg_type[0] != INT_RESULT))
 | 
						|
    {
 | 
						|
      sprintf(message, "%s() requires one integer argument (the lockID)", funcname);
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    initid->maybe_null = 1;
 | 
						|
    initid->max_length = 255;
 | 
						|
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool mcs_set_ddldebug_level_init(UDF_INIT* initid, UDF_ARGS* args, char* message, const char* funcname)
 | 
						|
  {
 | 
						|
    if ((args->arg_count != 1) || (args->arg_type[0] != INT_RESULT) ||
 | 
						|
        *reinterpret_cast<uint32_t*>(args->args[0]) > 3)
 | 
						|
    {
 | 
						|
      sprintf(message, "%s() requires one integer `debug level` ", funcname);
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    initid->maybe_null = 0;
 | 
						|
    initid->max_length = 5;
 | 
						|
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  const char* mcs_set_ddldebug_level(UDF_INIT* /*initid*/, UDF_ARGS* args, char* result,
 | 
						|
                                     unsigned long* length)
 | 
						|
  {
 | 
						|
    uint32_t level = *reinterpret_cast<uint32_t*>(args->args[0]);
 | 
						|
    std::unique_ptr<ddlpackage::DebugDDLStatement> stmt =
 | 
						|
        std::make_unique<ddlpackage::DebugDDLStatement>(level);
 | 
						|
    stmt->fSessionID = execplan::CalpontSystemCatalog::idb_tid2sid(current_thd->thread_id);
 | 
						|
    MessageQueueClient mq("DDLProc");
 | 
						|
 | 
						|
    ByteStream bytestream;
 | 
						|
    bytestream << (uint32_t)stmt->fSessionID;
 | 
						|
    stmt->serialize(bytestream);
 | 
						|
    ByteStream::byte b = 0;
 | 
						|
    THD* thd = current_thd;
 | 
						|
    std::string emsg;
 | 
						|
    mq.write(bytestream);
 | 
						|
 | 
						|
    try
 | 
						|
    {
 | 
						|
      bytestream = mq.read();
 | 
						|
 | 
						|
      if (bytestream.length() == 0)
 | 
						|
      {
 | 
						|
        thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
        thd->raise_error_printf(ER_INTERNAL_ERROR, "Lost connection to DDLProc");
 | 
						|
        std::memcpy(result, "Error", 5);
 | 
						|
        *length = 5;
 | 
						|
        return result;
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        bytestream >> b;
 | 
						|
        bytestream >> emsg;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    catch (std::runtime_error&)
 | 
						|
    {
 | 
						|
      thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
      thd->raise_error_printf(ER_INTERNAL_ERROR, "Lost connection to DDLProc");
 | 
						|
      std::memcpy(result, "Error", 5);
 | 
						|
      *length = 5;
 | 
						|
      return result;
 | 
						|
    }
 | 
						|
    catch (...)
 | 
						|
    {
 | 
						|
      thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
      thd->raise_error_printf(ER_INTERNAL_ERROR, "Unknown error caught");
 | 
						|
      std::memcpy(result, "Error", 5);
 | 
						|
      *length = 5;
 | 
						|
      return result;
 | 
						|
    }
 | 
						|
 | 
						|
    *length = 2;
 | 
						|
    std::memcpy(result, "Ok", 2);
 | 
						|
    return result;
 | 
						|
  }
 | 
						|
 | 
						|
  void mcs_set_ddldebug_level_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool mcscleartablelock_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    return cleartablelock_init(initid, args, message, "MCSCLEARTABLELOCK");
 | 
						|
  }
 | 
						|
 | 
						|
  const char* mcscleartablelock(UDF_INIT* /*initid*/, UDF_ARGS* args, char* result, unsigned long* length,
 | 
						|
                                char* /*is_null*/, char* /*error*/)
 | 
						|
  {
 | 
						|
    if (get_fe_conn_info_ptr() == NULL)
 | 
						|
    {
 | 
						|
      set_fe_conn_info_ptr((void*)new cal_connection_info());
 | 
						|
      thd_set_ha_data(current_thd, mcs_hton, get_fe_conn_info_ptr());
 | 
						|
    }
 | 
						|
 | 
						|
    cal_connection_info* ci = reinterpret_cast<cal_connection_info*>(get_fe_conn_info_ptr());
 | 
						|
    long long lockID = *reinterpret_cast<long long*>(args->args[0]);
 | 
						|
 | 
						|
    if (!ci->dmlProc)
 | 
						|
    {
 | 
						|
      ci->dmlProc = new MessageQueueClient("DMLProc");
 | 
						|
      // cout << "cleartablelock starts a new client " << ci->dmlProc << " for session " << thd->thread_id <<
 | 
						|
      // endl;
 | 
						|
    }
 | 
						|
 | 
						|
    unsigned long long uLockID = lockID;
 | 
						|
    std::string lockinfo = ha_mcs_impl_cleartablelock(*ci, uLockID);
 | 
						|
 | 
						|
    memcpy(result, lockinfo.c_str(), lockinfo.length());
 | 
						|
    *length = lockinfo.length();
 | 
						|
    return result;
 | 
						|
  }
 | 
						|
 | 
						|
  void mcscleartablelock_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool calcleartablelock_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    return cleartablelock_init(initid, args, message, "CALCLEARTABLELOCK");
 | 
						|
  }
 | 
						|
 | 
						|
  const char* calcleartablelock(UDF_INIT* initid, UDF_ARGS* args, char* result, unsigned long* length,
 | 
						|
                                char* is_null, char* error)
 | 
						|
  {
 | 
						|
    return mcscleartablelock(initid, args, result, length, is_null, error);
 | 
						|
  }
 | 
						|
 | 
						|
  void calcleartablelock_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool lastinsertid_init(UDF_INIT* initid, UDF_ARGS* args, char* message, const char* funcname)
 | 
						|
  {
 | 
						|
    if (args->arg_count == 2 && (args->arg_type[0] != STRING_RESULT || args->arg_type[1] != STRING_RESULT))
 | 
						|
    {
 | 
						|
      sprintf(message, "%s() requires two string arguments", funcname);
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
    else if ((args->arg_count == 1) && (args->arg_type[0] != STRING_RESULT))
 | 
						|
    {
 | 
						|
      sprintf(message, "%s() requires one string argument", funcname);
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
    else if (args->arg_count > 2)
 | 
						|
    {
 | 
						|
      sprintf(message, "%s() takes one or two arguments only", funcname);
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
    else if (args->arg_count == 0)
 | 
						|
    {
 | 
						|
      sprintf(message, "%s() requires at least one argument", funcname);
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    initid->maybe_null = 1;
 | 
						|
    initid->max_length = 255;
 | 
						|
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool mcslastinsertid_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    return lastinsertid_init(initid, args, message, "MCSLASTINSERTID");
 | 
						|
  }
 | 
						|
 | 
						|
  long long mcslastinsertid(UDF_INIT* /*initid*/, UDF_ARGS* args, char* /*is_null*/, char* /*error*/)
 | 
						|
  {
 | 
						|
    THD* thd = current_thd;
 | 
						|
 | 
						|
    execplan::CalpontSystemCatalog::TableName tableName;
 | 
						|
    uint64_t nextVal = 0;
 | 
						|
 | 
						|
    if (args->arg_count == 2)
 | 
						|
    {
 | 
						|
      tableName.schema = args->args[0];
 | 
						|
      tableName.table = args->args[1];
 | 
						|
    }
 | 
						|
    else if (args->arg_count == 1)
 | 
						|
    {
 | 
						|
      tableName.table = args->args[0];
 | 
						|
 | 
						|
      if (thd->db.length)
 | 
						|
        tableName.schema = thd->db.str;
 | 
						|
      else
 | 
						|
      {
 | 
						|
        return -1;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if (lower_case_table_names)
 | 
						|
    {
 | 
						|
      boost::algorithm::to_lower(tableName.schema);
 | 
						|
      boost::algorithm::to_lower(tableName.table);
 | 
						|
    }
 | 
						|
 | 
						|
    execplan::CalpontSystemCatalog csc;
 | 
						|
    csc.identity(execplan::CalpontSystemCatalog::FE);
 | 
						|
 | 
						|
    try
 | 
						|
    {
 | 
						|
      nextVal = csc.nextAutoIncrValue(tableName);
 | 
						|
    }
 | 
						|
    catch (std::exception&)
 | 
						|
    {
 | 
						|
      std::string msg("No such table found during autincrement");
 | 
						|
      setError(thd, ER_INTERNAL_ERROR, msg);
 | 
						|
      return nextVal;
 | 
						|
    }
 | 
						|
 | 
						|
    if (nextVal == AUTOINCR_SATURATED)
 | 
						|
    {
 | 
						|
      setError(thd, ER_INTERNAL_ERROR, IDBErrorInfo::instance()->errorMsg(ERR_EXCEED_LIMIT));
 | 
						|
      return nextVal;
 | 
						|
    }
 | 
						|
 | 
						|
    //@Bug 3559. Return a message for table without autoincrement column.
 | 
						|
    if (nextVal == 0)
 | 
						|
    {
 | 
						|
      std::string msg("Autoincrement does not exist for this table.");
 | 
						|
      setError(thd, ER_INTERNAL_ERROR, msg);
 | 
						|
      return nextVal;
 | 
						|
    }
 | 
						|
 | 
						|
    return (nextVal - 1);
 | 
						|
  }
 | 
						|
 | 
						|
  void mcslastinsertid_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool callastinsertid_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    return lastinsertid_init(initid, args, message, "CALLASTINSERTID");
 | 
						|
  }
 | 
						|
 | 
						|
  long long callastinsertid(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
 | 
						|
  {
 | 
						|
    return mcslastinsertid(initid, args, is_null, error);
 | 
						|
  }
 | 
						|
 | 
						|
  void callastinsertid_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool flushcache_init(UDF_INIT* /*initid*/, UDF_ARGS* args, char* message, const char* funcname)
 | 
						|
  {
 | 
						|
    if (args->arg_count != 0)
 | 
						|
    {
 | 
						|
      sprintf(message, "%s() takes no arguments", funcname);
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  void mcsflushcache_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  long long mcsflushcache(UDF_INIT* /*initid*/, UDF_ARGS* /*args*/, char* /*is_null*/, char* /*error*/)
 | 
						|
  {
 | 
						|
    return static_cast<long long>(cacheutils::flushPrimProcCache());
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool mcsflushcache_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    return flushcache_init(initid, args, message, "MCSFLUSHCACHE");
 | 
						|
  }
 | 
						|
 | 
						|
  void calflushcache_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  long long calflushcache(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
 | 
						|
  {
 | 
						|
    return mcsflushcache(initid, args, is_null, error);
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool calflushcache_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    return flushcache_init(initid, args, message, "CALFLUSHCACHE");
 | 
						|
  }
 | 
						|
 | 
						|
  static const unsigned long TraceSize = 16 * 1024;
 | 
						|
 | 
						|
  // mysqld will call this with only 766 bytes available in result no matter what we asked for in
 | 
						|
  // calgettrace_init()
 | 
						|
  // if we return a pointer that is not result, mysqld will take our pointer and use it, freeing up result
 | 
						|
  const char* mcsgettrace(UDF_INIT* /*initid*/, UDF_ARGS* args, char* /*result*/, unsigned long* length,
 | 
						|
                          char* is_null, char* /*error*/)
 | 
						|
  {
 | 
						|
    const std::string* msgp;
 | 
						|
    int flags = 0;
 | 
						|
 | 
						|
    if (args->arg_count > 0)
 | 
						|
    {
 | 
						|
      if (args->arg_type[0] == INT_RESULT)
 | 
						|
      {
 | 
						|
        flags = *reinterpret_cast<int*>(args->args[0]);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (get_fe_conn_info_ptr() == NULL)
 | 
						|
    {
 | 
						|
      set_fe_conn_info_ptr((void*)new cal_connection_info());
 | 
						|
      thd_set_ha_data(current_thd, mcs_hton, get_fe_conn_info_ptr());
 | 
						|
    }
 | 
						|
 | 
						|
    cal_connection_info* ci = reinterpret_cast<cal_connection_info*>(get_fe_conn_info_ptr());
 | 
						|
 | 
						|
    if (flags > 0)
 | 
						|
      // msgp = &connMap[sessionID].extendedStats;
 | 
						|
      msgp = &ci->extendedStats;
 | 
						|
    else
 | 
						|
      // msgp = &connMap[sessionID].miniStats;
 | 
						|
      msgp = &ci->miniStats;
 | 
						|
 | 
						|
    unsigned long l = msgp->size();
 | 
						|
 | 
						|
    if (l == 0)
 | 
						|
    {
 | 
						|
      *is_null = 1;
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    if (l > TraceSize)
 | 
						|
      l = TraceSize;
 | 
						|
 | 
						|
    *length = l;
 | 
						|
    return msgp->c_str();
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool gettrace_init(UDF_INIT* initid, UDF_ARGS* /*args*/, char* /*message*/, const char* /*funcname*/)
 | 
						|
  {
 | 
						|
#if 0
 | 
						|
 | 
						|
        if (args->arg_count != 0)
 | 
						|
        {
 | 
						|
            sprintf(message, "%s() takes no arguments", funcname);
 | 
						|
            return 1;
 | 
						|
        }
 | 
						|
 | 
						|
#endif
 | 
						|
    initid->maybe_null = 1;
 | 
						|
    initid->max_length = TraceSize;
 | 
						|
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool mcsgettrace_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    return gettrace_init(initid, args, message, "MCSGETTRACE");
 | 
						|
  }
 | 
						|
 | 
						|
  void mcsgettrace_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  const char* calgettrace(UDF_INIT* initid, UDF_ARGS* args, char* result, unsigned long* length,
 | 
						|
                          char* is_null, char* error)
 | 
						|
  {
 | 
						|
    return mcsgettrace(initid, args, result, length, is_null, error);
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool calgettrace_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    return gettrace_init(initid, args, message, "CALGETTRACE");
 | 
						|
  }
 | 
						|
 | 
						|
  void calgettrace_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  // --- Plan UDFs ---
 | 
						|
  // Return plan strings or applied rules based on optional parameter:
 | 
						|
  //   no arg or 1 -> optimized/latest plan (ci->queryPlan)
 | 
						|
  //   0 or 'original'  -> pre-RBO plan
 | 
						|
  //   1 or 'optimized' -> post-RBO plan
 | 
						|
  //   2 or 'rules'     -> comma-separated applied RBO rules
 | 
						|
  const char* mcs_get_plan(UDF_INIT* /*initid*/, UDF_ARGS* args, char* /*result*/, unsigned long* length,
 | 
						|
                           char* is_null, char* /*error*/)
 | 
						|
  {
 | 
						|
    if (get_fe_conn_info_ptr() == NULL)
 | 
						|
    {
 | 
						|
      set_fe_conn_info_ptr((void*)new cal_connection_info());
 | 
						|
      thd_set_ha_data(current_thd, mcs_hton, get_fe_conn_info_ptr());
 | 
						|
    }
 | 
						|
 | 
						|
    cal_connection_info* ci = reinterpret_cast<cal_connection_info*>(get_fe_conn_info_ptr());
 | 
						|
    static const std::string wrongArg("Wrong argument produced");
 | 
						|
    const std::string* out = &wrongArg;
 | 
						|
    ;
 | 
						|
    if (args && args->arg_count >= 1 && args->args[0])
 | 
						|
    {
 | 
						|
      if (args->arg_type[0] == INT_RESULT)
 | 
						|
      {
 | 
						|
        long long sel = *reinterpret_cast<long long*>(args->args[0]);
 | 
						|
        if (sel == 0)
 | 
						|
          out = &ci->queryPlanOriginal;
 | 
						|
        else if (sel == 1)
 | 
						|
          out = &ci->queryPlanOptimized;
 | 
						|
        else if (sel == 2)
 | 
						|
          out = &ci->rboAppliedRules;
 | 
						|
      }
 | 
						|
      else if (args->arg_type[0] == STRING_RESULT)
 | 
						|
      {
 | 
						|
        std::string key(args->args[0], args->lengths[0]);
 | 
						|
        // normalize to lower
 | 
						|
        for (auto& ch : key)
 | 
						|
          ch = (char)tolower((unsigned char)ch);
 | 
						|
        if (key == "original" || key == "orig" || key == "0")
 | 
						|
          out = &ci->queryPlanOriginal;
 | 
						|
        else if (key == "optimized" || key == "opt" || key == "1")
 | 
						|
          out = &ci->queryPlanOptimized;
 | 
						|
        else if (key == "rules" || key == "2")
 | 
						|
          out = &ci->rboAppliedRules;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    unsigned long l = out->size();
 | 
						|
 | 
						|
    if (l == 0)
 | 
						|
    {
 | 
						|
      *is_null = 1;
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    if (l > TraceSize * 100)
 | 
						|
      l = TraceSize * 100;
 | 
						|
 | 
						|
    *length = l;
 | 
						|
    return out->c_str();
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool mcs_get_plan_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    if (args->arg_count > 1)
 | 
						|
    {
 | 
						|
      sprintf(message, "MCSGETPLAN() takes 0 or 1 argument: [original|optimized|rules|0|1|2]");
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
    if (args->arg_count == 1 && !(args->arg_type[0] == INT_RESULT || args->arg_type[0] == STRING_RESULT))
 | 
						|
    {
 | 
						|
      sprintf(message, "MCSGETPLAN() argument must be INT or STRING");
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
    initid->maybe_null = 1;
 | 
						|
    initid->max_length = TraceSize;
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  void mcs_get_plan_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool getversion_init(UDF_INIT* /*initid*/, UDF_ARGS* args, char* message, const char* funcname)
 | 
						|
  {
 | 
						|
    if (args->arg_count != 0)
 | 
						|
    {
 | 
						|
      sprintf(message, "%s() takes no arguments", funcname);
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  const char* mcsgetversion(UDF_INIT* /*initid*/, UDF_ARGS* /*args*/, char* result, unsigned long* length,
 | 
						|
                            char* /*is_null*/, char* /*error*/)
 | 
						|
  {
 | 
						|
    std::string version(columnstore_version);
 | 
						|
    *length = version.size();
 | 
						|
    memcpy(result, version.c_str(), *length);
 | 
						|
    return result;
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool mcsgetversion_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    return getversion_init(initid, args, message, "MCSGETVERSION");
 | 
						|
  }
 | 
						|
 | 
						|
  void mcsgetversion_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  const char* calgetversion(UDF_INIT* initid, UDF_ARGS* args, char* result, unsigned long* length,
 | 
						|
                            char* is_null, char* error)
 | 
						|
  {
 | 
						|
    return mcsgetversion(initid, args, result, length, is_null, error);
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool calgetversion_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    return getversion_init(initid, args, message, "CALGETVERSION");
 | 
						|
  }
 | 
						|
 | 
						|
  void calgetversion_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool getsqlcount_init(UDF_INIT* /*initid*/, UDF_ARGS* args, char* message, const char* funcname)
 | 
						|
  {
 | 
						|
    if (args->arg_count != 0)
 | 
						|
    {
 | 
						|
      sprintf(message, "%s() takes no arguments", funcname);
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  const char* mcsgetsqlcount(UDF_INIT* /*initid*/, UDF_ARGS* /*args*/, char* result, unsigned long* length,
 | 
						|
                             char* /*is_null*/, char* /*error*/)
 | 
						|
  {
 | 
						|
    if (get_fe_conn_info_ptr() == NULL)
 | 
						|
    {
 | 
						|
      set_fe_conn_info_ptr((void*)new cal_connection_info());
 | 
						|
      thd_set_ha_data(current_thd, mcs_hton, get_fe_conn_info_ptr());
 | 
						|
    }
 | 
						|
 | 
						|
    cal_connection_info* ci = reinterpret_cast<cal_connection_info*>(get_fe_conn_info_ptr());
 | 
						|
    idbassert(ci != 0);
 | 
						|
 | 
						|
    MessageQueueClient* mqc = 0;
 | 
						|
    mqc = new MessageQueueClient("ExeMgr1");
 | 
						|
 | 
						|
    ByteStream msg;
 | 
						|
    ByteStream::quadbyte runningSql, waitingSql;
 | 
						|
    ByteStream::quadbyte qb = 5;
 | 
						|
    msg << qb;
 | 
						|
    mqc->write(msg);
 | 
						|
 | 
						|
    // get ExeMgr response
 | 
						|
    msg.restart();
 | 
						|
    msg = mqc->read();
 | 
						|
 | 
						|
    if (msg.length() == 0)
 | 
						|
    {
 | 
						|
      memcpy(result, "Lost connection to ExeMgr", *length);
 | 
						|
      return result;
 | 
						|
    }
 | 
						|
 | 
						|
    msg >> runningSql;
 | 
						|
    msg >> waitingSql;
 | 
						|
    delete mqc;
 | 
						|
 | 
						|
    char ans[128];
 | 
						|
    sprintf(ans, "Running SQL statements %d, Waiting SQL statments %d", runningSql, waitingSql);
 | 
						|
    *length = strlen(ans);
 | 
						|
    memcpy(result, ans, *length);
 | 
						|
    return result;
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool mcsgetsqlcount_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    return getstats_init(initid, args, message, "MCSGETSQLCOUNT");
 | 
						|
  }
 | 
						|
 | 
						|
  void mcsgetsqlcount_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  const char* calgetsqlcount(UDF_INIT* initid, UDF_ARGS* args, char* result, unsigned long* length,
 | 
						|
                             char* is_null, char* error)
 | 
						|
  {
 | 
						|
    return mcsgetsqlcount(initid, args, result, length, is_null, error);
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool calgetsqlcount_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    return getstats_init(initid, args, message, "CALGETSQLCOUNT");
 | 
						|
  }
 | 
						|
 | 
						|
  void calgetsqlcount_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  long long mcs_emindex_size(UDF_INIT* /*initid*/, UDF_ARGS* /*args*/, char* /*is_null*/, char* /*error*/)
 | 
						|
  {
 | 
						|
    DBRM dbrm;
 | 
						|
    return dbrm.EMIndexShmemSize();
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool mcs_emindex_size_init(UDF_INIT* /*initid*/, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    if (args->arg_count != 0)
 | 
						|
    {
 | 
						|
      strcpy(message, MsgEMIndexSizeInitErrMsg);
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  void mcs_emindex_size_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  long long mcs_emindex_free(UDF_INIT* /*initid*/, UDF_ARGS* /*args*/, char* /*is_null*/, char* /*error*/)
 | 
						|
  {
 | 
						|
    DBRM dbrm;
 | 
						|
    return dbrm.EMIndexShmemFree();
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool mcs_emindex_free_init(UDF_INIT* /*initid*/, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    if (args->arg_count != 0)
 | 
						|
    {
 | 
						|
      strcpy(message, MsgEMIndexFreeInitErrMsg);
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  void mcs_emindex_free_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
}  // extern "C"
 |