activerecord-cockroachdb-adapter 6.1.1 → 6.1.5

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: e12a061e79d389fd1c698456bf368bb8a2971d3c8e1580242aadb669bfa30809
4
- data.tar.gz: e12b269976f47ff593b3ece0f7848e56b76dda1d6a797dc826c483d301dc3082
3
+ metadata.gz: 91f5211d32cfc503198148dab27748e66dc7fd86bd7d1916ed78a59879cc7235
4
+ data.tar.gz: 69d4191eef0d08f6a472317413eb16abfcdb548e058c6d1074ca34c1a5ad21d4
5
5
  SHA512:
6
- metadata.gz: 52a6c9404a44dac790e2e7c61548d703d53f27c9654d492e9e58ba2b0f20cd7d93f9c92d26391038eccb590695b71c90d15872d44e299fd7a4e6e3f1185a2986
7
- data.tar.gz: fff215842d13491523a7001273df0abec8a95b31294c71b6873f1c604e77f3b43d98beac514bca747ef8bd55aec9160e2ff47cfb7181eac1e230a8a9d16ec6a7
6
+ metadata.gz: a8702aea7fd32df17b58c68d5a29df99c3514784bb876dc1d49c36b98f824f8200a02e74f4f543ec51aaa1d8ff5da14729e155ee5b1223e0944a5768df309244
7
+ data.tar.gz: 5980c011b221d6b23b96b7f0e4ec0050a991a83235ac975783b67d8543638e1e7b75b47e870ee720c0e4584ec739f312d2946aff8a1580dba46c49a6dab001d9
data/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## 6.1.5 - 2022-02-08
4
+
5
+ - Support `atttypmod` being sent for DECIMAL types.
6
+ This is needed for CockroachDB v22.1.
7
+
8
+ ## 6.1.4 - 2021-12-09
9
+
10
+ - Add support for CockroachDB v21.2.
11
+
12
+ ## 6.1.3 - 2021-07-28
13
+
14
+ - Santitize the input to the telemetry query that is issued on startup.
15
+
16
+ ## 6.1.2 - 2021-05-20
17
+
18
+ - Fix a bug where starting the driver can result in a ConnectionNotEstablished error.
19
+
20
+ ## 6.1.1 - 2021-05-14
21
+
22
+ - Fix a bug where starting the driver can result in a NoDatabaseError.
23
+
3
24
  ## 6.1.0 - 2021-04-26
4
25
 
5
26
  - Add a telemetry query on start-up. This helps the Cockroach Labs team
@@ -1,10 +1,14 @@
1
1
  # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
2
+
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
 
6
+ require './lib/version.rb'
7
+ version = ActiveRecord::COCKROACH_DB_ADAPTER_VERSION
8
+
5
9
  Gem::Specification.new do |spec|
6
10
  spec.name = "activerecord-cockroachdb-adapter"
7
- spec.version = "6.1.1"
11
+ spec.version = version
8
12
  spec.licenses = ["Apache-2.0"]
9
13
  spec.authors = ["Cockroach Labs"]
10
14
  spec.email = ["cockroach-db@googlegroups.com"]
data/build/Dockerfile CHANGED
@@ -4,7 +4,7 @@
4
4
  FROM cockroachdb/example-orms-builder:20200413-1918
5
5
 
6
6
  # Native dependencies for libxml-ruby and sqlite3.
7
- RUN apt-get update -y && apt-get install -y \
7
+ RUN apt-get --allow-releaseinfo-change update -y && apt-get install -y \
8
8
  libxslt-dev \
9
9
  libxml2-dev \
10
10
  libsqlite3-dev \
@@ -3,7 +3,7 @@
3
3
  set -euox pipefail
4
4
 
5
5
  # Download CockroachDB
6
- VERSION=v20.2.3
6
+ VERSION=v21.2.5
7
7
  wget -qO- https://binaries.cockroachdb.com/cockroach-$VERSION.linux-amd64.tgz | tar xvz
8
8
  readonly COCKROACH=./cockroach-$VERSION.linux-amd64/cockroach
9
9
 
