Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
2dot5
ClickHouse
提交
7ccf0444
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,发现更多精彩内容 >>
提交
7ccf0444
编写于
9月 17, 2019
作者:
C
CurtizJ
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
better code in Redis external dictionary
上级
df82e4bd
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
44 addition
and
83 deletion
+44
-83
dbms/src/Common/ErrorCodes.cpp
dbms/src/Common/ErrorCodes.cpp
+1
-1
dbms/src/Dictionaries/RedisBlockInputStream.cpp
dbms/src/Dictionaries/RedisBlockInputStream.cpp
+27
-66
dbms/src/Dictionaries/RedisBlockInputStream.h
dbms/src/Dictionaries/RedisBlockInputStream.h
+2
-2
dbms/src/Dictionaries/RedisDictionarySource.cpp
dbms/src/Dictionaries/RedisDictionarySource.cpp
+14
-14
未找到文件。
dbms/src/Common/ErrorCodes.cpp
浏览文件 @
7ccf0444
...
...
@@ -451,7 +451,7 @@ namespace ErrorCodes
extern
const
int
INVALID_TEMPLATE_FORMAT
=
474
;
extern
const
int
INVALID_WITH_FILL_EXPRESSION
=
475
;
extern
const
int
WITH_TIES_WITHOUT_ORDER_BY
=
476
;
extern
const
int
IN
VALID_USAGE_OF_INPUT
=
477
;
extern
const
int
IN
TERNAL_REDIS_ERROR
=
477
;
extern
const
int
KEEPER_EXCEPTION
=
999
;
extern
const
int
POCO_EXCEPTION
=
1000
;
...
...
dbms/src/Dictionaries/RedisBlockInputStream.cpp
浏览文件 @
7ccf0444
...
...
@@ -26,8 +26,8 @@ namespace DB
{
extern
const
int
TYPE_MISMATCH
;
extern
const
int
LOGICAL_ERROR
;
extern
const
int
LIMIT_EXCEEDED
;
extern
const
int
NUMBER_OF_COLUMNS_DOESNT_MATCH
;
extern
const
int
INTERNAL_REDIS_ERROR
;
}
...
...
@@ -49,42 +49,18 @@ namespace DB
{
using
ValueType
=
ExternalResultDescription
::
ValueType
;
bool
isNullString
(
const
Poco
::
Redis
::
RedisType
::
Ptr
&
value
)
{
return
value
->
isBulkString
()
&&
static_cast
<
const
Poco
::
Redis
::
Type
<
Poco
::
Redis
::
BulkString
>
*>
(
value
.
get
())
->
value
().
isNull
();
}
std
::
string
getStringOrThrow
(
const
Poco
::
Redis
::
RedisType
::
Ptr
&
value
,
const
std
::
string
&
column_name
)
{
switch
(
value
->
type
())
{
case
Poco
::
Redis
::
RedisTypeTraits
<
Poco
::
Redis
::
BulkString
>::
TypeId
:
{
const
auto
&
bs
=
static_cast
<
const
Poco
::
Redis
::
Type
<
Poco
::
Redis
::
BulkString
>
*>
(
value
.
get
())
->
value
();
if
(
bs
.
isNull
())
throw
Exception
{
"Type mismatch, expected not null String for column "
+
column_name
,
ErrorCodes
::
TYPE_MISMATCH
};
return
bs
.
value
();
}
case
Poco
::
Redis
::
RedisTypeTraits
<
std
::
string
>::
TypeId
:
return
static_cast
<
const
Poco
::
Redis
::
Type
<
std
::
string
>
*>
(
value
.
get
())
->
value
();
default:
throw
Exception
{
"Type mismatch, expected std::string, got type id = "
+
toString
(
value
->
type
())
+
" for column "
+
column_name
,
ErrorCodes
::
TYPE_MISMATCH
};
}
}
template
<
typename
T
>
inline
void
insert
(
IColumn
&
column
,
const
String
&
stringValue
)
{
static
_cast
<
ColumnVector
<
T
>
&>
(
column
).
insertValue
(
parse
<
T
>
(
stringValue
));
assert
_cast
<
ColumnVector
<
T
>
&>
(
column
).
insertValue
(
parse
<
T
>
(
stringValue
));
}
void
insertValue
(
IColumn
&
column
,
const
ValueType
type
,
const
Poco
::
Redis
::
RedisType
::
Ptr
&
value
,
const
std
::
string
&
name
)
void
insertValue
(
IColumn
&
column
,
const
ValueType
type
,
const
Poco
::
Redis
::
BulkString
&
bulk_string
)
{
String
stringValue
=
getStringOrThrow
(
value
,
name
);
if
(
bulk_string
.
isNull
())
throw
Exception
{
"Type mismatch, expected not Null String"
,
ErrorCodes
::
TYPE_MISMATCH
};
String
stringValue
=
bulk_string
.
value
();
switch
(
type
)
{
case
ValueType
::
vtUInt8
:
...
...
@@ -118,16 +94,16 @@ namespace DB
insert
<
Float64
>
(
column
,
stringValue
);
break
;
case
ValueType
::
vtString
:
static
_cast
<
ColumnString
&>
(
column
).
insert
(
parse
<
String
>
(
stringValue
));
assert
_cast
<
ColumnString
&>
(
column
).
insert
(
parse
<
String
>
(
stringValue
));
break
;
case
ValueType
::
vtDate
:
static
_cast
<
ColumnUInt16
&>
(
column
).
insertValue
(
parse
<
LocalDate
>
(
stringValue
).
getDayNum
());
assert
_cast
<
ColumnUInt16
&>
(
column
).
insertValue
(
parse
<
LocalDate
>
(
stringValue
).
getDayNum
());
break
;
case
ValueType
::
vtDateTime
:
static
_cast
<
ColumnUInt32
&>
(
column
).
insertValue
(
static_cast
<
UInt32
>
(
parse
<
LocalDateTime
>
(
stringValue
)));
assert
_cast
<
ColumnUInt32
&>
(
column
).
insertValue
(
static_cast
<
UInt32
>
(
parse
<
LocalDateTime
>
(
stringValue
)));
break
;
case
ValueType
::
vtUUID
:
static
_cast
<
ColumnUInt128
&>
(
column
).
insertValue
(
parse
<
UUID
>
(
stringValue
));
assert
_cast
<
ColumnUInt128
&>
(
column
).
insertValue
(
parse
<
UUID
>
(
stringValue
));
break
;
}
}
...
...
@@ -150,25 +126,21 @@ namespace DB
const
auto
insertValueByIdx
=
[
this
,
&
columns
](
size_t
idx
,
const
auto
&
value
)
{
const
auto
&
name
=
description
.
sample_block
.
getByPosition
(
idx
).
name
;
if
(
description
.
types
[
idx
].
second
)
{
ColumnNullable
&
column_nullable
=
static_cast
<
ColumnNullable
&>
(
*
columns
[
idx
]);
insertValue
(
column_nullable
.
getNestedColumn
(),
description
.
types
[
idx
].
first
,
value
,
name
);
insertValue
(
column_nullable
.
getNestedColumn
(),
description
.
types
[
idx
].
first
,
value
);
column_nullable
.
getNullMapData
().
emplace_back
(
0
);
}
else
insertValue
(
*
columns
[
idx
],
description
.
types
[
idx
].
first
,
value
,
name
);
insertValue
(
*
columns
[
idx
],
description
.
types
[
idx
].
first
,
value
);
};
if
(
storage_type
==
RedisStorageType
::
HASH_MAP
)
{
size_t
num_rows
=
0
;
while
(
num_rows
<
max_block_size
&&
!
all_read
)
for
(;
cursor
<
keys
.
size
();
++
cursor
)
{
if
(
cursor
>=
keys
.
size
())
break
;
const
auto
&
keys_array
=
keys
.
get
<
RedisArray
>
(
cursor
);
if
(
keys_array
.
size
()
<
2
)
{
...
...
@@ -183,24 +155,20 @@ namespace DB
for
(
auto
it
=
keys_array
.
begin
();
it
!=
keys_array
.
end
();
++
it
)
command_for_values
.
addRedisType
(
*
it
);
++
cursor
;
auto
values
=
client
->
execute
<
RedisArray
>
(
command_for_values
);
if
(
keys_array
.
size
()
!=
values
.
size
()
+
1
)
// 'HMGET' primary_key secondary_keys
throw
Exception
{
"Inconsistent sizes of keys and values in Redis request"
,
ErrorCodes
::
NUMBER_OF_COLUMNS_DOESNT_MATCH
};
const
auto
&
primary_key
=
*
keys_array
.
begin
(
);
const
auto
&
primary_key
=
keys_array
.
get
<
RedisBulkString
>
(
0
);
for
(
size_t
i
=
0
;
i
<
values
.
size
();
++
i
)
{
const
auto
&
secondary_key
=
*
(
keys_array
.
begin
()
+
i
+
1
);
const
auto
&
value
=
*
(
values
.
begin
()
+
i
);
if
(
value
.
isNull
())
throw
Exception
(
"Got NULL value in response from Redis"
,
ErrorCodes
::
LOGICAL_ERROR
);
const
auto
&
secondary_key
=
keys_array
.
get
<
RedisBulkString
>
(
i
+
1
);
const
auto
&
value
=
values
.
get
<
RedisBulkString
>
(
i
);
/// null string means 'no value for requested key'
if
(
!
isNullString
(
value
))
if
(
!
value
.
isNull
(
))
{
insertValueByIdx
(
0
,
primary_key
);
insertValueByIdx
(
1
,
secondary_key
);
...
...
@@ -214,34 +182,27 @@ namespace DB
{
Poco
::
Redis
::
Command
command_for_values
(
"MGET"
);
// keys.size() > 0
for
(
size_t
i
=
0
;
i
<
max_block_size
&&
cursor
<
keys
.
size
();
++
i
)
{
const
auto
&
key
=
*
(
keys
.
begin
()
+
cursor
);
command_for_values
.
addRedisType
(
key
);
++
cursor
;
}
size_t
need_values
=
std
::
min
(
max_block_size
,
keys
.
size
()
-
cursor
);
for
(
size_t
i
=
0
;
i
<
need_values
;
++
i
)
command_for_values
.
add
(
keys
.
get
<
RedisBulkString
>
(
cursor
+
i
));
auto
values
=
client
->
execute
<
RedisArray
>
(
command_for_values
);
if
(
command_for_values
.
size
()
!=
values
.
size
()
+
1
)
// 'MGET' keys
throw
Exception
{
"Inconsistent sizes of keys and values in Redis request"
,
ErrorCodes
::
NUMBER_OF_COLUMNS_DOESNT_MATCH
};
if
(
values
.
size
()
!=
need_values
)
throw
Exception
{
"Inconsistent sizes of keys and values in Redis request"
,
ErrorCodes
::
INTERNAL_REDIS_ERROR
};
for
(
size_t
i
=
0
;
i
<
values
.
size
();
++
i
)
{
const
auto
&
key
=
*
(
keys
.
begin
()
+
cursor
-
i
-
1
);
const
auto
&
value
=
*
(
values
.
begin
()
+
values
.
size
()
-
i
-
1
);
if
(
value
.
isNull
())
throw
Exception
(
"Got NULL value in response from Redis"
,
ErrorCodes
::
LOGICAL_ERROR
);
const
auto
&
key
=
keys
.
get
<
RedisBulkString
>
(
cursor
+
i
);
const
auto
&
value
=
values
.
get
<
RedisBulkString
>
(
i
);
///
n
ull string means 'no value for requested key'
if
(
!
isNullString
(
value
))
///
N
ull string means 'no value for requested key'
if
(
!
value
.
isNull
(
))
{
insertValueByIdx
(
0
,
key
);
insertValueByIdx
(
1
,
value
);
}
}
cursor
+=
need_values
;
}
return
description
.
sample_block
.
cloneWithColumns
(
std
::
move
(
columns
));
...
...
dbms/src/Dictionaries/RedisBlockInputStream.h
浏览文件 @
7ccf0444
...
...
@@ -8,14 +8,13 @@
# include <DataStreams/IBlockInputStream.h>
# include "RedisDictionarySource.h"
# include <Poco/Redis/Array.h>
# include <Poco/Redis/Type.h>
namespace
Poco
{
namespace
Redis
{
class
Array
;
class
Client
;
class
RedisType
;
}
}
...
...
@@ -26,6 +25,7 @@ namespace DB
{
public:
using
RedisArray
=
Poco
::
Redis
::
Array
;
using
RedisBulkString
=
Poco
::
Redis
::
BulkString
;
RedisBlockInputStream
(
const
std
::
shared_ptr
<
Poco
::
Redis
::
Client
>
&
client_
,
...
...
dbms/src/Dictionaries/RedisDictionarySource.cpp
浏览文件 @
7ccf0444
...
...
@@ -13,7 +13,7 @@ namespace DB
{
auto
createTableSource
=
[
=
](
const
DictionaryStructure
&
dict_struct
,
const
Poco
::
Util
::
AbstractConfiguration
&
config
,
const
std
::
s
tring
&
config_prefix
,
const
S
tring
&
config_prefix
,
Block
&
sample_block
,
const
Context
&
/* context */
)
->
DictionarySourcePtr
{
#if USE_POCO_REDIS
...
...
@@ -52,8 +52,8 @@ namespace DB
namespace
ErrorCodes
{
extern
const
int
UNSUPPORTED_METHOD
;
extern
const
int
CANNOT_SELECT
;
extern
const
int
INVALID_CONFIG_PARAMETER
;
extern
const
int
INTERNAL_REDIS_ERROR
;
}
...
...
@@ -61,7 +61,7 @@ namespace DB
RedisDictionarySource
::
RedisDictionarySource
(
const
DictionaryStructure
&
dict_struct_
,
const
std
::
s
tring
&
host_
,
const
S
tring
&
host_
,
UInt16
port_
,
UInt8
db_index_
,
RedisStorageType
storage_type_
,
...
...
@@ -81,12 +81,12 @@ namespace DB
if
(
storage_type
==
RedisStorageType
::
HASH_MAP
)
{
if
(
!
dict_struct
.
key
.
has_value
()
)
if
(
!
dict_struct
.
key
)
throw
Exception
{
"Redis source with storage type
\'
hash_map
\'
must have key"
,
ErrorCodes
::
INVALID_CONFIG_PARAMETER
};
if
(
dict_struct
.
key
.
value
().
size
()
>
2
)
throw
Exception
{
"Redis source with
complex keys having more than 2 attributes are unsupported
"
,
if
(
dict_struct
.
key
->
size
()
!=
2
)
throw
Exception
{
"Redis source with
storage type
\'
hash_map
\'
requiers 2 keys
"
,
ErrorCodes
::
INVALID_CONFIG_PARAMETER
};
// suppose key[0] is primary key, key[1] is secondary key
}
...
...
@@ -95,10 +95,10 @@ namespace DB
{
RedisCommand
command
(
"SELECT"
);
command
<<
static_cast
<
Int64
>
(
db_index
);
std
::
string
reply
=
client
->
execute
<
std
::
s
tring
>
(
command
);
String
reply
=
client
->
execute
<
S
tring
>
(
command
);
if
(
reply
!=
"+OK
\r\n
"
)
throw
Exception
{
"Selecting d
b with index "
+
DB
::
toString
(
db_index
)
+
" failed with reason "
+
reply
,
ErrorCodes
::
CANNOT_SELECT
};
throw
Exception
{
"Selecting d
atabase with index "
+
DB
::
toString
(
db_index
)
+
" failed with reason "
+
reply
,
ErrorCodes
::
INTERNAL_REDIS_ERROR
};
}
}
...
...
@@ -106,7 +106,7 @@ namespace DB
RedisDictionarySource
::
RedisDictionarySource
(
const
DictionaryStructure
&
dict_struct_
,
const
Poco
::
Util
::
AbstractConfiguration
&
config_
,
const
std
::
s
tring
&
config_prefix_
,
const
S
tring
&
config_prefix_
,
Block
&
sample_block_
)
:
RedisDictionarySource
(
dict_struct_
,
...
...
@@ -132,7 +132,7 @@ namespace DB
RedisDictionarySource
::~
RedisDictionarySource
()
=
default
;
static
std
::
s
tring
storageTypeToKeyType
(
RedisStorageType
type
)
static
S
tring
storageTypeToKeyType
(
RedisStorageType
type
)
{
switch
(
type
)
{
...
...
@@ -160,7 +160,7 @@ namespace DB
RedisArray
keys
;
auto
key_type
=
storageTypeToKeyType
(
storage_type
);
for
(
auto
&
key
:
all_keys
)
if
(
key_type
==
client
->
execute
<
std
::
s
tring
>
(
RedisCommand
(
"TYPE"
).
addRedisType
(
key
)))
if
(
key_type
==
client
->
execute
<
S
tring
>
(
RedisCommand
(
"TYPE"
).
addRedisType
(
key
)))
keys
.
addRedisType
(
std
::
move
(
key
));
if
(
storage_type
==
RedisStorageType
::
HASH_MAP
)
...
...
@@ -213,12 +213,12 @@ namespace DB
return
std
::
make_shared
<
RedisBlockInputStream
>
(
client
,
std
::
move
(
keys
),
storage_type
,
sample_block
,
max_block_size
);
}
std
::
s
tring
RedisDictionarySource
::
toString
()
const
S
tring
RedisDictionarySource
::
toString
()
const
{
return
"Redis: "
+
host
+
':'
+
DB
::
toString
(
port
);
}
RedisStorageType
RedisDictionarySource
::
parseStorageType
(
const
std
::
s
tring
&
storage_type_str
)
RedisStorageType
RedisDictionarySource
::
parseStorageType
(
const
S
tring
&
storage_type_str
)
{
if
(
storage_type_str
==
"hash_map"
)
return
RedisStorageType
::
HASH_MAP
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录