mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 15:12:02 +00:00
Comparison between DateTime64 and String values (just like for DateTime)
This commit is contained in:
parent
228dbf475e
commit
86edceeb81
@ -1125,12 +1125,10 @@ public:
|
|||||||
|
|
||||||
if (!((both_represented_by_number && !has_date) /// Do not allow compare date and number.
|
if (!((both_represented_by_number && !has_date) /// Do not allow compare date and number.
|
||||||
|| (left.isStringOrFixedString() && right.isStringOrFixedString())
|
|| (left.isStringOrFixedString() && right.isStringOrFixedString())
|
||||||
|| (left.isDate() && right.isDate())
|
/// You can compare the date, datetime, or datatime64 and an enumeration with a constant string.
|
||||||
|| (left.isDate() && right.isString()) /// You can compare the date, datetime and an enumeration with a constant string.
|
|| (left.isString() && right.isDateOrDateTime())
|
||||||
|| (left.isString() && right.isDate())
|
|| (left.isDateOrDateTime() && right.isString())
|
||||||
|| (left.isDateTime() && right.isDateTime())
|
|| (left.isDateOrDateTime() && right.isDateOrDateTime() && left.idx == right.idx) /// only date vs date, or datetime vs datetime
|
||||||
|| (left.isDateTime() && right.isString())
|
|
||||||
|| (left.isString() && right.isDateTime())
|
|
||||||
|| (left.isUUID() && right.isUUID())
|
|| (left.isUUID() && right.isUUID())
|
||||||
|| (left.isUUID() && right.isString())
|
|| (left.isUUID() && right.isString())
|
||||||
|| (left.isString() && right.isUUID())
|
|| (left.isString() && right.isUUID())
|
||||||
@ -1228,6 +1226,65 @@ public:
|
|||||||
{
|
{
|
||||||
executeTuple(block, result, col_with_type_and_name_left, col_with_type_and_name_right, input_rows_count);
|
executeTuple(block, result, col_with_type_and_name_left, col_with_type_and_name_right, input_rows_count);
|
||||||
}
|
}
|
||||||
|
else if (which_left.idx != which_right.idx
|
||||||
|
&& (which_left.isDateTime64() || which_right.isDateTime64())
|
||||||
|
&& (which_left.isStringOrFixedString() || which_right.isStringOrFixedString()))
|
||||||
|
{
|
||||||
|
/** Special case of comparing DateTime64 against a string.
|
||||||
|
*
|
||||||
|
* Can't be moved to executeDateOrDateTimeOrEnumOrUUIDWithConstString()
|
||||||
|
* since DateTime64 is basically a Decimal, but we do similar things, except type inference.
|
||||||
|
* Outline:
|
||||||
|
* - Extract string content
|
||||||
|
* - Parse it as a ColumnDateTime64 value (same type as DateTime64, means same precision)
|
||||||
|
* - Fabricate a column with type and name
|
||||||
|
* - Compare left and right comlumns as DateTime64 columns.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const size_t datetime64_col_index = which_left.isDateTime64() ? 0 : 1;
|
||||||
|
const size_t string_col_index = which_left.isStringOrFixedString() ? 0 : 1;
|
||||||
|
|
||||||
|
const auto & datetime64_col_with_type_and_name = block.getByPosition(arguments[datetime64_col_index]);
|
||||||
|
const auto & string_col_with_type_and_name = block.getByPosition(arguments[string_col_index]);
|
||||||
|
|
||||||
|
if (!isColumnConst(*string_col_with_type_and_name.column))
|
||||||
|
throw Exception(getName() + ", illegal column type of argument #" + std::to_string(string_col_index)
|
||||||
|
+ " '" + string_col_with_type_and_name.name + "'"
|
||||||
|
" expected const String or const FixedString,"
|
||||||
|
" got " + string_col_with_type_and_name.type->getName(),
|
||||||
|
ErrorCodes::ILLEGAL_COLUMN);
|
||||||
|
|
||||||
|
if (datetime64_col_with_type_and_name.column->size() == 0 || string_col_with_type_and_name.column->size() == 0)
|
||||||
|
{
|
||||||
|
// For some reason, when both left and right columns are empty (dry run while building a header block)
|
||||||
|
// executeDecimal() fills result column with bogus value.
|
||||||
|
block.getByPosition(result).column = ColumnUInt8::create();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto parsed_tmp_column_holder = datetime64_col_with_type_and_name.type->createColumn();
|
||||||
|
|
||||||
|
{
|
||||||
|
const StringRef string_value = string_col_with_type_and_name.column->getDataAt(0);
|
||||||
|
ReadBufferFromMemory in(string_value.data, string_value.size);
|
||||||
|
datetime64_col_with_type_and_name.type->deserializeAsWholeText(*parsed_tmp_column_holder, in, FormatSettings{});
|
||||||
|
|
||||||
|
if (!in.eof())
|
||||||
|
throw Exception(getName() + ": String is too long for " + datetime64_col_with_type_and_name.type->getName() + " : " + string_value.toString(), ErrorCodes::TOO_LARGE_STRING_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is necessary to wrap tmp column in ColumnConst to avoid overflow when comparing.
|
||||||
|
// (non-const columns are expected to have same number of rows as every other column in block).
|
||||||
|
const ColumnWithTypeAndName parsed_tmp_col_with_type_and_name{
|
||||||
|
ColumnConst::create(std::move(parsed_tmp_column_holder), 1),
|
||||||
|
datetime64_col_with_type_and_name.type,
|
||||||
|
string_col_with_type_and_name.name};
|
||||||
|
|
||||||
|
executeDecimal(block, result,
|
||||||
|
which_left.isDateTime64() ? datetime64_col_with_type_and_name : parsed_tmp_col_with_type_and_name,
|
||||||
|
which_right.isDateTime64() ? datetime64_col_with_type_and_name : parsed_tmp_col_with_type_and_name);
|
||||||
|
|
||||||
|
}
|
||||||
else if (isColumnedAsDecimal(left_type) || isColumnedAsDecimal(right_type))
|
else if (isColumnedAsDecimal(left_type) || isColumnedAsDecimal(right_type))
|
||||||
{
|
{
|
||||||
// compare
|
// compare
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
in SELECT
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
in WHERE
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
other operators
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
35
tests/queries/0_stateless/01268_DateTime64_in_WHERE.sql
Normal file
35
tests/queries/0_stateless/01268_DateTime64_in_WHERE.sql
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
-- Error cases:
|
||||||
|
-- non-const string column
|
||||||
|
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT DT64 = materialize(S); -- {serverError 44}
|
||||||
|
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT materialize(S) = toDateTime64(S, 3); -- {serverError 44}
|
||||||
|
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT * WHERE DT64 = materialize(S); -- {serverError 44}
|
||||||
|
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT * WHERE materialize(S) = DT64; -- {serverError 44}
|
||||||
|
|
||||||
|
SELECT * WHERE toDateTime64(123.345, 3) == 'ABCD'; -- {serverError 131} -- invalid DateTime64 string
|
||||||
|
SELECT * WHERE toDateTime64(123.345, 3) == '2020-02-05 14:34:12.33333333333333333333333333333333333333333333333333333333'; -- {serverError 131} -- invalid string length
|
||||||
|
|
||||||
|
SELECT 'in SELECT';
|
||||||
|
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT DT64 = S;
|
||||||
|
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT S = DT64;
|
||||||
|
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT materialize(DT64) = S;
|
||||||
|
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT S = materialize(DT64);
|
||||||
|
|
||||||
|
SELECT 'in WHERE';
|
||||||
|
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT * WHERE DT64 = S;
|
||||||
|
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT * WHERE S = DT64;
|
||||||
|
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT * WHERE materialize(DT64) = S;
|
||||||
|
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT * WHERE S = materialize(DT64);
|
||||||
|
|
||||||
|
SELECT 'other operators';
|
||||||
|
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT * WHERE DT64 <= S;
|
||||||
|
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT * WHERE DT64 >= S;
|
||||||
|
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT * WHERE S <= DT64;
|
||||||
|
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT * WHERE S >= DT64;
|
||||||
|
|
||||||
|
-- empty results
|
||||||
|
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT * WHERE DT64 < S;
|
||||||
|
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT * WHERE DT64 > S;
|
||||||
|
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT * WHERE DT64 != S;
|
||||||
|
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT * WHERE S < DT64;
|
||||||
|
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT * WHERE S > DT64;
|
||||||
|
WITH '2020-02-05 14:34:12.333' as S, toDateTime64(S, 3) as DT64 SELECT * WHERE S != DT64;
|
Loading…
Reference in New Issue
Block a user