click_house 1.7.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +15 -4
- data/CHANGELOG.md +8 -0
- data/Gemfile.lock +22 -31
- data/Gemfile_faraday1 +11 -0
- data/Gemfile_faraday1.lock +111 -0
- data/Gemfile_faraday2 +1 -0
- data/Gemfile_faraday2.lock +88 -0
- data/Makefile +25 -0
- data/README.md +5 -19
- data/click_house.gemspec +4 -3
- data/lib/click_house/ast/parser.rb +53 -0
- data/lib/click_house/ast/statement.rb +99 -0
- data/lib/click_house/ast/ticker.rb +42 -0
- data/lib/click_house/ast.rb +9 -0
- data/lib/click_house/config.rb +17 -1
- data/lib/click_house/connection.rb +3 -2
- data/lib/click_house/definition/column_set.rb +3 -2
- data/lib/click_house/extend/configurable.rb +2 -0
- data/lib/click_house/extend/type_definition.rb +1 -11
- data/lib/click_house/middleware/parse_csv.rb +5 -6
- data/lib/click_house/middleware/parse_json.rb +16 -0
- data/lib/click_house/middleware/parse_json_oj.rb +22 -0
- data/lib/click_house/middleware/raise_error.rb +6 -12
- data/lib/click_house/middleware/response_base.rb +45 -0
- data/lib/click_house/middleware.rb +3 -0
- data/lib/click_house/response/result_set.rb +56 -43
- data/lib/click_house/response.rb +1 -0
- data/lib/click_house/type/array_type.rb +6 -12
- data/lib/click_house/type/base_type.rb +25 -1
- data/lib/click_house/type/date_time64_type.rb +5 -1
- data/lib/click_house/type/date_time_type.rb +5 -1
- data/lib/click_house/type/decimal_type.rb +15 -1
- data/lib/click_house/type/low_cardinality_type.rb +4 -10
- data/lib/click_house/type/map_type.rb +15 -0
- data/lib/click_house/type/nullable_type.rb +6 -8
- data/lib/click_house/type/string_type.rb +1 -1
- data/lib/click_house/type/tuple_type.rb +15 -0
- data/lib/click_house/type.rb +2 -0
- data/lib/click_house/version.rb +1 -1
- data/lib/click_house.rb +9 -2
- metadata +37 -4
data/lib/click_house/config.rb
CHANGED
@@ -16,7 +16,20 @@ module ClickHouse
|
|
16
16
|
open_timeout: nil,
|
17
17
|
ssl_verify: false,
|
18
18
|
headers: {},
|
19
|
-
global_params: {}
|
19
|
+
global_params: {},
|
20
|
+
json_parser: ClickHouse::Middleware::ParseJson,
|
21
|
+
oj_load_options: {
|
22
|
+
mode: :custom,
|
23
|
+
allow_blank: true,
|
24
|
+
bigdecimal_as_decimal: false, # dump BigDecimal as a String
|
25
|
+
bigdecimal_load: :bigdecimal, # convert all decimal numbers to BigDecimal
|
26
|
+
empty_string: false,
|
27
|
+
second_precision: 6,
|
28
|
+
time_format: :ruby,
|
29
|
+
},
|
30
|
+
json_load_options: {
|
31
|
+
decimal_class: BigDecimal,
|
32
|
+
},
|
20
33
|
}.freeze
|
21
34
|
|
22
35
|
attr_accessor :adapter
|
@@ -33,6 +46,9 @@ module ClickHouse
|
|
33
46
|
attr_accessor :ssl_verify
|
34
47
|
attr_accessor :headers
|
35
48
|
attr_accessor :global_params
|
49
|
+
attr_accessor :oj_load_options
|
50
|
+
attr_accessor :json_load_options
|
51
|
+
attr_accessor :json_parser # response middleware
|
36
52
|
|
37
53
|
def initialize(params = {})
|
38
54
|
assign(DEFAULTS.merge(params))
|
@@ -46,6 +46,7 @@ module ClickHouse
|
|
46
46
|
transport.post(compose('/', query.merge(database: database, **params)), body)
|
47
47
|
end
|
48
48
|
|
49
|
+
# transport should work the same both with Faraday v1 and Faraday v2
|
49
50
|
def transport
|
50
51
|
@transport ||= Faraday.new(config.url!) do |conn|
|
51
52
|
conn.options.timeout = config.timeout
|
@@ -53,10 +54,10 @@ module ClickHouse
|
|
53
54
|
conn.headers = config.headers
|
54
55
|
conn.ssl.verify = config.ssl_verify
|
55
56
|
conn.request(:basic_auth, config.username, config.password) if config.auth?
|
56
|
-
conn.response :json, content_type: %r{application/json}
|
57
57
|
conn.response Middleware::RaiseError
|
58
58
|
conn.response Middleware::Logging, logger: config.logger!
|
59
|
-
conn.response
|
59
|
+
conn.response config.json_parser, content_type: %r{application/json}, parser_options: { config: config }
|
60
|
+
conn.response Middleware::ParseCsv, content_type: %r{text/csv}, parser_options: { config: config }
|
60
61
|
conn.adapter config.adapter
|
61
62
|
end
|
62
63
|
end
|
@@ -3,7 +3,9 @@
|
|
3
3
|
module ClickHouse
|
4
4
|
module Definition
|
5
5
|
class ColumnSet
|
6
|
-
TYPES = ClickHouse.
|
6
|
+
TYPES = ClickHouse.types.each_with_object([]) do |(name, type), object|
|
7
|
+
object << name.sub('%s', "'%s'") if type.ddl?
|
8
|
+
end
|
7
9
|
|
8
10
|
class << self
|
9
11
|
# @input "DateTime('%s')"
|
@@ -15,7 +17,6 @@ module ClickHouse
|
|
15
17
|
|
16
18
|
TYPES.each do |type|
|
17
19
|
method_name = method_name_for_type(type)
|
18
|
-
|
19
20
|
# t.Decimal :customer_id, nullable: true, default: ''
|
20
21
|
# t.Decimal :money, 1, 2, nullable: true, default: ''
|
21
22
|
class_eval <<-METHODS, __FILE__, __LINE__ + 1
|
@@ -3,22 +3,12 @@
|
|
3
3
|
module ClickHouse
|
4
4
|
module Extend
|
5
5
|
module TypeDefinition
|
6
|
-
NULLABLE = 'Nullable'
|
7
|
-
NULLABLE_RE = /#{NULLABLE}/i.freeze
|
8
|
-
LOW_CARDINALITY = 'LowCardinality'
|
9
|
-
|
10
6
|
def types
|
11
7
|
@types ||= Hash.new(Type::UndefinedType.new)
|
12
8
|
end
|
13
9
|
|
14
|
-
def add_type(type, klass
|
10
|
+
def add_type(type, klass)
|
15
11
|
types[type] = klass
|
16
|
-
types["#{NULLABLE}(#{type})"] = Type::NullableType.new(klass) if nullable
|
17
|
-
end
|
18
|
-
|
19
|
-
# @return [Enum<String>]
|
20
|
-
def type_names(nullable:)
|
21
|
-
nullable ? types.keys : types.keys.grep_v(NULLABLE_RE)
|
22
12
|
end
|
23
13
|
end
|
24
14
|
end
|
@@ -2,15 +2,14 @@
|
|
2
2
|
|
3
3
|
module ClickHouse
|
4
4
|
module Middleware
|
5
|
-
class ParseCsv <
|
5
|
+
class ParseCsv < ResponseBase
|
6
6
|
Faraday::Response.register_middleware self => self
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
# @param env [Faraday::Env]
|
9
|
+
def on_complete(env)
|
10
|
+
return unless content_type?(env, content_type)
|
11
11
|
|
12
|
-
|
13
|
-
CSV.parse(body, **Hash.new(parser_options)) unless body.strip.empty?
|
12
|
+
env.body = env.body.strip.empty? ? nil : CSV.parse(env.body)
|
14
13
|
end
|
15
14
|
end
|
16
15
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ClickHouse
|
4
|
+
module Middleware
|
5
|
+
class ParseJson < ResponseBase
|
6
|
+
Faraday::Response.register_middleware self => self
|
7
|
+
|
8
|
+
# @param env [Faraday::Env]
|
9
|
+
def on_complete(env)
|
10
|
+
return unless content_type?(env, content_type)
|
11
|
+
|
12
|
+
env.body = JSON.parse(env.body, config.json_load_options) unless env.body.strip.empty?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ClickHouse
|
4
|
+
module Middleware
|
5
|
+
class ParseJsonOj < ResponseBase
|
6
|
+
Faraday::Response.register_middleware self => self
|
7
|
+
|
8
|
+
# @param env [Faraday::Env]
|
9
|
+
def on_complete(env)
|
10
|
+
return unless content_type?(env, content_type)
|
11
|
+
|
12
|
+
env.body = Oj.load(env.body, config.oj_load_options) unless env.body.strip.empty?
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def on_setup
|
18
|
+
require 'oj' unless defined?(Oj)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -3,28 +3,22 @@
|
|
3
3
|
module ClickHouse
|
4
4
|
module Middleware
|
5
5
|
class RaiseError < Faraday::Middleware
|
6
|
-
SUCCEED_STATUSES = (200..299).freeze
|
7
6
|
EXCEPTION_CODE_HEADER = 'x-clickhouse-exception-code'
|
8
7
|
|
9
8
|
Faraday::Response.register_middleware self => self
|
10
9
|
|
11
|
-
|
12
|
-
|
10
|
+
# @param env [Faraday::Env]
|
11
|
+
def call(env)
|
12
|
+
super
|
13
13
|
rescue Faraday::ConnectionFailed => e
|
14
14
|
raise NetworkException, e.message, e.backtrace
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
# @param env [Faraday::Env]
|
19
18
|
def on_complete(env)
|
20
|
-
|
21
|
-
|
22
|
-
raise DbException, env.body
|
19
|
+
if env.response_headers.include?(EXCEPTION_CODE_HEADER) || !env.success?
|
20
|
+
raise DbException, "[#{env.status}] #{env.body}"
|
23
21
|
end
|
24
|
-
|
25
|
-
return if SUCCEED_STATUSES.include?(env.status)
|
26
|
-
|
27
|
-
raise DbException, "[#{env.status}] #{env.body}"
|
28
22
|
end
|
29
23
|
end
|
30
24
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ClickHouse
|
4
|
+
module Middleware
|
5
|
+
class ResponseBase < Faraday::Middleware
|
6
|
+
CONTENT_TYPE_HEADER = 'content-type'
|
7
|
+
|
8
|
+
attr_reader :parser_options
|
9
|
+
attr_reader :content_type
|
10
|
+
|
11
|
+
def initialize(app = nil, parser_options: {}, content_type: nil, preserve_raw: false)
|
12
|
+
super(app)
|
13
|
+
@parser_options = parser_options
|
14
|
+
@content_type = content_type
|
15
|
+
@preserve_raw = preserve_raw
|
16
|
+
on_setup
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Boolean]
|
20
|
+
# @param env [Faraday::Env]
|
21
|
+
# @param regexp [NilClass, Regexp]
|
22
|
+
def content_type?(env, regexp)
|
23
|
+
case regexp
|
24
|
+
when NilClass
|
25
|
+
false
|
26
|
+
when Regexp
|
27
|
+
regexp.match?(String(env[:response_headers][CONTENT_TYPE_HEADER]))
|
28
|
+
else
|
29
|
+
raise ArgumentError, "expected regexp got #{regexp.class}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [Config]
|
34
|
+
def config
|
35
|
+
parser_options.fetch(:config)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def on_setup
|
41
|
+
# require external dependencies here
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -2,8 +2,11 @@
|
|
2
2
|
|
3
3
|
module ClickHouse
|
4
4
|
module Middleware
|
5
|
+
autoload :ResponseBase, 'click_house/middleware/response_base'
|
5
6
|
autoload :Logging, 'click_house/middleware/logging'
|
6
7
|
autoload :ParseCsv, 'click_house/middleware/parse_csv'
|
8
|
+
autoload :ParseJsonOj, 'click_house/middleware/parse_json_oj'
|
9
|
+
autoload :ParseJson, 'click_house/middleware/parse_json'
|
7
10
|
autoload :RaiseError, 'click_house/middleware/raise_error'
|
8
11
|
end
|
9
12
|
end
|
@@ -6,10 +6,6 @@ module ClickHouse
|
|
6
6
|
extend Forwardable
|
7
7
|
include Enumerable
|
8
8
|
|
9
|
-
TYPE_ARGV_DELIM = ','
|
10
|
-
NULLABLE = 'Nullable'
|
11
|
-
NULLABLE_TYPE_RE = /#{NULLABLE}\((.+)\)/i.freeze
|
12
|
-
ARG_D_RE = /\A-?\d+\Z/.freeze
|
13
9
|
PLACEHOLDER_D = '%d'
|
14
10
|
PLACEHOLDER_S = '%s'
|
15
11
|
|
@@ -19,38 +15,6 @@ module ClickHouse
|
|
19
15
|
|
20
16
|
attr_reader :meta, :data, :totals, :statistics, :rows_before_limit_at_least
|
21
17
|
|
22
|
-
class << self
|
23
|
-
# @return [Array<String, Array>]
|
24
|
-
# * first element is name of "ClickHouse.types.keys"
|
25
|
-
# * second element is extra arguments that should to be passed to <cast> function
|
26
|
-
#
|
27
|
-
# @input "DateTime('Europe/Moscow')"
|
28
|
-
# @output "DateTime(%s)"
|
29
|
-
#
|
30
|
-
# @input "Nullable(Decimal(10, 5))"
|
31
|
-
# @output "Nullable(Decimal(%d, %d))"
|
32
|
-
#
|
33
|
-
# @input "Decimal(10, 5)"
|
34
|
-
# @output "Decimal(%d, %d)"
|
35
|
-
def extract_type_info(type)
|
36
|
-
type = type.gsub(NULLABLE_TYPE_RE, '\1')
|
37
|
-
nullable = Regexp.last_match(1)
|
38
|
-
argv = []
|
39
|
-
|
40
|
-
type = type.gsub(/\((.+)\)/, '')
|
41
|
-
|
42
|
-
if (match = Regexp.last_match(1))
|
43
|
-
argv = match.split("#{TYPE_ARGV_DELIM} ")
|
44
|
-
placeholder = argv.map do |value|
|
45
|
-
value.match?(ARG_D_RE) ? PLACEHOLDER_D : PLACEHOLDER_S
|
46
|
-
end
|
47
|
-
type = "#{type}(#{placeholder.join("#{TYPE_ARGV_DELIM} ")})"
|
48
|
-
end
|
49
|
-
|
50
|
-
[nullable ? "#{NULLABLE}(#{type})" : type, argv]
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
18
|
# @param meta [Array]
|
55
19
|
# @param data [Array]
|
56
20
|
# @param totals [Array|Hash|NilClass] Support for 'GROUP BY WITH TOTALS' modifier
|
@@ -67,20 +31,69 @@ module ClickHouse
|
|
67
31
|
def to_a
|
68
32
|
@to_a ||= data.each do |row|
|
69
33
|
row.each do |name, value|
|
70
|
-
|
71
|
-
row[name] = casting.fetch(:caster).cast(value, *casting.fetch(:arguments))
|
34
|
+
row[name] = cast_type(types.fetch(name), value)
|
72
35
|
end
|
73
36
|
end
|
74
37
|
end
|
75
38
|
|
39
|
+
# @return [Hash<String, Ast::Statement>]
|
76
40
|
def types
|
77
41
|
@types ||= meta.each_with_object({}) do |row, object|
|
78
|
-
|
42
|
+
object[row.fetch('name')] = begin
|
43
|
+
current = Ast::Parser.new(row.fetch('type')).parse
|
44
|
+
assign_type(current)
|
45
|
+
current
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
# @param stmt [Ast::Statement]
|
53
|
+
def assign_type(stmt)
|
54
|
+
stmt.caster = ClickHouse.types[stmt.name]
|
55
|
+
|
56
|
+
if stmt.caster.is_a?(Type::UndefinedType)
|
57
|
+
placeholders = stmt.arguments.map(&:placeholder)
|
58
|
+
stmt.caster = ClickHouse.types["#{stmt.name}(#{placeholders.join(', ')})"]
|
59
|
+
end
|
60
|
+
|
61
|
+
stmt.arguments.each(&method(:assign_type))
|
62
|
+
end
|
63
|
+
|
64
|
+
# @param stmt [Ast::Statement]
|
65
|
+
def cast_type(stmt, value)
|
66
|
+
return cast_container(stmt, value) if stmt.caster.container?
|
67
|
+
return cast_map(stmt, Hash(value)) if stmt.caster.map?
|
68
|
+
return cast_tuple(stmt, Array(value)) if stmt.caster.tuple?
|
69
|
+
|
70
|
+
stmt.caster.cast(value, *stmt.arguments.map(&:value))
|
71
|
+
end
|
72
|
+
|
73
|
+
# @return [Hash]
|
74
|
+
# @param stmt [Ast::Statement]
|
75
|
+
# @param hash [Hash]
|
76
|
+
def cast_map(stmt, hash)
|
77
|
+
raise ArgumentError, "expect hash got #{hash.class}" unless hash.is_a?(Hash)
|
78
|
+
|
79
|
+
key_type, value_type = stmt.arguments
|
80
|
+
hash.each_with_object({}) do |(key, value), object|
|
81
|
+
object[cast_type(key_type, key)] = cast_type(value_type, value)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# @param stmt [Ast::Statement]
|
86
|
+
def cast_container(stmt, value)
|
87
|
+
stmt.caster.cast_each(value) do |item|
|
88
|
+
# TODO: raise an error if multiple arguments
|
89
|
+
cast_type(stmt.arguments.first, item)
|
90
|
+
end
|
91
|
+
end
|
79
92
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
93
|
+
# @param stmt [Ast::Statement]
|
94
|
+
def cast_tuple(stmt, value)
|
95
|
+
value.map.with_index do |item, ix|
|
96
|
+
cast_type(stmt.arguments.fetch(ix), item)
|
84
97
|
end
|
85
98
|
end
|
86
99
|
end
|
data/lib/click_house/response.rb
CHANGED
@@ -3,22 +3,16 @@
|
|
3
3
|
module ClickHouse
|
4
4
|
module Type
|
5
5
|
class ArrayType < BaseType
|
6
|
-
|
7
|
-
|
8
|
-
def initialize(subtype)
|
9
|
-
@subtype = subtype
|
6
|
+
def cast_each(value, *_argv, &block)
|
7
|
+
value.map(&block)
|
10
8
|
end
|
11
9
|
|
12
|
-
def
|
13
|
-
|
10
|
+
def container?
|
11
|
+
true
|
14
12
|
end
|
15
13
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
array.map do |value|
|
20
|
-
subtype.serialize(value, *argv)
|
21
|
-
end
|
14
|
+
def ddl?
|
15
|
+
false
|
22
16
|
end
|
23
17
|
end
|
24
18
|
end
|
@@ -7,9 +7,33 @@ module ClickHouse
|
|
7
7
|
raise NotImplementedError, __method__
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
10
|
+
def cast_each(_value, *)
|
11
11
|
raise NotImplementedError, __method__
|
12
12
|
end
|
13
|
+
|
14
|
+
# @return [Boolean]
|
15
|
+
# true if type contains another type like Nullable(T) or Array(T)
|
16
|
+
def container?
|
17
|
+
false
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [Boolean]
|
21
|
+
# true if type is a Map
|
22
|
+
def map?
|
23
|
+
false
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [Boolean]
|
27
|
+
# true if type is a Tuple
|
28
|
+
def tuple?
|
29
|
+
false
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [Boolean]
|
33
|
+
# skip type from DDL statements
|
34
|
+
def ddl?
|
35
|
+
true
|
36
|
+
end
|
13
37
|
end
|
14
38
|
end
|
15
39
|
end
|
@@ -4,7 +4,11 @@ module ClickHouse
|
|
4
4
|
module Type
|
5
5
|
class DateTime64Type < BaseType
|
6
6
|
def cast(value, _precision = nil, tz = nil)
|
7
|
-
|
7
|
+
if tz
|
8
|
+
Time.find_zone(tz).parse(value)
|
9
|
+
else
|
10
|
+
Time.parse(value)
|
11
|
+
end
|
8
12
|
end
|
9
13
|
|
10
14
|
def serialize(value, precision = 3)
|
@@ -3,8 +3,22 @@
|
|
3
3
|
module ClickHouse
|
4
4
|
module Type
|
5
5
|
class DecimalType < BaseType
|
6
|
+
MAXIMUM = Float::DIG
|
7
|
+
|
8
|
+
# clickhouse:
|
9
|
+
# P - precision. Valid range: [ 1 : 76 ]. Determines how many decimal digits number can have (including fraction).
|
10
|
+
# S - scale. Valid range: [ 0 : P ]. Determines how many decimal digits fraction can have.
|
11
|
+
#
|
12
|
+
# when Oj parser @refs https://stackoverflow.com/questions/47885304/deserialise-json-numbers-as-bigdecimal
|
6
13
|
def cast(value, precision = Float::DIG, _scale = nil)
|
7
|
-
|
14
|
+
case value
|
15
|
+
when BigDecimal
|
16
|
+
value
|
17
|
+
when String
|
18
|
+
BigDecimal(value)
|
19
|
+
else
|
20
|
+
BigDecimal(value, precision > MAXIMUM ? MAXIMUM : precision)
|
21
|
+
end
|
8
22
|
end
|
9
23
|
|
10
24
|
def serialize(value, precision = Float::DIG, _scale = nil)
|
@@ -3,18 +3,12 @@
|
|
3
3
|
module ClickHouse
|
4
4
|
module Type
|
5
5
|
class LowCardinalityType < BaseType
|
6
|
-
|
7
|
-
|
8
|
-
def initialize(subtype)
|
9
|
-
@subtype = subtype
|
10
|
-
end
|
11
|
-
|
12
|
-
def cast(*argv)
|
13
|
-
subtype.cast(*argv)
|
6
|
+
def cast_each(value, *_argv)
|
7
|
+
yield(value) unless value.nil?
|
14
8
|
end
|
15
9
|
|
16
|
-
def
|
17
|
-
|
10
|
+
def container?
|
11
|
+
true
|
18
12
|
end
|
19
13
|
end
|
20
14
|
end
|
@@ -3,18 +3,16 @@
|
|
3
3
|
module ClickHouse
|
4
4
|
module Type
|
5
5
|
class NullableType < BaseType
|
6
|
-
|
7
|
-
|
8
|
-
def initialize(subtype)
|
9
|
-
@subtype = subtype
|
6
|
+
def cast_each(value, *_argv)
|
7
|
+
yield(value) unless value.nil?
|
10
8
|
end
|
11
9
|
|
12
|
-
def
|
13
|
-
|
10
|
+
def container?
|
11
|
+
true
|
14
12
|
end
|
15
13
|
|
16
|
-
def
|
17
|
-
|
14
|
+
def ddl?
|
15
|
+
false
|
18
16
|
end
|
19
17
|
end
|
20
18
|
end
|
data/lib/click_house/type.rb
CHANGED
@@ -14,6 +14,8 @@ module ClickHouse
|
|
14
14
|
autoload :DecimalType, 'click_house/type/decimal_type'
|
15
15
|
autoload :FixedStringType, 'click_house/type/fixed_string_type'
|
16
16
|
autoload :ArrayType, 'click_house/type/array_type'
|
17
|
+
autoload :TupleType, 'click_house/type/tuple_type'
|
18
|
+
autoload :MapType, 'click_house/type/map_type'
|
17
19
|
autoload :StringType, 'click_house/type/string_type'
|
18
20
|
autoload :IPType, 'click_house/type/ip_type'
|
19
21
|
autoload :LowCardinalityType, 'click_house/type/low_cardinality_type'
|
data/lib/click_house/version.rb
CHANGED
data/lib/click_house.rb
CHANGED
@@ -8,13 +8,14 @@ require 'logger'
|
|
8
8
|
require 'faraday'
|
9
9
|
require 'forwardable'
|
10
10
|
require 'bigdecimal'
|
11
|
-
require '
|
11
|
+
require 'active_support/core_ext/time/calculations'
|
12
12
|
require 'click_house/version'
|
13
13
|
require 'click_house/errors'
|
14
14
|
require 'click_house/response'
|
15
15
|
require 'click_house/type'
|
16
16
|
require 'click_house/middleware'
|
17
17
|
require 'click_house/extend'
|
18
|
+
require 'click_house/ast'
|
18
19
|
require 'click_house/util'
|
19
20
|
require 'click_house/definition'
|
20
21
|
|
@@ -26,6 +27,12 @@ module ClickHouse
|
|
26
27
|
autoload :Config, 'click_house/config'
|
27
28
|
autoload :Connection, 'click_house/connection'
|
28
29
|
|
30
|
+
add_type 'Array', Type::ArrayType.new
|
31
|
+
add_type 'Nullable', Type::NullableType.new
|
32
|
+
add_type 'Map', Type::MapType.new
|
33
|
+
add_type 'LowCardinality', Type::LowCardinalityType.new
|
34
|
+
add_type 'Tuple', Type::TupleType.new
|
35
|
+
|
29
36
|
%w[Date].each do |column|
|
30
37
|
add_type column, Type::DateType.new
|
31
38
|
end
|
@@ -42,7 +49,7 @@ module ClickHouse
|
|
42
49
|
add_type column, Type::DateTime64Type.new
|
43
50
|
end
|
44
51
|
|
45
|
-
['Decimal(%d, %d)', 'Decimal32(%d)', 'Decimal64(%d)', 'Decimal128(%d)'].each do |column|
|
52
|
+
['Decimal(%d, %d)', 'Decimal32(%d)', 'Decimal64(%d)', 'Decimal128(%d)', 'Decimal256(%d)'].each do |column|
|
46
53
|
add_type column, Type::DecimalType.new
|
47
54
|
end
|
48
55
|
|