Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
2dot5
ClickHouse
提交
b8d464aa
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,发现更多精彩内容 >>
提交
b8d464aa
编写于
11月 08, 2019
作者:
C
chertus
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
new consistent ANY JOIN (LEFT, INNER, RIGHT)
上级
2cafe933
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
212 addition
and
96 deletion
+212
-96
dbms/src/Interpreters/Join.cpp
dbms/src/Interpreters/Join.cpp
+86
-30
dbms/src/Interpreters/Join.h
dbms/src/Interpreters/Join.h
+20
-9
dbms/src/Interpreters/SyntaxAnalyzer.cpp
dbms/src/Interpreters/SyntaxAnalyzer.cpp
+8
-9
dbms/src/Interpreters/joinDispatch.h
dbms/src/Interpreters/joinDispatch.h
+24
-45
dbms/src/Parsers/ASTTablesInSelectQuery.cpp
dbms/src/Parsers/ASTTablesInSelectQuery.cpp
+1
-0
dbms/src/Parsers/ASTTablesInSelectQuery.h
dbms/src/Parsers/ASTTablesInSelectQuery.h
+2
-1
dbms/src/Storages/StorageJoin.cpp
dbms/src/Storages/StorageJoin.cpp
+7
-2
dbms/tests/queries/0_stateless/01031_new_any_join.reference
dbms/tests/queries/0_stateless/01031_new_any_join.reference
+32
-0
dbms/tests/queries/0_stateless/01031_new_any_join.sql
dbms/tests/queries/0_stateless/01031_new_any_join.sql
+32
-0
未找到文件。
dbms/src/Interpreters/Join.cpp
浏览文件 @
b8d464aa
...
...
@@ -367,7 +367,7 @@ namespace
};
template
<
typename
Map
,
typename
KeyGetter
>
struct
Inserter
<
ASTTableJoin
::
Strictness
::
Any
,
Map
,
KeyGetter
>
struct
Inserter
<
ASTTableJoin
::
Strictness
::
Right
Any
,
Map
,
KeyGetter
>
{
static
ALWAYS_INLINE
void
insert
(
const
Join
&
join
,
Map
&
map
,
KeyGetter
&
key_getter
,
Block
*
stored_block
,
size_t
i
,
Arena
&
pool
)
{
...
...
@@ -427,7 +427,16 @@ namespace
if
(
has_null_map
&&
(
*
null_map
)[
i
])
continue
;
if
constexpr
(
STRICTNESS
==
ASTTableJoin
::
Strictness
::
Asof
)
if
constexpr
(
STRICTNESS
==
ASTTableJoin
::
Strictness
::
Any
)
{
constexpr
bool
mapped_one
=
std
::
is_same_v
<
typename
Map
::
mapped_type
,
JoinStuff
::
MappedOne
>
||
std
::
is_same_v
<
typename
Map
::
mapped_type
,
JoinStuff
::
MappedOneFlagged
>
;
if
constexpr
(
mapped_one
)
Inserter
<
ASTTableJoin
::
Strictness
::
RightAny
,
Map
,
KeyGetter
>::
insert
(
join
,
map
,
key_getter
,
stored_block
,
i
,
pool
);
else
Inserter
<
ASTTableJoin
::
Strictness
::
All
,
Map
,
KeyGetter
>::
insert
(
join
,
map
,
key_getter
,
stored_block
,
i
,
pool
);
}
else
if
constexpr
(
STRICTNESS
==
ASTTableJoin
::
Strictness
::
Asof
)
Inserter
<
STRICTNESS
,
Map
,
KeyGetter
>::
insert
(
join
,
map
,
key_getter
,
stored_block
,
i
,
pool
,
asof_column
);
else
Inserter
<
STRICTNESS
,
Map
,
KeyGetter
>::
insert
(
join
,
map
,
key_getter
,
stored_block
,
i
,
pool
);
...
...
@@ -690,18 +699,25 @@ void addNotFoundRow(AddedColumns & added [[maybe_unused]], IColumn::Offset & cur
/// Joins right table columns which indexes are present in right_indexes using specified map.
/// Makes filter (1 if row presented in right table) and returns offsets to replicate (for ALL JOINS).
template
<
ASTTableJoin
::
Strictness
STRICTNESS
,
bool
_add_missing
,
typename
KeyGetter
,
typename
Map
,
bool
_has_null_map
>
template
<
ASTTableJoin
::
Kind
KIND
,
ASTTableJoin
::
Strictness
STRICTNESS
,
typename
KeyGetter
,
typename
Map
,
bool
_has_null_map
>
void
NO_INLINE
joinRightColumns
(
const
Map
&
map
,
AddedColumns
&
added_columns
)
{
constexpr
bool
is_any_join
=
STRICTNESS
==
ASTTableJoin
::
Strictness
::
Any
;
constexpr
bool
is_all_join
=
STRICTNESS
==
ASTTableJoin
::
Strictness
::
All
;
constexpr
bool
is_asof_join
=
STRICTNESS
==
ASTTableJoin
::
Strictness
::
Asof
;
constexpr
bool
left_or_full
=
static_in_v
<
KIND
,
ASTTableJoin
::
Kind
::
Left
,
ASTTableJoin
::
Kind
::
Full
>
;
constexpr
bool
right
=
KIND
==
ASTTableJoin
::
Kind
::
Right
;
constexpr
bool
_add_missing
=
left_or_full
;
constexpr
bool
need_replication
=
is_all_join
||
(
is_any_join
&&
right
);
size_t
rows
=
added_columns
.
rows_to_add
;
if
constexpr
(
STRICTNESS
==
ASTTableJoin
::
Strictness
::
All
)
added_columns
.
offsets_to_replicate
=
std
::
make_unique
<
IColumn
::
Offsets
>
(
rows
);
IColumn
::
Filter
&
filter
=
added_columns
.
filter
;
Arena
pool
;
const
IColumn
*
asof_column
[[
maybe_unused
]]
=
nullptr
;
if
constexpr
(
STRICTNESS
==
ASTTableJoin
::
Strictness
::
Asof
)
if
constexpr
(
is_asof_join
)
asof_column
=
extractAsofColumn
(
added_columns
.
key_columns
);
auto
key_getter
=
createKeyGetter
<
KeyGetter
,
STRICTNESS
>
(
added_columns
.
key_columns
,
added_columns
.
key_sizes
);
...
...
@@ -721,13 +737,13 @@ void NO_INLINE joinRightColumns(const Map & map, AddedColumns & added_columns)
if
(
find_result
.
isFound
())
{
auto
&
mapped
=
find_result
.
getMapped
();
filter
[
i
]
=
1
;
if
constexpr
(
STRICTNESS
==
ASTTableJoin
::
Strictness
::
Asof
)
if
constexpr
(
is_asof_join
)
{
const
Join
&
join
=
added_columns
.
join
;
if
(
const
RowRef
*
found
=
mapped
.
findAsof
(
join
.
getAsofType
(),
join
.
getAsofInequality
(),
asof_column
,
i
))
{
filter
[
i
]
=
1
;
mapped
.
setUsed
();
added_columns
.
appendFromBlock
(
*
found
->
block
,
found
->
row_num
);
}
...
...
@@ -737,13 +753,37 @@ void NO_INLINE joinRightColumns(const Map & map, AddedColumns & added_columns)
addNotFoundRow
<
_add_missing
>
(
added_columns
,
current_offset
);
}
}
else
if
constexpr
(
STRICTNESS
==
ASTTableJoin
::
Strictness
::
All
)
else
if
constexpr
(
is_all_join
)
{
filter
[
i
]
=
1
;
mapped
.
setUsed
();
addFoundRowAll
<
Map
>
(
mapped
,
added_columns
,
current_offset
);
}
else
else
if
constexpr
(
is_any_join
&&
right
)
{
/// Use first appered left key + it needs left columns replication
if
(
mapped
.
setUsedOnce
())
{
filter
[
i
]
=
1
;
addFoundRowAll
<
Map
>
(
mapped
,
added_columns
,
current_offset
);
}
}
else
if
constexpr
(
is_any_join
&&
KIND
==
ASTTableJoin
::
Kind
::
Inner
)
{
/// Use first appered left key only
if
(
mapped
.
setUsedOnce
())
{
filter
[
i
]
=
1
;
added_columns
.
appendFromBlock
(
*
mapped
.
block
,
mapped
.
row_num
);
}
}
else
if
constexpr
(
is_any_join
&&
KIND
==
ASTTableJoin
::
Kind
::
Full
)
{
/// TODO
}
else
/// ANY LEFT + old ANY (RightAny)
{
filter
[
i
]
=
1
;
mapped
.
setUsed
();
added_columns
.
appendFromBlock
(
*
mapped
.
block
,
mapped
.
row_num
);
}
...
...
@@ -752,7 +792,7 @@ void NO_INLINE joinRightColumns(const Map & map, AddedColumns & added_columns)
addNotFoundRow
<
_add_missing
>
(
added_columns
,
current_offset
);
}
if
constexpr
(
STRICTNESS
==
ASTTableJoin
::
Strictness
::
All
)
if
constexpr
(
need_replication
)
(
*
added_columns
.
offsets_to_replicate
)[
i
]
=
current_offset
;
}
...
...
@@ -762,12 +802,10 @@ void NO_INLINE joinRightColumns(const Map & map, AddedColumns & added_columns)
template
<
ASTTableJoin
::
Kind
KIND
,
ASTTableJoin
::
Strictness
STRICTNESS
,
typename
KeyGetter
,
typename
Map
>
void
joinRightColumnsSwitchNullability
(
const
Map
&
map
,
AddedColumns
&
added_columns
)
{
constexpr
bool
left_or_full
=
static_in_v
<
KIND
,
ASTTableJoin
::
Kind
::
Left
,
ASTTableJoin
::
Kind
::
Full
>
;
if
(
added_columns
.
null_map
)
joinRightColumns
<
STRICTNESS
,
left_or_full
,
KeyGetter
,
Map
,
true
>
(
map
,
added_columns
);
joinRightColumns
<
KIND
,
STRICTNESS
,
KeyGetter
,
Map
,
true
>
(
map
,
added_columns
);
else
joinRightColumns
<
STRICTNESS
,
left_or_full
,
KeyGetter
,
Map
,
false
>
(
map
,
added_columns
);
joinRightColumns
<
KIND
,
STRICTNESS
,
KeyGetter
,
Map
,
false
>
(
map
,
added_columns
);
}
template
<
ASTTableJoin
::
Kind
KIND
,
ASTTableJoin
::
Strictness
STRICTNESS
,
typename
Maps
>
...
...
@@ -799,6 +837,16 @@ void Join::joinBlockImpl(
const
Block
&
block_with_columns_to_add
,
const
Maps
&
maps_
)
const
{
constexpr
bool
is_any_join
=
STRICTNESS
==
ASTTableJoin
::
Strictness
::
Any
;
constexpr
bool
is_all_join
=
STRICTNESS
==
ASTTableJoin
::
Strictness
::
All
;
constexpr
bool
is_asof_join
=
STRICTNESS
==
ASTTableJoin
::
Strictness
::
Asof
;
constexpr
bool
right
=
KIND
==
ASTTableJoin
::
Kind
::
Right
;
constexpr
bool
inner_or_right
=
static_in_v
<
KIND
,
ASTTableJoin
::
Kind
::
Inner
,
ASTTableJoin
::
Kind
::
Right
>
;
constexpr
bool
right_or_full
=
static_in_v
<
KIND
,
ASTTableJoin
::
Kind
::
Right
,
ASTTableJoin
::
Kind
::
Full
>
;
constexpr
bool
need_filter
=
(
!
is_all_join
&&
inner_or_right
)
&&
!
(
is_any_join
&&
right
);
constexpr
bool
need_replication
=
is_all_join
||
(
is_any_join
&&
right
);
/// Rare case, when keys are constant. To avoid code bloat, simply materialize them.
Columns
materialized_columns
;
ColumnRawPtrs
key_columns
=
JoinCommon
::
temporaryMaterializeColumns
(
block
,
key_names_left
,
materialized_columns
);
...
...
@@ -813,7 +861,6 @@ void Join::joinBlockImpl(
* Because if they are constants, then in the "not joined" rows, they may have different values
* - default values, which can differ from the values of these constants.
*/
constexpr
bool
right_or_full
=
static_in_v
<
KIND
,
ASTTableJoin
::
Kind
::
Right
,
ASTTableJoin
::
Kind
::
Full
>
;
if
constexpr
(
right_or_full
)
{
materializeBlockInplace
(
block
);
...
...
@@ -828,25 +875,24 @@ void Join::joinBlockImpl(
* For ASOF, the last column is used as the ASOF column
*/
ColumnsWithTypeAndName
extras
;
if
constexpr
(
STRICTNESS
==
ASTTableJoin
::
Strictness
::
Asof
)
if
constexpr
(
is_asof_join
)
extras
.
push_back
(
right_table_keys
.
getByName
(
key_names_right
.
back
()));
AddedColumns
added_columns
(
sample_block_with_columns_to_add
,
block_with_columns_to_add
,
block
,
saved_block_sample
,
extras
,
*
this
,
key_columns
,
key_sizes
,
null_map
);
if
constexpr
(
need_replication
)
added_columns
.
offsets_to_replicate
=
std
::
make_unique
<
IColumn
::
Offsets
>
(
block
.
rows
());
switchJoinRightColumns
<
KIND
,
STRICTNESS
>
(
maps_
,
added_columns
,
type
);
IColumn
::
Filter
&
row_filter
=
added_columns
.
filter
;
for
(
size_t
i
=
0
;
i
<
added_columns
.
size
();
++
i
)
block
.
insert
(
added_columns
.
moveColumn
(
i
));
/// Filter & insert missing rows
constexpr
bool
is_all_join
=
STRICTNESS
==
ASTTableJoin
::
Strictness
::
All
;
constexpr
bool
inner_or_right
=
static_in_v
<
KIND
,
ASTTableJoin
::
Kind
::
Inner
,
ASTTableJoin
::
Kind
::
Right
>
;
std
::
vector
<
size_t
>
right_keys_to_replicate
[[
maybe_unused
]];
if
constexpr
(
!
is_all_join
&&
inner_or_right
)
if
constexpr
(
need_filter
)
{
/// If ANY INNER | RIGHT JOIN - filter all the columns except the new ones.
for
(
size_t
i
=
0
;
i
<
existing_columns
;
++
i
)
...
...
@@ -883,16 +929,14 @@ void Join::joinBlockImpl(
ColumnPtr
thin_column
=
filterWithBlanks
(
col
.
column
,
filter
);
block
.
insert
(
correctNullability
({
thin_column
,
col
.
type
,
right_key
.
name
},
is_nullable
,
null_map_filter
));
if
constexpr
(
is_all_joi
n
)
if
constexpr
(
need_replicatio
n
)
right_keys_to_replicate
.
push_back
(
block
.
getPositionByName
(
right_key
.
name
));
}
}
if
constexpr
(
is_all_joi
n
)
if
constexpr
(
need_replicatio
n
)
{
std
::
unique_ptr
<
IColumn
::
Offsets
>
&
offsets_to_replicate
=
added_columns
.
offsets_to_replicate
;
if
(
!
offsets_to_replicate
)
throw
Exception
(
"No data to filter columns"
,
ErrorCodes
::
LOGICAL_ERROR
);
/// If ALL ... JOIN - we replicate all the columns except the new ones.
for
(
size_t
i
=
0
;
i
<
existing_columns
;
++
i
)
...
...
@@ -982,7 +1026,7 @@ DataTypePtr Join::joinGetReturnType(const String & column_name) const
template
<
typename
Maps
>
void
Join
::
joinGetImpl
(
Block
&
block
,
const
String
&
column_name
,
const
Maps
&
maps_
)
const
{
joinBlockImpl
<
ASTTableJoin
::
Kind
::
Left
,
ASTTableJoin
::
Strictness
::
Any
>
(
joinBlockImpl
<
ASTTableJoin
::
Kind
::
Left
,
ASTTableJoin
::
Strictness
::
Right
Any
>
(
block
,
{
block
.
getByPosition
(
0
).
name
},
{
sample_block_with_columns_to_add
.
getByName
(
column_name
)},
maps_
);
}
...
...
@@ -999,9 +1043,10 @@ void Join::joinGet(Block & block, const String & column_name) const
checkTypeOfKey
(
block
,
right_table_keys
);
if
(
kind
==
ASTTableJoin
::
Kind
::
Left
&&
strictness
==
ASTTableJoin
::
Strictness
::
Any
)
if
((
strictness
==
ASTTableJoin
::
Strictness
::
Any
||
strictness
==
ASTTableJoin
::
Strictness
::
RightAny
)
&&
kind
==
ASTTableJoin
::
Kind
::
Left
)
{
joinGetImpl
(
block
,
column_name
,
std
::
get
<
Maps
Any
>
(
maps
));
joinGetImpl
(
block
,
column_name
,
std
::
get
<
Maps
One
>
(
maps
));
}
else
throw
Exception
(
"joinGet only supports StorageJoin of type Left Any"
,
ErrorCodes
::
LOGICAL_ERROR
);
...
...
@@ -1039,7 +1084,7 @@ template <ASTTableJoin::Strictness STRICTNESS, typename Mapped>
struct
AdderNonJoined
;
template
<
typename
Mapped
>
struct
AdderNonJoined
<
ASTTableJoin
::
Strictness
::
Any
,
Mapped
>
struct
AdderNonJoined
<
ASTTableJoin
::
Strictness
::
Right
Any
,
Mapped
>
{
static
void
add
(
const
Mapped
&
mapped
,
size_t
&
rows_added
,
MutableColumns
&
columns_right
)
{
...
...
@@ -1053,6 +1098,17 @@ struct AdderNonJoined<ASTTableJoin::Strictness::Any, Mapped>
}
};
template
<
typename
Mapped
>
struct
AdderNonJoined
<
ASTTableJoin
::
Strictness
::
Any
,
Mapped
>
{
static
void
add
(
const
Mapped
&
mapped
,
size_t
&
rows_added
,
MutableColumns
&
columns_right
)
{
constexpr
bool
mapped_one
=
std
::
is_same_v
<
Mapped
,
JoinStuff
::
MappedOne
>
||
std
::
is_same_v
<
Mapped
,
JoinStuff
::
MappedOneFlagged
>
;
if
constexpr
(
!
mapped_one
)
AdderNonJoined
<
ASTTableJoin
::
Strictness
::
All
,
Mapped
>::
add
(
mapped
,
rows_added
,
columns_right
);
}
};
template
<
typename
Mapped
>
struct
AdderNonJoined
<
ASTTableJoin
::
Strictness
::
All
,
Mapped
>
{
...
...
dbms/src/Interpreters/Join.h
浏览文件 @
b8d464aa
...
...
@@ -45,6 +45,16 @@ struct WithFlags<T, true> : T
mutable
std
::
atomic
<
bool
>
used
{};
void
setUsed
()
const
{
used
.
store
(
true
,
std
::
memory_order_relaxed
);
}
/// Could be set simultaneously from different threads.
bool
getUsed
()
const
{
return
used
;
}
bool
setUsedOnce
()
const
{
/// fast check to prevent heavy CAS with seq_cst order
if
(
used
.
load
(
std
::
memory_order_relaxed
))
return
false
;
bool
expected
=
false
;
return
used
.
compare_exchange_strong
(
expected
,
true
);
}
};
template
<
typename
T
>
...
...
@@ -55,13 +65,14 @@ struct WithFlags<T, false> : T
void
setUsed
()
const
{}
bool
getUsed
()
const
{
return
true
;
}
bool
setUsedOnce
()
const
{
return
true
;
}
};
using
Mapped
Any
=
WithFlags
<
RowRef
,
false
>
;
using
MappedAll
=
WithFlags
<
RowRefList
,
false
>
;
using
Mapped
AnyFull
=
WithFlags
<
RowRef
,
true
>
;
using
MappedAllF
ull
=
WithFlags
<
RowRefList
,
true
>
;
using
MappedAsof
=
WithFlags
<
AsofRowRefs
,
false
>
;
using
Mapped
One
=
WithFlags
<
RowRef
,
false
>
;
using
MappedAll
=
WithFlags
<
RowRefList
,
false
>
;
using
Mapped
OneFlagged
=
WithFlags
<
RowRef
,
true
>
;
using
MappedAllF
lagged
=
WithFlags
<
RowRefList
,
true
>
;
using
MappedAsof
=
WithFlags
<
AsofRowRefs
,
false
>
;
}
...
...
@@ -265,13 +276,13 @@ public:
}
};
using
Maps
Any
=
MapsTemplate
<
JoinStuff
::
MappedAny
>
;
using
Maps
One
=
MapsTemplate
<
JoinStuff
::
MappedOne
>
;
using
MapsAll
=
MapsTemplate
<
JoinStuff
::
MappedAll
>
;
using
Maps
AnyFull
=
MapsTemplate
<
JoinStuff
::
MappedAnyFull
>
;
using
MapsAllF
ull
=
MapsTemplate
<
JoinStuff
::
MappedAllFull
>
;
using
Maps
OneFlagged
=
MapsTemplate
<
JoinStuff
::
MappedOneFlagged
>
;
using
MapsAllF
lagged
=
MapsTemplate
<
JoinStuff
::
MappedAllFlagged
>
;
using
MapsAsof
=
MapsTemplate
<
JoinStuff
::
MappedAsof
>
;
using
MapsVariant
=
std
::
variant
<
Maps
Any
,
MapsAll
,
MapsAnyFull
,
MapsAllFull
,
MapsAsof
>
;
using
MapsVariant
=
std
::
variant
<
Maps
One
,
MapsAll
,
MapsOneFlagged
,
MapsAllFlagged
,
MapsAsof
>
;
private:
friend
class
NonJoinedBlockInputStream
;
...
...
dbms/src/Interpreters/SyntaxAnalyzer.cpp
浏览文件 @
b8d464aa
...
...
@@ -540,7 +540,7 @@ void getArrayJoinedColumns(ASTPtr & query, SyntaxAnalyzerResult & result, const
}
}
void
setJoinStrictness
(
ASTSelectQuery
&
select_query
,
JoinStrictness
join_default_strictness
,
ASTTableJoin
&
out_table_join
)
void
setJoinStrictness
(
ASTSelectQuery
&
select_query
,
JoinStrictness
join_default_strictness
,
bool
old_any
,
ASTTableJoin
&
out_table_join
)
{
const
ASTTablesInSelectQueryElement
*
node
=
select_query
.
join
();
if
(
!
node
)
...
...
@@ -560,6 +560,9 @@ void setJoinStrictness(ASTSelectQuery & select_query, JoinStrictness join_defaul
DB
::
ErrorCodes
::
EXPECTED_ALL_OR_ANY
);
}
if
(
old_any
&&
table_join
.
strictness
==
ASTTableJoin
::
Strictness
::
Any
)
table_join
.
strictness
=
ASTTableJoin
::
Strictness
::
RightAny
;
out_table_join
=
table_join
;
}
...
...
@@ -628,13 +631,8 @@ void checkJoin(const ASTTablesInSelectQueryElement * join)
const
auto
&
table_join
=
join
->
table_join
->
as
<
ASTTableJoin
&>
();
if
(
table_join
.
strictness
==
ASTTableJoin
::
Strictness
::
Any
)
if
(
table_join
.
kind
!=
ASTTableJoin
::
Kind
::
Left
)
throw
Exception
(
"Old ANY INNER|RIGHT|FULL JOINs are disabled by default. Their logic would be changed. "
"Old logic is many-to-one for all kinds of ANY JOINs. It's equil to apply distinct for right table keys. "
"Default bahaviour is reserved for many-to-one LEFT JOIN, one-to-many RIGHT JOIN and one-to-one INNER JOIN. "
"It would be equal to apply distinct for keys to right, left and both tables respectively. "
"Set any_join_distinct_right_table_keys=1 to enable old bahaviour."
,
ErrorCodes
::
NOT_IMPLEMENTED
);
if
(
table_join
.
kind
==
ASTTableJoin
::
Kind
::
Full
)
throw
Exception
(
"ANY FULL JOINs are not implemented."
,
ErrorCodes
::
NOT_IMPLEMENTED
);
}
std
::
vector
<
const
ASTFunction
*>
getAggregates
(
const
ASTPtr
&
query
)
...
...
@@ -958,7 +956,8 @@ SyntaxAnalyzerResultPtr SyntaxAnalyzer::analyze(
/// Push the predicate expression down to the subqueries.
result
.
rewrite_subqueries
=
PredicateExpressionsOptimizer
(
select_query
,
settings
,
context
).
optimize
();
setJoinStrictness
(
*
select_query
,
settings
.
join_default_strictness
,
result
.
analyzed_join
->
table_join
);
setJoinStrictness
(
*
select_query
,
settings
.
join_default_strictness
,
settings
.
any_join_distinct_right_table_keys
,
result
.
analyzed_join
->
table_join
);
collectJoinedColumns
(
*
result
.
analyzed_join
,
*
select_query
,
source_columns_set
,
result
.
aliases
);
}
...
...
dbms/src/Interpreters/joinDispatch.h
浏览文件 @
b8d464aa
...
...
@@ -12,54 +12,33 @@
namespace
DB
{
template
<
bool
fill_right
,
typename
ASTTableJoin
::
Strictness
>
struct
MapGetterImpl
;
template
<
>
struct
MapGetterImpl
<
false
,
ASTTableJoin
::
Strictness
::
Any
>
{
using
Map
=
Join
::
MapsAny
;
};
template
<
>
struct
MapGetterImpl
<
true
,
ASTTableJoin
::
Strictness
::
Any
>
{
using
Map
=
Join
::
MapsAnyFull
;
};
template
<
>
struct
MapGetterImpl
<
false
,
ASTTableJoin
::
Strictness
::
All
>
{
using
Map
=
Join
::
MapsAll
;
};
template
<
>
struct
MapGetterImpl
<
true
,
ASTTableJoin
::
Strictness
::
All
>
{
using
Map
=
Join
::
MapsAllFull
;
};
template
<
bool
fill_right
>
struct
MapGetterImpl
<
fill_right
,
ASTTableJoin
::
Strictness
::
Asof
>
template
<
ASTTableJoin
::
Kind
kind
,
typename
ASTTableJoin
::
Strictness
>
struct
MapGetter
;
template
<
>
struct
MapGetter
<
ASTTableJoin
::
Kind
::
Left
,
ASTTableJoin
::
Strictness
::
RightAny
>
{
using
Map
=
Join
::
MapsOne
;
};
template
<
>
struct
MapGetter
<
ASTTableJoin
::
Kind
::
Inner
,
ASTTableJoin
::
Strictness
::
RightAny
>
{
using
Map
=
Join
::
MapsOne
;
};
template
<
>
struct
MapGetter
<
ASTTableJoin
::
Kind
::
Right
,
ASTTableJoin
::
Strictness
::
RightAny
>
{
using
Map
=
Join
::
MapsOneFlagged
;
};
template
<
>
struct
MapGetter
<
ASTTableJoin
::
Kind
::
Full
,
ASTTableJoin
::
Strictness
::
RightAny
>
{
using
Map
=
Join
::
MapsOneFlagged
;
};
template
<
>
struct
MapGetter
<
ASTTableJoin
::
Kind
::
Left
,
ASTTableJoin
::
Strictness
::
Any
>
{
using
Map
=
Join
::
MapsOne
;
};
template
<
>
struct
MapGetter
<
ASTTableJoin
::
Kind
::
Inner
,
ASTTableJoin
::
Strictness
::
Any
>
{
using
Map
=
Join
::
MapsOneFlagged
;
};
template
<
>
struct
MapGetter
<
ASTTableJoin
::
Kind
::
Right
,
ASTTableJoin
::
Strictness
::
Any
>
{
using
Map
=
Join
::
MapsAllFlagged
;
};
template
<
>
struct
MapGetter
<
ASTTableJoin
::
Kind
::
Full
,
ASTTableJoin
::
Strictness
::
Any
>
{
using
Map
=
Join
::
MapsAllFlagged
;
};
template
<
>
struct
MapGetter
<
ASTTableJoin
::
Kind
::
Left
,
ASTTableJoin
::
Strictness
::
All
>
{
using
Map
=
Join
::
MapsAll
;
};
template
<
>
struct
MapGetter
<
ASTTableJoin
::
Kind
::
Inner
,
ASTTableJoin
::
Strictness
::
All
>
{
using
Map
=
Join
::
MapsAll
;
};
template
<
>
struct
MapGetter
<
ASTTableJoin
::
Kind
::
Right
,
ASTTableJoin
::
Strictness
::
All
>
{
using
Map
=
Join
::
MapsAllFlagged
;
};
template
<
>
struct
MapGetter
<
ASTTableJoin
::
Kind
::
Full
,
ASTTableJoin
::
Strictness
::
All
>
{
using
Map
=
Join
::
MapsAllFlagged
;
};
template
<
ASTTableJoin
::
Kind
kind
>
struct
MapGetter
<
kind
,
ASTTableJoin
::
Strictness
::
Asof
>
{
using
Map
=
Join
::
MapsAsof
;
};
template
<
ASTTableJoin
::
Kind
KIND
>
struct
KindTrait
{
// Affects the Adder trait so that when the right part is empty, adding a default value on the left
static
constexpr
bool
fill_left
=
static_in_v
<
KIND
,
ASTTableJoin
::
Kind
::
Left
,
ASTTableJoin
::
Kind
::
Full
>
;
// Affects the Map trait so that a `used` flag is attached to map slots in order to
// generate default values on the right when the left part is empty
static
constexpr
bool
fill_right
=
static_in_v
<
KIND
,
ASTTableJoin
::
Kind
::
Right
,
ASTTableJoin
::
Kind
::
Full
>
;
};
template
<
ASTTableJoin
::
Kind
kind
,
ASTTableJoin
::
Strictness
strictness
>
using
Map
=
typename
MapGetterImpl
<
KindTrait
<
kind
>::
fill_right
,
strictness
>::
Map
;
static
constexpr
std
::
array
<
ASTTableJoin
::
Strictness
,
3
>
STRICTNESSES
=
{
static
constexpr
std
::
array
<
ASTTableJoin
::
Strictness
,
4
>
STRICTNESSES
=
{
ASTTableJoin
::
Strictness
::
RightAny
,
ASTTableJoin
::
Strictness
::
Any
,
ASTTableJoin
::
Strictness
::
All
,
ASTTableJoin
::
Strictness
::
Asof
...
...
@@ -81,7 +60,7 @@ inline bool joinDispatchInit(ASTTableJoin::Kind kind, ASTTableJoin::Strictness s
constexpr
auto
j
=
ij
%
STRICTNESSES
.
size
();
if
(
kind
==
KINDS
[
i
]
&&
strictness
==
STRICTNESSES
[
j
])
{
maps
=
Map
<
KINDS
[
i
],
STRICTNESSES
[
j
]
>
();
maps
=
typename
MapGetter
<
KINDS
[
i
],
STRICTNESSES
[
j
]
>::
Map
();
return
true
;
}
return
false
;
...
...
@@ -103,7 +82,7 @@ inline bool joinDispatch(ASTTableJoin::Kind kind, ASTTableJoin::Strictness stric
func
(
std
::
integral_constant
<
ASTTableJoin
::
Kind
,
KINDS
[
i
]
>
(),
std
::
integral_constant
<
ASTTableJoin
::
Strictness
,
STRICTNESSES
[
j
]
>
(),
std
::
get
<
Map
<
KINDS
[
i
],
STRICTNESSES
[
j
]
>
>
(
maps
));
std
::
get
<
typename
MapGetter
<
KINDS
[
i
],
STRICTNESSES
[
j
]
>::
Map
>
(
maps
));
return
true
;
}
return
false
;
...
...
dbms/src/Parsers/ASTTablesInSelectQuery.cpp
浏览文件 @
b8d464aa
...
...
@@ -140,6 +140,7 @@ void ASTTableJoin::formatImplBeforeTable(const FormatSettings & settings, Format
{
case
Strictness
::
Unspecified
:
break
;
case
Strictness
::
RightAny
:
case
Strictness
::
Any
:
settings
.
ostr
<<
"ANY "
;
break
;
...
...
dbms/src/Parsers/ASTTablesInSelectQuery.h
浏览文件 @
b8d464aa
...
...
@@ -74,7 +74,8 @@ struct ASTTableJoin : public IAST
enum
class
Strictness
{
Unspecified
,
Any
,
/// If there are many suitable rows to join, use any from them (also known as unique JOIN).
RightAny
,
/// Right ANY. If there are many suitable rows in right table, use any from them to join.
Any
,
/// Semi Join with any value from filtering table. For LEFT JOIN with Any and RightAny are the same.
All
,
/// If there are many suitable rows to join, use all of them and replicate rows of "left" table (usual semantic of JOIN).
Asof
,
/// For the last JOIN column, pick the latest value
};
...
...
dbms/src/Storages/StorageJoin.cpp
浏览文件 @
b8d464aa
...
...
@@ -99,7 +99,7 @@ void registerStorageJoin(StorageFactory & factory)
const
String
strictness_str
=
Poco
::
toLower
(
*
opt_strictness_id
);
ASTTableJoin
::
Strictness
strictness
;
if
(
strictness_str
==
"any"
)
strictness
=
ASTTableJoin
::
Strictness
::
Any
;
strictness
=
ASTTableJoin
::
Strictness
::
Right
Any
;
else
if
(
strictness_str
==
"all"
)
strictness
=
ASTTableJoin
::
Strictness
::
All
;
else
...
...
@@ -329,7 +329,7 @@ private:
for
(;
it
!=
end
;
++
it
)
{
if
constexpr
(
STRICTNESS
==
ASTTableJoin
::
Strictness
::
Any
)
if
constexpr
(
STRICTNESS
==
ASTTableJoin
::
Strictness
::
Right
Any
)
{
for
(
size_t
j
=
0
;
j
<
columns
.
size
();
++
j
)
if
(
j
==
key_pos
)
...
...
@@ -338,6 +338,11 @@ private:
columns
[
j
]
->
insertFrom
(
*
it
->
getSecond
().
block
->
getByPosition
(
column_indices
[
j
]).
column
.
get
(),
it
->
getSecond
().
row_num
);
++
rows_added
;
}
else
if
constexpr
(
STRICTNESS
==
ASTTableJoin
::
Strictness
::
Any
)
{
throw
Exception
(
"New ANY join storage is not implemented yet (set any_join_distinct_right_table_keys=1 to use old one)"
,
ErrorCodes
::
NOT_IMPLEMENTED
);
}
else
if
constexpr
(
STRICTNESS
==
ASTTableJoin
::
Strictness
::
Asof
)
{
throw
Exception
(
"ASOF join storage is not implemented yet"
,
ErrorCodes
::
NOT_IMPLEMENTED
);
...
...
dbms/tests/queries/0_stateless/01031_new_any_join.reference
0 → 100644
浏览文件 @
b8d464aa
any left
0 a1 0
1 a2 0
2 a3 2 b1
3 a4 0
4 a5 4 b3
any left (rev)
2 a3 2 b1
2 a3 2 b2
4 a5 4 b3
4 a5 4 b4
4 a5 4 b5
4 a5 4 b6
any inner
2 a3 2 b1
4 a5 4 b3
any inner (rev)
2 a3 2 b1
4 a5 4 b3
any right
2 a3 2 b1
2 a3 2 b2
4 a5 4 b3
4 a5 4 b4
4 a5 4 b5
4 a5 4 b6
any right (rev)
0 a1 0
1 a2 0
2 a3 2 b1
3 a4 0
4 a5 4 b3
dbms/tests/queries/0_stateless/01031_new_any_join.sql
0 → 100644
浏览文件 @
b8d464aa
DROP
TABLE
IF
EXISTS
t1
;
DROP
TABLE
IF
EXISTS
t2
;
CREATE
TABLE
t1
(
x
UInt32
,
s
String
)
engine
=
Memory
;
CREATE
TABLE
t2
(
x
UInt32
,
s
String
)
engine
=
Memory
;
INSERT
INTO
t1
(
x
,
s
)
VALUES
(
0
,
'a1'
),
(
1
,
'a2'
),
(
2
,
'a3'
),
(
3
,
'a4'
),
(
4
,
'a5'
);
INSERT
INTO
t2
(
x
,
s
)
VALUES
(
2
,
'b1'
),
(
2
,
'b2'
),
(
4
,
'b3'
),
(
4
,
'b4'
),
(
4
,
'b5'
),
(
4
,
'b6'
);
SET
join_use_nulls
=
0
;
SET
any_join_distinct_right_table_keys
=
0
;
SELECT
'any left'
;
SELECT
t1
.
*
,
t2
.
*
FROM
t1
ANY
LEFT
JOIN
t2
USING
(
x
)
ORDER
BY
t1
.
x
,
t2
.
x
;
SELECT
'any left (rev)'
;
SELECT
t1
.
*
,
t2
.
*
FROM
t2
ANY
LEFT
JOIN
t1
USING
(
x
)
ORDER
BY
t1
.
x
,
t2
.
x
;
SELECT
'any inner'
;
SELECT
t1
.
*
,
t2
.
*
FROM
t1
ANY
INNER
JOIN
t2
USING
(
x
)
ORDER
BY
t1
.
x
,
t2
.
x
;
SELECT
'any inner (rev)'
;
SELECT
t1
.
*
,
t2
.
*
FROM
t2
ANY
INNER
JOIN
t1
USING
(
x
)
ORDER
BY
t1
.
x
,
t2
.
x
;
SELECT
'any right'
;
SELECT
t1
.
*
,
t2
.
*
FROM
t1
ANY
RIGHT
JOIN
t2
USING
(
x
)
ORDER
BY
t1
.
x
,
t2
.
x
;
SELECT
'any right (rev)'
;
SELECT
t1
.
*
,
t2
.
*
FROM
t2
ANY
RIGHT
JOIN
t1
USING
(
x
)
ORDER
BY
t1
.
x
,
t2
.
x
;
DROP
TABLE
t1
;
DROP
TABLE
t2
;
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录