Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
2dot5
ClickHouse
提交
7c03b35b
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,发现更多精彩内容 >>
提交
7c03b35b
编写于
12月 01, 2018
作者:
V
Vitaly Baranov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
CLICKHOUSE-4127: Fix assertion in debug build.
Do reading faster if the structure isn't altered.
上级
c399038e
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
45 addition
and
35 deletion
+45
-35
dbms/src/Storages/StorageBuffer.cpp
dbms/src/Storages/StorageBuffer.cpp
+45
-35
未找到文件。
dbms/src/Storages/StorageBuffer.cpp
浏览文件 @
7c03b35b
#include <boost/range/algorithm_ext/erase.hpp>
#include <Interpreters/InterpreterSelectQuery.h>
#include <Interpreters/InterpreterInsertQuery.h>
#include <Interpreters/InterpreterAlterQuery.h>
...
...
@@ -148,56 +149,65 @@ BlockInputStreams StorageBuffer::read(
if
(
destination
.
get
()
==
this
)
throw
Exception
(
"Destination table is myself. Read will cause infinite loop."
,
ErrorCodes
::
INFINITE_LOOP
);
/// Collect columns from the destination tables which can be requested.
/// Find out if there is a struct mismatch and we need to convert read blocks from the destination tables.
auto
destination_lock
=
destination
->
lockStructure
(
false
);
Names
columns_intersection
;
bool
struct_mismatch
=
false
;
for
(
const
String
&
column_name
:
column_names
)
const
bool
dst_has_same_structure
=
std
::
all_of
(
column_names
.
begin
(),
column_names
.
end
(),
[
this
,
destination
](
const
String
&
column_name
)
{
if
(
destination
->
hasColumn
(
column_name
))
return
destination
->
hasColumn
(
column_name
)
&&
destination
->
getColumn
(
column_name
).
type
->
equals
(
*
getColumn
(
column_name
).
type
);
});
if
(
dst_has_same_structure
)
{
/// The destination table has the same structure of the requested columns and we can simply read blocks from there.
streams_from_dst
=
destination
->
read
(
column_names
,
query_info
,
context
,
processed_stage
,
max_block_size
,
num_streams
);
}
else
{
/// There is a struct mismatch and we need to convert read blocks from the destination table.
const
Block
header
=
getSampleBlock
();
Names
columns_intersection
=
column_names
;
Block
header_after_adding_defaults
=
header
;
for
(
const
String
&
column_name
:
column_names
)
{
columns_intersection
.
emplace_back
(
column_name
);
if
(
!
destination
->
getColumn
(
column_name
).
type
->
equals
(
*
getColumn
(
column_name
).
type
))
if
(
!
destination
->
hasColumn
(
column_name
))
{
LOG_WARNING
(
log
,
"Destination table "
<<
backQuoteIfNeed
(
destination_database
)
<<
"."
<<
backQuoteIfNeed
(
destination_table
)
<<
" doesn't have column "
<<
backQuoteIfNeed
(
column_name
)
<<
". The default values are used."
);
boost
::
range
::
remove_erase
(
columns_intersection
,
column_name
);
continue
;
}
const
auto
&
dst_col
=
destination
->
getColumn
(
column_name
);
const
auto
&
col
=
getColumn
(
column_name
);
if
(
!
dst_col
.
type
->
equals
(
*
col
.
type
))
{
LOG_WARNING
(
log
,
"Destination table "
<<
backQuoteIfNeed
(
destination_database
)
<<
"."
<<
backQuoteIfNeed
(
destination_table
)
<<
" has different type of column "
<<
backQuoteIfNeed
(
column_name
)
<<
" ("
<<
destination
->
getColumn
(
column_name
).
type
->
getName
()
<<
" != "
<<
getColumn
(
column_name
).
type
->
getName
()
<<
"). Data from destination table is converted."
);
struct_mismatch
=
true
;
<<
dst_col
.
type
->
getName
()
<<
" != "
<<
col
.
type
->
getName
()
<<
"). Data from destination table are converted."
);
header_after_adding_defaults
.
getByName
(
column_name
)
=
ColumnWithTypeAndName
(
dst_col
.
type
,
column_name
);
}
}
else
if
(
columns_intersection
.
empty
())
{
LOG_WARNING
(
log
,
"Destination table "
<<
backQuoteIfNeed
(
destination_database
)
<<
"."
<<
backQuoteIfNeed
(
destination_table
)
<<
" doesn't have column "
<<
backQuoteIfNeed
(
column_name
)
<<
". The default values are used."
);
struct_mismatch
=
true
;
<<
" has no common columns with block in buffer. Block of data is skipped."
);
}
}
if
(
columns_intersection
.
empty
())
LOG_WARNING
(
log
,
"Destination table "
<<
backQuoteIfNeed
(
destination_database
)
<<
"."
<<
backQuoteIfNeed
(
destination_table
)
<<
" has no common columns with block in buffer. Block of data is skipped."
);
else
{
streams_from_dst
=
destination
->
read
(
columns_intersection
,
query_info
,
context
,
processed_stage
,
max_block_size
,
num_streams
);
for
(
auto
&
stream
:
streams_from_dst
)
stream
->
addTableLock
(
destination_lock
);
}
if
(
struct_mismatch
&&
!
streams_from_dst
.
empty
())
{
/// Add streams to convert read blocks from the destination table.
auto
header
=
getSampleBlock
();
for
(
auto
&
stream_from_dst
:
streams_from_dst
)
else
{
stream_from_dst
=
std
::
make_shared
<
AddingDefaultBlockInputStream
>
(
stream_from_dst
,
header
,
getColumns
().
defaults
,
context
);
stream_from_dst
=
std
::
make_shared
<
ConvertingBlockInputStream
>
(
context
,
stream_from_dst
,
header
,
ConvertingBlockInputStream
::
MatchColumnsMode
::
Name
);
streams_from_dst
=
destination
->
read
(
columns_intersection
,
query_info
,
context
,
processed_stage
,
max_block_size
,
num_streams
);
for
(
auto
&
stream
:
streams_from_dst
)
{
stream
=
std
::
make_shared
<
AddingDefaultBlockInputStream
>
(
stream
,
header_after_adding_defaults
,
getColumns
().
defaults
,
context
);
stream
=
std
::
make_shared
<
ConvertingBlockInputStream
>
(
context
,
stream
,
header
,
ConvertingBlockInputStream
::
MatchColumnsMode
::
Name
);
}
}
}
for
(
auto
&
stream
:
streams_from_dst
)
stream
->
addTableLock
(
destination_lock
);
}
BlockInputStreams
streams_from_buffers
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录