diff --git a/src/IO/ReadHelpers.cpp b/src/IO/ReadHelpers.cpp index 9d1d27611b5..d4574732c58 100644 --- a/src/IO/ReadHelpers.cpp +++ b/src/IO/ReadHelpers.cpp @@ -33,11 +33,8 @@ void parseHex(IteratorSrc src, IteratorDst dst, const size_t num_bytes) { size_t src_pos = 0; size_t dst_pos = 0; - for (; dst_pos < num_bytes; ++dst_pos) - { - dst[dst_pos] = UInt8(unhex(src[src_pos])) * 16 + UInt8(unhex(src[src_pos + 1])); - src_pos += 2; - } + for (; dst_pos < num_bytes; ++dst_pos, src_pos += 2) + dst[dst_pos] = unhex2(reinterpret_cast(&src[src_pos])); } void parseUUID(const UInt8 * src36, UInt8 * dst16) @@ -51,6 +48,13 @@ void parseUUID(const UInt8 * src36, UInt8 * dst16) parseHex(&src36[24], &dst16[10], 6); } +void parseUUIDWithoutSeparator(const UInt8 * src36, UInt8 * dst16) +{ + /// If string is not like UUID - implementation specific behaviour. + + parseHex(&src36[0], &dst16[0], 16); +} + /** Function used when byte ordering is important when parsing uuid * ex: When we create an UUID type */ @@ -66,6 +70,17 @@ void parseUUID(const UInt8 * src36, std::reverse_iterator dst16) parseHex(&src36[24], dst16 + 2, 6); } +/** Function used when byte ordering is important when parsing uuid + * ex: When we create an UUID type + */ +void parseUUIDWithoutSeparator(const UInt8 * src36, std::reverse_iterator dst16) +{ + /// If string is not like UUID - implementation specific behaviour. + + parseHex(&src36[0], dst16 + 8, 8); + parseHex(&src36[16], dst16, 8); +} + UInt128 stringToUUID(const String & str) { return parseFromString(str); diff --git a/src/IO/ReadHelpers.h b/src/IO/ReadHelpers.h index 00bc6113186..7254ae43c17 100644 --- a/src/IO/ReadHelpers.h +++ b/src/IO/ReadHelpers.h @@ -515,7 +515,9 @@ struct NullSink }; void parseUUID(const UInt8 * src36, UInt8 * dst16); +void parseUUIDWithoutSeparator(const UInt8 * src36, UInt8 * dst16); void parseUUID(const UInt8 * src36, std::reverse_iterator dst16); +void parseUUIDWithoutSeparator(const UInt8 * src36, std::reverse_iterator dst16); template void formatHex(IteratorSrc src, IteratorDst dst, const size_t num_bytes); @@ -602,15 +604,30 @@ inline bool tryReadDateText(DayNum & date, ReadBuffer & buf) inline void readUUIDText(UUID & uuid, ReadBuffer & buf) { char s[36]; - size_t size = buf.read(s, 36); + size_t size = buf.read(s, 32); - if (size != 36) + if (size == 32) + { + if (s[8] == '-') + { + size += buf.read(&s[32], 4); + + if (size != 36) + { + s[size] = 0; + throw Exception(std::string("Cannot parse uuid ") + s, ErrorCodes::CANNOT_PARSE_UUID); + } + + parseUUID(reinterpret_cast(s), std::reverse_iterator(reinterpret_cast(&uuid) + 16)); + } + else + parseUUIDWithoutSeparator(reinterpret_cast(s), std::reverse_iterator(reinterpret_cast(&uuid) + 16)); + } + else { s[size] = 0; throw Exception(std::string("Cannot parse uuid ") + s, ErrorCodes::CANNOT_PARSE_UUID); } - - parseUUID(reinterpret_cast(s), std::reverse_iterator(reinterpret_cast(&uuid) + 16)); } diff --git a/tests/queries/0_stateless/01338_uuid_without_separator.reference b/tests/queries/0_stateless/01338_uuid_without_separator.reference new file mode 100644 index 00000000000..9ae1e1e6e2b --- /dev/null +++ b/tests/queries/0_stateless/01338_uuid_without_separator.reference @@ -0,0 +1,4 @@ +417ddc5d-e556-4d27-95dd-a34d84e46a50 +417ddc5d-e556-4d27-95dd-a34d84e46a50 +1 417ddc5d-e556-4d27-95dd-a34d84e46a50 Example 1 +2 417ddc5d-e556-4d27-95dd-a34d84e46a51 Example 2 diff --git a/tests/queries/0_stateless/01338_uuid_without_separator.sql b/tests/queries/0_stateless/01338_uuid_without_separator.sql new file mode 100644 index 00000000000..efbf4bc2812 --- /dev/null +++ b/tests/queries/0_stateless/01338_uuid_without_separator.sql @@ -0,0 +1,11 @@ +SELECT toUUID('417ddc5de5564d2795dda34d84e46a50'); +SELECT toUUID('417ddc5d-e556-4d27-95dd-a34d84e46a50'); + +DROP TABLE IF EXISTS t_uuid; +CREATE TABLE t_uuid (x UInt8, y UUID, z String) ENGINE = TinyLog; + +INSERT INTO t_uuid VALUES (1, '417ddc5de5564d2795dda34d84e46a50', 'Example 1'); +INSERT INTO t_uuid VALUES (2, '417ddc5d-e556-4d27-95dd-a34d84e46a51', 'Example 2'); + +SELECT * FROM t_uuid ORDER BY x ASC; +DROP TABLE IF EXISTS t_uuid;