Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
2dot5
ClickHouse
提交
651bac51
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,发现更多精彩内容 >>
提交
651bac51
编写于
5月 14, 2018
作者:
N
Nikolai Kochetov
提交者:
alexey-milovidov
5月 15, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fixed element types for explicit set in IN function.
Fixed element types for explicit set in IN function. [#CLICKHOUSE-3730]
上级
7c2fa8b7
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
52 addition
and
56 deletion
+52
-56
dbms/src/Interpreters/ExpressionAnalyzer.cpp
dbms/src/Interpreters/ExpressionAnalyzer.cpp
+52
-56
未找到文件。
dbms/src/Interpreters/ExpressionAnalyzer.cpp
浏览文件 @
651bac51
...
...
@@ -58,7 +58,9 @@
#include <DataTypes/DataTypeFactory.h>
#include <DataTypes/DataTypeFunction.h>
#include <Functions/FunctionsMiscellaneous.h>
#include <DataTypes/DataTypeTuple.h>
#include "ProjectionManipulation.h"
#include "evaluateConstantExpression.h"
namespace
DB
...
...
@@ -1645,82 +1647,76 @@ void ExpressionAnalyzer::makeExplicitSet(const ASTFunction * node, const Block &
if
(
args
.
children
.
size
()
!=
2
)
throw
Exception
(
"Wrong number of arguments passed to function in"
,
ErrorCodes
::
NUMBER_OF_ARGUMENTS_DOESNT_MATCH
);
const
ASTPtr
&
arg
=
args
.
children
.
at
(
1
);
DataTypes
set_element_types
;
const
ASTPtr
&
left_arg
=
args
.
children
.
at
(
0
);
const
ASTPtr
&
right_arg
=
args
.
children
.
at
(
1
);
const
DataTypePtr
&
left_arg_type
=
sample_block
.
getByName
(
left_arg
->
getColumnName
()).
type
;
const
ASTFunction
*
left_arg_tuple
=
typeid_cast
<
const
ASTFunction
*>
(
left_arg
.
get
());
/** NOTE If tuple in left hand side specified non-explicitly
* Example: identity((a, b)) IN ((1, 2), (3, 4))
* instead of (a, b)) IN ((1, 2), (3, 4))
* then set creation doesn't work correctly.
*/
if
(
left_arg_tuple
&&
left_arg_tuple
->
name
==
"tuple"
)
std
::
function
<
size_t
(
const
DataTypePtr
&
)
>
getTupleDepth
;
getTupleDepth
=
[
&
getTupleDepth
](
const
DataTypePtr
&
type
)
->
size_t
{
for
(
const
auto
&
arg
:
left_arg_tuple
->
arguments
->
children
)
set_element_types
.
push_back
(
sample_block
.
getByName
(
arg
->
getColumnName
()).
type
);
}
else
{
DataTypePtr
left_type
=
sample_block
.
getByName
(
left_arg
->
getColumnName
()).
type
;
set_element_types
.
push_back
(
left_type
);
}
if
(
auto
tuple_type
=
typeid_cast
<
const
DataTypeTuple
*>
(
type
.
get
()))
return
1
+
(
tuple_type
->
getElements
().
empty
()
?
0
:
getTupleDepth
(
tuple_type
->
getElements
().
at
(
0
)));
/// The case `x in (1, 2)` distinguishes from the case `x in 1` (also `x in (1)`).
bool
single_value
=
false
;
ASTPtr
elements_ast
=
arg
;
return
0
;
};
if
(
ASTFunction
*
set_func
=
typeid_cast
<
ASTFunction
*>
(
arg
.
get
()))
auto
getTupleDepthFromAst
=
[
&
getTupleDepth
](
const
ASTPtr
&
node
)
->
size_t
{
if
(
set_func
->
name
==
"tuple"
)
size_t
depth
=
0
;
ASTPtr
element
=
node
;
auto
ast_function
=
typeid_cast
<
const
ASTFunction
*>
(
node
.
get
());
if
(
ast_function
&&
ast_function
->
name
==
"tuple"
&&
!
ast_function
->
arguments
->
children
.
empty
())
{
if
(
set_func
->
arguments
->
children
.
empty
())
{
/// Empty set.
elements_ast
=
set_func
->
arguments
;
}
else
{
/// Distinguish the case `(x, y) in ((1, 2), (3, 4))` from the case `(x, y) in (1, 2)`.
ASTFunction
*
any_element
=
typeid_cast
<
ASTFunction
*>
(
set_func
->
arguments
->
children
.
at
(
0
).
get
());
if
(
set_element_types
.
size
()
>=
2
&&
(
!
any_element
||
any_element
->
name
!=
"tuple"
))
single_value
=
true
;
else
elements_ast
=
set_func
->
arguments
;
}
++
depth
;
element
=
ast_function
->
arguments
->
children
.
at
(
0
);
}
else
{
if
(
set_element_types
.
size
()
>=
2
)
throw
Exception
(
"Incorrect type of 2nd argument for function "
+
node
->
name
+
". Must be subquery or set of "
+
toString
(
set_element_types
.
size
())
+
"-element tuples."
,
ErrorCodes
::
ILLEGAL_TYPE_OF_ARGUMENT
);
single_value
=
true
;
}
}
else
if
(
typeid_cast
<
ASTLiteral
*>
(
arg
.
get
()))
std
::
pair
<
Field
,
DataTypePtr
>
value_raw
=
evaluateConstantExpression
(
element
,
context
);
return
depth
+
getTupleDepth
(
value_raw
.
second
);
};
size_t
left_tuple_depth
=
getTupleDepth
(
left_arg_type
);
size_t
right_tuple_depth
=
getTupleDepthFromAst
(
right_arg
);
DataTypes
set_element_types
;
ASTPtr
elements_ast
=
nullptr
;
if
(
left_tuple_depth
>
0
)
{
single_value
=
true
;
auto
left_tuple_type
=
static_cast
<
const
DataTypeTuple
*>
(
left_arg_type
.
get
());
set_element_types
=
left_tuple_type
->
getElements
();
}
else
{
throw
Exception
(
"Incorrect type of 2nd argument for function "
+
node
->
name
+
". Must be subquery or set of values."
,
ErrorCodes
::
ILLEGAL_TYPE_OF_ARGUMENT
);
}
set_element_types
.
push_back
(
left_arg_type
);
if
(
single_value
)
/// 1 in 1; (1, 2) in (1, 2); identity(tuple(tuple(tuple(1)))) in tuple(tuple(tuple(1))); etc.
if
(
left_tuple_depth
==
right_tuple_depth
)
{
ASTPtr
exp_list
=
std
::
make_shared
<
ASTExpressionList
>
();
exp_list
->
children
.
push_back
(
elements_ast
);
exp_list
->
children
.
push_back
(
right_arg
);
elements_ast
=
exp_list
;
}
/// 1 in (1, 2); (1, 2) in ((1, 2), (3, 4)); etc.
else
if
(
left_tuple_depth
+
1
==
right_tuple_depth
)
{
ASTFunction
*
set_func
=
typeid_cast
<
ASTFunction
*>
(
right_arg
.
get
());
if
(
!
set_func
||
set_func
->
name
!=
"tuple"
)
throw
Exception
(
"Incorrect type of 2nd argument for function "
+
node
->
name
+
". Must be subquery or set of elements with type "
+
left_arg_type
->
getName
()
+
"."
,
ErrorCodes
::
ILLEGAL_TYPE_OF_ARGUMENT
);
elements_ast
=
set_func
->
arguments
;
}
else
throw
Exception
(
"Invalid types for IN function: "
+
left_arg_type
->
getName
()
+
" and "
+
right_arg_type
->
getName
()
+
"."
,
ErrorCodes
::
ILLEGAL_TYPE_OF_ARGUMENT
);
SetPtr
set
=
std
::
make_shared
<
Set
>
(
SizeLimits
(
settings
.
max_rows_in_set
,
settings
.
max_bytes_in_set
,
settings
.
set_overflow_mode
));
set
->
createFromAST
(
set_element_types
,
elements_ast
,
context
,
create_ordered_set
);
prepared_sets
[
arg
.
get
()]
=
std
::
move
(
set
);
prepared_sets
[
right_
arg
.
get
()]
=
std
::
move
(
set
);
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录