activerecord-cockroachdb-adapter 7.0.3 → 7.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.editorconfig +7 -0
- data/.github/workflows/ci.yml +43 -38
- data/.ruby-version +1 -1
- data/CHANGELOG.md +12 -0
- data/Gemfile +14 -1
- data/activerecord-cockroachdb-adapter.gemspec +1 -1
- data/bin/console +17 -33
- data/bin/console_schemas/default.rb +9 -0
- data/bin/console_schemas/schemas.rb +23 -0
- data/bin/start-cockroachdb +6 -21
- data/build/Dockerfile +1 -1
- data/lib/active_record/connection_adapters/cockroachdb/arel_tosql.rb +8 -0
- data/lib/active_record/connection_adapters/cockroachdb/column.rb +3 -7
- data/lib/active_record/connection_adapters/cockroachdb/column_methods.rb +8 -0
- data/lib/active_record/connection_adapters/cockroachdb/database_statements.rb +0 -83
- data/lib/active_record/connection_adapters/cockroachdb/database_tasks.rb +32 -24
- data/lib/active_record/connection_adapters/cockroachdb/referential_integrity.rb +14 -10
- data/lib/active_record/connection_adapters/cockroachdb/schema_statements.rb +49 -14
- data/lib/active_record/connection_adapters/cockroachdb/type.rb +3 -2
- data/lib/active_record/connection_adapters/cockroachdb_adapter.rb +116 -233
- data/lib/active_record/relation/query_methods_ext.rb +29 -1
- data/lib/arel/nodes/join_source_ext.rb +28 -0
- data/lib/version.rb +1 -1
- data/setup.sql +18 -0
- metadata +9 -5
- data/lib/active_record/connection_adapters/cockroachdb/oid/type_map_initializer.rb +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 672289521537934d4b9ed2d707c3faf55b4761c8d2b4e9e12cd8622166963ae7
|
4
|
+
data.tar.gz: 345a84d7c5bca0d574aa65eb0fb0e30986a23fcc2830f422e5b1d80ffa971076
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ce6d2119bfc27192630c32ec488b3e7f533cc64963fc04035609122e5bdbc33e75b83766ca68e3eb73e2592b2fe0a1bae53a74389527762f790b16bda687da9
|
7
|
+
data.tar.gz: 42e10ab1106e4ffc4df89bbbf98f8ddbd05b6bccf97b062a9445ebf874a8bfef9e628dce8b39c3287424a7094f70790457293a2766a849bd39ac0e20c7a684fe
|
data/.editorconfig
ADDED
data/.github/workflows/ci.yml
CHANGED
@@ -4,12 +4,9 @@
|
|
4
4
|
name: Test
|
5
5
|
|
6
6
|
on:
|
7
|
-
# Triggers the workflow on push or pull request events.
|
8
7
|
push:
|
9
|
-
|
10
|
-
|
11
|
-
branches:
|
12
|
-
- "*"
|
8
|
+
branches: [master]
|
9
|
+
# Triggers the workflow on pull request events.
|
13
10
|
pull_request:
|
14
11
|
types: [opened, reopened, synchronize]
|
15
12
|
|
@@ -18,40 +15,69 @@ on:
|
|
18
15
|
|
19
16
|
# This allows a subsequently queued workflow run to interrupt previous runs.
|
20
17
|
concurrency:
|
21
|
-
group:
|
18
|
+
group: "${{ github.workflow }} @ ${{ github.ref }}"
|
22
19
|
cancel-in-progress: true
|
23
20
|
|
24
21
|
jobs:
|
22
|
+
# Since the name of the matrix job depends on the version, we define another job with a more stable name.
|
23
|
+
test_results:
|
24
|
+
if: ${{ always() }}
|
25
|
+
runs-on: ubuntu-latest
|
26
|
+
name: Test Results
|
27
|
+
needs: [test]
|
28
|
+
steps:
|
29
|
+
- run: |
|
30
|
+
result="${{ needs.test.result }}"
|
31
|
+
if [[ $result == "success" || $result == "skipped" ]]; then
|
32
|
+
exit 0
|
33
|
+
else
|
34
|
+
exit 1
|
35
|
+
fi
|
36
|
+
|
25
37
|
test:
|
26
38
|
runs-on: ubuntu-latest
|
27
39
|
strategy:
|
40
|
+
fail-fast: false
|
28
41
|
matrix:
|
29
|
-
|
30
|
-
|
42
|
+
# https://www.cockroachlabs.com/docs/releases/release-support-policy
|
43
|
+
crdb: [v22.2, v23.1, v23.2]
|
44
|
+
ruby: [head]
|
31
45
|
name: Test (crdb=${{ matrix.crdb }} ruby=${{ matrix.ruby }})
|
32
46
|
steps:
|
33
47
|
- name: Set Up Actions
|
34
|
-
uses: actions/checkout@
|
48
|
+
uses: actions/checkout@v4
|
35
49
|
- name: Install GEOS
|
36
|
-
run: sudo apt-get install libgeos-dev
|
50
|
+
run: sudo apt-get install -yqq libgeos-dev
|
37
51
|
- name: Set Up Ruby
|
38
52
|
uses: ruby/setup-ruby@v1
|
39
53
|
with:
|
40
|
-
|
41
|
-
|
54
|
+
ruby-version: ${{ matrix.ruby }}
|
55
|
+
bundler-cache: true
|
42
56
|
- name: Install and Start Cockroachdb
|
43
57
|
run: |
|
44
58
|
# Download CockroachDB
|
45
|
-
|
59
|
+
readonly full_version=$(ruby -rnet/http -ruri -ryaml -e '
|
60
|
+
link = "https://raw.githubusercontent.com/cockroachdb/docs/main/src/current/_data/releases.yml"
|
61
|
+
puts YAML.safe_load(Net::HTTP.get(URI(link))).reverse.find {
|
62
|
+
_1["major_version"] == "${{ matrix.crdb }}" &&
|
63
|
+
_1["release_type"] == "Production" &&
|
64
|
+
!_1["cloud_only"] &&
|
65
|
+
!_1["withdrawn"] &&
|
66
|
+
!_1["release_name"].include?("-") # Pre-release
|
67
|
+
}["release_name"]
|
68
|
+
')
|
69
|
+
|
70
|
+
echo "Downloading $full_version..."
|
71
|
+
wget -qO- "https://binaries.cockroachdb.com/cockroach-$full_version.linux-amd64.tgz" | tar xvz
|
46
72
|
|
47
|
-
export PATH=./cockroach-$
|
73
|
+
export PATH=./cockroach-$full_version.linux-amd64/:$PATH
|
48
74
|
readonly urlfile=cockroach-url
|
49
75
|
|
50
76
|
# Start a CockroachDB server and wait for it to become ready.
|
51
77
|
rm -f "$urlfile"
|
52
78
|
rm -rf cockroach-data
|
53
79
|
# Start CockroachDB.
|
54
|
-
cockroach start-single-node --max-sql-memory=25% --cache=25% --insecure --host=localhost --spatial-libs=./cockroach-$
|
80
|
+
cockroach start-single-node --max-sql-memory=25% --cache=25% --insecure --host=localhost --spatial-libs=./cockroach-$full_version.linux-amd64/lib --listening-url-file="$urlfile" >/dev/null 2>&1 &
|
55
81
|
# Ensure CockroachDB is stopped on script exit.
|
56
82
|
# Wait until CockroachDB has started.
|
57
83
|
for i in {0..3}; do
|
@@ -60,27 +86,6 @@ jobs:
|
|
60
86
|
echo "server not yet available; sleeping for $backoff seconds"
|
61
87
|
sleep $backoff
|
62
88
|
done
|
63
|
-
cockroach sql --insecure
|
64
|
-
CREATE DATABASE activerecord_unittest;
|
65
|
-
CREATE DATABASE activerecord_unittest2;
|
66
|
-
SET CLUSTER SETTING sql.stats.automatic_collection.enabled = false;
|
67
|
-
SET CLUSTER SETTING sql.stats.histogram_collection.enabled = false;
|
68
|
-
SET CLUSTER SETTING jobs.retention_time = '180s';
|
69
|
-
SET CLUSTER SETTING sql.defaults.experimental_alter_column_type.enabled = 'true';
|
70
|
-
|
71
|
-
ALTER RANGE default CONFIGURE ZONE USING num_replicas = 1, gc.ttlseconds = 30;
|
72
|
-
ALTER TABLE system.public.jobs CONFIGURE ZONE USING num_replicas = 1, gc.ttlseconds = 30;
|
73
|
-
ALTER RANGE meta CONFIGURE ZONE USING num_replicas = 1, gc.ttlseconds = 30;
|
74
|
-
ALTER RANGE system CONFIGURE ZONE USING num_replicas = 1, gc.ttlseconds = 30;
|
75
|
-
ALTER RANGE liveness CONFIGURE ZONE USING num_replicas = 1, gc.ttlseconds = 30;
|
76
|
-
|
77
|
-
SET CLUSTER SETTING kv.range_merge.queue_interval = '50ms';
|
78
|
-
SET CLUSTER SETTING kv.raft_log.disable_synchronization_unsafe = 'true';
|
79
|
-
SET CLUSTER SETTING jobs.registry.interval.cancel = '180s';
|
80
|
-
SET CLUSTER SETTING jobs.registry.interval.gc = '30s';
|
81
|
-
SET CLUSTER SETTING kv.range_split.by_load_merge_delay = '5s';
|
82
|
-
|
83
|
-
SET CLUSTER SETTING sql.defaults.experimental_temporary_tables.enabled = 'true';
|
84
|
-
"
|
89
|
+
cat ${{ github.workspace }}/setup.sql | cockroach sql --insecure
|
85
90
|
- name: Test
|
86
|
-
run: bundle exec rake test
|
91
|
+
run: bundle exec rake test TESTOPTS='--profile=3'
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.2.
|
1
|
+
3.2.3
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,18 @@
|
|
2
2
|
|
3
3
|
## Ongoing
|
4
4
|
|
5
|
+
## 7.1.1 - 2024-05-01
|
6
|
+
|
7
|
+
- Enable precision support ([#318](https://github.com/cockroachdb/activerecord-cockroachdb-adapter/pull/318))
|
8
|
+
- Support arbitrary max identifier length ([#317](https://github.com/cockroachdb/activerecord-cockroachdb-adapter/pull/317)).
|
9
|
+
- Fix `#schema_names` not to return `crdb_internal` ([#316](https://github.com/cockroachdb/activerecord-cockroachdb-adapter/pull/316))
|
10
|
+
|
11
|
+
## 7.1.0 - 2024-01-30
|
12
|
+
|
13
|
+
- Add support for Rails 7.1 ([#300](https://github.com/cockroachdb/activerecord-cockroachdb-adapter/pull/300)).
|
14
|
+
- Add support for [AOST](cockroachlabs.com/docs/stable/as-of-system-time) queries ([#284](https://github.com/cockroachdb/activerecord-cockroachdb-adapter/pull/284))
|
15
|
+
- Dump schema name in foreign keys ([#289](https://github.com/cockroachdb/activerecord-cockroachdb-adapter/pull/289))
|
16
|
+
|
5
17
|
## 7.0.3 - 2023-08-23
|
6
18
|
|
7
19
|
- Fix Multiple Database connections ([#283](https://github.com/cockroachdb/activerecord-cockroachdb-adapter/pull/)).
|
data/Gemfile
CHANGED
@@ -10,6 +10,11 @@ module RailsTag
|
|
10
10
|
def call
|
11
11
|
req = gemspec_requirement
|
12
12
|
"v" + all_activerecord_versions.find { req.satisfied_by?(_1) }.version
|
13
|
+
rescue => e
|
14
|
+
warn "Unable to determine Rails version. Using last used. Error: #{e.message}"
|
15
|
+
lockfile = File.expand_path("Gemfile.lock", __dir__)
|
16
|
+
File.foreach(lockfile, chomp: true).find { _1[/tag: (.*)$/] }
|
17
|
+
Regexp.last_match(1)
|
13
18
|
end
|
14
19
|
|
15
20
|
def gemspec_requirement
|
@@ -43,9 +48,17 @@ group :development, :test do
|
|
43
48
|
# a specific rails codebase.
|
44
49
|
gem "rails", github: "rails/rails", tag: RailsTag.call
|
45
50
|
|
51
|
+
# Needed for the test suite
|
52
|
+
gem "msgpack", ">= 1.7.0"
|
53
|
+
|
46
54
|
gem "rake"
|
47
|
-
gem "
|
55
|
+
gem "debug"
|
48
56
|
gem "minitest-excludes", "~> 2.0.1"
|
57
|
+
gem "minitest-github_action_reporter", github: "BuonOmo/minitest-github_action_reporter", require: "minitest/github_action_reporter_plugin"
|
58
|
+
gem "ostruct", "~> 0.6"
|
59
|
+
|
60
|
+
# Gems used for tests meta-programming.
|
61
|
+
gem "parser"
|
49
62
|
|
50
63
|
# Gems used by the ActiveRecord test suite
|
51
64
|
gem "bcrypt", "~> 3.1.18"
|
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
|
|
14
14
|
spec.description = "Allows the use of CockroachDB as a backend for ActiveRecord and Rails apps."
|
15
15
|
spec.homepage = "https://github.com/cockroachdb/activerecord-cockroachdb-adapter"
|
16
16
|
|
17
|
-
spec.add_dependency "activerecord", "~> 7.0
|
17
|
+
spec.add_dependency "activerecord", "~> 7.1.0"
|
18
18
|
spec.add_dependency "pg", "~> 1.2"
|
19
19
|
spec.add_dependency "rgeo-activerecord", "~> 7.0.0"
|
20
20
|
|
data/bin/console
CHANGED
@@ -12,39 +12,23 @@ require "active_record"
|
|
12
12
|
# structure_load(Post.connection_db_config, "awesome-file.sql")
|
13
13
|
require "active_record/connection_adapters/cockroachdb/database_tasks"
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
class Post < ActiveRecord::Base
|
35
|
-
end
|
36
|
-
|
37
|
-
unless Post.table_exists?
|
38
|
-
migration = Class.new(ActiveRecord::Migration::Current) do
|
39
|
-
def up
|
40
|
-
create_table("posts") do |t|
|
41
|
-
t.string :title
|
42
|
-
t.text :body
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
migration.migrate(:up)
|
47
|
-
end
|
15
|
+
schema_kind = ENV.fetch("SCHEMA_KIND", ENV.fetch("SCHEMA", "default"))
|
16
|
+
|
17
|
+
system("cockroach sql --insecure --host=localhost:26257 --execute='drop database if exists ar_crdb_console'",
|
18
|
+
exception: true)
|
19
|
+
system("cockroach sql --insecure --host=localhost:26257 --execute='create database ar_crdb_console'",
|
20
|
+
exception: true)
|
21
|
+
|
22
|
+
ActiveRecord::Base.establish_connection(
|
23
|
+
#Alternative version: "cockroachdb://root@localhost:26257/ar_crdb_console"
|
24
|
+
adapter: "cockroachdb",
|
25
|
+
host: "localhost",
|
26
|
+
port: 26257,
|
27
|
+
user: "root",
|
28
|
+
database: "ar_crdb_console"
|
29
|
+
)
|
30
|
+
|
31
|
+
load "#{__dir__}/console_schemas/#{schema_kind}.rb"
|
48
32
|
|
49
33
|
require "irb"
|
50
34
|
IRB.start(__FILE__)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Post < ActiveRecord::Base
|
2
|
+
self.table_name = "bar.posts"
|
3
|
+
end
|
4
|
+
|
5
|
+
class Comment < ActiveRecord::Base
|
6
|
+
self.table_name = "foo.comments"
|
7
|
+
end
|
8
|
+
|
9
|
+
ActiveRecord::Schema.define do
|
10
|
+
create_schema("foo")
|
11
|
+
create_schema("bar")
|
12
|
+
create_table("bar.posts") do |t|
|
13
|
+
t.string :title
|
14
|
+
t.text :body
|
15
|
+
end
|
16
|
+
|
17
|
+
create_table("foo.comments") do |t|
|
18
|
+
t.integer :post_id
|
19
|
+
t.text :body
|
20
|
+
end
|
21
|
+
|
22
|
+
add_foreign_key "foo.comments", "bar.posts", column: "post_id"
|
23
|
+
end
|
data/bin/start-cockroachdb
CHANGED
@@ -9,6 +9,7 @@ pid_file="$root_dir/tmp/cockroach.pid"
|
|
9
9
|
log_file="$root_dir/tmp/cockroachdb.log"
|
10
10
|
|
11
11
|
mkdir -p "$root_dir/tmp"
|
12
|
+
[[ -f "$pid_file" ]] && kill -9 $(cat "$pid_file") || true
|
12
13
|
rm -f "$pid_file"
|
13
14
|
|
14
15
|
if ! (( ${+commands[cockroach]} )); then
|
@@ -17,32 +18,16 @@ See https://www.cockroachlabs.com/docs/stable/install-cockroachdb.html'
|
|
17
18
|
fi
|
18
19
|
|
19
20
|
cockroach start-single-node \
|
20
|
-
--insecure --store=type=mem,size=0.25 --advertise-addr=localhost
|
21
|
+
--insecure --store=type=mem,size=0.25 --advertise-addr=localhost \
|
22
|
+
--spatial-libs="$(geos-config --includes)" \
|
23
|
+
--pid-file "$pid_file" \
|
21
24
|
&> "$log_file" &
|
22
25
|
|
23
|
-
cockroach_pid=$!
|
24
|
-
|
25
26
|
until [[ -f "$pid_file" ]]; do
|
26
27
|
sleep 1
|
27
28
|
done
|
28
29
|
|
29
30
|
|
30
|
-
cat
|
31
|
-
-- https://www.cockroachlabs.com/docs/stable/local-testing.html
|
32
|
-
SET CLUSTER SETTING kv.raft_log.disable_synchronization_unsafe = true;
|
33
|
-
SET CLUSTER SETTING kv.range_merge.queue_interval = '50ms';
|
34
|
-
SET CLUSTER SETTING jobs.registry.interval.gc = '30s';
|
35
|
-
SET CLUSTER SETTING jobs.registry.interval.cancel = '180s';
|
36
|
-
SET CLUSTER SETTING jobs.retention_time = '15s';
|
37
|
-
SET CLUSTER SETTING sql.stats.automatic_collection.enabled = false;
|
38
|
-
SET CLUSTER SETTING kv.range_split.by_load_merge_delay = '5s';
|
39
|
-
ALTER RANGE default CONFIGURE ZONE USING "gc.ttlseconds" = 600;
|
40
|
-
ALTER DATABASE system CONFIGURE ZONE USING "gc.ttlseconds" = 600;
|
41
|
-
|
42
|
-
CREATE DATABASE activerecord_unittest;
|
43
|
-
CREATE DATABASE activerecord_unittest2;
|
44
|
-
SQL
|
45
|
-
|
46
|
-
tail -f "$log_file"
|
31
|
+
cat "$root_dir/setup.sql" | cockroach sql --insecure --host=localhost:26257 > /dev/null
|
47
32
|
|
48
|
-
|
33
|
+
echo "CockroachDB started. PID: $(cat "$pid_file"). log: $log_file"
|
data/build/Dockerfile
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# This Dockerfile extends the Examples-ORM testing image in order to
|
2
2
|
# install specific dependencies required for ActiveRecord tests.
|
3
3
|
|
4
|
-
FROM
|
4
|
+
FROM us-east1-docker.pkg.dev/crl-ci-images/cockroach/example-orms-builder:20200413-1918
|
5
5
|
|
6
6
|
# Native dependencies for libxml-ruby and sqlite3.
|
7
7
|
RUN apt-get --allow-releaseinfo-change update -y && apt-get install -y \
|
@@ -22,6 +22,14 @@ module Arel # :nodoc:
|
|
22
22
|
module Visitors # :nodoc:
|
23
23
|
class CockroachDB < PostgreSQL # :nodoc:
|
24
24
|
include RGeo::ActiveRecord::SpatialToSql
|
25
|
+
|
26
|
+
def visit_Arel_Nodes_JoinSource(o, collector)
|
27
|
+
super
|
28
|
+
if o.aost
|
29
|
+
collector << " AS OF SYSTEM TIME '#{o.aost.iso8601}'"
|
30
|
+
end
|
31
|
+
collector
|
32
|
+
end
|
25
33
|
end
|
26
34
|
end
|
27
35
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module ConnectionAdapters
|
3
3
|
module CockroachDB
|
4
|
-
class Column <
|
4
|
+
class Column < PostgreSQL::Column
|
5
5
|
# most functions taken from activerecord-postgis-adapter spatial_column
|
6
6
|
# https://github.com/rgeo/activerecord-postgis-adapter/blob/master/lib/active_record/connection_adapters/postgis/spatial_column.rb
|
7
7
|
def initialize(name, default, sql_type_metadata = nil, null = true,
|
8
|
-
default_function = nil, collation: nil, comment: nil,
|
8
|
+
default_function = nil, collation: nil, comment: nil, identity: nil,
|
9
9
|
serial: nil, spatial: nil, generated: nil, hidden: nil)
|
10
10
|
@sql_type_metadata = sql_type_metadata
|
11
11
|
@geographic = !!(sql_type_metadata.sql_type =~ /geography\(/i)
|
@@ -30,7 +30,7 @@ module ActiveRecord
|
|
30
30
|
build_from_sql_type(sql_type_metadata.sql_type)
|
31
31
|
end
|
32
32
|
super(name, default, sql_type_metadata, null, default_function,
|
33
|
-
collation: collation, comment: comment, serial: serial, generated: generated)
|
33
|
+
collation: collation, comment: comment, serial: serial, generated: generated, identity: identity)
|
34
34
|
if spatial? && @srid
|
35
35
|
@limit = { srid: @srid, type: to_type_name(geometric_type) }
|
36
36
|
@limit[:has_z] = true if @has_z
|
@@ -53,10 +53,6 @@ module ActiveRecord
|
|
53
53
|
spatial? ? @limit : super
|
54
54
|
end
|
55
55
|
|
56
|
-
def virtual?
|
57
|
-
@generated.present?
|
58
|
-
end
|
59
|
-
|
60
56
|
def hidden?
|
61
57
|
@hidden
|
62
58
|
end
|
@@ -45,6 +45,14 @@ module ActiveRecord
|
|
45
45
|
def st_polygon(name, options = {})
|
46
46
|
column(name, :st_polygon, **options)
|
47
47
|
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def valid_column_definition_options
|
52
|
+
spatial = [:srid, :has_z, :has_m, :geographic, :spatial_type]
|
53
|
+
crdb = [:hidden]
|
54
|
+
super + spatial + crdb
|
55
|
+
end
|
48
56
|
end
|
49
57
|
end
|
50
58
|
|
@@ -2,21 +2,6 @@ module ActiveRecord
|
|
2
2
|
module ConnectionAdapters
|
3
3
|
module CockroachDB
|
4
4
|
module DatabaseStatements
|
5
|
-
# Since CockroachDB will run all transactions with serializable isolation,
|
6
|
-
# READ UNCOMMITTED, READ COMMITTED, and REPEATABLE READ are all aliases
|
7
|
-
# for SERIALIZABLE. This lets the adapter support all isolation levels,
|
8
|
-
# but READ UNCOMMITTED has been removed from this list because the
|
9
|
-
# ActiveRecord transaction isolation test fails for READ UNCOMMITTED.
|
10
|
-
# See https://www.cockroachlabs.com/docs/v19.2/transactions.html#isolation-levels
|
11
|
-
def transaction_isolation_levels
|
12
|
-
{
|
13
|
-
read_committed: "READ COMMITTED",
|
14
|
-
repeatable_read: "REPEATABLE READ",
|
15
|
-
serializable: "SERIALIZABLE",
|
16
|
-
read_uncommitted: "READ UNCOMMITTED"
|
17
|
-
}
|
18
|
-
end
|
19
|
-
|
20
5
|
# Overridden to avoid using transactions for schema creation.
|
21
6
|
def insert_fixtures_set(fixture_set, tables_to_delete = [])
|
22
7
|
fixture_inserts = build_fixture_statements(fixture_set)
|
@@ -29,74 +14,6 @@ module ActiveRecord
|
|
29
14
|
end
|
30
15
|
end
|
31
16
|
end
|
32
|
-
|
33
|
-
private
|
34
|
-
def execute_batch(statements, name = nil)
|
35
|
-
statements.each do |statement|
|
36
|
-
execute(statement, name)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
DEFAULT_INSERT_VALUE = Arel.sql("DEFAULT").freeze
|
41
|
-
private_constant :DEFAULT_INSERT_VALUE
|
42
|
-
|
43
|
-
def default_insert_value(column)
|
44
|
-
DEFAULT_INSERT_VALUE
|
45
|
-
end
|
46
|
-
|
47
|
-
def build_fixture_sql(fixtures, table_name)
|
48
|
-
columns = schema_cache.columns_hash(table_name)
|
49
|
-
|
50
|
-
values_list = fixtures.map do |fixture|
|
51
|
-
fixture = fixture.stringify_keys
|
52
|
-
|
53
|
-
unknown_columns = fixture.keys - columns.keys
|
54
|
-
if unknown_columns.any?
|
55
|
-
raise Fixture::FixtureError, %(table "#{table_name}" has no columns named #{unknown_columns.map(&:inspect).join(', ')}.)
|
56
|
-
end
|
57
|
-
|
58
|
-
columns.map do |name, column|
|
59
|
-
if fixture.key?(name)
|
60
|
-
type = lookup_cast_type_from_column(column)
|
61
|
-
with_yaml_fallback(type.serialize(fixture[name]))
|
62
|
-
else
|
63
|
-
default_insert_value(column)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
table = Arel::Table.new(table_name)
|
69
|
-
manager = Arel::InsertManager.new
|
70
|
-
manager.into(table)
|
71
|
-
|
72
|
-
if values_list.size == 1
|
73
|
-
values = values_list.shift
|
74
|
-
new_values = []
|
75
|
-
columns.each_key.with_index { |column, i|
|
76
|
-
unless values[i].equal?(DEFAULT_INSERT_VALUE)
|
77
|
-
new_values << values[i]
|
78
|
-
manager.columns << table[column]
|
79
|
-
end
|
80
|
-
}
|
81
|
-
values_list << new_values
|
82
|
-
else
|
83
|
-
columns.each_key { |column| manager.columns << table[column] }
|
84
|
-
end
|
85
|
-
|
86
|
-
manager.values = manager.create_values_list(values_list)
|
87
|
-
manager.to_sql
|
88
|
-
end
|
89
|
-
|
90
|
-
def build_fixture_statements(fixture_set)
|
91
|
-
fixture_set.map do |table_name, fixtures|
|
92
|
-
next if fixtures.empty?
|
93
|
-
build_fixture_sql(fixtures, table_name)
|
94
|
-
end.compact
|
95
|
-
end
|
96
|
-
|
97
|
-
def with_multi_statements
|
98
|
-
yield
|
99
|
-
end
|
100
17
|
end
|
101
18
|
end
|
102
19
|
end
|
@@ -10,37 +10,45 @@ module ActiveRecord
|
|
10
10
|
"https://github.com/cockroachdb/activerecord-cockroachdb-adapter/issues/new"
|
11
11
|
end
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
13
|
+
# "See https://github.com/cockroachdb/cockroach/issues/26443."
|
14
|
+
search_path =
|
15
|
+
case ActiveRecord.dump_schemas
|
16
|
+
when :schema_search_path
|
17
|
+
configuration_hash[:schema_search_path]
|
18
|
+
when :all
|
19
|
+
nil
|
20
|
+
when String
|
21
|
+
ActiveRecord.dump_schemas
|
21
22
|
end
|
22
|
-
end
|
23
23
|
|
24
24
|
conn = ActiveRecord::Base.connection
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
begin
|
26
|
+
old_search_path = conn.schema_search_path
|
27
|
+
conn.schema_search_path = search_path
|
28
|
+
File.open(filename, "w") do |file|
|
29
|
+
# NOTE: There is no issue with the crdb_internal schema, it is ignored by SHOW CREATE.
|
30
|
+
%w(SCHEMAS TYPES).each do |object_kind|
|
31
|
+
ActiveRecord::Base.connection.execute("SHOW CREATE ALL #{object_kind}").each_row { file.puts _1 }
|
32
|
+
end
|
29
33
|
|
30
|
-
|
34
|
+
ignore_tables = ActiveRecord::SchemaDumper.ignore_tables.to_set
|
31
35
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
36
|
+
conn.execute("SHOW CREATE ALL TABLES").each_row do |(sql)|
|
37
|
+
if sql.start_with?("CREATE")
|
38
|
+
table_name = sql[/CREATE TABLE (?:.*?\.)?\"?(.*?)[\" ]/, 1]
|
39
|
+
next if ignore_tables.member?(table_name)
|
40
|
+
elsif sql.start_with?("ALTER")
|
41
|
+
table_name = sql[/ALTER TABLE (?:.*?\.)?\"?(.*?)[\" ]/, 1]
|
42
|
+
ref_table_name = sql[/REFERENCES (?:.*?\.)?\"?(.*?)[\" ]/, 1]
|
43
|
+
next if ignore_tables.member?(table_name) || ignore_tables.member?(ref_table_name)
|
44
|
+
end
|
41
45
|
|
42
|
-
|
46
|
+
file.puts sql
|
47
|
+
end
|
48
|
+
file.puts "SET search_path TO #{conn.schema_search_path};\n\n"
|
43
49
|
end
|
50
|
+
ensure
|
51
|
+
conn.schema_search_path = old_search_path
|
44
52
|
end
|
45
53
|
end
|
46
54
|
|
@@ -11,6 +11,14 @@ module ActiveRecord
|
|
11
11
|
module ConnectionAdapters
|
12
12
|
module CockroachDB
|
13
13
|
module ReferentialIntegrity
|
14
|
+
# CockroachDB will raise a `PG::ForeignKeyViolation` when re-enabling
|
15
|
+
# referential integrity (e.g: adding a foreign key with invalid data
|
16
|
+
# raises).
|
17
|
+
# So foreign keys should always be valid for that matter.
|
18
|
+
def check_all_foreign_keys_valid!
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
14
22
|
def disable_referential_integrity
|
15
23
|
foreign_keys = tables.map { |table| foreign_keys(table) }.flatten
|
16
24
|
|
@@ -31,16 +39,12 @@ module ActiveRecord
|
|
31
39
|
|
32
40
|
begin
|
33
41
|
foreign_keys.each do |foreign_key|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
else
|
41
|
-
raise error
|
42
|
-
end
|
43
|
-
end
|
42
|
+
# Avoid having PG:DuplicateObject error if a test is ran in transaction.
|
43
|
+
# TODO: verify that there is no cache issue related to running this (e.g: fk
|
44
|
+
# still in cache but not in db)
|
45
|
+
next if foreign_key_exists?(foreign_key.from_table, name: foreign_key.options[:name])
|
46
|
+
|
47
|
+
add_foreign_key(foreign_key.from_table, foreign_key.to_table, **foreign_key.options)
|
44
48
|
end
|
45
49
|
ensure
|
46
50
|
ActiveRecord::Base.table_name_prefix = old_prefix
|