activerecord-cockroachdb-adapter 6.1.0 → 6.1.4

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: 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.