diff --git a/storage/tianmu/core/rc_attr_typeinfo.h b/storage/tianmu/core/rc_attr_typeinfo.h deleted file mode 100644 index b9691355959240da4e2ceab030fd484ffa6d1d99..0000000000000000000000000000000000000000 --- a/storage/tianmu/core/rc_attr_typeinfo.h +++ /dev/null @@ -1,131 +0,0 @@ -/* Copyright (c) 2022 StoneAtom, Inc. All rights reserved. - Use is subject to license terms - - 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-1335 USA -*/ -#ifndef TIANMU_CORE_RC_ATTR_TYPEINFO_H_ -#define TIANMU_CORE_RC_ATTR_TYPEINFO_H_ -#pragma once - -#include - -#include "common/common_definitions.h" - -namespace Tianmu { -namespace types { -class RCDataType; -} // namespace types -namespace core { -class ATI { - public: - static int TextSize(common::CT attrt, uint precision, int scale, DTCollation col = DTCollation()); - - static bool IsInteger32Type(common::CT attr_type) { - return attr_type == common::CT::INT || attr_type == common::CT::BYTEINT || attr_type == common::CT::SMALLINT || - attr_type == common::CT::MEDIUMINT; - } - - static bool IsIntegerType(common::CT attr_type) { - return IsInteger32Type(attr_type) || attr_type == common::CT::BIGINT; - } - static bool IsFixedNumericType(common::CT attr_type) { - return IsInteger32Type(attr_type) || attr_type == common::CT::BIGINT || attr_type == common::CT::NUM; - } - - static bool IsRealType(common::CT attr_type) { - return attr_type == common::CT::FLOAT || attr_type == common::CT::REAL; - } - static bool IsNumericType(common::CT attr_type) { - return IsInteger32Type(attr_type) || attr_type == common::CT::BIGINT || attr_type == common::CT::NUM || - attr_type == common::CT::FLOAT || attr_type == common::CT::REAL; - } - - static bool IsBinType(common::CT attr_type) { - return attr_type == common::CT::BYTE || attr_type == common::CT::VARBYTE || attr_type == common::CT::BIN; - } - - static bool IsTxtType(common::CT attr_type) { - return attr_type == common::CT::STRING || attr_type == common::CT::VARCHAR || attr_type == common::CT::LONGTEXT; - } - - static bool IsCharType(common::CT attr_type) { return attr_type == common::CT::STRING; } - static bool IsStringType(common::CT attr_type) { - return attr_type == common::CT::STRING || attr_type == common::CT::VARCHAR || attr_type == common::CT::LONGTEXT || - IsBinType(attr_type); - } - - static bool IsDateTimeType(common::CT attr_type) { - return attr_type == common::CT::DATE || attr_type == common::CT::TIME || attr_type == common::CT::YEAR || - attr_type == common::CT::DATETIME || attr_type == common::CT::TIMESTAMP; - } - - static bool IsDateTimeNType(common::CT attr_type) { - return attr_type == common::CT::TIME_N || attr_type == common::CT::DATETIME_N || - attr_type == common::CT::TIMESTAMP_N; - } -}; - -class AttributeTypeInfo { - public: - enum class enumATI { - NOT_NULL = 0, - AUTO_INC = 1, - BLOOM_FILTER = 2, - }; - - AttributeTypeInfo(common::CT attrt, bool notnull, uint precision = 0, ushort scale = 0, bool auto_inc = false, - DTCollation collation = DTCollation(), common::PackFmt fmt = common::PackFmt::DEFAULT, - bool filter = false) - : attrt(attrt), fmt(fmt), precision(precision), scale(scale), collation(collation) { - flag[static_cast(enumATI::NOT_NULL)] = notnull; - flag[static_cast(enumATI::BLOOM_FILTER)] = filter; - flag[static_cast(enumATI::AUTO_INC)] = auto_inc; - - // lookup only applies to string type - if (attrt != common::CT::STRING && attrt != common::CT::VARCHAR && Lookup()) - fmt = common::PackFmt::DEFAULT; - } - common::CT Type() const { return attrt; } - common::PackType GetPackType() const { - return ATI::IsDateTimeType(attrt) || ATI::IsNumericType(attrt) || Lookup() ? common::PackType::INT - : common::PackType::STR; - } - uint Precision() const { return precision; } - ushort Scale() const { return scale; } - uint CharLen() const { return precision / collation.collation->mbmaxlen; } - bool NotNull() const { return flag[static_cast(enumATI::NOT_NULL)]; } - bool AutoInc() const { return flag[static_cast(enumATI::AUTO_INC)]; } - void SetCollation(const DTCollation &collation) { this->collation = collation; } - void SetCollation(CHARSET_INFO *charset_info) { this->collation.set(charset_info); } - DTCollation GetCollation() const { return collation; } - CHARSET_INFO *CharsetInfo() const { return const_cast(this->collation.collation); } - const types::RCDataType &ValuePrototype() const; - common::PackFmt Fmt() const { return fmt; } - bool Lookup() const { return fmt == common::PackFmt::LOOKUP; } - unsigned char Flag() const { return flag.to_ulong(); } - void SetFlag(unsigned char v) { flag = std::bitset::digits>(v); } - - private: - common::CT attrt; - common::PackFmt fmt; - uint precision; - int scale; - DTCollation collation; - - std::bitset::digits> flag; -}; -} // namespace core -} // namespace Tianmu - -#endif // TIANMU_CORE_RC_ATTR_TYPEINFO_H_ diff --git a/storage/tianmu/handler/tianmu_handler.cpp b/storage/tianmu/handler/tianmu_handler.cpp deleted file mode 100644 index 5065a1848615e1c14f1a7b1afcd0250b4746fd7c..0000000000000000000000000000000000000000 --- a/storage/tianmu/handler/tianmu_handler.cpp +++ /dev/null @@ -1,1742 +0,0 @@ -/* Copyright (c) 2022 StoneAtom, Inc. All rights reserved. - Use is subject to license terms - - 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-1335 USA -*/ - -#include "tianmu_handler.h" - -#include - -#include "mysql/plugin.h" - -#include "common/assert.h" -#include "common/exception.h" -#include "core/compilation_tools.h" -#include "core/compiled_query.h" -#include "core/temp_table.h" -#include "core/tools.h" -#include "core/transaction.h" -#include "core/value.h" -#include "system/configuration.h" -#include "util/fs.h" - -#define MYSQL_SERVER 1 - -namespace Tianmu { -namespace dbhandler { - -const Alter_inplace_info::HA_ALTER_FLAGS TianmuHandler::TIANMU_SUPPORTED_ALTER_ADD_DROP_ORDER = - Alter_inplace_info::ADD_COLUMN | Alter_inplace_info::DROP_COLUMN | Alter_inplace_info::ALTER_STORED_COLUMN_ORDER; -const Alter_inplace_info::HA_ALTER_FLAGS TianmuHandler::TIANMU_SUPPORTED_ALTER_COLUMN_NAME = - Alter_inplace_info::ALTER_COLUMN_DEFAULT | Alter_inplace_info::ALTER_COLUMN_NAME; -///////////////////////////////////////////////////////////////////// -// -// NOTICE: ALL EXCEPTIONS SHOULD BE CAUGHT in the handler API!!! -// MySQL doesn't use exception. -// -///////////////////////////////////////////////////////////////////// - -/* - Example of simple lock controls. The "share" it creates is structure we will - pass to each rcbase handler. Do you have to have one of these? Well, you have - pieces that are used for locking, and they are needed to function. - */ - -my_bool rcbase_query_caching_of_table_permitted(THD *thd, [[maybe_unused]] char *full_name, - [[maybe_unused]] uint full_name_len, - [[maybe_unused]] ulonglong *unused) { - if (!thd_test_options(thd, (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) - return ((my_bool)TRUE); - return ((my_bool)FALSE); -} - -static core::Value GetValueFromField(Field *f) { - core::Value v; - - if (f->is_null()) - return v; - - switch (f->type()) { - case MYSQL_TYPE_TINY: - case MYSQL_TYPE_SHORT: - case MYSQL_TYPE_LONG: - case MYSQL_TYPE_INT24: - case MYSQL_TYPE_LONGLONG: - v.SetInt(f->val_int()); - break; - case MYSQL_TYPE_DECIMAL: - case MYSQL_TYPE_FLOAT: - case MYSQL_TYPE_DOUBLE: - v.SetDouble(f->val_real()); - break; - case MYSQL_TYPE_NEWDECIMAL: { - auto dec_f = dynamic_cast(f); - v.SetInt(std::lround(dec_f->val_real() * types::PowOfTen(dec_f->dec))); - break; - } - case MYSQL_TYPE_TIMESTAMP: { - MYSQL_TIME my_time; - std::memset(&my_time, 0, sizeof(my_time)); - f->get_time(&my_time); - // convert to UTC - if (!common::IsTimeStampZero(my_time)) { - my_bool myb; - my_time_t secs_utc = current_txn_->Thd()->variables.time_zone->TIME_to_gmt_sec(&my_time, &myb); - common::GMTSec2GMTTime(&my_time, secs_utc); - } - types::DT dt = {}; - dt.year = my_time.year; - dt.month = my_time.month; - dt.day = my_time.day; - dt.hour = my_time.hour; - dt.minute = my_time.minute; - dt.second = my_time.second; - v.SetInt(dt.val); - break; - } - case MYSQL_TYPE_TIME: - case MYSQL_TYPE_TIME2: - case MYSQL_TYPE_DATE: - case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_NEWDATE: - case MYSQL_TYPE_TIMESTAMP2: - case MYSQL_TYPE_DATETIME2: { - MYSQL_TIME my_time; - std::memset(&my_time, 0, sizeof(my_time)); - f->get_time(&my_time); - types::DT dt = {}; - dt.year = my_time.year; - dt.month = my_time.month; - dt.day = my_time.day; - dt.hour = my_time.hour; - dt.minute = my_time.minute; - dt.second = my_time.second; - v.SetInt(dt.val); - break; - } - case MYSQL_TYPE_YEAR: // what the hell? - { - types::DT dt = {}; - dt.year = f->val_int(); - v.SetInt(dt.val); - break; - } - case MYSQL_TYPE_VARCHAR: - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_VAR_STRING: - case MYSQL_TYPE_STRING: { - String str; - f->val_str(&str); - v.SetString(const_cast(str.ptr()), str.length()); - break; - } - case MYSQL_TYPE_SET: - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_GEOMETRY: - case MYSQL_TYPE_NULL: - case MYSQL_TYPE_BIT: - default: - throw common::Exception("unsupported mysql type " + std::to_string(f->type())); - break; - } - return v; -} - -TianmuHandler::TianmuHandler(handlerton *hton, TABLE_SHARE *table_arg) : handler(hton, table_arg) { - ref_length = sizeof(uint64_t); -} - -const char **TianmuHandler::bas_ext() const { - static const char *ha_rcbase_exts[] = {common::TIANMU_EXT, 0}; - return ha_rcbase_exts; -} - -namespace { -std::vector GetAttrsUseIndicator(TABLE *table) { - int col_id = 0; - std::vector attr_uses; - for (Field **field = table->field; *field; ++field, ++col_id) { - if (bitmap_is_set(table->read_set, col_id) || bitmap_is_set(table->write_set, col_id)) - attr_uses.push_back(true); - else - attr_uses.push_back(false); - } - return attr_uses; -} -} // namespace - -static bool is_delay_insert(THD *thd) { - return tianmu_sysvar_insert_delayed && - (thd_sql_command(thd) == SQLCOM_INSERT || thd_sql_command(thd) == SQLCOM_INSERT_SELECT) && - thd->lex->duplicates != DUP_UPDATE; -} - -/* - The idea with handler::store_lock() is the following: - - The statement decided which locks we should need for the table - for updates/deletes/inserts we get WRITE locks, for SELECT... we get - read locks. - - Before adding the lock into the table lock handler (see thr_lock.c) - mysqld calls store lock with the requested locks. Store lock can now - modify a write lock to a read lock (or some other lock), ignore the - lock (if we don't want to use MySQL table locks at all) or add locks - for many tables (like we do when we are using a MERGE handler). - - Berkeley DB for example changes all WRITE locks to TL_WRITE_ALLOW_WRITE - (which signals that we are doing WRITES, but we are still allowing other - reader's and writer's. - - When releasing locks, store_lock() are also called. In this case one - usually doesn't have to do anything. - - In some exceptional cases MySQL may send a request for a TL_IGNORE; - This means that we are requesting the same lock as last time and this - should also be ignored. (This may happen when someone does a flush - table when we have opened a part of the tables, in which case mysqld - closes and reopens the tables and tries to get the same locks at last - time). In the future we will probably try to remove this. - - Called from lock.cc by get_lock_data(). - */ -THR_LOCK_DATA **TianmuHandler::store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type) { - if (lock_type >= TL_WRITE_CONCURRENT_INSERT && lock_type <= TL_WRITE) { - if (is_delay_insert(thd)) - lock_type = TL_READ; - else - lock_type = TL_WRITE_CONCURRENT_INSERT; - } - - if (lock_type != TL_IGNORE && m_lock.type == TL_UNLOCK) - m_lock.type = lock_type; - *to++ = &m_lock; - return to; -} - -/* - First you should go read the section "locking functions for mysql" in - lock.cc to understand this. - This create a lock on the table. If you are implementing a storage engine - that can handle transacations look at ha_berkely.cc to see how you will - want to goo about doing this. Otherwise you should consider calling flock() - here. - - Called from lock.cc by lock_external() and unlock_external(). Also called - from sql_table.cc by copy_data_between_tables(). - */ -int TianmuHandler::external_lock(THD *thd, int lock_type) { - DBUG_ENTER(__PRETTY_FUNCTION__); - - int ret = 1; - - // static const char *ss[] = { "READ LOCK", "WRITE LOCK", "UNLOCK", }; - // rclog << lock << "external lock table " << m_table_name << " type: " << - // ss[lock_type] << " command: " << thd->lex->sql_command << unlock; - - if (thd->lex->sql_command == SQLCOM_LOCK_TABLES) - DBUG_RETURN(HA_ERR_WRONG_COMMAND); - - if (is_delay_insert(thd) && table_share->tmp_table == NO_TMP_TABLE && lock_type == F_WRLCK) { - DBUG_RETURN(0); - } - - try { - if (lock_type == F_UNLCK) { - if (thd->lex->sql_command == SQLCOM_UNLOCK_TABLES) - current_txn_->ExplicitUnlockTables(); - - if (thd->killed) - ha_rcengine_->Rollback(thd, true); - if (current_txn_) { - current_txn_->RemoveTable(share); - if (current_txn_->Empty()) { - ha_rcengine_->ClearTx(thd); - } - } - } else { - auto tx = ha_rcengine_->GetTx(thd); - if (thd->lex->sql_command == SQLCOM_LOCK_TABLES) - tx->ExplicitLockTables(); - - if (lock_type == F_RDLCK) { - tx->AddTableRD(share); - } else { - tx->AddTableWR(share); - trans_register_ha(thd, false, rcbase_hton, NULL); - if (thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) - trans_register_ha(thd, true, rcbase_hton, NULL); - } - } - ret = 0; - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), "Tianmu internal error", MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught: %s.", e.what()); - } catch (...) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), "An unknown system exception error caught.", MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An unknown system exception error caught."); - } - - // destroy the tx on failure - if (ret != 0) - ha_rcengine_->ClearTx(thd); - - DBUG_RETURN(ret); -} - -namespace { -inline bool has_dup_key(std::shared_ptr &indextab, TABLE *table, size_t &row) { - common::ErrorCode ret; - std::vector records; - KEY *key = table->key_info + table->s->primary_key; - - for (uint i = 0; i < key->actual_key_parts; i++) { - uint col = key->key_part[i].field->field_index; - Field *f = table->field[col]; - switch (f->type()) { - case MYSQL_TYPE_TINY: - case MYSQL_TYPE_SHORT: - case MYSQL_TYPE_LONG: - case MYSQL_TYPE_INT24: - case MYSQL_TYPE_LONGLONG: { - int64_t v = f->val_int(); - records.emplace_back((const char *)&v, sizeof(int64_t)); - break; - } - case MYSQL_TYPE_DECIMAL: - case MYSQL_TYPE_FLOAT: - case MYSQL_TYPE_DOUBLE: { - double v = f->val_real(); - records.emplace_back((const char *)&v, sizeof(double)); - break; - } - case MYSQL_TYPE_NEWDECIMAL: { - auto dec_f = dynamic_cast(f); - double v = std::lround(dec_f->val_real() * types::PowOfTen(dec_f->dec)); - records.emplace_back((const char *)&v, sizeof(double)); - break; - } - case MYSQL_TYPE_TIME: - case MYSQL_TYPE_TIME2: - case MYSQL_TYPE_DATE: - case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_NEWDATE: - case MYSQL_TYPE_TIMESTAMP2: - case MYSQL_TYPE_DATETIME2: { - MYSQL_TIME my_time; - std::memset(&my_time, 0, sizeof(my_time)); - f->get_time(&my_time); - types::DT dt(my_time); - records.emplace_back((const char *)&dt.val, sizeof(int64_t)); - break; - } - - case MYSQL_TYPE_TIMESTAMP: { - MYSQL_TIME my_time; - std::memset(&my_time, 0, sizeof(my_time)); - f->get_time(&my_time); - auto saved = my_time.second_part; - // convert to UTC - if (!common::IsTimeStampZero(my_time)) { - my_bool myb; - my_time_t secs_utc = current_thd->variables.time_zone->TIME_to_gmt_sec(&my_time, &myb); - common::GMTSec2GMTTime(&my_time, secs_utc); - } - my_time.second_part = saved; - types::DT dt(my_time); - records.emplace_back((const char *)&dt.val, sizeof(int64_t)); - break; - } - case MYSQL_TYPE_YEAR: // what the hell? - { - types::DT dt = {}; - dt.year = f->val_int(); - records.emplace_back((const char *)&dt.val, sizeof(int64_t)); - break; - } - case MYSQL_TYPE_VARCHAR: - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_VAR_STRING: - case MYSQL_TYPE_STRING: { - String str; - f->val_str(&str); - records.emplace_back(str.ptr(), str.length()); - break; - } - case MYSQL_TYPE_SET: - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_GEOMETRY: - case MYSQL_TYPE_NULL: - case MYSQL_TYPE_BIT: - default: - throw common::Exception("unsupported mysql type " + std::to_string(f->type())); - break; - } - } - - ret = indextab->GetRowByKey(current_txn_, records, row); - return (ret == common::ErrorCode::SUCCESS); -} -} // namespace - -/* - write_row() inserts a row. No extra() hint is given currently if a bulk load - is happeneding. buf() is a byte array of data. You can use the field - information to extract the data from the native byte array type. - Example of this would be: - for (Field **field=table->field ; *field ; field++) - { - ... - } - - See ha_tina.cc for an example of extracting all of the data as strings. - ha_berekly.cc has an example of how to store it intact by "packing" it - for ha_berkeley's own native storage type. - - See the note for update_row() on auto_increments and timestamps. This - case also applied to write_row(). - - Called from item_sum.cc, item_sum.cc, sql_acl.cc, sql_insert.cc, - sql_insert.cc, sql_select.cc, sql_table.cc, sql_udf.cc, and sql_update.cc. - */ -int TianmuHandler::write_row([[maybe_unused]] uchar *buf) { - int ret = 1; - DBUG_ENTER(__PRETTY_FUNCTION__); - try { - if (ha_thd()->lex->duplicates == DUP_UPDATE) { - if (auto indextab = ha_rcengine_->GetTableIndex(m_table_name)) { - if (size_t row; has_dup_key(indextab, table, row)) { - m_dupkey_pos = row; - DBUG_RETURN(HA_ERR_FOUND_DUPP_KEY); - } - } - } - ret = ha_rcengine_->InsertRow(m_table_name, current_txn_, table, share); - } catch (common::OutOfMemoryException &e) { - DBUG_RETURN(ER_LOCK_WAIT_TIMEOUT); - } catch (common::DatabaseException &e) { - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught in Engine::InsertRow: %s.", e.what()); - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - } catch (common::FormatException &e) { - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught in Engine::InsertRow: %s Row: %ld, field %u.", e.what(), - e.m_row_no, e.m_field_no); - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - } catch (common::FileException &e) { - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught in Engine::InsertRow: %s.", e.what()); - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - } catch (common::Exception &e) { - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught in Engine::InsertRow: %s.", e.what()); - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught in Engine::InsertRow: %s.", e.what()); - } catch (...) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), "An unknown system exception error caught.", MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An unknown system exception error caught."); - } - DBUG_RETURN(ret); -} - -/* - Yes, update_row() does what you expect, it updates a row. old_data will have - the previous row record in it, while new_data will have the newest data in - it. - Keep in mind that the server can do updates based on ordering if an ORDER BY - clause was used. Consecutive ordering is not guarenteed. - Currently new_data will not have an updated auto_increament record, or - and updated timestamp field. You can do these for example by doing these: - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) - table->timestamp_field->set_time(); - if (table->next_number_field && record == table->record[0]) - update_auto_increment(); - - Called from sql_select.cc, sql_acl.cc, sql_update.cc, and sql_insert.cc. - */ -int TianmuHandler::update_row(const uchar *old_data, uchar *new_data) { - DBUG_ENTER(__PRETTY_FUNCTION__); - int ret = HA_ERR_INTERNAL_ERROR; - auto org_bitmap = dbug_tmp_use_all_columns(table, table->write_set); - - std::shared_ptr defer(nullptr, - [org_bitmap, this](...) { dbug_tmp_restore_column_map(table->write_set, org_bitmap); }); - - try { - auto tab = current_txn_->GetTableByPath(m_table_name); - - for (uint i = 0; i < table->s->fields; i++) { - if (!bitmap_is_set(table->write_set, i)) { - continue; - } - auto field = table->field[i]; - if (field->real_maybe_null()) { - if (field->is_null_in_record(old_data) && field->is_null_in_record(new_data)) { - continue; - } - - if (field->is_null_in_record(new_data)) { - core::Value null; - tab->UpdateItem(current_position, i, null); - continue; - } - } - auto o_ptr = field->ptr - table->record[0] + old_data; - auto n_ptr = field->ptr - table->record[0] + new_data; - if (field->is_null_in_record(old_data) || std::memcmp(o_ptr, n_ptr, field->pack_length()) != 0) { - my_bitmap_map *org_bitmap2 = dbug_tmp_use_all_columns(table, table->read_set); - std::shared_ptr defer( - nullptr, [org_bitmap2, this](...) { dbug_tmp_restore_column_map(table->read_set, org_bitmap2); }); - core::Value v = GetValueFromField(field); - tab->UpdateItem(current_position, i, v); - } - } - ha_rcengine_->IncTianmuStatUpdate(); - DBUG_RETURN(0); - } catch (common::DatabaseException &e) { - TIANMU_LOG(LogCtl_Level::ERROR, "Update exception: %s.", e.what()); - } catch (common::FileException &e) { - TIANMU_LOG(LogCtl_Level::ERROR, "Update exception: %s.", e.what()); - } catch (common::DupKeyException &e) { - ret = HA_ERR_FOUND_DUPP_KEY; - TIANMU_LOG(LogCtl_Level::ERROR, "Update exception: %s.", e.what()); - } catch (common::Exception &e) { - TIANMU_LOG(LogCtl_Level::ERROR, "Update exception: %s.", e.what()); - } catch (std::exception &e) { - TIANMU_LOG(LogCtl_Level::ERROR, "Update exception: %s.", e.what()); - } catch (...) { - TIANMU_LOG(LogCtl_Level::ERROR, "An unknown system exception error caught."); - } - DBUG_RETURN(ret); -} - -/* - This will delete a row. buf will contain a copy of the row to be deleted. - The server will call this right after the current row has been called (from - either a previous rnd_nexT() or index call). - If you keep a pointer to the last row or can access a primary key it will - make doing the deletion quite a bit easier. - Keep in mind that the server does no guarentee consecutive deletions. ORDER BY - clauses can be used. - - Called in sql_acl.cc and sql_udf.cc to manage internal table information. - Called in sql_delete.cc, sql_insert.cc, and sql_select.cc. In sql_select it is - used for removing duplicates while in insert it is used for REPLACE calls. - */ -int TianmuHandler::delete_row([[maybe_unused]] const uchar *buf) { - DBUG_ENTER(__PRETTY_FUNCTION__); - int ret = HA_ERR_INTERNAL_ERROR; - auto org_bitmap = dbug_tmp_use_all_columns(table, table->write_set); - - std::shared_ptr defer(nullptr, - [org_bitmap, this](...) { dbug_tmp_restore_column_map(table->write_set, org_bitmap); }); - - try { - auto tab = current_txn_->GetTableByPath(m_table_name); - - for (uint i = 0; i < table->s->fields; i++) { - tab->DeleteItem(current_position, i); - } - DBUG_RETURN(0); - } catch (common::DatabaseException &e) { - TIANMU_LOG(LogCtl_Level::ERROR, "Delete exception: %s.", e.what()); - } catch (common::FileException &e) { - TIANMU_LOG(LogCtl_Level::ERROR, "Delete exception: %s.", e.what()); - } catch (common::Exception &e) { - TIANMU_LOG(LogCtl_Level::ERROR, "Delete exception: %s.", e.what()); - } catch (std::exception &e) { - TIANMU_LOG(LogCtl_Level::ERROR, "Delete exception: %s.", e.what()); - } catch (...) { - TIANMU_LOG(LogCtl_Level::ERROR, "An unknown system exception error caught."); - } - DBUG_RETURN(ret); -} -/* - Used to delete all rows in a table. Both for cases of truncate and - for cases where the optimizer realizes that all rows will be - removed as a result of a SQL statement. - - Called from item_sum.cc by Item_func_group_concat::clear(), - Item_sum_count_distinct::clear(), and Item_func_group_concat::clear(). - Called from sql_delete.cc by mysql_delete(). - Called from sql_select.cc by JOIN::rein*it. - Called from sql_union.cc by st_select_lex_unit::exec(). - */ -int TianmuHandler::delete_all_rows() { - DBUG_ENTER(__PRETTY_FUNCTION__); - int ret = 1; - try { - ha_rcengine_->TruncateTable(m_table_name, ha_thd()); - ret = 0; - } catch (std::exception &e) { - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught: %s", e.what()); - } catch (...) { - TIANMU_LOG(LogCtl_Level::ERROR, "An unknown system exception error caught."); - } - DBUG_RETURN(ret); -} - -int TianmuHandler::rename_table(const char *from, const char *to) { - try { - ha_rcengine_->RenameTable(current_txn_, from, to, ha_thd()); - return 0; - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught: %s", e.what()); - } catch (...) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), "An unknown system exception error caught.", MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An unknown system exception error caught."); - } - return 1; -} - -void TianmuHandler::update_create_info([[maybe_unused]] HA_CREATE_INFO *create_info) {} - -/* - ::info() is used to return information to the optimizer. - see my_base.h for the complete description - - Currently this table handler doesn't implement most of the fields - really needed. SHOW also makes use of this data - Another note, you will probably want to have the following in your - code: - if (records < 2) - records = 2; - The reason is that the server will optimize for cases of only a single - record. If in a table scan you don't know the number of records - it will probably be better to set records to two so you can return - as many records as you need. - Along with records a few more variables you may wish to set are: - records - deleted - data_file_length - index_file_length - delete_length - check_time - Take a look at the public variables in handler.h for more information. - - Called in: - filesort.cc - ha_heap.cc - item_sum.cc - opt_sum.cc - sql_delete.cc - sql_delete.cc - sql_derived.cc - sql_select.cc - sql_select.cc - sql_select.cc - sql_select.cc - sql_select.cc - sql_show.cc - sql_show.cc - sql_show.cc - sql_show.cc - sql_table.cc - sql_union.cc - sql_update.cc - - */ -int TianmuHandler::info(uint flag) { - DBUG_ENTER(__PRETTY_FUNCTION__); - int ret = 1; - try { - std::scoped_lock guard(global_mutex_); - if (flag & HA_STATUS_VARIABLE) { - std::shared_ptr tab; - if (current_txn_ != nullptr) { - tab = current_txn_->GetTableByPath(m_table_name); - } else - tab = ha_rcengine_->GetTableRD(m_table_name); - stats.records = (ha_rows)(tab->NumOfValues() - tab->NumOfDeleted()); - stats.data_file_length = 0; - stats.mean_rec_length = 0; - if (stats.records > 0) { - std::vector attr_info(tab->GetAttributesInfo()); - uint no_attrs = tab->NumOfAttrs(); - for (uint j = 0; j < no_attrs; j++) stats.data_file_length += attr_info[j].comp_size; // compressed size - stats.mean_rec_length = ulong(stats.data_file_length / stats.records); - } - } - - if (flag & HA_STATUS_CONST) - stats.create_time = share->GetCreateTime(); - - if (flag & HA_STATUS_TIME) - stats.update_time = share->GetUpdateTime(); - - if (flag & HA_STATUS_ERRKEY) { - errkey = 0; // TODO: for now only support one pk index - my_store_ptr(dup_ref, ref_length, m_dupkey_pos); - } - - ret = 0; - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught: %s", e.what()); - } catch (...) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), "An unknown system exception error caught.", MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An unknown system exception error caught."); - } - - DBUG_RETURN(ret); -} - -/* this should return 0 for concurrent insert to work */ -my_bool tianmu_check_status([[maybe_unused]] void *param) { return 0; } - -/* - Used for opening tables. The name will be the name of the file. - A table is opened when it needs to be opened. For instance - when a request comes in for a select on the table (tables are not - open and closed for each request, they are cached). - - Called from handler.cc by handler::ha_open(). The server opens all tables by - calling ha_open() which then calls the handler specific open(). - */ -int TianmuHandler::open(const char *name, [[maybe_unused]] int mode, [[maybe_unused]] uint test_if_locked) { - DBUG_ENTER(__PRETTY_FUNCTION__); - - m_table_name = name; - int ret = 1; - - try { - // TODO: - // Probably we don't need to search from the map each time. - // Keeping the share together with mysql handler cache makes - // more sense that would mean once a table is opened the TableShare - // would be kept. - if (!(share = ha_rcengine_->GetTableShare(table_share))) - DBUG_RETURN(ret); - - thr_lock_data_init(&share->thr_lock, &m_lock, NULL); - share->thr_lock.check_status = tianmu_check_status; - // have primary key, use table index - if (table->s->primary_key != MAX_INDEXES) - ha_rcengine_->AddTableIndex(name, table, ha_thd()); - ha_rcengine_->AddMemTable(table, share); - ret = 0; - } catch (common::Exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), "Error from Tianmu engine", MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "A tianmu exception is caught: %s", e.what()); - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught: %s", e.what()); - } catch (...) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), "An unknown system exception error caught.", MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An unknown system exception error caught."); - } - - info(HA_STATUS_CONST); - - DBUG_RETURN(ret); -} - -int TianmuHandler::free_share() { - share.reset(); - return 0; -} - -/* - Closes a table. We call the free_share() function to free any resources - that we have allocated in the "shared" structure. - - Called from sql_base.cc, sql_select.cc, and table.cc. - In sql_select.cc it is only used to close up temporary tables or during - the process where a temporary table is converted over to being a - myisam table. - For sql_base.cc look at close_data_tables(). - */ -int TianmuHandler::close() { - DBUG_ENTER(__PRETTY_FUNCTION__); - DBUG_RETURN(free_share()); -} - -int TianmuHandler::fill_row_by_id([[maybe_unused]] uchar *buf, uint64_t rowid) { - DBUG_ENTER(__PRETTY_FUNCTION__); - int rc = HA_ERR_KEY_NOT_FOUND; - try { - auto tab = current_txn_->GetTableByPath(m_table_name); - if (tab) { - my_bitmap_map *org_bitmap = dbug_tmp_use_all_columns(table, table->write_set); - std::shared_ptr defer( - nullptr, [org_bitmap, this](...) { dbug_tmp_restore_column_map(table->write_set, org_bitmap); }); - - tab->FillRowByRowid(table, rowid); - current_position = rowid; - rc = 0; - } - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught: %s", e.what()); - } - DBUG_RETURN(rc); -} - -int TianmuHandler::index_init(uint index, [[maybe_unused]] bool sorted) { - DBUG_ENTER(__PRETTY_FUNCTION__); - active_index = index; - DBUG_RETURN(0); -} - -int TianmuHandler::index_end() { - DBUG_ENTER(__PRETTY_FUNCTION__); - active_index = MAX_KEY; - DBUG_RETURN(0); -} - -/* - Positions an index cursor to the index specified in the handle. Fetches the - row if available. If the key value is null, begin at the first key of the - index. - */ -int TianmuHandler::index_read([[maybe_unused]] uchar *buf, [[maybe_unused]] const uchar *key, - [[maybe_unused]] uint key_len __attribute__((unused)), - enum ha_rkey_function find_flag __attribute__((unused))) { - DBUG_ENTER(__PRETTY_FUNCTION__); - int rc = HA_ERR_KEY_NOT_FOUND; - try { - auto index = ha_rcengine_->GetTableIndex(m_table_name); - if (index && (active_index == table_share->primary_key)) { - std::vector keys; - key_convert(key, key_len, index->KeyCols(), keys); - // support equality fullkey lookup over primary key, using full tuple - if (find_flag == HA_READ_KEY_EXACT) { - uint64_t rowid; - if (index->GetRowByKey(current_txn_, keys, rowid) == common::ErrorCode::SUCCESS) { - rc = fill_row_by_id(buf, rowid); - } - } else if (find_flag == HA_READ_AFTER_KEY || find_flag == HA_READ_KEY_OR_NEXT) { - auto iter = current_txn_->KVTrans().KeyIter(); - common::Operator op = (find_flag == HA_READ_AFTER_KEY) ? common::Operator::O_MORE : common::Operator::O_MORE_EQ; - iter->ScanToKey(index, keys, op); - uint64_t rowid; - iter->GetRowid(rowid); - rc = fill_row_by_id(buf, rowid); - - } else { - // not support HA_READ_PREFIX_LAST_OR_PREV HA_READ_PREFIX_LAST - rc = HA_ERR_WRONG_COMMAND; - TIANMU_LOG(LogCtl_Level::ERROR, "Error: index_read not support prefix search"); - } - - } else { - // other index not support - rc = HA_ERR_WRONG_INDEX; - TIANMU_LOG(LogCtl_Level::ERROR, "Error: index_read only support primary key"); - } - - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught: %s", e.what()); - } - - DBUG_RETURN(rc); -} - -/* - Used to read forward through the index. - */ -int TianmuHandler::index_next([[maybe_unused]] uchar *buf) { - DBUG_ENTER(__PRETTY_FUNCTION__); - int rc = HA_ERR_END_OF_FILE; - try { - auto iter = current_txn_->KVTrans().KeyIter(); - ++(*iter); - if (iter->IsValid()) { - uint64_t rowid; - iter->GetRowid(rowid); - rc = fill_row_by_id(buf, rowid); - } else { - rc = HA_ERR_KEY_NOT_FOUND; - } - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught: %s", e.what()); - } - DBUG_RETURN(rc); -} - -/* - Used to read backwards through the index. - */ -int TianmuHandler::index_prev([[maybe_unused]] uchar *buf) { - DBUG_ENTER(__PRETTY_FUNCTION__); - int rc = HA_ERR_END_OF_FILE; - try { - auto iter = current_txn_->KVTrans().KeyIter(); - --(*iter); - if (iter->IsValid()) { - uint64_t rowid; - iter->GetRowid(rowid); - rc = fill_row_by_id(buf, rowid); - } else { - rc = HA_ERR_KEY_NOT_FOUND; - } - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught: %s", e.what()); - } - DBUG_RETURN(rc); -} - -/* - index_first() asks for the first key in the index. - - Called from opt_range.cc, opt_sum.cc, sql_handler.cc, - and sql_select.cc. - */ -int TianmuHandler::index_first([[maybe_unused]] uchar *buf) { - DBUG_ENTER(__PRETTY_FUNCTION__); - int rc = HA_ERR_END_OF_FILE; - try { - auto index = ha_rcengine_->GetTableIndex(m_table_name); - if (index && current_txn_) { - uint64_t rowid; - auto iter = current_txn_->KVTrans().KeyIter(); - iter->ScanToEdge(index, true); - if (iter->IsValid()) { - iter->GetRowid(rowid); - rc = fill_row_by_id(buf, rowid); - } else { - rc = HA_ERR_KEY_NOT_FOUND; - } - } - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught: %s", e.what()); - } - DBUG_RETURN(rc); -} - -/* - index_last() asks for the last key in the index. - - Called from opt_range.cc, opt_sum.cc, sql_handler.cc, - and sql_select.cc. - */ -int TianmuHandler::index_last([[maybe_unused]] uchar *buf) { - DBUG_ENTER(__PRETTY_FUNCTION__); - int rc = HA_ERR_END_OF_FILE; - try { - auto index = ha_rcengine_->GetTableIndex(m_table_name); - if (index && current_txn_) { - uint64_t rowid; - auto iter = current_txn_->KVTrans().KeyIter(); - iter->ScanToEdge(index, false); - if (iter->IsValid()) { - iter->GetRowid(rowid); - rc = fill_row_by_id(buf, rowid); - } else { - rc = HA_ERR_KEY_NOT_FOUND; - } - } - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught: %s", e.what()); - } - DBUG_RETURN(rc); -} - -/* - rnd_init() is called when the system wants the storage engine to do a table - scan. - See the example in the introduction at the top of this file to see when - rnd_init() is called. - - Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc, - sql_table.cc, and sql_update.cc. - */ -int TianmuHandler::rnd_init(bool scan) { - DBUG_ENTER(__PRETTY_FUNCTION__); - - int ret = 1; - try { - if (m_query && !m_result && table_ptr->NumOfObj() != 0) { - m_cq->Result(m_tmp_table); // it is ALWAYS -2 though.... - m_result = true; - - try { - core::FunctionExecutor fe(std::bind(&core::Query::LockPackInfoForUse, std::ref(m_query)), - std::bind(&core::Query::UnlockPackInfoFromUse, std::ref(m_query))); - - core::TempTable *push_down_result = m_query->Preexecute(*m_cq, NULL, false); - if (!push_down_result || push_down_result->NumOfTables() != 1) - throw common::InternalException("core::Query execution returned no result object"); - - core::Filter *filter(push_down_result->GetMultiIndexP()->GetFilter(0)); - if (!filter) - filter_ptr.reset( - new core::Filter(push_down_result->GetMultiIndexP()->OrigSize(0), table_ptr->Getpackpower())); - else - filter_ptr.reset(new core::Filter(*filter)); - - table_ptr = push_down_result->GetTableP(0); - table_new_iter = ((core::RCTable *)table_ptr)->Begin(GetAttrsUseIndicator(table), *filter); - table_new_iter_end = ((core::RCTable *)table_ptr)->End(); - } catch (common::Exception const &e) { - rc_control_ << system::lock << "Error in push-down execution, push-down execution aborted: " << e.what() - << system::unlock; - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught in push-down execution: %s", e.what()); - } - m_query.reset(); - m_cq.reset(); - } else { - if (scan && filter_ptr.get()) { - table_new_iter = ((core::RCTable *)table_ptr)->Begin(GetAttrsUseIndicator(table), *filter_ptr); - table_new_iter_end = ((core::RCTable *)table_ptr)->End(); - } else { - std::shared_ptr rctp; - ha_rcengine_->GetTableIterator(m_table_name, table_new_iter, table_new_iter_end, rctp, - GetAttrsUseIndicator(table), table->in_use); - table_ptr = rctp.get(); - filter_ptr.reset(); - } - } - ret = 0; - blob_buffers.resize(0); - if (table_ptr != NULL) - blob_buffers.resize(table_ptr->NumOfDisplaybleAttrs()); - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught: %s", e.what()); - } catch (...) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), "An unknown system exception error caught.", MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An unknown system exception error caught."); - } - - DBUG_RETURN(ret); -} - -int TianmuHandler::rnd_end() { - DBUG_ENTER(__PRETTY_FUNCTION__); - reset(); - DBUG_RETURN(0); -} - -/* - This is called for each row of the table scan. When you run out of records - you should return HA_ERR_END_OF_FILE. Fill buff up with the row information. - The Field structure for the table is the key to getting data into buf - in a manner that will allow the server to understand it. - - Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc, - sql_table.cc, and sql_update.cc. - */ -int TianmuHandler::rnd_next(uchar *buf) { - DBUG_ENTER(__PRETTY_FUNCTION__); - - int ret = HA_ERR_END_OF_FILE; - try { - table->status = 0; - if (fill_row(buf) == HA_ERR_END_OF_FILE) { - table->status = STATUS_NOT_FOUND; - DBUG_RETURN(ret); - } - ret = 0; - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught: %s", e.what()); - } catch (...) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), "An unknown system exception error caught.", MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An unknown system exception error caught."); - } - - DBUG_RETURN(ret); -} - -/* - position() is called after each call to rnd_next() if the data needs - to be ordered. You can do something like the following to store - the position: - my_store_ptr(ref, ref_length, current_position); - - The server uses ref to store data. ref_length in the above case is - the size needed to store current_position. ref is just a byte array - that the server will maintain. If you are using offsets to mark rows, then - current_position should be the offset. If it is a primary key like in - BDB, then it needs to be a primary key. - - Called from filesort.cc, sql_select.cc, sql_delete.cc and sql_update.cc. - */ -void TianmuHandler::position([[maybe_unused]] const uchar *record) { - DBUG_ENTER(__PRETTY_FUNCTION__); - - my_store_ptr(ref, ref_length, current_position); - - DBUG_VOID_RETURN; -} - -/* - This is like rnd_next, but you are given a position to use - to determine the row. The position will be of the type that you stored in - ref. You can use ha_get_ptr(pos,ref_length) to retrieve whatever key - or position you saved when position() was called. - Called from filesort.cc records.cc sql_insert.cc sql_select.cc sql_update.cc. - */ -int TianmuHandler::rnd_pos(uchar *buf, uchar *pos) { - DBUG_ENTER(__PRETTY_FUNCTION__); - - int ret = HA_ERR_END_OF_FILE; - try { - uint64_t position = my_get_ptr(pos, ref_length); - - filter_ptr = std::make_unique(position + 1, share->PackSizeShift()); - filter_ptr->Reset(); - filter_ptr->Set(position); - - auto tab_ptr = ha_rcengine_->GetTx(table->in_use)->GetTableByPath(m_table_name); - table_new_iter = tab_ptr->Begin(GetAttrsUseIndicator(table), *filter_ptr); - table_new_iter_end = tab_ptr->End(); - table_ptr = tab_ptr.get(); - - table_new_iter.MoveToRow(position); - table->status = 0; - blob_buffers.resize(table->s->fields); - if (fill_row(buf) == HA_ERR_END_OF_FILE) { - table->status = STATUS_NOT_FOUND; - DBUG_RETURN(ret); - } - ret = 0; - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught: %s", e.what()); - } catch (...) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), "An unknown system exception error caught.", MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An unknown system exception error caught."); - } - - DBUG_RETURN(ret); -} - -/* - extra() is called whenever the server wishes to send a hint to - the storage engine. The myisam engine implements the most hints. - ha_innodb.cc has the most exhaustive list of these hints. - */ -int TianmuHandler::extra(enum ha_extra_function operation) { - DBUG_ENTER(__PRETTY_FUNCTION__); - /* This preemptive delete might cause problems here. - * Other place where it can be put is TianmuHandler::external_lock(). - */ - if (operation == HA_EXTRA_NO_CACHE) { - m_cq.reset(); - m_query.reset(); - } - DBUG_RETURN(0); -} - -int TianmuHandler::start_stmt(THD *thd, thr_lock_type lock_type) { - try { - if (lock_type == TL_WRITE_CONCURRENT_INSERT || lock_type == TL_WRITE_DEFAULT || lock_type == TL_WRITE) { - trans_register_ha(thd, false, rcbase_hton, NULL); - if (thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { - trans_register_ha(thd, true, rcbase_hton, NULL); - } - current_txn_ = ha_rcengine_->GetTx(thd); - current_txn_->AddTableWRIfNeeded(share); - } - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught: %s", e.what()); - } catch (...) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), "An unknown system exception error caught.", MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An unknown system exception error caught."); - } - return 0; -} - -/* - Ask rcbase handler about permission to cache table during query registration. - If current thread is in non-autocommit, we don't permit any mysql query - caching. - */ -my_bool TianmuHandler::register_query_cache_table(THD *thd, char *table_key, size_t key_length, - qc_engine_callback *call_back, - [[maybe_unused]] ulonglong *engine_data) { - *call_back = rcbase_query_caching_of_table_permitted; - return rcbase_query_caching_of_table_permitted(thd, table_key, key_length, 0); -} - -/* - Used to delete a table. By the time delete_table() has been called all - opened references to this table will have been closed (and your globally - shared references released. The variable name will just be the name of - the table. You will need to remove any files you have created at this point. - - If you do not implement this, the default delete_table() is called from - handler.cc and it will delete all files with the file extentions returned - by bas_ext(). - - Called from handler.cc by delete_table and ha_create_table(). Only used - during create if the table_flag HA_DROP_BEFORE_CREATE was specified for - the storage engine. - */ -int TianmuHandler::delete_table(const char *name) { - DBUG_ENTER(__PRETTY_FUNCTION__); - int ret = 1; - try { - ha_rcengine_->DeleteTable(name, ha_thd()); - ret = 0; - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught: %s", e.what()); - } catch (...) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), "An unknown system exception error caught.", MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An unknown system exception error caught."); - } - - DBUG_RETURN(ret); -} - -/* - Given a starting key, and an ending key estimate the number of rows that - will exist between the two. end_key may be empty which in case determine - if start_key matches any rows. - - Called from opt_range.cc by check_quick_keys(). - */ -ha_rows TianmuHandler::records_in_range([[maybe_unused]] uint inx, [[maybe_unused]] key_range *min_key, - [[maybe_unused]] key_range *max_key) { - DBUG_ENTER(__PRETTY_FUNCTION__); - DBUG_RETURN(stats.records); // low number to force index usage -} - -/* - create() is called to create a database. The variable name will have the name - of the table. When create() is called you do not need to worry about opening - the table. Also, the FRM file will have already been created so adjusting - create_info will not do you any good. You can overwrite the frm file at this - point if you wish to change the table definition, but there are no methods - currently provided for doing that. - - Called from handle.cc by ha_create_table(). - */ -int TianmuHandler::create(const char *name, TABLE *table_arg, [[maybe_unused]] HA_CREATE_INFO *create_info) { - DBUG_ENTER(__PRETTY_FUNCTION__); - try { - // fix issue 487: bug for create table #mysql50#q.q should return failure and actually return success - const size_t table_name_len = strlen(name); - if (name[table_name_len - 1] == '/') { - TIANMU_LOG(LogCtl_Level::ERROR, "Table name is empty"); - DBUG_RETURN(ER_WRONG_TABLE_NAME); - } - - ha_rcengine_->CreateTable(name, table_arg); - DBUG_RETURN(0); - } catch (common::AutoIncException &e) { - my_message(ER_WRONG_AUTO_KEY, e.what(), MYF(0)); - } catch (common::UnsupportedDataTypeException &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - } catch (fs::filesystem_error &e) { - TIANMU_LOG(LogCtl_Level::ERROR, "filesystem_error on table creation '%s'", e.what()); - fs::remove_all(std::string(name) + common::TIANMU_EXT); - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught: %s", e.what()); - } catch (...) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), "An unknown system exception error caught.", MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An unknown system exception error caught."); - } - - DBUG_RETURN(1); -} - -int TianmuHandler::truncate() { - DBUG_ENTER(__PRETTY_FUNCTION__); - int ret = 1; - try { - ha_rcengine_->TruncateTable(m_table_name, ha_thd()); - ret = 0; - } catch (std::exception &e) { - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught: %s", e.what()); - } catch (...) { - TIANMU_LOG(LogCtl_Level::ERROR, "An unknown system exception error caught."); - } - DBUG_RETURN(ret); -} - -uint TianmuHandler::max_supported_key_part_length(HA_CREATE_INFO *create_info) const { - if (tianmu_sysvar_large_prefix) - return (Tianmu::common::TIANMU_MAX_INDEX_COL_LEN_LARGE); - else - return (Tianmu::common::TIANMU_MAX_INDEX_COL_LEN_SMALL); -} - -int TianmuHandler::fill_row(uchar *buf) { - if (table_new_iter == table_new_iter_end) - return HA_ERR_END_OF_FILE; - - my_bitmap_map *org_bitmap = dbug_tmp_use_all_columns(table, table->write_set); - - std::shared_ptr buffer; - - // we should pack the row into `buf` but seems it just use record[0] blindly. - // So this is a workaround to handle the case that `buf` is not record[0]. - if (buf != table->record[0]) { - buffer.reset(new char[table->s->reclength]); - std::memcpy(buffer.get(), table->record[0], table->s->reclength); - } - - for (uint col_id = 0; col_id < table->s->fields; col_id++) - core::Engine::ConvertToField(table->field[col_id], *(table_new_iter.GetData(col_id)), &blob_buffers[col_id]); - - if (buf != table->record[0]) { - std::memcpy(buf, table->record[0], table->s->reclength); - std::memcpy(table->record[0], buffer.get(), table->s->reclength); - } - - current_position = table_new_iter.GetCurrentRowId(); - table_new_iter++; - - dbug_tmp_restore_column_map(table->write_set, org_bitmap); - - return 0; -} - -char *TianmuHandler::update_table_comment(const char *comment) { - char *ret = const_cast(comment); - try { - uint length = (uint)std::strlen(comment); - char *str = NULL; - uint extra_len = 0; - - if (length > 64000 - 3) { - return ((char *)comment); // string too long - } - - // get size & ratio - int64_t sum_c = 0, sum_u = 0; - std::vector attr_info = ha_rcengine_->GetTableAttributesInfo(m_table_name, table_share); - for (uint j = 0; j < attr_info.size(); j++) { - sum_c += attr_info[j].comp_size; - sum_u += attr_info[j].uncomp_size; - } - char buf[256]; - double ratio = (sum_c > 0 ? double(sum_u) / double(sum_c) : 0); - int count = std::sprintf(buf, "Overall compression ratio: %.3f, Raw size=%ld MB", ratio, sum_u >> 20); - extra_len += count; - - str = (char *)my_malloc(PSI_NOT_INSTRUMENTED, length + extra_len + 3, MYF(0)); - if (str) { - char *pos = str + length; - if (length) { - std::memcpy(str, comment, length); - *pos++ = ';'; - *pos++ = ' '; - } - - std::memcpy(pos, buf, extra_len); - pos[extra_len] = 0; - } - ret = str; - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught: %s", e.what()); - } catch (...) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), "An unknown system exception error caught.", MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An unknown system exception error caught."); - } - - return ret; -} - -bool TianmuHandler::explain_message(const Item *a_cond, String *buf) { - DBUG_ENTER(__PRETTY_FUNCTION__); - if (current_txn_->Explain()) { - cond_push(a_cond); - std::string str = current_txn_->GetExplainMsg(); - buf->append(str.c_str(), str.length()); - } - DBUG_RETURN(TRUE); -} - -int TianmuHandler::set_cond_iter() { - int ret = 1; - if (m_query && !m_result && table_ptr->NumOfObj() != 0) { - m_cq->Result(m_tmp_table); // it is ALWAYS -2 though.... - m_result = true; - - try { - core::FunctionExecutor fe(std::bind(&core::Query::LockPackInfoForUse, std::ref(m_query)), - std::bind(&core::Query::UnlockPackInfoFromUse, std::ref(m_query))); - - core::TempTable *push_down_result = m_query->Preexecute(*m_cq, NULL, false); - if (!push_down_result || push_down_result->NumOfTables() != 1) - throw common::InternalException("core::Query execution returned no result object"); - - core::Filter *filter(push_down_result->GetMultiIndexP()->GetFilter(0)); - if (!filter) - filter_ptr.reset(new core::Filter(push_down_result->GetMultiIndexP()->OrigSize(0), table_ptr->Getpackpower())); - else - filter_ptr.reset(new core::Filter(*filter)); - - table_ptr = push_down_result->GetTableP(0); - table_new_iter = ((core::RCTable *)table_ptr)->Begin(GetAttrsUseIndicator(table), *filter_ptr); - table_new_iter_end = ((core::RCTable *)table_ptr)->End(); - ret = 0; - } catch (common::Exception const &e) { - rc_control_ << system::lock << "Error in push-down execution, push-down execution aborted: " << e.what() - << system::unlock; - TIANMU_LOG(LogCtl_Level::ERROR, "Error in push-down execution, push-down execution aborted: %s", e.what()); - } - m_query.reset(); - m_cq.reset(); - } - return ret; -} - -const Item *TianmuHandler::cond_push(const Item *a_cond) { - Item const *ret = a_cond; - Item *cond = const_cast(a_cond); - - try { - if (!m_query) { - std::shared_ptr rctp; - ha_rcengine_->GetTableIterator(m_table_name, table_new_iter, table_new_iter_end, rctp, - GetAttrsUseIndicator(table), table->in_use); - table_ptr = rctp.get(); - m_query.reset(new core::Query(current_txn_)); - m_cq.reset(new core::CompiledQuery); - m_result = false; - - m_query->AddTable(rctp); - core::TabID t_out; - m_cq->TableAlias(t_out, - core::TabID(0)); // we apply it to the only table in this query - m_cq->TmpTable(m_tmp_table, t_out); - - std::string ext_alias; - if (table->pos_in_table_list->referencing_view) - ext_alias = std::string(table->pos_in_table_list->referencing_view->table_name); - else - ext_alias = std::string(table->s->table_name.str); - ext_alias += std::string(":") + std::string(table->alias); - m_query->table_alias2index_ptr.insert(std::make_pair(ext_alias, std::make_pair(t_out.n, table))); - - int col_no = 0; - core::AttrID col, vc; - core::TabID tab(m_tmp_table); - - my_bitmap_map *org_bitmap = dbug_tmp_use_all_columns(table, table->read_set); - for (Field **field = table->field; *field; field++) { - core::AttrID at; - if (bitmap_is_set(table->read_set, col_no)) { - col.n = col_no++; - m_cq->CreateVirtualColumn(vc.n, m_tmp_table, t_out, col); - m_cq->AddColumn(at, m_tmp_table, core::CQTerm(vc.n), common::ColOperation::LISTING, (*field)->field_name, - false); - } - } - dbug_tmp_restore_column_map(table->read_set, org_bitmap); - } - - if (m_result) - return a_cond; // if m_result there is already a result command in - // compilation - - std::unique_ptr tmp_cq(new core::CompiledQuery(*m_cq)); - core::CondID cond_id; - if (!m_query->BuildConditions(cond, cond_id, tmp_cq.get(), m_tmp_table, core::CondType::WHERE_COND, false)) { - m_query.reset(); - return a_cond; - } - tmp_cq->AddConds(m_tmp_table, cond_id, core::CondType::WHERE_COND); - tmp_cq->ApplyConds(m_tmp_table); - m_cq.reset(tmp_cq.release()); - // reset table_new_iter with push condition - set_cond_iter(); - ret = 0; - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught: %s", e.what()); - } catch (...) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), "An unknown system exception error caught.", MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An unknown system exception error caught."); - } - return ret; -} - -int TianmuHandler::reset() { - DBUG_ENTER(__PRETTY_FUNCTION__); - - int ret = 1; - try { - table_new_iter = core::RCTable::Iterator(); - table_new_iter_end = core::RCTable::Iterator(); - table_ptr = NULL; - filter_ptr.reset(); - m_query.reset(); - m_cq.reset(); - m_result = false; - blob_buffers.resize(0); - ret = 0; - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught: %s", e.what()); - } catch (...) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), "An unknown system exception error caught.", MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An unknown system exception error caught."); - } - - DBUG_RETURN(ret); -} - -enum_alter_inplace_result TianmuHandler::check_if_supported_inplace_alter([[maybe_unused]] TABLE *altered_table, - Alter_inplace_info *ha_alter_info) { - DBUG_ENTER(__PRETTY_FUNCTION__); - if ((ha_alter_info->handler_flags & ~TIANMU_SUPPORTED_ALTER_ADD_DROP_ORDER) && - (ha_alter_info->handler_flags != TIANMU_SUPPORTED_ALTER_COLUMN_NAME)) { - // support alter table column type - if (ha_alter_info->handler_flags & Alter_inplace_info::ALTER_STORED_COLUMN_TYPE) - DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); - // support alter table column exceeded length - if ((ha_alter_info->handler_flags & Alter_inplace_info::ALTER_COLUMN_EQUAL_PACK_LENGTH)) - DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); - // support alter table column default - if (ha_alter_info->handler_flags & Alter_inplace_info::ALTER_COLUMN_DEFAULT) - DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); - - DBUG_RETURN(HA_ALTER_ERROR); - } - DBUG_RETURN(HA_ALTER_INPLACE_EXCLUSIVE_LOCK); -} - -bool TianmuHandler::inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha_alter_info) { - try { - if (!(ha_alter_info->handler_flags & ~TIANMU_SUPPORTED_ALTER_ADD_DROP_ORDER)) { - std::vector v_old(table_share->field, table_share->field + table_share->fields); - std::vector v_new(altered_table->s->field, altered_table->s->field + altered_table->s->fields); - ha_rcengine_->PrepareAlterTable(m_table_name, v_new, v_old, ha_thd()); - return false; - } else if (ha_alter_info->handler_flags == TIANMU_SUPPORTED_ALTER_COLUMN_NAME) { - return false; - } - } catch (std::exception &e) { - TIANMU_LOG(LogCtl_Level::ERROR, "An exception is caught: %s", e.what()); - } catch (...) { - TIANMU_LOG(LogCtl_Level::ERROR, "An unknown system exception error caught."); - } - - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), "Unable to inplace alter table", MYF(0)); - - return true; -} - -bool TianmuHandler::commit_inplace_alter_table([[maybe_unused]] TABLE *altered_table, Alter_inplace_info *ha_alter_info, - bool commit) { - if (!commit) { - TIANMU_LOG(LogCtl_Level::INFO, "Alter table failed : %s%s", m_table_name.c_str(), " rollback"); - return true; - } - if (ha_alter_info->handler_flags == TIANMU_SUPPORTED_ALTER_COLUMN_NAME) { - return false; - } - if ((ha_alter_info->handler_flags & ~TIANMU_SUPPORTED_ALTER_ADD_DROP_ORDER)) { - TIANMU_LOG(LogCtl_Level::INFO, "Altered table not support type %lu", ha_alter_info->handler_flags); - return true; - } - fs::path tmp_dir(m_table_name + ".tmp"); - fs::path tab_dir(m_table_name + common::TIANMU_EXT); - fs::path bak_dir(m_table_name + ".backup"); - - try { - fs::rename(tab_dir, bak_dir); - fs::rename(tmp_dir, tab_dir); - - // now we are safe to clean up - std::unordered_set s; - for (auto &it : fs::directory_iterator(tab_dir / common::COLUMN_DIR)) { - auto target = fs::read_symlink(it.path()).string(); - if (!target.empty()) - s.insert(target); - } - - for (auto &it : fs::directory_iterator(bak_dir / common::COLUMN_DIR)) { - auto target = fs::read_symlink(it.path()).string(); - if (target.empty()) - continue; - auto search = s.find(target); - if (search == s.end()) { - fs::remove_all(target); - TIANMU_LOG(LogCtl_Level::INFO, "removing %s", target.c_str()); - } - } - fs::remove_all(bak_dir); - } catch (fs::filesystem_error &e) { - TIANMU_LOG(LogCtl_Level::ERROR, "file system error: %s %s|%s", e.what(), e.path1().string().c_str(), - e.path2().string().c_str()); - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), "Failed to commit alter table", MYF(0)); - return true; - } - return false; -} -/* - key: mysql format, may be union key, need changed to kvstore key format - - */ -void TianmuHandler::key_convert(const uchar *key, uint key_len, std::vector cols, - std::vector &keys) { - key_restore(table->record[0], (uchar *)key, &table->key_info[active_index], key_len); - - Field **field = table->field; - std::vector records; - for (auto &i : cols) { - Field *f = field[i]; - size_t length; - if (f->is_null()) { - throw common::Exception("Priamry key part can not be NULL"); - } - if (f->flags & BLOB_FLAG) - length = dynamic_cast(f)->get_length(); - else - length = f->row_pack_length(); - - std::unique_ptr buf(new char[length]); - char *ptr = buf.get(); - - switch (f->type()) { - case MYSQL_TYPE_TINY: { - int64_t v = f->val_int(); - if (v > TIANMU_TINYINT_MAX) - v = TIANMU_TINYINT_MAX; - else if (v < TIANMU_TINYINT_MIN) - v = TIANMU_TINYINT_MIN; - *(int64_t *)ptr = v; - ptr += sizeof(int64_t); - } break; - case MYSQL_TYPE_SHORT: { - int64_t v = f->val_int(); - if (v > TIANMU_SMALLINT_MAX) - v = TIANMU_SMALLINT_MAX; - else if (v < TIANMU_SMALLINT_MIN) - v = TIANMU_SMALLINT_MIN; - *(int64_t *)ptr = v; - ptr += sizeof(int64_t); - } break; - case MYSQL_TYPE_LONG: { - int64_t v = f->val_int(); - if (v > std::numeric_limits::max()) - v = std::numeric_limits::max(); - else if (v < TIANMU_INT_MIN) - v = TIANMU_INT_MIN; - *(int64_t *)ptr = v; - ptr += sizeof(int64_t); - } break; - case MYSQL_TYPE_INT24: { - int64_t v = f->val_int(); - if (v > TIANMU_MEDIUMINT_MAX) - v = TIANMU_MEDIUMINT_MAX; - else if (v < TIANMU_MEDIUMINT_MIN) - v = TIANMU_MEDIUMINT_MIN; - *(int64_t *)ptr = v; - ptr += sizeof(int64_t); - } break; - case MYSQL_TYPE_LONGLONG: { - int64_t v = f->val_int(); - if (v > common::TIANMU_BIGINT_MAX) - v = common::TIANMU_BIGINT_MAX; - else if (v < common::TIANMU_BIGINT_MIN) - v = common::TIANMU_BIGINT_MIN; - *(int64_t *)ptr = v; - ptr += sizeof(int64_t); - } break; - case MYSQL_TYPE_DECIMAL: - case MYSQL_TYPE_FLOAT: - case MYSQL_TYPE_DOUBLE: { - double v = f->val_real(); - *(int64_t *)ptr = *reinterpret_cast(&v); - ptr += sizeof(int64_t); - } break; - case MYSQL_TYPE_NEWDECIMAL: { - auto dec_f = dynamic_cast(f); - *(int64_t *)ptr = std::lround(dec_f->val_real() * types::PowOfTen(dec_f->dec)); - ptr += sizeof(int64_t); - } break; - case MYSQL_TYPE_TIME: - case MYSQL_TYPE_TIME2: - case MYSQL_TYPE_DATE: - case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_NEWDATE: - case MYSQL_TYPE_TIMESTAMP2: - case MYSQL_TYPE_DATETIME2: { - MYSQL_TIME my_time; - std::memset(&my_time, 0, sizeof(my_time)); - f->get_time(&my_time); - types::DT dt(my_time); - *(int64_t *)ptr = dt.val; - ptr += sizeof(int64_t); - } break; - - case MYSQL_TYPE_TIMESTAMP: { - MYSQL_TIME my_time; - std::memset(&my_time, 0, sizeof(my_time)); - f->get_time(&my_time); - auto saved = my_time.second_part; - // convert to UTC - if (!common::IsTimeStampZero(my_time)) { - my_bool myb; - my_time_t secs_utc = current_thd->variables.time_zone->TIME_to_gmt_sec(&my_time, &myb); - common::GMTSec2GMTTime(&my_time, secs_utc); - } - my_time.second_part = saved; - types::DT dt(my_time); - *(int64_t *)ptr = dt.val; - ptr += sizeof(int64_t); - } break; - case MYSQL_TYPE_YEAR: // what the hell? - { - types::DT dt = {}; - dt.year = f->val_int(); - *(int64_t *)ptr = dt.val; - ptr += sizeof(int64_t); - } break; - case MYSQL_TYPE_VARCHAR: - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_VAR_STRING: - case MYSQL_TYPE_STRING: { - String str; - f->val_str(&str); - *(uint32_t *)ptr = str.length(); - ptr += sizeof(uint32_t); - std::memcpy(ptr, str.ptr(), str.length()); - ptr += str.length(); - } break; - case MYSQL_TYPE_SET: - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_GEOMETRY: - case MYSQL_TYPE_NULL: - case MYSQL_TYPE_BIT: - default: - throw common::Exception("unsupported mysql type " + std::to_string(f->type())); - break; - } - records.emplace_back((const char *)buf.get(), ptr - buf.get()); - } - - for (auto &elem : records) { - keys.emplace_back(elem.data(), elem.size()); - } -} - -} // namespace dbhandler -} // namespace Tianmu diff --git a/storage/tianmu/handler/tianmu_handler_com.cpp b/storage/tianmu/handler/tianmu_handler_com.cpp deleted file mode 100644 index 63d42880548f02b20eab6f52c4460efddf8782e4..0000000000000000000000000000000000000000 --- a/storage/tianmu/handler/tianmu_handler_com.cpp +++ /dev/null @@ -1,761 +0,0 @@ -/* Copyright (c) 2022 StoneAtom, Inc. All rights reserved. - Use is subject to license terms - - 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-1335 USA -*/ -#include - -#include -#include - -#include "binlog.h" -#include "core/transaction.h" -#include "handler/tianmu_handler.h" -#include "mm/initializer.h" -#include "system/file_out.h" - -handlerton *rcbase_hton; - -struct st_mysql_sys_var { - MYSQL_PLUGIN_VAR_HEADER; -}; - -namespace Tianmu { -namespace dbhandler { - -/* - If frm_error() is called then we will use this to to find out what file - extentions exist for the storage engine. This is also used by the default - rename_table and delete_table method in handler.cc. - */ -my_bool tianmu_bootstrap = 0; - -char *strmov_str(char *dst, const char *src) { - while ((*dst++ = *src++)) - ; - return dst - 1; -} - -static int rcbase_done_func([[maybe_unused]] void *p) { - DBUG_ENTER(__PRETTY_FUNCTION__); - - if (ha_rcengine_) { - delete ha_rcengine_; - ha_rcengine_ = nullptr; - } - if (ha_kvstore_) { - delete ha_kvstore_; - ha_kvstore_ = nullptr; - } - - DBUG_RETURN(0); -} - -handler *rcbase_create_handler(handlerton *hton, TABLE_SHARE *table, MEM_ROOT *mem_root) { - return new (mem_root) TianmuHandler(hton, table); -} - -int rcbase_panic_func([[maybe_unused]] handlerton *hton, enum ha_panic_function flag) { - if (tianmu_bootstrap) - return 0; - - if (flag == HA_PANIC_CLOSE) { - delete ha_rcengine_; - ha_rcengine_ = nullptr; - delete ha_kvstore_; - ha_kvstore_ = nullptr; - } - return 0; -} - -int rcbase_rollback([[maybe_unused]] handlerton *hton, THD *thd, bool all) { - DBUG_ENTER(__PRETTY_FUNCTION__); - - int ret = 1; - try { - ha_rcengine_->Rollback(thd, all); - ret = 0; - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception error is caught: %s.", e.what()); - } catch (...) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), "An unknown system exception error caught.", MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An unknown system exception error caught."); - } - - DBUG_RETURN(ret); -} - -int rcbase_close_connection(handlerton *hton, THD *thd) { - DBUG_ENTER(__PRETTY_FUNCTION__); - - int ret = 1; - try { - rcbase_rollback(hton, thd, true); - ha_rcengine_->ClearTx(thd); - ret = 0; - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception error is caught: %s.", e.what()); - } catch (...) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), "An unknown system exception error caught.", MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An unknown system exception error caught."); - } - - DBUG_RETURN(ret); -} - -int rcbase_commit([[maybe_unused]] handlerton *hton, THD *thd, bool all) { - DBUG_ENTER(__PRETTY_FUNCTION__); - - int ret = 1; - std::string error_message; - - if (!(thd->no_errors != 0 || thd->killed || thd->transaction_rollback_request)) { - try { - ha_rcengine_->CommitTx(thd, all); - ret = 0; - } catch (std::exception &e) { - error_message = std::string("Error: ") + e.what(); - } catch (...) { - error_message = std::string(__func__) + " An unknown system exception error caught."; - } - } - - if (ret) { - try { - ha_rcengine_->Rollback(thd, all, true); - if (!error_message.empty()) { - TIANMU_LOG(LogCtl_Level::ERROR, "%s", error_message.c_str()); - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), error_message.c_str(), MYF(0)); - } - } catch (std::exception &e) { - if (!error_message.empty()) { - TIANMU_LOG(LogCtl_Level::ERROR, "%s", error_message.c_str()); - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), error_message.c_str(), MYF(0)); - } - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), - (std::string("Failed to rollback transaction. Error: ") + e.what()).c_str(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "Failed to rollback transaction. Error: %s.", e.what()); - } catch (...) { - if (!error_message.empty()) { - TIANMU_LOG(LogCtl_Level::ERROR, "%s", error_message.c_str()); - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), error_message.c_str(), MYF(0)); - } - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), "Failed to rollback transaction. Unknown error.", - MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "Failed to rollback transaction. Unknown error."); - } - } - - DBUG_RETURN(ret); -} - -bool rcbase_show_status([[maybe_unused]] handlerton *hton, THD *thd, stat_print_fn *pprint, enum ha_stat_type stat) { - const static char *hton_name = "TIANMU"; - - std::ostringstream buf(std::ostringstream::out); - - buf << std::endl; - - if (stat == HA_ENGINE_STATUS) { - mm::TraceableObject::Instance()->HeapHistogram(buf); - return pprint(thd, hton_name, uint(std::strlen(hton_name)), "Heap Histograms", uint(std::strlen("Heap Histograms")), - buf.str().c_str(), uint(buf.str().length())); - } - return false; -} - -extern my_bool tianmu_bootstrap; - -static int init_variables() { - opt_binlog_order_commits = false; - return 0; -} - -int rcbase_init_func(void *p) { - DBUG_ENTER(__PRETTY_FUNCTION__); - rcbase_hton = (handlerton *)p; - - if (init_variables()) { - DBUG_RETURN(1); - } - - rcbase_hton->state = SHOW_OPTION_YES; - rcbase_hton->db_type = DB_TYPE_TIANMU; - rcbase_hton->create = rcbase_create_handler; - rcbase_hton->flags = HTON_NO_FLAGS; - rcbase_hton->panic = rcbase_panic_func; - rcbase_hton->close_connection = rcbase_close_connection; - rcbase_hton->commit = rcbase_commit; - rcbase_hton->rollback = rcbase_rollback; - rcbase_hton->show_status = rcbase_show_status; - - // When mysqld runs as bootstrap mode, we do not need to initialize - // memmanager. - if (tianmu_bootstrap) - DBUG_RETURN(0); - - int ret = 1; - ha_rcengine_ = NULL; - - try { - std::string log_file = mysql_home_ptr; - log_setup(log_file + "/log/tianmu.log"); - rc_control_.addOutput(new system::FileOut(log_file + "/log/trace.log")); - rc_querylog_.addOutput(new system::FileOut(log_file + "/log/query.log")); - struct hostent *hent = NULL; - hent = gethostbyname(glob_hostname); - if (hent) - strmov_str(global_hostIP_, inet_ntoa(*(struct in_addr *)(hent->h_addr_list[0]))); - my_snprintf(global_serverinfo_, sizeof(global_serverinfo_), "\tServerIp:%s\tServerHostName:%s\tServerPort:%d", - global_hostIP_, glob_hostname, mysqld_port); - // startup tianmu engine. - ha_rcengine_ = new core::Engine(); - ret = ha_rcengine_->Init(total_ha); - { - TIANMU_LOG(LogCtl_Level::INFO, - "\n" - "------------------------------------------------------------" - "----------------------------------" - "-------------\n" - " ###### ######## ####### ## ## ######## ###### " - "###### \n" - " ## ## ## ## ## #### ## ## ## ## " - "## ## \n" - " ## ## ## ## ## ## ## ## ## ## " - "## ## \n" - " ###### ## ## ## ## ## ## ###### ## ## " - "######## \n" - " ## ## ## ## ## #### ## ## ## " - "## ## \n" - " ## ## ## ## ## ## ### ## ## ## " - "## ## \n" - " ###### ## ####### ## ## ######## ###### " - "###### \n" - "------------------------------------------------------------" - "----------------------------------" - "-------------\n"); - } - - } catch (std::exception &e) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An exception error is caught: %s.", e.what()); - } catch (...) { - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), "An unknown system exception error caught.", MYF(0)); - TIANMU_LOG(LogCtl_Level::ERROR, "An unknown system exception error caught."); - } - - DBUG_RETURN(ret); -} - -struct st_mysql_storage_engine tianmu_storage_engine = {MYSQL_HANDLERTON_INTERFACE_VERSION}; - -int get_DelayedBufferUsage_StatusVar([[maybe_unused]] MYSQL_THD thd, SHOW_VAR *var, char *buff) { - var->type = SHOW_CHAR; - var->value = buff; - std::string str = ha_rcengine_->DelayedBufferStat(); - std::memcpy(buff, str.c_str(), str.length() + 1); - return 0; -} - -int get_RowStoreUsage_StatusVar([[maybe_unused]] MYSQL_THD thd, SHOW_VAR *var, char *buff) { - var->type = SHOW_CHAR; - var->value = buff; - std::string str = ha_rcengine_->RowStoreStat(); - std::memcpy(buff, str.c_str(), str.length() + 1); - return 0; -} - -int get_InsertPerMinute_StatusVar([[maybe_unused]] MYSQL_THD thd, SHOW_VAR *outvar, char *tmp) { - *((int64_t *)tmp) = ha_rcengine_->GetIPM(); - outvar->value = tmp; - outvar->type = SHOW_LONG; - return 0; -} - -int get_QueryPerMinute_StatusVar([[maybe_unused]] MYSQL_THD thd, SHOW_VAR *outvar, char *tmp) { - *((int64_t *)tmp) = ha_rcengine_->GetQPM(); - outvar->value = tmp; - outvar->type = SHOW_LONG; - return 0; -} - -int get_LoadPerMinute_StatusVar([[maybe_unused]] MYSQL_THD thd, SHOW_VAR *outvar, char *tmp) { - *((int64_t *)tmp) = ha_rcengine_->GetLPM(); - outvar->value = tmp; - outvar->type = SHOW_LONG; - return 0; -} - -int get_Freeable_StatusVar([[maybe_unused]] MYSQL_THD thd, struct st_mysql_show_var *outvar, char *tmp) { - *((int64_t *)tmp) = mm::TraceableObject::GetFreeableSize(); - outvar->value = tmp; - outvar->type = SHOW_LONGLONG; - return 0; -} - -int get_UnFreeable_StatusVar([[maybe_unused]] MYSQL_THD thd, struct st_mysql_show_var *outvar, char *tmp) { - *((int64_t *)tmp) = mm::TraceableObject::GetUnFreeableSize(); - outvar->value = tmp; - outvar->type = SHOW_LONGLONG; - return 0; -} - -int get_MemoryScale_StatusVar([[maybe_unused]] MYSQL_THD thd, struct st_mysql_show_var *outvar, char *tmp) { - *((int64_t *)tmp) = mm::TraceableObject::MemorySettingsScale(); - outvar->value = tmp; - outvar->type = SHOW_LONGLONG; - return 0; -} - -int get_InsertTotal_StatusVar([[maybe_unused]] MYSQL_THD thd, SHOW_VAR *outvar, char *tmp) { - *((int64_t *)tmp) = ha_rcengine_->GetIT(); - outvar->value = tmp; - outvar->type = SHOW_LONG; - return 0; -} - -int get_QueryTotal_StatusVar([[maybe_unused]] MYSQL_THD thd, SHOW_VAR *outvar, char *tmp) { - *((int64_t *)tmp) = ha_rcengine_->GetQT(); - outvar->value = tmp; - outvar->type = SHOW_LONG; - return 0; -} - -int get_LoadTotal_StatusVar([[maybe_unused]] MYSQL_THD thd, SHOW_VAR *outvar, char *tmp) { - *((int64_t *)tmp) = ha_rcengine_->GetLT(); - outvar->value = tmp; - outvar->type = SHOW_LONG; - return 0; -} - -int get_LoadDupTotal_StatusVar([[maybe_unused]] MYSQL_THD thd, SHOW_VAR *outvar, char *tmp) { - *((int64_t *)tmp) = ha_rcengine_->GetLDT(); - outvar->value = tmp; - outvar->type = SHOW_LONG; - return 0; -} - -int get_LoadDupPerMinute_StatusVar([[maybe_unused]] MYSQL_THD thd, SHOW_VAR *outvar, char *tmp) { - *((int64_t *)tmp) = ha_rcengine_->GetLDPM(); - outvar->value = tmp; - outvar->type = SHOW_LONG; - return 0; -} - -int get_UpdateTotal_StatusVar([[maybe_unused]] MYSQL_THD thd, SHOW_VAR *outvar, char *tmp) { - *((int64_t *)tmp) = ha_rcengine_->GetUT(); - outvar->value = tmp; - outvar->type = SHOW_LONG; - return 0; -} - -int get_UpdatePerMinute_StatusVar([[maybe_unused]] MYSQL_THD thd, SHOW_VAR *outvar, char *tmp) { - *((int64_t *)tmp) = ha_rcengine_->GetUPM(); - outvar->value = tmp; - outvar->type = SHOW_LONG; - return 0; -} - -char masteslave_info[8192] = {0}; - -SHOW_VAR tianmu_masterslave_dump[] = {{"info", masteslave_info, SHOW_CHAR, SHOW_SCOPE_UNDEF}, - {NullS, NullS, SHOW_LONG, SHOW_SCOPE_UNDEF}}; - -// showtype -// ===================== -// SHOW_UNDEF, SHOW_BOOL, SHOW_INT, SHOW_LONG, -// SHOW_LONGLONG, SHOW_CHAR, SHOW_CHAR_PTR, -// SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE - -int tianmu_throw_error_func([[maybe_unused]] MYSQL_THD thd, [[maybe_unused]] struct st_mysql_sys_var *var, - [[maybe_unused]] void *save, struct st_mysql_value *value) { - int buffer_length = 512; - char buff[512] = {0}; - - DEBUG_ASSERT(value->value_type(value) == MYSQL_VALUE_TYPE_STRING); - - my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), value->val_str(value, buff, &buffer_length), MYF(0)); - return -1; -} - -static void update_func_str([[maybe_unused]] THD *thd, struct st_mysql_sys_var *var, void *tgt, const void *save) { - char *old = *(char **)tgt; - *(char **)tgt = *(char **)save; - if (var->flags & PLUGIN_VAR_MEMALLOC) { - *(char **)tgt = my_strdup(PSI_NOT_INSTRUMENTED, *(char **)save, MYF(0)); - my_free(old); - } -} - -void refresh_sys_table_func([[maybe_unused]] MYSQL_THD thd, [[maybe_unused]] struct st_mysql_sys_var *var, void *tgt, - const void *save) { - *(my_bool *)tgt = *(my_bool *)save ? TRUE : FALSE; -} - -void debug_update(MYSQL_THD thd, struct st_mysql_sys_var *var, void *var_ptr, const void *save); -void trace_update(MYSQL_THD thd, struct st_mysql_sys_var *var, void *var_ptr, const void *save); -void controlquerylog_update(MYSQL_THD thd, struct st_mysql_sys_var *var, void *var_ptr, const void *save); -void start_async_update(MYSQL_THD thd, struct st_mysql_sys_var *var, void *var_ptr, const void *save); -extern void async_join_update(MYSQL_THD thd, struct st_mysql_sys_var *var, void *var_ptr, const void *save); - -#define STATUS_FUNCTION(name, showtype, member) \ - int get_##name##_StatusVar([[maybe_unused]] MYSQL_THD thd, struct st_mysql_show_var *outvar, char *tmp) { \ - *((int64_t *)tmp) = ha_rcengine_->cache.member(); \ - outvar->value = tmp; \ - outvar->type = showtype; \ - return 0; \ - } - -#define MM_STATUS_FUNCTION(name, showtype, member) \ - int get_##name##_StatusVar([[maybe_unused]] MYSQL_THD thd, struct st_mysql_show_var *outvar, char *tmp) { \ - *((int64_t *)tmp) = mm::TraceableObject::Instance()->member(); \ - outvar->value = tmp; \ - outvar->type = showtype; \ - return 0; \ - } - -#define STATUS_MEMBER(name, label) \ - { "Tianmu_" #label, (char *)get_##name##_StatusVar, SHOW_FUNC, SHOW_SCOPE_GLOBAL } - -STATUS_FUNCTION(gdchits, SHOW_LONGLONG, getCacheHits) -STATUS_FUNCTION(gdcmisses, SHOW_LONGLONG, getCacheMisses) -STATUS_FUNCTION(gdcreleased, SHOW_LONGLONG, getReleased) -STATUS_FUNCTION(gdcreadwait, SHOW_LONGLONG, getReadWait) -STATUS_FUNCTION(gdcfalsewakeup, SHOW_LONGLONG, getFalseWakeup) -STATUS_FUNCTION(gdcreadwaitinprogress, SHOW_LONGLONG, getReadWaitInProgress) -STATUS_FUNCTION(gdcpackloads, SHOW_LONGLONG, getPackLoads) -STATUS_FUNCTION(gdcloaderrors, SHOW_LONGLONG, getLoadErrors) -STATUS_FUNCTION(gdcredecompress, SHOW_LONGLONG, getReDecompress) - -MM_STATUS_FUNCTION(mmallocblocks, SHOW_LONGLONG, getAllocBlocks) -MM_STATUS_FUNCTION(mmallocobjs, SHOW_LONGLONG, getAllocObjs) -MM_STATUS_FUNCTION(mmallocsize, SHOW_LONGLONG, getAllocSize) -MM_STATUS_FUNCTION(mmallocpack, SHOW_LONGLONG, getAllocPack) -MM_STATUS_FUNCTION(mmalloctemp, SHOW_LONGLONG, getAllocTemp) -MM_STATUS_FUNCTION(mmalloctempsize, SHOW_LONGLONG, getAllocTempSize) -MM_STATUS_FUNCTION(mmallocpacksize, SHOW_LONGLONG, getAllocPackSize) -MM_STATUS_FUNCTION(mmfreeblocks, SHOW_LONGLONG, getFreeBlocks) -MM_STATUS_FUNCTION(mmfreepacks, SHOW_LONGLONG, getFreePacks) -MM_STATUS_FUNCTION(mmfreetemp, SHOW_LONGLONG, getFreeTemp) -MM_STATUS_FUNCTION(mmfreepacksize, SHOW_LONGLONG, getFreePackSize) -MM_STATUS_FUNCTION(mmfreetempsize, SHOW_LONGLONG, getFreeTempSize) -MM_STATUS_FUNCTION(mmfreesize, SHOW_LONGLONG, getFreeSize) -MM_STATUS_FUNCTION(mmrelease1, SHOW_LONGLONG, getReleaseCount1) -MM_STATUS_FUNCTION(mmrelease2, SHOW_LONGLONG, getReleaseCount2) -MM_STATUS_FUNCTION(mmrelease3, SHOW_LONGLONG, getReleaseCount3) -MM_STATUS_FUNCTION(mmrelease4, SHOW_LONGLONG, getReleaseCount4) -MM_STATUS_FUNCTION(mmreloaded, SHOW_LONGLONG, getReloaded) -MM_STATUS_FUNCTION(mmreleasecount, SHOW_LONGLONG, getReleaseCount) -MM_STATUS_FUNCTION(mmreleasetotal, SHOW_LONGLONG, getReleaseTotal) - -static struct st_mysql_show_var statusvars[] = { - STATUS_MEMBER(gdchits, gdc_hits), - STATUS_MEMBER(gdcmisses, gdc_misses), - STATUS_MEMBER(gdcreleased, gdc_released), - STATUS_MEMBER(gdcreadwait, gdc_readwait), - STATUS_MEMBER(gdcfalsewakeup, gdc_false_wakeup), - STATUS_MEMBER(gdcreadwaitinprogress, gdc_read_wait_in_progress), - STATUS_MEMBER(gdcpackloads, gdc_pack_loads), - STATUS_MEMBER(gdcloaderrors, gdc_load_errors), - STATUS_MEMBER(gdcredecompress, gdc_redecompress), - STATUS_MEMBER(mmrelease1, mm_release1), - STATUS_MEMBER(mmrelease2, mm_release2), - STATUS_MEMBER(mmrelease3, mm_release3), - STATUS_MEMBER(mmrelease4, mm_release4), - STATUS_MEMBER(mmallocblocks, mm_alloc_blocs), - STATUS_MEMBER(mmallocobjs, mm_alloc_objs), - STATUS_MEMBER(mmallocsize, mm_alloc_size), - STATUS_MEMBER(mmallocpack, mm_alloc_packs), - STATUS_MEMBER(mmalloctemp, mm_alloc_temp), - STATUS_MEMBER(mmalloctempsize, mm_alloc_temp_size), - STATUS_MEMBER(mmallocpacksize, mm_alloc_pack_size), - STATUS_MEMBER(mmfreeblocks, mm_free_blocks), - STATUS_MEMBER(mmfreepacks, mm_free_packs), - STATUS_MEMBER(mmfreetemp, mm_free_temp), - STATUS_MEMBER(mmfreepacksize, mm_free_pack_size), - STATUS_MEMBER(mmfreetempsize, mm_free_temp_size), - STATUS_MEMBER(mmfreesize, mm_free_size), - STATUS_MEMBER(mmreloaded, mm_reloaded), - STATUS_MEMBER(mmreleasecount, mm_release_count), - STATUS_MEMBER(mmreleasetotal, mm_release_total), - STATUS_MEMBER(DelayedBufferUsage, delay_buffer_usage), - STATUS_MEMBER(RowStoreUsage, row_store_usage), - STATUS_MEMBER(Freeable, mm_freeable), - STATUS_MEMBER(InsertPerMinute, insert_per_minute), - STATUS_MEMBER(LoadPerMinute, load_per_minute), - STATUS_MEMBER(QueryPerMinute, query_per_minute), - STATUS_MEMBER(MemoryScale, mm_scale), - STATUS_MEMBER(UnFreeable, mm_unfreeable), - STATUS_MEMBER(InsertTotal, insert_total), - STATUS_MEMBER(LoadTotal, load_total), - STATUS_MEMBER(QueryTotal, query_total), - STATUS_MEMBER(LoadDupPerMinute, load_dup_per_minute), - STATUS_MEMBER(LoadDupTotal, load_dup_total), - STATUS_MEMBER(UpdatePerMinute, update_per_minute), - STATUS_MEMBER(UpdateTotal, update_total), - {0, 0, SHOW_UNDEF, SHOW_SCOPE_UNDEF}, -}; - -static MYSQL_SYSVAR_BOOL(refresh_sys_tianmu, tianmu_sysvar_refresh_sys_table, PLUGIN_VAR_BOOL, "-", NULL, - refresh_sys_table_func, TRUE); -static MYSQL_THDVAR_STR(trigger_error, PLUGIN_VAR_STR | PLUGIN_VAR_THDLOCAL, "-", tianmu_throw_error_func, - update_func_str, NULL); - -static MYSQL_SYSVAR_INT(ini_allowmysqlquerypath, tianmu_sysvar_allowmysqlquerypath, PLUGIN_VAR_READONLY, "-", NULL, - NULL, 0, 0, 1, 0); -static MYSQL_SYSVAR_STR(ini_cachefolder, tianmu_sysvar_cachefolder, PLUGIN_VAR_READONLY, "-", NULL, NULL, "cache"); -static MYSQL_SYSVAR_INT(ini_knlevel, tianmu_sysvar_knlevel, PLUGIN_VAR_READONLY, "-", NULL, NULL, 99, 0, 99, 0); -static MYSQL_SYSVAR_BOOL(ini_pushdown, tianmu_sysvar_pushdown, PLUGIN_VAR_READONLY, "-", NULL, NULL, TRUE); -static MYSQL_SYSVAR_INT(ini_servermainheapsize, tianmu_sysvar_servermainheapsize, PLUGIN_VAR_READONLY, "-", NULL, NULL, - 0, 0, 1000000, 0); -static MYSQL_SYSVAR_BOOL(ini_usemysqlimportexportdefaults, tianmu_sysvar_usemysqlimportexportdefaults, - PLUGIN_VAR_READONLY, "-", NULL, NULL, FALSE); -static MYSQL_SYSVAR_INT(ini_threadpoolsize, tianmu_sysvar_threadpoolsize, PLUGIN_VAR_READONLY, "-", NULL, NULL, 1, 0, - 1000000, 0); -static MYSQL_SYSVAR_INT(ini_cachesizethreshold, tianmu_sysvar_cachesizethreshold, PLUGIN_VAR_INT, "-", NULL, NULL, 4, 0, - 1024, 0); -static MYSQL_SYSVAR_INT(ini_cachereleasethreshold, tianmu_sysvar_cachereleasethreshold, PLUGIN_VAR_INT, "-", NULL, NULL, - 100, 0, 100000, 0); -static MYSQL_SYSVAR_BOOL(insert_delayed, tianmu_sysvar_insert_delayed, PLUGIN_VAR_READONLY, "-", NULL, NULL, TRUE); -static MYSQL_SYSVAR_INT(insert_cntthreshold, tianmu_sysvar_insert_cntthreshold, PLUGIN_VAR_READONLY, "-", NULL, NULL, 2, - 0, 1000, 0); -static MYSQL_SYSVAR_INT(insert_numthreshold, tianmu_sysvar_insert_numthreshold, PLUGIN_VAR_READONLY, "-", NULL, NULL, - 10000, 0, 100000, 0); -static MYSQL_SYSVAR_INT(insert_wait_ms, tianmu_sysvar_insert_wait_ms, PLUGIN_VAR_READONLY, "-", NULL, NULL, 100, 10, - 10000, 0); -static MYSQL_SYSVAR_INT(insert_wait_time, tianmu_sysvar_insert_wait_time, PLUGIN_VAR_INT, "-", NULL, NULL, 1000, 0, - 600000, 0); -static MYSQL_SYSVAR_INT(insert_max_buffered, tianmu_sysvar_insert_max_buffered, PLUGIN_VAR_READONLY, "-", NULL, NULL, - 65536, 0, 10000000, 0); -static MYSQL_SYSVAR_BOOL(compensation_start, tianmu_sysvar_compensation_start, PLUGIN_VAR_BOOL, "-", NULL, NULL, FALSE); -static MYSQL_SYSVAR_STR(hugefiledir, tianmu_sysvar_hugefiledir, PLUGIN_VAR_READONLY, "-", NULL, NULL, ""); -static MYSQL_SYSVAR_INT(cachinglevel, tianmu_sysvar_cachinglevel, PLUGIN_VAR_READONLY, "-", NULL, NULL, 1, 0, 512, 0); -static MYSQL_SYSVAR_STR(mm_policy, tianmu_sysvar_mm_policy, PLUGIN_VAR_READONLY, "-", NULL, NULL, ""); -static MYSQL_SYSVAR_INT(mm_hardlimit, tianmu_sysvar_mm_hardlimit, PLUGIN_VAR_READONLY, "-", NULL, NULL, 0, 0, 1, 0); -static MYSQL_SYSVAR_STR(mm_releasepolicy, tianmu_sysvar_mm_releasepolicy, PLUGIN_VAR_READONLY, "-", NULL, NULL, "2q"); -static MYSQL_SYSVAR_INT(mm_largetempratio, tianmu_sysvar_mm_largetempratio, PLUGIN_VAR_READONLY, "-", NULL, NULL, 0, 0, - 99, 0); -static MYSQL_SYSVAR_INT(mm_largetemppool_threshold, tianmu_sysvar_mm_large_threshold, PLUGIN_VAR_INT, - "size threshold in MB for using large temp thread pool", NULL, NULL, 16, 0, 10240, 0); -static MYSQL_SYSVAR_INT(sync_buffers, tianmu_sysvar_sync_buffers, PLUGIN_VAR_READONLY, "-", NULL, NULL, 0, 0, 1, 0); - -static MYSQL_SYSVAR_INT(query_threads, tianmu_sysvar_query_threads, PLUGIN_VAR_READONLY, "-", NULL, NULL, 0, 0, 100, 0); -static MYSQL_SYSVAR_INT(load_threads, tianmu_sysvar_load_threads, PLUGIN_VAR_READONLY, "-", NULL, NULL, 0, 0, 100, 0); -static MYSQL_SYSVAR_INT(bg_load_threads, tianmu_sysvar_bg_load_threads, PLUGIN_VAR_READONLY, "-", NULL, NULL, 0, 0, 100, - 0); -static MYSQL_SYSVAR_INT(insert_buffer_size, tianmu_sysvar_insert_buffer_size, PLUGIN_VAR_READONLY, "-", NULL, NULL, 512, - 512, 10000, 0); - -static MYSQL_THDVAR_INT(session_debug_level, PLUGIN_VAR_INT, "session debug level", NULL, debug_update, 3, 0, 5, 0); -static MYSQL_THDVAR_INT(control_trace, PLUGIN_VAR_OPCMDARG, "ini controltrace", NULL, trace_update, 0, 0, 100, 0); -static MYSQL_SYSVAR_INT(global_debug_level, tianmu_sysvar_global_debug_level, PLUGIN_VAR_INT, "global debug level", - NULL, NULL, 4, 0, 5, 0); - -static MYSQL_SYSVAR_INT(distinct_cache_size, tianmu_sysvar_distcache_size, PLUGIN_VAR_INT, - "Upper byte limit for GroupDistinctCache buffer", NULL, NULL, 64, 64, 256, 0); -static MYSQL_SYSVAR_BOOL(filterevaluation_speedup, tianmu_sysvar_filterevaluation_speedup, PLUGIN_VAR_BOOL, "-", NULL, - NULL, TRUE); -static MYSQL_SYSVAR_BOOL(groupby_speedup, tianmu_sysvar_groupby_speedup, PLUGIN_VAR_BOOL, "-", NULL, NULL, TRUE); -static MYSQL_SYSVAR_BOOL(orderby_speedup, tianmu_sysvar_orderby_speedup, PLUGIN_VAR_BOOL, "-", NULL, NULL, FALSE); -static MYSQL_SYSVAR_INT(join_parallel, tianmu_sysvar_join_parallel, PLUGIN_VAR_INT, - "join matching parallel: 0-Disabled, 1-Auto, N-specify count", NULL, NULL, 1, 0, 1000, 0); -static MYSQL_SYSVAR_INT(join_splitrows, tianmu_sysvar_join_splitrows, PLUGIN_VAR_INT, - "join split rows:0-Disabled, 1-Auto, N-specify count", NULL, NULL, 0, 0, 1000, 0); -static MYSQL_SYSVAR_BOOL(minmax_speedup, tianmu_sysvar_minmax_speedup, PLUGIN_VAR_BOOL, "-", NULL, NULL, TRUE); -static MYSQL_SYSVAR_UINT(index_cache_size, tianmu_sysvar_index_cache_size, PLUGIN_VAR_READONLY, - "Index cache size in MB", NULL, NULL, 0, 0, 65536, 0); -static MYSQL_SYSVAR_BOOL(index_search, tianmu_sysvar_index_search, PLUGIN_VAR_BOOL, "-", NULL, NULL, TRUE); -static MYSQL_SYSVAR_BOOL(enable_rowstore, tianmu_sysvar_enable_rowstore, PLUGIN_VAR_BOOL, "-", NULL, NULL, TRUE); -static MYSQL_SYSVAR_BOOL(parallel_filloutput, tianmu_sysvar_parallel_filloutput, PLUGIN_VAR_BOOL, "-", NULL, NULL, - TRUE); -static MYSQL_SYSVAR_BOOL(parallel_mapjoin, tianmu_sysvar_parallel_mapjoin, PLUGIN_VAR_BOOL, "-", NULL, NULL, FALSE); - -static MYSQL_SYSVAR_INT(max_execution_time, tianmu_sysvar_max_execution_time, PLUGIN_VAR_INT, - "max query execution time in seconds", NULL, NULL, 0, 0, 10000, 0); -static MYSQL_SYSVAR_INT(ini_controlquerylog, tianmu_sysvar_controlquerylog, PLUGIN_VAR_INT, "global controlquerylog", - NULL, controlquerylog_update, 1, 0, 100, 0); - -static const char *dist_policy_names[] = {"round-robin", "random", "space", 0}; -static TYPELIB policy_typelib_t = {array_elements(dist_policy_names) - 1, "dist_policy_names", dist_policy_names, 0}; -static MYSQL_SYSVAR_ENUM(data_distribution_policy, tianmu_sysvar_dist_policy, PLUGIN_VAR_RQCMDARG, - "Specifies the policy to distribute column data among multiple data " - "directories." - "Possible values are round-robin(default), random, and space", - NULL, NULL, 2, &policy_typelib_t); - -static MYSQL_SYSVAR_INT(disk_usage_threshold, tianmu_sysvar_disk_usage_threshold, PLUGIN_VAR_INT, - "Specifies the disk usage threshold for data diretories.", NULL, NULL, 85, 10, 99, 0); - -static MYSQL_SYSVAR_UINT(lookup_max_size, tianmu_sysvar_lookup_max_size, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, - "Lookup dictionary max size", NULL, NULL, 100000, 1000, 1000000, 0); - -static MYSQL_SYSVAR_BOOL(qps_log, tianmu_sysvar_qps_log, PLUGIN_VAR_BOOL, "-", NULL, NULL, TRUE); - -static MYSQL_SYSVAR_BOOL(force_hashjoin, tianmu_sysvar_force_hashjoin, PLUGIN_VAR_BOOL, "-", NULL, NULL, FALSE); -static MYSQL_SYSVAR_INT(start_async, tianmu_sysvar_start_async, PLUGIN_VAR_INT, - "Enable async, specifies async threads x/100 * cpus", NULL, start_async_update, 0, 0, 100, 0); -static MYSQL_SYSVAR_STR(async_join, tianmu_sysvar_async_join, PLUGIN_VAR_STR, - "Set async join params: packStep;traverseCount;matchCount", NULL, async_join_update, "1;0;0;0"); -static MYSQL_SYSVAR_BOOL(join_disable_switch_side, tianmu_sysvar_join_disable_switch_side, PLUGIN_VAR_BOOL, "-", NULL, - NULL, FALSE); -static MYSQL_SYSVAR_BOOL(enable_histogram_cmap_bloom, tianmu_sysvar_enable_histogram_cmap_bloom, PLUGIN_VAR_BOOL, "-", - NULL, NULL, FALSE); -static MYSQL_SYSVAR_BOOL(large_prefix, tianmu_sysvar_large_prefix, PLUGIN_VAR_RQCMDARG, - "Support large index prefix length of 3072 bytes. If off, the maximum " - "index prefix length is 767.", - NULL, NULL, TRUE); -static MYSQL_SYSVAR_UINT(result_sender_rows, tianmu_sysvar_result_sender_rows, PLUGIN_VAR_UNSIGNED, - "The number of rows to load at a time when processing " - "queries like select xxx from yyya", - NULL, NULL, 65536, 1024, 131072, 0); - -void debug_update(MYSQL_THD thd, [[maybe_unused]] struct st_mysql_sys_var *var, void *var_ptr, const void *save) { - if (ha_rcengine_) { - auto cur_conn = ha_rcengine_->GetTx(thd); - // set debug_level for connection level - cur_conn->SetDebugLevel(*((int *)save)); - } - *((int *)var_ptr) = *((int *)save); -} - -void trace_update(MYSQL_THD thd, [[maybe_unused]] struct st_mysql_sys_var *var, void *var_ptr, const void *save) { - *((int *)var_ptr) = *((int *)save); - // get global mysql_sysvar_control_trace - tianmu_sysvar_controltrace = THDVAR(nullptr, control_trace); - if (ha_rcengine_) { - core::Transaction *cur_conn = ha_rcengine_->GetTx(thd); - cur_conn->SetSessionTrace(*((int *)save)); - ConfigureRCControl(); - } -} - -void controlquerylog_update([[maybe_unused]] MYSQL_THD thd, [[maybe_unused]] struct st_mysql_sys_var *var, - void *var_ptr, const void *save) { - *((int *)var_ptr) = *((int *)save); - int control = *((int *)var_ptr); - if (ha_rcengine_) { - control ? rc_querylog_.setOn() : rc_querylog_.setOff(); - } -} - -void start_async_update([[maybe_unused]] MYSQL_THD thd, [[maybe_unused]] struct st_mysql_sys_var *var, void *var_ptr, - const void *save) { - int percent = *((int *)save); - *((int *)var_ptr) = percent; - if (ha_rcengine_) { - ha_rcengine_->ResetTaskExecutor(percent); - } -} - -void resolve_async_join_settings(const std::string &settings) { - std::vector splits_vec; - boost::split(splits_vec, settings, boost::is_any_of(";")); - if (splits_vec.size() >= 4) { - try { - tianmu_sysvar_async_join_setting.pack_per_step = boost::lexical_cast(splits_vec[0]); - tianmu_sysvar_async_join_setting.rows_per_step = boost::lexical_cast(splits_vec[1]); - tianmu_sysvar_async_join_setting.traverse_slices = boost::lexical_cast(splits_vec[2]); - tianmu_sysvar_async_join_setting.match_slices = boost::lexical_cast(splits_vec[3]); - } catch (...) { - TIANMU_LOG(LogCtl_Level::ERROR, "Failed resolve async join settings"); - } - } -} - -void async_join_update([[maybe_unused]] MYSQL_THD thd, [[maybe_unused]] struct st_mysql_sys_var *var, - [[maybe_unused]] void *var_ptr, const void *save) { - const char *str = *static_cast(save); - std::string settings(str); - resolve_async_join_settings(settings); -} - -static struct st_mysql_sys_var *tianmu_showvars[] = {MYSQL_SYSVAR(bg_load_threads), - MYSQL_SYSVAR(cachinglevel), - MYSQL_SYSVAR(compensation_start), - MYSQL_SYSVAR(control_trace), - MYSQL_SYSVAR(data_distribution_policy), - MYSQL_SYSVAR(disk_usage_threshold), - MYSQL_SYSVAR(distinct_cache_size), - MYSQL_SYSVAR(filterevaluation_speedup), - MYSQL_SYSVAR(global_debug_level), - MYSQL_SYSVAR(groupby_speedup), - MYSQL_SYSVAR(hugefiledir), - MYSQL_SYSVAR(index_cache_size), - MYSQL_SYSVAR(index_search), - MYSQL_SYSVAR(enable_rowstore), - MYSQL_SYSVAR(ini_allowmysqlquerypath), - MYSQL_SYSVAR(ini_cachefolder), - MYSQL_SYSVAR(ini_cachereleasethreshold), - MYSQL_SYSVAR(ini_cachesizethreshold), - MYSQL_SYSVAR(ini_controlquerylog), - MYSQL_SYSVAR(ini_knlevel), - MYSQL_SYSVAR(ini_pushdown), - MYSQL_SYSVAR(ini_servermainheapsize), - MYSQL_SYSVAR(ini_threadpoolsize), - MYSQL_SYSVAR(ini_usemysqlimportexportdefaults), - MYSQL_SYSVAR(insert_buffer_size), - MYSQL_SYSVAR(insert_cntthreshold), - MYSQL_SYSVAR(insert_delayed), - MYSQL_SYSVAR(insert_max_buffered), - MYSQL_SYSVAR(insert_numthreshold), - MYSQL_SYSVAR(insert_wait_ms), - MYSQL_SYSVAR(insert_wait_time), - MYSQL_SYSVAR(join_disable_switch_side), - MYSQL_SYSVAR(enable_histogram_cmap_bloom), - MYSQL_SYSVAR(join_parallel), - MYSQL_SYSVAR(join_splitrows), - MYSQL_SYSVAR(large_prefix), - MYSQL_SYSVAR(load_threads), - MYSQL_SYSVAR(lookup_max_size), - MYSQL_SYSVAR(max_execution_time), - MYSQL_SYSVAR(minmax_speedup), - MYSQL_SYSVAR(mm_hardlimit), - MYSQL_SYSVAR(mm_largetempratio), - MYSQL_SYSVAR(mm_largetemppool_threshold), - MYSQL_SYSVAR(mm_policy), - MYSQL_SYSVAR(mm_releasepolicy), - MYSQL_SYSVAR(orderby_speedup), - MYSQL_SYSVAR(parallel_filloutput), - MYSQL_SYSVAR(parallel_mapjoin), - MYSQL_SYSVAR(qps_log), - MYSQL_SYSVAR(query_threads), - MYSQL_SYSVAR(refresh_sys_tianmu), - MYSQL_SYSVAR(session_debug_level), - MYSQL_SYSVAR(sync_buffers), - MYSQL_SYSVAR(trigger_error), - MYSQL_SYSVAR(async_join), - MYSQL_SYSVAR(force_hashjoin), - MYSQL_SYSVAR(start_async), - MYSQL_SYSVAR(result_sender_rows), - NULL}; -} // namespace dbhandler -} // namespace Tianmu - -mysql_declare_plugin(tianmu){ - MYSQL_STORAGE_ENGINE_PLUGIN, - &Tianmu::dbhandler::tianmu_storage_engine, - "TIANMU", - "StoneAtom Group Holding Limited", - "Tianmu storage engine", - PLUGIN_LICENSE_GPL, - Tianmu::dbhandler::rcbase_init_func, /* Plugin Init */ - Tianmu::dbhandler::rcbase_done_func, /* Plugin Deinit */ - 0x0001 /* 0.1 */, - Tianmu::dbhandler::statusvars, /* status variables */ - Tianmu::dbhandler::tianmu_showvars, /* system variables */ - NULL, /* config options */ - 0 /* flags for plugin */ -} mysql_declare_plugin_end; diff --git a/storage/tianmu/types/rc_data_types.cpp b/storage/tianmu/types/rc_data_types.cpp deleted file mode 100644 index b558cc819044a879aa0697f105aa34659a989e76..0000000000000000000000000000000000000000 --- a/storage/tianmu/types/rc_data_types.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* Copyright (c) 2022 StoneAtom, Inc. All rights reserved. - Use is subject to license terms - - 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-1335 USA -*/ - -#include "rc_data_types.h" - -#include "core/rc_attr.h" -#include "core/rc_attr_typeinfo.h" - -namespace Tianmu { -namespace types { - -RCDataType::~RCDataType() {} - -bool RCDataType::AreComperable(const RCDataType &rcdt) const { return RCDataType::AreComperable(*this, rcdt); } - -bool RCDataType::AreComperable(const RCDataType &rcdt1, const RCDataType &rcdt2) { - common::CT att1 = rcdt1.Type(); - common::CT att2 = rcdt2.Type(); - return AreComparable(att1, att2); -} - -bool RCDataType::compare(const RCDataType &rcdt1, const RCDataType &rcdt2, common::Operator op, char like_esc) { - // DEBUG_ASSERT(RCDataType::AreComperable(rcdt1, rcdt2)); - if (op == common::Operator::O_LIKE || op == common::Operator::O_NOT_LIKE) { - if (rcdt1.IsNull() || rcdt2.IsNull()) - return false; - BString x, y; - BString *rcbs1 = dynamic_cast(const_cast(&rcdt1)); - if (!rcbs1) { - x = rcdt1.ToBString(); - rcbs1 = &x; - } - BString *rcbs2 = dynamic_cast(const_cast(&rcdt2)); - if (!rcbs2) { - y = rcdt2.ToBString(); - rcbs2 = &y; - } - bool res = rcbs1->Like(*rcbs2, like_esc); - if (op == common::Operator::O_LIKE) - return res; - else - return !res; - } else if (!rcdt1.IsNull() && !rcdt2.IsNull() && - (((op == common::Operator::O_EQ) && rcdt1 == rcdt2) || - (op == common::Operator::O_NOT_EQ && rcdt1 != rcdt2) || - (op == common::Operator::O_LESS && rcdt1 < rcdt2) || - (op == common::Operator::O_LESS_EQ && (rcdt1 < rcdt2 || rcdt1 == rcdt2)) || - (op == common::Operator::O_MORE && (!(rcdt1 < rcdt2) && rcdt1 != rcdt2)) || - (op == common::Operator::O_MORE_EQ && (!(rcdt1 < rcdt2) || rcdt1 == rcdt2)))) - return true; - return false; -} - -bool RCDataType::compare(const RCDataType &rcdt, common::Operator op, char like_esc) const { - return RCDataType::compare(*this, rcdt, op, like_esc); -} - -bool AreComparable(common::CT attr1_t, common::CT attr2_t) { - if (attr1_t == attr2_t) - return true; - if ((core::ATI::IsDateTimeType(attr1_t)) && (core::ATI::IsDateTimeType(attr2_t))) - return true; - if ((core::ATI::IsTxtType(attr2_t) && attr1_t == common::CT::VARBYTE) || - (core::ATI::IsTxtType(attr1_t) && attr2_t == common::CT::VARBYTE)) - return true; - if ((((attr1_t == common::CT::TIME) || (attr1_t == common::CT::DATE)) && attr2_t != common::CT::DATETIME) || - (((attr2_t == common::CT::TIME) || (attr2_t == common::CT::DATE)) && attr1_t != common::CT::DATETIME) || - (core::ATI::IsBinType(attr1_t) && !core::ATI::IsBinType(attr2_t)) || - (core::ATI::IsBinType(attr2_t) && !core::ATI::IsBinType(attr1_t)) || - (core::ATI::IsTxtType(attr1_t) && !core::ATI::IsTxtType(attr2_t)) || - (core::ATI::IsTxtType(attr2_t) && !core::ATI::IsTxtType(attr1_t))) - return false; - return true; -} - -bool RCDataType::ToDecimal(const RCDataType &in, int scale, RCNum &out) { - if (RCNum *rcn = dynamic_cast(const_cast(&in))) { - if (rcn->IsDecimal(scale)) { - out = rcn->ToDecimal(scale); - return true; - } - } else if (BString *rcs = dynamic_cast(const_cast(&in))) { - if (RCNum::Parse(*rcs, out) == common::ErrorCode::SUCCESS) - return true; - } - return false; -} - -bool RCDataType::ToInt(const RCDataType &in, RCNum &out) { - if (RCNum *rcn = dynamic_cast(const_cast(&in))) { - if (rcn->IsInt()) { - out = rcn->ToInt(); - return true; - } - } else if (BString *rcs = dynamic_cast(const_cast(&in))) { - if (RCNum::Parse(*rcs, out) == common::ErrorCode::SUCCESS) - return true; - } - return false; -} - -bool RCDataType::ToReal(const RCDataType &in, RCNum &out) { - if (RCNum *rcn = dynamic_cast(const_cast(&in))) { - if (rcn->IsReal()) { - out = rcn->ToReal(); - return true; - } - } else if (BString *rcs = dynamic_cast(const_cast(&in))) { - if (RCNum::ParseReal(*rcs, out, common::CT::UNK) == common::ErrorCode::SUCCESS) - return true; - } - return false; -} - -ValueTypeEnum RCDataType::GetValueType(common::CT attr_type) { - if (core::ATI::IsNumericType(attr_type)) - return ValueTypeEnum::NUMERIC_TYPE; - else if (core::ATI::IsDateTimeType(attr_type)) - return ValueTypeEnum::DATE_TIME_TYPE; - else if (core::ATI::IsStringType(attr_type)) - return ValueTypeEnum::STRING_TYPE; - return ValueTypeEnum::NULL_TYPE; -} - -} // namespace types -} // namespace Tianmu diff --git a/storage/tianmu/types/rc_num.cpp b/storage/tianmu/types/rc_num.cpp deleted file mode 100644 index 6b05ebd6a9fec0e4861c2b49212fe9e7785ec951..0000000000000000000000000000000000000000 --- a/storage/tianmu/types/rc_num.cpp +++ /dev/null @@ -1,605 +0,0 @@ -/* Copyright (c) 2022 StoneAtom, Inc. All rights reserved. - Use is subject to license terms - - 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-1335 USA -*/ - -#include "rc_num.h" - -#include - -#include "common/assert.h" -#include "core/tools.h" -#include "system/txt_utils.h" -#include "types/rc_data_types.h" -#include "types/value_parser4txt.h" - -namespace Tianmu { -namespace types { - -RCNum::RCNum(common::CT attrt) : value_(0), scale_(0), is_double_(false), is_dot_(false), attr_type_(attrt) {} - -RCNum::RCNum(int64_t value_, short scale, bool is_double_, common::CT attrt) { - Assign(value_, scale, is_double_, attrt); -} - -RCNum::RCNum(double value_) - : value_(*(int64_t *)&value_), scale_(0), is_double_(true), is_dot_(false), attr_type_(common::CT::REAL) { - null = (value_ == NULL_VALUE_D ? true : false); -} - -RCNum::RCNum(const RCNum &rcn) - : ValueBasic(rcn), - value_(rcn.value_), - scale_(rcn.scale_), - is_double_(rcn.is_double_), - is_dot_(rcn.is_dot_), - attr_type_(rcn.attr_type_) { - null = rcn.null; -} - -RCNum::~RCNum() {} - -RCNum &RCNum::Assign(int64_t value_, short scale, bool is_double_, common::CT attrt) { - this->value_ = value_; - this->scale_ = scale; - this->is_double_ = is_double_; - this->attr_type_ = attrt; - - if (scale != -1 && !is_double_) { - if (scale != 0 || attrt == common::CT::UNK) { - is_dot_ = true; - this->attr_type_ = common::CT::NUM; - } - } - if (scale <= -1 && !is_double_) - scale_ = 0; - if (is_double_) { - if (!(this->attr_type_ == common::CT::REAL || this->attr_type_ == common::CT::FLOAT)) - this->attr_type_ = common::CT::REAL; - this->is_dot_ = false; - scale_ = 0; - null = (value_ == *(int64_t *)&NULL_VALUE_D ? true : false); - } else - null = (value_ == common::NULL_VALUE_64 ? true : false); - return *this; -} - -RCNum &RCNum::Assign(double value_) { - this->value_ = *(int64_t *)&value_; - this->scale_ = 0; - this->is_double_ = true; - this->is_dot_ = false; - this->attr_type_ = common::CT::REAL; - common::double_int_t v(value_); - null = (v.i == common::NULL_VALUE_64 ? true : false); - return *this; -} - -common::ErrorCode RCNum::Parse(const BString &rcs, RCNum &rcn, common::CT at) { - return ValueParserForText::Parse(rcs, rcn, at); -} - -common::ErrorCode RCNum::ParseReal(const BString &rcbs, RCNum &rcn, common::CT at) { - return ValueParserForText::ParseReal(rcbs, rcn, at); -} - -common::ErrorCode RCNum::ParseNum(const BString &rcs, RCNum &rcn, short scale) { - return ValueParserForText::ParseNum(rcs, rcn, scale); -} - -RCNum &RCNum::operator=(const RCNum &rcn) { - value_ = rcn.value_; - is_double_ = rcn.is_double_; - scale_ = rcn.scale_; - null = rcn.null; - attr_type_ = rcn.attr_type_; - return *this; -} - -RCNum &RCNum::operator=(const RCDataType &rcdt) { - if (rcdt.GetValueType() == ValueTypeEnum::NUMERIC_TYPE) - *this = (RCNum &)rcdt; - else { - RCNum rcn1; - if (common::IsError(RCNum::Parse(rcdt.ToBString(), rcn1, this->attr_type_))) { - *this = rcn1; - } else { - TIANMU_ERROR("Unsupported assign operation!"); - null = true; - } - } - return *this; -} - -common::CT RCNum::Type() const { return attr_type_; } - -bool RCNum::IsDecimal(ushort scale) const { - if (core::ATI::IsIntegerType(this->attr_type_)) { - return GetDecIntLen() <= (MAX_DEC_PRECISION - scale); - } else if (attr_type_ == common::CT::NUM) { - if (this->GetDecFractLen() <= scale) - return true; - if (scale_ > scale) - return value_ % (int64_t)Uint64PowOfTen(scale_ - scale) == 0; - return true; - } else { - double f = GetFractPart(); - return f == 0.0 || (fabs(f) >= (1.0 / (double)Uint64PowOfTen(scale))); - } - return false; -} - -bool RCNum::IsInt() const { - if (!is_double_) { - if ((value_ % (int64_t)Uint64PowOfTen(scale_)) != 0) { - return false; - } - return true; - } - return false; -} - -RCNum RCNum::ToDecimal(int scale) const { - int64_t tmpv = 0; - short tmpp = 0; - int sign = 1; - - if (is_double_) { - double intpart(0); - double fracpart(modf(*(double *)&value_, &intpart)); - - if (intpart < 0 || fracpart < 0) { - sign = -1; - intpart = fabs(intpart); - fracpart = fabs(fracpart); - } - - if (scale == -1) { - if (intpart >= Uint64PowOfTen(MAX_DEC_PRECISION)) { - if (sign != 1) - scale = 0; - } else { - int l = 0; - if (intpart != 0) - l = (int)floor(log10(intpart)) + 1; - scale = MAX_DEC_PRECISION - l; - } - } - - if (intpart >= Uint64PowOfTen(MAX_DEC_PRECISION)) { - tmpv = (Uint64PowOfTen(MAX_DEC_PRECISION) - 1); - } else - tmpv = (int64_t)intpart * Uint64PowOfTen(scale) + std::llround(fracpart * Uint64PowOfTen(scale)); - - tmpp = scale; - } else { - tmpv = this->value_; - tmpp = this->scale_; - if (scale != -1) { - if (tmpp > scale) - tmpv /= (int64_t)Uint64PowOfTen(tmpp - scale); - else - tmpv *= (int64_t)Uint64PowOfTen(scale - tmpp); - tmpp = scale; - } - } - return RCNum(tmpv * sign, tmpp); -} - -RCNum RCNum::ToReal() const { - if (core::ATI::IsRealType(attr_type_)) { - return RCNum(*(double *)&value_); - } - return RCNum((double)((double)(this->value_ / PowOfTen(scale_)))); -} - -RCNum RCNum::ToInt() const { return GetIntPart(); } - -static char *Text(int64_t value_, char buf[], int scale) { - bool sign = true; - if (value_ < 0) { - sign = false; - value_ *= -1; - } - longlong2str(value_, buf, 10); - int l = (int)std::strlen(buf); - std::memset(buf + l + 1, ' ', 21 - l); - int pos = 21; - int i = 0; - for (i = l; i >= 0; i--) { - if (scale != 0 && pos + scale == 20) { - buf[pos--] = '.'; - i++; - } else { - buf[pos--] = buf[i]; - buf[i] = ' '; - } - } - - if (scale >= l) { - buf[20 - scale] = '.'; - buf[20 - scale - 1] = '0'; - i = 20 - scale + 1; - while (buf[i] == ' ') buf[i++] = '0'; - } - pos = 0; - while (buf[pos] == ' ') pos++; - if (!sign) - buf[--pos] = '-'; - return buf + pos; -} - -BString RCNum::ToBString() const { - if (!IsNull()) { - static int const SIZE(24); - char buf[SIZE]; - if (core::ATI::IsRealType(attr_type_)) { - gcvt(*(double *)&value_, 15, buf); - size_t s = std::strlen(buf); - if (s && buf[s - 1] == '.') - buf[s - 1] = 0; - } else if (core::ATI::IsIntegerType(attr_type_)) - std::sprintf(buf, "%ld", value_); - else { - return BString(Text(value_, buf, scale_), 0, true); - } - return BString(buf, std::strlen(buf), true); - } - return BString(); -} - -RCNum::operator double() const { - return (core::ATI::IsRealType(Type()) || Type() == common::CT::FLOAT) ? *(double *)&value_ - : GetIntPart() + GetFractPart(); -} - -bool RCNum::operator==(const RCDataType &rcdt) const { - if (null || rcdt.IsNull()) - return false; - if (rcdt.GetValueType() == ValueTypeEnum::NUMERIC_TYPE) - return (compare((RCNum &)rcdt) == 0); - if (rcdt.GetValueType() == ValueTypeEnum::DATE_TIME_TYPE) - return (compare((RCDateTime &)rcdt) == 0); - if (rcdt.GetValueType() == ValueTypeEnum::STRING_TYPE) - return (rcdt == this->ToBString()); - TIANMU_ERROR("Bad cast inside RCNum"); - return false; -} - -bool RCNum::operator!=(const RCDataType &rcdt) const { - if (null || rcdt.IsNull()) - return false; - if (rcdt.GetValueType() == ValueTypeEnum::NUMERIC_TYPE) - return (compare((RCNum &)rcdt) != 0); - if (rcdt.GetValueType() == ValueTypeEnum::DATE_TIME_TYPE) - return (compare((RCDateTime &)rcdt) != 0); - if (rcdt.GetValueType() == ValueTypeEnum::STRING_TYPE) - return (rcdt != this->ToBString()); - TIANMU_ERROR("Bad cast inside RCNum"); - return false; -} - -bool RCNum::operator<(const RCDataType &rcdt) const { - if (IsNull() || rcdt.IsNull()) - return false; - if (rcdt.GetValueType() == ValueTypeEnum::NUMERIC_TYPE) - return (compare((RCNum &)rcdt) < 0); - if (rcdt.GetValueType() == ValueTypeEnum::DATE_TIME_TYPE) - return (compare((RCDateTime &)rcdt) < 0); - if (rcdt.GetValueType() == ValueTypeEnum::STRING_TYPE) - return (this->ToBString() < rcdt); - TIANMU_ERROR("Bad cast inside RCNum"); - return false; -} - -bool RCNum::operator>(const RCDataType &rcdt) const { - if (IsNull() || rcdt.IsNull()) - return false; - if (rcdt.GetValueType() == ValueTypeEnum::NUMERIC_TYPE) - return (compare((RCNum &)rcdt) > 0); - if (rcdt.GetValueType() == ValueTypeEnum::DATE_TIME_TYPE) - return (compare((RCDateTime &)rcdt) > 0); - if (rcdt.GetValueType() == ValueTypeEnum::STRING_TYPE) - return (this->ToBString() > rcdt); - TIANMU_ERROR("Bad cast inside RCNum"); - return false; -} - -bool RCNum::operator<=(const RCDataType &rcdt) const { - if (IsNull() || rcdt.IsNull()) - return false; - if (rcdt.GetValueType() == ValueTypeEnum::NUMERIC_TYPE) - return (compare((RCNum &)rcdt) <= 0); - if (rcdt.GetValueType() == ValueTypeEnum::DATE_TIME_TYPE) - return (compare((RCDateTime &)rcdt) <= 0); - if (rcdt.GetValueType() == ValueTypeEnum::STRING_TYPE) - return (this->ToBString() <= rcdt); - TIANMU_ERROR("Bad cast inside RCNum"); - return false; -} - -bool RCNum::operator>=(const RCDataType &rcdt) const { - if (null || rcdt.IsNull()) - return false; - if (rcdt.GetValueType() == ValueTypeEnum::NUMERIC_TYPE) - return (compare((RCNum &)rcdt) >= 0); - if (rcdt.GetValueType() == ValueTypeEnum::DATE_TIME_TYPE) - return (compare((RCDateTime &)rcdt) >= 0); - if (rcdt.GetValueType() == ValueTypeEnum::STRING_TYPE) - return (this->ToBString() >= rcdt); - TIANMU_ERROR("Bad cast inside RCNum"); - return false; -} - -RCNum &RCNum::operator-=(const RCNum &rcn) { - DEBUG_ASSERT(!null); - if (rcn.IsNull() || rcn.IsNull()) - return *this; - if (IsReal() || rcn.IsReal()) { - if (IsReal() && rcn.IsReal()) - *(double *)&value_ -= *(double *)&rcn.value_; - else { - if (IsReal()) - *this -= rcn.ToReal(); - else - *this -= rcn.ToDecimal(); - } - } else { - if (scale_ < rcn.scale_) { - value_ = ((int64_t)(value_ * PowOfTen(rcn.scale_ - scale_)) - rcn.value_); - scale_ = rcn.scale_; - } else { - value_ -= (int64_t)(rcn.value_ * PowOfTen(scale_ - rcn.scale_)); - } - } - return *this; -} - -RCNum &RCNum::operator+=(const RCNum &rcn) { - DEBUG_ASSERT(!null); - if (rcn.IsNull() || rcn.IsNull()) - return *this; - if (IsReal() || rcn.IsReal()) { - if (IsReal() && rcn.IsReal()) - *(double *)&value_ -= *(double *)&rcn.value_; - else { - if (IsReal()) - *this += rcn.ToReal(); - else - *this += rcn.ToDecimal(); - } - } else { - if (scale_ < rcn.scale_) { - value_ = ((int64_t)(value_ * PowOfTen(rcn.scale_ - scale_)) + rcn.value_); - scale_ = rcn.scale_; - } else { - value_ += (int64_t)(rcn.value_ * PowOfTen(scale_ - rcn.scale_)); - } - } - return *this; -} - -RCNum &RCNum::operator*=(const RCNum &rcn) { - DEBUG_ASSERT(!null); - if (rcn.IsNull() || rcn.IsNull()) - return *this; - if (IsReal() || rcn.IsReal()) { - if (IsReal() && rcn.IsReal()) - *(double *)&value_ -= *(double *)&rcn.value_; - else { - if (IsReal()) - *this /= rcn.ToReal(); - else - *this /= rcn.ToDecimal(); - } - } else { - value_ *= rcn.value_; - scale_ += rcn.scale_; - } - return *this; -} - -void fcvt(char *buf_, double val_, int digits_, int *dec_, int *sign_) { - static int const fmtlen = 10; - char format[fmtlen + 1]; - std::snprintf(format, fmtlen + 1, "%%.%df", digits_); - std::snprintf(buf_, digits_, format, val_); - int len(std::strlen(buf_)); - (*sign_) = (buf_[0] == '-') ? 1 : 0; - (*sign_) && std::memmove(buf_, buf_ + 1, len); - char *pbuf(buf_); - ::strsep(&pbuf, ".,"); - if (pbuf) { - (*dec_) = pbuf - buf_ - 1; - std::memmove(pbuf - 1, pbuf, std::strlen(pbuf) + 1); - } - return; -} - -RCNum &RCNum::operator/=(const RCNum &rcn) { - DEBUG_ASSERT(!null); - if (rcn.IsNull() || rcn.IsNull()) - return *this; - if (IsReal() || rcn.IsReal()) { - if (IsReal() && rcn.IsReal()) - *(double *)&value_ -= *(double *)&rcn.value_; - else { - if (IsReal()) - *this /= rcn.ToReal(); - else - *this /= rcn.ToDecimal(); - } - } else { - double tmv = ((double)(value_ / rcn.value_) / PowOfTen(scale_ - rcn.scale_)); - int decimal = 0; - int sign; - static int const MAX_NUM_DIGITS = 21 + 1; - char buf[MAX_NUM_DIGITS - 1]; - fcvt(buf, tmv, 18, &decimal, &sign); - buf[18] = 0; - ptrdiff_t lz = std::strlen(buf) - 1; - while (lz >= 0 && buf[lz--] == '0') - ; - buf[lz + 2] = 0; - value_ = std::strtoll(buf, NULL, 10) * (sign == 1 ? -1 : 1); - scale_ = (short)((lz + 2) - decimal); - } - return *this; -} - -RCNum RCNum::operator-(const RCNum &rcn) const { - RCNum res(*this); - return res -= rcn; -} - -RCNum RCNum::operator+(const RCNum &rcn) const { - RCNum res(*this); - return res += rcn; -} - -RCNum RCNum::operator*(const RCNum &rcn) const { - RCNum res(*this); - return res *= rcn; -} - -RCNum RCNum::operator/(const RCNum &rcn) const { - RCNum res(*this); - return res /= rcn; -} - -uint RCNum::GetHashCode() const { return uint(GetIntPart() * 1040021); } - -int RCNum::compare(const RCNum &rcn) const { - if (IsNull() || rcn.IsNull()) - return false; - if (IsReal() || rcn.IsReal()) { - if (IsReal() && rcn.IsReal()) - return (*(double *)&value_ > *(double *)&rcn.value_ ? 1 - : (*(double *)&value_ == *(double *)&rcn.value_ ? 0 : -1)); - else { - if (IsReal()) - return (*this > rcn.ToReal() ? 1 : (*this == rcn.ToReal() ? 0 : -1)); - else - return (this->ToReal() > rcn ? 1 : (this->ToReal() == rcn ? 0 : -1)); - } - } else { - if (scale_ != rcn.scale_) { - if (value_ < 0 && rcn.value_ >= 0) - return -1; - if (value_ >= 0 && rcn.value_ < 0) - return 1; - if (scale_ < rcn.scale_) { - int64_t power_of_ten = (int64_t)PowOfTen(rcn.scale_ - scale_); - int64_t tmpv = (int64_t)(rcn.value_ / power_of_ten); - if (value_ > tmpv) - return 1; - if (value_ < tmpv || rcn.value_ % power_of_ten > 0) - return -1; - if (rcn.value_ % power_of_ten < 0) - return 1; - return 0; - } else { - int64_t power_of_ten = (int64_t)PowOfTen(scale_ - rcn.scale_); - int64_t tmpv = (int64_t)(value_ / power_of_ten); - if (tmpv < rcn.value_) - return -1; - if (tmpv > rcn.value_ || value_ % power_of_ten > 0) - return 1; - if (value_ % power_of_ten < 0) - return -1; - return 0; - } - } else - return (value_ > rcn.value_ ? 1 : (value_ == rcn.value_ ? 0 : -1)); - } -} - -int RCNum::compare(const RCDateTime &rcdt) const { - int64_t tmp; - rcdt.ToInt64(tmp); - return int(GetIntPart() - tmp); -} - -double RCNum::GetIntPartAsDouble() const { - if (is_double_) { - double integer; - modf(*(double *)&value_, &integer); - return integer; - } else { - return (double)(value_ / (int64_t)Uint64PowOfTen(scale_)); - } -} - -double RCNum::GetFractPart() const { - if (is_double_) { - double fract, integer; - fract = modf(*(double *)&value_, &integer); - return fract; - } else { - double tmpv = ((double)value_ / Uint64PowOfTen(scale_)); - double fract, integer; - fract = modf(tmpv, &integer); - return fract; - } -} - -short RCNum::GetDecStrLen() const { - if (IsNull()) - return 0; - if (is_double_) - return 18; - short res = scale_; - int64_t tmpi = value_ / (int64_t)PowOfTen(scale_); - while (tmpi != 0) { - tmpi /= 10; - res++; - } - return res; -} - -short RCNum::GetDecIntLen() const { - if (IsNull()) - return 0; - short res = 0; - int64_t tmpi = 0; - if (is_double_) - tmpi = GetIntPart(); - else { - tmpi = value_ / (int64_t)PowOfTen(scale_); - } - while (tmpi != 0) { - tmpi /= 10; - res++; - } - return res; -} - -short RCNum::GetDecFractLen() const { - if (IsNull()) - return 0; - return scale_; -} - -void RCNum::Negate() { - if (IsNull()) - return; - if (is_double_) - *(double *)&value_ = *(double *)&value_ * -1; - else - value_ *= -1; -} - -} // namespace types -} // namespace Tianmu diff --git a/storage/tianmu/types/rc_num.h b/storage/tianmu/types/rc_num.h deleted file mode 100644 index 4a16c94e6df0ed8039a0f61dcbcb8b2ce4d63d5b..0000000000000000000000000000000000000000 --- a/storage/tianmu/types/rc_num.h +++ /dev/null @@ -1,118 +0,0 @@ -/* Copyright (c) 2022 StoneAtom, Inc. All rights reserved. - Use is subject to license terms - - 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-1335 USA -*/ -#ifndef TIANMU_TYPES_RC_NUM_H_ -#define TIANMU_TYPES_RC_NUM_H_ -#pragma once - -#include "types/rc_data_types.h" - -namespace Tianmu { -namespace types { - -class BString; - -class RCNum : public ValueBasic { - friend class ValueParserForText; - friend class Engine; - - public: - RCNum(common::CT attrt = common::CT::NUM); - RCNum(int64_t value, short scale = -1, bool dbl = false, common::CT attrt = common::CT::UNK); - RCNum(double value); - RCNum(const RCNum &); - ~RCNum(); - - RCNum &Assign(int64_t value, short scale = -1, bool dbl = false, common::CT attrt = common::CT::UNK); - RCNum &Assign(double value); - - static common::ErrorCode Parse(const BString &rcs, RCNum &rcn, common::CT at = common::CT::UNK); - static common::ErrorCode ParseReal(const BString &, RCNum &, common::CT at); - static common::ErrorCode ParseNum(const BString &, RCNum &, short scale = -1); - - RCNum &operator=(const RCNum &rcn); - RCNum &operator=(const RCDataType &rcdt) override; - - common::CT Type() const override; - - bool operator==(const RCDataType &rcdt) const override; - bool operator<(const RCDataType &rcdt) const override; - bool operator>(const RCDataType &rcdt) const override; - bool operator>=(const RCDataType &rcdt) const override; - bool operator<=(const RCDataType &rcdt) const override; - bool operator!=(const RCDataType &rcdt) const override; - - RCNum &operator-=(const RCNum &rcn); - RCNum &operator+=(const RCNum &rcn); - RCNum &operator*=(const RCNum &rcn); - RCNum &operator/=(const RCNum &rcn); - - RCNum operator-(const RCNum &rcn) const; - RCNum operator+(const RCNum &rcn) const; - RCNum operator*(const RCNum &rcn) const; - RCNum operator/(const RCNum &rcn) const; - - bool IsDecimal(ushort scale) const; - bool IsReal() const { return is_double_; } - bool IsInt() const; - - BString ToBString() const override; - RCNum ToDecimal(int scale = -1) const; - RCNum ToReal() const; - RCNum ToInt() const; - - operator int64_t() const { return GetIntPart(); } - operator double() const; - operator float() const { return (float)(double)*this; } - - short Scale() const { return scale_; } - int64_t ValueInt() const { return value_; } - char *GetDataBytesPointer() const override { return (char *)&value_; } - int64_t GetIntPart() const { - return is_double_ ? (int64_t)GetIntPartAsDouble() : value_ / (int64_t)Uint64PowOfTen(scale_); - } - - int64_t GetValueInt64() const { return value_; } - double GetIntPartAsDouble() const; - double GetFractPart() const; - - short GetDecStrLen() const; - short GetDecIntLen() const; - short GetDecFractLen() const; - - uint GetHashCode() const override; - void Negate(); - - private: - int compare(const RCNum &rcn) const; - int compare(const RCDateTime &rcn) const; - - private: - static constexpr int MAX_DEC_PRECISION = 18; - int64_t value_; - ushort scale_; // means 'scale' actually - bool is_double_; - bool is_dot_; - common::CT attr_type_; - - public: - const static ValueTypeEnum value_type = ValueTypeEnum::NUMERIC_TYPE; -}; - -} // namespace types -} // namespace Tianmu - -#endif // TIANMU_TYPES_RC_NUM_H_ diff --git a/storage/tianmu/types/rc_value_object.cpp b/storage/tianmu/types/rc_value_object.cpp deleted file mode 100644 index fa3498c3899d32f8527ac7bd4ec959a311aa9c09..0000000000000000000000000000000000000000 --- a/storage/tianmu/types/rc_value_object.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* Copyright (c) 2022 StoneAtom, Inc. All rights reserved. - Use is subject to license terms - - 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-1335 USA -*/ - -#include "types/rc_num.h" - -namespace Tianmu { -namespace types { - -RCValueObject::RCValueObject() {} - -RCValueObject::RCValueObject(const RCValueObject &rcvo) { - if (rcvo.value.get()) - construct(*rcvo.value); -} - -RCValueObject::RCValueObject(const RCDataType &rcdt) { construct(rcdt); } - -RCValueObject::~RCValueObject() {} - -RCValueObject &RCValueObject::operator=(const RCValueObject &rcvo) { - if (rcvo.value.get()) - construct(*rcvo.value); - else - value.reset(); - return *this; -} - -inline void RCValueObject::construct(const RCDataType &rcdt) { value = rcdt.Clone(); } - -bool RCValueObject::compare(const RCValueObject &rcvo1, const RCValueObject &rcvo2, common::Operator op, - char like_esc) { - if (rcvo1.IsNull() || rcvo2.IsNull()) - return false; - else - return RCDataType::compare(*rcvo1.value, *rcvo2.value, op, like_esc); -} - -bool RCValueObject::compare(const RCValueObject &rcvo, common::Operator op, char like_esc) const { - return compare(*this, rcvo, op, like_esc); -} - -bool RCValueObject::operator==(const RCValueObject &rcvo) const { - if (IsNull() || rcvo.IsNull()) - return false; - return *value == *rcvo.value; -} - -bool RCValueObject::operator<(const RCValueObject &rcvo) const { - if (IsNull() || rcvo.IsNull()) - return false; - return *value < *rcvo.value; -} - -bool RCValueObject::operator>(const RCValueObject &rcvo) const { - if (IsNull() || rcvo.IsNull()) - return false; - return *value > *rcvo.value; -} - -bool RCValueObject::operator>=(const RCValueObject &rcvo) const { - if (IsNull() || rcvo.IsNull()) - return false; - return *value >= *rcvo.value; -} - -bool RCValueObject::operator<=(const RCValueObject &rcvo) const { - if (IsNull() || rcvo.IsNull()) - return false; - return *value <= *rcvo.value; -} - -bool RCValueObject::operator!=(const RCValueObject &rcvo) const { - if (IsNull() || rcvo.IsNull()) - return false; - return *value != *rcvo.value; -} - -bool RCValueObject::operator==(const RCDataType &rcn) const { - if (IsNull() || rcn.IsNull()) - return false; - return *value == rcn; -} - -bool RCValueObject::operator<(const RCDataType &rcn) const { - if (IsNull() || rcn.IsNull()) - return false; - return *value < rcn; -} - -bool RCValueObject::operator>(const RCDataType &rcn) const { - if (IsNull() || rcn.IsNull()) - return false; - return *value > rcn; -} - -bool RCValueObject::operator>=(const RCDataType &rcn) const { - if (IsNull() || rcn.IsNull()) - return false; - return *value >= rcn; -} - -bool RCValueObject::operator<=(const RCDataType &rcdt) const { - if (IsNull() || rcdt.IsNull()) - return false; - return *value <= rcdt; -} - -bool RCValueObject::operator!=(const RCDataType &rcn) const { - if (IsNull() || rcn.IsNull()) - return false; - return *value != rcn; -} - -bool RCValueObject::IsNull() const { return value.get() ? value->IsNull() : true; } - -RCDataType &RCValueObject::operator*() const { return value.get() ? *value.get() : RCNum::NullValue(); } - -RCValueObject::operator RCNum &() const { - if (IsNull()) - return RCNum::NullValue(); - if (GetValueType() == ValueTypeEnum::NUMERIC_TYPE || GetValueType() == ValueTypeEnum::DATE_TIME_TYPE) - return static_cast(*value); - - TIANMU_ERROR("Bad cast in RCValueObject::RCNum&()"); - return static_cast(*value); -} - -RCValueObject::operator RCDateTime &() const { - if (IsNull()) - return RCDateTime::NullValue(); - if (GetValueType() == ValueTypeEnum::DATE_TIME_TYPE) - return static_cast(*value); - - TIANMU_ERROR("Bad cast in RCValueObject::RCDateTime&()"); - return static_cast(*value); -} - -BString RCValueObject::ToBString() const { - if (IsNull()) - return BString(); - return value->ToBString(); -} - -uint RCValueObject::GetHashCode() const { - if (IsNull()) - return 0; - return value->GetHashCode(); -} - -} // namespace types -} // namespace Tianmu