activerecord-cockroachdb-adapter 6.1.0 → 6.1.4

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: 50e75b02ff521bc6e8988549a1ceaa7bbd8ed3eddb138e3fdd6f0d7f91b50e23
4
- data.tar.gz: f67eac0c8dce552a8c5270d6c0740281fb9853ccde09ed53ebfc4bac21904cc7
3
+ metadata.gz: ee61867492cc8b0c28f58b9090625a08914e610e6a1732924a2b4d925a01a714
4
+ data.tar.gz: d7ae4281ca3738f92e84df29243c687693cf8aed64ba006d9c44541c25ba2029
5
5
  SHA512:
6
- metadata.gz: 5ee1478689e350aeb60b9397c106c3576582d9ac8d33af80b4e721f5dfb6aa1509c149250f16869db85fe5ff5b3db3542da0575ad95517681d55fa77db815b19
7
- data.tar.gz: 57ba40b8ca956807626b147592f55b1b193fffbcc5947ea47a11e1830f42a231a08dc0393c3f80fded3035b1897b0fa5579f37da27e97f83809946c692156766
6
+ metadata.gz: c61ca3b032274dc8cc5063e55465fdc2b418bbda7c6d8a4093405d61c5c2b49758faaf77f95a76eb0c46101e3ec0a4f9c1442744abe49bcc747a0b86de64bec9
7
+ data.tar.gz: f91ea52d72dcef0c50e87186b12f10c7118882e48e10ef667c64e59da159493ea8dd23b5bbb4256c9222d703afaf89d7554831d2ef523096151af9fdf9faaf9f
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 6.1.4 - 2021-12-09
4
+
5
+ - Add support for CockroachDB v21.2.
6
+
7
+ ## 6.1.3 - 2021-07-28
8
+
9
+ - Santitize the input to the telemetry query that is issued on startup.
10
+
11
+ ## 6.1.2 - 2021-05-20
12
+
13
+ - Fix a bug where starting the driver can result in a ConnectionNotEstablished error.
14
+
15
+ ## 6.1.1 - 2021-05-14
16
+
17
+ - Fix a bug where starting the driver can result in a NoDatabaseError.
18
+
3
19
  ## 6.1.0 - 2021-04-26
4
20
 
5
21
  - Add a telemetry query on start-up. This helps the Cockroach Labs team
data/README.md CHANGED
@@ -1,16 +1,18 @@
1
1
  # ActiveRecord CockroachDB Adapter
2
2
 
3
- CockroachDB adapter for ActiveRecord 4 and 5. This is a lightweight extension of the PostgreSQL adapter that establishes compatibility with [CockroachDB](https://github.com/cockroachdb/cockroach).
3
+ CockroachDB adapter for ActiveRecord 5 and 6. This is a lightweight extension of the PostgreSQL adapter that establishes compatibility with [CockroachDB](https://github.com/cockroachdb/cockroach).
4
4
 
5
5
  ## Installation
6
6
 
7
7
  Add this line to your project's Gemfile:
8
8
 
9
9
  ```ruby
10
- gem 'activerecord-cockroachdb-adapter', '~> 5.2.0'
10
+ gem 'activerecord-cockroachdb-adapter', '~> 6.1.0'
11
11
  ```
12
12
 
13
- If you're using Rails 4.x, use the `0.1.x` versions of this gem.
13
+ If you're using Rails 5.2, use the `5.2.x` versions of this gem.
14
+
15
+ If you're using Rails 6.0, use the `6.0.x` versions of this gem.
14
16
 
15
17
  In `database.yml`, use the following adapter setting:
16
18
 
@@ -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.0"
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.0
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
 
@@ -36,6 +36,7 @@ run_cockroach() {
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
38
  cockroach sql --insecure -e "SET CLUSTER SETTING jobs.retention_time = '180s';"
39
+ cockroach sql --insecure -e "SET CLUSTER SETTING sql.defaults.experimental_temporary_tables.enabled = 'true'"
39
40
  }
40
41
 
41
42
  # 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,18 +66,28 @@ module ActiveRecord
63
66
  adapter = pool_config.db_config.configuration_hash[:adapter]
64
67
  return if disable_telemetry || adapter != "cockroachdb"
65
68
 
66
- with_connection do |conn|
67
- if conn.active?
68
- begin
69
- query = "SELECT crdb_internal.increment_feature_counter('ActiveRecord %d.%d')"
70
- conn.execute(query % [ActiveRecord::VERSION::MAJOR, ActiveRecord::VERSION::MINOR])
71
- rescue ActiveRecord::StatementInvalid
72
- # The increment_feature_counter built-in is not supported on this
73
- # CockroachDB version. Ignore.
74
- rescue StandardError => e
75
- conn.logger.warn "Unexpected error when incrementing feature counter: #{e}"
69
+ begin
70
+ with_connection do |conn|
71
+ if conn.active?
72
+ begin
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)
81
+ rescue ActiveRecord::StatementInvalid
82
+ # The increment_feature_counter built-in is not supported on this
83
+ # CockroachDB version. Ignore.
84
+ rescue StandardError => e
85
+ conn.logger.warn "Unexpected error when incrementing feature counter: #{e}"
86
+ end
76
87
  end
77
88
  end
89
+ rescue StandardError
90
+ # Prevent failures on db creation and parallel testing.
78
91
  end
79
92
  end
80
93
  end
@@ -98,7 +111,7 @@ module ActiveRecord
98
111
  st_polygon: {},
99
112
  }
