activerecord-cockroachdb-adapter 6.1.1 → 6.1.5

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 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: []