activerecord-cockroachdb-adapter 6.1.3 → 6.1.6
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 +4 -4
- data/CHANGELOG.md +13 -0
- data/build/Dockerfile +1 -1
- data/build/teamcity-test.sh +23 -3
- data/docker.sh +2 -5
- data/lib/active_record/connection_adapters/cockroachdb/referential_integrity.rb +1 -1
- data/lib/active_record/connection_adapters/cockroachdb/schema_statements.rb +35 -0
- data/lib/active_record/connection_adapters/cockroachdb_adapter.rb +83 -35
- data/lib/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 55fcba0c750ea29dde5f7a7efcabd35c1c81d1cbabee65ad1aeca9e16ab3e9d6
|
4
|
+
data.tar.gz: 1f3b6c480c3430c53f632d11647afc4d76b8d5a05990e3a7b7f21191f093c746
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c29d9e502572a94a2a34ddf43f9cf09aac0aca3c63b6e489844a256cbbce7728ce90280acc8153ab4114dc9721eac37f26752936d5b3418c731fee17a2c1bd98
|
7
|
+
data.tar.gz: 68943312caf4a756081d806e7e6bb29a563d396f435226f2dadf595f2068649d1877f8bd79a88f2b65df9cc57ee998b4e2f7f6a81a7589f1ef03198cd3dc3a1d
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 6.1.6 - 2022-02-25
|
4
|
+
|
5
|
+
- Fix mixed versions of CockroachDB v21.1 and v21.2 not working.
|
6
|
+
|
7
|
+
## 6.1.5 - 2022-02-08
|
8
|
+
|
9
|
+
- Support `atttypmod` being sent for DECIMAL types.
|
10
|
+
This is needed for CockroachDB v22.1.
|
11
|
+
|
12
|
+
## 6.1.4 - 2021-12-09
|
13
|
+
|
14
|
+
- Add support for CockroachDB v21.2.
|
15
|
+
|
3
16
|
## 6.1.3 - 2021-07-28
|
4
17
|
|
5
18
|
- Santitize the input to the telemetry query that is issued on startup.
|
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 \
|
data/build/teamcity-test.sh
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
set -euox pipefail
|
4
4
|
|
5
5
|
# Download CockroachDB
|
6
|
-
VERSION=v21.
|
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,8 +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
|
-
|
39
|
-
cockroach sql --insecure -e "
|
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;"
|
40
60
|
}
|
41
61
|
|
42
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.
|
@@ -46,7 +46,9 @@ module ActiveRecord
|
|
46
46
|
# This rescue flow appears in new_client, but it is needed here as well
|
47
47
|
# since Cockroach will sometimes not raise until a query is made.
|
48
48
|
rescue ActiveRecord::StatementInvalid => error
|
49
|
-
|
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
|
50
52
|
raise ActiveRecord::NoDatabaseError
|
51
53
|
else
|
52
54
|
raise ActiveRecord::ConnectionNotEstablished, error.message
|
@@ -173,12 +175,11 @@ module ActiveRecord
|
|
173
175
|
end
|
174
176
|
|
175
177
|
def supports_partial_index?
|
176
|
-
@crdb_version >=
|
178
|
+
@crdb_version >= 2020
|
177
179
|
end
|
178
180
|
|
179
181
|
def supports_expression_index?
|
180
|
-
|
181
|
-
false
|
182
|
+
@crdb_version >= 2122
|
182
183
|
end
|
183
184
|
|
184
185
|
def supports_datetime_with_precision?
|
@@ -186,7 +187,7 @@ module ActiveRecord
|
|
186
187
|
end
|
187
188
|
|
188
189
|
def supports_comments?
|
189
|
-
@crdb_version >=
|
190
|
+
@crdb_version >= 2010
|
190
191
|
end
|
191
192
|
|
192
193
|
def supports_comments_in_create?
|
@@ -198,12 +199,11 @@ module ActiveRecord
|
|
198
199
|
end
|
199
200
|
|
200
201
|
def supports_virtual_columns?
|
201
|
-
# See cockroachdb/cockroach#20882.
|
202
202
|
false
|
203
203
|
end
|
204
204
|
|
205
205
|
def supports_string_to_array_coercion?
|
206
|
-
@crdb_version >=
|
206
|
+
@crdb_version >= 2020
|
207
207
|
end
|
208
208
|
|
209
209
|
def supports_partitioned_indexes?
|
@@ -228,23 +228,37 @@ module ActiveRecord
|
|
228
228
|
def initialize(connection, logger, conn_params, config)
|
229
229
|
super(connection, logger, conn_params, config)
|
230
230
|
|
231
|
-
crdb_version_string = query_value("SHOW
|
232
|
-
if crdb_version_string.
|
231
|
+
crdb_version_string = query_value("SHOW CLUSTER SETTING version")
|
232
|
+
if crdb_version_string.start_with? "1."
|
233
233
|
version_num = 1
|
234
|
-
elsif crdb_version_string.
|
235
|
-
version_num 2
|
236
|
-
elsif crdb_version_string.
|
237
|
-
version_num =
|
238
|
-
elsif crdb_version_string.
|
239
|
-
version_num =
|
240
|
-
elsif crdb_version_string.
|
241
|
-
version_num =
|
242
|
-
elsif crdb_version_string.
|
243
|
-
version_num =
|
234
|
+
elsif crdb_version_string.start_with? "2."
|
235
|
+
version_num = 2
|
236
|
+
elsif crdb_version_string.start_with? "19.1"
|
237
|
+
version_num = 1910
|
238
|
+
elsif crdb_version_string.start_with? "19.2"
|
239
|
+
version_num = 1920
|
240
|
+
elsif crdb_version_string.start_with? "20.1"
|
241
|
+
version_num = 2010
|
242
|
+
elsif crdb_version_string.start_with? "20.2"
|
243
|
+
version_num = 2020
|
244
|
+
elsif crdb_version_string.start_with? "21.1"
|
245
|
+
version_num = 2110
|
246
|
+
elsif crdb_version_string.start_with? "21.2"
|
247
|
+
version_num = 2120
|
244
248
|
else
|
245
|
-
version_num =
|
249
|
+
version_num = 2210
|
246
250
|
end
|
247
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
|
248
262
|
end
|
249
263
|
|
250
264
|
def self.database_exists?(config)
|
@@ -283,9 +297,19 @@ module ActiveRecord
|
|
283
297
|
precision = extract_precision(sql_type)
|
284
298
|
scale = extract_scale(sql_type)
|
285
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.
|
286
310
|
# If fmod is -1, that means that precision is defined but not
|
287
311
|
# scale, or neither is defined.
|
288
|
-
if fmod && fmod == -1 && !precision.nil?
|
312
|
+
if fmod && ((fmod == -1 && !precision.nil?) || (fmod - 4 & 0xffff).zero?)
|
289
313
|
# Below comment is from ActiveRecord
|
290
314
|
# FIXME: Remove this class, and the second argument to
|
291
315
|
# lookups on PG
|
@@ -352,7 +376,8 @@ module ActiveRecord
|
|
352
376
|
super ||
|
353
377
|
extract_escaped_string_from_default(default) ||
|
354
378
|
extract_time_from_default(default) ||
|
355
|
-
extract_empty_array_from_default(default)
|
379
|
+
extract_empty_array_from_default(default) ||
|
380
|
+
extract_decimal_from_default(default)
|
356
381
|
end
|
357
382
|
|
358
383
|
# Both PostgreSQL and CockroachDB use C-style string escapes under the
|
@@ -403,6 +428,14 @@ module ActiveRecord
|
|
403
428
|
return "{}"
|
404
429
|
end
|
405
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
|
+
|
406
439
|
# override
|
407
440
|
# This method makes a query to gather information about columns
|
408
441
|
# in a table. It returns an array of arrays (one for each col) and
|
@@ -416,7 +449,21 @@ module ActiveRecord
|
|
416
449
|
#
|
417
450
|
# @see: https://github.com/rails/rails/blob/8695b028261bdd244e254993255c6641bdbc17a5/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L829
|
418
451
|
def column_definitions(table_name)
|
419
|
-
fields =
|
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)
|
420
467
|
|
421
468
|
# Use regex comparison because if a type is an array it will
|
422
469
|
# have [] appended to the end of it.
|
@@ -426,32 +473,33 @@ module ActiveRecord
|
|
426
473
|
/interval/,
|
427
474
|
/numeric/
|
428
475
|
]
|
476
|
+
|
429
477
|
re = Regexp.union(target_types)
|
430
478
|
fields.map do |field|
|
431
479
|
dtype = field[1]
|
432
|
-
if re.match(dtype)
|
433
|
-
|
434
|
-
|
435
|
-
field
|
436
|
-
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
|
437
483
|
end
|
438
484
|
end
|
439
485
|
|
486
|
+
# Fetch the column comment because it's faster this way
|
440
487
|
# Use the crdb_sql_type instead of the sql_type returned by
|
441
488
|
# column_definitions. This will include limit,
|
442
489
|
# precision, and scale information in the type.
|
443
490
|
# Ex. geometry -> geometry(point, 4326)
|
444
|
-
def
|
445
|
-
|
446
|
-
data_type = \
|
491
|
+
def crdb_column_definitions(table_name)
|
492
|
+
fields = \
|
447
493
|
query(<<~SQL, "SCHEMA")
|
448
|
-
SELECT c.crdb_sql_type
|
494
|
+
SELECT c.column_name, c.column_comment, c.crdb_sql_type
|
449
495
|
FROM information_schema.columns c
|
450
496
|
WHERE c.table_name = #{quote(table_name)}
|
451
|
-
AND c.column_name = #{quote(col_name)}
|
452
497
|
SQL
|
453
|
-
|
454
|
-
|
498
|
+
|
499
|
+
fields.reduce({}) do |a, e|
|
500
|
+
a[e[0]] = e
|
501
|
+
a
|
502
|
+
end
|
455
503
|
end
|
456
504
|
|
457
505
|
# override
|
data/lib/version.rb
CHANGED
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.
|
4
|
+
version: 6.1.6
|
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:
|
11
|
+
date: 2022-02-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -101,7 +101,7 @@ licenses:
|
|
101
101
|
- Apache-2.0
|
102
102
|
metadata:
|
103
103
|
allowed_push_host: https://rubygems.org
|
104
|
-
post_install_message:
|
104
|
+
post_install_message:
|
105
105
|
rdoc_options: []
|
106
106
|
require_paths:
|
107
107
|
- lib
|
@@ -116,8 +116,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
116
116
|
- !ruby/object:Gem::Version
|
117
117
|
version: '0'
|
118
118
|
requirements: []
|
119
|
-
rubygems_version: 3.
|
120
|
-
signing_key:
|
119
|
+
rubygems_version: 3.0.3.1
|
120
|
+
signing_key:
|
121
121
|
specification_version: 4
|
122
122
|
summary: CockroachDB adapter for ActiveRecord.
|
123
123
|
test_files: []
|