From a374a070ddc9343578ca97a3eb013413c90f7bba Mon Sep 17 00:00:00 2001 From: hustjieke Date: Tue, 23 May 2023 06:18:42 +0000 Subject: [PATCH] feat(tianmu): limit unsigned range #1716 --- .../tianmu/r/out_of_range_issue1151.result | 191 ++++++++++++++++++ .../tianmu/t/out_of_range_issue1151.test | 189 +++++++++++++++++ storage/tianmu/common/common_definitions.cpp | 70 +++++++ storage/tianmu/common/common_definitions.h | 7 + storage/tianmu/core/engine.cpp | 55 +---- storage/tianmu/core/engine.h | 2 +- storage/tianmu/core/rc_table.cpp | 18 +- 7 files changed, 481 insertions(+), 51 deletions(-) create mode 100644 mysql-test/suite/tianmu/r/out_of_range_issue1151.result create mode 100644 mysql-test/suite/tianmu/t/out_of_range_issue1151.test diff --git a/mysql-test/suite/tianmu/r/out_of_range_issue1151.result b/mysql-test/suite/tianmu/r/out_of_range_issue1151.result new file mode 100644 index 000000000..9e10f9fa8 --- /dev/null +++ b/mysql-test/suite/tianmu/r/out_of_range_issue1151.result @@ -0,0 +1,191 @@ +drop database if exists out_of_range_issue1151; +create database test; +create database out_of_range_issue1151; +use out_of_range_issue1151; +create table tiny(a tinyint, b tinyint unsigned) engine = tianmu DEFAULT CHARSET=utf8mb4; +insert into tiny values(-128, 0); +insert into tiny values(127, 127); +insert into tiny values(0, 127); +insert into tiny values(-0, -0); +insert into tiny values(+0, +0); +select * from tiny; +a b +-128 0 +127 127 +0 127 +0 0 +0 0 +insert into tiny values(-129, 0); +ERROR 22003: Out of range value for column 'a' at row 1 +insert into tiny values(128, 0); +ERROR 22003: Out of range value for column 'a' at row 1 +insert into tiny values(1234, 0); +ERROR 22003: Out of range value for column 'a' at row 1 +insert into tiny values(0, 128); +ERROR 22003: Out of range[0, 127] for column 'b' value: 128 +insert into tiny values(0, 255); +ERROR 22003: Out of range[0, 127] for column 'b' value: 255 +insert into tiny values(0, -1); +ERROR 22003: Out of range value for column 'b' at row 1 +insert into tiny values(0, -127); +ERROR 22003: Out of range value for column 'b' at row 1 +insert into tiny values(0, 256); +ERROR 22003: Out of range value for column 'b' at row 1 +insert into tiny values(0, 1234567); +ERROR 22003: Out of range value for column 'b' at row 1 +drop table tiny; +create table small(a smallint, b smallint unsigned) engine = tianmu DEFAULT CHARSET=utf8mb4; +insert into small values(-32768, 0); +insert into small values(0, 0); +insert into small values(122, 122); +insert into small values(32767, 32767); +insert into small values(-0, -0); +insert into small values(+0, +0); +select * from small; +a b +-32768 0 +0 0 +122 122 +32767 32767 +0 0 +0 0 +insert into small values(-32769, 0); +ERROR 22003: Out of range value for column 'a' at row 1 +insert into small values(32768, 0); +ERROR 22003: Out of range value for column 'a' at row 1 +insert into small values(-3276911, 0); +ERROR 22003: Out of range value for column 'a' at row 1 +insert into small values(3276811, 0); +ERROR 22003: Out of range value for column 'a' at row 1 +insert into small values(0, 32768); +ERROR 22003: Out of range[0, 32767] for column 'b' value: 32768 +insert into small values(0, 41234); +ERROR 22003: Out of range[0, 32767] for column 'b' value: 41234 +insert into small values(0, 65535); +ERROR 22003: Out of range[0, 32767] for column 'b' value: 65535 +insert into small values(0, -1); +ERROR 22003: Out of range value for column 'b' at row 1 +insert into small values(0, -32768); +ERROR 22003: Out of range value for column 'b' at row 1 +insert into small values(0, 65536); +ERROR 22003: Out of range value for column 'b' at row 1 +insert into small values(0, 1234567); +ERROR 22003: Out of range value for column 'b' at row 1 +drop table small; +create table medium(a mediumint, b mediumint unsigned) engine = tianmu DEFAULT CHARSET=utf8mb4; +insert into medium values(-8388608, 0); +insert into medium values(0, 0); +insert into medium values(122, 122); +insert into medium values(8388607, 8388607); +insert into medium values(-0, -0); +insert into medium values(+0, +0); +select * from medium; +a b +-8388608 0 +0 0 +122 122 +8388607 8388607 +0 0 +0 0 +insert into medium values(-8388609, 0); +ERROR 22003: Out of range value for column 'a' at row 1 +insert into medium values(8388608, 0); +ERROR 22003: Out of range value for column 'a' at row 1 +insert into medium values(-8388608111, 0); +ERROR 22003: Out of range value for column 'a' at row 1 +insert into medium values(8388608111, 0); +ERROR 22003: Out of range value for column 'a' at row 1 +insert into medium values(0, 8388608); +ERROR 22003: Out of range[0, 8388607] for column 'b' value: 8388608 +insert into medium values(0, 8388610); +ERROR 22003: Out of range[0, 8388607] for column 'b' value: 8388610 +insert into medium values(0, 16777215); +ERROR 22003: Out of range[0, 8388607] for column 'b' value: 16777215 +insert into medium values(0, -1); +ERROR 22003: Out of range value for column 'b' at row 1 +insert into medium values(0, -8388608); +ERROR 22003: Out of range value for column 'b' at row 1 +insert into medium values(0, 16777216); +ERROR 22003: Out of range value for column 'b' at row 1 +insert into medium values(0, 1677721511); +ERROR 22003: Out of range value for column 'b' at row 1 +drop table medium; +create table int_(a int, b int unsigned) engine = tianmu DEFAULT CHARSET=utf8mb4; +insert into int_ values(-2147483647, 0); +insert into int_ values(0, 0); +insert into int_ values(122, 122); +insert into int_ values(2147483647, 2147483647); +insert into int_ values(-0, -0); +insert into int_ values(+0, +0); +select * from int_; +a b +-2147483647 0 +0 0 +122 122 +2147483647 2147483647 +0 0 +0 0 +insert into int_ values(-2147483649, 0); +ERROR 22003: Out of range value for column 'a' at row 1 +insert into int_ values(2147483648, 0); +ERROR 22003: Out of range value for column 'a' at row 1 +insert into int_ values(-214748364811, 0); +ERROR 22003: Out of range value for column 'a' at row 1 +insert into int_ values(214748364811, 0); +ERROR 22003: Out of range value for column 'a' at row 1 +insert into int_ values(-2147483648, 0); +ERROR 22003: Out of range[-2147483647, 2147483647] for column 'a' value: -2147483648 +insert into int_ values(0, 2147483648); +ERROR 22003: Out of range[0, 2147483647] for column 'b' value: 2147483648 +insert into int_ values(0, 3294967295); +ERROR 22003: Out of range[0, 2147483647] for column 'b' value: 3294967295 +insert into int_ values(0, 4294967295); +ERROR 22003: Out of range[0, 2147483647] for column 'b' value: 4294967295 +insert into int_ values(0, -1); +ERROR 22003: Out of range value for column 'b' at row 1 +insert into int_ values(0, -4294967295); +ERROR 22003: Out of range value for column 'b' at row 1 +insert into int_ values(0, 4294967296); +ERROR 22003: Out of range value for column 'b' at row 1 +insert into int_ values(0, 429496729611); +ERROR 22003: Out of range value for column 'b' at row 1 +drop table int_; +create table bigint_(a bigint, b bigint unsigned) engine = tianmu DEFAULT CHARSET=utf8mb4; +insert into bigint_ values(-9223372036854775806, 0); +insert into bigint_ values(0, 0); +insert into bigint_ values(122, 122); +insert into bigint_ values(9223372036854775807, 9223372036854775807); +insert into bigint_ values(-0, -0); +insert into bigint_ values(+0, +0); +select * from bigint_; +a b +-9223372036854775806 0 +0 0 +122 122 +9223372036854775807 9223372036854775807 +0 0 +0 0 +insert into bigint_ values(-9223372036854775808, 0); +ERROR 22003: Out of range[-9223372036854775807, 9223372036854775807] for column 'a' value: -9223372036854775808 +insert into bigint_ values(9223372036854775808, 0); +ERROR 22003: Out of range value for column 'a' at row 1 +insert into bigint_ values(-9223372036854775810, 0); +ERROR 22003: Out of range value for column 'a' at row 1 +insert into bigint_ values(9223372036854775810, 0); +ERROR 22003: Out of range value for column 'a' at row 1 +insert into bigint_ values(0, 9223372036854775808); +ERROR 22003: Out of range[0, 9223372036854775807] for column 'b' value: 9223372036854775808 +insert into bigint_ values(0, 10223372036854775808); +ERROR 22003: Out of range[0, 9223372036854775807] for column 'b' value: 10223372036854775808 +insert into bigint_ values(0, 18446744073709551615); +ERROR 22003: Out of range[0, 9223372036854775807] for column 'b' value: 18446744073709551615 +insert into bigint_ values(0, -1); +ERROR 22003: Out of range value for column 'b' at row 1 +insert into bigint_ values(0, -4294967295); +ERROR 22003: Out of range value for column 'b' at row 1 +insert into bigint_ values(0, 18446744073709551616); +ERROR 22003: Out of range value for column 'b' at row 1 +insert into bigint_ values(0, 1844674407370955161566); +ERROR 22003: Out of range value for column 'b' at row 1 +drop table bigint_; +drop database out_of_range_issue1151; diff --git a/mysql-test/suite/tianmu/t/out_of_range_issue1151.test b/mysql-test/suite/tianmu/t/out_of_range_issue1151.test new file mode 100644 index 000000000..8095f33a2 --- /dev/null +++ b/mysql-test/suite/tianmu/t/out_of_range_issue1151.test @@ -0,0 +1,189 @@ +--source include/have_tianmu.inc + +--disable_warnings +drop database if exists out_of_range_issue1151; +--enable_warnings +create database out_of_range_issue1151; +use out_of_range_issue1151; +create table tiny(a tinyint, b tinyint unsigned) engine = tianmu DEFAULT CHARSET=utf8mb4; +# test insert correctly +insert into tiny values(-128, 0); +insert into tiny values(127, 127); +insert into tiny values(0, 127); +insert into tiny values(-0, -0); +insert into tiny values(+0, +0); +select * from tiny; +# test out of range, currently the max value of unsigned is equal to signed +# column signed a out of value +--error 1264 +insert into tiny values(-129, 0); +--error 1264 +insert into tiny values(128, 0); +--error 1264 +insert into tiny values(1234, 0); +# column unsigned b out of value[128, 255], deal with tianmu +--error 1264 +insert into tiny values(0, 128); +--error 1264 +insert into tiny values(0, 255); +# column unsigned b out of value(>255 || <0), deal with mysql +--error 1264 +insert into tiny values(0, -1); +--error 1264 +insert into tiny values(0, -127); +--error 1264 +insert into tiny values(0, 256); +--error 1264 +insert into tiny values(0, 1234567); +drop table tiny; + +create table small(a smallint, b smallint unsigned) engine = tianmu DEFAULT CHARSET=utf8mb4; +# test insert correctly +insert into small values(-32768, 0); +insert into small values(0, 0); +insert into small values(122, 122); +insert into small values(32767, 32767); +insert into small values(-0, -0); +insert into small values(+0, +0); +select * from small; +# test out of range, currently the max value of unsigned is equal to signed +# column signed a out of value +--error 1264 +insert into small values(-32769, 0); +--error 1264 +insert into small values(32768, 0); +--error 1264 +insert into small values(-3276911, 0); +--error 1264 +insert into small values(3276811, 0); +# column unsigned b out of value[32768, 65535], deal with tianmu +--error 1264 +insert into small values(0, 32768); +--error 1264 +insert into small values(0, 41234); +--error 1264 +insert into small values(0, 65535); +# column unsigned b out of value(>65535 || <0), deal with mysql +--error 1264 +insert into small values(0, -1); +--error 1264 +insert into small values(0, -32768); +--error 1264 +insert into small values(0, 65536); +--error 1264 +insert into small values(0, 1234567); +drop table small; + +create table medium(a mediumint, b mediumint unsigned) engine = tianmu DEFAULT CHARSET=utf8mb4; +# test insert correctly +insert into medium values(-8388608, 0); +insert into medium values(0, 0); +insert into medium values(122, 122); +insert into medium values(8388607, 8388607); +insert into medium values(-0, -0); +insert into medium values(+0, +0); +select * from medium; +# test out of range, currently the max value of unsigned is equal to signed +# column signed a out of value +--error 1264 +insert into medium values(-8388609, 0); +--error 1264 +insert into medium values(8388608, 0); +--error 1264 +insert into medium values(-8388608111, 0); +--error 1264 +insert into medium values(8388608111, 0); +# column unsigned b out of value[8388608, 16777215], deal with tianmu +--error 1264 +insert into medium values(0, 8388608); +--error 1264 +insert into medium values(0, 8388610); +--error 1264 +insert into medium values(0, 16777215); +# column unsigned b out of value(>8388607 || <0), deal with mysql +--error 1264 +insert into medium values(0, -1); +--error 1264 +insert into medium values(0, -8388608); +--error 1264 +insert into medium values(0, 16777216); +--error 1264 +insert into medium values(0, 1677721511); +drop table medium; + +create table int_(a int, b int unsigned) engine = tianmu DEFAULT CHARSET=utf8mb4; +# test insert correctly, range[-2147483647, 2147483647] +insert into int_ values(-2147483647, 0); +insert into int_ values(0, 0); +insert into int_ values(122, 122); +insert into int_ values(2147483647, 2147483647); +insert into int_ values(-0, -0); +insert into int_ values(+0, +0); +select * from int_; +# test out of range, currently the max value of unsigned is equal to signed +# column signed a out of value +--error 1264 +insert into int_ values(-2147483649, 0); +--error 1264 +insert into int_ values(2147483648, 0); +--error 1264 +insert into int_ values(-214748364811, 0); +--error 1264 +insert into int_ values(214748364811, 0); +# column unsigned b out of value[2147483648, 4294967295], deal with tianmu, -2147483648 also deal with tianmu +--error 1264 +insert into int_ values(-2147483648, 0); +--error 1264 +insert into int_ values(0, 2147483648); +--error 1264 +insert into int_ values(0, 3294967295); +--error 1264 +insert into int_ values(0, 4294967295); +# column unsigned b out of value(>4294967295 || <0), deal with mysql +--error 1264 +insert into int_ values(0, -1); +--error 1264 +insert into int_ values(0, -4294967295); +--error 1264 +insert into int_ values(0, 4294967296); +--error 1264 +insert into int_ values(0, 429496729611); +drop table int_; + +create table bigint_(a bigint, b bigint unsigned) engine = tianmu DEFAULT CHARSET=utf8mb4; +# test insert correctly, range [-9223372036854775806, 9223372036854775807] +insert into bigint_ values(-9223372036854775806, 0); +insert into bigint_ values(0, 0); +insert into bigint_ values(122, 122); +insert into bigint_ values(9223372036854775807, 9223372036854775807); +insert into bigint_ values(-0, -0); +insert into bigint_ values(+0, +0); +select * from bigint_; +# test out of range, currently the max value of unsigned is equal to signed +# column signed a out of value, -9223372036854775808 ret error and -9223372036854775807(null) +--error 1264 +insert into bigint_ values(-9223372036854775808, 0); +--error 1264 +insert into bigint_ values(9223372036854775808, 0); +--error 1264 +insert into bigint_ values(-9223372036854775810, 0); +--error 1264 +insert into bigint_ values(9223372036854775810, 0); +# column unsigned b out of value[9223372036854775808, 18446744073709551615], deal with tianmu +--error 1264 +insert into bigint_ values(0, 9223372036854775808); +--error 1264 +insert into bigint_ values(0, 10223372036854775808); +--error 1264 +insert into bigint_ values(0, 18446744073709551615); +# column unsigned b out of value(>18446744073709551615 || <0), deal with mysql +--error 1264 +insert into bigint_ values(0, -1); +--error 1264 +insert into bigint_ values(0, -4294967295); +--error 1264 +insert into bigint_ values(0, 18446744073709551616); +--error 1264 +insert into bigint_ values(0, 1844674407370955161566); +drop table bigint_; +drop database out_of_range_issue1151; diff --git a/storage/tianmu/common/common_definitions.cpp b/storage/tianmu/common/common_definitions.cpp index fbdd1f713..2745ca006 100644 --- a/storage/tianmu/common/common_definitions.cpp +++ b/storage/tianmu/common/common_definitions.cpp @@ -32,6 +32,76 @@ void PushWarning(THD *thd, Sql_condition::enum_severity_level level, uint code, push_warning(thd, level, code, msg); } +// Here for args int `type`, we do not use enum directly as it'll caused compiling failed for the dependent package. +void PushWarningIfOutOfRange(THD *thd, std::string col_name, int64_t v, int type, bool unsigned_flag) { + // below `0` is for min unsigned value. + switch (type) { + case 1: { // MYSQL_TYPE_TINY + if (unsigned_flag && (static_cast(v) > TIANMU_TINYINT_MAX)) { + PushWarning(thd, Sql_condition::SL_WARNING, ER_WARN_DATA_OUT_OF_RANGE, + getErrMsg(col_name, 0, TIANMU_TINYINT_MAX, unsigned_flag, v).c_str()); + throw std::exception(); + } else if (v > TIANMU_TINYINT_MAX || v < TIANMU_TINYINT_MIN) { + PushWarning(thd, Sql_condition::SL_WARNING, ER_WARN_DATA_OUT_OF_RANGE, + getErrMsg(col_name, TIANMU_TINYINT_MIN, TIANMU_TINYINT_MAX, unsigned_flag, v).c_str()); + throw std::exception(); + } + } break; + case 2: { // MYSQL_TYPE_SHORT + if (unsigned_flag && (static_cast(v) > TIANMU_SMALLINT_MAX)) { + PushWarning(thd, Sql_condition::SL_WARNING, ER_WARN_DATA_OUT_OF_RANGE, + getErrMsg(col_name, 0, TIANMU_SMALLINT_MAX, unsigned_flag, v).c_str()); + } else if (v > TIANMU_SMALLINT_MAX || v < TIANMU_SMALLINT_MIN) { + PushWarning(thd, Sql_condition::SL_WARNING, ER_WARN_DATA_OUT_OF_RANGE, + getErrMsg(col_name, TIANMU_SMALLINT_MIN, TIANMU_SMALLINT_MAX, unsigned_flag, v).c_str()); + }; + } break; + case 9: { // MYSQL_TYPE_INT24 + if (unsigned_flag && (static_cast(v) > TIANMU_MEDIUMINT_MAX)) { + PushWarning(thd, Sql_condition::SL_WARNING, ER_WARN_DATA_OUT_OF_RANGE, + getErrMsg(col_name, 0, TIANMU_MEDIUMINT_MAX, unsigned_flag, v).c_str()); + } else if (v > TIANMU_MEDIUMINT_MAX || v < TIANMU_MEDIUMINT_MIN) { + PushWarning(thd, Sql_condition::SL_WARNING, ER_WARN_DATA_OUT_OF_RANGE, + getErrMsg(col_name, TIANMU_MEDIUMINT_MIN, TIANMU_MEDIUMINT_MAX, unsigned_flag, v).c_str()); + } + } break; + case 3: { // MYSQL_TYPE_LONG + if (unsigned_flag && (static_cast(v) > TIANMU_INT_MAX)) { + PushWarning(thd, Sql_condition::SL_WARNING, ER_WARN_DATA_OUT_OF_RANGE, + getErrMsg(col_name, 0, TIANMU_INT_MAX, unsigned_flag, v).c_str()); + } else if (v > TIANMU_INT_MAX || v < TIANMU_INT_MIN) { + PushWarning(thd, Sql_condition::SL_WARNING, ER_WARN_DATA_OUT_OF_RANGE, + getErrMsg(col_name, TIANMU_INT_MIN, TIANMU_INT_MAX, unsigned_flag, v).c_str()); + } + } break; + case 8: { // MYSQL_TYPE_LONGLONG + if (unsigned_flag && (static_cast(v) > TIANMU_BIGINT_MAX)) { + PushWarning(thd, Sql_condition::SL_WARNING, ER_WARN_DATA_OUT_OF_RANGE, + getErrMsg(col_name, 0, TIANMU_BIGINT_MAX, unsigned_flag, v).c_str()); + } else if (v > TIANMU_BIGINT_MAX || v < TIANMU_BIGINT_MIN) { + PushWarning(thd, Sql_condition::SL_WARNING, ER_WARN_DATA_OUT_OF_RANGE, + getErrMsg(col_name, TIANMU_BIGINT_MIN, TIANMU_BIGINT_MAX, unsigned_flag, v).c_str()); + } + } break; + default: // For type which is not integer, nothing to do + break; + } +} + +// Msg: Out of range[min, max] for column 'col' value: 123 +// Just for unsigned type check in tianmu engine. +std::string getErrMsg(std::string col_name, int64_t min, int64_t max, bool unsigned_flag, int64_t v) { + std::string str = "Out of range["; + str += std::to_string(min); + str += ", "; + str += std::to_string(max); + str += "] for column '"; + str += col_name; + str += "' value: "; + str += unsigned_flag ? std::to_string(static_cast(v)) : std::to_string(v); + return str; +} + std::string TX_ID::ToString() const { std::stringstream ss; ss << std::setfill('0') << std::setw(sizeof(v) * 2) << std::hex << v; diff --git a/storage/tianmu/common/common_definitions.h b/storage/tianmu/common/common_definitions.h index a50553c65..6fa4b9d3b 100644 --- a/storage/tianmu/common/common_definitions.h +++ b/storage/tianmu/common/common_definitions.h @@ -38,6 +38,8 @@ constexpr size_t operator""_GB(unsigned long long v) { return 1024u * 1024u * 10 namespace common { extern void PushWarning(THD *thd, Sql_condition::enum_severity_level level, uint code, const char *msg); +extern void PushWarningIfOutOfRange(THD *thd, std::string col_name, int64_t v, int type, bool unsigned_flag); +std::string getErrMsg(std::string col_name, int64_t min, int64_t max, bool unsigned_flag, int64_t v); // Column Type // NOTE: do not change the order of implemented data types! Stored as int(...) @@ -93,13 +95,18 @@ constexpr int64_t TIANMU_BIGINT_MAX = PLUS_INF_64; constexpr int64_t TIANMU_BIGINT_MIN = NULL_VALUE_64; #define NULL_VALUE_D (*reinterpret_cast("\x01\x00\x00\x00\x00\x00\x00\x80")) +#define TIANMU_INT_MAX (2147483647) #define TIANMU_INT_MIN (-2147483647) +#define TIANMU_INT_UNSIGNED_MAX (0xFFFFFFFFULL) #define TIANMU_MEDIUMINT_MAX ((1 << 23) - 1) #define TIANMU_MEDIUMINT_MIN (-((1 << 23))) +#define TIANMU_MEDIUMINT_UNSIGNED_MAX ((1 << 24) - 1) #define TIANMU_TINYINT_MAX 127 #define TIANMU_TINYINT_MIN (-128) +#define TIANMU_TINYINT_UNSIGNED_MAX 255 #define TIANMU_SMALLINT_MAX ((1 << 15) - 1) #define TIANMU_SMALLINT_MIN (-(1 << 15)) +#define TIANMU_SMALLINT_UNSIGNED_MAX ((1 << 16) - 1) #define PACK_INVALID 0 #define FIELD_MAXLENGTH 65535 diff --git a/storage/tianmu/core/engine.cpp b/storage/tianmu/core/engine.cpp index 2c1285abf..d23a25f40 100644 --- a/storage/tianmu/core/engine.cpp +++ b/storage/tianmu/core/engine.cpp @@ -382,7 +382,7 @@ Engine::~Engine() { } void Engine::EncodeRecord(const std::string &table_path, int table_id, Field **field, size_t col, size_t blobs, - std::unique_ptr &buf, uint32_t &size) { + std::unique_ptr &buf, uint32_t &size, THD *thd) { size = blobs > 0 ? 4_MB : 128_KB; buf.reset(new char[size]); utils::BitSet null_mask(col); @@ -435,49 +435,14 @@ void Engine::EncodeRecord(const std::string &table_path, int table_id, Field **f } 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_TINY: + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_INT24: 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; + common::PushWarningIfOutOfRange(thd, std::string(f->field_name), v, f->type(), f->is_flag_set(UNSIGNED_FLAG)); + *reinterpret_cast(ptr) = v; ptr += sizeof(int64_t); } break; case MYSQL_TYPE_DECIMAL: @@ -1463,7 +1428,7 @@ void Engine::InsertDelayed(const std::string &table_path, int table_id, TABLE *t uint32_t buf_sz = 0; std::unique_ptr buf; - EncodeRecord(table_path, table_id, table->field, table->s->fields, table->s->blob_fields, buf, buf_sz); + EncodeRecord(table_path, table_id, table->field, table->s->fields, table->s->blob_fields, buf, buf_sz, table->in_use); int failed = 0; while (true) { @@ -1490,7 +1455,8 @@ void Engine::InsertMemRow(const std::string &table_path, std::shared_ptr buf; - EncodeRecord(table_path, share->TabID(), table->field, table->s->fields, table->s->blob_fields, buf, buf_sz); + EncodeRecord(table_path, share->TabID(), table->field, table->s->fields, table->s->blob_fields, buf, buf_sz, + table->in_use); auto rctable = share->GetSnapshot(); rctable->InsertMemRow(std::move(buf), buf_sz); } @@ -1516,6 +1482,7 @@ int Engine::InsertRow(const std::string &table_path, [[maybe_unused]] Transactio TIANMU_LOG(LogCtl_Level::ERROR, "delayed inserting failed. %s %s", e.what(), e.trace().c_str()); } catch (std::exception &e) { TIANMU_LOG(LogCtl_Level::ERROR, "delayed inserting failed. %s", e.what()); + ret = 1; } catch (...) { TIANMU_LOG(LogCtl_Level::ERROR, "delayed inserting failed."); } diff --git a/storage/tianmu/core/engine.h b/storage/tianmu/core/engine.h index 03ba6dcbb..5db0447f0 100644 --- a/storage/tianmu/core/engine.h +++ b/storage/tianmu/core/engine.h @@ -207,7 +207,7 @@ class Engine final { void ProcessDelayedMerge(); std::unique_ptr GetRecord(size_t &len); void EncodeRecord(const std::string &table_path, int table_id, Field **field, size_t col, size_t blobs, - std::unique_ptr &buf, uint32_t &size); + std::unique_ptr &buf, uint32_t &size, THD *thd); private: struct TianmuStat { diff --git a/storage/tianmu/core/rc_table.cpp b/storage/tianmu/core/rc_table.cpp index 573fe573d..f41e57de8 100644 --- a/storage/tianmu/core/rc_table.cpp +++ b/storage/tianmu/core/rc_table.cpp @@ -599,20 +599,27 @@ void RCTable::Field2VC(Field *f, loader::ValueCache &vc, size_t col) { case MYSQL_TYPE_LONG: case MYSQL_TYPE_INT24: case MYSQL_TYPE_LONGLONG: { - int64_t v = f->val_int(); - if (m_attrs[col]->GetIfAutoInc() && v == 0) + int64_t value = f->val_int(); + common::PushWarningIfOutOfRange(m_tx->Thd(), std::string(f->field_name), value, f->type(), + f->is_flag_set(UNSIGNED_FLAG)); + if (m_attrs[col]->GetIfAutoInc() && value == 0) // Value of auto inc column was not assigned by user *reinterpret_cast(vc.Prepare(sizeof(int64_t))) = m_attrs[col]->AutoIncNext(); else - *reinterpret_cast(vc.Prepare(sizeof(int64_t))) = v; + *reinterpret_cast(vc.Prepare(sizeof(int64_t))) = value; vc.ExpectedSize(sizeof(int64_t)); if (m_attrs[col]->GetIfAutoInc()) { // inc counter should be set to value of user assigned - if (static_cast(v) > m_attrs[col]->GetAutoInc()) { - m_attrs[col]->SetAutoInc(v); + if (static_cast(value) > m_attrs[col]->GetAutoInc()) { + m_attrs[col]->SetAutoInc(value); } } } break; + case MYSQL_TYPE_BIT: { + int64_t value = f->val_int(); + *reinterpret_cast(vc.Prepare(sizeof(int64_t))) = value; + vc.ExpectedSize(sizeof(int64_t)); + } break; case MYSQL_TYPE_DECIMAL: case MYSQL_TYPE_FLOAT: case MYSQL_TYPE_DOUBLE: { @@ -699,7 +706,6 @@ void RCTable::Field2VC(Field *f, loader::ValueCache &vc, size_t col) { 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;