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 
			
		
		
		
	* MSan added with fixes for libc++ * libc++ sepatare build * add libc++ to ci * libstdc++ in CI * libcpp and msan to external projects * std::sqrt * awful_hack(ci): install whole llvm instead of libc++ in terrible way for test containers * Adding ddeb packages for teststages and repos * libc++ more for test container * save some money on debug * colored coredumps * revert ci * chore(ci): collect asan ubsan and libc++ build with mtr and regression status ignored
		
			
				
	
	
		
			2831 lines
		
	
	
		
			95 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			2831 lines
		
	
	
		
			95 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* Copyright (C) 2014 InfiniDB, Inc.
 | 
						|
   Copyright (C) 2016 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. */
 | 
						|
 | 
						|
/*
 | 
						|
 * $Id: ha_mcs_ddl.cpp 9675 2013-07-11 15:38:12Z chao $
 | 
						|
 */
 | 
						|
 | 
						|
#define PREFER_MY_CONFIG_H
 | 
						|
#include <my_config.h>
 | 
						|
#include <string>
 | 
						|
#include <iostream>
 | 
						|
#include <stack>
 | 
						|
#include <fstream>
 | 
						|
#include <sstream>
 | 
						|
#include <cerrno>
 | 
						|
#include <cstring>
 | 
						|
#include <regex>
 | 
						|
#include <unordered.h>
 | 
						|
#include <utility>
 | 
						|
#include <cassert>
 | 
						|
 | 
						|
#include <boost/shared_ptr.hpp>
 | 
						|
#include <boost/tokenizer.hpp>
 | 
						|
using namespace boost;
 | 
						|
 | 
						|
#include "ha_mcs_sysvars.h"
 | 
						|
#include "idb_mysql.h"
 | 
						|
 | 
						|
#include "ha_mcs.h"
 | 
						|
#include "ha_mcs_impl_if.h"
 | 
						|
using namespace cal_impl_if;
 | 
						|
 | 
						|
#include "ddlpkg.h"
 | 
						|
#include "sqlparser.h"
 | 
						|
using namespace ddlpackage;
 | 
						|
 | 
						|
#include "ddlpackageprocessor.h"
 | 
						|
using namespace ddlpackageprocessor;
 | 
						|
 | 
						|
#include "bytestream.h"
 | 
						|
using namespace messageqcpp;
 | 
						|
 | 
						|
#include "configcpp.h"
 | 
						|
using namespace config;
 | 
						|
 | 
						|
#include "idbcompress.h"
 | 
						|
using namespace compress;
 | 
						|
 | 
						|
#include "idberrorinfo.h"
 | 
						|
#include "errorids.h"
 | 
						|
using namespace logging;
 | 
						|
 | 
						|
#include "dbrm.h"
 | 
						|
using namespace BRM;
 | 
						|
 | 
						|
#include "calpontsystemcatalog.h"
 | 
						|
#include "expressionparser.h"
 | 
						|
#include "calpontselectexecutionplan.h"
 | 
						|
#include "simplefilter.h"
 | 
						|
#include "simplecolumn.h"
 | 
						|
#include "expressionparser.h"
 | 
						|
#include "constantcolumn.h"
 | 
						|
using namespace execplan;
 | 
						|
 | 
						|
#include "resourcemanager.h"
 | 
						|
using namespace joblist;
 | 
						|
using namespace std;
 | 
						|
 | 
						|
