Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
2dot5
ClickHouse
提交
a9becd36
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,发现更多精彩内容 >>
提交
a9becd36
编写于
6月 12, 2015
作者:
A
Alexey Milovidov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
dbms: allowed constant expressions in IN [#METR-2944].
上级
5b8008e2
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
54 addition
and
26 deletion
+54
-26
dbms/include/DB/Interpreters/Set.h
dbms/include/DB/Interpreters/Set.h
+1
-1
dbms/src/Interpreters/ExpressionAnalyzer.cpp
dbms/src/Interpreters/ExpressionAnalyzer.cpp
+1
-1
dbms/src/Interpreters/Set.cpp
dbms/src/Interpreters/Set.cpp
+52
-24
未找到文件。
dbms/include/DB/Interpreters/Set.h
浏览文件 @
a9becd36
...
...
@@ -283,7 +283,7 @@ public:
* node - это список значений: 1, 2, 3 или список tuple-ов: (1, 2), (3, 4), (5, 6).
* create_ordered_set - создавать ли вектор упорядоченных элементов. Нужен для работы индекса
*/
void
createFromAST
(
DataTypes
&
types
,
ASTPtr
node
,
bool
create_ordered_set
);
void
createFromAST
(
DataTypes
&
types
,
ASTPtr
node
,
const
Context
&
context
,
bool
create_ordered_set
);
// Возвращает false, если превышено какое-нибудь ограничение, и больше не нужно вставлять.
bool
insertFromBlock
(
const
Block
&
block
,
bool
create_ordered_set
=
false
);
...
...
dbms/src/Interpreters/ExpressionAnalyzer.cpp
浏览文件 @
a9becd36
...
...
@@ -954,7 +954,7 @@ void ExpressionAnalyzer::makeExplicitSet(ASTFunction * node, const Block & sampl
ASTPtr
ast_set_ptr
=
ast_set
;
ast_set
->
set
=
new
Set
(
settings
.
limits
);
ast_set
->
is_explicit
=
true
;
ast_set
->
set
->
createFromAST
(
set_element_types
,
elements_ast
,
create_ordered_set
);
ast_set
->
set
->
createFromAST
(
set_element_types
,
elements_ast
,
c
ontext
,
c
reate_ordered_set
);
arg
=
ast_set_ptr
;
}
...
...
dbms/src/Interpreters/Set.cpp
浏览文件 @
a9becd36
...
...
@@ -10,8 +10,12 @@
#include <DB/Parsers/ASTExpressionList.h>
#include <DB/Parsers/ASTFunction.h>
#include <DB/Parsers/ASTLiteral.h>
#include <DB/Parsers/formatAST.h>
#include <DB/Interpreters/Set.h>
#include <DB/Interpreters/ExpressionAnalyzer.h>
#include <DB/Interpreters/ExpressionActions.h>
#include <DB/DataTypes/DataTypeArray.h>
#include <DB/DataTypes/DataTypesNumberFixed.h>
#include <DB/DataTypes/DataTypeString.h>
...
...
@@ -259,10 +263,10 @@ static Field convertToType(const Field & src, const IDataType & type)
if
(
is_uint8
||
is_uint16
||
is_uint32
||
is_uint64
)
{
if
(
src
.
getType
()
==
Field
::
Types
::
Int64
)
throw
Exception
(
"Type mismatch in IN section: "
+
type
.
getName
()
+
" at left, signed
literal
at right"
);
throw
Exception
(
"Type mismatch in IN section: "
+
type
.
getName
()
+
" at left, signed at right"
);
if
(
src
.
getType
()
==
Field
::
Types
::
Float64
)
throw
Exception
(
"Type mismatch in IN section: "
+
type
.
getName
()
+
" at left, floating point
literal
at right"
);
throw
Exception
(
"Type mismatch in IN section: "
+
type
.
getName
()
+
" at left, floating point at right"
);
if
(
src
.
getType
()
==
Field
::
Types
::
UInt64
)
{
...
...
@@ -276,12 +280,12 @@ static Field convertToType(const Field & src, const IDataType & type)
}
throw
Exception
(
"Type mismatch in IN section: "
+
type
.
getName
()
+
" at left, "
+
Field
::
Types
::
toString
(
src
.
getType
())
+
"
literal
at right"
);
+
Field
::
Types
::
toString
(
src
.
getType
())
+
" at right"
);
}
else
if
(
is_int8
||
is_int16
||
is_int32
||
is_int64
)
{
if
(
src
.
getType
()
==
Field
::
Types
::
Float64
)
throw
Exception
(
"Type mismatch in IN section: "
+
type
.
getName
()
+
" at left, floating point
literal
at right"
);
throw
Exception
(
"Type mismatch in IN section: "
+
type
.
getName
()
+
" at left, floating point at right"
);
if
(
src
.
getType
()
==
Field
::
Types
::
UInt64
)
{
...
...
@@ -308,7 +312,7 @@ static Field convertToType(const Field & src, const IDataType & type)
}
throw
Exception
(
"Type mismatch in IN section: "
+
type
.
getName
()
+
" at left, "
+
Field
::
Types
::
toString
(
src
.
getType
())
+
"
literal
at right"
);
+
Field
::
Types
::
toString
(
src
.
getType
())
+
" at right"
);
}
else
if
(
is_float32
||
is_float64
)
{
...
...
@@ -322,7 +326,7 @@ static Field convertToType(const Field & src, const IDataType & type)
return
src
;
throw
Exception
(
"Type mismatch in IN section: "
+
type
.
getName
()
+
" at left, "
+
Field
::
Types
::
toString
(
src
.
getType
())
+
"
literal
at right"
);
+
Field
::
Types
::
toString
(
src
.
getType
())
+
" at right"
);
}
}
else
...
...
@@ -337,22 +341,54 @@ static Field convertToType(const Field & src, const IDataType & type)
||
(
src
.
getType
()
==
Field
::
Types
::
Array
&&
!
typeid_cast
<
const
DataTypeArray
*>
(
&
type
)))
throw
Exception
(
"Type mismatch in IN section: "
+
type
.
getName
()
+
" at left, "
+
Field
::
Types
::
toString
(
src
.
getType
())
+
"
literal
at right"
);
+
Field
::
Types
::
toString
(
src
.
getType
())
+
" at right"
);
}
return
src
;
}
void
Set
::
createFromAST
(
DataTypes
&
types
,
ASTPtr
node
,
bool
create_ordered_set
)
/** Выполнить константное выражение (для элемента множества в IN). Весьма неоптимально. */
static
Field
evaluateConstantExpression
(
ASTPtr
&
node
,
const
Context
&
context
)
{
ExpressionActionsPtr
expr_for_constant_folding
=
ExpressionAnalyzer
(
node
,
context
,
NamesAndTypesList
{{
"_dummy"
,
new
DataTypeUInt8
}}).
getConstActions
();
/// В блоке должен быть хотя бы один столбец, чтобы у него было известно число строк.
Block
block_with_constants
{{
new
ColumnConstUInt8
(
1
,
0
),
new
DataTypeUInt8
,
"_dummy"
}};
expr_for_constant_folding
->
execute
(
block_with_constants
);
if
(
!
block_with_constants
||
block_with_constants
.
rows
()
==
0
)
throw
Exception
(
"Logical error: empty block after evaluation constant expression for IN"
,
ErrorCodes
::
LOGICAL_ERROR
);
String
name
=
node
->
getColumnName
();
if
(
!
block_with_constants
.
has
(
name
))
throw
Exception
(
"Element of set in IN is not a constant expression: "
+
name
,
ErrorCodes
::
BAD_ARGUMENTS
);
const
IColumn
&
result_column
=
*
block_with_constants
.
getByName
(
name
).
column
;
if
(
!
result_column
.
isConst
())
throw
Exception
(
"Element of set in IN is not a constant expression: "
+
name
,
ErrorCodes
::
BAD_ARGUMENTS
);
return
result_column
[
0
];
}
static
Field
extractValueFromNode
(
ASTPtr
&
node
,
const
IDataType
&
type
,
const
Context
&
context
)
{
/** NOTE:
* На данный момент в секции IN не поддерживаются выражения (вызовы функций), кроме кортежей.
* То есть, например, не поддерживаются массивы. А по хорошему, хотелось бы поддерживать.
* Для этого можно сделать constant folding с помощью ExpressionAnalyzer/ExpressionActions.
* Но при этом, конечно же, не забыть про производительность работы с крупными множествами.
*/
if
(
ASTLiteral
*
lit
=
typeid_cast
<
ASTLiteral
*>
(
node
.
get
()))
return
convertToType
(
lit
->
value
,
type
);
else
if
(
typeid_cast
<
ASTFunction
*>
(
node
.
get
()))
return
convertToType
(
evaluateConstantExpression
(
node
,
context
),
type
);
else
throw
Exception
(
"Incorrect element of set. Must be literal or constant expression."
,
ErrorCodes
::
INCORRECT_ELEMENT_OF_SET
);
}
void
Set
::
createFromAST
(
DataTypes
&
types
,
ASTPtr
node
,
const
Context
&
context
,
bool
create_ordered_set
)
{
data_types
=
types
;
/// Засунем множество в блок.
...
...
@@ -372,10 +408,7 @@ void Set::createFromAST(DataTypes & types, ASTPtr node, bool create_ordered_set)
{
if
(
data_types
.
size
()
==
1
)
{
if
(
ASTLiteral
*
lit
=
typeid_cast
<
ASTLiteral
*>
(
&**
it
))
block
.
getByPosition
(
0
).
column
->
insert
(
convertToType
(
lit
->
value
,
*
data_types
[
0
]));
else
throw
Exception
(
"Incorrect element of set. Must be literal."
,
ErrorCodes
::
INCORRECT_ELEMENT_OF_SET
);
block
.
getByPosition
(
0
).
column
->
insert
(
extractValueFromNode
(
*
it
,
*
data_types
[
0
],
context
));
}
else
if
(
ASTFunction
*
func
=
typeid_cast
<
ASTFunction
*>
(
&**
it
))
{
...
...
@@ -388,16 +421,11 @@ void Set::createFromAST(DataTypes & types, ASTPtr node, bool create_ordered_set)
for
(
size_t
j
=
0
;
j
<
tuple_size
;
++
j
)
{
if
(
ASTLiteral
*
lit
=
typeid_cast
<
ASTLiteral
*>
(
&*
func
->
arguments
->
children
[
j
]))
block
.
getByPosition
(
j
).
column
->
insert
(
convertToType
(
lit
->
value
,
*
data_types
[
j
]));
else
throw
Exception
(
"Incorrect element of tuple in set. Must be literal."
,
ErrorCodes
::
INCORRECT_ELEMENT_OF_SET
);
block
.
getByPosition
(
j
).
column
->
insert
(
extractValueFromNode
(
func
->
arguments
->
children
[
j
],
*
data_types
[
j
],
context
));
}
}
else
throw
Exception
(
"Incorrect element of set"
,
ErrorCodes
::
INCORRECT_ELEMENT_OF_SET
);
/// NOTE: Потом можно реализовать возможность задавать константные выражения в множествах.
}
if
(
create_ordered_set
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录