Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
2dot5
ClickHouse
提交
43d48a21
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,发现更多精彩内容 >>
未验证
提交
43d48a21
编写于
4月 18, 2020
作者:
A
alexey-milovidov
提交者:
GitHub
4月 18, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #10318 from ClickHouse/least-greatest-generic
Added generic variants for functions 'least' and 'greatest'.
上级
72dd453c
4f245dc2
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
214 addition
and
3 deletion
+214
-3
src/Columns/IColumn.h
src/Columns/IColumn.h
+1
-1
src/Functions/LeastGreatestGeneric.h
src/Functions/LeastGreatestGeneric.h
+140
-0
src/Functions/greatest.cpp
src/Functions/greatest.cpp
+3
-1
src/Functions/least.cpp
src/Functions/least.cpp
+3
-1
tests/performance/least_greatest_hits.xml
tests/performance/least_greatest_hits.xml
+9
-0
tests/queries/0_stateless/01246_least_greatest_generic.reference
...ueries/0_stateless/01246_least_greatest_generic.reference
+22
-0
tests/queries/0_stateless/01246_least_greatest_generic.sql
tests/queries/0_stateless/01246_least_greatest_generic.sql
+36
-0
未找到文件。
src/Columns/IColumn.h
浏览文件 @
43d48a21
...
...
@@ -44,7 +44,7 @@ public:
/// Name of a Column kind, without parameters (example: FixedString, Array).
virtual
const
char
*
getFamilyName
()
const
=
0
;
/** If column isn't constant, returns
nullptr (or itself)
.
/** If column isn't constant, returns
itself
.
* If column is constant, transforms constant to full column (if column type allows such transform) and return it.
*/
virtual
Ptr
convertToFullColumnIfConst
()
const
{
return
getPtr
();
}
...
...
src/Functions/LeastGreatestGeneric.h
0 → 100644
浏览文件 @
43d48a21
#pragma once
#include <DataTypes/getLeastSupertype.h>
#include <DataTypes/NumberTraits.h>
#include <Interpreters/castColumn.h>
#include <Columns/ColumnsNumber.h>
#include <Functions/IFunctionImpl.h>
#include <Functions/FunctionFactory.h>
#include <ext/map.h>
namespace
DB
{
namespace
ErrorCodes
{
extern
const
int
NUMBER_OF_ARGUMENTS_DOESNT_MATCH
;
}
enum
class
LeastGreatest
{
Least
,
Greatest
};
template
<
LeastGreatest
kind
>
class
FunctionLeastGreatestGeneric
:
public
IFunction
{
public:
static
constexpr
auto
name
=
kind
==
LeastGreatest
::
Least
?
"least"
:
"greatest"
;
static
FunctionPtr
create
(
const
Context
&
)
{
return
std
::
make_shared
<
FunctionLeastGreatestGeneric
<
kind
>>
();
}
private:
String
getName
()
const
override
{
return
name
;
}
size_t
getNumberOfArguments
()
const
override
{
return
0
;
}
bool
isVariadic
()
const
override
{
return
true
;
}
bool
useDefaultImplementationForConstants
()
const
override
{
return
true
;
}
DataTypePtr
getReturnTypeImpl
(
const
DataTypes
&
types
)
const
override
{
if
(
types
.
empty
())
throw
Exception
(
"Function "
+
getName
()
+
" cannot be called without arguments"
,
ErrorCodes
::
NUMBER_OF_ARGUMENTS_DOESNT_MATCH
);
return
getLeastSupertype
(
types
);
}
void
executeImpl
(
Block
&
block
,
const
ColumnNumbers
&
arguments
,
size_t
result
,
size_t
input_rows_count
)
override
{
size_t
num_arguments
=
arguments
.
size
();
if
(
1
==
num_arguments
)
{
block
.
getByPosition
(
result
).
column
=
block
.
getByPosition
(
arguments
[
0
]).
column
;
return
;
}
auto
result_type
=
block
.
getByPosition
(
result
).
type
;
Columns
converted_columns
(
num_arguments
);
for
(
size_t
arg
=
0
;
arg
<
num_arguments
;
++
arg
)
converted_columns
[
arg
]
=
castColumn
(
block
.
getByPosition
(
arguments
[
arg
]),
result_type
)
->
convertToFullColumnIfConst
();
auto
result_column
=
result_type
->
createColumn
();
result_column
->
reserve
(
input_rows_count
);
for
(
size_t
row_num
=
0
;
row_num
<
input_rows_count
;
++
row_num
)
{
size_t
best_arg
=
0
;
for
(
size_t
arg
=
1
;
arg
<
num_arguments
;
++
arg
)
{
auto
cmp_result
=
converted_columns
[
arg
]
->
compareAt
(
row_num
,
row_num
,
*
converted_columns
[
best_arg
],
1
);
if
constexpr
(
kind
==
LeastGreatest
::
Least
)
{
if
(
cmp_result
<
0
)
best_arg
=
arg
;
}
else
{
if
(
cmp_result
>
0
)
best_arg
=
arg
;
}
}
result_column
->
insertFrom
(
*
converted_columns
[
best_arg
],
row_num
);
}
block
.
getByPosition
(
result
).
column
=
std
::
move
(
result_column
);
}
};
template
<
LeastGreatest
kind
,
typename
SpecializedFunction
>
class
LeastGreatestOverloadResolver
:
public
IFunctionOverloadResolverImpl
{
public:
static
constexpr
auto
name
=
kind
==
LeastGreatest
::
Least
?
"least"
:
"greatest"
;
static
FunctionOverloadResolverImplPtr
create
(
const
Context
&
context
)
{
return
std
::
make_unique
<
LeastGreatestOverloadResolver
<
kind
,
SpecializedFunction
>>
(
context
);
}
explicit
LeastGreatestOverloadResolver
(
const
Context
&
context_
)
:
context
(
context_
)
{}
String
getName
()
const
override
{
return
name
;
}
size_t
getNumberOfArguments
()
const
override
{
return
0
;
}
bool
isVariadic
()
const
override
{
return
true
;
}
FunctionBaseImplPtr
build
(
const
ColumnsWithTypeAndName
&
arguments
,
const
DataTypePtr
&
return_type
)
const
override
{
DataTypes
argument_types
;
/// More efficient specialization for two numeric arguments.
if
(
arguments
.
size
()
==
2
&&
isNumber
(
arguments
[
0
].
type
)
&&
isNumber
(
arguments
[
1
].
type
))
return
std
::
make_unique
<
DefaultFunction
>
(
SpecializedFunction
::
create
(
context
),
argument_types
,
return_type
);
return
std
::
make_unique
<
DefaultFunction
>
(
FunctionLeastGreatestGeneric
<
kind
>::
create
(
context
),
argument_types
,
return_type
);
}
DataTypePtr
getReturnType
(
const
DataTypes
&
types
)
const
override
{
if
(
types
.
empty
())
throw
Exception
(
"Function "
+
getName
()
+
" cannot be called without arguments"
,
ErrorCodes
::
NUMBER_OF_ARGUMENTS_DOESNT_MATCH
);
if
(
types
.
size
()
==
2
&&
isNumber
(
types
[
0
])
&&
isNumber
(
types
[
1
]))
return
SpecializedFunction
::
create
(
context
)
->
getReturnTypeImpl
(
types
);
return
getLeastSupertype
(
types
);
}
private:
const
Context
&
context
;
};
}
src/Functions/greatest.cpp
浏览文件 @
43d48a21
#include <Functions/FunctionFactory.h>
#include <Functions/FunctionBinaryArithmetic.h>
#include <Core/AccurateComparison.h>
#include <Functions/LeastGreatestGeneric.h>
namespace
DB
{
...
...
@@ -57,7 +59,7 @@ using FunctionGreatest = FunctionBinaryArithmetic<GreatestImpl, NameGreatest>;
void
registerFunctionGreatest
(
FunctionFactory
&
factory
)
{
factory
.
registerFunction
<
FunctionGreatest
>
(
FunctionFactory
::
CaseInsensitive
);
factory
.
registerFunction
<
LeastGreatestOverloadResolver
<
LeastGreatest
::
Greatest
,
FunctionGreatest
>
>
(
FunctionFactory
::
CaseInsensitive
);
}
}
src/Functions/least.cpp
浏览文件 @
43d48a21
#include <Functions/FunctionFactory.h>
#include <Functions/FunctionBinaryArithmetic.h>
#include <Core/AccurateComparison.h>
#include <Functions/LeastGreatestGeneric.h>
namespace
DB
{
...
...
@@ -57,7 +59,7 @@ using FunctionLeast = FunctionBinaryArithmetic<LeastImpl, NameLeast>;
void
registerFunctionLeast
(
FunctionFactory
&
factory
)
{
factory
.
registerFunction
<
FunctionLeast
>
(
FunctionFactory
::
CaseInsensitive
);
factory
.
registerFunction
<
LeastGreatestOverloadResolver
<
LeastGreatest
::
Least
,
FunctionLeast
>
>
(
FunctionFactory
::
CaseInsensitive
);
}
}
tests/performance/least_greatest_hits.xml
0 → 100644
浏览文件 @
43d48a21
<test>
<preconditions>
<table_exists>
test.hits
</table_exists>
</preconditions>
<query>
SELECT count() FROM test.hits WHERE NOT ignore(least(URL, Referer))
</query>
<query>
SELECT count() FROM test.hits WHERE NOT ignore(greatest(URL, Referer, Title))
</query>
<query>
SELECT count() FROM test.hits WHERE NOT ignore(greatest(ClientIP, RemoteIP))
</query>
</test>
tests/queries/0_stateless/01246_least_greatest_generic.reference
0 → 100644
浏览文件 @
43d48a21
hello
world
z
hello
world
1
\N
\N
nan
inf
-0
123
-1
4294967295
['world']
[[[]]]
[[[],[]]]
[]
[NULL]
[0]
[NULL]
tests/queries/0_stateless/01246_least_greatest_generic.sql
0 → 100644
浏览文件 @
43d48a21
SELECT
least
(
'hello'
,
'world'
);
SELECT
greatest
(
'hello'
,
'world'
);
SELECT
least
(
'hello'
,
'world'
,
''
);
SELECT
greatest
(
'hello'
,
'world'
,
'z'
);
SELECT
least
(
'hello'
);
SELECT
greatest
(
'world'
);
SELECT
least
(
1
,
inf
,
nan
);
SELECT
least
(
1
,
inf
,
nan
,
NULL
);
SELECT
greatest
(
1
,
inf
,
nan
,
NULL
);
SELECT
greatest
(
1
,
inf
,
nan
);
SELECT
greatest
(
1
,
inf
);
SELECT
least
(
0
.,
-
0
.);
SELECT
least
(
toNullable
(
123
),
456
);
-- This can be improved
SELECT
LEAST
(
-
1
,
18446744073709551615
);
-- { serverError 43 }
SELECT
LEAST
(
-
1
.,
18446744073709551615
);
-- { serverError 43 }
SELECT
LEAST
(
-
1
.,
18446744073709551615
.);
SELECT
greatest
(
-
1
,
1
,
4294967295
);
SELECT
greatest
([],
[
'hello'
],
[
'world'
]);
SELECT
least
([[[],
[]]],
[[[]]],
[[[]],
[[]]]);
SELECT
greatest
([[[],
[]]],
[[[]]],
[[[]],
[[]]]);
SELECT
least
([],
[
NULL
]);
SELECT
greatest
([],
[
NULL
]);
SELECT
LEAST
([
NULL
],
[
0
]);
SELECT
GREATEST
([
NULL
],
[
0
]);
SELECT
Greatest
();
-- { serverError 42 }
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录