@@ -35,7 +35,28 @@ run_cockroach() {
35
35
  cockroach sql --insecure -e 'CREATE DATABASE activerecord_unittest2;'
36
36
  cockroach sql --insecure -e 'SET CLUSTER SETTING sql.stats.automatic_collection.enabled = false;'
37
37
  cockroach sql --insecure -e 'SET CLUSTER SETTING sql.stats.histogram_collection.enabled = false;'
38
- cockroach sql --insecure -e "SET CLUSTER SETTING jobs.retention_time = '180s';"
38
+
39
+ cockroach sql --insecure -e "ALTER RANGE default CONFIGURE ZONE USING num_replicas = 1, gc.ttlseconds = 30;"
40
+ cockroach sql --insecure -e "ALTER TABLE system.public.jobs CONFIGURE ZONE USING num_replicas = 1, gc.ttlseconds = 30;"
41
+ cockroach sql --insecure -e "ALTER RANGE meta CONFIGURE ZONE USING num_replicas = 1, gc.ttlseconds = 30;"
42
+ cockroach sql --insecure -e "ALTER RANGE system CONFIGURE ZONE USING num_replicas = 1, gc.ttlseconds = 30;"
43
+ cockroach sql --insecure -e "ALTER RANGE liveness CONFIGURE ZONE USING num_replicas = 1, gc.ttlseconds = 30;"
44
+
45
+ cockroach sql --insecure -e "SET CLUSTER SETTING kv.range_merge.queue_interval = '50ms'"
46
+ cockroach sql --insecure -e "SET CLUSTER SETTING kv.raft_log.disable_synchronization_unsafe = 'true'"
47
+ cockroach sql --insecure -e "SET CLUSTER SETTING jobs.registry.interval.cancel = '180s';"
48
+ cockroach sql --insecure -e "SET CLUSTER SETTING jobs.registry.interval.gc = '30s';"
49
+ cockroach sql --insecure -e "SET CLUSTER SETTING jobs.retention_time = '15s';"
50
+ cockroach sql --insecure -e "SET CLUSTER SETTING sql.stats.automatic_collection.enabled = false;"
51
+ cockroach sql --insecure -e "SET CLUSTER SETTING kv.range_split.by_load_merge_delay = '5s';"
52
+
53
+ # Enable when we test with v22.1.
54
+ # cockroach sql --insecure -e "SET CLUSTER SETTING sql.catalog.unsafe_skip_system_config_trigger.enabled = true;"
55
+
56
+ # Enable experimental features.
57
+ cockroach sql --insecure -e "SET CLUSTER SETTING sql.defaults.experimental_temporary_tables.enabled = 'true';"
58
+ cockroach sql --insecure -e "SET CLUSTER SETTING sql.defaults.datestyle.enabled = true"
59
+ cockroach sql --insecure -e "SET CLUSTER SETTING sql.defaults.intervalstyle.enabled = true;"
39
60
  }
40
61
 
41
62
  # Install ruby dependencies.
data/docker.sh CHANGED
@@ -4,10 +4,7 @@
4
4
 
5
5
  set -euox pipefail
6
6
 
7
- DOCKER_IMAGE_TAG=activerecord_test_container
8
-
9
- # Build the docker image to use.
10
- docker build -t ${DOCKER_IMAGE_TAG} build/
7
+ DOCKER_IMAGE_TAG=cockroachdb/activerecord_test_container:20210914
11
8
 
12
9
  # Absolute path to this repository.
13
10
  repo_root=$(cd "$(dirname "${0}")" && pwd)
@@ -26,7 +23,7 @@ container_root=${repo_root}/docker_root
26
23
  mkdir -p "${container_root}"/{etc,home,home/"${username}"/activerecord-cockroachdb-adapter,home/.gems}
27
24
  echo "${username}:x:${uid_gid}::/home/${username}:/bin/bash" > "${container_root}/etc/passwd"
28
25
 
29
- docker run \
26
+ exec docker run \
30
27
  --volume="${container_root}/etc/passwd:/etc/passwd" \
31
28
  --volume="${container_root}/home/${username}:/home/${username}" \
32
29
  --volume="${repo_root}:/home/${username}/activerecord-cockroachdb-adapter" \
@@ -22,7 +22,7 @@ module ActiveRecord
22
22
 
23
23
  foreign_keys.each do |foreign_key|
24
24
  begin
25
- add_foreign_key(foreign_key.from_table, foreign_key.to_table, foreign_key.options)
25
+ add_foreign_key(foreign_key.from_table, foreign_key.to_table, **foreign_key.options)
26
26
  rescue ActiveRecord::StatementInvalid => error
27
27
  if error.cause.class == PG::DuplicateObject
28
28
  # This error is safe to ignore because the yielded caller
@@ -32,6 +32,41 @@ module ActiveRecord
32
32
  end
33
33
  end
34
34
 
