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 
			
		
		
		
	feat: add vacuum_partition functionality with initialization and execution logic
This commit is contained in:
		@@ -1230,6 +1230,67 @@ extern "C"
 | 
			
		||||
  {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  my_bool vacuum_partition_init(UDF_INIT* initid, UDF_ARGS* args, char* message, const char* funcname)
 | 
			
		||||
  {
 | 
			
		||||
    if (args->arg_count != 3 || 
 | 
			
		||||
        args->arg_type[0] != STRING_RESULT || 
 | 
			
		||||
        args->arg_type[1] != STRING_RESULT || 
 | 
			
		||||
        args->arg_type[2] != STRING_RESULT)
 | 
			
		||||
    {
 | 
			
		||||
      sprintf(message, "%s() requires three string arguments", funcname);
 | 
			
		||||
      return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    initid->maybe_null = 0;
 | 
			
		||||
    initid->max_length = 255;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  my_bool mcs_vacuum_partition_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
 | 
			
		||||
  {
 | 
			
		||||
    return vacuum_partition_init(initid, args, message, "MCSVACUUMPARTITION");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const char* mcs_vacuum_partition(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;
 | 
			
		||||
 | 
			
		||||
    tableName.schema = args->args[0];
 | 
			
		||||
    tableName.table = args->args[1];
 | 
			
		||||
    std::string partition = args->args[2];
 | 
			
		||||
 | 
			
		||||
    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");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string vacuumResult = ha_mcs_impl_vacuum_partition(*ci, tableName, partition);
 | 
			
		||||
 | 
			
		||||
    memcpy(result, vacuumResult.c_str(), vacuumResult.length());
 | 
			
		||||
    *length = vacuumResult.length();
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void mcs_vacuum_partition_deinit(UDF_INIT* /*initid*/)
 | 
			
		||||
  {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  my_bool analyze_table_bloat_init(UDF_INIT* initid, UDF_ARGS* args, char* message, const char* funcname)
 | 
			
		||||
  {
 | 
			
		||||
    if (args->arg_count != 2 || 
 | 
			
		||||
 
 | 
			
		||||
@@ -28,6 +28,7 @@
 | 
			
		||||
#include <unordered.h>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <cerrno>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
 | 
			
		||||
@@ -1077,6 +1078,158 @@ std::string ha_mcs_impl_analyze_partition_bloat(cal_impl_if::cal_connection_info
 | 
			
		||||
  return analysisResult;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string ha_mcs_impl_vacuum_partition(cal_impl_if::cal_connection_info& ci,
 | 
			
		||||
                                         execplan::CalpontSystemCatalog::TableName& tablename,
 | 
			
		||||
                                         const std::string& partition)
 | 
			
		||||
{
 | 
			
		||||
  THD* thd = current_thd;
 | 
			
		||||
  ulong sessionID = tid2sid(thd->thread_id);
 | 
			
		||||
  std::string result;
 | 
			
		||||
 | 
			
		||||
  try
 | 
			
		||||
  {
 | 
			
		||||
    // Parse partition triplet string: "dbroot.segment.partition"
 | 
			
		||||
    uint16_t dbRoot;
 | 
			
		||||
    uint16_t segmentNum;
 | 
			
		||||
    uint32_t partitionNum;
 | 
			
		||||
    
 | 
			
		||||
    std::istringstream ss(partition);
 | 
			
		||||
    std::string item;
 | 
			
		||||
    std::vector<std::string> tokens;
 | 
			
		||||
    
 | 
			
		||||
    while (std::getline(ss, item, '.')) {
 | 
			
		||||
      tokens.push_back(item);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (tokens.size() != 3) {
 | 
			
		||||
      return "Error: Invalid partition triplet format. Expected: dbroot.segment.partition";
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
      dbRoot = static_cast<uint16_t>(std::stoul(tokens[0]));
 | 
			
		||||
      segmentNum = static_cast<uint16_t>(std::stoul(tokens[1]));
 | 
			
		||||
      partitionNum = std::stoul(tokens[2]);
 | 
			
		||||
    }
 | 
			
		||||
    catch (const std::exception&)
 | 
			
		||||
    {
 | 
			
		||||
      return "Error: Invalid numeric values in partition triplet";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Get system catalog
 | 
			
		||||
    boost::shared_ptr<execplan::CalpontSystemCatalog> systemCatalogPtr =
 | 
			
		||||
        execplan::CalpontSystemCatalog::makeCalpontSystemCatalog(sessionID);
 | 
			
		||||
    systemCatalogPtr->identity(execplan::CalpontSystemCatalog::EC);
 | 
			
		||||
 | 
			
		||||
    // Get table information
 | 
			
		||||
    execplan::CalpontSystemCatalog::TableName sysCatalogTableName;
 | 
			
		||||
    sysCatalogTableName.schema = tablename.schema;
 | 
			
		||||
    sysCatalogTableName.table = tablename.table;
 | 
			
		||||
 | 
			
		||||
    // Check if table exists
 | 
			
		||||
    execplan::CalpontSystemCatalog::RIDList ridList;
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
      ridList = systemCatalogPtr->columnRIDs(sysCatalogTableName);
 | 
			
		||||
    }
 | 
			
		||||
    catch (const std::exception& ex)
 | 
			
		||||
    {
 | 
			
		||||
      return std::string("Error: Table not found - ") + ex.what();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ridList.empty())
 | 
			
		||||
    {
 | 
			
		||||
      return "Error: Table has no columns";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Get AUX column OID
 | 
			
		||||
    execplan::CalpontSystemCatalog::OID auxColumnOid = systemCatalogPtr->tableAUXColumnOID(sysCatalogTableName);
 | 
			
		||||
 | 
			
		||||
    // Build column list for createHiddenStripeColumnExtents
 | 
			
		||||
    std::vector<BRM::CreateStripeColumnExtentsArgIn> cols;
 | 
			
		||||
 | 
			
		||||
    // Add regular columns
 | 
			
		||||
    for (const auto& roPair : ridList)
 | 
			
		||||
    {
 | 
			
		||||
      BRM::CreateStripeColumnExtentsArgIn colArg;
 | 
			
		||||
      colArg.oid = roPair.objnum;
 | 
			
		||||
      
 | 
			
		||||
      execplan::CalpontSystemCatalog::ColType colType = systemCatalogPtr->colType(roPair.objnum);
 | 
			
		||||
      colArg.colDataType = colType.colDataType;
 | 
			
		||||
      
 | 
			
		||||
      // Set width based on whether it's a dictionary column
 | 
			
		||||
      if (colType.ddn.dictOID > 3000)
 | 
			
		||||
      {
 | 
			
		||||
        colArg.width = 8; // Dictionary columns use 8-byte tokens
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
      {
 | 
			
		||||
        colArg.width = colType.colWidth;
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      cols.push_back(colArg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Add AUX column if it exists
 | 
			
		||||
    if (auxColumnOid > 3000)
 | 
			
		||||
    {
 | 
			
		||||
      BRM::CreateStripeColumnExtentsArgIn auxColArg;
 | 
			
		||||
      auxColArg.oid = auxColumnOid;
 | 
			
		||||
      execplan::CalpontSystemCatalog::ColType auxColType = systemCatalogPtr->colType(auxColumnOid);
 | 
			
		||||
      auxColArg.colDataType = auxColType.colDataType;
 | 
			
		||||
      auxColArg.width = auxColType.colWidth;
 | 
			
		||||
      cols.push_back(auxColArg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::vector<BRM::CreateStripeColumnExtentsArgOut> extents;
 | 
			
		||||
 | 
			
		||||
    // Store original values for comparison
 | 
			
		||||
    uint16_t originalSegmentNum = segmentNum;
 | 
			
		||||
    uint32_t originalPartitionNum = partitionNum;
 | 
			
		||||
    
 | 
			
		||||
    // Call createHiddenStripeColumnExtents
 | 
			
		||||
    BRM::DBRM dbrm;
 | 
			
		||||
    int rc = dbrm.createHiddenStripeColumnExtents(cols, dbRoot, partitionNum, segmentNum, extents);
 | 
			
		||||
 | 
			
		||||
    if (rc != 0)
 | 
			
		||||
    {
 | 
			
		||||
      std::ostringstream oss;
 | 
			
		||||
      oss << "Error: Failed to create hidden stripe column extents, error code: " << rc;
 | 
			
		||||
      return oss.str();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Build success message
 | 
			
		||||
    std::ostringstream successMsg;
 | 
			
		||||
    successMsg << "Successfully created hidden partition on DBRoot " << dbRoot;
 | 
			
		||||
    
 | 
			
		||||
    // Check if the function used our requested values or assigned different ones
 | 
			
		||||
    if (partitionNum != originalPartitionNum || segmentNum != originalSegmentNum)
 | 
			
		||||
    {
 | 
			
		||||
      successMsg << " (requested: " << originalPartitionNum << "." << originalSegmentNum 
 | 
			
		||||
                 << ", assigned: " << partitionNum << "." << segmentNum << ")";
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
      successMsg << " at partition " << partitionNum << ", segment " << segmentNum;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    successMsg << " with " << extents.size() << " extents";
 | 
			
		||||
 | 
			
		||||
    result = successMsg.str();
 | 
			
		||||
  }
 | 
			
		||||
  catch (const std::exception& ex)
 | 
			
		||||
  {
 | 
			
		||||
    std::ostringstream errorMsg;
 | 
			
		||||
    errorMsg << "Error: " << ex.what();
 | 
			
		||||
    result = errorMsg.str();
 | 
			
		||||
  }
 | 
			
		||||
  catch (...)
 | 
			
		||||
  {
 | 
			
		||||
    result = "Error: Unknown exception occurred during vacuum partition operation";
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string ha_mcs_impl_analyze_table_bloat(cal_impl_if::cal_connection_info& ci,
 | 
			
		||||
                                               execplan::CalpontSystemCatalog::TableName& tablename)
 | 
			
		||||
 
 | 
			
		||||
@@ -80,4 +80,7 @@ extern std::string ha_mcs_impl_analyze_partition_bloat(cal_impl_if::cal_connecti
 | 
			
		||||
                                                        const std::string& partition);
 | 
			
		||||
extern std::string ha_mcs_impl_analyze_table_bloat(cal_impl_if::cal_connection_info& ci,
 | 
			
		||||
                                                    execplan::CalpontSystemCatalog::TableName& tablename);
 | 
			
		||||
extern std::string ha_mcs_impl_vacuum_partition(cal_impl_if::cal_connection_info& ci,
 | 
			
		||||
                                                 execplan::CalpontSystemCatalog::TableName& tablename,
 | 
			
		||||
                                                 const std::string& partition);
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -58,6 +58,7 @@ CREATE OR REPLACE FUNCTION mcs_emindex_size RETURNS INTEGER SONAME 'ha_columnsto
 | 
			
		||||
CREATE OR REPLACE FUNCTION mcs_emindex_free RETURNS INTEGER SONAME 'ha_columnstore.so';
 | 
			
		||||
CREATE OR REPLACE FUNCTION mcs_analyze_partition_bloat RETURNS STRING SONAME 'ha_columnstore.so';
 | 
			
		||||
CREATE OR REPLACE FUNCTION mcs_analyze_table_bloat RETURNS STRING SONAME 'ha_columnstore.so';
 | 
			
		||||
CREATE OR REPLACE FUNCTION mcs_vacuum_partition RETURNS STRING SONAME 'ha_columnstore.so';
 | 
			
		||||
CREATE OR REPLACE FUNCTION columnstore_dataload RETURNS STRING SONAME 'ha_columnstore.so';
 | 
			
		||||
CREATE OR REPLACE AGGREGATE FUNCTION regr_avgx RETURNS REAL SONAME 'libregr_mysql.so';
 | 
			
		||||
CREATE OR REPLACE AGGREGATE FUNCTION regr_avgy RETURNS REAL SONAME 'libregr_mysql.so';
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user