namespace
 | 
						|
{
 | 
						|
typedef CalpontSelectExecutionPlan::ColumnMap::value_type CMVT_;
 | 
						|
// HDFS is never used nowadays, so don't bother
 | 
						|
bool useHdfs = false;  // ResourceManager::instance()->useHdfs();
 | 
						|
 | 
						|
#include "ha_autoi.cpp"
 | 
						|
 | 
						|
// convenience fcn
 | 
						|
inline uint32_t tid2sid(const uint32_t tid)
 | 
						|
{
 | 
						|
  return CalpontSystemCatalog::idb_tid2sid(tid);
 | 
						|
}
 | 
						|
 | 
						|
static void decode_objectname(char* buf, const char* path, size_t buf_size)
 | 
						|
{
 | 
						|
  size_t new_path_len = filename_to_tablename(path, buf, buf_size);
 | 
						|
  buf[new_path_len] = '\0';
 | 
						|
}
 | 
						|
 | 
						|
static void decode_file_path(const char* path, char* decoded_dbname, char* decoded_tbname)
 | 
						|
{
 | 
						|
  // The format cont ains './' in the beginning of a path.
 | 
						|
  char* dbname_start = (char*)path + 2;
 | 
						|
  char* dbname_end = dbname_start;
 | 
						|
  while (*dbname_end != '/')
 | 
						|
    dbname_end++;
 | 
						|
 | 
						|
  int cnt = dbname_end - dbname_start;
 | 
						|
  char* dbname = (char*)my_alloca(cnt + 1);
 | 
						|
  memcpy(dbname, dbname_start, cnt);
 | 
						|
  dbname[cnt] = '\0';
 | 
						|
  decode_objectname(decoded_dbname, dbname, FN_REFLEN);
 | 
						|
  my_afree(dbname);
 | 
						|
 | 
						|
  char* tbname_start = dbname_end + 1;
 | 
						|
  decode_objectname(decoded_tbname, tbname_start, FN_REFLEN);
 | 
						|
}
 | 
						|
 | 
						|
CalpontSystemCatalog::ColDataType convertDataType(const ddlpackage::ColumnType& ct)
 | 
						|
{
 | 
						|
  const datatypes::TypeHandler* h = datatypes::TypeHandler::find_by_ddltype(ct);
 | 
						|
  if (!h)
 | 
						|
  {
 | 
						|
    throw runtime_error("Unsupported datatype!");
 | 
						|
    return CalpontSystemCatalog::UNDEFINED;
 | 
						|
  }
 | 
						|
  return h->code();
 | 
						|
}
 | 
						|
 | 
						|
int parseCompressionComment(std::string comment)
 | 
						|
{
 | 
						|
  boost::algorithm::to_upper(comment);
 | 
						|
  std::regex compat("[[:space:]]*COMPRESSION[[:space:]]*=[[:space:]]*", std::regex_constants::extended);
 | 
						|
  int compressiontype = 0;
 | 
						|
  std::match_results<std::string::const_iterator> what;
 | 
						|
  std::string::const_iterator start, end;
 | 
						|
  start = comment.begin();
 | 
						|
  end = comment.end();
 | 
						|
  std::regex_constants::match_flag_type flags = std::regex_constants::match_default;
 | 
						|
 | 
						|
  if (std::regex_search(start, end, what, compat, flags))
 | 
						|
  {
 | 
						|
    // Find the pattern, now get the compression type
 | 
						|
    string compType(&(*(what[0].second)));
 | 
						|
    //; is the separator between compression and autoincrement comments.
 | 
						|
    unsigned i = compType.find_first_of(";");
 | 
						|
 | 
						|
    if (i <= compType.length())
 | 
						|
    {
 | 
						|
      compType = compType.substr(0, i);
 | 
						|
    }
 | 
						|
 | 
						|
    i = compType.find_last_not_of(" ");
 | 
						|
 | 
						|
    if (i <= compType.length())
 | 
						|
    {
 | 
						|
      compType = compType.substr(0, i + 1);
 | 
						|
    }
 | 
						|
 | 
						|
    errno = 0;
 | 
						|
    char* ep = NULL;
 | 
						|
    const char* str = compType.c_str();
 | 
						|
    compressiontype = strtoll(str, &ep, 10);
 | 
						|
 | 
						|
    //  (no digits) || (more chars)  || (other errors & value = 0)
 | 
						|
    if ((ep == str) || (*ep != '\0') || (errno != 0 && compressiontype == 0))
 | 
						|
    {
 | 
						|
      compressiontype = -1;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else
 | 
						|
    compressiontype = MAX_INT;
 | 
						|
 | 
						|
  // MCOL-4685: ignore [COMMENT '[compression=0] option at table or column level (no error
 | 
						|
  // messages, just disregard);
 | 
						|
  if (compressiontype == 0)
 | 
						|
    compressiontype = 2;
 | 
						|
 | 
						|
  return compressiontype;
 | 
						|
}
 | 
						|
 | 
						|
bool validateAutoincrementDatatype(int type)
 | 
						|
{
 | 
						|
  bool validAutoType = false;
 | 
						|
 | 
						|
  switch (type)
 | 
						|
  {
 | 
						|
    case ddlpackage::DDL_INT:
 | 
						|
    case ddlpackage::DDL_INTEGER:
 | 
						|
    case ddlpackage::DDL_BIGINT:
 | 
						|
    case ddlpackage::DDL_MEDINT:
 | 
						|
    case ddlpackage::DDL_SMALLINT:
 | 
						|
    case ddlpackage::DDL_TINYINT:
 | 
						|
    case ddlpackage::DDL_UNSIGNED_INT:
 | 
						|
    case ddlpackage::DDL_UNSIGNED_BIGINT:
 | 
						|
    case ddlpackage::DDL_UNSIGNED_MEDINT:
 | 
						|
    case ddlpackage::DDL_UNSIGNED_SMALLINT:
 | 
						|
    case ddlpackage::DDL_UNSIGNED_TINYINT: validAutoType = true; break;
 | 
						|
  }
 | 
						|
 | 
						|
  return validAutoType;
 | 
						|
}
 | 
						|
 | 
						|
bool validateNextValue(int type, int64_t value)
 | 
						|
{
 | 
						|
  bool validValue = true;
 | 
						|
 | 
						|
  switch (type)
 | 
						|
  {
 | 
						|
    case ddlpackage::DDL_BIGINT:
 | 
						|
    {
 | 
						|
      if (value > MAX_BIGINT)
 | 
						|
        validValue = false;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
    case ddlpackage::DDL_UNSIGNED_BIGINT:
 | 
						|
    {
 | 
						|
      if (static_cast<uint64_t>(value) > MAX_UBIGINT)
 | 
						|
        validValue = false;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
    case ddlpackage::DDL_INT:
 | 
						|
    case ddlpackage::DDL_INTEGER:
 | 
						|
    {
 | 
						|
      if (value > MAX_INT)
 | 
						|
        validValue = false;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
    case ddlpackage::DDL_MEDINT:
 | 
						|
    {
 | 
						|
      if (value > MAX_MEDINT)
 | 
						|
        validValue = false;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
    case ddlpackage::DDL_UNSIGNED_INT:
 | 
						|
    {
 | 
						|
      if (static_cast<uint64_t>(value) > MAX_UINT)
 | 
						|
        validValue = false;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
    case ddlpackage::DDL_UNSIGNED_MEDINT:
 | 
						|
    {
 | 
						|
      if (static_cast<uint64_t>(value) > MAX_UMEDINT)
 | 
						|
        validValue = false;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
    case ddlpackage::DDL_SMALLINT:
 | 
						|
    {
 | 
						|
      if (value > MAX_SMALLINT)
 | 
						|
        validValue = false;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
    case ddlpackage::DDL_UNSIGNED_SMALLINT:
 | 
						|
    {
 | 
						|
      if (static_cast<uint64_t>(value) > MAX_USMALLINT)
 | 
						|
        validValue = false;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
    case ddlpackage::DDL_TINYINT:
 | 
						|
    {
 | 
						|
      if (value > MAX_TINYINT)
 | 
						|
        validValue = false;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
    case ddlpackage::DDL_UNSIGNED_TINYINT:
 | 
						|
    {
 | 
						|
      if (static_cast<uint64_t>(value) > MAX_UTINYINT)
 | 
						|
        validValue = false;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  }
 | 
						|
 | 
						|
  return validValue;
 | 
						|
}
 | 
						|
 | 
						|
bool anyRowInTable(string& schema, string& tableName, int sessionID)
 | 
						|
{
 | 
						|
  // find a column in the table
 | 
						|
  boost::shared_ptr<CalpontSystemCatalog> csc = CalpontSystemCatalog::makeCalpontSystemCatalog(sessionID);
 | 
						|
  csc->identity(execplan::CalpontSystemCatalog::FE);
 | 
						|
  CalpontSystemCatalog::TableName aTableName;
 | 
						|
  if (lower_case_table_names)
 | 
						|
  {
 | 
						|
    algorithm::to_lower(schema);
 | 
						|
    algorithm::to_lower(tableName);
 | 
						|
  }
 | 
						|
  aTableName.schema = schema;
 | 
						|
  aTableName.table = tableName;
 | 
						|
 | 
						|
  CalpontSystemCatalog::RIDList ridList = csc->columnRIDs(aTableName, true);
 | 
						|
  CalpontSystemCatalog::TableColName tableColName = csc->colName(ridList[0].objnum);
 | 
						|
 | 
						|
  CalpontSelectExecutionPlan csep;
 | 
						|
  CalpontSelectExecutionPlan::ReturnedColumnList returnedColumnList;
 | 
						|
  CalpontSelectExecutionPlan::ColumnMap colMap;
 | 
						|
 | 
						|
  SessionManager sm;
 | 
						|
  BRM::TxnID txnID;
 | 
						|
  txnID = sm.getTxnID(sessionID);
 | 
						|
 | 
						|
  if (!txnID.valid)
 | 
						|
  {
 | 
						|
    txnID.id = 0;
 | 
						|
    txnID.valid = true;
 | 
						|
  }
 | 
						|
 | 
						|
  QueryContext verID;
 | 
						|
  verID = sm.verID();
 | 
						|
  csep.txnID(txnID.id);
 | 
						|
  csep.verID(verID);
 | 
						|
  csep.sessionID(sessionID);
 | 
						|
 | 
						|
  string firstCol = tableColName.schema + "." + tableColName.table + "." + tableColName.column;
 | 
						|
  SimpleColumn* col[1];
 | 
						|
  col[0] = new SimpleColumn(firstCol, sessionID);
 | 
						|
  SRCP srcp;
 | 
						|
  srcp.reset(col[0]);
 | 
						|
  colMap.insert(CMVT_(firstCol, srcp));
 | 
						|
  csep.columnMapNonStatic(colMap);
 | 
						|
  returnedColumnList.push_back(srcp);
 | 
						|
  csep.returnedCols(returnedColumnList);
 | 
						|
 | 
						|
  CalpontSelectExecutionPlan::TableList tablelist;
 | 
						|
  tablelist.push_back(make_aliastable(schema, tableName, ""));
 | 
						|
  csep.tableList(tablelist);
 | 
						|
 | 
						|
  boost::shared_ptr<messageqcpp::MessageQueueClient> exemgrClient(
 | 
						|
      new messageqcpp::MessageQueueClient("ExeMgr1"));
 | 
						|
  ByteStream msg, emsgBs;
 | 
						|
  rowgroup::RGData rgData;
 | 
						|
  ByteStream::quadbyte qb = 4;
 | 
						|
  msg << qb;
 | 
						|
  std::shared_ptr<rowgroup::RowGroup> rowGroup = 0;
 | 
						|
  bool anyRow = false;
 | 
						|
 | 
						|
  exemgrClient->write(msg);
 | 
						|
  ByteStream msgPlan;
 | 
						|
  csep.serialize(msgPlan);
 | 
						|
  exemgrClient->write(msgPlan);
 | 
						|
  msg.restart();
 | 
						|
  msg = exemgrClient->read();  // error handling
 | 
						|
  emsgBs = exemgrClient->read();
 | 
						|
  ByteStream::quadbyte qb1;
 | 
						|
 | 
						|
  if (emsgBs.length() == 0)
 | 
						|
  {
 | 
						|
    // exemgrClient->shutdown();
 | 
						|
    // delete exemgrClient;
 | 
						|
    // exemgrClient = 0;
 | 
						|
    throw runtime_error("Lost conection to ExeMgr.");
 | 
						|
  }
 | 
						|
 | 
						|
  string emsgStr;
 | 
						|
  emsgBs >> emsgStr;
 | 
						|
 | 
						|
  if (msg.length() == 4)
 | 
						|
  {
 | 
						|
    msg >> qb1;
 | 
						|
 | 
						|
    if (qb1 != 0)
 | 
						|
    {
 | 
						|
      // exemgrClient->shutdown();
 | 
						|
      // delete exemgrClient;
 | 
						|
      // exemgrClient = 0;
 | 
						|
      throw runtime_error(emsgStr);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  while (true)
 | 
						|
  {
 | 
						|
    msg.restart();
 | 
						|
    msg = exemgrClient->read();
 | 
						|
 | 
						|
    if (msg.length() == 0)
 | 
						|
    {
 | 
						|
      // exemgrClient->shutdown();
 | 
						|
      // delete exemgrClient;
 | 
						|
      // exemgrClient = 0;
 | 
						|
      throw runtime_error("Lost conection to ExeMgr.");
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      if (!rowGroup)
 | 
						|
      {
 | 
						|
        // This is mete data
 | 
						|
        rowGroup.reset(new rowgroup::RowGroup());
 | 
						|
        rowGroup->deserialize(msg);
 | 
						|
        qb = 100;
 | 
						|
        msg.restart();
 | 
						|
        msg << qb;
 | 
						|
        exemgrClient->write(msg);
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      rgData.deserialize(msg);
 | 
						|
      rowGroup->setData(&rgData);
 | 
						|
 | 
						|
      if (rowGroup->getStatus() != 0)
 | 
						|
      {
 | 
						|
        // msg.advance(rowGroup->getDataSize());
 | 
						|
        msg >> emsgStr;
 | 
						|
        // exemgrClient->shutdown();
 | 
						|
        // delete exemgrClient;
 | 
						|
        // exemgrClient = 0;
 | 
						|
        throw runtime_error(emsgStr);
 | 
						|
      }
 | 
						|
 | 
						|
      if (rowGroup->getRowCount() > 0)
 | 
						|
        anyRow = true;
 | 
						|
 | 
						|
      // exemgrClient->shutdown();
 | 
						|
      // delete exemgrClient;
 | 
						|
      // exemgrClient = 0;
 | 
						|
      return anyRow;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool anyTimestampColumn(string& schema, string& tableName, int sessionID)
 | 
						|
{
 | 
						|
  boost::shared_ptr<CalpontSystemCatalog> csc = CalpontSystemCatalog::makeCalpontSystemCatalog(sessionID);
 | 
						|
  csc->identity(execplan::CalpontSystemCatalog::FE);
 | 
						|
  CalpontSystemCatalog::TableName aTableName;
 | 
						|
  if (lower_case_table_names)
 | 
						|
  {
 | 
						|
    algorithm::to_lower(schema);
 | 
						|
    algorithm::to_lower(tableName);
 | 
						|
  }
 | 
						|
 | 
						|
  // select columnname from calpontsys.syscolumn
 | 
						|
  // where schema = schema and tablename = tableName
 | 
						|
  // and datatype = 'timestamp'
 | 
						|
  CalpontSelectExecutionPlan csep;
 | 
						|
  CalpontSelectExecutionPlan::ReturnedColumnList returnedColumnList;
 | 
						|
  CalpontSelectExecutionPlan::FilterTokenList filterTokenList;
 | 
						|
  CalpontSelectExecutionPlan::ColumnMap colMap;
 | 
						|
 | 
						|
  SessionManager sm;
 | 
						|
  BRM::TxnID txnID;
 | 
						|
  txnID = sm.getTxnID(sessionID);
 | 
						|
 | 
						|
  if (!txnID.valid)
 | 
						|
  {
 | 
						|
    txnID.id = 0;
 | 
						|
    txnID.valid = true;
 | 
						|
  }
 | 
						|
 | 
						|
  QueryContext verID;
 | 
						|
  verID = sm.verID();
 | 
						|
  csep.txnID(txnID.id);
 | 
						|
  csep.verID(verID);
 | 
						|
  csep.sessionID(sessionID);
 | 
						|
 | 
						|
  string sysTable = "calpontsys.syscolumn.";
 | 
						|
  string firstCol = sysTable + "columnname";
 | 
						|
  SimpleColumn* c1 = new SimpleColumn(firstCol, sessionID);
 | 
						|
  string secondCol = sysTable + "schema";
 | 
						|
  SimpleColumn* c2 = new SimpleColumn(secondCol, sessionID);
 | 
						|
  string thirdCol = sysTable + "tablename";
 | 
						|
  SimpleColumn* c3 = new SimpleColumn(thirdCol, sessionID);
 | 
						|
  string fourthCol = sysTable + "datatype";
 | 
						|
  SimpleColumn* c4 = new SimpleColumn(fourthCol, sessionID);
 | 
						|
  SRCP srcp;
 | 
						|
  srcp.reset(c1);
 | 
						|
  colMap.insert(CMVT_(firstCol, srcp));
 | 
						|
  srcp.reset(c2);
 | 
						|
  colMap.insert(CMVT_(secondCol, srcp));
 | 
						|
  srcp.reset(c3);
 | 
						|
  colMap.insert(CMVT_(thirdCol, srcp));
 | 
						|
  srcp.reset(c4);
 | 
						|
  colMap.insert(CMVT_(fourthCol, srcp));
 | 
						|
  csep.columnMapNonStatic(colMap);
 | 
						|
  srcp.reset(c1->clone());
 | 
						|
  returnedColumnList.push_back(srcp);
 | 
						|
  csep.returnedCols(returnedColumnList);
 | 
						|
 | 
						|
  // Filters
 | 
						|
  const SOP opeq(new Operator("="));
 | 
						|
  SimpleFilter* f1 = new SimpleFilter(opeq, c2->clone(), new ConstantColumn(schema, ConstantColumn::LITERAL));
 | 
						|
  filterTokenList.push_back(f1);
 | 
						|
  filterTokenList.push_back(new Operator("and"));
 | 
						|
 | 
						|
  SimpleFilter* f2 =
 | 
						|
      new SimpleFilter(opeq, c3->clone(), new ConstantColumn(tableName, ConstantColumn::LITERAL));
 | 
						|
  filterTokenList.push_back(f2);
 | 
						|
  filterTokenList.push_back(new Operator("and"));
 | 
						|
 | 
						|
  SimpleFilter* f3 = new SimpleFilter(
 | 
						|
      opeq, c4->clone(),
 | 
						|
      new ConstantColumn((uint64_t)execplan::CalpontSystemCatalog::TIMESTAMP, ConstantColumn::NUM));
 | 
						|
  filterTokenList.push_back(f3);
 | 
						|
  csep.filterTokenList(filterTokenList);
 | 
						|
 | 
						|
  CalpontSelectExecutionPlan::TableList tablelist;
 | 
						|
  tablelist.push_back(make_aliastable("calpontsys", "syscolumn", ""));
 | 
						|
  csep.tableList(tablelist);
 | 
						|
 | 
						|
  boost::shared_ptr<messageqcpp::MessageQueueClient> exemgrClient(
 | 
						|
      new messageqcpp::MessageQueueClient("ExeMgr1"));
 | 
						|
  ByteStream msg, emsgBs;
 | 
						|
  rowgroup::RGData rgData;
 | 
						|
  ByteStream::quadbyte qb = 4;
 | 
						|
  msg << qb;
 | 
						|
  std::shared_ptr<rowgroup::RowGroup> rowGroup = 0;
 | 
						|
  bool anyRow = false;
 | 
						|
 | 
						|
  exemgrClient->write(msg);
 | 
						|
  ByteStream msgPlan;
 | 
						|
  csep.serialize(msgPlan);
 | 
						|
  exemgrClient->write(msgPlan);
 | 
						|
  msg.restart();
 | 
						|
  msg = exemgrClient->read();  // error handling
 | 
						|
  emsgBs = exemgrClient->read();
 | 
						|
  ByteStream::quadbyte qb1;
 | 
						|
 | 
						|
  if (emsgBs.length() == 0)
 | 
						|
  {
 | 
						|
    // exemgrClient->shutdown();
 | 
						|
    // delete exemgrClient;
 | 
						|
    // exemgrClient = 0;
 | 
						|
    throw runtime_error("Lost conection to ExeMgr.");
 | 
						|
  }
 | 
						|
 | 
						|
  string emsgStr;
 | 
						|
  emsgBs >> emsgStr;
 | 
						|
 | 
						|
  if (msg.length() == 4)
 | 
						|
  {
 | 
						|
    msg >> qb1;
 | 
						|
 | 
						|
    if (qb1 != 0)
 | 
						|
    {
 | 
						|
      // exemgrClient->shutdown();
 | 
						|
      // delete exemgrClient;
 | 
						|
      // exemgrClient = 0;
 | 
						|
      throw runtime_error(emsgStr);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  while (true)
 | 
						|
  {
 | 
						|
    msg.restart();
 | 
						|
    msg = exemgrClient->read();
 | 
						|
 | 
						|
    if (msg.length() == 0)
 | 
						|
    {
 | 
						|
      // exemgrClient->shutdown();
 | 
						|
      // delete exemgrClient;
 | 
						|
      // exemgrClient = 0;
 | 
						|
      throw runtime_error("Lost conection to ExeMgr.");
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      if (!rowGroup)
 | 
						|
      {
 | 
						|
        // This is mete data
 | 
						|
        rowGroup.reset(new rowgroup::RowGroup());
 | 
						|
        rowGroup->deserialize(msg);
 | 
						|
        qb = 100;
 | 
						|
        msg.restart();
 | 
						|
        msg << qb;
 | 
						|
        exemgrClient->write(msg);
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      rgData.deserialize(msg);
 | 
						|
      rowGroup->setData(&rgData);
 | 
						|
 | 
						|
      if (rowGroup->getStatus() != 0)
 | 
						|
      {
 | 
						|
        // msg.advance(rowGroup->getDataSize());
 | 
						|
        msg >> emsgStr;
 | 
						|
        // exemgrClient->shutdown();
 | 
						|
        // delete exemgrClient;
 | 
						|
        // exemgrClient = 0;
 | 
						|
        throw runtime_error(emsgStr);
 | 
						|
      }
 | 
						|
 | 
						|
      if (rowGroup->getRowCount() > 0)
 | 
						|
        anyRow = true;
 | 
						|
 | 
						|
      // exemgrClient->shutdown();
 | 
						|
      // delete exemgrClient;
 | 
						|
      // exemgrClient = 0;
 | 
						|
      return anyRow;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool anyNullInTheColumn(THD* thd, string& schema, string& table, string& columnName, int sessionID)
 | 
						|
{
 | 
						|
  CalpontSelectExecutionPlan csep;
 | 
						|
  CalpontSelectExecutionPlan::ReturnedColumnList returnedColumnList;
 | 
						|
  CalpontSelectExecutionPlan::FilterTokenList filterTokenList;
 | 
						|
  CalpontSelectExecutionPlan::ColumnMap colMap;
 | 
						|
  if (lower_case_table_names)
 | 
						|
  {
 | 
						|
    algorithm::to_lower(schema);
 | 
						|
    algorithm::to_lower(table);
 | 
						|
  }
 | 
						|
  algorithm::to_lower(columnName);
 | 
						|
 | 
						|
  SessionManager sm;
 | 
						|
  BRM::TxnID txnID;
 | 
						|
  txnID = sm.getTxnID(sessionID);
 | 
						|
 | 
						|
  if (!txnID.valid)
 | 
						|
  {
 | 
						|
    txnID.id = 0;
 | 
						|
    txnID.valid = true;
 | 
						|
  }
 | 
						|
 | 
						|
  QueryContext verID;
 | 
						|
  verID = sm.verID();
 | 
						|
  csep.txnID(txnID.id);
 | 
						|
  csep.verID(verID);
 | 
						|
  csep.sessionID(sessionID);
 | 
						|
 | 
						|
  string firstCol = schema + "." + table + "." + columnName;
 | 
						|
  SimpleColumn* col[1];
 | 
						|
  col[0] = new SimpleColumn(firstCol, sessionID);
 | 
						|
  SRCP srcp;
 | 
						|
  srcp.reset(col[0]);
 | 
						|
  colMap.insert(CMVT_(firstCol, srcp));
 | 
						|
  csep.columnMapNonStatic(colMap);
 | 
						|
  returnedColumnList.push_back(srcp);
 | 
						|
  csep.returnedCols(returnedColumnList);
 | 
						|
 | 
						|
  SimpleFilter* sf = new SimpleFilter();
 | 
						|
  const char* timeZone = thd->variables.time_zone->get_name()->ptr();
 | 
						|
  long timeZoneOffset;
 | 
						|
  dataconvert::timeZoneToOffset(timeZone, strlen(timeZone), &timeZoneOffset);
 | 
						|
  sf->timeZone(timeZoneOffset);
 | 
						|
  boost::shared_ptr<Operator> sop(new PredicateOperator("isnull"));
 | 
						|
  sf->op(sop);
 | 
						|
  ConstantColumn* rhs = new ConstantColumn("", ConstantColumn::NULLDATA);
 | 
						|
  rhs->timeZone(timeZoneOffset);
 | 
						|
  sf->lhs(col[0]->clone());
 | 
						|
  sf->rhs(rhs);
 | 
						|
 | 
						|
  filterTokenList.push_back(sf);
 | 
						|
  csep.filterTokenList(filterTokenList);
 | 
						|
 | 
						|
  CalpontSelectExecutionPlan::TableList tablelist;
 | 
						|
  tablelist.push_back(make_aliastable(schema, table, ""));
 | 
						|
  csep.tableList(tablelist);
 | 
						|
 | 
						|
  boost::shared_ptr<messageqcpp::MessageQueueClient> exemgrClient(
 | 
						|
      new messageqcpp::MessageQueueClient("ExeMgr1"));
 | 
						|
  ByteStream msg, emsgBs;
 | 
						|
  rowgroup::RGData rgData;
 | 
						|
  ByteStream::quadbyte qb = 4;
 | 
						|
  msg << qb;
 | 
						|
  rowgroup::RowGroup* rowGroup = 0;
 | 
						|
  bool anyRow = false;
 | 
						|
 | 
						|
  exemgrClient->write(msg);
 | 
						|
  ByteStream msgPlan;
 | 
						|
  csep.serialize(msgPlan);
 | 
						|
  exemgrClient->write(msgPlan);
 | 
						|
  msg.restart();
 | 
						|
  msg = exemgrClient->read();  // error handling
 | 
						|
  emsgBs = exemgrClient->read();
 | 
						|
  ByteStream::quadbyte qb1;
 | 
						|
 | 
						|
  if (emsgBs.length() == 0)
 | 
						|
  {
 | 
						|
    // exemgrClient->shutdown();
 | 
						|
    // delete exemgrClient;
 | 
						|
    // exemgrClient = 0;
 | 
						|
    throw runtime_error("Lost conection to ExeMgr.");
 | 
						|
  }
 | 
						|
 | 
						|
  string emsgStr;
 | 
						|
  emsgBs >> emsgStr;
 | 
						|
 | 
						|
  if (msg.length() == 4)
 | 
						|
  {
 | 
						|
    msg >> qb1;
 | 
						|
 | 
						|
    if (qb1 != 0)
 | 
						|
    {
 | 
						|
      // exemgrClient->shutdown();
 | 
						|
      // delete exemgrClient;
 | 
						|
      // exemgrClient = 0;
 | 
						|
      throw runtime_error(emsgStr);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  while (true)
 | 
						|
  {
 | 
						|
    msg.restart();
 | 
						|
    msg = exemgrClient->read();
 | 
						|
 | 
						|
    if (msg.length() == 0)
 | 
						|
    {
 | 
						|
      // exemgrClient->shutdown();
 | 
						|
      // delete exemgrClient;
 | 
						|
      // exemgrClient = 0;
 | 
						|
      throw runtime_error("Lost conection to ExeMgr.");
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      if (!rowGroup)
 | 
						|
      {
 | 
						|
        // This is mete data
 | 
						|
        rowGroup = new rowgroup::RowGroup();
 | 
						|
        rowGroup->deserialize(msg);
 | 
						|
        qb = 100;
 | 
						|
        msg.restart();
 | 
						|
        msg << qb;
 | 
						|
        exemgrClient->write(msg);
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      rgData.deserialize(msg);
 | 
						|
      rowGroup->setData(&rgData);
 | 
						|
 | 
						|
      if (rowGroup->getStatus() != 0)
 | 
						|
      {
 | 
						|
        // msg.advance(amount);
 | 
						|
        msg >> emsgStr;
 | 
						|
        // exemgrClient->shutdown();
 | 
						|
        // delete exemgrClient;
 | 
						|
        // exemgrClient = 0;
 | 
						|
        throw runtime_error(emsgStr);
 | 
						|
      }
 | 
						|
 | 
						|
      if (rowGroup->getRowCount() > 0)
 | 
						|
        anyRow = true;
 | 
						|
 | 
						|
      // exemgrClient->shutdown();
 | 
						|
      // delete exemgrClient;
 | 
						|
      // exemgrClient = 0;
 | 
						|
      return anyRow;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
int ProcessDDLStatement(string& ddlStatement, string& schema, const string& /*table*/, int sessionID,
 | 
						|
                        string& emsg, int compressionTypeIn = 2, bool isAnyAutoincreCol = false,
 | 
						|
                        int64_t nextvalue = 1, std::string autoiColName = "",
 | 
						|
                        const CHARSET_INFO* default_table_charset = NULL)
 | 
						|
{
 | 
						|
  SqlParser parser;
 | 
						|
  THD* thd = current_thd;
 | 
						|
#ifdef MCS_DEBUG
 | 
						|
  cout << "ProcessDDLStatement: " << schema << "." << table << ":" << ddlStatement << endl;
 | 
						|
#endif
 | 
						|
 | 
						|
  parser.setDefaultSchema(schema);
 | 
						|
  parser.setDefaultCharset(default_table_charset);
 | 
						|
  int rc = 0;
 | 
						|
  parser.Parse(ddlStatement.c_str(), thd->get_utf8_flag());
 | 
						|
 | 
						|
  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());
 | 
						|
 | 
						|
  if (parser.Good())
 | 
						|
  {
 | 
						|
    boost::shared_ptr<CalpontSystemCatalog> csc = CalpontSystemCatalog::makeCalpontSystemCatalog(sessionID);
 | 
						|
    csc->identity(execplan::CalpontSystemCatalog::FE);
 | 
						|
    const ddlpackage::ParseTree& ptree = parser.GetParseTree();
 | 
						|
 | 
						|
    if (UNLIKELY(ptree.fList.size() == 0))
 | 
						|
    {
 | 
						|
      // TODO: Once the crash bug is found, this should convert to "return 0"
 | 
						|
      cout << "***** ProcessDDLStatement has no stmt *****" << endl;
 | 
						|
      setError(thd, ER_CHECK_NOT_IMPLEMENTED, "DDL processed without statement");
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    SqlStatement& stmt = *ptree.fList[0];
 | 
						|
    bool isVarbinaryAllowed = false;
 | 
						|
    std::string valConfig = config::Config::makeConfig()->getConfig("WriteEngine", "AllowVarbinary");
 | 
						|
    algorithm::to_upper(valConfig);
 | 
						|
 | 
						|
    if (valConfig.compare("YES") == 0)
 | 
						|
      isVarbinaryAllowed = true;
 | 
						|
 | 
						|
    const char* timeZone = thd->variables.time_zone->get_name()->ptr();
 | 
						|
    long timeZoneOffset;
 | 
						|
    dataconvert::timeZoneToOffset(timeZone, strlen(timeZone), &timeZoneOffset);
 | 
						|
 | 
						|
    //@Bug 1771. error out for not supported feature.
 | 
						|
    if (typeid(stmt) == typeid(CreateTableStatement))
 | 
						|
    {
 | 
						|
      CreateTableStatement* createTable = dynamic_cast<CreateTableStatement*>(&stmt);
 | 
						|
      if (lower_case_table_names)
 | 
						|
      {
 | 
						|
        algorithm::to_lower(createTable->fTableDef->fQualifiedName->fSchema);
 | 
						|
        algorithm::to_lower(createTable->fTableDef->fQualifiedName->fName);
 | 
						|
      }
 | 
						|
 | 
						|
      bool matchedCol = false;
 | 
						|
      bool isFirstTimestamp = true;
 | 
						|
 | 
						|
      for (unsigned i = 0; i < createTable->fTableDef->fColumns.size(); i++)
 | 
						|
      {
 | 
						|
        // if there are any constraints other than 'DEFAULT NULL' (which is the default in IDB), kill
 | 
						|
        //  the statement
 | 
						|
        bool autoIncre = false;
 | 
						|
        uint64_t startValue = 1;
 | 
						|
 | 
						|
        if (createTable->fTableDef->fColumns[i]->fConstraints.size() > 0)
 | 
						|
        {
 | 
						|
          // support default value and NOT NULL constraint
 | 
						|
          for (uint32_t j = 0; j < createTable->fTableDef->fColumns[i]->fConstraints.size(); j++)
 | 
						|
          {
 | 
						|
            if (createTable->fTableDef->fColumns[i]->fConstraints[j]->fConstraintType != DDL_NOT_NULL)
 | 
						|
            {
 | 
						|
              rc = 1;
 | 
						|
              thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
 | 
						|
              thd->raise_error_printf(ER_CHECK_NOT_IMPLEMENTED,
 | 
						|
                                      (IDBErrorInfo::instance()->errorMsg(ERR_CONSTRAINTS)).c_str());
 | 
						|
              ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
              ci->isAlter = false;
 | 
						|
              return rc;
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        // check varbinary data type
 | 
						|
        if ((createTable->fTableDef->fColumns[i]->fType->fType == ddlpackage::DDL_VARBINARY) &&
 | 
						|
            !isVarbinaryAllowed)
 | 
						|
        {
 | 
						|
          rc = 1;
 | 
						|
          thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
 | 
						|
          thd->raise_error_printf(ER_CHECK_NOT_IMPLEMENTED,
 | 
						|
                                  "Varbinary is currently not supported by Columnstore.");
 | 
						|
          ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
          ci->isAlter = false;
 | 
						|
          return rc;
 | 
						|
        }
 | 
						|
 | 
						|
        if ((createTable->fTableDef->fColumns[i]->fType->fType == ddlpackage::DDL_VARBINARY) &&
 | 
						|
            ((createTable->fTableDef->fColumns[i]->fType->fLength > 8000) ||
 | 
						|
             (createTable->fTableDef->fColumns[i]->fType->fLength < 8)))
 | 
						|
        {
 | 
						|
          rc = 1;
 | 
						|
          thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
 | 
						|
          thd->raise_error_printf(ER_CHECK_NOT_IMPLEMENTED, "Varbinary length has to be between 8 and 8000.");
 | 
						|
          ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
          ci->isAlter = false;
 | 
						|
          return rc;
 | 
						|
        }
 | 
						|
 | 
						|
#if MYSQL_VERSION_ID < 110400
 | 
						|
        // For TIMESTAMP, if no constraint is given, default to NOT NULL
 | 
						|
        if (createTable->fTableDef->fColumns[i]->fType->fType == ddlpackage::DDL_TIMESTAMP &&
 | 
						|
            createTable->fTableDef->fColumns[i]->fConstraints.empty())
 | 
						|
        {
 | 
						|
          createTable->fTableDef->fColumns[i]->fConstraints.push_back(new ColumnConstraintDef(DDL_NOT_NULL));
 | 
						|
        }
 | 
						|
#endif
 | 
						|
 | 
						|
        if (createTable->fTableDef->fColumns[i]->fDefaultValue)
 | 
						|
        {
 | 
						|
          if ((!createTable->fTableDef->fColumns[i]->fDefaultValue->fNull) &&
 | 
						|
              (createTable->fTableDef->fColumns[i]->fType->fType == ddlpackage::DDL_VARBINARY))
 | 
						|
          {
 | 
						|
            rc = 1;
 | 
						|
            thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
 | 
						|
            thd->raise_error_printf(ER_CHECK_NOT_IMPLEMENTED, "Varbinary column cannot have default value.");
 | 
						|
            ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
            ci->isAlter = false;
 | 
						|
            return rc;
 | 
						|
          }
 | 
						|
 | 
						|
          if (!createTable->fTableDef->fColumns[i]->fDefaultValue->fNull)
 | 
						|
          {
 | 
						|
            // validate the default value, if out of range, just error out
 | 
						|
            CalpontSystemCatalog::ColDataType dataType;
 | 
						|
            dataType = convertDataType(createTable->fTableDef->fColumns[i]->fType->fType);
 | 
						|
            CalpontSystemCatalog::ColType colType;
 | 
						|
            colType.colDataType = dataType;
 | 
						|
            colType.colWidth = createTable->fTableDef->fColumns[i]->fType->fLength;
 | 
						|
            colType.precision = createTable->fTableDef->fColumns[i]->fType->fPrecision;
 | 
						|
            colType.scale = createTable->fTableDef->fColumns[i]->fType->fScale;
 | 
						|
            boost::any convertedVal;
 | 
						|
            bool pushWarning = false;
 | 
						|
 | 
						|
            try
 | 
						|
            {
 | 
						|
              convertedVal =
 | 
						|
                  colType.convertColumnData(createTable->fTableDef->fColumns[i]->fDefaultValue->fValue,
 | 
						|
                                            pushWarning, timeZoneOffset, false, false, false);
 | 
						|
            }
 | 
						|
            catch (std::exception&)
 | 
						|
            {
 | 
						|
              rc = 1;
 | 
						|
              thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
              thd->raise_error_printf(ER_INTERNAL_ERROR,
 | 
						|
                                      "The default value is out of range for the specified data type.");
 | 
						|
              ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
              ci->isAlter = false;
 | 
						|
              return rc;
 | 
						|
            }
 | 
						|
 | 
						|
            if (pushWarning)
 | 
						|
            {
 | 
						|
              rc = 1;
 | 
						|
              thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
              thd->raise_error_printf(ER_INTERNAL_ERROR,
 | 
						|
                                      "The default value is out of range for the specified data type.");
 | 
						|
              ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
              ci->isAlter = false;
 | 
						|
              return rc;
 | 
						|
            }
 | 
						|
            if (createTable->fTableDef->fColumns[i]->fType->fType == ddlpackage::DDL_TIMESTAMP)
 | 
						|
            {
 | 
						|
              if (createTable->fTableDef->fColumns[i]->fDefaultValue->fValue == "0")
 | 
						|
              {
 | 
						|
                createTable->fTableDef->fColumns[i]->fDefaultValue->fValue = "0000-00-00 00:00:00";
 | 
						|
              }
 | 
						|
              if (isFirstTimestamp)
 | 
						|
              {
 | 
						|
                isFirstTimestamp = false;
 | 
						|
              }
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
        // If no default value exists for TIMESTAMP, we apply
 | 
						|
        // automatic TIMESTAMP properties.
 | 
						|
        // TODO: If no default value exists but the constraint is NULL,
 | 
						|
        // default value should be set to NULL. But this is currently
 | 
						|
        // not supported since columnstore does not track whether user
 | 
						|
        // specified a NULL or not
 | 
						|
        else if (createTable->fTableDef->fColumns[i]->fType->fType == ddlpackage::DDL_TIMESTAMP)
 | 
						|
        {
 | 
						|
          if (isFirstTimestamp)
 | 
						|
          {
 | 
						|
            isFirstTimestamp = false;
 | 
						|
            createTable->fTableDef->fColumns[i]->fDefaultValue =
 | 
						|
                new ColumnDefaultValue("current_timestamp() ON UPDATE current_timestamp()");
 | 
						|
          }
 | 
						|
          else
 | 
						|
          {
 | 
						|
            createTable->fTableDef->fColumns[i]->fDefaultValue =
 | 
						|
                new ColumnDefaultValue("0000-00-00 00:00:00");
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        // Parse the column comment
 | 
						|
        string comment = createTable->fTableDef->fColumns[i]->fComment;
 | 
						|
        int compressionType = compressionTypeIn;
 | 
						|
 | 
						|
        if (comment.length() > 0)
 | 
						|
        {
 | 
						|
          compressionType = parseCompressionComment(comment);
 | 
						|
 | 
						|
          if (compressionType == MAX_INT)
 | 
						|
          {
 | 
						|
            compressionType = compressionTypeIn;
 | 
						|
          }
 | 
						|
          else if (compressionType < 0)
 | 
						|
          {
 | 
						|
            rc = 1;
 | 
						|
            thd->raise_error_printf(
 | 
						|
                ER_INTERNAL_ERROR,
 | 
						|
                (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_COMPRESSION_TYPE)).c_str());
 | 
						|
            ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
            ci->isAlter = false;
 | 
						|
            return rc;
 | 
						|
          }
 | 
						|
 | 
						|
          if (compressionType == 1)
 | 
						|
            compressionType = 2;
 | 
						|
 | 
						|
          if ((compressionType > 0) && !(compress::CompressInterface::isCompressionAvail(compressionType)))
 | 
						|
          {
 | 
						|
            rc = 1;
 | 
						|
            ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
            ci->isAlter = false;
 | 
						|
#ifdef SKIP_IDB_COMPRESSION
 | 
						|
            Message::Args args;
 | 
						|
            thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
            args.add("The compression type");
 | 
						|
            thd->raise_error_printf(ER_INTERNAL_ERROR,
 | 
						|
                                    (IDBErrorInfo::instance()->errorMsg(ERR_ENTERPRISE_ONLY, args)).c_str());
 | 
						|
#else
 | 
						|
            thd->raise_error_printf(
 | 
						|
                ER_INTERNAL_ERROR,
 | 
						|
                (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_COMPRESSION_TYPE)).c_str());
 | 
						|
#endif
 | 
						|
            return rc;
 | 
						|
          }
 | 
						|
 | 
						|
          try
 | 
						|
          {
 | 
						|
            autoIncre = parseAutoincrementColumnComment(comment, startValue);
 | 
						|
 | 
						|
            if (autoIncre)
 | 
						|
            {
 | 
						|
              // Check whether there is a column with autoincrement already
 | 
						|
              bool isAutoIncrementColumn =
 | 
						|
                  default_table_charset ? datatypes::CollationAwareComparator(default_table_charset)(
 | 
						|
                                              autoiColName, createTable->fTableDef->fColumns[i]->fName)
 | 
						|
                                        : datatypes::ASCIIStringCaseInsensetiveEquals(
 | 
						|
                                              autoiColName, createTable->fTableDef->fColumns[i]->fName);
 | 
						|
 | 
						|
              if (isAnyAutoincreCol && !isAutoIncrementColumn)
 | 
						|
              {
 | 
						|
                rc = 1;
 | 
						|
                thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                thd->raise_error_printf(
 | 
						|
                    ER_INTERNAL_ERROR,
 | 
						|
                    (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_NUMBER_AUTOINCREMENT)).c_str());
 | 
						|
                ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                ci->isAlter = false;
 | 
						|
                return rc;
 | 
						|
              }
 | 
						|
              else
 | 
						|
              {
 | 
						|
                isAnyAutoincreCol = true;
 | 
						|
                autoiColName = createTable->fTableDef->fColumns[i]->fName;
 | 
						|
                matchedCol = true;
 | 
						|
              }
 | 
						|
 | 
						|
              // Check whether the column has default value. If there is, error out
 | 
						|
              if (createTable->fTableDef->fColumns[i]->fDefaultValue)
 | 
						|
              {
 | 
						|
                if (!createTable->fTableDef->fColumns[i]->fDefaultValue->fNull)
 | 
						|
                {
 | 
						|
                  rc = 1;
 | 
						|
                  thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                  thd->raise_error_printf(ER_INTERNAL_ERROR,
 | 
						|
                                          "Autoincrement column cannot have a default value.");
 | 
						|
                  ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                  ci->isAlter = false;
 | 
						|
                  return rc;
 | 
						|
                }
 | 
						|
              }
 | 
						|
            }
 | 
						|
          }
 | 
						|
          catch (runtime_error& ex)
 | 
						|
          {
 | 
						|
            rc = 1;
 | 
						|
            thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
            thd->raise_error_printf(ER_INTERNAL_ERROR, ex.what());
 | 
						|
            ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
            ci->isAlter = false;
 | 
						|
            return rc;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        bool isAutoIncrementColumn = default_table_charset
 | 
						|
                                         ? datatypes::CollationAwareComparator(default_table_charset)(
 | 
						|
                                               autoiColName, createTable->fTableDef->fColumns[i]->fName)
 | 
						|
                                         : datatypes::ASCIIStringCaseInsensetiveEquals(
 | 
						|
                                               autoiColName, createTable->fTableDef->fColumns[i]->fName);
 | 
						|
 | 
						|
        if (!autoIncre && isAnyAutoincreCol && isAutoIncrementColumn)
 | 
						|
        {
 | 
						|
          autoIncre = true;
 | 
						|
          matchedCol = true;
 | 
						|
          startValue = nextvalue;
 | 
						|
        }
 | 
						|
 | 
						|
        if (startValue <= 0)
 | 
						|
        {
 | 
						|
          rc = 1;
 | 
						|
          thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
          thd->raise_error_printf(ER_INTERNAL_ERROR,
 | 
						|
                                  (IDBErrorInfo::instance()->errorMsg(ERR_NEGATIVE_STARTVALUE)).c_str());
 | 
						|
          ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
          ci->isAlter = false;
 | 
						|
          return rc;
 | 
						|
        }
 | 
						|
 | 
						|
        if (autoIncre)
 | 
						|
        {
 | 
						|
          if (!validateAutoincrementDatatype(createTable->fTableDef->fColumns[i]->fType->fType))
 | 
						|
          {
 | 
						|
            rc = 1;
 | 
						|
            thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
            thd->raise_error_printf(
 | 
						|
                ER_CHECK_NOT_IMPLEMENTED,
 | 
						|
                (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_AUTOINCREMENT_TYPE)).c_str());
 | 
						|
            ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
            ci->isAlter = false;
 | 
						|
            return rc;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        if (!validateNextValue(createTable->fTableDef->fColumns[i]->fType->fType, startValue))
 | 
						|
        {
 | 
						|
          rc = 1;
 | 
						|
          thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
          thd->raise_error_printf(ER_INTERNAL_ERROR,
 | 
						|
                                  (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_STARTVALUE)).c_str());
 | 
						|
          ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
          ci->isAlter = false;
 | 
						|
          return rc;
 | 
						|
        }
 | 
						|
 | 
						|
        // hdfs
 | 
						|
        if ((compressionType == 0) && (useHdfs))
 | 
						|
        {
 | 
						|
          compressionType = 2;
 | 
						|
          string errmsg("The table is created with Columnstore compression type 2 under HDFS.");
 | 
						|
          push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 9999, errmsg.c_str());
 | 
						|
        }
 | 
						|
 | 
						|
        (createTable->fTableDef->fColumns[i]->fType)->fCompressiontype = compressionType;
 | 
						|
 | 
						|
        if (autoIncre)
 | 
						|
          (createTable->fTableDef->fColumns[i]->fType)->fAutoincrement = "y";
 | 
						|
        else
 | 
						|
          (createTable->fTableDef->fColumns[i]->fType)->fAutoincrement = "n";
 | 
						|
 | 
						|
        (createTable->fTableDef->fColumns[i]->fType)->fNextvalue = startValue;
 | 
						|
      }
 | 
						|
 | 
						|
      if (isAnyAutoincreCol && !matchedCol)  //@Bug 3555 error out on invalid column
 | 
						|
      {
 | 
						|
        rc = 1;
 | 
						|
        Message::Args args;
 | 
						|
        thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
        args.add(autoiColName);
 | 
						|
        thd->raise_error_printf(ER_INTERNAL_ERROR,
 | 
						|
                                (IDBErrorInfo::instance()->errorMsg(ERR_UNKNOWN_COL, args)).c_str());
 | 
						|
        ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
        ci->isAlter = false;
 | 
						|
        return rc;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else if (typeid(stmt) == typeid(AlterTableStatement))
 | 
						|
    {
 | 
						|
      AlterTableStatement* alterTable = dynamic_cast<AlterTableStatement*>(&stmt);
 | 
						|
      if (lower_case_table_names)
 | 
						|
      {
 | 
						|
        algorithm::to_lower(alterTable->fTableName->fSchema);
 | 
						|
        algorithm::to_lower(alterTable->fTableName->fName);
 | 
						|
      }
 | 
						|
 | 
						|
      alterTable->setTimeZone(timeZoneOffset);
 | 
						|
 | 
						|
      if (schema.length() == 0)
 | 
						|
      {
 | 
						|
        schema = alterTable->fTableName->fSchema;
 | 
						|
 | 
						|
        if (schema.length() == 0)
 | 
						|
        {
 | 
						|
          rc = 1;
 | 
						|
          thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
 | 
						|
          thd->raise_error_printf(ER_INTERNAL_ERROR, "No database selected.");
 | 
						|
          ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
          ci->isAlter = false;
 | 
						|
          return rc;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      ddlpackage::AlterTableActionList actionList = alterTable->fActions;
 | 
						|
 | 
						|
      if (actionList.size() > 1)  //@bug 3753 we don't support multiple actions in alter table statement
 | 
						|
      {
 | 
						|
        rc = 1;
 | 
						|
        thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
 | 
						|
        thd->raise_error_printf(
 | 
						|
            ER_CHECK_NOT_IMPLEMENTED,
 | 
						|
            "Multiple actions in alter table statement is currently not supported by Columnstore.");
 | 
						|
 | 
						|
        ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
        ci->isAlter = false;
 | 
						|
        return rc;
 | 
						|
      }
 | 
						|
 | 
						|
      for (unsigned i = 0; i < actionList.size(); i++)
 | 
						|
      {
 | 
						|
        if (ddlpackage::AtaAddColumn* addColumnPtr = dynamic_cast<AtaAddColumn*>(actionList[i]))
 | 
						|
        {
 | 
						|
          // check varbinary data type
 | 
						|
          if ((addColumnPtr->fColumnDef->fType->fType == ddlpackage::DDL_VARBINARY) && !isVarbinaryAllowed)
 | 
						|
          {
 | 
						|
            rc = 1;
 | 
						|
            thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
            thd->raise_error_printf(ER_CHECK_NOT_IMPLEMENTED,
 | 
						|
                                    "Varbinary is currently not supported by Columnstore.");
 | 
						|
            ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
            ci->isAlter = false;
 | 
						|
            return rc;
 | 
						|
          }
 | 
						|
 | 
						|
          if ((addColumnPtr->fColumnDef->fType->fType == ddlpackage::DDL_VARBINARY) &&
 | 
						|
              ((addColumnPtr->fColumnDef->fType->fLength > 8000) ||
 | 
						|
               (addColumnPtr->fColumnDef->fType->fLength < 8)))
 | 
						|
          {
 | 
						|
            rc = 1;
 | 
						|
            thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
            thd->raise_error_printf(ER_INTERNAL_ERROR, "Varbinary length has to be between 8 and 8000.");
 | 
						|
            ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
            ci->isAlter = false;
 | 
						|
            return rc;
 | 
						|
          }
 | 
						|
 | 
						|
          uint64_t startValue = 1;
 | 
						|
          bool autoIncre = false;
 | 
						|
 | 
						|
          if ((addColumnPtr->fColumnDef->fConstraints.size() > 0) || addColumnPtr->fColumnDef->fDefaultValue)
 | 
						|
          {
 | 
						|
            // support default value and NOT NULL constraint
 | 
						|
            for (uint32_t j = 0; j < addColumnPtr->fColumnDef->fConstraints.size(); j++)
 | 
						|
            {
 | 
						|
              if (addColumnPtr->fColumnDef->fConstraints[j]->fConstraintType != DDL_NOT_NULL)
 | 
						|
              {
 | 
						|
                rc = 1;
 | 
						|
                thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                thd->raise_error_printf(ER_CHECK_NOT_IMPLEMENTED,
 | 
						|
                                        (IDBErrorInfo::instance()->errorMsg(ERR_CONSTRAINTS)).c_str());
 | 
						|
                ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                ci->isAlter = false;
 | 
						|
                return rc;
 | 
						|
              }
 | 
						|
 | 
						|
              // if not null constraint, user has to provide a default value
 | 
						|
              if ((addColumnPtr->fColumnDef->fConstraints[j]->fConstraintType == DDL_NOT_NULL) &&
 | 
						|
                  (!addColumnPtr->fColumnDef->fDefaultValue) &&
 | 
						|
                  (addColumnPtr->fColumnDef->fType->fType != ddlpackage::DDL_TIMESTAMP))
 | 
						|
              {
 | 
						|
                // do select count(*) from the table to check whether there are existing rows. if there is,
 | 
						|
                // error out.
 | 
						|
                bool anyRow = false;
 | 
						|
 | 
						|
                try
 | 
						|
                {
 | 
						|
                  anyRow = anyRowInTable(alterTable->fTableName->fSchema, alterTable->fTableName->fName,
 | 
						|
                                         sessionID);
 | 
						|
                }
 | 
						|
                catch (runtime_error& ex)
 | 
						|
                {
 | 
						|
                  rc = 1;
 | 
						|
                  thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                  thd->raise_error_printf(ER_INTERNAL_ERROR, ex.what());
 | 
						|
                  ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                  ci->isAlter = false;
 | 
						|
                  return rc;
 | 
						|
                }
 | 
						|
                catch (...)
 | 
						|
                {
 | 
						|
                  rc = 1;
 | 
						|
                  thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                  thd->raise_error_printf(ER_INTERNAL_ERROR,
 | 
						|
                                          "Unknown exception caught when checking any rows in the table.");
 | 
						|
                  ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                  ci->isAlter = false;
 | 
						|
                  return rc;
 | 
						|
                }
 | 
						|
 | 
						|
                if (anyRow)
 | 
						|
                {
 | 
						|
                  rc = 1;
 | 
						|
                  thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                  thd->raise_error_printf(
 | 
						|
                      ER_INTERNAL_ERROR,
 | 
						|
                      "Table is not empty. New column has to have a default value if NOT NULL required.");
 | 
						|
                  ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                  ci->isAlter = false;
 | 
						|
                  return rc;
 | 
						|
                }
 | 
						|
              }
 | 
						|
              else if ((addColumnPtr->fColumnDef->fConstraints[j]->fConstraintType == DDL_NOT_NULL) &&
 | 
						|
                       (addColumnPtr->fColumnDef->fDefaultValue))
 | 
						|
              {
 | 
						|
                if (addColumnPtr->fColumnDef->fDefaultValue->fValue.length() ==
 | 
						|
                    0)  // empty string is NULL in infinidb
 | 
						|
                {
 | 
						|
                  rc = 1;
 | 
						|
                  thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                  thd->raise_error_printf(ER_INTERNAL_ERROR,
 | 
						|
                                          "New column has to have a default value if NOT NULL required.");
 | 
						|
                  ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                  ci->isAlter = false;
 | 
						|
                  return rc;
 | 
						|
                }
 | 
						|
              }
 | 
						|
            }
 | 
						|
 | 
						|
            if (addColumnPtr->fColumnDef->fDefaultValue)
 | 
						|
            {
 | 
						|
              if ((!addColumnPtr->fColumnDef->fDefaultValue->fNull) &&
 | 
						|
                  (addColumnPtr->fColumnDef->fType->fType == ddlpackage::DDL_VARBINARY))
 | 
						|
              {
 | 
						|
                rc = 1;
 | 
						|
                thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                thd->raise_error_printf(ER_INTERNAL_ERROR, "Varbinary column cannot have default value.");
 | 
						|
                ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                ci->isAlter = false;
 | 
						|
                return rc;
 | 
						|
              }
 | 
						|
 | 
						|
              // validate the default value, if out of range, just error out
 | 
						|
              CalpontSystemCatalog::ColDataType dataType;
 | 
						|
              dataType = convertDataType(addColumnPtr->fColumnDef->fType->fType);
 | 
						|
              CalpontSystemCatalog::ColType colType;
 | 
						|
              colType.colDataType = dataType;
 | 
						|
              colType.colWidth = addColumnPtr->fColumnDef->fType->fLength;
 | 
						|
              colType.precision = addColumnPtr->fColumnDef->fType->fPrecision;
 | 
						|
              colType.scale = addColumnPtr->fColumnDef->fType->fScale;
 | 
						|
              boost::any convertedVal;
 | 
						|
              bool pushWarning = false;
 | 
						|
 | 
						|
              try
 | 
						|
              {
 | 
						|
                convertedVal = colType.convertColumnData(addColumnPtr->fColumnDef->fDefaultValue->fValue,
 | 
						|
                                                         pushWarning, timeZoneOffset, false, false, false);
 | 
						|
              }
 | 
						|
              catch (std::exception&)
 | 
						|
              {
 | 
						|
                rc = 1;
 | 
						|
                thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                thd->raise_error_printf(ER_INTERNAL_ERROR,
 | 
						|
                                        "The default value is out of range for the specified data type.");
 | 
						|
                ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                ci->isAlter = false;
 | 
						|
                return rc;
 | 
						|
              }
 | 
						|
 | 
						|
              if (pushWarning)
 | 
						|
              {
 | 
						|
                rc = 1;
 | 
						|
                thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                thd->raise_error_printf(ER_INTERNAL_ERROR,
 | 
						|
                                        "The default value is out of range for the specified data type.");
 | 
						|
                ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                ci->isAlter = false;
 | 
						|
                return rc;
 | 
						|
              }
 | 
						|
              if (addColumnPtr->fColumnDef->fType->fType == ddlpackage::DDL_TIMESTAMP &&
 | 
						|
                  addColumnPtr->fColumnDef->fDefaultValue->fValue == "0")
 | 
						|
              {
 | 
						|
                addColumnPtr->fColumnDef->fDefaultValue->fValue = "0000-00-00 00:00:00";
 | 
						|
              }
 | 
						|
            }
 | 
						|
          }
 | 
						|
 | 
						|
          // For TIMESTAMP, if no constraint is given, default to NOT NULL
 | 
						|
          if (addColumnPtr->fColumnDef->fType->fType == ddlpackage::DDL_TIMESTAMP &&
 | 
						|
              addColumnPtr->fColumnDef->fConstraints.empty())
 | 
						|
          {
 | 
						|
            addColumnPtr->fColumnDef->fConstraints.push_back(new ColumnConstraintDef(DDL_NOT_NULL));
 | 
						|
          }
 | 
						|
 | 
						|
          // If no default value exists for TIMESTAMP, we apply
 | 
						|
          // automatic TIMESTAMP properties.
 | 
						|
          // TODO: If no default value exists but the constraint is NULL,
 | 
						|
          // default value should be set to NULL. But this is currently
 | 
						|
          // not supported since columnstore does not track whether user
 | 
						|
          // specified a NULL or not
 | 
						|
          if (addColumnPtr->fColumnDef->fType->fType == ddlpackage::DDL_TIMESTAMP &&
 | 
						|
              !addColumnPtr->fColumnDef->fDefaultValue)
 | 
						|
          {
 | 
						|
            // Query calpontsys.syscolumn to see
 | 
						|
            // if a timestamp column already exists in this table
 | 
						|
            if (!anyTimestampColumn(alterTable->fTableName->fSchema, alterTable->fTableName->fName,
 | 
						|
                                    sessionID))
 | 
						|
            {
 | 
						|
              addColumnPtr->fColumnDef->fDefaultValue =
 | 
						|
                  new ColumnDefaultValue("current_timestamp() ON UPDATE current_timestamp()");
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
              addColumnPtr->fColumnDef->fDefaultValue = new ColumnDefaultValue("0000-00-00 00:00:00");
 | 
						|
            }
 | 
						|
          }
 | 
						|
 | 
						|
          // Handle compression type
 | 
						|
          string comment = addColumnPtr->fColumnDef->fComment;
 | 
						|
          int compressionType = compressionTypeIn;
 | 
						|
 | 
						|
          if (comment.length() > 0)
 | 
						|
          {
 | 
						|
            //@Bug 3782 This is for synchronization after calonlinealter to use
 | 
						|
            boost::algorithm::to_upper(comment);
 | 
						|
            std::regex pat("[[:space:]]*SCHEMA[[:space:]]+SYNC[[:space:]]+ONLY",
 | 
						|
                           std::regex_constants::extended);
 | 
						|
 | 
						|
            if (std::regex_search(comment, pat))
 | 
						|
            {
 | 
						|
              return 0;
 | 
						|
            }
 | 
						|
 | 
						|
            compressionType = parseCompressionComment(comment);
 | 
						|
 | 
						|
            if (compressionType == MAX_INT)
 | 
						|
            {
 | 
						|
              compressionType = compressionTypeIn;
 | 
						|
            }
 | 
						|
            else if (compressionType < 0)
 | 
						|
            {
 | 
						|
              rc = 1;
 | 
						|
              thd->raise_error_printf(
 | 
						|
                  ER_INTERNAL_ERROR,
 | 
						|
                  (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_COMPRESSION_TYPE)).c_str());
 | 
						|
              ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
              ci->isAlter = false;
 | 
						|
              return rc;
 | 
						|
            }
 | 
						|
 | 
						|
            if ((compressionType > 0) && !(compress::CompressInterface::isCompressionAvail(compressionType)))
 | 
						|
            {
 | 
						|
              rc = 1;
 | 
						|
              thd->raise_error_printf(
 | 
						|
                  ER_INTERNAL_ERROR,
 | 
						|
                  (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_COMPRESSION_TYPE)).c_str());
 | 
						|
              ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
              ci->isAlter = false;
 | 
						|
              return rc;
 | 
						|
            }
 | 
						|
 | 
						|
            if ((compressionType == 0) && (useHdfs))
 | 
						|
            {
 | 
						|
              compressionType = 2;
 | 
						|
              string errmsg("The column is created with Columnstore compression type 2 under HDFS.");
 | 
						|
              push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 9999, errmsg.c_str());
 | 
						|
            }
 | 
						|
 | 
						|
            try
 | 
						|
            {
 | 
						|
              autoIncre = parseAutoincrementColumnComment(comment, startValue);
 | 
						|
            }
 | 
						|
            catch (runtime_error& ex)
 | 
						|
            {
 | 
						|
              rc = 1;
 | 
						|
              thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
              thd->raise_error_printf(ER_INTERNAL_ERROR, ex.what());
 | 
						|
              ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
              ci->isAlter = false;
 | 
						|
              return rc;
 | 
						|
            }
 | 
						|
 | 
						|
            if (autoIncre)
 | 
						|
            {
 | 
						|
              // Check if the table already has autoincrement column
 | 
						|
              boost::shared_ptr<CalpontSystemCatalog> csc =
 | 
						|
                  CalpontSystemCatalog::makeCalpontSystemCatalog(sessionID);
 | 
						|
              csc->identity(execplan::CalpontSystemCatalog::FE);
 | 
						|
              CalpontSystemCatalog::TableName tableName;
 | 
						|
              tableName.schema = alterTable->fTableName->fSchema;
 | 
						|
              tableName.table = alterTable->fTableName->fName;
 | 
						|
              CalpontSystemCatalog::TableInfo tblInfo;
 | 
						|
 | 
						|
              try
 | 
						|
              {
 | 
						|
                tblInfo = csc->tableInfo(tableName);
 | 
						|
              }
 | 
						|
              catch (runtime_error& ex)
 | 
						|
              {
 | 
						|
                rc = 1;
 | 
						|
                thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                thd->raise_error_printf(ER_INTERNAL_ERROR, ex.what());
 | 
						|
                ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                ci->isAlter = false;
 | 
						|
                return rc;
 | 
						|
              }
 | 
						|
 | 
						|
              if (tblInfo.tablewithautoincr == 1)
 | 
						|
              {
 | 
						|
                rc = 1;
 | 
						|
                thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                thd->raise_error_printf(
 | 
						|
                    ER_INTERNAL_ERROR,
 | 
						|
                    (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_NUMBER_AUTOINCREMENT)).c_str());
 | 
						|
                ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                ci->isAlter = false;
 | 
						|
                return rc;
 | 
						|
              }
 | 
						|
 | 
						|
              if (!validateAutoincrementDatatype(addColumnPtr->fColumnDef->fType->fType))
 | 
						|
              {
 | 
						|
                rc = 1;
 | 
						|
                thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                thd->raise_error_printf(
 | 
						|
                    ER_INTERNAL_ERROR,
 | 
						|
                    (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_AUTOINCREMENT_TYPE)).c_str());
 | 
						|
                ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                ci->isAlter = false;
 | 
						|
                return rc;
 | 
						|
              }
 | 
						|
 | 
						|
              if (!validateNextValue(addColumnPtr->fColumnDef->fType->fType, startValue))
 | 
						|
              {
 | 
						|
                rc = 1;
 | 
						|
                thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                thd->raise_error_printf(ER_INTERNAL_ERROR,
 | 
						|
                                        (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_STARTVALUE)).c_str());
 | 
						|
                ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                ci->isAlter = false;
 | 
						|
                return rc;
 | 
						|
              }
 | 
						|
 | 
						|
              if (startValue <= 0)
 | 
						|
              {
 | 
						|
                rc = 1;
 | 
						|
                thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                thd->raise_error_printf(
 | 
						|
                    ER_CHECK_NOT_IMPLEMENTED,
 | 
						|
                    (IDBErrorInfo::instance()->errorMsg(ERR_NEGATIVE_STARTVALUE)).c_str());
 | 
						|
                ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                ci->isAlter = false;
 | 
						|
                return rc;
 | 
						|
              }
 | 
						|
            }
 | 
						|
          }
 | 
						|
 | 
						|
          addColumnPtr->fColumnDef->fType->fCompressiontype = compressionType;
 | 
						|
 | 
						|
          if (autoIncre)
 | 
						|
            addColumnPtr->fColumnDef->fType->fAutoincrement = "y";
 | 
						|
          else
 | 
						|
            addColumnPtr->fColumnDef->fType->fAutoincrement = "n";
 | 
						|
 | 
						|
          addColumnPtr->fColumnDef->fType->fNextvalue = startValue;
 | 
						|
        }
 | 
						|
        else if (dynamic_cast<AtaAddTableConstraint*>(actionList[i]))
 | 
						|
        {
 | 
						|
          rc = 1;
 | 
						|
          thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
 | 
						|
          thd->raise_error_printf(ER_CHECK_NOT_IMPLEMENTED,
 | 
						|
                                  (IDBErrorInfo::instance()->errorMsg(ERR_CONSTRAINTS)).c_str());
 | 
						|
          ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
          ci->isAlter = false;
 | 
						|
          return rc;
 | 
						|
        }
 | 
						|
        /*			else if ( dynamic_cast<AtaSetColumnDefault*> (actionList[i]) )
 | 
						|
                                {
 | 
						|
                                        rc = 1;
 | 
						|
                                        thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                                        thd->raise_error_printf(ER_CHECK_NOT_IMPLEMENTED,
 | 
						|
           (IDBErrorInfo::instance()->errorMsg(ERR_CONSTRAINTS)).c_str()); ci->alterTableState =
 | 
						|
           cal_connection_info::NOT_ALTER; ci->isAlter = false; return rc;
 | 
						|
                                }
 | 
						|
                                else if ( dynamic_cast<AtaDropColumnDefault*> (actionList[i]) )
 | 
						|
                                {
 | 
						|
                                        rc = 1;
 | 
						|
                                        thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                                        thd->raise_error_printf(ER_CHECK_NOT_IMPLEMENTED,
 | 
						|
           (IDBErrorInfo::instance()->errorMsg(ERR_CONSTRAINTS)).c_str()); ci->alterTableState =
 | 
						|
           cal_connection_info::NOT_ALTER; ci->isAlter = false; return rc;
 | 
						|
                                }
 | 
						|
        */
 | 
						|
        else if (ddlpackage::AtaAddColumns* addColumnsPtr = dynamic_cast<AtaAddColumns*>(actionList[i]))
 | 
						|
        {
 | 
						|
          if ((addColumnsPtr->fColumns).size() > 1)
 | 
						|
          {
 | 
						|
            rc = 1;
 | 
						|
            thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
            thd->raise_error_printf(
 | 
						|
                ER_CHECK_NOT_IMPLEMENTED,
 | 
						|
                "Multiple actions in alter table statement is currently not supported by Columnstore.");
 | 
						|
            ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
            ci->isAlter = false;
 | 
						|
            return rc;
 | 
						|
          }
 | 
						|
 | 
						|
          // check varbinary data type
 | 
						|
          if ((addColumnsPtr->fColumns[0]->fType->fType == ddlpackage::DDL_VARBINARY) && !isVarbinaryAllowed)
 | 
						|
          {
 | 
						|
            rc = 1;
 | 
						|
            thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
            thd->raise_error_printf(ER_CHECK_NOT_IMPLEMENTED,
 | 
						|
                                    "Varbinary is currently not supported by Columnstore.");
 | 
						|
            ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
            ci->isAlter = false;
 | 
						|
            return rc;
 | 
						|
          }
 | 
						|
 | 
						|
          if ((addColumnsPtr->fColumns[0]->fType->fType == ddlpackage::DDL_VARBINARY) &&
 | 
						|
              ((addColumnsPtr->fColumns[0]->fType->fLength > 8000) ||
 | 
						|
               (addColumnsPtr->fColumns[0]->fType->fLength < 8)))
 | 
						|
          {
 | 
						|
            rc = 1;
 | 
						|
            thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
            thd->raise_error_printf(ER_INTERNAL_ERROR, "Varbinary length has to be between 8 and 8000.");
 | 
						|
            ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
            ci->isAlter = false;
 | 
						|
            return rc;
 | 
						|
          }
 | 
						|
 | 
						|
          uint64_t startValue = 1;
 | 
						|
          bool autoIncre = false;
 | 
						|
 | 
						|
          if ((addColumnsPtr->fColumns[0]->fConstraints.size() > 0) ||
 | 
						|
              addColumnsPtr->fColumns[0]->fDefaultValue)
 | 
						|
          {
 | 
						|
            //@Bug 5274. support default value and NOT NULL constraint
 | 
						|
            for (uint32_t j = 0; j < addColumnsPtr->fColumns[0]->fConstraints.size(); j++)
 | 
						|
            {
 | 
						|
              if (addColumnsPtr->fColumns[0]->fConstraints[j]->fConstraintType != DDL_NOT_NULL)
 | 
						|
              {
 | 
						|
                rc = 1;
 | 
						|
                thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                thd->raise_error_printf(ER_CHECK_NOT_IMPLEMENTED,
 | 
						|
                                        (IDBErrorInfo::instance()->errorMsg(ERR_CONSTRAINTS)).c_str());
 | 
						|
                ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                ci->isAlter = false;
 | 
						|
                return rc;
 | 
						|
              }
 | 
						|
 | 
						|
              // if not null constraint, user has to provide a default value
 | 
						|
              if ((addColumnsPtr->fColumns[0]->fConstraints[j]->fConstraintType == DDL_NOT_NULL) &&
 | 
						|
                  (!addColumnsPtr->fColumns[0]->fDefaultValue) &&
 | 
						|
                  (addColumnsPtr->fColumns[0]->fType->fType != ddlpackage::DDL_TIMESTAMP))
 | 
						|
              {
 | 
						|
                // do select count(*) from the table to check whether there are existing rows. if there is,
 | 
						|
                // error out.
 | 
						|
                bool anyRow = false;
 | 
						|
 | 
						|
                try
 | 
						|
                {
 | 
						|
                  anyRow = anyRowInTable(alterTable->fTableName->fSchema, alterTable->fTableName->fName,
 | 
						|
                                         sessionID);
 | 
						|
                }
 | 
						|
                catch (runtime_error& ex)
 | 
						|
                {
 | 
						|
                  rc = 1;
 | 
						|
                  thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                  thd->raise_error_printf(ER_INTERNAL_ERROR, ex.what());
 | 
						|
                  ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                  ci->isAlter = false;
 | 
						|
                  return rc;
 | 
						|
                }
 | 
						|
                catch (...)
 | 
						|
                {
 | 
						|
                  rc = 1;
 | 
						|
                  thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                  thd->raise_error_printf(ER_INTERNAL_ERROR,
 | 
						|
                                          "Unknown exception caught when checking any rows in the table.");
 | 
						|
                  ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                  ci->isAlter = false;
 | 
						|
                  return rc;
 | 
						|
                }
 | 
						|
 | 
						|
                if (anyRow)
 | 
						|
                {
 | 
						|
                  rc = 1;
 | 
						|
                  thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                  thd->raise_error_printf(
 | 
						|
                      ER_INTERNAL_ERROR,
 | 
						|
                      "Table is not empty. New column has to have a default value if NOT NULL required.");
 | 
						|
                  ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                  ci->isAlter = false;
 | 
						|
                  return rc;
 | 
						|
                }
 | 
						|
              }
 | 
						|
              else if ((addColumnsPtr->fColumns[0]->fConstraints[j]->fConstraintType == DDL_NOT_NULL) &&
 | 
						|
                       (addColumnsPtr->fColumns[0]->fDefaultValue))
 | 
						|
              {
 | 
						|
                if (addColumnsPtr->fColumns[0]->fDefaultValue->fValue.length() ==
 | 
						|
                    0)  // empty string is NULL in infinidb
 | 
						|
                {
 | 
						|
                  rc = 1;
 | 
						|
                  thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                  thd->raise_error_printf(ER_INTERNAL_ERROR,
 | 
						|
                                          "New column has to have a default value if NOT NULL required.");
 | 
						|
                  ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                  ci->isAlter = false;
 | 
						|
                  return rc;
 | 
						|
                }
 | 
						|
              }
 | 
						|
            }
 | 
						|
 | 
						|
            if (addColumnsPtr->fColumns[0]->fDefaultValue)
 | 
						|
            {
 | 
						|
              if ((!addColumnsPtr->fColumns[0]->fDefaultValue->fNull) &&
 | 
						|
                  (addColumnsPtr->fColumns[0]->fType->fType == ddlpackage::DDL_VARBINARY))
 | 
						|
              {
 | 
						|
                rc = 1;
 | 
						|
                thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                thd->raise_error_printf(ER_INTERNAL_ERROR, "Varbinary column cannot have default value.");
 | 
						|
                ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                ci->isAlter = false;
 | 
						|
                return rc;
 | 
						|
              }
 | 
						|
 | 
						|
              // validate the default value, if out of range, just error out
 | 
						|
              CalpontSystemCatalog::ColDataType dataType;
 | 
						|
              dataType = convertDataType(addColumnsPtr->fColumns[0]->fType->fType);
 | 
						|
              CalpontSystemCatalog::ColType colType;
 | 
						|
              colType.colDataType = dataType;
 | 
						|
              colType.colWidth = addColumnsPtr->fColumns[0]->fType->fLength;
 | 
						|
              colType.precision = addColumnsPtr->fColumns[0]->fType->fPrecision;
 | 
						|
              colType.scale = addColumnsPtr->fColumns[0]->fType->fScale;
 | 
						|
              boost::any convertedVal;
 | 
						|
              bool pushWarning = false;
 | 
						|
 | 
						|
              try
 | 
						|
              {
 | 
						|
                convertedVal = colType.convertColumnData(addColumnsPtr->fColumns[0]->fDefaultValue->fValue,
 | 
						|
                                                         pushWarning, timeZoneOffset, false, false, false);
 | 
						|
              }
 | 
						|
              catch (std::exception&)
 | 
						|
              {
 | 
						|
                rc = 1;
 | 
						|
                thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                thd->raise_error_printf(ER_INTERNAL_ERROR,
 | 
						|
                                        "The default value is out of range for the specified data type.");
 | 
						|
                ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                ci->isAlter = false;
 | 
						|
                return rc;
 | 
						|
              }
 | 
						|
 | 
						|
              if (pushWarning)
 | 
						|
              {
 | 
						|
                rc = 1;
 | 
						|
                thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                thd->raise_error_printf(ER_INTERNAL_ERROR,
 | 
						|
                                        "The default value is out of range for the specified data type.");
 | 
						|
                ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                ci->isAlter = false;
 | 
						|
                return rc;
 | 
						|
              }
 | 
						|
              if (addColumnsPtr->fColumns[0]->fType->fType == ddlpackage::DDL_TIMESTAMP &&
 | 
						|
                  addColumnsPtr->fColumns[0]->fDefaultValue->fValue == "0")
 | 
						|
              {
 | 
						|
                addColumnsPtr->fColumns[0]->fDefaultValue->fValue = "0000-00-00 00:00:00";
 | 
						|
              }
 | 
						|
            }
 | 
						|
          }
 | 
						|
 | 
						|
          // For TIMESTAMP, if no constraint is given, default to NOT NULL
 | 
						|
          if (addColumnsPtr->fColumns[0]->fType->fType == ddlpackage::DDL_TIMESTAMP &&
 | 
						|
              addColumnsPtr->fColumns[0]->fConstraints.empty())
 | 
						|
          {
 | 
						|
            addColumnsPtr->fColumns[0]->fConstraints.push_back(new ColumnConstraintDef(DDL_NOT_NULL));
 | 
						|
          }
 | 
						|
 | 
						|
          // If no default value exists for TIMESTAMP, we apply
 | 
						|
          // automatic TIMESTAMP properties.
 | 
						|
          // TODO: If no default value exists but the constraint is NULL,
 | 
						|
          // default value should be set to NULL. But this is currently
 | 
						|
          // not supported since columnstore does not track whether user
 | 
						|
          // specified a NULL or not
 | 
						|
          if (addColumnsPtr->fColumns[0]->fType->fType == ddlpackage::DDL_TIMESTAMP &&
 | 
						|
              !addColumnsPtr->fColumns[0]->fDefaultValue)
 | 
						|
          {
 | 
						|
            // Query calpontsys.syscolumn to see
 | 
						|
            // if a timestamp column already exists in this table
 | 
						|
            if (!anyTimestampColumn(alterTable->fTableName->fSchema, alterTable->fTableName->fName,
 | 
						|
                                    sessionID))
 | 
						|
            {
 | 
						|
              addColumnsPtr->fColumns[0]->fDefaultValue =
 | 
						|
                  new ColumnDefaultValue("current_timestamp() ON UPDATE current_timestamp()");
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
              addColumnsPtr->fColumns[0]->fDefaultValue = new ColumnDefaultValue("0000-00-00 00:00:00");
 | 
						|
            }
 | 
						|
          }
 | 
						|
 | 
						|
          // Handle compression type
 | 
						|
          string comment = addColumnsPtr->fColumns[0]->fComment;
 | 
						|
          int compressionType = compressionTypeIn;
 | 
						|
 | 
						|
          if (comment.length() > 0)
 | 
						|
          {
 | 
						|
            compressionType = parseCompressionComment(comment);
 | 
						|
 | 
						|
            if (compressionType == MAX_INT)
 | 
						|
            {
 | 
						|
              compressionType = compressionTypeIn;
 | 
						|
            }
 | 
						|
            else if (compressionType < 0)
 | 
						|
            {
 | 
						|
              rc = 1;
 | 
						|
              thd->raise_error_printf(
 | 
						|
                  ER_INTERNAL_ERROR,
 | 
						|
                  (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_COMPRESSION_TYPE)).c_str());
 | 
						|
              ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
              ci->isAlter = false;
 | 
						|
              return rc;
 | 
						|
            }
 | 
						|
 | 
						|
            if ((compressionType > 0) && !(compress::CompressInterface::isCompressionAvail(compressionType)))
 | 
						|
            {
 | 
						|
              rc = 1;
 | 
						|
              thd->raise_error_printf(
 | 
						|
                  ER_INTERNAL_ERROR,
 | 
						|
                  (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_COMPRESSION_TYPE)).c_str());
 | 
						|
              ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
              ci->isAlter = false;
 | 
						|
              return rc;
 | 
						|
            }
 | 
						|
 | 
						|
            if ((compressionType == 0) && (useHdfs))
 | 
						|
            {
 | 
						|
              compressionType = 2;
 | 
						|
              string errmsg("The column is created with Columnstore compression type 2 under HDFS.");
 | 
						|
              push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 9999, errmsg.c_str());
 | 
						|
            }
 | 
						|
 | 
						|
            try
 | 
						|
            {
 | 
						|
              autoIncre = parseAutoincrementColumnComment(comment, startValue);
 | 
						|
            }
 | 
						|
            catch (runtime_error& ex)
 | 
						|
            {
 | 
						|
              rc = 1;
 | 
						|
              thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
              thd->raise_error_printf(ER_INTERNAL_ERROR, ex.what());
 | 
						|
              ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
              ci->isAlter = false;
 | 
						|
              return rc;
 | 
						|
            }
 | 
						|
 | 
						|
            if (autoIncre)
 | 
						|
            {
 | 
						|
              // Check if the table already has autoincrement column
 | 
						|
              boost::shared_ptr<CalpontSystemCatalog> csc =
 | 
						|
                  CalpontSystemCatalog::makeCalpontSystemCatalog(sessionID);
 | 
						|
              csc->identity(execplan::CalpontSystemCatalog::FE);
 | 
						|
              CalpontSystemCatalog::TableName tableName;
 | 
						|
              tableName.schema = alterTable->fTableName->fSchema;
 | 
						|
              tableName.table = alterTable->fTableName->fName;
 | 
						|
              CalpontSystemCatalog::TableInfo tblInfo;
 | 
						|
 | 
						|
              try
 | 
						|
              {
 | 
						|
                tblInfo = csc->tableInfo(tableName);
 | 
						|
              }
 | 
						|
              catch (runtime_error& ex)
 | 
						|
              {
 | 
						|
                rc = 1;
 | 
						|
                thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                thd->raise_error_printf(ER_INTERNAL_ERROR, ex.what());
 | 
						|
                ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                ci->isAlter = false;
 | 
						|
                return rc;
 | 
						|
              }
 | 
						|
 | 
						|
              if (tblInfo.tablewithautoincr == 1)
 | 
						|
              {
 | 
						|
                rc = 1;
 | 
						|
                thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                thd->raise_error_printf(
 | 
						|
                    ER_INTERNAL_ERROR,
 | 
						|
                    (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_NUMBER_AUTOINCREMENT)).c_str());
 | 
						|
                ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                ci->isAlter = false;
 | 
						|
                return rc;
 | 
						|
              }
 | 
						|
 | 
						|
              if (!validateAutoincrementDatatype(addColumnsPtr->fColumns[0]->fType->fType))
 | 
						|
              {
 | 
						|
                rc = 1;
 | 
						|
                thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                thd->raise_error_printf(
 | 
						|
                    ER_INTERNAL_ERROR,
 | 
						|
                    (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_AUTOINCREMENT_TYPE)).c_str());
 | 
						|
                ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                ci->isAlter = false;
 | 
						|
                return rc;
 | 
						|
              }
 | 
						|
 | 
						|
              if (!validateNextValue(addColumnsPtr->fColumns[0]->fType->fType, startValue))
 | 
						|
              {
 | 
						|
                rc = 1;
 | 
						|
                thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                thd->raise_error_printf(ER_INTERNAL_ERROR,
 | 
						|
                                        (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_STARTVALUE)).c_str());
 | 
						|
                ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                ci->isAlter = false;
 | 
						|
                return rc;
 | 
						|
              }
 | 
						|
 | 
						|
              if (startValue <= 0)
 | 
						|
              {
 | 
						|
                rc = 1;
 | 
						|
                thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                thd->raise_error_printf(
 | 
						|
                    ER_INTERNAL_ERROR, (IDBErrorInfo::instance()->errorMsg(ERR_NEGATIVE_STARTVALUE)).c_str());
 | 
						|
                return rc;
 | 
						|
              }
 | 
						|
            }
 | 
						|
          }
 | 
						|
 | 
						|
          addColumnsPtr->fColumns[0]->fType->fCompressiontype = compressionType;
 | 
						|
 | 
						|
          if (autoIncre)
 | 
						|
            addColumnsPtr->fColumns[0]->fType->fAutoincrement = "y";
 | 
						|
          else
 | 
						|
            addColumnsPtr->fColumns[0]->fType->fAutoincrement = "n";
 | 
						|
 | 
						|
          addColumnsPtr->fColumns[0]->fType->fNextvalue = startValue;
 | 
						|
        }
 | 
						|
        else if (ddlpackage::AtaRenameColumn* renameColumnsPtr =
 | 
						|
                     dynamic_cast<AtaRenameColumn*>(actionList[i]))
 | 
						|
        {
 | 
						|
          uint64_t startValue = 1;
 | 
						|
          bool autoIncre = false;
 | 
						|
          //@Bug 3746 Handle compression type
 | 
						|
          string comment = renameColumnsPtr->fComment;
 | 
						|
          int compressionType = compressionTypeIn;
 | 
						|
 | 
						|
          if (comment.length() > 0)
 | 
						|
          {
 | 
						|
            compressionType = parseCompressionComment(comment);
 | 
						|
 | 
						|
            if (compressionType == MAX_INT)
 | 
						|
            {
 | 
						|
              compressionType = compressionTypeIn;
 | 
						|
            }
 | 
						|
            else if (compressionType < 0)
 | 
						|
            {
 | 
						|
              rc = 1;
 | 
						|
              thd->raise_error_printf(
 | 
						|
                  ER_INTERNAL_ERROR,
 | 
						|
                  (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_COMPRESSION_TYPE)).c_str());
 | 
						|
              ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
              ci->isAlter = false;
 | 
						|
              return rc;
 | 
						|
            }
 | 
						|
 | 
						|
            if ((compressionType > 0) && !(compress::CompressInterface::isCompressionAvail(compressionType)))
 | 
						|
            {
 | 
						|
              rc = 1;
 | 
						|
              thd->raise_error_printf(
 | 
						|
                  ER_INTERNAL_ERROR,
 | 
						|
                  (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_COMPRESSION_TYPE)).c_str());
 | 
						|
              ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
              ci->isAlter = false;
 | 
						|
              return rc;
 | 
						|
            }
 | 
						|
 | 
						|
            if ((compressionType == 0) && (useHdfs))
 | 
						|
            {
 | 
						|
              compressionType = 2;
 | 
						|
              string errmsg("The column is created with Columnstore compression type 2 under HDFS.");
 | 
						|
              push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 9999, errmsg.c_str());
 | 
						|
            }
 | 
						|
          }
 | 
						|
 | 
						|
          // Handle autoincrement
 | 
						|
          if (comment.length() > 0)
 | 
						|
          {
 | 
						|
            try
 | 
						|
            {
 | 
						|
              autoIncre = parseAutoincrementColumnComment(comment, startValue);
 | 
						|
            }
 | 
						|
            catch (runtime_error& ex)
 | 
						|
            {
 | 
						|
              rc = 1;
 | 
						|
              thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
              thd->raise_error_printf(ER_INTERNAL_ERROR, ex.what());
 | 
						|
              ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
              ci->isAlter = false;
 | 
						|
              return rc;
 | 
						|
            }
 | 
						|
 | 
						|
            if (autoIncre)
 | 
						|
            {
 | 
						|
              // Check if the table already has autoincrement column
 | 
						|
              CalpontSystemCatalog::TableName tableName;
 | 
						|
              tableName.schema = alterTable->fTableName->fSchema;
 | 
						|
              tableName.table = alterTable->fTableName->fName;
 | 
						|
              // CalpontSystemCatalog::TableInfo tblInfo = csc->tableInfo(tableName);
 | 
						|
 | 
						|
              //@Bug 5444. rename column doen't need to check this.
 | 
						|
              /*	if (tblInfo.tablewithautoincr == 1)
 | 
						|
                  {
 | 
						|
                          rc = 1;
 | 
						|
                          thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                          thd->raise_error_printf(ER_INTERNAL_ERROR,
 | 
						|
                 (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_NUMBER_AUTOINCREMENT)).c_str());
 | 
						|
                          ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                          ci->isAlter = false;
 | 
						|
                          return rc;
 | 
						|
                  } */
 | 
						|
 | 
						|
              if (!validateAutoincrementDatatype(renameColumnsPtr->fNewType->fType))
 | 
						|
              {
 | 
						|
                rc = 1;
 | 
						|
                thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                thd->raise_error_printf(
 | 
						|
                    ER_INTERNAL_ERROR,
 | 
						|
                    (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_AUTOINCREMENT_TYPE)).c_str());
 | 
						|
                ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                ci->isAlter = false;
 | 
						|
                return rc;
 | 
						|
              }
 | 
						|
 | 
						|
              if (!validateNextValue(renameColumnsPtr->fNewType->fType, startValue))
 | 
						|
              {
 | 
						|
                rc = 1;
 | 
						|
                thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                thd->raise_error_printf(ER_INTERNAL_ERROR,
 | 
						|
                                        (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_STARTVALUE)).c_str());
 | 
						|
                ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                ci->isAlter = false;
 | 
						|
                return rc;
 | 
						|
              }
 | 
						|
            }
 | 
						|
          }
 | 
						|
 | 
						|
          if (autoIncre)
 | 
						|
            renameColumnsPtr->fNewType->fAutoincrement = "y";
 | 
						|
          else
 | 
						|
            renameColumnsPtr->fNewType->fAutoincrement = "n";
 | 
						|
 | 
						|
          renameColumnsPtr->fNewType->fNextvalue = startValue;
 | 
						|
          renameColumnsPtr->fNewType->fCompressiontype = compressionType;
 | 
						|
 | 
						|
          if (renameColumnsPtr->fConstraints.size() > 0)
 | 
						|
          {
 | 
						|
            for (uint32_t j = 0; j < renameColumnsPtr->fConstraints.size(); j++)
 | 
						|
            {
 | 
						|
              if (renameColumnsPtr->fConstraints[j]->fConstraintType == DDL_NOT_NULL)
 | 
						|
              {
 | 
						|
                // If NOT NULL constraint is added, check whether the existing rows has null vlues. If there
 | 
						|
                // is, error out the query.
 | 
						|
                bool anyNullVal = false;
 | 
						|
 | 
						|
                try
 | 
						|
                {
 | 
						|
                  anyNullVal =
 | 
						|
                      anyNullInTheColumn(thd, alterTable->fTableName->fSchema, alterTable->fTableName->fName,
 | 
						|
                                         renameColumnsPtr->fName, sessionID);
 | 
						|
                }
 | 
						|
                catch (runtime_error& ex)
 | 
						|
                {
 | 
						|
                  rc = 1;
 | 
						|
                  thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                  thd->raise_error_printf(ER_INTERNAL_ERROR, ex.what());
 | 
						|
                  ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                  ci->isAlter = false;
 | 
						|
                  return rc;
 | 
						|
                }
 | 
						|
                catch (...)
 | 
						|
                {
 | 
						|
                  rc = 1;
 | 
						|
                  thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                  thd->raise_error_printf(
 | 
						|
                      ER_INTERNAL_ERROR,
 | 
						|
                      "Unknown exception caught when checking any existing null values in the column.");
 | 
						|
                  ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                  ci->isAlter = false;
 | 
						|
                  return rc;
 | 
						|
                }
 | 
						|
 | 
						|
                if (anyNullVal)
 | 
						|
                {
 | 
						|
                  rc = 1;
 | 
						|
                  thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                  thd->raise_error_printf(ER_INTERNAL_ERROR,
 | 
						|
                                          "The existing rows in this column has null value already.");
 | 
						|
                  ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                  ci->isAlter = false;
 | 
						|
                  return rc;
 | 
						|
                }
 | 
						|
              }
 | 
						|
              else
 | 
						|
              {
 | 
						|
                rc = 1;
 | 
						|
                thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
                thd->raise_error_printf(ER_CHECK_NOT_IMPLEMENTED,
 | 
						|
                                        (IDBErrorInfo::instance()->errorMsg(ERR_CONSTRAINTS)).c_str());
 | 
						|
                ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
                ci->isAlter = false;
 | 
						|
                return rc;
 | 
						|
              }
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    //@Bug 5923 error out on unsupported statements.
 | 
						|
    else if ((typeid(stmt) != typeid(DropTableStatement)) && (typeid(stmt) != typeid(TruncTableStatement)) &&
 | 
						|
             (typeid(stmt) != typeid(MarkPartitionStatement)) &&
 | 
						|
             (typeid(stmt) != typeid(RestorePartitionStatement)) &&
 | 
						|
             (typeid(stmt) != typeid(DropPartitionStatement)))
 | 
						|
    {
 | 
						|
      rc = 1;
 | 
						|
      thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
      thd->raise_error_printf(ER_INTERNAL_ERROR,
 | 
						|
                              (IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_SYNTAX)).c_str());
 | 
						|
      ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
      ci->isAlter = false;
 | 
						|
      return rc;
 | 
						|
    }
 | 
						|
 | 
						|
    //@Bug 4387
 | 
						|
    scoped_ptr<DBRM> dbrmp(new DBRM());
 | 
						|
    int rc = dbrmp->isReadWrite();
 | 
						|
 | 
						|
    if (rc != 0)
 | 
						|
    {
 | 
						|
      rc = 1;
 | 
						|
      thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
      thd->raise_error_printf(ER_INTERNAL_ERROR, "Cannot execute the statement. DBRM is read only!");
 | 
						|
      ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
      ci->isAlter = false;
 | 
						|
      return rc;
 | 
						|
    }
 | 
						|
 | 
						|
    stmt.fSessionID = sessionID;
 | 
						|
    stmt.fSql = ddlStatement;
 | 
						|
    stmt.fOwner = schema;
 | 
						|
    stmt.fTableWithAutoi = isAnyAutoincreCol;
 | 
						|
    ByteStream bytestream;
 | 
						|
    bytestream << stmt.fSessionID;
 | 
						|
    stmt.serialize(bytestream);
 | 
						|
    MessageQueueClient mq("DDLProc");
 | 
						|
    ByteStream::byte b = 0;
 | 
						|
 | 
						|
    try
 | 
						|
    {
 | 
						|
      mq.write(bytestream);
 | 
						|
      bytestream = mq.read();
 | 
						|
 | 
						|
      if (bytestream.length() == 0)
 | 
						|
      {
 | 
						|
        rc = 1;
 | 
						|
        thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
 | 
						|
        thd->raise_error_printf(ER_INTERNAL_ERROR, "Lost connection to DDLProc");
 | 
						|
        ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
        ci->isAlter = false;
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        bytestream >> b;
 | 
						|
        bytestream >> emsg;
 | 
						|
        rc = b;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    catch (runtime_error& e)
 | 
						|
    {
 | 
						|
      rc = 1;
 | 
						|
      thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
 | 
						|
      thd->raise_error_printf(ER_INTERNAL_ERROR, "Lost connection to DDLProc");
 | 
						|
      ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
      ci->isAlter = false;
 | 
						|
    }
 | 
						|
    catch (...)
 | 
						|
    {
 | 
						|
      rc = 1;
 | 
						|
      thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
 | 
						|
      thd->raise_error_printf(ER_INTERNAL_ERROR, "Unknown error caught");
 | 
						|
      ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
      ci->isAlter = false;
 | 
						|
    }
 | 
						|
 | 
						|
    if (b == ddlpackageprocessor::DDLPackageProcessor::DROP_TABLE_NOT_IN_CATALOG_ERROR)
 | 
						|
    {
 | 
						|
      return ER_NO_SUCH_TABLE_IN_ENGINE;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((b != 0) && (b != ddlpackageprocessor::DDLPackageProcessor::WARNING))
 | 
						|
    {
 | 
						|
      thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
 | 
						|
      thd->raise_error_printf(ER_INTERNAL_ERROR, emsg.c_str());
 | 
						|
    }
 | 
						|
 | 
						|
    if (b == ddlpackageprocessor::DDLPackageProcessor::WARNING)
 | 
						|
    {
 | 
						|
      rc = 0;
 | 
						|
      string errmsg(
 | 
						|
          "Error occurred during file deletion. Restart DDLProc or use command tool ddlcleanup to clean "
 | 
						|
          "up. ");
 | 
						|
      push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 9999, errmsg.c_str());
 | 
						|
    }
 | 
						|
 | 
						|
    return rc;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    rc = 1;
 | 
						|
    thd->get_stmt_da()->set_overwrite_status(true);
 | 
						|
    //@Bug 3602. Error message for MySql syntax for autoincrement
 | 
						|
    algorithm::to_upper(ddlStatement);
 | 
						|
 | 
						|
    if (ddlStatement.find("AUTO_INCREMENT") != string::npos)
 | 
						|
    {
 | 
						|
      thd->raise_error_printf(ER_CHECK_NOT_IMPLEMENTED,
 | 
						|
                              "The syntax auto_increment is not supported in Columnstore. Please check the "
 | 
						|
                              "Columnstore syntax guide for supported syntax or data types.");
 | 
						|
    }
 | 
						|
    else if (ddlStatement.find("RENAME COLUMN") != string::npos)
 | 
						|
    {
 | 
						|
      thd->raise_error_printf(ER_CHECK_NOT_IMPLEMENTED,
 | 
						|
                              "The syntax rename column is not supported by Columnstore. Please check the "
 | 
						|
                              "Columnstore syntax guide for supported syntax or data types.");
 | 
						|
    }
 | 
						|
    else if (ddlStatement.find("MAX_ROWS") != string::npos || ddlStatement.find("MIN_ROWS") != string::npos)
 | 
						|
    {
 | 
						|
      thd->raise_error_printf(ER_CHECK_NOT_IMPLEMENTED,
 | 
						|
                              "The syntax min_rows/max_rows is not supported by Columnstore. Please check "
 | 
						|
                              "the Columnstore syntax guide for supported syntax or data types.");
 | 
						|
    }
 | 
						|
    else if (ddlStatement.find("REPLACE TABLE") != string::npos)
 | 
						|
    {
 | 
						|
      thd->raise_error_printf(ER_CHECK_NOT_IMPLEMENTED,
 | 
						|
                              "The syntax replace table is not supported by Columnstore. Please check the "
 | 
						|
                              "Columnstore syntax guide for supported syntax or data types.");
 | 
						|
    }
 | 
						|
    else if (ddlStatement.find("DROP COLUMN IF EXISTS") != string::npos)
 | 
						|
    {
 | 
						|
      thd->raise_error_printf(ER_CHECK_NOT_IMPLEMENTED,
 | 
						|
                              "The syntax drop column if exists is not supported by Columnstore. Please "
 | 
						|
                              "check the Columnstore syntax guide for supported syntax or data types.");
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      //@Bug 1888,1885. update error message
 | 
						|
      thd->raise_error_printf(ER_CHECK_NOT_IMPLEMENTED,
 | 
						|
                              "The syntax or the data type(s) is not supported by Columnstore. Please check "
 | 
						|
                              "the Columnstore syntax guide for supported syntax or data types.");
 | 
						|
    }
 | 
						|
 | 
						|
    ci->alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
    ci->isAlter = false;
 | 
						|
  }
 | 
						|
 | 
						|
  return rc;
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace
 | 
						|
 | 
						|
//
 | 
						|
// get_field_default_value: Returns the default value as a string value
 | 
						|
// NOTE: This is duplicated code copied from show.cc and a MDEV-17006 has
 | 
						|
//       been created.
 | 
						|
//
 | 
						|
 | 
						|
static bool get_field_default_value(THD* /*thd*/, Field* field, String* def_value, bool quoted)
 | 
						|
{
 | 
						|
  bool has_default;
 | 
						|
  enum enum_field_types field_type = field->type();
 | 
						|
 | 
						|
  has_default = (field->default_value ||
 | 
						|
                 (!(field->flags & NO_DEFAULT_VALUE_FLAG) && field->unireg_check != Field::NEXT_NUMBER));
 | 
						|
 | 
						|
  def_value->length(0);
 | 
						|
  if (has_default)
 | 
						|
  {
 | 
						|
    StringBuffer<MAX_FIELD_WIDTH> str(field->charset());
 | 
						|
    if (field->default_value)
 | 
						|
    {
 | 
						|
      field->default_value->print(&str);
 | 
						|
      if (field->default_value->expr->need_parentheses_in_default())
 | 
						|
      {
 | 
						|
        def_value->set_charset(&my_charset_utf8mb4_general_ci);
 | 
						|
        def_value->append('(');
 | 
						|
        def_value->append(str);
 | 
						|
        def_value->append(')');
 | 
						|
      }
 | 
						|
      else
 | 
						|
        def_value->append(str);
 | 
						|
    }
 | 
						|
    else if (!field->is_null())
 | 
						|
    {  // Not null by default
 | 
						|
      if (field_type == MYSQL_TYPE_BIT)
 | 
						|
      {
 | 
						|
        str.qs_append('b');
 | 
						|
        str.qs_append('\'');
 | 
						|
        str.qs_append(field->val_int(), 2);
 | 
						|
        str.qs_append('\'');
 | 
						|
        quoted = 0;
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        field->val_str(&str);
 | 
						|
        if (!field->str_needs_quotes())
 | 
						|
          quoted = 0;
 | 
						|
      }
 | 
						|
      if (str.length())
 | 
						|
      {
 | 
						|
        StringBuffer<MAX_FIELD_WIDTH> def_val;
 | 
						|
        uint dummy_errors;
 | 
						|
        /* convert to system_charset_info == utf8 */
 | 
						|
        def_val.copy(str.ptr(), str.length(), field->charset(), system_charset_info, &dummy_errors);
 | 
						|
        if (quoted)
 | 
						|
          append_unescaped(def_value, def_val.ptr(), def_val.length());
 | 
						|
        else
 | 
						|
          def_value->append(def_val);
 | 
						|
      }
 | 
						|
      else if (quoted)
 | 
						|
        def_value->set(STRING_WITH_LEN("''"), system_charset_info);
 | 
						|
    }
 | 
						|
    else if (field->maybe_null() && quoted)
 | 
						|
      def_value->set(STRING_WITH_LEN("NULL"), system_charset_info);  // Null as default
 | 
						|
    else
 | 
						|
      return 0;
 | 
						|
  }
 | 
						|
  return has_default;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
    Utility function search for ZEROFILL
 | 
						|
*/
 | 
						|
 | 
						|
bool hasZerofillDecimal(TABLE* table_arg)
 | 
						|
{
 | 
						|
  for (Field** field = table_arg->field; *field; field++)
 | 
						|
  {
 | 
						|
    if (((*field)->flags & ZEROFILL_FLAG) && typeid(**field) == typeid(Field_new_decimal))
 | 
						|
      return true;
 | 
						|
  }
 | 
						|
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
int ha_mcs_impl_create_(const char* /*name*/, TABLE* table_arg, HA_CREATE_INFO* create_info,
 | 
						|
                        cal_connection_info& ci)
 | 
						|
{
 | 
						|
#ifdef MCS_DEBUG
 | 
						|
  cout << "ha_mcs_impl_create_: " << name << endl;
 | 
						|
#endif
 | 
						|
  THD* thd = current_thd;
 | 
						|
 | 
						|
  if (thd->slave_thread && !get_replication_slave(thd))
 | 
						|
    return 0;
 | 
						|
 | 
						|
  char* query = thd->query();
 | 
						|
 | 
						|
  if (!query)
 | 
						|
  {
 | 
						|
    setError(thd, ER_INTERNAL_ERROR, "Attempt to create table, but query is NULL");
 | 
						|
    return 1;
 | 
						|
  }
 | 
						|
 | 
						|
  string stmt(query);
 | 
						|
  stmt += ";";
 | 
						|
  algorithm::to_upper(stmt);
 | 
						|
 | 
						|
  string db, tbl;
 | 
						|
  db = table_arg->s->db.str;
 | 
						|
  tbl = table_arg->s->table_name.str;
 | 
						|
 | 
						|
  string tablecomment;
 | 
						|
  bool isAnyAutoincreCol = false;
 | 
						|
  std::string columnName("");
 | 
						|
  uint64_t startValue = 1;
 | 
						|
 | 
						|
  if (table_arg->s->comment.length > 0)
 | 
						|
  {
 | 
						|
    tablecomment = table_arg->s->comment.str;
 | 
						|
 | 
						|
    try
 | 
						|
    {
 | 
						|
      isAnyAutoincreCol = parseAutoincrementTableComment(tablecomment, startValue, columnName);
 | 
						|
    }
 | 
						|
    catch (runtime_error& ex)
 | 
						|
    {
 | 
						|
      setError(thd, ER_INTERNAL_ERROR, ex.what());
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    algorithm::to_upper(tablecomment);
 | 
						|
  }
 | 
						|
 | 
						|
  //@Bug 2553 Add a parenthesis around option to group them together
 | 
						|
  string alterpatstr(
 | 
						|
      "ALTER[[:space:]]+TABLE[[:space:]]+.*[[:space:]]+(((ADD)|(DROP)|(CHANGE)|(ALTER)|(COMMENT))[[:space:]]+"
 | 
						|
      "|(COMMENT=))");
 | 
						|
  string createpatstr("CREATE[[:space:]]+TABLE[[:space:]]");
 | 
						|
  bool schemaSyncOnly = false;
 | 
						|
  bool isCreate = true;
 | 
						|
 | 
						|
  std::regex pat("[[:space:]]*SCHEMA[[:space:]]+SYNC[[:space:]]+ONLY", std::regex_constants::extended);
 | 
						|
 | 
						|
  if (std::regex_search(tablecomment, pat))
 | 
						|
  {
 | 
						|
    schemaSyncOnly = true;
 | 
						|
    pat = createpatstr;
 | 
						|
 | 
						|
    if (!std::regex_search(stmt, pat))
 | 
						|
    {
 | 
						|
      isCreate = false;
 | 
						|
    }
 | 
						|
 | 
						|
    if (isCreate)
 | 
						|
    {
 | 
						|
#ifdef MCS_DEBUG
 | 
						|
      cout << "ha_mcs_impl_create_: SCHEMA SYNC ONLY found, returning" << endl;
 | 
						|
#endif
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    if (db == "calpontsys")
 | 
						|
    {
 | 
						|
      setError(thd, ER_INTERNAL_ERROR, "Calpont system tables can only be created with 'SCHEMA SYNC ONLY'");
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
    else if (db == "infinidb_vtable")  //@bug 3540. table created in infinidb_vtable schema could be dropped
 | 
						|
                                       // when select statement happen to have same tablename.
 | 
						|
    {
 | 
						|
      setError(thd, ER_INTERNAL_ERROR, "Table creation is not allowed in infinidb_vtable schema.");
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  pat = alterpatstr;
 | 
						|
 | 
						|
  if (std::regex_search(stmt, pat))
 | 
						|
  {
 | 
						|
    ci.isAlter = true;
 | 
						|
    ci.alterTableState = cal_connection_info::ALTER_FIRST_RENAME;
 | 
						|
#ifdef MCS_DEBUG
 | 
						|
    cout << "ha_mcs_impl_create_: now in state ALTER_FIRST_RENAME" << endl;
 | 
						|
#endif
 | 
						|
  }
 | 
						|
 | 
						|
  string emsg;
 | 
						|
  stmt = thd->query();
 | 
						|
  stmt += ";";
 | 
						|
  int rc = 0;
 | 
						|
 | 
						|
  // Don't do the DDL (only for create table if this is SSO. Should only get here on ATAC w/SSO.
 | 
						|
  if (schemaSyncOnly && isCreate)
 | 
						|
    return rc;
 | 
						|
 | 
						|
  //@bug 5660. Error out REAL DDL/DML on slave node.
 | 
						|
  // When the statement gets here, it's NOT SSO or RESTRICT
 | 
						|
  if (ci.isSlaveNode)
 | 
						|
  {
 | 
						|
    string emsg = logging::IDBErrorInfo::instance()->errorMsg(ERR_DML_DDL_SLAVE);
 | 
						|
    setError(thd, ER_CHECK_NOT_IMPLEMENTED, emsg);
 | 
						|
    return 1;
 | 
						|
  }
 | 
						|
 | 
						|
  // Send notice if primary key specified that it is not supported
 | 
						|
  if (table_arg->key_info && table_arg->key_info->name.length &&
 | 
						|
      string(table_arg->key_info->name.str) == "PRIMARY")
 | 
						|
  {
 | 
						|
    push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, WARN_OPTION_IGNORED, "INDEXES");
 | 
						|
  }
 | 
						|
 | 
						|
  int compressiontype = get_compression_type(thd);
 | 
						|
 | 
						|
  // MCOL-4685:
 | 
						|
  // remove the option to declare uncompressed columns (set infinidb_compression_type = 0).
 | 
						|
  if (compressiontype == 1 || compressiontype == 0)
 | 
						|
    compressiontype = 2;
 | 
						|
 | 
						|
  // string tablecomment;
 | 
						|
  if (table_arg->s->comment.length > 0)
 | 
						|
  {
 | 
						|
    tablecomment = table_arg->s->comment.str;
 | 
						|
    compressiontype = parseCompressionComment(tablecomment);
 | 
						|
  }
 | 
						|
 | 
						|
  if (compressiontype == MAX_INT)
 | 
						|
  {
 | 
						|
    compressiontype = get_compression_type(thd);
 | 
						|
    // MCOL-4685:
 | 
						|
    // remove the option to declare uncompressed columns (set infinidb_compression_type = 0).
 | 
						|
    if (compressiontype == 0)
 | 
						|
      compressiontype = 2;
 | 
						|
  }
 | 
						|
  else if (compressiontype < 0)
 | 
						|
  {
 | 
						|
    string emsg = IDBErrorInfo::instance()->errorMsg(ERR_INVALID_COMPRESSION_TYPE);
 | 
						|
    setError(thd, ER_INTERNAL_ERROR, emsg);
 | 
						|
    ci.alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
    ci.isAlter = false;
 | 
						|
    return 1;
 | 
						|
  }
 | 
						|
 | 
						|
  // hdfs
 | 
						|
  if ((compressiontype == 0) && (useHdfs))
 | 
						|
  {
 | 
						|
    compressiontype = 2;
 | 
						|
    push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 9999,
 | 
						|
                 "The table is created with Columnstore compression type 2 under HDFS.");
 | 
						|
  }
 | 
						|
 | 
						|
  if (compressiontype == 1)
 | 
						|
    compressiontype = 2;
 | 
						|
 | 
						|
  if ((compressiontype > 0) && !(compress::CompressInterface::isCompressionAvail(compressiontype)))
 | 
						|
  {
 | 
						|
    string emsg = IDBErrorInfo::instance()->errorMsg(ERR_INVALID_COMPRESSION_TYPE);
 | 
						|
    setError(thd, ER_INTERNAL_ERROR, emsg);
 | 
						|
    ci.alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
    ci.isAlter = false;
 | 
						|
    return 1;
 | 
						|
  }
 | 
						|
 | 
						|
  // Check if this is one of
 | 
						|
  // * "CREATE TABLE ... LIKE "
 | 
						|
  // * "ALTER TABLE ... ENGINE=Columnstore"
 | 
						|
  // * "CREATE TABLE ... AS ..."
 | 
						|
  // If so generate a full create table statement using the properties of
 | 
						|
  // the source table. Note that source table has to be a columnstore table and
 | 
						|
  // we only check for currently supported options.
 | 
						|
  //
 | 
						|
 | 
						|
  if ((thd->lex->sql_command == SQLCOM_CREATE_TABLE && thd->lex->used_tables) ||
 | 
						|
      (thd->lex->sql_command == SQLCOM_ALTER_TABLE && create_info->used_fields & HA_CREATE_USED_ENGINE) ||
 | 
						|
      (thd->lex->create_info.like()))
 | 
						|
  {
 | 
						|
    TABLE_SHARE* share = table_arg->s;
 | 
						|
    MY_BITMAP* old_map;  // To save the read_set
 | 
						|
    char datatype_buf[MAX_FIELD_WIDTH], def_value_buf[MAX_FIELD_WIDTH];
 | 
						|
    String datatype, def_value;
 | 
						|
    ostringstream oss;
 | 
						|
    string tbl_name = "`" + string(share->db.str) + "`.`" + string(share->table_name.str) + "`";
 | 
						|
 | 
						|
    // Save the current read_set map and mark it for read
 | 
						|
    old_map = tmp_use_all_columns(table_arg, &table_arg->read_set);
 | 
						|
 | 
						|
    oss << "CREATE TABLE " << tbl_name << " (";
 | 
						|
 | 
						|
    restore_record(table_arg, s->default_values);
 | 
						|
    for (Field** field = table_arg->field; *field; field++)
 | 
						|
    {
 | 
						|
      uint flags = (*field)->flags;
 | 
						|
      datatype.set(datatype_buf, sizeof(datatype_buf), system_charset_info);
 | 
						|
      (*field)->sql_type(datatype);
 | 
						|
      if (field != table_arg->field)
 | 
						|
        oss << ", ";
 | 
						|
      oss << "`" << (*field)->field_name.str << "` " << datatype.ptr();
 | 
						|
 | 
						|
      if ((*field)->has_charset())
 | 
						|
      {
 | 
						|
        const CHARSET_INFO* field_cs = (*field)->charset();
 | 
						|
        if (field_cs && (!share->table_charset || field_cs->number != share->table_charset->number))
 | 
						|
        {
 | 
						|
          oss << " CHARACTER SET " << field_cs->cs_name.str << " COLLATE " << field_cs->coll_name.str;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (flags & NOT_NULL_FLAG)
 | 
						|
        oss << " NOT NULL";
 | 
						|
 | 
						|
      def_value.set(def_value_buf, sizeof(def_value_buf), system_charset_info);
 | 
						|
      if (get_field_default_value(thd, *field, &def_value, true))
 | 
						|
      {
 | 
						|
        oss << " DEFAULT " << def_value.c_ptr();
 | 
						|
      }
 | 
						|
 | 
						|
      if ((*field)->comment.length)
 | 
						|
      {
 | 
						|
        String comment;
 | 
						|
        append_unescaped(&comment, (*field)->comment.str, (*field)->comment.length);
 | 
						|
        oss << " COMMENT ";
 | 
						|
        oss << comment.c_ptr();
 | 
						|
      }
 | 
						|
    }
 | 
						|
    // End the list of columns
 | 
						|
    oss << ") ENGINE=columnstore ";
 | 
						|
 | 
						|
    // Process table level options
 | 
						|
 | 
						|
    /* TODO: uncomment when we support AUTO_INCREMENT
 | 
						|
            if (create_info->auto_increment_value > 1)
 | 
						|
            {
 | 
						|
                    oss << " AUTO_INCREMENT=" << create_info->auto_increment_value;
 | 
						|
            }
 | 
						|
    */
 | 
						|
 | 
						|
    if (create_info->auto_increment_value > 1)
 | 
						|
    {
 | 
						|
      push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, WARN_OPTION_IGNORED, "AUTO INCREMENT");
 | 
						|
    }
 | 
						|
 | 
						|
    if (share->table_charset)
 | 
						|
    {
 | 
						|
      oss << " DEFAULT CHARSET=" << share->table_charset->cs_name.str
 | 
						|
          << " COLLATE=" << share->table_charset->coll_name.str;
 | 
						|
    }
 | 
						|
 | 
						|
    // Process table level options such as MIN_ROWS, MAX_ROWS, COMMENT
 | 
						|
 | 
						|
    if (share->min_rows)
 | 
						|
    {
 | 
						|
      char buff[80];
 | 
						|
      longlong10_to_str(share->min_rows, buff, 10);
 | 
						|
      oss << " MIN_ROWS=" << buff;
 | 
						|
    }
 | 
						|
 | 
						|
    if (share->max_rows)
 | 
						|
    {
 | 
						|
      char buff[80];
 | 
						|
      longlong10_to_str(share->max_rows, buff, 10);
 | 
						|
      oss << " MAX_ROWS=" << buff;
 | 
						|
    }
 | 
						|
 | 
						|
    if (share->comment.length)
 | 
						|
    {
 | 
						|
      String comment;
 | 
						|
      append_unescaped(&comment, share->comment.str, share->comment.length);
 | 
						|
      oss << " COMMENT ";
 | 
						|
      oss << comment.c_ptr();
 | 
						|
    }
 | 
						|
 | 
						|
    oss << ";";
 | 
						|
    stmt = oss.str();
 | 
						|
 | 
						|
    tmp_restore_column_map(&table_arg->read_set, old_map);
 | 
						|
  }
 | 
						|
 | 
						|
  rc = ProcessDDLStatement(stmt, db, tbl, tid2sid(thd->thread_id), emsg, compressiontype, isAnyAutoincreCol,
 | 
						|
                           startValue, columnName, create_info->default_table_charset);
 | 
						|
 | 
						|
  if (rc != 0)
 | 
						|
  {
 | 
						|
    push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 9999, emsg.c_str());
 | 
						|
    // Bug 1705 reset the flag if error occurs
 | 
						|
    ci.alterTableState = cal_connection_info::NOT_ALTER;
 | 
						|
    ci.isAlter = false;
 | 
						|
#ifdef MCS_DEBUG
 | 
						|
    cout << "ha_mcs_impl_create_: ProcessDDL error, now in state NOT_ALTER" << endl;
 | 
						|
#endif
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    if (hasZerofillDecimal(table_arg))
 | 
						|
    {
 | 
						|
      push_warning(thd, Sql_condition::WARN_LEVEL_WARN, WARN_OPTION_IGNORED,
 | 
						|
                   "ZEROFILL is ignored in ColumnStore");
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return rc;
 | 
						|
}
 | 
						|
 | 
						|
int ha_mcs_impl_delete_table_(const char* /*db*/, const char* name, cal_connection_info& ci)
 | 
						|
{
 | 
						|
#ifdef MCS_DEBUG
 | 
						|
  cout << "ha_mcs_impl_delete_table: " << db << name << endl;
 | 
						|
#endif
 | 
						|
  THD* thd = current_thd;
 | 
						|
 | 
						|
  if (thd->slave_thread && !get_replication_slave(thd))
 | 
						|
    return 0;
 | 
						|
 | 
						|
  char* query = thd->query();
 | 
						|
 | 
						|
  if (!query)
 | 
						|
  {
 | 
						|
    setError(thd, ER_INTERNAL_ERROR, "Attempt to drop table, but query is NULL");
 | 
						|
    return 1;
 | 
						|
  }
 | 
						|
 | 
						|
  std::string stmt(query);
 | 
						|
  algorithm::to_upper(stmt);
 | 
						|
  // @bug 4158 allow table name with 'restrict' in it (but not by itself)
 | 
						|
  std::string::size_type fpos;
 | 
						|
  fpos = stmt.rfind(" RESTRICT");
 | 
						|
 | 
						|
  if ((fpos != std::string::npos) && ((stmt.size() - fpos) == 9))  // last 9 chars of stmt are " RESTRICT"
 | 
						|
  {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  //@bug 5660. Error out REAL DDL/DML on slave node.
 | 
						|
  // When the statement gets here, it's NOT SSO or RESTRICT
 | 
						|
  if (ci.isSlaveNode)
 | 
						|
  {
 | 
						|
    string emsg = logging::IDBErrorInfo::instance()->errorMsg(ERR_DML_DDL_SLAVE);
 | 
						|
    setError(thd, ER_CHECK_NOT_IMPLEMENTED, emsg);
 | 
						|
    return 1;
 | 
						|
  }
 | 
						|
 | 
						|
  std::string emsg;
 | 
						|
 | 
						|
  char decodedSchema[FN_REFLEN];
 | 
						|
  char decodedTbl[FN_REFLEN];
 | 
						|
  decode_file_path(name, decodedSchema, decodedTbl);
 | 
						|
  std::string schema(decodedSchema);
 | 
						|
  std::string tbl(decodedTbl);
 | 
						|
 | 
						|
  stmt.clear();
 | 
						|
  stmt.assign("DROP TABLE `");
 | 
						|
  stmt.append(decodedSchema);
 | 
						|
  stmt.append("`.`");
 | 
						|
  stmt.append(decodedTbl);
 | 
						|
  stmt.append("`;");
 | 
						|
 | 
						|
  int rc = ProcessDDLStatement(stmt, schema, tbl, tid2sid(thd->thread_id), emsg);
 | 
						|
 | 
						|
  if (rc != 0 && rc != ER_NO_SUCH_TABLE_IN_ENGINE)
 | 
						|
  {
 | 
						|
    push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 9999, emsg.c_str());
 | 
						|
  }
 | 
						|
 | 
						|
  return rc;
 | 
						|
}
 | 
						|
 | 
						|
int ha_mcs_impl_rename_table_(const char* from, const char* to, cal_connection_info& ci)
 | 
						|
{
 | 
						|
  THD* thd = current_thd;
 | 
						|
 | 
						|
  if (thd->slave_thread && !get_replication_slave(thd))
 | 
						|
    return 0;
 | 
						|
 | 
						|
  string emsg;
 | 
						|
 | 
						|
  string tblFrom(from + 2);
 | 
						|
  size_t pos = tblFrom.find("/");
 | 
						|
  std::string dbFrom = tblFrom.substr(0, pos);
 | 
						|
  tblFrom = tblFrom.erase(0, pos + 1);
 | 
						|
 | 
						|
  string tblTo(to + 2);
 | 
						|
  pos = tblTo.find("/");
 | 
						|
  std::string dbTo = tblTo.substr(0, pos);
 | 
						|
  tblTo = tblTo.erase(0, pos + 1);
 | 
						|
 | 
						|
  string stmt;
 | 
						|
 | 
						|
  // This is a temporary table rename, we don't use the temporary table name
 | 
						|
  // so this is a NULL op
 | 
						|
  if (tblFrom.compare(0, 4, "#sql") == 0)
 | 
						|
  {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  //@bug 5660. Error out REAL DDL/DML on slave node.
 | 
						|
  // When the statement gets here, it's NOT SSO or RESTRICT
 | 
						|
  if (ci.isSlaveNode)
 | 
						|
  {
 | 
						|
    string emsg = logging::IDBErrorInfo::instance()->errorMsg(ERR_DML_DDL_SLAVE);
 | 
						|
    setError(current_thd, ER_CHECK_NOT_IMPLEMENTED, emsg);
 | 
						|
    return 1;
 | 
						|
  }
 | 
						|
 | 
						|
  stmt.assign("alter table `");
 | 
						|
  stmt.append(dbFrom);
 | 
						|
  stmt.append("`.`");
 | 
						|
  stmt.append(tblFrom);
 | 
						|
  stmt.append("` rename to `");
 | 
						|
  stmt.append(dbTo);
 | 
						|
  stmt.append("`.`");
 | 
						|
  stmt.append(tblTo);
 | 
						|
  stmt.append("`;");
 | 
						|
 | 
						|
  string db;
 | 
						|
  if (thd->db.length)
 | 
						|
    db = thd->db.str;
 | 
						|
  else
 | 
						|
    db.assign(dbFrom);
 | 
						|
 | 
						|
  int rc = ProcessDDLStatement(stmt, db, "", tid2sid(thd->thread_id), emsg);
 | 
						|
 | 
						|
  if (rc != 0)
 | 
						|
    push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 9999, emsg.c_str());
 | 
						|
 | 
						|
  return rc;
 | 
						|
}
 | 
						|
 | 
						|
extern "C"
 | 
						|
{
 | 
						|
  long long calonlinealter(UDF_INIT* /*initid*/, UDF_ARGS* args, char* /*is_null*/, char* /*error*/)
 | 
						|
  {
 | 
						|
    string stmt(args->args[0], args->lengths[0]);
 | 
						|
 | 
						|
    string emsg;
 | 
						|
    THD* thd = current_thd;
 | 
						|
    string db("");
 | 
						|
 | 
						|
    if (thd->db.length)
 | 
						|
      db = thd->db.str;
 | 
						|
 | 
						|
    // MCOL-4685:
 | 
						|
    // remove the option to declare uncompressed columns (set infinidb_compression_type = 0).
 | 
						|
    int compressiontype = get_compression_type(thd);
 | 
						|
 | 
						|
    if (compressiontype == 1 || compressiontype == 0)
 | 
						|
      compressiontype = 2;
 | 
						|
 | 
						|
    if (compressiontype == MAX_INT)
 | 
						|
    {
 | 
						|
      // MCOL-4685: remove the option to declare uncompressed columns (set
 | 
						|
      // infinidb_compression_type = 0).
 | 
						|
      compressiontype = get_compression_type(thd);
 | 
						|
      if (compressiontype == 0)
 | 
						|
        compressiontype = 2;
 | 
						|
    }
 | 
						|
 | 
						|
    if (compressiontype == 1)
 | 
						|
      compressiontype = 2;
 | 
						|
 | 
						|
    int rc = ProcessDDLStatement(stmt, db, "", tid2sid(thd->thread_id), emsg, compressiontype);
 | 
						|
 | 
						|
    if (rc != 0)
 | 
						|
      push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 9999, emsg.c_str());
 | 
						|
 | 
						|
    return rc;
 | 
						|
  }
 | 
						|
 | 
						|
  my_bool calonlinealter_init(UDF_INIT* /*initid*/, UDF_ARGS* args, char* message)
 | 
						|
  {
 | 
						|
    if (args->arg_count != 1 || args->arg_type[0] != STRING_RESULT)
 | 
						|
    {
 | 
						|
      strcpy(message, "CALONLINEALTER() requires one string argument");
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  void calonlinealter_deinit(UDF_INIT* /*initid*/)
 | 
						|
  {
 | 
						|
  }
 | 
						|
}
 |