diff --git a/mysql-test/suite/tianmu/r/bit_type.result b/mysql-test/suite/tianmu/r/bit_type.result index db7df46b94..f2c1eaef53 100644 --- a/mysql-test/suite/tianmu/r/bit_type.result +++ b/mysql-test/suite/tianmu/r/bit_type.result @@ -124,4 +124,25 @@ ERROR 22003: BIGINT UNSIGNED value is out of range in '(`test`.`bit2`.`a` * 1234 select a * 12345678910111213123456 from bit2; ERROR HY000: Numeric result of an expression is too large and cannot be handled by tianmu. Please use an explicit cast to a data type handled by tianmu, e.g. CAST( AS DECIMAL(18,6)). drop table bit2; +CREATE TABLE `bit_test` ( +`bit1` bit(1) DEFAULT NULL, +`bit2` bit(2) DEFAULT NULL, +`bit8` bit(8) DEFAULT NULL, +`bit16` bit(16) DEFAULT NULL, +`bit32` bit(32) DEFAULT NULL, +`bit63` bit(63) DEFAULT NULL +) ENGINE=TIANMU DEFAULT CHARSET=utf8mb4; +LOAD DATA local INFILE 'MYSQL_TEST_DIR/suite/tianmu/std_data/bit_test.txt' INTO TABLE bit_test fields TERMINATED BY ',' (@var1, @var2, @var3, @var4, @var5, @var6) +SET bit1 = CAST(CONV(MID(@var1, 3, LENGTH(@var1)-3), 2, 10) AS UNSIGNED), +bit2 = CAST(CONV(MID(@var2, 3, LENGTH(@var2)-3), 2, 10) AS UNSIGNED), +bit8 = CAST(CONV(MID(@var3, 3, LENGTH(@var3)-3), 2, 10) AS UNSIGNED), +bit16 = CAST(CONV(MID(@var4, 3, LENGTH(@var4)-3), 2, 10) AS UNSIGNED), +bit32 = CAST(CONV(MID(@var5, 3, LENGTH(@var5)-3), 2, 10) AS UNSIGNED), +bit63 = CAST(CONV(MID(@var6, 3, LENGTH(@var6)-3), 2, 10) AS UNSIGNED); +select bit1+0, bit2+0, bit8+0, bit16+0, bit32+0, bit63+0 from bit_test; +bit1+0 bit2+0 bit8+0 bit16+0 bit32+0 bit63+0 +NULL NULL NULL NULL NULL NULL +0 0 0 0 0 0 +1 2 7 47 3071 268435455 +drop table bit_test; drop database test_bit; diff --git a/mysql-test/suite/tianmu/std_data/bit_test.txt b/mysql-test/suite/tianmu/std_data/bit_test.txt new file mode 100644 index 0000000000..d9fdd6494b --- /dev/null +++ b/mysql-test/suite/tianmu/std_data/bit_test.txt @@ -0,0 +1,3 @@ +,,,,, +NULL,NULL,NULL,NULL,NULL,NULL +b'11111111111',b'101,b'111',b'101111',b'101111111111',b'1111111111111111111111111111' diff --git a/mysql-test/suite/tianmu/t/bit_type.test b/mysql-test/suite/tianmu/t/bit_type.test index 199ae59bb9..9b94a095d1 100644 --- a/mysql-test/suite/tianmu/t/bit_type.test +++ b/mysql-test/suite/tianmu/t/bit_type.test @@ -96,4 +96,28 @@ select a * 12345678910111213123 from bit2; --error 1105 select a * 12345678910111213123456 from bit2; drop table bit2; + +#load bit data +CREATE TABLE `bit_test` ( + `bit1` bit(1) DEFAULT NULL, + `bit2` bit(2) DEFAULT NULL, + `bit8` bit(8) DEFAULT NULL, + `bit16` bit(16) DEFAULT NULL, + `bit32` bit(32) DEFAULT NULL, + `bit63` bit(63) DEFAULT NULL +) ENGINE=TIANMU DEFAULT CHARSET=utf8mb4; + +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +eval LOAD DATA local INFILE '$MYSQL_TEST_DIR/suite/tianmu/std_data/bit_test.txt' INTO TABLE bit_test fields TERMINATED BY ',' (@var1, @var2, @var3, @var4, @var5, @var6) +SET bit1 = CAST(CONV(MID(@var1, 3, LENGTH(@var1)-3), 2, 10) AS UNSIGNED), +bit2 = CAST(CONV(MID(@var2, 3, LENGTH(@var2)-3), 2, 10) AS UNSIGNED), +bit8 = CAST(CONV(MID(@var3, 3, LENGTH(@var3)-3), 2, 10) AS UNSIGNED), +bit16 = CAST(CONV(MID(@var4, 3, LENGTH(@var4)-3), 2, 10) AS UNSIGNED), +bit32 = CAST(CONV(MID(@var5, 3, LENGTH(@var5)-3), 2, 10) AS UNSIGNED), +bit63 = CAST(CONV(MID(@var6, 3, LENGTH(@var6)-3), 2, 10) AS UNSIGNED); + +select bit1+0, bit2+0, bit8+0, bit16+0, bit32+0, bit63+0 from bit_test; + +drop table bit_test; + drop database test_bit; diff --git a/storage/tianmu/loader/parsing_strategy.cpp b/storage/tianmu/loader/parsing_strategy.cpp index f04b289b9d..e40cf10b13 100644 --- a/storage/tianmu/loader/parsing_strategy.cpp +++ b/storage/tianmu/loader/parsing_strategy.cpp @@ -486,7 +486,7 @@ ParsingStrategy::ParseResult ParsingStrategy::GetOneRow(const char *const buf, s str = vec_field_Str_list_[index_of_field]; } String *res = field->str_result(str); - DEBUG_ASSERT(res); + // DEBUG_ASSERT(res); if (res && res != str) { str->copy(*res); } diff --git a/storage/tianmu/types/value_parser4txt.cpp b/storage/tianmu/types/value_parser4txt.cpp index 51d28053cc..54ac3626d7 100644 --- a/storage/tianmu/types/value_parser4txt.cpp +++ b/storage/tianmu/types/value_parser4txt.cpp @@ -597,6 +597,51 @@ common::ErrorCode ValueParserForText::ParseBigIntAdapter(const BString &tianmu_s return return_code; } +// Unlike the other numeric values, the exactly bit value has already stored int Field_bit in GetOneRow() function, +// and make the string buffer to arg tianmu_s, so this function just convert the string value to int64 back. +common::ErrorCode ValueParserForText::ParseBitAdapter(const BString &tianmu_s, int64_t &out) { + char *val_ptr = tianmu_s.val_; + int len = tianmu_s.len_; + // No matter null value or not, the value stored in char buffer at least one byte and up to 8 bytes. + // calculated by len = (prec+7)/8 + DEBUG_ASSERT(len >=1 && len <=8); + + // The parse code may never go here, but we still check null value for integrity. + if (tianmu_s.Equals("nullptr", 4)) { + out = common::NULL_VALUE_64; + return common::ErrorCode::SUCCESS; + } + + switch (len) { + case 1: { + out = mi_uint1korr(val_ptr);break; + } + case 2: { + out = mi_uint2korr(val_ptr);break; + } + case 3: { + out = mi_uint3korr(val_ptr);break; + } + case 4: { + out = mi_uint4korr(val_ptr);break; + } + case 5: { + out = mi_uint5korr(val_ptr);break; + } + case 6: { + out = mi_uint6korr(val_ptr);break; + } + case 7: { + out = mi_uint7korr(val_ptr);break; + } + default: { + out = mi_uint8korr(val_ptr);break; + } + } + + return common::ErrorCode::SUCCESS; +} + common::ErrorCode ValueParserForText::ParseDecimal(BString const &tianmu_s, int64_t &out, short precision, short scale) { TianmuNum number; diff --git a/storage/tianmu/types/value_parser4txt.h b/storage/tianmu/types/value_parser4txt.h index 8705f3a9c2..aa105ee13b 100644 --- a/storage/tianmu/types/value_parser4txt.h +++ b/storage/tianmu/types/value_parser4txt.h @@ -44,8 +44,9 @@ class ValueParserForText { case common::ColumnType::INT: return std::bind(&ParseNumeric, std::placeholders::_1, std::placeholders::_2, at.Type()); case common::ColumnType::BIGINT: - case common::ColumnType::BIT: return &ParseBigIntAdapter; + case common::ColumnType::BIT: + return &ParseBitAdapter; case common::ColumnType::DATE: case common::ColumnType::TIME: case common::ColumnType::YEAR: @@ -62,6 +63,7 @@ class ValueParserForText { static common::ErrorCode ParseNumeric(BString const &tianmu_s, int64_t &out, common::ColumnType at); static common::ErrorCode ParseBigIntAdapter(const BString &tianmu_s, int64_t &out); + static common::ErrorCode ParseBitAdapter(const BString &tianmu_s, int64_t &out); static common::ErrorCode ParseDecimal(BString const &tianmu_s, int64_t &out, short precision, short scale); static common::ErrorCode ParseDateTimeAdapter(BString const &tianmu_s, int64_t &out, common::ColumnType at);