100
113
 
101
- # http://postgis.17.x6.nabble.com/Default-SRID-td5001115.html
114
+ # http://postgis.17.x6.nabble.com/Default-SRID-td5001115.html
102
115
  DEFAULT_SRID = 0
103
116
 
104
117
  include CockroachDB::SchemaStatements
@@ -162,12 +175,11 @@ module ActiveRecord
162
175
  end
163
176
 
164
177
  def supports_partial_index?
165
- @crdb_version >= 202
178
+ @crdb_version >= 2020
166
179
  end
167
180
 
168
181
  def supports_expression_index?
169
- # See cockroachdb/cockroach#9682
170
- false
182
+ @crdb_version >= 2122
171
183
  end
172
184
 
173
185
  def supports_datetime_with_precision?
@@ -175,12 +187,10 @@ module ActiveRecord
175
187
  end
176
188
 
177
189
  def supports_comments?
178
- # See cockroachdb/cockroach#19472.
179
- false
190
+ @crdb_version >= 2010
180
191
  end
181
192
 
182
193
  def supports_comments_in_create?
183
- # See cockroachdb/cockroach#19472.
184
194
  false
185
195
  end
186
196
 
@@ -189,12 +199,11 @@ module ActiveRecord
189
199
  end
190
200
 
191
201
  def supports_virtual_columns?
192
- # See cockroachdb/cockroach#20882.
193
202
  false
194
203
  end
195
204
 
196
205
  def supports_string_to_array_coercion?
197
- @crdb_version >= 202
206
+ @crdb_version >= 2020
198
207
  end
199
208
 
200
209
  def supports_partitioned_indexes?
@@ -225,15 +234,31 @@ module ActiveRecord
225
234
  elsif crdb_version_string.include? "v2."
226
235
  version_num 2
227
236
  elsif crdb_version_string.include? "v19.1."
228
- version_num = 191
237
+ version_num = 1910
229
238
  elsif crdb_version_string.include? "v19.2."
230
- version_num = 192
239
+ version_num = 1920
231
240
  elsif crdb_version_string.include? "v20.1."
232
- 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
233
248
  else
234
- version_num = 202
249
+ version_num = 2121
235
250
  end
236
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
237
262
  end
238
263
 
239
264
  def self.database_exists?(config)
@@ -272,12 +297,9 @@ module ActiveRecord
272
297
  precision = extract_precision(sql_type)
273
298
  scale = extract_scale(sql_type)
274
299
 
275
- # TODO(#178) this should never use DecimalWithoutScale since scale
276
- # is assumed to be 0 if it is not explicitly defined.
277
- #
278
300
  # If fmod is -1, that means that precision is defined but not
279
301
  # scale, or neither is defined.
280
- if fmod && fmod == -1
302
+ if fmod && fmod == -1 && !precision.nil?
281
303
  # Below comment is from ActiveRecord
282
304
  # FIXME: Remove this class, and the second argument to
283
305
  # lookups on PG
@@ -344,7 +366,8 @@ module ActiveRecord
344
366
  super ||
345
367
  extract_escaped_string_from_default(default) ||
346
368
  extract_time_from_default(default) ||
347
- extract_empty_array_from_default(default)
369
+ extract_empty_array_from_default(default) ||
370
+ extract_decimal_from_default(default)
348
371
  end
