Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
2dot5
ClickHouse
提交
f1e9f671
C
ClickHouse
项目概览
2dot5
/
ClickHouse
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
ClickHouse
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
f1e9f671
编写于
11月 29, 2020
作者:
R
robot-clickhouse
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Backport #17145 to 20.12: Fix unmatched type comparison in KeyCondition
上级
8f2d33f5
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
95 addition
and
19 deletion
+95
-19
src/DataTypes/getLeastSupertype.cpp
src/DataTypes/getLeastSupertype.cpp
+24
-1
src/Storages/MergeTree/KeyCondition.cpp
src/Storages/MergeTree/KeyCondition.cpp
+50
-18
tests/queries/0_stateless/01579_date_datetime_index_comparison.reference
..._stateless/01579_date_datetime_index_comparison.reference
+5
-0
tests/queries/0_stateless/01579_date_datetime_index_comparison.sql
...ries/0_stateless/01579_date_datetime_index_comparison.sql
+16
-0
未找到文件。
src/DataTypes/getLeastSupertype.cpp
浏览文件 @
f1e9f671
...
...
@@ -358,6 +358,8 @@ DataTypePtr getLeastSupertype(const DataTypes & types)
maximize
(
max_bits_of_unsigned_integer
,
32
);
else
if
(
typeid_cast
<
const
DataTypeUInt64
*>
(
type
.
get
()))
maximize
(
max_bits_of_unsigned_integer
,
64
);
else
if
(
typeid_cast
<
const
DataTypeUInt256
*>
(
type
.
get
()))
maximize
(
max_bits_of_unsigned_integer
,
256
);
else
if
(
typeid_cast
<
const
DataTypeInt8
*>
(
type
.
get
()))
maximize
(
max_bits_of_signed_integer
,
8
);
else
if
(
typeid_cast
<
const
DataTypeInt16
*>
(
type
.
get
()))
...
...
@@ -366,6 +368,10 @@ DataTypePtr getLeastSupertype(const DataTypes & types)
maximize
(
max_bits_of_signed_integer
,
32
);
else
if
(
typeid_cast
<
const
DataTypeInt64
*>
(
type
.
get
()))
maximize
(
max_bits_of_signed_integer
,
64
);
else
if
(
typeid_cast
<
const
DataTypeInt128
*>
(
type
.
get
()))
maximize
(
max_bits_of_signed_integer
,
128
);
else
if
(
typeid_cast
<
const
DataTypeInt256
*>
(
type
.
get
()))
maximize
(
max_bits_of_signed_integer
,
256
);
else
if
(
typeid_cast
<
const
DataTypeFloat32
*>
(
type
.
get
()))
maximize
(
max_mantissa_bits_of_floating
,
24
);
else
if
(
typeid_cast
<
const
DataTypeFloat64
*>
(
type
.
get
()))
...
...
@@ -386,7 +392,18 @@ DataTypePtr getLeastSupertype(const DataTypes & types)
/// If unsigned is not covered by signed.
if
(
max_bits_of_signed_integer
&&
max_bits_of_unsigned_integer
>=
max_bits_of_signed_integer
)
++
min_bit_width_of_integer
;
{
// Because 128 and 256 bit integers are significantly slower, we should not promote to them.
// But if we already have wide numbers, promotion is necessary.
if
(
min_bit_width_of_integer
!=
64
)
++
min_bit_width_of_integer
;
else
throw
Exception
(
getExceptionMessagePrefix
(
types
)
+
" because some of them are signed integers and some are unsigned integers,"
" but there is no signed integer type, that can exactly represent all required unsigned integer values"
,
ErrorCodes
::
NO_COMMON_TYPE
);
}
/// If the result must be floating.
if
(
max_mantissa_bits_of_floating
)
...
...
@@ -413,6 +430,10 @@ DataTypePtr getLeastSupertype(const DataTypes & types)
return
std
::
make_shared
<
DataTypeInt32
>
();
else
if
(
min_bit_width_of_integer
<=
64
)
return
std
::
make_shared
<
DataTypeInt64
>
();
else
if
(
min_bit_width_of_integer
<=
128
)
return
std
::
make_shared
<
DataTypeInt128
>
();
else
if
(
min_bit_width_of_integer
<=
256
)
return
std
::
make_shared
<
DataTypeInt256
>
();
else
throw
Exception
(
getExceptionMessagePrefix
(
types
)
+
" because some of them are signed integers and some are unsigned integers,"
...
...
@@ -429,6 +450,8 @@ DataTypePtr getLeastSupertype(const DataTypes & types)
return
std
::
make_shared
<
DataTypeUInt32
>
();
else
if
(
min_bit_width_of_integer
<=
64
)
return
std
::
make_shared
<
DataTypeUInt64
>
();
else
if
(
min_bit_width_of_integer
<=
256
)
return
std
::
make_shared
<
DataTypeUInt256
>
();
else
throw
Exception
(
"Logical error: "
+
getExceptionMessagePrefix
(
types
)
+
" but as all data types are unsigned integers, we must have found maximum unsigned integer type"
,
ErrorCodes
::
NO_COMMON_TYPE
);
...
...
src/Storages/MergeTree/KeyCondition.cpp
浏览文件 @
f1e9f671
...
...
@@ -2,12 +2,14 @@
#include <Storages/MergeTree/BoolMask.h>
#include <DataTypes/DataTypesNumber.h>
#include <DataTypes/FieldToDataType.h>
#include <DataTypes/getLeastSupertype.h>
#include <Interpreters/TreeRewriter.h>
#include <Interpreters/ExpressionAnalyzer.h>
#include <Interpreters/ExpressionActions.h>
#include <Interpreters/castColumn.h>
#include <Interpreters/misc.h>
#include <Functions/FunctionFactory.h>
#include <Functions/FunctionsConversion.h>
#include <Functions/IFunction.h>
#include <Common/FieldVisitorsAccurateComparison.h>
#include <Common/typeid_cast.h>
...
...
@@ -23,7 +25,6 @@
#include <cassert>
#include <stack>
namespace
DB
{
...
...
@@ -959,9 +960,6 @@ bool KeyCondition::isKeyPossiblyWrappedByMonotonicFunctionsImpl(
static
void
castValueToType
(
const
DataTypePtr
&
desired_type
,
Field
&
src_value
,
const
DataTypePtr
&
src_type
,
const
ASTPtr
&
node
)
{
if
(
desired_type
->
equals
(
*
src_type
))
return
;
try
{
src_value
=
convertFieldToType
(
src_value
,
*
desired_type
,
src_type
.
get
());
...
...
@@ -1068,15 +1066,6 @@ bool KeyCondition::tryParseAtomFromAST(const ASTPtr & node, const Context & cont
if
(
key_column_num
==
static_cast
<
size_t
>
(
-
1
))
throw
Exception
(
"`key_column_num` wasn't initialized. It is a bug."
,
ErrorCodes
::
LOGICAL_ERROR
);
/// Transformed constant must weaken the condition, for example "x > 5" must weaken to "round(x) >= 5"
if
(
is_constant_transformed
)
{
if
(
func_name
==
"less"
)
func_name
=
"lessOrEquals"
;
else
if
(
func_name
==
"greater"
)
func_name
=
"greaterOrEquals"
;
}
/// Replace <const> <sign> <data> on to <data> <-sign> <const>
if
(
key_arg_pos
==
1
)
{
...
...
@@ -1098,12 +1087,55 @@ bool KeyCondition::tryParseAtomFromAST(const ASTPtr & node, const Context & cont
}
}
bool
cast_not_needed
=
is_set_const
/// Set args are already casted inside Set::createFromAST
||
(
isNativeNumber
(
key_expr_type
)
&&
isNativeNumber
(
const_type
));
/// Numbers are accurately compared without cast.
bool
cast_not_needed
=
is_set_const
/// Set args are already casted inside Set::createFromAST
||
((
isNativeNumber
(
key_expr_type
)
||
isDateTime
(
key_expr_type
))
&&
(
isNativeNumber
(
const_type
)
||
isDateTime
(
const_type
)));
/// Numbers and DateTime are accurately compared without cast.
if
(
!
cast_not_needed
&&
!
key_expr_type
->
equals
(
*
const_type
))
{
if
(
const_value
.
getType
()
==
Field
::
Types
::
String
)
{
const_value
=
convertFieldToType
(
const_value
,
*
key_expr_type
);
if
(
const_value
.
isNull
())
return
false
;
// No need to set is_constant_transformed because we're doing exact conversion
}
else
{
DataTypePtr
common_type
=
getLeastSupertype
({
key_expr_type
,
const_type
});
if
(
!
const_type
->
equals
(
*
common_type
))
{
castValueToType
(
common_type
,
const_value
,
const_type
,
node
);
// Need to set is_constant_transformed unless we're doing exact conversion
if
(
!
key_expr_type
->
equals
(
*
common_type
))
is_constant_transformed
=
true
;
}
if
(
!
key_expr_type
->
equals
(
*
common_type
))
{
ColumnsWithTypeAndName
arguments
{
{
nullptr
,
key_expr_type
,
""
},
{
DataTypeString
().
createColumnConst
(
1
,
common_type
->
getName
()),
common_type
,
""
}};
FunctionOverloadResolverPtr
func_builder_cast
=
std
::
make_shared
<
FunctionOverloadResolverAdaptor
>
(
CastOverloadResolver
::
createImpl
(
false
));
auto
func_cast
=
func_builder_cast
->
build
(
arguments
);
/// If we know the given range only contains one value, then we treat all functions as positive monotonic.
if
(
!
func_cast
||
(
!
single_point
&&
!
func_cast
->
hasInformationAboutMonotonicity
()))
return
false
;
chain
.
push_back
(
func_cast
);
}
}
}
/// Transformed constant must weaken the condition, for example "x > 5" must weaken to "round(x) >= 5"
if
(
is_constant_transformed
)
{
if
(
func_name
==
"less"
)
func_name
=
"lessOrEquals"
;
else
if
(
func_name
==
"greater"
)
func_name
=
"greaterOrEquals"
;
}
if
(
!
cast_not_needed
)
castValueToType
(
key_expr_type
,
const_value
,
const_type
,
node
);
}
else
return
false
;
...
...
tests/queries/0_stateless/01579_date_datetime_index_comparison.reference
0 → 100644
浏览文件 @
f1e9f671
1
Array(Int64)
Array(Int128)
Array(Int128)
Array(UInt256)
tests/queries/0_stateless/01579_date_datetime_index_comparison.sql
0 → 100644
浏览文件 @
f1e9f671
drop
table
if
exists
test_index
;
create
table
test_index
(
date
Date
)
engine
MergeTree
partition
by
toYYYYMM
(
date
)
order
by
date
;
insert
into
test_index
values
(
'2020-10-30'
);
select
1
from
test_index
where
date
<
toDateTime
(
'2020-10-30 06:00:00'
);
drop
table
if
exists
test_index
;
select
toTypeName
([
-
1
,
toUInt32
(
1
)]);
-- We don't promote to wide integers
select
toTypeName
([
-
1
,
toUInt64
(
1
)]);
-- { serverError 386 }
select
toTypeName
([
-
1
,
toInt128
(
1
)]);
select
toTypeName
([
toInt64
(
-
1
),
toInt128
(
1
)]);
select
toTypeName
([
toUInt64
(
1
),
toUInt256
(
1
)]);
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录