click_house 1.7.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
|