35
+ # override
36
+ # Modified version of the postgresql foreign_keys method.
37
+ # Replaces t2.oid::regclass::text with t2.relname since this is
38
+ # more efficient in CockroachDB.
39
+ def foreign_keys(table_name)
40
+ scope = quoted_scope(table_name)
41
+ fk_info = exec_query(<<~SQL, "SCHEMA")
42
+ SELECT t2.relname AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete, c.convalidated AS valid
43
+ FROM pg_constraint c
44
+ JOIN pg_class t1 ON c.conrelid = t1.oid
45
+ JOIN pg_class t2 ON c.confrelid = t2.oid
46
+ JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
47
+ JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
48
+ JOIN pg_namespace t3 ON c.connamespace = t3.oid
49
+ WHERE c.contype = 'f'
50
+ AND t1.relname = #{scope[:name]}
51
+ AND t3.nspname = #{scope[:schema]}
52
+ ORDER BY c.conname
53
+ SQL
54
+
55
+ fk_info.map do |row|
56
+ options = {
57
+ column: row["column"],
58
+ name: row["name"],
59
+ primary_key: row["primary_key"]
60
+ }
61
+
62
+ options[:on_delete] = extract_foreign_key_action(row["on_delete"])
63
+ options[:on_update] = extract_foreign_key_action(row["on_update"])
64
+ options[:validate] = row["valid"]
65
+
66
+ ForeignKeyDefinition.new(table_name, row["to_table"], options)
67
+ end
68
+ end
69
+
35
70
  # CockroachDB uses unique_rowid() for primary keys, not sequences. It's
36
71
  # possible to force a table to use sequences, but since it's not the
37
72
  # default behavior we'll always return nil for default_sequence_name.
@@ -17,6 +17,7 @@ require "active_record/connection_adapters/cockroachdb/oid/type_map_initializer"
17
17
  require "active_record/connection_adapters/cockroachdb/oid/spatial"
18
18
  require "active_record/connection_adapters/cockroachdb/oid/interval"
19
19
  require "active_record/connection_adapters/cockroachdb/arel_tosql"
20
+ require_relative "../../version"
20
21
 
21
22
  # Run to ignore spatial tables that will break schemna dumper.
22
23
  # Defined in ./setup.rb
@@ -45,7 +46,9 @@ module ActiveRecord
45
46
  # This rescue flow appears in new_client, but it is needed here as well
46
47
  # since Cockroach will sometimes not raise until a query is made.
47
48
  rescue ActiveRecord::StatementInvalid => error
48
- if conn_params && conn_params[:dbname] && error.cause.message.include?(conn_params[:dbname])
49
+ no_db_err_check1 = conn_params && conn_params[:dbname] && error.cause.message.include?(conn_params[:dbname])
50
+ no_db_err_check2 = conn_params && conn_params[:dbname] && error.cause.message.include?("pg_type")
51
+ if no_db_err_check1 || no_db_err_check2
49
52
  raise ActiveRecord::NoDatabaseError
50
53
  else
51
54
  raise ActiveRecord::ConnectionNotEstablished, error.message
@@ -63,13 +66,18 @@ module ActiveRecord
63
66
  adapter = pool_config.db_config.configuration_hash[:adapter]
64
67
  return if disable_telemetry || adapter != "cockroachdb"
65
68
 
66
-
67
69
  begin
68
70
  with_connection do |conn|
69
71
  if conn.active?
70
72
  begin
71
- query = "SELECT crdb_internal.increment_feature_counter('ActiveRecord %d.%d')"
72
- conn.execute(query % [ActiveRecord::VERSION::MAJOR, ActiveRecord::VERSION::MINOR])
73
+ ar_version = conn.quote("ActiveRecord %d.%d" % [ActiveRecord::VERSION::MAJOR,
74
+ ActiveRecord::VERSION::MINOR])
75
+ ar_query = "SELECT crdb_internal.increment_feature_counter(%s)" % ar_version
76
+ adapter_version = conn.quote("activerecord-cockroachdb-adapter #{ActiveRecord::COCKROACH_DB_ADAPTER_VERSION}")
77
+ adapter_query = "SELECT crdb_internal.increment_feature_counter(%s)" % adapter_version
78
+
79
+ conn.execute(ar_query)
80
+ conn.execute(adapter_query)
73
81
  rescue ActiveRecord::StatementInvalid
74
82
  # The increment_feature_counter built-in is not supported on this
75
83
  # CockroachDB version. Ignore.
@@ -78,7 +86,7 @@ module ActiveRecord
78
86
  end
79
87
  end
80
88
  end
81
- rescue ActiveRecord::NoDatabaseError
89
+ rescue StandardError
82
90
  # Prevent failures on db creation and parallel testing.
83
91
  end
