clickhouse-activerecord 0.4.9 → 0.4.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 64fdd9e93e5277c2639a5f88ced05132f09f1c8e455d7db2c171b8cf524295c2
4
- data.tar.gz: f9745f682cd6a74c940dcf6e049b802e2ceefad4df10c249c0f7f47d7ac2756c
3
+ metadata.gz: '08f97b801fdb83a013dfeaf3aa11b9aa8bdaf4f66d7e63550666a3519f5cc2ce'
4
+ data.tar.gz: b6e6e5e5b4ce521cf05fe994488625bf589843d340627ae957d827dba67c842e
5
5
  SHA512:
6
- metadata.gz: df3570664e14b336f3f6bbfa91c03a1450647e1936c45f1e61e812fd449c842be49764d3e16f2b1184bc329a7f9f2e03c6000f10e4344c132cd1f1b269e6395c
7
- data.tar.gz: 436b4436079fe95ee5e99b3579c6b191738178540f384f6317199f4eaca99a452a178134ae2706f7fe36a121d56c458dfe215118558c5c539956804cecb85790
6
+ metadata.gz: 26c2e974e5c4f0ec1e67b647c065b4d5bdc3cb98fd7c2f375f9b767214b004a278382723fbfcd998b372f9e1261262689faa1c05ff07d6f6b483985d2722303c
7
+ data.tar.gz: a0def62c1153f5359653c8c1036201258b52813cb40bf0db9f00f4fafdd68bf0d70a3d1fabc3730fc2c8b5badcdd14daa66d283b56892f6d48b7f4b73089446d
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ### Version 0.4.10 (Mar 10, 2021)
2
+
3
+ * Support ClickHouse 20.9+
4
+ * Fix schema create / dump
5
+ * Support all integer types through :limit and :unsigned [@bdevel](https://github.com/bdevel)
6
+
1
7
  ### Version 0.4.4 (Sep 23, 2020)
2
8
 
3
9
  * Full support migration and rollback database
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Clickhouse::Activerecord
2
2
 
3
3
  A Ruby database ActiveRecord driver for ClickHouse. Support Rails >= 5.2.
4
- Support ClickHouse version from 19.14 LTS.
4
+ Support ClickHouse version from 20.9 LTS.
5
5
 
6
6
  ## Installation
7
7
 
@@ -162,6 +162,44 @@ ActionView.maximum(:date)
162
162
  #=> 'Wed, 29 Nov 2017'
163
163
  ```
164
164
 
165
+
166
+ ### Migration Data Types
167
+
168
+ Integer types are unsigned by default. Specify signed values with `:unsigned =>
169
+ false`. The default integer is `UInt32`
170
+
171
+ | Type (bit size) | Range | :limit (byte size) |
172
+ | :--- | :----: | ---: |
173
+ | Int8 | -128 to 127 | 1 |
174
+ | Int16 | -32768 to 32767 | 2 |
175
+ | Int32 | -2147483648 to 2,147,483,647 | 3,4 |
176
+ | Int64 | -9223372036854775808 to 9223372036854775807] | 5,6,7,8 |
177
+ | Int128 | ... | 9 - 15 |
178
+ | Int256 | ... | 16+ |
179
+ | UInt8 | 0 to 255 | 1 |
180
+ | UInt16 | 0 to 65,535 | 2 |
181
+ | UInt32 | 0 to 4,294,967,295 | 3,4 |
182
+ | UInt64 | 0 to 18446744073709551615 | 5,6,7,8 |
183
+ | UInt256 | 0 to ... | 8+ |
184
+
185
+ Example:
186
+
187
+ ``` ruby
188
+ class CreateDataItems < ActiveRecord::Migration
189
+ def change
190
+ create_table "data_items", id: false, options: "VersionedCollapsingMergeTree(sign, version) PARTITION BY toYYYYMM(day) ORDER BY category", force: :cascade do |t|
191
+ t.date "day", null: false
192
+ t.string "category", null: false
193
+ t.integer "value_in", null: false
194
+ t.integer "sign", limit: 1, unsigned: false, default: -> { "CAST(1, 'Int8')" }, null: false
195
+ t.integer "version", limit: 8, default: -> { "CAST(toUnixTimestamp(now()), 'UInt64')" }, null: false
196
+ end
197
+ end
198
+ end
199
+
200
+ ```
201
+
202
+
165
203
  ### Using replica and cluster params in connection parameters
166
204
 
167
205
  ```yml
@@ -39,7 +39,9 @@ module ActiveRecord
39
39
  statements << accept(o.primary_keys) if o.primary_keys
40
40
 
41
41
  create_sql << "(#{statements.join(', ')})" if statements.present?
42
- add_table_options!(create_sql, table_options(o))
42
+ # Attach options for only table or materialized view
43
+ add_table_options!(create_sql, table_options(o)) if !o.view || o.view && o.materialized
44
+
43
45
  create_sql << " AS #{to_sql(o.as)}" if o.as
44
46
  create_sql
45
47
  end
@@ -35,13 +35,31 @@ module ActiveRecord
35
35
  end
36
36
 
37
37
  def integer(*args, **options)
38
- if options[:limit] == 8
39
- args.each { |name| column(name, :big_integer, options.except(:limit)) }
40
- else
41
- super
38
+ # default to unsigned
39
+ unsigned = options[:unsigned]
40
+ unsigned = true if unsigned.nil?
41
+
42
+ kind = :uint32 # default
43
+
44
+ if options[:limit]
45
+ if unsigned
46
+ kind = :uint8 if options[:limit] == 1
47
+ kind = :uint16 if options[:limit] == 2
48
+ kind = :uint32 if [3,4].include?(options[:limit])
49
+ kind = :uint64 if [5,6,7].include?(options[:limit])
50
+ kind = :big_integer if options[:limit] == 8
51
+ kind = :uint256 if options[:limit] > 8
52
+ else
53
+ kind = :int8 if options[:limit] == 1
54
+ kind = :int16 if options[:limit] == 2
55
+ kind = :int32 if [3,4].include?(options[:limit])
56
+ kind = :int64 if options[:limit] > 5 && options[:limit] <= 8
57
+ kind = :int128 if options[:limit] > 8 && options[:limit] <= 16
58
+ kind = :int256 if options[:limit] > 16
59
+ end
42
60
  end
61
+ args.each { |name| column(name, kind, options.except(:limit, :unsigned)) }
43
62
  end
44
-
45
63
  end
46
64
  end
47
65
  end
@@ -37,7 +37,7 @@ module ActiveRecord
37
37
 
38
38
  def table_options(table)
39
39
  sql = show_create_table(table)
40
- { options: sql.gsub(/^(?:.*?)ENGINE = (.*?)$/, '\\1') }
40
+ { options: sql.gsub(/^(?:.*?)(?:ENGINE = (.*?))?( AS SELECT .*?)?$/, '\\1').presence, as: sql.match(/^CREATE (?:.*?) AS (SELECT .*?)$/).try(:[], 1) }.compact
41
41
  end
42
42
 
43
43
  # Not indexes on clickhouse
@@ -79,7 +79,6 @@ module ActiveRecord
79
79
 
80
80
  class ClickhouseAdapter < AbstractAdapter
81
81
  ADAPTER_NAME = 'Clickhouse'.freeze
82
-
83
82
  NATIVE_DATABASE_TYPES = {
84
83
  string: { name: 'String' },
85
84
  integer: { name: 'UInt32' },
@@ -88,7 +87,21 @@ module ActiveRecord
88
87
  decimal: { name: 'Decimal' },
89
88
  datetime: { name: 'DateTime' },
90
89
  date: { name: 'Date' },
91
- boolean: { name: 'UInt8' }
90
+ boolean: { name: 'UInt8' },
91
+
92
+ int8: { name: 'Int8' },
93
+ int16: { name: 'Int16' },
94
+ int32: { name: 'Int32' },
95
+ int64: { name: 'Int64' },
96
+ int128: { name: 'Int128' },
97
+ int256: { name: 'Int256' },
98
+
99
+ uint8: { name: 'UInt8' },
100
+ uint16: { name: 'UInt16' },
101
+ uint32: { name: 'UInt32' },
102
+ uint64: { name: 'UInt64' },
103
+ # uint128: { name: 'UInt128' }, not yet implemented in clickhouse
104
+ uint256: { name: 'UInt256' },
92
105
  }.freeze
93
106
 
94
107
  include Clickhouse::SchemaStatements
@@ -139,10 +152,12 @@ module ActiveRecord
139
152
  when /(Nullable)?\(?String\)?/
140
153
  super('String')
141
154
  when /(Nullable)?\(?U?Int8\)?/
142
- super('int2')
143
- when /(Nullable)?\(?U?Int(16|32)\)?/
144
- super('int4')
145
- when /(Nullable)?\(?U?Int(64)\)?/
155
+ 1
156
+ when /(Nullable)?\(?U?Int16\)?/
157
+ 2
158
+ when /(Nullable)?\(?U?Int32\)?/
159
+ nil
160
+ when /(Nullable)?\(?U?Int64\)?/
146
161
  8
147
162
  else
148
163
  super
@@ -154,14 +169,20 @@ module ActiveRecord
154
169
  register_class_with_limit m, %r(String), Type::String
155
170
  register_class_with_limit m, 'Date', Clickhouse::OID::Date
156
171
  register_class_with_limit m, 'DateTime', Clickhouse::OID::DateTime
157
- register_class_with_limit m, %r(Uint8), Type::UnsignedInteger
158
- m.alias_type 'UInt16', 'UInt8'
159
- m.alias_type 'UInt32', 'UInt8'
160
- register_class_with_limit m, %r(UInt64), Type::UnsignedInteger
172
+
161
173
  register_class_with_limit m, %r(Int8), Type::Integer
162
- m.alias_type 'Int16', 'Int8'
163
- m.alias_type 'Int32', 'Int8'
174
+ register_class_with_limit m, %r(Int16), Type::Integer
175
+ register_class_with_limit m, %r(Int32), Type::Integer
164
176
  register_class_with_limit m, %r(Int64), Type::Integer
177
+ register_class_with_limit m, %r(Int128), Type::Integer
178
+ register_class_with_limit m, %r(Int256), Type::Integer
179
+
180
+ register_class_with_limit m, %r(Uint8), Type::UnsignedInteger
181
+ register_class_with_limit m, %r(UInt16), Type::UnsignedInteger
182
+ register_class_with_limit m, %r(UInt32), Type::UnsignedInteger
183
+ register_class_with_limit m, %r(UInt64), Type::UnsignedInteger
184
+ #register_class_with_limit m, %r(UInt128), Type::UnsignedInteger #not implemnted in clickhouse
185
+ register_class_with_limit m, %r(UInt256), Type::UnsignedInteger
165
186
  end
166
187
 
167
188
  # Quoting time without microseconds
@@ -34,7 +34,7 @@ HEADER
34
34
  end
35
35
 
36
36
  def tables(stream)
37
- sorted_tables = @connection.tables.sort {|a,b| @connection.show_create_table(a).match(/^CREATE\s+(MATERIALIZED)\s+VIEW/) ? 1 : a <=> b }
37
+ sorted_tables = @connection.tables.sort {|a,b| @connection.show_create_table(a).match(/^CREATE\s+(MATERIALIZED\s+)?VIEW/) ? 1 : a <=> b }
38
38
 
39
39
  sorted_tables.each do |table_name|
40
40
  table(table_name, stream) unless ignored?(table_name)
@@ -50,7 +50,7 @@ HEADER
50
50
  # super(table.gsub(/^\.inner\./, ''), stream)
51
51
 
52
52
  # detect view table
53
- match = sql.match(/^CREATE\s+(MATERIALIZED)\s+VIEW/)
53
+ match = sql.match(/^CREATE\s+(MATERIALIZED\s+)?VIEW/)
54
54
  end
55
55
 
56
56
  # Copy from original dumper
@@ -138,5 +138,16 @@ HEADER
138
138
  return nil if column.type == :float
139
139
  super
140
140
  end
141
+
142
+ def schema_unsigned(column)
143
+ return nil unless column.type == :integer && !simple
144
+ (column.sql_type =~ /(Nullable)?\(?UInt\d+\)?/).nil? ? false : nil
145
+ end
146
+
147
+ def prepare_column_options(column)
148
+ spec = {}
149
+ spec[:unsigned] = schema_unsigned(column)
150
+ spec.merge(super).compact
151
+ end
141
152
  end
142
153
  end
@@ -1,3 +1,3 @@
1
1
  module ClickhouseActiverecord
2
- VERSION = '0.4.9'
2
+ VERSION = '0.4.10'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clickhouse-activerecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.9
4
+ version: 0.4.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sergey Odintsov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-03-09 00:00:00.000000000 Z
11
+ date: 2021-03-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler