/** * Copyright (c) 2021 OceanBase * OceanBase CE is licensed under Mulan PubL v2. * You can use this software according to the terms and conditions of the Mulan PubL v2. * You may obtain a copy of Mulan PubL v2 at: * http://license.coscl.org.cn/MulanPubL-2.0 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PubL v2 for more details. */ #define USING_LOG_PREFIX SQL #include "lib/rowid/ob_urowid.h" #include "lib/container/ob_array.h" #include "lib/number/ob_number_v2.h" #include "lib/timezone/ob_timezone_info.h" #include "lib/timezone/ob_time_convert.h" #include "lib/encode/ob_base64_encode.h" #include "common/object/ob_object.h" #include "share/ob_errno.h" #include #include #include #include #include using std::cout; using std::endl; namespace oceanbase { namespace common { class TestAllocator: public ObIAllocator { public: virtual void *alloc(const int64_t size) override { return std::malloc(size); } virtual void free(void *ptr) override { return std::free(ptr); } virtual void *alloc(const int64_t size, const ObMemAttr &/* not used */) { return std::malloc(size); } }; class TestURowID { public: // void SetUp() override {} // void TearDown() override {} void multi_set_and_get() { ObObj pk_val; ObArray pk_vals; TestAllocator allocator; pk_val.set_null(); ASSERT_EQ(OB_SUCCESS, pk_vals.push_back(pk_val)); pk_val.set_tinyint(1); ASSERT_EQ(OB_SUCCESS, pk_vals.push_back(pk_val)); pk_val.set_smallint(2); ASSERT_EQ(OB_SUCCESS, pk_vals.push_back(pk_val)); pk_val.set_mediumint(322); ASSERT_EQ(OB_SUCCESS, pk_vals.push_back(pk_val)); pk_val.set_int32(4333); ASSERT_EQ(OB_SUCCESS, pk_vals.push_back(pk_val)); pk_val.set_int(512345678); ASSERT_EQ(OB_SUCCESS, pk_vals.push_back(pk_val)); pk_val.set_float(1.2345678); ASSERT_EQ(OB_SUCCESS, pk_vals.push_back(pk_val)); pk_val.set_double(2345.231312411); ASSERT_EQ(OB_SUCCESS, pk_vals.push_back(pk_val)); number::ObNumber test_number; test_number.from("123456789987654321.12345678987654321", allocator); pk_val.set_number(test_number); ASSERT_EQ(OB_SUCCESS, pk_vals.push_back(pk_val)); const char *test_str = "hello, this is a test"; pk_val.set_char(ObString(strlen(test_str), test_str)); ASSERT_EQ(OB_SUCCESS, pk_vals.push_back(pk_val)); pk_val.set_varchar(ObString(strlen(test_str), test_str)); ASSERT_EQ(OB_SUCCESS, pk_vals.push_back(pk_val)); pk_val.set_nchar(ObString(strlen(test_str), test_str)); ASSERT_EQ(OB_SUCCESS, pk_vals.push_back(pk_val)); pk_val.set_nvarchar2(ObString(strlen(test_str), test_str)); ASSERT_EQ(OB_SUCCESS, pk_vals.push_back(pk_val)); ObTimeZoneInfo time_zone_info; time_zone_info.set_timezone("+8:00"); ObTimeConvertCtx time_convert_ctx(&time_zone_info, ObTimeConverter::COMPAT_OLD_NLS_DATE_FORMAT, true); ObOTimestampData otime_data; ObScale scale; ASSERT_EQ(OB_SUCCESS, ObTimeConverter::str_to_otimestamp("2020-02-24 21:37:25", time_convert_ctx, ObTimestampTZType, otime_data, scale)); pk_val.set_timestamp_tz(otime_data); ASSERT_EQ(OB_SUCCESS, pk_vals.push_back(pk_val)); ASSERT_EQ(OB_SUCCESS, ObTimeConverter::str_to_otimestamp("2020-02-24 21:37:25", time_convert_ctx, ObTimestampNanoType, otime_data, scale)); pk_val.set_timestamp_nano(otime_data); ASSERT_EQ(OB_SUCCESS, pk_vals.push_back(pk_val)); ASSERT_EQ(OB_SUCCESS, ObTimeConverter::str_to_otimestamp("2020-02-24 21:37:25", time_convert_ctx, ObTimestampNanoType, otime_data, scale)); pk_val.set_timestamp_nano(otime_data); ASSERT_EQ(OB_SUCCESS, pk_vals.push_back(pk_val)); scale = 9; ObIntervalYMValue ym_value; ASSERT_EQ(OB_SUCCESS, ObTimeConverter::str_to_interval_ym("000000019-11", ym_value, scale)); pk_val.set_interval_ym(ym_value); ASSERT_EQ(OB_SUCCESS, pk_vals.push_back(pk_val)); scale = 99; ObIntervalDSValue ds_value; ASSERT_EQ(OB_SUCCESS, ObTimeConverter::str_to_interval_ds("000000012 11:11:11", ds_value, scale)); ASSERT_EQ(OB_SUCCESS, pk_vals.push_back(pk_val)); ObURowIDData urowid_data; ASSERT_EQ(OB_SUCCESS, urowid_data.set_rowid_content(pk_vals, ObURowIDData::PK_ROWID_VERSION, allocator)); int64_t pos = urowid_data.get_pk_content_offset(); int i = 0; ObObj tmp_obj; for(; pos < urowid_data.rowid_len_;) { ASSERT_EQ(urowid_data.get_pk_type(pos), pk_vals.at(i).get_type()); ASSERT_EQ(OB_SUCCESS, urowid_data.get_pk_value(pk_vals.at(i).get_type(), pos, tmp_obj)); ASSERT_EQ(tmp_obj, pk_vals.at(i)); i++; } test_encode_decode(pk_vals, urowid_data); } void set_and_get_pk() { #define TEST_SET_AND_GET_VAL(val, val_len) \ do { \ pk_vals.reset(); \ urowid_data.reset(); \ ObObj tmp_obj; \ int64_t urowid_version = ObURowIDData::PK_ROWID_VERSION; \ ASSERT_EQ(OB_SUCCESS, pk_vals.push_back(pk_val)); \ ASSERT_EQ(OB_SUCCESS, urowid_data.set_rowid_content(pk_vals, ObURowIDData::PK_ROWID_VERSION, allocator)); \ int64_t tmp_pos = urowid_data.get_pk_content_offset(); \ ASSERT_EQ(urowid_version, urowid_data.get_version()); \ ASSERT_TRUE(urowid_data.is_valid_urowid()); \ ASSERT_EQ(val_len + 1, urowid_data.get_obj_size(val)); \ ASSERT_EQ(tmp_pos + val_len + 1, urowid_data.get_buf_len()); \ ASSERT_EQ(urowid_data.get_pk_type(tmp_pos), val.get_type()); \ ASSERT_EQ(tmp_pos, urowid_data.get_pk_content_offset() + 1); \ ASSERT_EQ(OB_SUCCESS, \ urowid_data.get_pk_value(val.get_type(), tmp_pos, tmp_obj)); \ ASSERT_EQ(tmp_obj, val); \ test_encode_decode(pk_vals, urowid_data); \ \ ObObj urowid_obj; \ ObURowIDData urowid2; \ urowid_obj.set_urowid(urowid_data); \ pk_vals.reset(); \ tmp_obj.reset(); \ ASSERT_EQ(OB_SUCCESS, pk_vals.push_back(urowid_obj)); \ ASSERT_EQ(OB_SUCCESS, urowid2.set_rowid_content(pk_vals, ObURowIDData::PK_ROWID_VERSION, allocator)); \ ASSERT_TRUE(urowid2.is_valid_urowid()); \ tmp_pos = urowid2.get_pk_content_offset(); \ ASSERT_EQ(ObURowIDType, urowid2.get_pk_type(tmp_pos)); \ ASSERT_EQ(OB_SUCCESS, \ urowid2.get_pk_value(urowid_obj.get_type(), tmp_pos, tmp_obj)); \ ASSERT_TRUE(urowid_data == tmp_obj.get_urowid()); \ } while (0); ObURowIDData urowid_data; ObArray pk_vals; TestAllocator allocator; ObObj pk_val; pk_val.set_null(); ObObj val; val.set_null(); // int64_t val_len = 0; TEST_SET_AND_GET_VAL(pk_val, 0); pk_val.set_tinyint(1); TEST_SET_AND_GET_VAL(pk_val, 1); pk_val.set_smallint(2); TEST_SET_AND_GET_VAL(pk_val, 2); pk_val.set_mediumint(3); TEST_SET_AND_GET_VAL(pk_val, 4); pk_val.set_int32(4); TEST_SET_AND_GET_VAL(pk_val, 4); pk_val.set_int(5); TEST_SET_AND_GET_VAL(pk_val, 8); pk_val.set_float(1.2345678); TEST_SET_AND_GET_VAL(pk_val, sizeof(float)); pk_val.set_double(2345.231312411); TEST_SET_AND_GET_VAL(pk_val, sizeof(double)); pk_val.set_datetime(1582569960); TEST_SET_AND_GET_VAL(pk_val, 8); number::ObNumber test_number; test_number.from("123456789987654321.12345678987654321", allocator); pk_val.set_number(test_number); TEST_SET_AND_GET_VAL(pk_val, 4 + sizeof(uint32_t) * test_number.get_desc().len_); pk_val.set_number_float(test_number); TEST_SET_AND_GET_VAL(pk_val, 4 + sizeof(uint32_t) * test_number.get_desc().len_); const char *test_str = "hello, this is a test"; pk_val.set_char(ObString(strlen(test_str), test_str)); TEST_SET_AND_GET_VAL(pk_val, 5 + strlen(test_str)); pk_val.set_varchar(ObString(strlen(test_str), test_str)); TEST_SET_AND_GET_VAL(pk_val, 5 + strlen(test_str)); pk_val.set_nchar(ObString(strlen(test_str), test_str)); TEST_SET_AND_GET_VAL(pk_val, 5 + strlen(test_str)); pk_val.set_nvarchar2(ObString(strlen(test_str), test_str)); TEST_SET_AND_GET_VAL(pk_val, 5 + strlen(test_str)); ObTimeZoneInfo time_zone_info; time_zone_info.set_timezone("+8:00"); ObTimeConvertCtx time_convert_ctx(&time_zone_info, ObTimeConverter::COMPAT_OLD_NLS_DATE_FORMAT, true); ObOTimestampData otime_data; ObScale scale; ASSERT_EQ(OB_SUCCESS, ObTimeConverter::str_to_otimestamp("2020-02-24 21:37:25", time_convert_ctx, ObTimestampTZType, otime_data, scale)); pk_val.set_timestamp_tz(otime_data); TEST_SET_AND_GET_VAL(pk_val, 12); ASSERT_EQ(OB_SUCCESS, ObTimeConverter::str_to_otimestamp("2020-02-24 21:37:25", time_convert_ctx, ObTimestampLTZType, otime_data, scale)); pk_val.set_timestamp_ltz(otime_data); TEST_SET_AND_GET_VAL(pk_val, 10); ASSERT_EQ(OB_SUCCESS, ObTimeConverter::str_to_otimestamp("2020-02-24 21:37:25", time_convert_ctx, ObTimestampNanoType, otime_data, scale)); pk_val.set_timestamp_nano(otime_data); TEST_SET_AND_GET_VAL(pk_val, 10); scale = 9; ObIntervalYMValue ym_value; ASSERT_EQ(OB_SUCCESS, ObTimeConverter::str_to_interval_ym("000000019-11", ym_value, scale)); pk_val.set_interval_ym(ym_value); TEST_SET_AND_GET_VAL(pk_val, 8); scale = 99; ObIntervalDSValue ds_value; ASSERT_EQ(OB_SUCCESS, ObTimeConverter::str_to_interval_ds("000000012 11:11:11", ds_value, scale)); pk_val.set_interval_ds(ds_value); TEST_SET_AND_GET_VAL(pk_val, 12); } void test_encode_decode(ObIArray &pk_vals, ObURowIDData &urowid_data) { TestAllocator allocator; const int64_t encode_buf_len = urowid_data.needed_base64_buffer_size(); char *encode_buf = (char *)allocator.alloc(encode_buf_len); int64_t encoded_len = 0; ASSERT_EQ(OB_SUCCESS, urowid_data.get_base64_str(encode_buf, encode_buf_len, encoded_len)); ASSERT_EQ(encoded_len, encode_buf_len); std::cout << std::string(encode_buf, encoded_len) << '\n'; // const int64_t decode_buf_len = ObURowIDData::needed_urowid_buf_size(encoded_len); // char *decode_buf = (char *)allocator.alloc(decode_buf_len); ObURowIDData decode_data; ASSERT_EQ(OB_SUCCESS, ObURowIDData::decode2urowid(encode_buf, encoded_len, allocator, decode_data)); ASSERT_EQ(decode_data, urowid_data); int64_t decode_pos = decode_data.get_pk_content_offset(); int64_t i = 0; for(; decode_pos < decode_data.rowid_len_; ) { ObObjType obj_type = decode_data.get_pk_type(decode_pos); ASSERT_EQ(obj_type, pk_vals.at(i).get_type()); ObObj tmp_obj; ASSERT_EQ(OB_SUCCESS, decode_data.get_pk_value(obj_type, decode_pos, tmp_obj)); ASSERT_EQ(tmp_obj, pk_vals.at(i)); i += 1; } } void test_urowid_cmp() { TestAllocator allocator; ObURowIDData urowid1, urowid2; ObObj obj; number::ObNumber num; ObArray pk_vals; num.from("123456.123456", allocator); obj.set_int(123456); pk_vals.push_back(obj); obj.set_number(num); pk_vals.push_back(obj); obj.set_varchar("hello"); pk_vals.push_back(obj); ASSERT_EQ(OB_SUCCESS, urowid1.set_rowid_content(pk_vals, ObURowIDData::PK_ROWID_VERSION, allocator)); pk_vals.reset(); num.from("123456.124356", allocator); obj.set_int(123456); pk_vals.push_back(obj); obj.set_number(num); pk_vals.push_back(obj); ASSERT_EQ(OB_SUCCESS, urowid2.set_rowid_content(pk_vals, ObURowIDData::PK_ROWID_VERSION, allocator)); ASSERT_TRUE(-1 == urowid1.compare(urowid2)); ASSERT_TRUE(1 == urowid2.compare(urowid1)); pk_vals.reset(); num.from("123456.123456", allocator); obj.set_int(123456); pk_vals.push_back(obj); obj.set_number(num); pk_vals.push_back(obj); obj.set_varchar("hella"); pk_vals.push_back(obj); ASSERT_EQ(OB_SUCCESS, urowid2.set_rowid_content(pk_vals, ObURowIDData::PK_ROWID_VERSION, allocator)); ASSERT_TRUE(1 == urowid1.compare(urowid2)); ASSERT_TRUE(-1 == urowid2.compare(urowid1)); } }; TEST(TestURowID, single_urowid_test) { TestAllocator alloc; // bug: const char *str = "*AAEWLlcAAABnYXJuaXNoIG51bWJlciB0ZWFyaW5nIG1hbnRsaW5nIGFjY3VzdG9tcyBleHRyZW1lcyBiYXNlbHkgY3JhemlseSBlbGRlciB0YXJkaWVzIHByZW1pc2UtCwAAAAACCkcywAAAAAAA"; ObURowIDData dec_data; ASSERT_EQ(OB_SUCCESS, ObURowIDData::decode2urowid(str, strlen(str), alloc, dec_data)); } TEST(TestURowID, set_and_get_pk) { TestURowID urowid_test; urowid_test.set_and_get_pk(); } void decode_output() { TestAllocator alloc; // const char *str = "*AAIPAQEAwHsAAAAACgEAAAAAAAAA"; const char *str = "*AAEWLlcAAABnYXJuaXNoIG51bWJlciB0ZWFyaW5nIG1hbnRsaW5nIGFjY3VzdG9tcyBleHRyZW1lcyBiYXNlbHkgY3JhemlseSBlbGRlciB0YXJkaWVzIHByZW1pc2UtCwAAAAACCkcywAAAAAAA"; ObURowIDData dec_data; ASSERT_EQ(OB_SUCCESS, ObURowIDData::decode2urowid(str, strlen(str), alloc, dec_data)); ObArray pk_vals; LOG_INFO("dba len: ", K(dec_data.get_guess_dba_len())); LOG_INFO("ver: ", K(dec_data.get_version())); ASSERT_EQ(OB_SUCCESS, dec_data.get_pk_vals(pk_vals)); LOG_INFO("cnt: ", K(pk_vals.count())); for (int i = 0; i < pk_vals.count(); ++i) { LOG_INFO("pk", K(pk_vals.at(i))); } } TEST(TestURowID, multi_set_and_get) { TestURowID urowid_test; urowid_test.multi_set_and_get(); } TEST(TestURowID, cmp) { TestURowID urowid_test; urowid_test.test_urowid_cmp(); } } // end namesapce common } // end namespace oceanbase int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); system("rm -rf test_urowid.log"); OB_LOGGER.set_log_level("INFO"); OB_LOGGER.set_file_name("test_urowid.log", true); oceanbase::common::decode_output(); return RUN_ALL_TESTS(); }