clickhouse-activerecord 0.4.11 → 0.5.2

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: d8d1d60f75e0f889dc5d947df77924f1490c0325f097d634048fb25405eeca70
4
- data.tar.gz: 309eda1c3f605682c04525fce8633b85a73a38643e367f33d87588939f7815fe
3
+ metadata.gz: c75ca45e5f91a7d83d79b8583539e66021589fc76c7ce48a68f07f49176a6f5a
4
+ data.tar.gz: 282fba24c4ecacdb11e4d358db15ba88beb0457099f3b9efe22d6c873676ead8
5
5
  SHA512:
6
- metadata.gz: 5727f1a23c48e04db1052bfbf4c56af412338be88f4b985ed6700e9a833436bcde893ba9cb1ed7b89473dae95b31e4b70de26c6885cce10b8fffcdb9c65fbb3d
7
- data.tar.gz: 18fad92b704c1c41b97029facbc020111c3b067cbb825d6e5c4d11d6a4b7a220873b922aea7112ec741f1d87a1a5c2217a11047e764959a2edffb98e0b7f2463
6
+ metadata.gz: 69b20ad39aced0dc3ba4f6883664dabdba45c8c677848010b1dd926e26de36a707839cbc5d806e59f0bc73a786daeee6c3448681313de0f973d93faa16f63a5d
7
+ data.tar.gz: cf195bf822304c31f3cd5121f3ca5ea0f5d5fc1b0211862e1cde9ffae32042960ad512a9c10a3a17d146205308aefdfcc09f5de95b07bab952baa9cffab4b60c
data/README.md CHANGED
@@ -35,6 +35,21 @@ default: &default
35
35
  replica_name: '{replica}' # replica macros name, optional for creating replicated tables
