Merge "CQL 3.3.1 support" from Pekka
"This patch series adds support for CQL 3.3.1. The changes to CQL are listed here: https://github.com/apache/cassandra/blob/cassandra-2.2/doc/cql3/CQL.textile#changes The following CQL features are already supported by Scylla: - TRUNCATE TABLE alias - Double-dollar string literals - Aggregate functions: MIN, MAX, SUM, and AVG This series adds the following CQL features: - New data types: tinyint, smallint, date, and time - CQL binary protocol v4 (required by the new data types) - Advertise Cassandra 2.2.8 version from Scylla so that drivers correctly detect the presence of CQL 3.3.1 The following CQL features are not supported by Scylla: - Role-based access control (issue #1941) - JSON data type - User-defined functions (UDFs) - User-defined aggregates (UDAs) The following CQL binary protocol v4 changes are not implemented by this series: - Read_failure and Write_failure error codes are not implemented. They error codes not used by the smart drivers but as they are propagated to application code, we eventually need to wire them up to our storage proxy implementation. - Function_failure error code is only used by user-defined functions and the fromJson function, which are not implemented by Scylla. Fixes #1284." * 'penberg/cql-3.3.1/v5' of github.com:cloudius-systems/seastar-dev: version: Bump Cassandra version to 2.2.8 db/schema_tables: Add schema_functions and schema_aggregates tables tests/type_tests: TIME type test cases tests/cql_query_test: TIME type test cases cql3: TIME data type support tests/type_tests: DATE type test cases tests/cql_query_test: DATE type test cases cql3: DATE type support date.h: 64-bit year and days representation licenses: Add utils/date.h license utils/date.h: Import date and time library sources tests/type_tests: TINYINT and SMALLINT type test cases tests/cql_query_test: TINYINT and SMALLINT type test cases cql3: TINYINT and SMALLINT data type support types: Fix integer_type_impl::parse_int() for bytes
This commit is contained in:
@@ -1465,12 +1465,16 @@ native_type returns [shared_ptr<cql3_type> t]
|
||||
| K_FLOAT { $t = cql3_type::float_; }
|
||||
| K_INET { $t = cql3_type::inet; }
|
||||
| K_INT { $t = cql3_type::int_; }
|
||||
| K_SMALLINT { $t = cql3_type::smallint; }
|
||||
| K_TEXT { $t = cql3_type::text; }
|
||||
| K_TIMESTAMP { $t = cql3_type::timestamp; }
|
||||
| K_TINYINT { $t = cql3_type::tinyint; }
|
||||
| K_UUID { $t = cql3_type::uuid; }
|
||||
| K_VARCHAR { $t = cql3_type::varchar; }
|
||||
| K_VARINT { $t = cql3_type::varint; }
|
||||
| K_TIMEUUID { $t = cql3_type::timeuuid; }
|
||||
| K_DATE { $t = cql3_type::date; }
|
||||
| K_TIME { $t = cql3_type::time; }
|
||||
;
|
||||
|
||||
collection_type returns [shared_ptr<cql3::cql3_type::raw> pt]
|
||||
@@ -1644,6 +1648,8 @@ K_DOUBLE: D O U B L E;
|
||||
K_FLOAT: F L O A T;
|
||||
K_INET: I N E T;
|
||||
K_INT: I N T;
|
||||
K_SMALLINT: S M A L L I N T;
|
||||
K_TINYINT: T I N Y I N T;
|
||||
K_TEXT: T E X T;
|
||||
K_UUID: U U I D;
|
||||
K_VARCHAR: V A R C H A R;
|
||||
@@ -1651,6 +1657,8 @@ K_VARINT: V A R I N T;
|
||||
K_TIMEUUID: T I M E U U I D;
|
||||
K_TOKEN: T O K E N;
|
||||
K_WRITETIME: W R I T E T I M E;
|
||||
K_DATE: D A T E;
|
||||
K_TIME: T I M E;
|
||||
|
||||
K_NULL: N U L L;
|
||||
K_NOT: N O T;
|
||||
|
||||
@@ -97,7 +97,9 @@ constants::literal::test_assignment(database& db, const sstring& keyspace, ::sha
|
||||
cql3_type::kind::TEXT,
|
||||
cql3_type::kind::INET,
|
||||
cql3_type::kind::VARCHAR,
|
||||
cql3_type::kind::TIMESTAMP>::contains(kind)) {
|
||||
cql3_type::kind::TIMESTAMP,
|
||||
cql3_type::kind::DATE,
|
||||
cql3_type::kind::TIME>::contains(kind)) {
|
||||
return assignment_testable::test_result::WEAKLY_ASSIGNABLE;
|
||||
}
|
||||
break;
|
||||
@@ -109,7 +111,10 @@ constants::literal::test_assignment(database& db, const sstring& keyspace, ::sha
|
||||
cql3_type::kind::DOUBLE,
|
||||
cql3_type::kind::FLOAT,
|
||||
cql3_type::kind::INT,
|
||||
cql3_type::kind::SMALLINT,
|
||||
cql3_type::kind::TIMESTAMP,
|
||||
cql3_type::kind::DATE,
|
||||
cql3_type::kind::TINYINT,
|
||||
cql3_type::kind::VARINT>::contains(kind)) {
|
||||
return assignment_testable::test_result::WEAKLY_ASSIGNABLE;
|
||||
}
|
||||
|
||||
@@ -273,11 +273,15 @@ thread_local shared_ptr<cql3_type> cql3_type::boolean = make("boolean", boolean_
|
||||
thread_local shared_ptr<cql3_type> cql3_type::double_ = make("double", double_type, cql3_type::kind::DOUBLE);
|
||||
thread_local shared_ptr<cql3_type> cql3_type::float_ = make("float", float_type, cql3_type::kind::FLOAT);
|
||||
thread_local shared_ptr<cql3_type> cql3_type::int_ = make("int", int32_type, cql3_type::kind::INT);
|
||||
thread_local shared_ptr<cql3_type> cql3_type::smallint = make("smallint", short_type, cql3_type::kind::SMALLINT);
|
||||
thread_local shared_ptr<cql3_type> cql3_type::text = make("text", utf8_type, cql3_type::kind::TEXT);
|
||||
thread_local shared_ptr<cql3_type> cql3_type::timestamp = make("timestamp", timestamp_type, cql3_type::kind::TIMESTAMP);
|
||||
thread_local shared_ptr<cql3_type> cql3_type::tinyint = make("tinyint", byte_type, cql3_type::kind::TINYINT);
|
||||
thread_local shared_ptr<cql3_type> cql3_type::uuid = make("uuid", uuid_type, cql3_type::kind::UUID);
|
||||
thread_local shared_ptr<cql3_type> cql3_type::varchar = make("varchar", utf8_type, cql3_type::kind::TEXT);
|
||||
thread_local shared_ptr<cql3_type> cql3_type::timeuuid = make("timeuuid", timeuuid_type, cql3_type::kind::TIMEUUID);
|
||||
thread_local shared_ptr<cql3_type> cql3_type::date = make("date", simple_date_type, cql3_type::kind::DATE);
|
||||
thread_local shared_ptr<cql3_type> cql3_type::time = make("time", time_type, cql3_type::kind::TIME);
|
||||
thread_local shared_ptr<cql3_type> cql3_type::inet = make("inet", inet_addr_type, cql3_type::kind::INET);
|
||||
thread_local shared_ptr<cql3_type> cql3_type::varint = make("varint", varint_type, cql3_type::kind::VARINT);
|
||||
thread_local shared_ptr<cql3_type> cql3_type::decimal = make("decimal", decimal_type, cql3_type::kind::DECIMAL);
|
||||
@@ -296,12 +300,16 @@ cql3_type::values() {
|
||||
cql3_type::float_,
|
||||
cql3_type:inet,
|
||||
cql3_type::int_,
|
||||
cql3_type::smallint,
|
||||
cql3_type::text,
|
||||
cql3_type::timestamp,
|
||||
cql3_type::tinyint,
|
||||
cql3_type::uuid,
|
||||
cql3_type::varchar,
|
||||
cql3_type::varint,
|
||||
cql3_type::timeuuid,
|
||||
cql3_type::date,
|
||||
cql3_type::time,
|
||||
};
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ private:
|
||||
|
||||
public:
|
||||
enum class kind : int8_t {
|
||||
ASCII, BIGINT, BLOB, BOOLEAN, COUNTER, DECIMAL, DOUBLE, FLOAT, INT, INET, TEXT, TIMESTAMP, UUID, VARCHAR, VARINT, TIMEUUID
|
||||
ASCII, BIGINT, BLOB, BOOLEAN, COUNTER, DECIMAL, DOUBLE, FLOAT, INT, SMALLINT, TINYINT, INET, TEXT, TIMESTAMP, UUID, VARCHAR, VARINT, TIMEUUID, DATE, TIME
|
||||
};
|
||||
using kind_enum = super_enum<kind,
|
||||
kind::ASCII,
|
||||
@@ -111,12 +111,16 @@ public:
|
||||
kind::FLOAT,
|
||||
kind::INET,
|
||||
kind::INT,
|
||||
kind::SMALLINT,
|
||||
kind::TINYINT,
|
||||
kind::TEXT,
|
||||
kind::TIMESTAMP,
|
||||
kind::UUID,
|
||||
kind::VARCHAR,
|
||||
kind::VARINT,
|
||||
kind::TIMEUUID>;
|
||||
kind::TIMEUUID,
|
||||
kind::DATE,
|
||||
kind::TIME>;
|
||||
using kind_enum_set = enum_set<kind_enum>;
|
||||
private:
|
||||
std::experimental::optional<kind_enum_set::prepared> _kind;
|
||||
@@ -131,11 +135,15 @@ public:
|
||||
static thread_local shared_ptr<cql3_type> double_;
|
||||
static thread_local shared_ptr<cql3_type> float_;
|
||||
static thread_local shared_ptr<cql3_type> int_;
|
||||
static thread_local shared_ptr<cql3_type> smallint;
|
||||
static thread_local shared_ptr<cql3_type> text;
|
||||
static thread_local shared_ptr<cql3_type> timestamp;
|
||||
static thread_local shared_ptr<cql3_type> tinyint;
|
||||
static thread_local shared_ptr<cql3_type> uuid;
|
||||
static thread_local shared_ptr<cql3_type> varchar;
|
||||
static thread_local shared_ptr<cql3_type> timeuuid;
|
||||
static thread_local shared_ptr<cql3_type> date;
|
||||
static thread_local shared_ptr<cql3_type> time;
|
||||
static thread_local shared_ptr<cql3_type> inet;
|
||||
static thread_local shared_ptr<cql3_type> varint;
|
||||
static thread_local shared_ptr<cql3_type> decimal;
|
||||
|
||||
@@ -59,7 +59,7 @@ logging::logger log("query_processor");
|
||||
|
||||
distributed<query_processor> _the_query_processor;
|
||||
|
||||
const sstring query_processor::CQL_VERSION = "3.2.1";
|
||||
const sstring query_processor::CQL_VERSION = "3.3.1";
|
||||
|
||||
class query_processor::internal_state {
|
||||
service::query_state _qs;
|
||||
|
||||
@@ -35,7 +35,7 @@ using cql_protocol_version_type = uint8_t;
|
||||
class cql_serialization_format {
|
||||
cql_protocol_version_type _version;
|
||||
public:
|
||||
static constexpr cql_protocol_version_type latest_version = 3;
|
||||
static constexpr cql_protocol_version_type latest_version = 4;
|
||||
explicit cql_serialization_format(cql_protocol_version_type version) : _version(version) {}
|
||||
static cql_serialization_format latest() { return cql_serialization_format{latest_version}; }
|
||||
static cql_serialization_format internal() { return latest(); }
|
||||
|
||||
@@ -2175,7 +2175,7 @@ data_type parse_type(sstring str)
|
||||
|
||||
std::vector<schema_ptr> all_tables() {
|
||||
return {
|
||||
keyspaces(), columnfamilies(), columns(), triggers(), usertypes(), /* Not in 2.1.8 functions(), aggregates() */
|
||||
keyspaces(), columnfamilies(), columns(), triggers(), usertypes(), functions(), aggregates(),
|
||||
views(),
|
||||
};
|
||||
}
|
||||
|
||||
32
licenses/date-license.txt
Normal file
32
licenses/date-license.txt
Normal file
@@ -0,0 +1,32 @@
|
||||
The license for utils/date.h is:
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015, 2016 Howard Hinnant
|
||||
Copyright (c) 2016 Adrian Colomitchi
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
Our apologies. When the previous paragraph was written, lowercase had not yet
|
||||
been invented (that woud involve another several millennia of evolution).
|
||||
We did not mean to shout.
|
||||
|
||||
Source code was imported from the following repository:
|
||||
|
||||
https://github.com/HowardHinnant/date
|
||||
@@ -1358,11 +1358,15 @@ SEASTAR_TEST_CASE(test_types) {
|
||||
" m varchar,"
|
||||
" n varint,"
|
||||
" o decimal,"
|
||||
" p tinyint,"
|
||||
" q smallint,"
|
||||
" r date,"
|
||||
" s time,"
|
||||
");").discard_result();
|
||||
}).then([&e] {
|
||||
e.require_table_exists("ks", "all_types");
|
||||
return e.execute_cql(
|
||||
"INSERT INTO all_types (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) VALUES ("
|
||||
"INSERT INTO all_types (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) VALUES ("
|
||||
" 'ascii',"
|
||||
" 123456789,"
|
||||
" 0xdeadbeef,"
|
||||
@@ -1377,7 +1381,11 @@ SEASTAR_TEST_CASE(test_types) {
|
||||
" d2177dd0-eaa2-11de-a572-001b779c76e3,"
|
||||
" 'varchar',"
|
||||
" 123,"
|
||||
" 1.23"
|
||||
" 1.23,"
|
||||
" 3,"
|
||||
" 3,"
|
||||
" '1970-01-02',"
|
||||
" '00:00:00.000000001'"
|
||||
");").discard_result();
|
||||
}).then([&e] {
|
||||
return e.execute_cql("SELECT * FROM all_types WHERE a = 'ascii'");
|
||||
@@ -1401,11 +1409,15 @@ SEASTAR_TEST_CASE(test_types) {
|
||||
timeuuid_type->decompose(utils::UUID(sstring("d2177dd0-eaa2-11de-a572-001b779c76e3"))),
|
||||
uuid_type->decompose(utils::UUID(sstring("d2177dd0-eaa2-11de-a572-001b779c76e3"))),
|
||||
utf8_type->decompose(sstring("varchar")), varint_type->decompose(boost::multiprecision::cpp_int(123)),
|
||||
decimal_type->decompose(big_decimal { 2, boost::multiprecision::cpp_int(123) })
|
||||
decimal_type->decompose(big_decimal { 2, boost::multiprecision::cpp_int(123) }),
|
||||
byte_type->decompose(int8_t(3)),
|
||||
short_type->decompose(int16_t(3)),
|
||||
simple_date_type->decompose(int32_t(0x80000001)),
|
||||
time_type->decompose(int64_t(0x0000000000000001)),
|
||||
}
|
||||
});
|
||||
return e.execute_cql(
|
||||
"INSERT INTO all_types (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) VALUES ("
|
||||
"INSERT INTO all_types (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) VALUES ("
|
||||
" blobAsAscii(asciiAsBlob('ascii2')),"
|
||||
" blobAsBigint(bigintAsBlob(123456789)),"
|
||||
" bigintAsBlob(12),"
|
||||
@@ -1419,7 +1431,11 @@ SEASTAR_TEST_CASE(test_types) {
|
||||
" blobAsTimeuuid(timeuuidAsBlob(d2177dd0-eaa2-11de-a572-001b779c76e3)),"
|
||||
" blobAsUuid(uuidAsBlob(d2177dd0-eaa2-11de-a572-001b779c76e3)),"
|
||||
" blobAsVarchar(varcharAsBlob('varchar')), blobAsVarint(varintAsBlob(123)),"
|
||||
" blobAsDecimal(decimalAsBlob(1.23))"
|
||||
" blobAsDecimal(decimalAsBlob(1.23)),"
|
||||
" blobAsTinyint(tinyintAsBlob(3)),"
|
||||
" blobAsSmallint(smallintAsBlob(3)),"
|
||||
" blobAsDate(dateAsBlob('1970-01-02')),"
|
||||
" blobAsTime(timeAsBlob('00:00:00.000000001'))"
|
||||
");").discard_result();
|
||||
}).then([&e] {
|
||||
return e.execute_cql("SELECT * FROM all_types WHERE a = 'ascii2'");
|
||||
@@ -1443,7 +1459,11 @@ SEASTAR_TEST_CASE(test_types) {
|
||||
timeuuid_type->decompose(utils::UUID(sstring("d2177dd0-eaa2-11de-a572-001b779c76e3"))),
|
||||
uuid_type->decompose(utils::UUID(sstring("d2177dd0-eaa2-11de-a572-001b779c76e3"))),
|
||||
utf8_type->decompose(sstring("varchar")), varint_type->decompose(boost::multiprecision::cpp_int(123)),
|
||||
decimal_type->decompose(big_decimal { 2, boost::multiprecision::cpp_int(123) })
|
||||
decimal_type->decompose(big_decimal { 2, boost::multiprecision::cpp_int(123) }),
|
||||
byte_type->decompose(int8_t(3)),
|
||||
short_type->decompose(int16_t(3)),
|
||||
simple_date_type->decompose(int32_t(0x80000001)),
|
||||
time_type->decompose(int64_t(0x0000000000000001)),
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -51,6 +51,64 @@ BOOST_AUTO_TEST_CASE(test_bytes_type_string_conversions) {
|
||||
BOOST_REQUIRE(bytes_type->equal(bytes_type->from_string("616263646566"), bytes_type->decompose(data_value(bytes{"abcdef"}))));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_byte_type_string_conversions) {
|
||||
BOOST_REQUIRE(byte_type->equal(byte_type->from_string("123"), byte_type->decompose(int8_t(123))));
|
||||
BOOST_REQUIRE_EQUAL(byte_type->to_string(byte_type->decompose(int8_t(123))), "123");
|
||||
|
||||
BOOST_REQUIRE(byte_type->equal(byte_type->from_string("12"), byte_type->decompose(int8_t(12))));
|
||||
BOOST_REQUIRE(byte_type->equal(byte_type->from_string("0012"), byte_type->decompose(int8_t(12))));
|
||||
BOOST_REQUIRE(byte_type->equal(byte_type->from_string("+12"), byte_type->decompose(int8_t(12))));
|
||||
BOOST_REQUIRE_EQUAL(byte_type->to_string(byte_type->decompose(int8_t(12))), "12");
|
||||
BOOST_REQUIRE(byte_type->equal(byte_type->from_string("-12"), byte_type->decompose(int8_t(-12))));
|
||||
BOOST_REQUIRE_EQUAL(byte_type->to_string(byte_type->decompose(int8_t(-12))), "-12");
|
||||
|
||||
BOOST_REQUIRE(byte_type->equal(byte_type->from_string("0"), byte_type->decompose(int8_t(0))));
|
||||
BOOST_REQUIRE(byte_type->equal(byte_type->from_string("-0"), byte_type->decompose(int8_t(0))));
|
||||
BOOST_REQUIRE(byte_type->equal(byte_type->from_string("+0"), byte_type->decompose(int8_t(0))));
|
||||
BOOST_REQUIRE_EQUAL(byte_type->to_string(byte_type->decompose(int8_t(0))), "0");
|
||||
|
||||
BOOST_REQUIRE(byte_type->equal(byte_type->from_string("-128"), byte_type->decompose(int8_t(-128))));
|
||||
BOOST_REQUIRE_EQUAL(byte_type->to_string(byte_type->decompose((int8_t(-128)))), "-128");
|
||||
|
||||
BOOST_REQUIRE(byte_type->equal(byte_type->from_string("127"), byte_type->decompose(int8_t(127))));
|
||||
BOOST_REQUIRE_EQUAL(byte_type->to_string(byte_type->decompose(int8_t(127))), "127");
|
||||
|
||||
test_parsing_fails(byte_type, "asd");
|
||||
test_parsing_fails(byte_type, "-129");
|
||||
test_parsing_fails(byte_type, "128");
|
||||
|
||||
BOOST_REQUIRE_EQUAL(byte_type->to_string(bytes()), "");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_short_type_string_conversions) {
|
||||
BOOST_REQUIRE(short_type->equal(short_type->from_string("12345"), short_type->decompose(int16_t(12345))));
|
||||
BOOST_REQUIRE_EQUAL(short_type->to_string(short_type->decompose(int16_t(12345))), "12345");
|
||||
|
||||
BOOST_REQUIRE(short_type->equal(short_type->from_string("12"), short_type->decompose(int16_t(12))));
|
||||
BOOST_REQUIRE(short_type->equal(short_type->from_string("0012"), short_type->decompose(int16_t(12))));
|
||||
BOOST_REQUIRE(short_type->equal(short_type->from_string("+12"), short_type->decompose(int16_t(12))));
|
||||
BOOST_REQUIRE_EQUAL(short_type->to_string(short_type->decompose(int16_t(12))), "12");
|
||||
BOOST_REQUIRE(short_type->equal(short_type->from_string("-12"), short_type->decompose(int16_t(-12))));
|
||||
BOOST_REQUIRE_EQUAL(short_type->to_string(short_type->decompose(int16_t(-12))), "-12");
|
||||
|
||||
BOOST_REQUIRE(short_type->equal(short_type->from_string("0"), short_type->decompose(int16_t(0))));
|
||||
BOOST_REQUIRE(short_type->equal(short_type->from_string("-0"), short_type->decompose(int16_t(0))));
|
||||
BOOST_REQUIRE(short_type->equal(short_type->from_string("+0"), short_type->decompose(int16_t(0))));
|
||||
BOOST_REQUIRE_EQUAL(short_type->to_string(short_type->decompose(int16_t(0))), "0");
|
||||
|
||||
BOOST_REQUIRE(short_type->equal(short_type->from_string("-32768"), short_type->decompose(int16_t(-32768))));
|
||||
BOOST_REQUIRE_EQUAL(short_type->to_string(short_type->decompose((int16_t(-32768)))), "-32768");
|
||||
|
||||
BOOST_REQUIRE(short_type->equal(short_type->from_string("32677"), short_type->decompose(int16_t(32677))));
|
||||
BOOST_REQUIRE_EQUAL(short_type->to_string(short_type->decompose(int16_t(32677))), "32677");
|
||||
|
||||
test_parsing_fails(short_type, "asd");
|
||||
test_parsing_fails(short_type, "-32769");
|
||||
test_parsing_fails(short_type, "32768");
|
||||
|
||||
BOOST_REQUIRE_EQUAL(short_type->to_string(bytes()), "");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_int32_type_string_conversions) {
|
||||
BOOST_REQUIRE(int32_type->equal(int32_type->from_string("1234567890"), int32_type->decompose(1234567890)));
|
||||
BOOST_REQUIRE_EQUAL(int32_type->to_string(int32_type->decompose(1234567890)), "1234567890");
|
||||
@@ -94,6 +152,49 @@ BOOST_AUTO_TEST_CASE(test_timeuuid_type_string_conversions) {
|
||||
test_parsing_fails(timeuuid_type, utils::make_random_uuid().to_sstring());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_simple_date_type_string_conversions) {
|
||||
BOOST_REQUIRE(simple_date_type->equal(simple_date_type->from_string("1970-01-01"), simple_date_type->decompose(int32_t(0x80000000))));
|
||||
BOOST_REQUIRE_EQUAL(simple_date_type->to_string(simple_date_type->decompose(int32_t(0x80000000))), "1970-01-01");
|
||||
|
||||
BOOST_REQUIRE(simple_date_type->equal(simple_date_type->from_string("-5877641-06-23"), simple_date_type->decompose(int32_t(0x00000000))));
|
||||
BOOST_REQUIRE_EQUAL(simple_date_type->to_string(simple_date_type->decompose(int32_t(0x00000000))), "-5877641-06-23");
|
||||
|
||||
BOOST_REQUIRE(simple_date_type->equal(simple_date_type->from_string("5881580-07-11"), simple_date_type->decompose(int32_t(0xffffffff))));
|
||||
BOOST_REQUIRE_EQUAL(simple_date_type->to_string(simple_date_type->decompose(int32_t(0xffffffff))), "5881580-07-11");
|
||||
|
||||
test_parsing_fails(simple_date_type, "something");
|
||||
test_parsing_fails(simple_date_type, "-5877641-06-22");
|
||||
test_parsing_fails(simple_date_type, "5881580-07-12");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_time_type_string_conversions) {
|
||||
BOOST_REQUIRE(time_type->equal(time_type->from_string("12:34:56"), time_type->decompose(int64_t(45296000000000))));
|
||||
BOOST_REQUIRE_EQUAL(time_type->to_string(time_type->decompose(int64_t(45296000000000))), "12:34:56.000000000");
|
||||
|
||||
BOOST_REQUIRE(time_type->equal(time_type->from_string("12:34:56.000000000"), time_type->decompose(int64_t(45296000000000))));
|
||||
BOOST_REQUIRE_EQUAL(time_type->to_string(time_type->decompose(int64_t(45296000000000))), "12:34:56.000000000");
|
||||
|
||||
BOOST_REQUIRE(time_type->equal(time_type->from_string("12:34:56.123456789"), time_type->decompose(int64_t(45296123456789))));
|
||||
BOOST_REQUIRE_EQUAL(time_type->to_string(time_type->decompose(int64_t(45296123456789))), "12:34:56.123456789");
|
||||
|
||||
BOOST_REQUIRE(time_type->equal(time_type->from_string("00:00:00.000000000"), time_type->decompose(int64_t(0x00000000))));
|
||||
BOOST_REQUIRE_EQUAL(time_type->to_string(time_type->decompose(int64_t(0x00000000))), "00:00:00.000000000");
|
||||
|
||||
BOOST_REQUIRE(time_type->equal(time_type->from_string("23:59:59.999999999"), time_type->decompose(int64_t(86399999999999))));
|
||||
BOOST_REQUIRE_EQUAL(time_type->to_string(time_type->decompose(int64_t(86399999999999))), "23:59:59.999999999");
|
||||
|
||||
BOOST_REQUIRE(time_type->equal(time_type->from_string("-00:00:00.000000000"), time_type->decompose(int64_t(0x00000000))));
|
||||
BOOST_REQUIRE(time_type->equal(time_type->from_string("-00:00:00.000000001"), time_type->decompose(int64_t(0x00000001))));
|
||||
|
||||
test_parsing_fails(time_type, "something");
|
||||
test_parsing_fails(time_type, "00:00");
|
||||
test_parsing_fails(time_type, "24:00:00.000000000");
|
||||
test_parsing_fails(time_type, "-01:00:00.0000000000");
|
||||
test_parsing_fails(time_type, "00:-01:00.0000000000");
|
||||
test_parsing_fails(time_type, "00:00:-10.0000000000");
|
||||
test_parsing_fails(time_type, "00:00:00.-0000000001");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_uuid_type_comparison) {
|
||||
auto uuid1 = uuid_type->decompose(utils::UUID(sstring("ad4d3770-7a50-11e6-ac4d-000000000003")));
|
||||
auto uuid2 = uuid_type->decompose(utils::UUID(sstring("c512ba10-7a50-11e6-ac4d-000000000003")));
|
||||
|
||||
@@ -1724,6 +1724,10 @@ private:
|
||||
VARINT = 0x000E,
|
||||
TIMEUUID = 0x000F,
|
||||
INET = 0x0010,
|
||||
DATE = 0x0011,
|
||||
TIME = 0x0012,
|
||||
SMALLINT = 0x0013,
|
||||
TINYINT = 0x0014,
|
||||
LIST = 0x0020,
|
||||
MAP = 0x0021,
|
||||
SET = 0x0022,
|
||||
@@ -1809,11 +1813,15 @@ thread_local const type_codec::type_id_to_type_type type_codec::type_id_to_type
|
||||
(type_id::DOUBLE , double_type)
|
||||
(type_id::FLOAT , float_type)
|
||||
(type_id::INT , int32_type)
|
||||
(type_id::TINYINT , byte_type)
|
||||
(type_id::SMALLINT , short_type)
|
||||
(type_id::TIMESTAMP , timestamp_type)
|
||||
(type_id::UUID , uuid_type)
|
||||
(type_id::VARCHAR , utf8_type)
|
||||
(type_id::VARINT , varint_type)
|
||||
(type_id::TIMEUUID , timeuuid_type)
|
||||
(type_id::DATE , simple_date_type)
|
||||
(type_id::TIME , time_type)
|
||||
(type_id::INET , inet_addr_type);
|
||||
|
||||
void cql_server::response::write(const cql3::metadata& m) {
|
||||
|
||||
249
types.cc
249
types.cc
@@ -32,7 +32,9 @@
|
||||
#include "utils/serialization.hh"
|
||||
#include "combine.hh"
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <regex>
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
#include <boost/range/adaptor/filtered.hpp>
|
||||
@@ -42,6 +44,7 @@
|
||||
#include <boost/locale/encoding_utf.hpp>
|
||||
#include <boost/multiprecision/cpp_int.hpp>
|
||||
#include "utils/big_decimal.hh"
|
||||
#include "utils/date.h"
|
||||
|
||||
template<typename T>
|
||||
sstring time_point_to_string(const T& tp)
|
||||
@@ -51,6 +54,8 @@ sstring time_point_to_string(const T& tp)
|
||||
return boost::posix_time::to_iso_extended_string(time);
|
||||
}
|
||||
|
||||
static const char* byte_type_name = "org.apache.cassandra.db.marshal.ByteType";
|
||||
static const char* short_type_name = "org.apache.cassandra.db.marshal.ShortType";
|
||||
static const char* int32_type_name = "org.apache.cassandra.db.marshal.Int32Type";
|
||||
static const char* long_type_name = "org.apache.cassandra.db.marshal.LongType";
|
||||
static const char* ascii_type_name = "org.apache.cassandra.db.marshal.AsciiType";
|
||||
@@ -60,6 +65,8 @@ static const char* boolean_type_name = "org.apache.cassandra.db.marshal.Boolea
|
||||
static const char* timeuuid_type_name = "org.apache.cassandra.db.marshal.TimeUUIDType";
|
||||
static const char* timestamp_type_name = "org.apache.cassandra.db.marshal.TimestampType";
|
||||
static const char* date_type_name = "org.apache.cassandra.db.marshal.DateType";
|
||||
static const char* simple_date_type_name = "org.apache.cassandra.db.marshal.SimpleDateType";
|
||||
static const char* time_type_name = "org.apache.cassandra.db.marshal.TimeType";
|
||||
static const char* uuid_type_name = "org.apache.cassandra.db.marshal.UUIDType";
|
||||
static const char* inet_addr_type_name = "org.apache.cassandra.db.marshal.InetAddressType";
|
||||
static const char* double_type_name = "org.apache.cassandra.db.marshal.DoubleType";
|
||||
@@ -172,7 +179,12 @@ struct integer_type_impl : simple_type_impl<T> {
|
||||
}
|
||||
T parse_int(sstring_view s) const {
|
||||
try {
|
||||
return boost::lexical_cast<T>(s.begin(), s.size());
|
||||
auto value64 = boost::lexical_cast<int64_t>(s.begin(), s.size());
|
||||
auto value = static_cast<T>(value64);
|
||||
if (value != value64) {
|
||||
throw marshal_exception(sprint("Value out of range for type %s: '%s'", this->name(), s));
|
||||
}
|
||||
return static_cast<T>(value);
|
||||
} catch (const boost::bad_lexical_cast& e) {
|
||||
throw marshal_exception(sprint("Invalid number format '%s'", s));
|
||||
}
|
||||
@@ -188,6 +200,36 @@ struct integer_type_impl : simple_type_impl<T> {
|
||||
}
|
||||
};
|
||||
|
||||
struct byte_type_impl : integer_type_impl<int8_t> {
|
||||
byte_type_impl() : integer_type_impl{byte_type_name}
|
||||
{ }
|
||||
|
||||
virtual void validate(bytes_view v) const override {
|
||||
if (v.size() != 0 && v.size() != 1) {
|
||||
throw marshal_exception(sprint("Expected 1 byte for a tinyint (%d)", v.size()));
|
||||
}
|
||||
}
|
||||
|
||||
virtual ::shared_ptr<cql3::cql3_type> as_cql3_type() const override {
|
||||
return cql3::cql3_type::tinyint;
|
||||
}
|
||||
};
|
||||
|
||||
struct short_type_impl : integer_type_impl<int16_t> {
|
||||
short_type_impl() : integer_type_impl{short_type_name}
|
||||
{ }
|
||||
|
||||
virtual void validate(bytes_view v) const override {
|
||||
if (v.size() != 0 && v.size() != 2) {
|
||||
throw marshal_exception(sprint("Expected 2 bytes for a smallint (%d)", v.size()));
|
||||
}
|
||||
}
|
||||
|
||||
virtual ::shared_ptr<cql3::cql3_type> as_cql3_type() const override {
|
||||
return cql3::cql3_type::smallint;
|
||||
}
|
||||
};
|
||||
|
||||
struct int32_type_impl : integer_type_impl<int32_t> {
|
||||
int32_type_impl() : integer_type_impl{int32_type_name}
|
||||
{ }
|
||||
@@ -732,6 +774,197 @@ public:
|
||||
};
|
||||
logging::logger timestamp_type_impl::_logger(timestamp_type_name);
|
||||
|
||||
struct simple_date_type_impl : public simple_type_impl<uint32_t> {
|
||||
simple_date_type_impl() : simple_type_impl{simple_date_type_name}
|
||||
{ }
|
||||
virtual void serialize(const void* value, bytes::iterator& out) const override {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
auto&& v1 = from_value(value);
|
||||
if (v1.empty()) {
|
||||
return;
|
||||
}
|
||||
uint32_t v = v1.get();
|
||||
v = net::hton(v);
|
||||
out = std::copy_n(reinterpret_cast<const char*>(&v), sizeof(v), out);
|
||||
|
||||
}
|
||||
virtual size_t serialized_size(const void* value) const override {
|
||||
if (!value || from_value(value).empty()) {
|
||||
return 0;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
virtual data_value deserialize(bytes_view in) const override {
|
||||
if (in.empty()) {
|
||||
return make_empty();
|
||||
}
|
||||
auto v = read_simple_exactly<uint32_t>(in);
|
||||
return make_value(v);
|
||||
}
|
||||
virtual void validate(bytes_view v) const override {
|
||||
if (v.size() != 0 && v.size() != 4) {
|
||||
throw marshal_exception(sprint("Expected 4 byte long for date (%d)", v.size()));
|
||||
}
|
||||
}
|
||||
virtual bytes from_string(sstring_view s) const override {
|
||||
if (s.empty()) {
|
||||
return bytes();
|
||||
}
|
||||
uint32_t ts = net::hton(days_from_string(s));
|
||||
bytes b(bytes::initialized_later(), sizeof(int32_t));
|
||||
std::copy_n(reinterpret_cast<const int8_t*>(&ts), sizeof(ts), b.begin());
|
||||
return b;
|
||||
}
|
||||
static uint32_t days_from_string(sstring_view s) {
|
||||
std::string str;
|
||||
str.resize(s.size());
|
||||
std::transform(s.begin(), s.end(), str.begin(), ::tolower);
|
||||
char* end;
|
||||
auto v = std::strtoll(s.begin(), &end, 10);
|
||||
if (end == s.begin() + s.size()) {
|
||||
return v;
|
||||
}
|
||||
static std::regex date_re("^(-?\\d+)-(\\d+)-(\\d+)");
|
||||
std::smatch dsm;
|
||||
if (!std::regex_match(str, dsm, date_re)) {
|
||||
throw marshal_exception(sprint("Unable to coerce '%s' to a formatted date (long)", str));
|
||||
}
|
||||
auto t = get_time(dsm);
|
||||
return serialize(str, date::local_days(t).time_since_epoch().count());
|
||||
}
|
||||
static date::year_month_day get_time(const std::smatch& sm) {
|
||||
auto year = boost::lexical_cast<long>(sm[1]);
|
||||
auto month = boost::lexical_cast<unsigned>(sm[2]);
|
||||
auto day = boost::lexical_cast<unsigned>(sm[3]);
|
||||
return date::year_month_day{date::year{year}, date::month{month}, date::day{day}};
|
||||
}
|
||||
static uint32_t serialize(const std::string& input, int64_t days) {
|
||||
if (days < std::numeric_limits<int32_t>::min()) {
|
||||
throw marshal_exception(sprint("Input date %s is less than min supported date -5877641-06-23", input));
|
||||
}
|
||||
if (days > std::numeric_limits<int32_t>::max()) {
|
||||
throw marshal_exception(sprint("Input date %s is greater than max supported date 5881580-07-11", input));
|
||||
}
|
||||
days += 1UL << 31;
|
||||
return static_cast<uint32_t>(days);
|
||||
}
|
||||
virtual sstring to_string(const bytes& b) const override {
|
||||
auto v = deserialize(b);
|
||||
if (v.is_null()) {
|
||||
return "";
|
||||
}
|
||||
date::days days{from_value(v).get() - (1UL << 31)};
|
||||
date::year_month_day ymd{date::local_days{days}};
|
||||
std::ostringstream str;
|
||||
str << ymd;
|
||||
return str.str();
|
||||
}
|
||||
virtual ::shared_ptr<cql3::cql3_type> as_cql3_type() const override {
|
||||
return cql3::cql3_type::date;
|
||||
}
|
||||
};
|
||||
|
||||
struct time_type_impl : public simple_type_impl<int64_t> {
|
||||
time_type_impl() : simple_type_impl{time_type_name}
|
||||
{ }
|
||||
virtual void serialize(const void* value, bytes::iterator& out) const override {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
auto&& v1 = from_value(value);
|
||||
if (v1.empty()) {
|
||||
return;
|
||||
}
|
||||
uint64_t v = v1.get();
|
||||
v = net::hton(v);
|
||||
out = std::copy_n(reinterpret_cast<const char*>(&v), sizeof(v), out);
|
||||
}
|
||||
virtual size_t serialized_size(const void* value) const override {
|
||||
if (!value || from_value(value).empty()) {
|
||||
return 0;
|
||||
}
|
||||
return 8;
|
||||
}
|
||||
virtual data_value deserialize(bytes_view in) const override {
|
||||
if (in.empty()) {
|
||||
return make_empty();
|
||||
}
|
||||
auto v = read_simple_exactly<int64_t>(in);
|
||||
return make_value(v);
|
||||
}
|
||||
virtual void validate(bytes_view v) const override {
|
||||
if (v.size() != 0 && v.size() != 8) {
|
||||
throw marshal_exception(sprint("Expected 8 byte long for time (%d)", v.size()));
|
||||
}
|
||||
}
|
||||
virtual bytes from_string(sstring_view s) const override {
|
||||
if (s.empty()) {
|
||||
return bytes();
|
||||
}
|
||||
int64_t ts = net::hton(parse_time(s));
|
||||
bytes b(bytes::initialized_later(), sizeof(int64_t));
|
||||
std::copy_n(reinterpret_cast<const int8_t*>(&ts), sizeof(ts), b.begin());
|
||||
return b;
|
||||
}
|
||||
static int64_t parse_time(sstring_view s) {
|
||||
static auto format_error = "Timestamp format must be hh:mm:ss[.fffffffff]";
|
||||
auto hours_end = s.find(':');
|
||||
if (hours_end == std::string::npos) {
|
||||
throw marshal_exception(format_error);
|
||||
}
|
||||
int64_t hours = std::stol(s.substr(0, hours_end).to_string());
|
||||
if (hours < 0 || hours >= 24) {
|
||||
throw marshal_exception("Hour out of bounds.");
|
||||
}
|
||||
auto minutes_end = s.find(':', hours_end+1);
|
||||
if (minutes_end == std::string::npos) {
|
||||
throw marshal_exception(format_error);
|
||||
}
|
||||
int64_t minutes = std::stol(s.substr(hours_end + 1, hours_end-minutes_end).to_string());
|
||||
if (minutes < 0 || minutes >= 60) {
|
||||
throw marshal_exception("Minute out of bounds.");
|
||||
}
|
||||
auto seconds_end = s.find('.', minutes_end+1);
|
||||
if (seconds_end == std::string::npos) {
|
||||
seconds_end = s.length();
|
||||
}
|
||||
int64_t seconds = std::stol(s.substr(minutes_end + 1, minutes_end-seconds_end).to_string());
|
||||
if (seconds < 0 || seconds >= 60) {
|
||||
throw marshal_exception("Second out of bounds.");
|
||||
}
|
||||
int64_t nanoseconds = 0;
|
||||
if (seconds_end < s.length()) {
|
||||
nanoseconds = std::stol(s.substr(seconds_end + 1).to_string());
|
||||
nanoseconds *= std::pow(10, 9-(s.length() - (seconds_end + 1)));
|
||||
if (nanoseconds < 0 || nanoseconds >= 1000 * 1000 * 1000) {
|
||||
throw marshal_exception("Nanosecond out of bounds.");
|
||||
}
|
||||
}
|
||||
std::chrono::nanoseconds result;
|
||||
result += std::chrono::hours(hours);
|
||||
result += std::chrono::minutes(minutes);
|
||||
result += std::chrono::seconds(seconds);
|
||||
result += std::chrono::nanoseconds(nanoseconds);
|
||||
return result.count();
|
||||
}
|
||||
virtual sstring to_string(const bytes& b) const override {
|
||||
auto v = deserialize(b);
|
||||
if (v.is_null()) {
|
||||
return "";
|
||||
}
|
||||
std::chrono::nanoseconds nanoseconds{from_value(v).get()};
|
||||
auto time = date::make_time(nanoseconds);
|
||||
std::ostringstream str;
|
||||
str << time;
|
||||
return str.str();
|
||||
}
|
||||
virtual ::shared_ptr<cql3::cql3_type> as_cql3_type() const override {
|
||||
return cql3::cql3_type::time;
|
||||
}
|
||||
};
|
||||
|
||||
struct uuid_type_impl : concrete_type<utils::UUID> {
|
||||
uuid_type_impl() : concrete_type(uuid_type_name) {}
|
||||
virtual void serialize(const void* value, bytes::iterator& out) const override {
|
||||
@@ -2811,6 +3044,8 @@ reversed_type_impl::native_typeid() const {
|
||||
return _underlying_type->native_typeid();
|
||||
}
|
||||
|
||||
thread_local const shared_ptr<const abstract_type> byte_type(make_shared<byte_type_impl>());
|
||||
thread_local const shared_ptr<const abstract_type> short_type(make_shared<short_type_impl>());
|
||||
thread_local const shared_ptr<const abstract_type> int32_type(make_shared<int32_type_impl>());
|
||||
thread_local const shared_ptr<const abstract_type> long_type(make_shared<long_type_impl>());
|
||||
thread_local const shared_ptr<const abstract_type> ascii_type(make_shared<ascii_type_impl>());
|
||||
@@ -2820,6 +3055,8 @@ thread_local const shared_ptr<const abstract_type> boolean_type(make_shared<bool
|
||||
thread_local const shared_ptr<const abstract_type> date_type(make_shared<date_type_impl>());
|
||||
thread_local const shared_ptr<const abstract_type> timeuuid_type(make_shared<timeuuid_type_impl>());
|
||||
thread_local const shared_ptr<const abstract_type> timestamp_type(make_shared<timestamp_type_impl>());
|
||||
thread_local const shared_ptr<const abstract_type> simple_date_type(make_shared<simple_date_type_impl>());
|
||||
thread_local const shared_ptr<const abstract_type> time_type(make_shared<time_type_impl>());
|
||||
thread_local const shared_ptr<const abstract_type> uuid_type(make_shared<uuid_type_impl>());
|
||||
thread_local const shared_ptr<const abstract_type> inet_addr_type(make_shared<inet_addr_type_impl>());
|
||||
thread_local const shared_ptr<const abstract_type> float_type(make_shared<float_type_impl>());
|
||||
@@ -2832,6 +3069,8 @@ thread_local const data_type empty_type(make_shared<empty_type_impl>());
|
||||
data_type abstract_type::parse_type(const sstring& name)
|
||||
{
|
||||
static thread_local const std::unordered_map<sstring, data_type> types = {
|
||||
{ byte_type_name, byte_type },
|
||||
{ short_type_name, short_type },
|
||||
{ int32_type_name, int32_type },
|
||||
{ long_type_name, long_type },
|
||||
{ ascii_type_name, ascii_type },
|
||||
@@ -2841,6 +3080,8 @@ data_type abstract_type::parse_type(const sstring& name)
|
||||
{ date_type_name, date_type },
|
||||
{ timeuuid_type_name, timeuuid_type },
|
||||
{ timestamp_type_name, timestamp_type },
|
||||
{ simple_date_type_name, simple_date_type },
|
||||
{ time_type_name, time_type },
|
||||
{ uuid_type_name, uuid_type },
|
||||
{ inet_addr_type_name, inet_addr_type },
|
||||
{ float_type_name, float_type },
|
||||
@@ -2889,6 +3130,12 @@ data_value::data_value(const char* v) : data_value(make_new(utf8_type, sstring(v
|
||||
data_value::data_value(bool v) : data_value(make_new(boolean_type, v)) {
|
||||
}
|
||||
|
||||
data_value::data_value(int8_t v) : data_value(make_new(byte_type, v)) {
|
||||
}
|
||||
|
||||
data_value::data_value(int16_t v) : data_value(make_new(short_type, v)) {
|
||||
}
|
||||
|
||||
data_value::data_value(int32_t v) : data_value(make_new(int32_type, v)) {
|
||||
}
|
||||
|
||||
|
||||
18
types.hh
18
types.hh
@@ -310,6 +310,8 @@ public:
|
||||
data_value(sstring);
|
||||
data_value(const char*);
|
||||
data_value(bool);
|
||||
data_value(int8_t);
|
||||
data_value(int16_t);
|
||||
data_value(int32_t);
|
||||
data_value(int64_t);
|
||||
data_value(utils::UUID);
|
||||
@@ -1082,6 +1084,8 @@ abstract_type::as_tri_comparator() const {
|
||||
using key_compare = serialized_compare;
|
||||
|
||||
// Remember to update type_codec in transport/server.cc and cql3/cql3_type.cc
|
||||
extern thread_local const shared_ptr<const abstract_type> byte_type;
|
||||
extern thread_local const shared_ptr<const abstract_type> short_type;
|
||||
extern thread_local const shared_ptr<const abstract_type> int32_type;
|
||||
extern thread_local const shared_ptr<const abstract_type> long_type;
|
||||
extern thread_local const shared_ptr<const abstract_type> ascii_type;
|
||||
@@ -1091,6 +1095,8 @@ extern thread_local const shared_ptr<const abstract_type> boolean_type;
|
||||
extern thread_local const shared_ptr<const abstract_type> date_type;
|
||||
extern thread_local const shared_ptr<const abstract_type> timeuuid_type;
|
||||
extern thread_local const shared_ptr<const abstract_type> timestamp_type;
|
||||
extern thread_local const shared_ptr<const abstract_type> simple_date_type;
|
||||
extern thread_local const shared_ptr<const abstract_type> time_type;
|
||||
extern thread_local const shared_ptr<const abstract_type> uuid_type;
|
||||
extern thread_local const shared_ptr<const abstract_type> inet_addr_type;
|
||||
extern thread_local const shared_ptr<const abstract_type> float_type;
|
||||
@@ -1100,6 +1106,18 @@ extern thread_local const shared_ptr<const abstract_type> decimal_type;
|
||||
extern thread_local const shared_ptr<const abstract_type> counter_type;
|
||||
extern thread_local const data_type empty_type;
|
||||
|
||||
template <>
|
||||
inline
|
||||
shared_ptr<const abstract_type> data_type_for<int8_t>() {
|
||||
return byte_type;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline
|
||||
shared_ptr<const abstract_type> data_type_for<int16_t>() {
|
||||
return short_type;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline
|
||||
shared_ptr<const abstract_type> data_type_for<int32_t>() {
|
||||
|
||||
6528
utils/date.h
Normal file
6528
utils/date.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -37,7 +37,7 @@ public:
|
||||
}
|
||||
|
||||
static version current() {
|
||||
static version v(2, 1, 8);
|
||||
static version v(2, 2, 8);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user