clickhouse-activerecord 0.4.3 → 0.4.8
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/CHANGELOG.md +1 -1
- data/lib/active_record/connection_adapters/clickhouse/schema_creation.rb +23 -2
- data/lib/active_record/connection_adapters/clickhouse/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/clickhouse/schema_statements.rb +3 -1
- data/lib/active_record/connection_adapters/clickhouse_adapter.rb +30 -3
- data/lib/clickhouse-activerecord/migration.rb +2 -2
- data/lib/clickhouse-activerecord/schema_dumper.rb +20 -10
- data/lib/clickhouse-activerecord/version.rb +1 -1
- data/lib/tasks/clickhouse.rake +2 -1
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dd2cc6144472b64d9ffe1c8b61bc86e75cc74863566aa65ff9f86ffd526d9ff4
|
4
|
+
data.tar.gz: 34e95e5728a4d90c69e7f604eac303174a0c873cae7e503f7edcca36e8ab9c5f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3638e95511941d90a06a9df8c2d640ef68742fb54474ddf289d1d136a077bae0e1510cfd9752029d6654f4e2777b865ea5ed0d6703fdb31f64ab23fca7a500b1
|
7
|
+
data.tar.gz: 650b30cfc25416e6d0cce0fe4b48146c55a256e7a9a0df61b2addaf55ca5e7533f0e8facc5599030ddaaa93bc5a07cea498390d9ad750ba77650fec914a5f476
|
data/CHANGELOG.md
CHANGED
@@ -6,15 +6,17 @@ module ActiveRecord
|
|
6
6
|
class SchemaCreation < AbstractAdapter::SchemaCreation# :nodoc:
|
7
7
|
|
8
8
|
def visit_AddColumnDefinition(o)
|
9
|
-
+"ADD COLUMN #{accept(o.column)}"
|
9
|
+
sql = +"ADD COLUMN #{accept(o.column)}"
|
10
|
+
sql << " AFTER " + quote_column_name(o.column.options[:after]) if o.column.options.key?(:after)
|
11
|
+
sql
|
10
12
|
end
|
11
13
|
|
12
14
|
def add_column_options!(sql, options)
|
13
|
-
sql << " DEFAULT #{quote_default_expression(options[:default], options[:column])}" if options_include_default?(options)
|
14
15
|
if options[:null] || options[:null].nil?
|
15
16
|
sql.gsub!(/\s+(.*)/, ' Nullable(\1)')
|
16
17
|
end
|
17
18
|
sql.gsub!(/(\sString)\(\d+\)/, '\1')
|
19
|
+
sql << " DEFAULT #{quote_default_expression(options[:default], options[:column])}" if options_include_default?(options)
|
18
20
|
sql
|
19
21
|
end
|
20
22
|
|
@@ -47,6 +49,25 @@ module ActiveRecord
|
|
47
49
|
" TEMPORARY" if o.temporary
|
48
50
|
" MATERIALIZED" if o.materialized
|
49
51
|
end
|
52
|
+
|
53
|
+
def visit_ChangeColumnDefinition(o)
|
54
|
+
column = o.column
|
55
|
+
column.sql_type = type_to_sql(column.type, column.options)
|
56
|
+
options = column_options(column)
|
57
|
+
|
58
|
+
quoted_column_name = quote_column_name(o.name)
|
59
|
+
type = column.sql_type
|
60
|
+
type = "Nullable(#{type})" if options[:null]
|
61
|
+
change_column_sql = +"MODIFY COLUMN #{quoted_column_name} #{type}"
|
62
|
+
|
63
|
+
if options.key?(:default)
|
64
|
+
quoted_default = quote_default_expression(options[:default], column)
|
65
|
+
change_column_sql << " DEFAULT #{quoted_default}"
|
66
|
+
end
|
67
|
+
|
68
|
+
change_column_sql
|
69
|
+
end
|
70
|
+
|
50
71
|
end
|
51
72
|
end
|
52
73
|
end
|
@@ -36,7 +36,7 @@ module ActiveRecord
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def table_options(table)
|
39
|
-
sql =
|
39
|
+
sql = show_create_table(table)
|
40
40
|
{ options: sql.gsub(/^(?:.*?)ENGINE = (.*?)$/, '\\1') }
|
41
41
|
end
|
42
42
|
|
@@ -156,6 +156,8 @@ module ActiveRecord
|
|
156
156
|
when "true".freeze, "false".freeze
|
157
157
|
default
|
158
158
|
# Object identifier types
|
159
|
+
when "''"
|
160
|
+
''
|
159
161
|
when /\A-?\d+\z/
|
160
162
|
$1
|
161
163
|
else
|
@@ -201,11 +201,17 @@ module ActiveRecord
|
|
201
201
|
ClickhouseActiverecord::SchemaDumper.create(self, options)
|
202
202
|
end
|
203
203
|
|
204
|
+
# @param [String] table
|
205
|
+
# @return [String]
|
206
|
+
def show_create_table(table)
|
207
|
+
do_system_execute("SHOW CREATE TABLE `#{table}`")['data'].try(:first).try(:first).gsub(/[\n\s]+/m, ' ')
|
208
|
+
end
|
209
|
+
|
204
210
|
# Create a new ClickHouse database.
|
205
211
|
def create_database(name)
|
206
212
|
sql = apply_cluster "CREATE DATABASE #{quote_table_name(name)}"
|
207
213
|
log_with_debug(sql, adapter_name) do
|
208
|
-
res = @connection.post("/?#{@config.except(:database).to_param}",
|
214
|
+
res = @connection.post("/?#{@config.except(:database).to_param}", sql)
|
209
215
|
process_response(res)
|
210
216
|
end
|
211
217
|
end
|
@@ -213,7 +219,7 @@ module ActiveRecord
|
|
213
219
|
def create_view(table_name, **options)
|
214
220
|
options.merge!(view: true)
|
215
221
|
options = apply_replica(table_name, options)
|
216
|
-
td = create_table_definition(table_name, options)
|
222
|
+
td = create_table_definition(apply_cluster(table_name), options)
|
217
223
|
yield td if block_given?
|
218
224
|
|
219
225
|
if options[:force]
|
@@ -225,7 +231,7 @@ module ActiveRecord
|
|
225
231
|
|
226
232
|
def create_table(table_name, **options)
|
227
233
|
options = apply_replica(table_name, options)
|
228
|
-
td = create_table_definition(table_name, options)
|
234
|
+
td = create_table_definition(apply_cluster(table_name), options)
|
229
235
|
yield td if block_given?
|
230
236
|
|
231
237
|
if options[:force]
|
@@ -252,6 +258,21 @@ module ActiveRecord
|
|
252
258
|
do_execute apply_cluster "DROP TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}"
|
253
259
|
end
|
254
260
|
|
261
|
+
def change_column(table_name, column_name, type, options = {})
|
262
|
+
result = do_execute "ALTER TABLE #{quote_table_name(table_name)} #{change_column_for_alter(table_name, column_name, type, options)}"
|
263
|
+
raise "Error parse json response: #{result}" if result.presence && !result.is_a?(Hash)
|
264
|
+
end
|
265
|
+
|
266
|
+
def change_column_null(table_name, column_name, null, default = nil)
|
267
|
+
structure = table_structure(table_name).select{|v| v[0] == column_name.to_s}.first
|
268
|
+
raise "Column #{column_name} not found in table #{table_name}" if structure.nil?
|
269
|
+
change_column table_name, column_name, structure[1].gsub(/(Nullable\()?(.*?)\)?/, '\2'), {null: null, default: default}.compact
|
270
|
+
end
|
271
|
+
|
272
|
+
def change_column_default(table_name, column_name, default)
|
273
|
+
change_column table_name, column_name, nil, {default: default}.compact
|
274
|
+
end
|
275
|
+
|
255
276
|
def cluster
|
256
277
|
@full_config[:cluster_name]
|
257
278
|
end
|
@@ -274,6 +295,12 @@ module ActiveRecord
|
|
274
295
|
result
|
275
296
|
end
|
276
297
|
|
298
|
+
def change_column_for_alter(table_name, column_name, type, options = {})
|
299
|
+
td = create_table_definition(table_name)
|
300
|
+
cd = td.new_column_definition(column_name, type, options)
|
301
|
+
schema_creation.accept(ChangeColumnDefinition.new(cd, column_name))
|
302
|
+
end
|
303
|
+
|
277
304
|
private
|
278
305
|
|
279
306
|
def connect
|
@@ -7,7 +7,7 @@ module ClickhouseActiverecord
|
|
7
7
|
unless table_exists?
|
8
8
|
version_options = connection.internal_string_options_for_primary_key
|
9
9
|
|
10
|
-
connection.create_table(table_name, id: false, options: 'ReplacingMergeTree(ver) PARTITION BY version ORDER BY (version)') do |t|
|
10
|
+
connection.create_table(table_name, id: false, options: 'ReplacingMergeTree(ver) PARTITION BY version ORDER BY (version)', if_not_exists: true) do |t|
|
11
11
|
t.string :version, version_options
|
12
12
|
t.column :active, 'Int8', null: false, default: '1'
|
13
13
|
t.datetime :ver, null: false, default: -> { 'now()' }
|
@@ -27,7 +27,7 @@ module ClickhouseActiverecord
|
|
27
27
|
unless table_exists?
|
28
28
|
key_options = connection.internal_string_options_for_primary_key
|
29
29
|
|
30
|
-
connection.create_table(table_name, id: false, options: 'MergeTree() PARTITION BY toDate(created_at) ORDER BY (created_at)') do |t|
|
30
|
+
connection.create_table(table_name, id: false, options: 'MergeTree() PARTITION BY toDate(created_at) ORDER BY (created_at)', if_not_exists: true) do |t|
|
31
31
|
t.string :key, key_options
|
32
32
|
t.string :value
|
33
33
|
t.timestamps
|
@@ -33,11 +33,19 @@ module ClickhouseActiverecord
|
|
33
33
|
HEADER
|
34
34
|
end
|
35
35
|
|
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 }
|
38
|
+
|
39
|
+
sorted_tables.each do |table_name|
|
40
|
+
table(table_name, stream) unless ignored?(table_name)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
36
44
|
def table(table, stream)
|
37
|
-
if table.match(/^\.inner
|
45
|
+
if table.match(/^\.inner/).nil?
|
38
46
|
unless simple
|
39
47
|
stream.puts " # TABLE: #{table}"
|
40
|
-
sql = @connection.
|
48
|
+
sql = @connection.show_create_table(table)
|
41
49
|
stream.puts " # SQL: #{sql.gsub(/ENGINE = Replicated(.*?)\('[^']+',\s*'[^']+',?\s?([^\)]*)?\)/, "ENGINE = \\1(\\2)")}" if sql
|
42
50
|
# super(table.gsub(/^\.inner\./, ''), stream)
|
43
51
|
|
@@ -85,13 +93,15 @@ HEADER
|
|
85
93
|
tbl.puts ", force: :cascade do |t|"
|
86
94
|
|
87
95
|
# then dump all non-primary key columns
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
96
|
+
if simple || !match
|
97
|
+
columns.each do |column|
|
98
|
+
raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
|
99
|
+
next if column.name == pk
|
100
|
+
type, colspec = column_spec(column)
|
101
|
+
tbl.print " t.#{type} #{column.name.inspect}"
|
102
|
+
tbl.print ", #{format_colspec(colspec)}" if colspec.present?
|
103
|
+
tbl.puts
|
104
|
+
end
|
95
105
|
end
|
96
106
|
|
97
107
|
indexes_in_create(table, tbl)
|
@@ -118,7 +128,7 @@ HEADER
|
|
118
128
|
|
119
129
|
def format_colspec(colspec)
|
120
130
|
if simple
|
121
|
-
super.gsub(/CAST\(([^,]
|
131
|
+
super.gsub(/CAST\('?([^,']*)'?,\s?'.*?'\)/, "\\1")
|
122
132
|
else
|
123
133
|
super
|
124
134
|
end
|
data/lib/tasks/clickhouse.rake
CHANGED
@@ -20,8 +20,9 @@ namespace :clickhouse do
|
|
20
20
|
|
21
21
|
# todo not testing
|
22
22
|
desc 'Load database schema'
|
23
|
-
task load: [:load_config, :
|
23
|
+
task load: [:load_config, :prepare_internal_metadata_table] do |t, args|
|
24
24
|
simple = ENV['simple'] || ARGV.map{|a| a.include?('--simple') ? true : nil}.compact.any? ? '_simple' : nil
|
25
|
+
ClickhouseActiverecord::SchemaMigration.drop_table
|
25
26
|
load("#{Rails.root}/db/clickhouse_schema#{simple}.rb")
|
26
27
|
end
|
27
28
|
|
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.
|
4
|
+
version: 0.4.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sergey Odintsov
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-12-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -134,7 +134,7 @@ homepage: https://github.com/pnixx/clickhouse-activerecord
|
|
134
134
|
licenses:
|
135
135
|
- MIT
|
136
136
|
metadata: {}
|
137
|
-
post_install_message:
|
137
|
+
post_install_message:
|
138
138
|
rdoc_options: []
|
139
139
|
require_paths:
|
140
140
|
- lib
|
@@ -150,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
150
150
|
version: '0'
|
151
151
|
requirements: []
|
152
152
|
rubygems_version: 3.0.1
|
153
|
-
signing_key:
|
153
|
+
signing_key:
|
154
154
|
specification_version: 4
|
155
155
|
summary: ClickHouse ActiveRecord
|
156
156
|
test_files: []
|