84
92
  end
@@ -167,12 +175,11 @@ module ActiveRecord
167
175
  end
168
176
 
169
177
  def supports_partial_index?
170
- @crdb_version >= 202
178
+ @crdb_version >= 2020
171
179
  end
172
180
 
173
181
  def supports_expression_index?
174
- # See cockroachdb/cockroach#9682
175
- false
182
+ @crdb_version >= 2122
176
183
  end
177
184
 
178
185
  def supports_datetime_with_precision?
@@ -180,12 +187,10 @@ module ActiveRecord
180
187
  end
181
188
 
182
189
  def supports_comments?
183
- # See cockroachdb/cockroach#19472.
184
- false
190
+ @crdb_version >= 2010
185
191
  end
186
192
 
187
193
  def supports_comments_in_create?
188
- # See cockroachdb/cockroach#19472.
189
194
  false
190
195
  end
191
196
 
@@ -194,12 +199,11 @@ module ActiveRecord
194
199
  end
195
200
 
196
201
  def supports_virtual_columns?
197
- # See cockroachdb/cockroach#20882.
198
202
  false
199
203
  end
200
204
 
201
205
  def supports_string_to_array_coercion?
202
- @crdb_version >= 202
206
+ @crdb_version >= 2020
203
207
  end
204
208
 
205
209
  def supports_partitioned_indexes?
@@ -230,15 +234,31 @@ module ActiveRecord
230
234
  elsif crdb_version_string.include? "v2."
231
235
  version_num 2
232
236
  elsif crdb_version_string.include? "v19.1."
233
- version_num = 191
237
+ version_num = 1910
234
238
  elsif crdb_version_string.include? "v19.2."
235
- version_num = 192
239
+ version_num = 1920
236
240
  elsif crdb_version_string.include? "v20.1."
237
- version_num = 201
241
+ version_num = 2010
242
+ elsif crdb_version_string.include? "v20.2."
243
+ version_num = 2020
244
+ elsif crdb_version_string.include? "v21.1."
245
+ version_num = 2110
246
+ elsif crdb_version_string.include? "v21.2.0"
247
+ version_num = 2120
238
248
  else
239
- version_num = 202
249
+ version_num = 2121
240
250
  end
241
251
  @crdb_version = version_num
252
+
253
+ # NOTE: this is normally in configure_connection, but that is run
254
+ # before crdb_version is determined. Once all supported versions
255
+ # of CockroachDB support SET intervalstyle it can safely be moved
256
+ # back.
257
+ # Set interval output format to ISO 8601 for ease of parsing by ActiveSupport::Duration.parse
258
+ if @crdb_version >= 2120
259
+ execute("SET intervalstyle_enabled = true", "SCHEMA")
260
+ execute("SET intervalstyle = iso_8601", "SCHEMA")
261
+ end
242
262
  end
243
263
 
244
264
  def self.database_exists?(config)
@@ -277,9 +297,19 @@ module ActiveRecord
277
297
  precision = extract_precision(sql_type)
278
298
  scale = extract_scale(sql_type)
279
299
 
300
+
301
+ # The type for the numeric depends on the width of the field,
302
+ # so we'll do something special here.
303
+ #
304
+ # When dealing with decimal columns:
305
+ #
306
+ # places after decimal = fmod - 4 & 0xffff
307
+ # places before decimal = (fmod - 4) >> 16 & 0xffff
308
+ #
309
+ # For older versions of CockroachDB (<v22.1), fmod is -1 for 0 width.
280
310
  # If fmod is -1, that means that precision is defined but not
281
311
  # scale, or neither is defined.
282
- if fmod && fmod == -1 && !precision.nil?
312
+ if fmod && ((fmod == -1 && !precision.nil?) || (fmod - 4 & 0xffff).zero?)
283
313
  # Below comment is from ActiveRecord
284
314
  # FIXME: Remove this class, and the second argument to
285
315
  # lookups on PG
@@ -346,7 +376,8 @@ module ActiveRecord
346
376
  super ||
347
377
  extract_escaped_string_from_default(default) ||
348
378
  extract_time_from_default(default) ||
349
- extract_empty_array_from_default(default)
379
+ extract_empty_array_from_default(default) ||
380
+ extract_decimal_from_default(default)
350
381
  end
351
382
 
352
383
  # Both PostgreSQL and CockroachDB use C-style string escapes under the
@@ -397,6 +428,14 @@ module ActiveRecord
397
428
  return "{}"
398
429
  end
399
430
 
