mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-25 17:12:03 +00:00
Fixed generateSnowflakeID function and tests according
Update uuid-functions.md Adjust comments in unit tests
This commit is contained in:
parent
ab2509fdd3
commit
ace4aa36bf
@ -567,13 +567,15 @@ While no standard or recommendation exists for the epoch of Snowflake IDs, imple
|
|||||||
**Syntax**
|
**Syntax**
|
||||||
|
|
||||||
``` sql
|
``` sql
|
||||||
generateSnowflakeID([expr])
|
generateSnowflakeID([expr, [machine_id]])
|
||||||
```
|
```
|
||||||
|
|
||||||
**Arguments**
|
**Arguments**
|
||||||
|
|
||||||
- `expr` — An arbitrary [expression](../../sql-reference/syntax.md#syntax-expressions) used to bypass [common subexpression elimination](../../sql-reference/functions/index.md#common-subexpression-elimination) if the function is called multiple times in a query. The value of the expression has no effect on the returned Snowflake ID. Optional.
|
- `expr` — An arbitrary [expression](../../sql-reference/syntax.md#syntax-expressions) used to bypass [common subexpression elimination](../../sql-reference/functions/index.md#common-subexpression-elimination) if the function is called multiple times in a query. The value of the expression has no effect on the returned Snowflake ID. Optional.
|
||||||
|
|
||||||
|
- `machine_id` — A machine ID, the 10 least significant bits are used. Optional.
|
||||||
|
|
||||||
**Returned value**
|
**Returned value**
|
||||||
|
|
||||||
A value of type UInt64.
|
A value of type UInt64.
|
||||||
@ -608,6 +610,16 @@ SELECT generateSnowflakeID(1), generateSnowflakeID(2);
|
|||||||
└────────────────────────┴────────────────────────┘
|
└────────────────────────┴────────────────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Example with expression and machine ID
|
||||||
|
```
|
||||||
|
SELECT generateSnowflakeID('expr', 1);
|
||||||
|
|
||||||
|
┌─generateSnowflakeID('expr', 1)─┐
|
||||||
|
│ 7201148511606784002 │
|
||||||
|
└────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## snowflakeToDateTime
|
## snowflakeToDateTime
|
||||||
|
|
||||||
:::warning
|
:::warning
|
||||||
|
@ -96,7 +96,8 @@ struct SnowflakeIdRange
|
|||||||
/// 1. calculate Snowflake ID by current timestamp (`now`)
|
/// 1. calculate Snowflake ID by current timestamp (`now`)
|
||||||
/// 2. `begin = max(available, now)`
|
/// 2. `begin = max(available, now)`
|
||||||
/// 3. Calculate `end = begin + input_rows_count` handling `machine_seq_num` overflow
|
/// 3. Calculate `end = begin + input_rows_count` handling `machine_seq_num` overflow
|
||||||
SnowflakeIdRange getRangeOfAvailableIds(const SnowflakeId & available, size_t input_rows_count, uint64_t machine_id)
|
SnowflakeIdRange getRangeOfAvailableIds(const SnowflakeId & available, uint64_t machine_id, size_t input_rows_count)
|
||||||
|
|
||||||
{
|
{
|
||||||
/// 1. `now`
|
/// 1. `now`
|
||||||
SnowflakeId begin = {.timestamp = getTimestamp(), .machine_id = machine_id, .machine_seq_num = 0};
|
SnowflakeId begin = {.timestamp = getTimestamp(), .machine_id = machine_id, .machine_seq_num = 0};
|
||||||
@ -134,7 +135,7 @@ struct Data
|
|||||||
SnowflakeIdRange range;
|
SnowflakeIdRange range;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
range = getRangeOfAvailableIds(toSnowflakeId(available_snowflake_id), input_rows_count, machine_id);
|
range = getRangeOfAvailableIds(toSnowflakeId(available_snowflake_id), machine_id, input_rows_count);
|
||||||
}
|
}
|
||||||
while (!lowest_available_snowflake_id.compare_exchange_weak(available_snowflake_id, fromSnowflakeId(range.end)));
|
while (!lowest_available_snowflake_id.compare_exchange_weak(available_snowflake_id, fromSnowflakeId(range.end)));
|
||||||
/// CAS failed --> another thread updated `lowest_available_snowflake_id` and we re-try
|
/// CAS failed --> another thread updated `lowest_available_snowflake_id` and we re-try
|
||||||
@ -166,7 +167,9 @@ public:
|
|||||||
FunctionArgumentDescriptors mandatory_args;
|
FunctionArgumentDescriptors mandatory_args;
|
||||||
FunctionArgumentDescriptors optional_args{
|
FunctionArgumentDescriptors optional_args{
|
||||||
{"expr", nullptr, nullptr, "Arbitrary expression"},
|
{"expr", nullptr, nullptr, "Arbitrary expression"},
|
||||||
{"machine_id", static_cast<FunctionArgumentDescriptor::TypeValidator>(&isNativeUInt), nullptr, "UInt*"}
|
{"machine_id", static_cast<FunctionArgumentDescriptor::TypeValidator>(&isNativeUInt), static_cast<FunctionArgumentDescriptor::ColumnValidator>(&isColumnConst), "UInt*"}
|
||||||
|
{"machine_id", static_cast<FunctionArgumentDescriptor::TypeValidator>(&isNativeUInt), static_cast<FunctionArgumentDescriptor::ColumnValidator>(&isColumnConst), "const UInt*"}
|
||||||
|
|
||||||
};
|
};
|
||||||
validateFunctionArguments(*this, arguments, mandatory_args, optional_args);
|
validateFunctionArguments(*this, arguments, mandatory_args, optional_args);
|
||||||
|
|
||||||
@ -179,17 +182,14 @@ public:
|
|||||||
typename ColumnVector<UInt64>::Container & vec_to = col_res->getData();
|
typename ColumnVector<UInt64>::Container & vec_to = col_res->getData();
|
||||||
vec_to.resize(input_rows_count);
|
vec_to.resize(input_rows_count);
|
||||||
|
|
||||||
uint64_t machine_id = 0;
|
uint64_t machine_id = getMachineId();
|
||||||
if (arguments.size() == 2 && input_rows_count > 0)
|
if (arguments.size() == 2 && input_rows_count > 0)
|
||||||
{
|
{
|
||||||
const auto & col_machine_id = arguments[1].column;
|
const auto & col_machine_id = arguments[1].column;
|
||||||
machine_id = col_machine_id->getUInt(0);
|
machine_id = col_machine_id->getUInt(0);
|
||||||
|
/// Truncate machine id to 10 bits
|
||||||
|
machine_id &= (1ull << machine_id_bits_count) - 1;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
machine_id = getMachineId();
|
|
||||||
|
|
||||||
/// Truncate machine id to 10 bits
|
|
||||||
machine_id &= (1ull << machine_id_bits_count) - 1;
|
|
||||||
|
|
||||||
if (input_rows_count > 0)
|
if (input_rows_count > 0)
|
||||||
{
|
{
|
||||||
@ -226,7 +226,7 @@ REGISTER_FUNCTION(GenerateSnowflakeID)
|
|||||||
{"machine_id", "A machine ID, the 10 least significant bits are used. Optional."}
|
{"machine_id", "A machine ID, the 10 least significant bits are used. Optional."}
|
||||||
};
|
};
|
||||||
FunctionDocumentation::ReturnedValue returned_value = "A value of type UInt64";
|
FunctionDocumentation::ReturnedValue returned_value = "A value of type UInt64";
|
||||||
FunctionDocumentation::Examples examples = {{"single", "SELECT generateSnowflakeID()", "7201148511606784000"}, {"with_machine_id", "SELECT generateSnowflakeID(1)", ""}, {"with_machine_id_and_expression", "SELECT generateSnowflakeID('some_expression', 1)", ""}};
|
FunctionDocumentation::Examples examples = {{"no_arguments", "SELECT generateSnowflakeID()", "7201148511606784000"}, {"with_machine_id", "SELECT generateSnowflakeID(1)", "7201148511606784001"}, {"with_expression_and_machine_id", "SELECT generateSnowflakeID('some_expression', 1)", "7201148511606784002"}};
|
||||||
FunctionDocumentation::Categories categories = {"Snowflake ID"};
|
FunctionDocumentation::Categories categories = {"Snowflake ID"};
|
||||||
|
|
||||||
factory.registerFunction<FunctionGenerateSnowflakeID>({description, syntax, arguments, returned_value, examples, categories});
|
factory.registerFunction<FunctionGenerateSnowflakeID>({description, syntax, arguments, returned_value, examples, categories});
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
1
|
1
|
||||||
0
|
|
||||||
1
|
1
|
||||||
0
|
0
|
||||||
1
|
1
|
||||||
1
|
1
|
||||||
|
0
|
||||||
1
|
1
|
||||||
1
|
100
|
||||||
100
|
|
@ -2,14 +2,17 @@
|
|||||||
|
|
||||||
SELECT bitAnd(bitShiftRight(toUInt64(generateSnowflakeID()), 63), 1) = 0; -- check first bit is zero
|
SELECT bitAnd(bitShiftRight(toUInt64(generateSnowflakeID()), 63), 1) = 0; -- check first bit is zero
|
||||||
SELECT generateSnowflakeID() = generateSnowflakeID(1); -- same as ^^
|
SELECT generateSnowflakeID() = generateSnowflakeID(1); -- same as ^^
|
||||||
SELECT generateSnowflakeID(1) = generateSnowflakeID(1); -- enabled common subexpression elimination
|
|
||||||
|
|
||||||
SELECT generateSnowflakeID(1) = generateSnowflakeID(2); -- disabled common subexpression elimination --> lhs != rhs
|
SELECT generateSnowflakeID(1) = generateSnowflakeID(2); -- disabled common subexpression elimination --> lhs != rhs
|
||||||
SELECT generateSnowflakeID(1) != generateSnowflakeID(); -- Check different invocations yield different results
|
SELECT generateSnowflakeID(1) = generateSnowflakeID(1); -- enabled common subexpression elimination
|
||||||
|
|
||||||
SELECT generateSnowflakeID('expr', 1) = generateSnowflakeID('expr', 1); -- enabled common subexpression elimination
|
SELECT generateSnowflakeID('expr', 1) = generateSnowflakeID('expr', 1); -- enabled common subexpression elimination
|
||||||
SELECT generateSnowflakeID('expr', 1) != generateSnowflakeID('expr', 2); -- different machine IDs should produce different results
|
SELECT generateSnowflakeID('expr', 1) != generateSnowflakeID('expr', 2); -- different machine IDs should produce different results
|
||||||
SELECT generateSnowflakeID('expr', 1) != generateSnowflakeID('different_expr', 1); -- different expressions should bypass common subexpression elimination
|
|
||||||
|
SELECT bitAnd(generateSnowflakeID(1023), 1023) = 1023; -- check if the last 10 bits match the machine ID
|
||||||
|
|
||||||
|
SELECT generateSnowflakeID('invalid_machine_id'); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
|
||||||
|
|
||||||
|
SELECT generateSnowflakeID(materialize(toUInt64(1))) = generateSnowflakeID(materialize(toUInt64(1))); -- -- test with non-const machine ID
|
||||||
|
|
||||||
SELECT count(*)
|
SELECT count(*)
|
||||||
FROM
|
FROM
|
||||||
|
Loading…
Reference in New Issue
Block a user