mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 15:12:02 +00:00
Merge pull request #16337 from kitaisreal/uuid-safe-cast-functions-added
UUID safe cast functions added
This commit is contained in:
commit
5fbca7d62d
@ -61,6 +61,54 @@ SELECT toUUID('61f0c404-5cb3-11e7-907b-a6006ad3dba0') AS uuid
|
||||
└──────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## toUUIDOrNull (x) {#touuidornull-x}
|
||||
|
||||
It takes an argument of type String and tries to parse it into UUID. If failed, returns NULL.
|
||||
|
||||
``` sql
|
||||
toUUIDOrNull(String)
|
||||
```
|
||||
|
||||
**Returned value**
|
||||
|
||||
The Nullable(UUID) type value.
|
||||
|
||||
**Usage example**
|
||||
|
||||
``` sql
|
||||
SELECT toUUIDOrNull('61f0c404-5cb3-11e7-907b-a6006ad3dba0T') AS uuid
|
||||
```
|
||||
|
||||
``` text
|
||||
┌─uuid─┐
|
||||
│ ᴺᵁᴸᴸ │
|
||||
└──────┘
|
||||
```
|
||||
|
||||
## toUUIDOrZero (x) {#touuidorzero-x}
|
||||
|
||||
It takes an argument of type String and tries to parse it into UUID. If failed, returns zero UUID.
|
||||
|
||||
``` sql
|
||||
toUUIDOrZero(String)
|
||||
```
|
||||
|
||||
**Returned value**
|
||||
|
||||
The UUID type value.
|
||||
|
||||
**Usage example**
|
||||
|
||||
``` sql
|
||||
SELECT toUUIDOrZero('61f0c404-5cb3-11e7-907b-a6006ad3dba0T') AS uuid
|
||||
```
|
||||
|
||||
``` text
|
||||
┌─────────────────────────────────uuid─┐
|
||||
│ 00000000-0000-0000-0000-000000000000 │
|
||||
└──────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## UUIDStringToNum {#uuidstringtonum}
|
||||
|
||||
Accepts a string containing 36 characters in the format `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`, and returns it as a set of bytes in a [FixedString(16)](../../sql-reference/data-types/fixedstring.md).
|
||||
|
@ -68,6 +68,8 @@ void registerFunctionsConversion(FunctionFactory & factory)
|
||||
factory.registerFunction<FunctionToDecimal128OrZero>();
|
||||
factory.registerFunction<FunctionToDecimal256OrZero>();
|
||||
|
||||
factory.registerFunction<FunctionToUUIDOrZero>();
|
||||
|
||||
factory.registerFunction<FunctionToUInt8OrNull>();
|
||||
factory.registerFunction<FunctionToUInt16OrNull>();
|
||||
factory.registerFunction<FunctionToUInt32OrNull>();
|
||||
@ -90,6 +92,8 @@ void registerFunctionsConversion(FunctionFactory & factory)
|
||||
factory.registerFunction<FunctionToDecimal128OrNull>();
|
||||
factory.registerFunction<FunctionToDecimal256OrNull>();
|
||||
|
||||
factory.registerFunction<FunctionToUUIDOrNull>();
|
||||
|
||||
factory.registerFunction<FunctionParseDateTimeBestEffort>();
|
||||
factory.registerFunction<FunctionParseDateTimeBestEffortUS>();
|
||||
factory.registerFunction<FunctionParseDateTimeBestEffortOrZero>();
|
||||
|
@ -569,7 +569,7 @@ template <>
|
||||
inline void parseImpl<DataTypeUUID>(DataTypeUUID::FieldType & x, ReadBuffer & rb, const DateLUTImpl *)
|
||||
{
|
||||
UUID tmp;
|
||||
readText(tmp, rb);
|
||||
readUUIDText(tmp, rb);
|
||||
x = tmp;
|
||||
}
|
||||
|
||||
@ -603,6 +603,17 @@ inline bool tryParseImpl<DataTypeDateTime>(DataTypeDateTime::FieldType & x, Read
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool tryParseImpl<DataTypeUUID>(DataTypeUUID::FieldType & x, ReadBuffer & rb, const DateLUTImpl *)
|
||||
{
|
||||
UUID tmp;
|
||||
if (!tryReadUUIDText(tmp, rb))
|
||||
return false;
|
||||
|
||||
x = tmp;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/** Throw exception with verbose message when string value is not parsed completely.
|
||||
*/
|
||||
@ -1755,6 +1766,7 @@ struct NameToDecimal32OrZero { static constexpr auto name = "toDecimal32OrZero";
|
||||
struct NameToDecimal64OrZero { static constexpr auto name = "toDecimal64OrZero"; };
|
||||
struct NameToDecimal128OrZero { static constexpr auto name = "toDecimal128OrZero"; };
|
||||
struct NameToDecimal256OrZero { static constexpr auto name = "toDecimal256OrZero"; };
|
||||
struct NameToUUIDOrZero { static constexpr auto name = "toUUIDOrZero"; };
|
||||
|
||||
using FunctionToUInt8OrZero = FunctionConvertFromString<DataTypeUInt8, NameToUInt8OrZero, ConvertFromStringExceptionMode::Zero>;
|
||||
using FunctionToUInt16OrZero = FunctionConvertFromString<DataTypeUInt16, NameToUInt16OrZero, ConvertFromStringExceptionMode::Zero>;
|
||||
@ -1776,6 +1788,7 @@ using FunctionToDecimal32OrZero = FunctionConvertFromString<DataTypeDecimal<Deci
|
||||
using FunctionToDecimal64OrZero = FunctionConvertFromString<DataTypeDecimal<Decimal64>, NameToDecimal64OrZero, ConvertFromStringExceptionMode::Zero>;
|
||||
using FunctionToDecimal128OrZero = FunctionConvertFromString<DataTypeDecimal<Decimal128>, NameToDecimal128OrZero, ConvertFromStringExceptionMode::Zero>;
|
||||
using FunctionToDecimal256OrZero = FunctionConvertFromString<DataTypeDecimal<Decimal256>, NameToDecimal256OrZero, ConvertFromStringExceptionMode::Zero>;
|
||||
using FunctionToUUIDOrZero = FunctionConvertFromString<DataTypeUUID, NameToUUIDOrZero, ConvertFromStringExceptionMode::Zero>;
|
||||
|
||||
struct NameToUInt8OrNull { static constexpr auto name = "toUInt8OrNull"; };
|
||||
struct NameToUInt16OrNull { static constexpr auto name = "toUInt16OrNull"; };
|
||||
@ -1797,6 +1810,7 @@ struct NameToDecimal32OrNull { static constexpr auto name = "toDecimal32OrNull";
|
||||
struct NameToDecimal64OrNull { static constexpr auto name = "toDecimal64OrNull"; };
|
||||
struct NameToDecimal128OrNull { static constexpr auto name = "toDecimal128OrNull"; };
|
||||
struct NameToDecimal256OrNull { static constexpr auto name = "toDecimal256OrNull"; };
|
||||
struct NameToUUIDOrNull { static constexpr auto name = "toUUIDOrNull"; };
|
||||
|
||||
using FunctionToUInt8OrNull = FunctionConvertFromString<DataTypeUInt8, NameToUInt8OrNull, ConvertFromStringExceptionMode::Null>;
|
||||
using FunctionToUInt16OrNull = FunctionConvertFromString<DataTypeUInt16, NameToUInt16OrNull, ConvertFromStringExceptionMode::Null>;
|
||||
@ -1818,6 +1832,7 @@ using FunctionToDecimal32OrNull = FunctionConvertFromString<DataTypeDecimal<Deci
|
||||
using FunctionToDecimal64OrNull = FunctionConvertFromString<DataTypeDecimal<Decimal64>, NameToDecimal64OrNull, ConvertFromStringExceptionMode::Null>;
|
||||
using FunctionToDecimal128OrNull = FunctionConvertFromString<DataTypeDecimal<Decimal128>, NameToDecimal128OrNull, ConvertFromStringExceptionMode::Null>;
|
||||
using FunctionToDecimal256OrNull = FunctionConvertFromString<DataTypeDecimal<Decimal256>, NameToDecimal256OrNull, ConvertFromStringExceptionMode::Null>;
|
||||
using FunctionToUUIDOrNull = FunctionConvertFromString<DataTypeUUID, NameToUUIDOrNull, ConvertFromStringExceptionMode::Null>;
|
||||
|
||||
struct NameParseDateTimeBestEffort { static constexpr auto name = "parseDateTimeBestEffort"; };
|
||||
struct NameParseDateTimeBestEffortUS { static constexpr auto name = "parseDateTimeBestEffortUS"; };
|
||||
|
@ -619,9 +619,11 @@ inline bool tryReadDateText(DayNum & date, ReadBuffer & buf)
|
||||
return readDateTextImpl<bool>(date, buf);
|
||||
}
|
||||
|
||||
|
||||
inline void readUUIDText(UUID & uuid, ReadBuffer & buf)
|
||||
template <typename ReturnType = void>
|
||||
inline ReturnType readUUIDTextImpl(UUID & uuid, ReadBuffer & buf)
|
||||
{
|
||||
static constexpr bool throw_exception = std::is_same_v<ReturnType, void>;
|
||||
|
||||
char s[36];
|
||||
size_t size = buf.read(s, 32);
|
||||
|
||||
@ -634,21 +636,49 @@ inline void readUUIDText(UUID & uuid, ReadBuffer & buf)
|
||||
if (size != 36)
|
||||
{
|
||||
s[size] = 0;
|
||||
throw Exception(std::string("Cannot parse uuid ") + s, ErrorCodes::CANNOT_PARSE_UUID);
|
||||
|
||||
if constexpr (throw_exception)
|
||||
{
|
||||
throw Exception(std::string("Cannot parse uuid ") + s, ErrorCodes::CANNOT_PARSE_UUID);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ReturnType(false);
|
||||
}
|
||||
}
|
||||
|
||||
parseUUID(reinterpret_cast<const UInt8 *>(s), std::reverse_iterator<UInt8 *>(reinterpret_cast<UInt8 *>(&uuid) + 16));
|
||||
}
|
||||
else
|
||||
parseUUIDWithoutSeparator(reinterpret_cast<const UInt8 *>(s), std::reverse_iterator<UInt8 *>(reinterpret_cast<UInt8 *>(&uuid) + 16));
|
||||
|
||||
return ReturnType(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
s[size] = 0;
|
||||
throw Exception(std::string("Cannot parse uuid ") + s, ErrorCodes::CANNOT_PARSE_UUID);
|
||||
|
||||
if constexpr (throw_exception)
|
||||
{
|
||||
throw Exception(std::string("Cannot parse uuid ") + s, ErrorCodes::CANNOT_PARSE_UUID);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ReturnType(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void readUUIDText(UUID & uuid, ReadBuffer & buf)
|
||||
{
|
||||
return readUUIDTextImpl<void>(uuid, buf);
|
||||
}
|
||||
|
||||
inline bool tryReadUUIDText(UUID & uuid, ReadBuffer & buf)
|
||||
{
|
||||
return readUUIDTextImpl<bool>(uuid, buf);
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
inline T parse(const char * data, size_t size);
|
||||
|
@ -0,0 +1,8 @@
|
||||
61f0c404-5cb3-11e7-907b-a6006ad3dba0
|
||||
\N
|
||||
00000000-0000-0000-0000-000000000000
|
||||
61f0c404-5cb3-11e7-907b-a6006ad3dba0
|
||||
61f0c404-5cb3-11e7-907b-a6006ad3dba0
|
||||
\N
|
||||
61f0c404-5cb3-11e7-907b-a6006ad3dba0
|
||||
00000000-0000-0000-0000-000000000000
|
19
tests/queries/0_stateless/01528_to_uuid_or_null_or_zero.sql
Normal file
19
tests/queries/0_stateless/01528_to_uuid_or_null_or_zero.sql
Normal file
@ -0,0 +1,19 @@
|
||||
DROP TABLE IF EXISTS to_uuid_test;
|
||||
|
||||
SELECT toUUID('61f0c404-5cb3-11e7-907b-a6006ad3dba0');
|
||||
SELECT toUUID('61f0c404-5cb3-11e7-907b-a6006ad3dba0T'); --{serverError 6}
|
||||
SELECT toUUIDOrNull('61f0c404-5cb3-11e7-907b-a6006ad3dba0T');
|
||||
SELECT toUUIDOrZero('59f0c404-5cb3-11e7-907b-a6006ad3dba0T');
|
||||
|
||||
CREATE TABLE to_uuid_test (value String) ENGINE = TinyLog();
|
||||
|
||||
INSERT INTO to_uuid_test VALUES ('61f0c404-5cb3-11e7-907b-a6006ad3dba0');
|
||||
SELECT toUUID(value) FROM to_uuid_test;
|
||||
|
||||
INSERT INTO to_uuid_test VALUES ('61f0c404-5cb3-11e7-907b-a6006ad3dba0T');
|
||||
SELECT toUUID(value) FROM to_uuid_test; -- {serverError 6}
|
||||
SELECT toUUIDOrNull(value) FROM to_uuid_test;
|
||||
SELECT toUUIDOrZero(value) FROM to_uuid_test;
|
||||
|
||||
DROP TABLE to_uuid_test;
|
||||
|
Loading…
Reference in New Issue
Block a user