36
36
  ```
37
37
 
38
+ Alternatively if you wish to pass a custom `Net::HTTP` transport (or any other
39
+ object which supports a `.post()` function with the same parameters as
40
+ `Net::HTTP`'s), you can do this directly instead of specifying
41
+ `host`/`port`/`ssl`:
42
+
43
+ ```ruby
44
+ class ActionView < ActiveRecord::Base
45
+ establish_connection(
46
+ adapter: 'clickhouse',
47
+ database: 'database',
48
+ connection: Net::HTTP.start('http://example.org', 8123)
49
+ )
50
+ end
51
+ ```
52
+
38
53
  ## Usage in Rails 5
39
54
 
40
55
  Add your `database.yml` connection information with postfix `_clickhouse` for you environment:
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ module Clickhouse
6
+ module OID # :nodoc:
7
+ class Array < Type::Value # :nodoc:
8
+
9
+ def initialize(sql_type)
10
+ @subtype = case sql_type
11
+ when /U?Int\d+/
12
+ :integer
13
+ when /DateTime/
14
+ :datetime
15
+ when /Date/
16
+ :date
17
+ else
18
+ :string
19
+ end
20
+ end
21
+
22
+ def type
23
+ @subtype
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,9 +1,16 @@
1
1
  # frozen_string_literal: true
2
+ begin
3
+ require "active_record/connection_adapters/deduplicable"
4
+ rescue LoadError => e
5
+ # Rails < 6.1 does not have this file in this location, ignore
6
+ end
7
+
8
+ require "active_record/connection_adapters/abstract/schema_creation"
2
9
 
3
10
  module ActiveRecord
4
11
  module ConnectionAdapters
5
12
  module Clickhouse
6
- class SchemaCreation < AbstractAdapter::SchemaCreation# :nodoc:
13
+ class SchemaCreation < ConnectionAdapters::SchemaCreation# :nodoc:
7
14
 
8
15
  def visit_AddColumnDefinition(o)
9
16
  sql = +"ADD COLUMN #{accept(o.column)}"
@@ -15,14 +22,23 @@ module ActiveRecord
15
22
  if options[:null] || options[:null].nil?
16
23
  sql.gsub!(/\s+(.*)/, ' Nullable(\1)')
17
24
  end
25
+ if options[:array]
26
+ sql.gsub!(/\s+(.*)/, ' Array(\1)')
27
+ end
18
28
  sql.gsub!(/(\sString)\(\d+\)/, '\1')
19
29
  sql << " DEFAULT #{quote_default_expression(options[:default], options[:column])}" if options_include_default?(options)
20
30
  sql
21
31
  end
22
32
 
23
33
  def add_table_options!(create_sql, options)
24
- if options[:options].present?
25
- create_sql << " ENGINE = #{options[:options]}"
34
+ opts = options[:options]
35
+ if options.respond_to?(:options)
36
+ # rails 6.1
37
+ opts ||= options.options
38
+ end
39
+
40
+ if opts.present?
41
+ create_sql << " ENGINE = #{opts}"
26
42
  else
27
43
  create_sql << " ENGINE = Log()"
28
44
  end
@@ -37,11 +53,9 @@ module ActiveRecord
37
53
 
38
54
  statements = o.columns.map { |c| accept c }
39
55
  statements << accept(o.primary_keys) if o.primary_keys
40
-
41
56
  create_sql << "(#{statements.join(', ')})" if statements.present?
42
57
  # 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
-
58
+ add_table_options!(create_sql, o) if !o.view || o.view && o.materialized
45
59
  create_sql << " AS #{to_sql(o.as)}" if o.as
46
60
  create_sql
47
61
  end
@@ -17,8 +17,15 @@ module ActiveRecord
17
17
  def exec_query(sql, name = nil, binds = [], prepare: false)
18
18
  result = do_execute(sql, name)
19
19
  ActiveRecord::Result.new(result['meta'].map { |m| m['name'] }, result['data'])
20
- rescue StandardError => _e
21
- raise ActiveRecord::ActiveRecordError, "Response: #{result}"
20
+ rescue ActiveRecord::ActiveRecordError => e
21
+ raise e
22
+ rescue StandardError => e
23
+ raise ActiveRecord::ActiveRecordError, "Response: #{e.message}"
24
+ end
25
+
26
+ def exec_insert_all(sql, name)
27
+ do_execute(sql, name, format: nil)
28
+ true
22
29
  end
23
30
 
24
31
  def exec_update(_sql, _name = nil, _binds = [])
@@ -114,8 +121,8 @@ module ActiveRecord
114
121
  Clickhouse::SchemaCreation.new(self)
115
122
  end
116
123
 
117
- def create_table_definition(*args)
118
- Clickhouse::TableDefinition.new(self, *args)
124
+ def create_table_definition(table_name, **options)
125
+ Clickhouse::TableDefinition.new(self, table_name, **options)
119
126
  end
120
127
 
121
128
  def new_column_from_field(table_name, field)
@@ -3,6 +3,7 @@
3
3
  require 'clickhouse-activerecord/arel/visitors/to_sql'
4
4
  require 'clickhouse-activerecord/arel/table'
5
5
  require 'clickhouse-activerecord/migration'
6
+ require 'active_record/connection_adapters/clickhouse/oid/array'
6
7
  require 'active_record/connection_adapters/clickhouse/oid/date'
7
8
  require 'active_record/connection_adapters/clickhouse/oid/date_time'
8
9
  require 'active_record/connection_adapters/clickhouse/oid/big_integer'
@@ -17,9 +18,22 @@ module ActiveRecord
17
18
  # Establishes a connection to the database that's used by all Active Record objects
18
19
  def clickhouse_connection(config)
19
20
  config = config.symbolize_keys
20
- host = config[:host] || 'localhost'
21
- port = config[:port] || 8123
22
- ssl = config[:ssl].present? ? config[:ssl] : port == 443
21
+
22
+ if config[:connection]
23
+ connection = {
24
+ connection: config[:connection]
25
+ }
26
+ else
27
+ port = config[:port] || 8123
28
+ connection = {
29
+ host: config[:host] || 'localhost',
30
+ port: port,
31
+ ssl: config[:ssl].present? ? config[:ssl] : port == 443,
32
+ sslca: config[:sslca],
33
+ read_timeout: config[:read_timeout],
34
+ write_timeout: config[:write_timeout],
35
+ }
36
+ end
23
37
 
24
38
  if config.key?(:database)
25
39
  database = config[:database]
@@ -27,7 +41,7 @@ module ActiveRecord
27
41
  raise ArgumentError, 'No database specified. Missing argument: database.'
28
42
  end
29
43
 
30
- ConnectionAdapters::ClickhouseAdapter.new(logger, [host, port, ssl], { user: config[:username], password: config[:password], database: database }.compact, config)
44
+ ConnectionAdapters::ClickhouseAdapter.new(logger, connection, { user: config[:username], password: config[:password], database: database }.compact, config)
31
45
  end
32
46
  end
33
47
  end
@@ -50,7 +64,11 @@ module ActiveRecord
50
64
  module TypeCaster
51
65
  class Map
52
66
  def is_view
53
- types.is_view
67
+ if @klass.respond_to?(:is_view)
68
+ @klass.is_view # rails 6.1
69
+ else
70
+ types.is_view # less than 6.1
71
+ end
54
72
  end
55
73
  end
56
74
  end
@@ -177,12 +195,16 @@ module ActiveRecord
177
195
  register_class_with_limit m, %r(Int128), Type::Integer
178
196
  register_class_with_limit m, %r(Int256), Type::Integer
179
197
 
180
- register_class_with_limit m, %r(Uint8), Type::UnsignedInteger
198
+ register_class_with_limit m, %r(UInt8), Type::UnsignedInteger
181
199
  register_class_with_limit m, %r(UInt16), Type::UnsignedInteger
182
200
  register_class_with_limit m, %r(UInt32), Type::UnsignedInteger
183
201
  register_class_with_limit m, %r(UInt64), Type::UnsignedInteger
184
202
  #register_class_with_limit m, %r(UInt128), Type::UnsignedInteger #not implemnted in clickhouse
185
203
  register_class_with_limit m, %r(UInt256), Type::UnsignedInteger
204
+ # register_class_with_limit m, %r(Array), Clickhouse::OID::Array
205
+ m.register_type(%r(Array)) do |sql_type|
206
+ Clickhouse::OID::Array.new(sql_type)
207
+ end
186
208
  end
187
209
 
188
210
  # Quoting time without microseconds
@@ -310,6 +332,19 @@ module ActiveRecord
310
332
  cluster ? "#{sql} ON CLUSTER #{cluster}" : sql
311
333
  end
312
334
 
335
+ def supports_insert_on_duplicate_skip?
336
+ true
337
+ end
338
+
339
+ def supports_insert_on_duplicate_update?
340
+ true
341
+ end
342
+
343
+ def build_insert_sql(insert) # :nodoc:
344
+ sql = +"INSERT #{insert.into} #{insert.values_list}"
345
+ sql
346
+ end
347
+
313
348
  protected
314
349
 
315
350
  def last_inserted_id(result)
@@ -325,7 +360,13 @@ module ActiveRecord
325
360
  private
326
361
 
327
362
  def connect
328
- @connection = Net::HTTP.start(@connection_parameters[0], @connection_parameters[1], use_ssl: @connection_parameters[2], verify_mode: OpenSSL::SSL::VERIFY_NONE)
363
+ @connection = @connection_parameters[:connection] || Net::HTTP.start(@connection_parameters[:host], @connection_parameters[:port], use_ssl: @connection_parameters[:ssl], verify_mode: OpenSSL::SSL::VERIFY_NONE)
364
+
365
+ @connection.ca_file = @connection_parameters[:ca_file] if @connection_parameters[:ca_file]
366
+ @connection.read_timeout = @connection_parameters[:read_timeout] if @connection_parameters[:read_timeout]
367
+ @connection.write_timeout = @connection_parameters[:write_timeout] if @connection_parameters[:write_timeout]
368
+
369
+ @connection
329
370
  end
330
371
 
331
372
  def apply_replica(table, options)
@@ -1,3 +1,5 @@
1
+ require 'active_record/migration'
2
+
1
3
  module ClickhouseActiverecord
2
4
 
3
5
  class SchemaMigration < ::ActiveRecord::SchemaMigration
@@ -8,7 +10,7 @@ module ClickhouseActiverecord
8
10
  version_options = connection.internal_string_options_for_primary_key
9
11
 
10
12
  connection.create_table(table_name, id: false, options: 'ReplacingMergeTree(ver) PARTITION BY version ORDER BY (version)', if_not_exists: true) do |t|
11
- t.string :version, version_options
13
+ t.string :version, **version_options
12
14
  t.column :active, 'Int8', null: false, default: '1'
13
15
  t.datetime :ver, null: false, default: -> { 'now()' }
14
16
  end
@@ -144,9 +144,14 @@ HEADER
144
144
  (column.sql_type =~ /(Nullable)?\(?UInt\d+\)?/).nil? ? false : nil
145
145
  end
146
146
 
147
+ def schema_array(column)
148
+ (column.sql_type =~ /Array?\(/).nil? ? nil : true
149
+ end
150
+
147
151
  def prepare_column_options(column)
148
152
  spec = {}
149
153
  spec[:unsigned] = schema_unsigned(column)
154
+ spec[:array] = schema_array(column)
150
155
  spec.merge(super).compact
151
156
  end
152
157
  end
@@ -6,7 +6,7 @@ module ClickhouseActiverecord
6
6
  delegate :connection, :establish_connection, :clear_active_connections!, to: ActiveRecord::Base
7
7
 
8
8
  def initialize(configuration)
9
- @configuration = configuration
9
+ @configuration = configuration.with_indifferent_access
10
10
  end
11
11
 
12
12
  def create
@@ -1,3 +1,3 @@
1
1
  module ClickhouseActiverecord
2
- VERSION = '0.4.11'
2
+ VERSION = '0.5.2'
3
3
  end
@@ -13,7 +13,7 @@ class ClickhouseMigrationGenerator < ActiveRecord::Generators::MigrationGenerato
13
13
 
14
14
  def db_migrate_path
15
15
  if defined?(Rails.application) && Rails.application && respond_to?(:configured_migrate_path, true)
16
- configured_migrate_path
16
+ configured_migrate_path || default_migrate_path
17
17
  else
18
18
  default_migrate_path
19
19
  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.11
4
+ version: 0.5.2
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: 2021-03-23 00:00:00.000000000 Z
11
+ date: 2021-08-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -112,6 +112,7 @@ files:
112
112
  - bin/console
113
113
  - bin/setup
114
114
  - clickhouse-activerecord.gemspec
115
+ - lib/active_record/connection_adapters/clickhouse/oid/array.rb
115
116
  - lib/active_record/connection_adapters/clickhouse/oid/big_integer.rb
116
117
  - lib/active_record/connection_adapters/clickhouse/oid/date.rb
117
118
  - lib/active_record/connection_adapters/clickhouse/oid/date_time.rb
@@ -134,7 +135,7 @@ homepage: https://github.com/pnixx/clickhouse-activerecord
134
135
  licenses:
135
136
  - MIT
136
137
  metadata: {}
137
- post_install_message:
138
+ post_install_message:
138
139
  rdoc_options: []
139
140
  require_paths:
140
141
  - lib
@@ -149,8 +150,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
149
150
  - !ruby/object:Gem::Version
150
151
  version: '0'
151
152
  requirements: []
152
- rubygems_version: 3.0.3
153
- signing_key:
153
+ rubygems_version: 3.0.4
154
+ signing_key:
154
155
  specification_version: 4
155
156
  summary: ClickHouse ActiveRecord
156
157
  test_files: []