349
372
 
350
373
  # Both PostgreSQL and CockroachDB use C-style string escapes under the
@@ -390,11 +413,19 @@ module ActiveRecord
390
413
  # In general, it is hard to parse that, but it is easy to handle the common
391
414
  # case of an empty array.
392
415
  def extract_empty_array_from_default(default)
393
- return unless supports_string_to_array_coercion?
416
+ return unless supports_string_to_array_coercion?
394
417
  return unless default =~ /\AARRAY\[\]\z/
395
418
  return "{}"
396
419
  end
397
420
 
421
+ # This method exists to extract the decimal defaults (e.g. scientific notation)
422
+ # that don't get parsed correctly
423
+ def extract_decimal_from_default(default)
424
+ Float(default).to_s
425
+ rescue
426
+ nil
427
+ end
428
+
398
429
  # override
399
430
  # This method makes a query to gather information about columns
400
431
  # in a table. It returns an array of arrays (one for each col) and
@@ -408,7 +439,21 @@ module ActiveRecord
408
439
  #
409
440
  # @see: https://github.com/rails/rails/blob/8695b028261bdd244e254993255c6641bdbc17a5/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L829
410
441
  def column_definitions(table_name)
411
- fields = super
442
+ fields = query(<<~SQL, "SCHEMA")
443
+ SELECT a.attname, format_type(a.atttypid, a.atttypmod),
444
+ pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
445
+ c.collname, NULL AS comment,
446
+ #{supports_virtual_columns? ? 'attgenerated' : quote('')} as attgenerated
447
+ FROM pg_attribute a
448
+ LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
449
+ LEFT JOIN pg_type t ON a.atttypid = t.oid
450
+ LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation
451
+ WHERE a.attrelid = #{quote(quote_table_name(table_name))}::regclass
452
+ AND a.attnum > 0 AND NOT a.attisdropped
453
+ ORDER BY a.attnum
454
+ SQL
455
+
456
+ crdb_fields = crdb_column_definitions(table_name)
412
457
 
413
458
  # Use regex comparison because if a type is an array it will
414
459
  # have [] appended to the end of it.
@@ -418,32 +463,33 @@ module ActiveRecord
418
463
  /interval/,
419
464
  /numeric/
420
465
  ]
466
+
421
467
  re = Regexp.union(target_types)
422
468
  fields.map do |field|
423
469
  dtype = field[1]
424
- if re.match(dtype)
425
- crdb_column_definition(field, table_name)
426
- else
427
- field
428
- end
470
+ field[1] = crdb_fields[field[0]][2].downcase if re.match(dtype)
471
+ field[7] = crdb_fields[field[0]][1]&.gsub!(/^\'|\'?$/, '')
472
+ field
429
473
  end
430
474
  end
431
475
 
476
+ # Fetch the column comment because it's faster this way
432
477
  # Use the crdb_sql_type instead of the sql_type returned by
433
478
  # column_definitions. This will include limit,
434
479
  # precision, and scale information in the type.
435
480
  # Ex. geometry -> geometry(point, 4326)
436
- def crdb_column_definition(field, table_name)
437
- col_name = field[0]
438
- data_type = \
481
+ def crdb_column_definitions(table_name)
482
+ fields = \
439
483
  query(<<~SQL, "SCHEMA")
440
- SELECT c.crdb_sql_type
484
+ SELECT c.column_name, c.column_comment, c.crdb_sql_type
441
485
  FROM information_schema.columns c
442
486
  WHERE c.table_name = #{quote(table_name)}
443
- AND c.column_name = #{quote(col_name)}
444
487
  SQL
445
- field[1] = data_type[0][0].downcase
446
- field
488
+
489
+ fields.reduce({}) do |a, e|
490
+ a[e[0]] = e
491
+ a
492
+ end
447
493
  end
448
494
 
449
495
  # 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.4"
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.0
4
+ version: 6.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cockroach Labs
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-04-26 00:00:00.000000000 Z
11
+ date: 2021-12-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -95,6 +95,7 @@ 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
@@ -115,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
115
116
  - !ruby/object:Gem::Version
116
117
  version: '0'
117
118
  requirements: []
118
- rubygems_version: 3.1.4
119
+ rubygems_version: 3.1.6
119
120
  signing_key:
120
121
  specification_version: 4
121
122
  summary: CockroachDB adapter for ActiveRecord.