431
+ # This method exists to extract the decimal defaults (e.g. scientific notation)
432
+ # that don't get parsed correctly
433
+ def extract_decimal_from_default(default)
434
+ Float(default).to_s
435
+ rescue
436
+ nil
437
+ end
438
+
400
439
  # override
401
440
  # This method makes a query to gather information about columns
402
441
  # in a table. It returns an array of arrays (one for each col) and
@@ -410,7 +449,21 @@ module ActiveRecord
410
449
  #
411
450
  # @see: https://github.com/rails/rails/blob/8695b028261bdd244e254993255c6641bdbc17a5/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L829
412
451
  def column_definitions(table_name)
413
- fields = super
452
+ fields = query(<<~SQL, "SCHEMA")
453
+ SELECT a.attname, format_type(a.atttypid, a.atttypmod),
454
+ pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
455
+ c.collname, NULL AS comment,
456
+ #{supports_virtual_columns? ? 'attgenerated' : quote('')} as attgenerated
457
+ FROM pg_attribute a
458
+ LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
459
+ LEFT JOIN pg_type t ON a.atttypid = t.oid
460
+ LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation
461
+ WHERE a.attrelid = #{quote(quote_table_name(table_name))}::regclass
462
+ AND a.attnum > 0 AND NOT a.attisdropped
463
+ ORDER BY a.attnum
464
+ SQL
465
+
466
+ crdb_fields = crdb_column_definitions(table_name)
414
467
 
415
468
  # Use regex comparison because if a type is an array it will
416
469
  # have [] appended to the end of it.
@@ -420,32 +473,33 @@ module ActiveRecord
420
473
  /interval/,
421
474
  /numeric/
422
475
  ]
476
+
423
477
  re = Regexp.union(target_types)
424
478
  fields.map do |field|
425
479
  dtype = field[1]
426
- if re.match(dtype)
427
- crdb_column_definition(field, table_name)
428
- else
429
- field
430
- end
480
+ field[1] = crdb_fields[field[0]][2].downcase if re.match(dtype)
481
+ field[7] = crdb_fields[field[0]][1]&.gsub!(/^\'|\'?$/, '')
482
+ field
431
483
  end
432
484
  end
433
485
 
486
+ # Fetch the column comment because it's faster this way
434
487
  # Use the crdb_sql_type instead of the sql_type returned by
435
488
  # column_definitions. This will include limit,
436
489
  # precision, and scale information in the type.
437
490
  # Ex. geometry -> geometry(point, 4326)
438
- def crdb_column_definition(field, table_name)
439
- col_name = field[0]
440
- data_type = \
491
+ def crdb_column_definitions(table_name)
492
+ fields = \
441
493
  query(<<~SQL, "SCHEMA")
442
- SELECT c.crdb_sql_type
494
+ SELECT c.column_name, c.column_comment, c.crdb_sql_type
443
495
  FROM information_schema.columns c
444
496
  WHERE c.table_name = #{quote(table_name)}
445
- AND c.column_name = #{quote(col_name)}
446
497
  SQL
447
- field[1] = data_type[0][0].downcase
448
- field
498
+
499
+ fields.reduce({}) do |a, e|
500
+ a[e[0]] = e
501
+ a
502
+ end
449
503
  end
450
504
 
451
505
  # override
data/lib/version.rb ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ COCKROACH_DB_ADAPTER_VERSION = "6.1.5"
5
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-cockroachdb-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.1.1
4
+ version: 6.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cockroach Labs
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-05-14 00:00:00.000000000 Z
11
+ date: 2022-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -95,12 +95,13 @@ files:
95
95
  - lib/active_record/connection_adapters/cockroachdb/type.rb
96
96
  - lib/active_record/connection_adapters/cockroachdb_adapter.rb
97
97
  - lib/activerecord-cockroachdb-adapter.rb
98
+ - lib/version.rb
98
99
  homepage: https://github.com/cockroachdb/activerecord-cockroachdb-adapter
99
100
  licenses:
100
101
  - Apache-2.0
101
102
  metadata:
102
103
  allowed_push_host: https://rubygems.org
103
- post_install_message:
104
+ post_install_message:
104
105
  rdoc_options: []
105
106
  require_paths:
106
107
  - lib
@@ -115,8 +116,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
115
116
  - !ruby/object:Gem::Version
116
117
  version: '0'
117
118
  requirements: []
118
- rubygems_version: 3.0.3
119
- signing_key:
119
+ rubygems_version: 3.1.6
120
+ signing_key:
120
121
  specification_version: 4
121
122
  summary: CockroachDB adapter for ActiveRecord.
122
123
  test_files: []