activerecord-cockroachdb-adapter 0.2.3 → 6.0.0beta1

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
- SHA1:
3
- metadata.gz: 96a284c08e5798cc8b45332be543b14f60bdb8c0
4
- data.tar.gz: ffa757e8b581788ba8d1880842d37eca7058695e
2
+ SHA256:
3
+ metadata.gz: a580dde40d074b1982c6642310513d79bbcb710032a476a64bb9fcb99bec72bb
4
+ data.tar.gz: 91b11b334235484e298704ae514d435a61451a02f3f759881141fd6354549ee4
5
5
  SHA512:
6
- metadata.gz: 456d42bc6a8a973488a6c66a9631d8e78f7e4a35abb379b3958239b6fb474bce9a3503678be6a098d788bb09425c02d30732fb1ee546b3d4c2b8cb21b3a7fe57
7
- data.tar.gz: 40ada5999c613d6d2f953ce7fc99b9fbb3793685d258fe9cef790e2421df96d218ee3684081a499571ed38cc129be6e65de6a87328d57297fdd62323430c61c6
6
+ metadata.gz: 77b98dff7d2069ba0cdcd78bccf5aedf9ac31192c0813d7893a5a6f1084537d9d0b03039be58fe83a5a0e0cd58d5d42ba567e43beee62507d8212242722fdb13
7
+ data.tar.gz: f1bf6e2fa1925d94133a98dcd03690a24da2631134cc6a5eb6dd860253392f398db88572942f409f13dec4d3d7aeb34f18317a5b8cd4b30c70e4d75d13599b47
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ *.gem
@@ -1,3 +0,0 @@
1
- [submodule "rails"]
2
- path = rails
3
- url = https://github.com/lego/ruby-on-rails.git
@@ -11,15 +11,19 @@ CockroachDBAdapter to initialize ActiveRecord for their projects.
11
11
  This adapter extends the PostgreSQL ActiveRecord adapter in order to
12
12
  override and monkey-patch functionality.
13
13
 
14
- The other repository is a fork of [Rails]. The tests have been modified
15
- for the purposes of testing our CockroachDB adapter.
16
-
17
14
  [activerecord-cockroachdb-adapter]: https://github.com/cockroachdb/activerecord-cockroachdb-adapter/
18
- [Rails]: https://github.com/lego/ruby-on-rails
19
-
20
15
 
21
16
  ## Setup and running tests
22
17
 
18
+ In CockroachDB, create two databases to be used by the ActiveRecord test suite:
19
+ activerecord_unittest and activerecord_unittest2.
20
+
21
+ ```sql
22
+ CREATE DATABASE activerecord_unittest;
23
+
24
+ CREATE DATABASE activerecord_unittest2;
25
+ ```
26
+
23
27
  It is best to have a Ruby environment manager installed, such as
24
28
  [rvm](https://rvm.io/), as Rails has varying Ruby version requirements.
25
29
  If you are using rvm, you then install and use the required Ruby
@@ -37,65 +41,42 @@ rvm use 2.2.5
37
41
  ```
38
42
 
39
43
  Using [bundler](http://bundler.io/), install the dependancies of Rails.
40
- Additionally, make sure the Rails git submodule is loaded.
41
44
 
42
45
  ```bash
43
- # Ensure the rails fork is fetched.
44
- git submodule update
45
- # Install rails dependancies.
46
- (cd rails && bundle install)
46
+ bundle install
47
47
  ```
48
48
 
49
- Then, to run the test with an active CockroachDB instance:
49
+ Then, to run the full test suite with an active CockroachDB instance:
50
50
 
51
51
  ```bash
52
- cp build/config.teamcity.yml rails/activerecord/test/config.yml
53
- (cd rails/activerecord && BUNDLE_GEMFILE=../Gemfile bundle exec rake db:cockroachdb:rebuild)
54
- (cd rails/activerecord && BUNDLE_GEMFILE=../Gemfile bundle exec rake test:cockroachdb)
52
+ bundle exec rake test
55
53
  ```
56
54
 
57
- ### Test commands in detail
55
+ To run specific ActiveRecord tests, set environemnt variable `TEST_FILES_AR`. For example, to run ActiveRecord tests `test/cases/associations_test.rb` and `test/cases/ar_schema_test.rb.rb`
58
56
 
59
57
  ```bash
60
- cp build/config.teamcity.yml rails/activerecord/test/config.yml
58
+ TEST_FILES_AR="test/cases/associations_test.rb,test/cases/ar_schema_test.rb" bundle exec rake test
61
59
  ```
62
60
 
63
- This copies the TeamCity ActiveRecord configuration for the application.
64
- This configuration specifies:
65
-
66
- - CockroachDB port and host the test suite uses.
67
- - Database names used for the different test connections. (ActiveRecord
68
- uses two separate connections for some tests.)
61
+ To run specific CockroachDB Adapter tests, set environemnt variable `TEST_FILES`. For example, to run CockroachDB Adpater tests `test/cases/adapter_test.rb` and `test/cases/associations/left_outer_join_association_test.rb`
69
62
 
70
- ```
71
- (cd rails/activerecord && BUNDLE_GEMFILE=../Gemfile bundle exec rake db:cockroachdb:rebuild)
63
+ ```bash
64
+ TEST_FILES="test/cases/adapter_test.rb,test/cases/associations/left_outer_join_association_test.rb" bundle exec rake test
72
65
  ```
73
66
 
74
- This prepares CockroachDB for running tests. It only drops and
75
- re-creates all of the databases needed.
67
+ To run a specific test case, use minitest's `-n` option to run tests that match a given pattern. All minitest options are set via the `TESTOPTS` environemnt variable. For example, to run `test_indexes` from CockroachDB's `test/cases/adapter_test.rb` file
76
68
 
77
- - This command needs to be run from activerecord folder in order to use
78
- the ActiveRecord `Rakefile`. The `Rakefile` defines scripts (called
79
- tasks) such as executing tests.
80
- - `BUNDLE_GEMFILE=../Gemfile` tells `bundle` to use the dependancies for
81
- Rails that were previously installed.
82
- - `bundle exec rake` uses `bundle` to execute the Ruby package `rake`.
83
- - `rake db:cockroachdb:rebuild` runs the specified Rake task. All tasks
84
- can be found in `rails/activerecord/Rakefile`.
85
-
86
-
87
- ```
88
- (cd rails/activerecord && BUNDLE_GEMFILE=../Gemfile bundle exec rake test:cockroachdb)
69
+ ```bash
70
+ TEST_FILES="test/cases/adapter_test.rb" TESTOPTS=`-n=/test_indexes/` bundle exec rake test
89
71
  ```
90
72
 
91
- This executes the CockroachDB tests.
73
+ By default, tests will be run from the bundled version of Rails. To run against a local copy, set environemnt variable `RAILS_SOURCE`. Running against a local copy of Rails can be helpful when try to debug issues.
92
74
 
93
- - Like the previous command, this one uses the Activerecord Rakefile and
94
- the Rails Gemfile. The task code can be found in the Rakefile.
95
- - Running specific test files can be done by appending
96
- `TESTFILES=test/cases/attribute_methods.rb` to the command. Globs are
97
- used. Multiple individual files cannot be specified.
75
+ ```bash
76
+ RAILS_SOURCE="path/to/local_copy" bundle exec rake test
77
+ ```
98
78
 
79
+ `test/config.yml` assumes CockroachDB will be running at localhost:26257 with a root user. Make changes to `test/config.yml` as needed.
99
80
 
100
81
  # Improvements
101
82
 
@@ -143,15 +124,6 @@ A possible way to approach this would be to add a shim to cause any
143
124
  tests that use it to fail, and grep the tests that pass and then skip
144
125
  them.
145
126
 
146
- # Cleanup
147
-
148
- One of the earlier commits to the Rails repo did a big grep of
149
- `PostgreSQLAdapter` -> `CockroachDBAdapter`. In order to better support
150
- changes upstream, this modification should be changed to instead only
151
- add `CockroachDBAdapter` alongside any `PostgreSQLAdapter`. The later
152
- test cleanup commit will conflict on any further changes (like adding
153
- back PostgreSQL, or removing CockroachDB for PostgreSQL).
154
-
155
127
  ## Publishing to Rubygems
156
128
 
157
129
  TODO: Expand on this. Jordan is likely the only person with publishing
data/Gemfile CHANGED
@@ -1,11 +1,63 @@
1
+ require 'openssl'
1
2
  source 'https://rubygems.org'
3
+ gemspec
2
4
 
3
- # gem 'activerecord', git: 'https://github.com/lego/ruby-on-rails.git'
5
+ if ENV['RAILS_SOURCE']
6
+ gemspec path: ENV['RAILS_SOURCE']
7
+ else
8
+ def get_version_from_gemspec
9
+ gemspec = eval(File.read('activerecord-cockroachdb-adapter.gemspec'))
4
10
 
5
- git_source(:github) { |repo| "https://github.com/#{repo}.git" }
11
+ gem_version = gemspec.dependencies.
12
+ find { |dep| dep.name == 'activerecord' }.
13
+ requirement.
14
+ requirements.
15
+ first.
16
+ last
6
17
 
7
- # Specify your gem's dependencies in activerecord-cockroachdb-adapter.gemspec
8
- gemspec
18
+ major, minor, tiny, pre = gem_version.segments
19
+
20
+ if pre
21
+ gem_version.to_s
22
+ else
23
+ find_latest_matching_version(major, minor)
24
+ end
25
+ end
26
+
27
+ def find_latest_matching_version(gemspec_major, gemspec_minor)
28
+ all_activerecord_versions.
29
+ reject { |version| version["prerelease"] }.
30
+ map { |version| version["number"].split(".").map(&:to_i) }.
31
+ find { |major, minor|
32
+ major == gemspec_major && (minor == gemspec_minor || gemspec_minor.nil?)
33
+ }.join(".")
34
+ end
35
+
36
+ def all_activerecord_versions
37
+ require 'net/http'
38
+ require 'yaml'
39
+
40
+ uri = URI.parse "https://rubygems.org/api/v1/versions/activerecord.yaml"
41
+ http = Net::HTTP.new(uri.host, uri.port)
42
+ http.use_ssl = true
43
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
44
+
45
+ YAML.load(
46
+ http.request(Net::HTTP::Get.new(uri.request_uri)).body
47
+ )
48
+ end
49
+
50
+ # Get Rails from source beacause the gem doesn't include tests
51
+ version = ENV['RAILS_VERSION'] || get_version_from_gemspec
52
+ gem 'rails', git: "https://github.com/rails/rails.git", tag: "v#{version}"
53
+ end
54
+
55
+ group :development do
56
+ gem "byebug"
57
+ gem "minitest-excludes"
9
58
 
10
- # We need a newish Rake since Active Job sets its test tasks' descriptions.
11
- gem "rake", ">= 11.1"
59
+ # Gems used by the ActiveRecord test suite
60
+ gem "bcrypt"
61
+ gem "mocha"
62
+ gem "sqlite3"
63
+ end
data/README.md CHANGED
@@ -7,7 +7,7 @@ CockroachDB adapter for ActiveRecord 4 and 5. This is a lightweight extension of
7
7
  Add this line to your project's Gemfile:
8
8
 
9
9
  ```ruby
10
- gem 'activerecord-cockroachdb-adapter', '~> 0.2.2'
10
+ gem 'activerecord-cockroachdb-adapter', '~> 5.2.0'
11
11
  ```
12
12
 
13
13
  If you're using Rails 4.x, use the `0.1.x` versions of this gem.
@@ -26,4 +26,4 @@ development:
26
26
  ## Modifying the adapter?
27
27
 
28
28
  See [CONTRIBUTING.md](/CONTRIBUTING.md) for more details on setting up
29
- the environment and making modifications.
29
+ the environment and making modifications.
data/Rakefile CHANGED
@@ -1,10 +1,22 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rake/testtask"
3
+ require_relative 'test/support/paths_cockroachdb'
4
+ require_relative 'test/support/rake_helpers'
3
5
 
4
- Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
7
- t.test_files = FileList['test/**/*_test.rb']
6
+ task test: ["test:cockroachdb"]
7
+ task default: [:test]
8
+
9
+ namespace :test do
10
+ Rake::TestTask.new("cockroachdb") do |t|
11
+ t.libs = ARTest::CockroachDB.test_load_paths
12
+ t.test_files = test_files
13
+ t.warning = !!ENV["WARNING"]
14
+ t.verbose = false
15
+ end
16
+
17
+ task "cockroachdb:env" do
18
+ ENV["ARCONN"] = "cockroachdb"
19
+ end
8
20
  end
9
21
 
10
- task :default => :test
22
+ task 'test:cockroachdb' => 'test:cockroachdb:env'
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "activerecord-cockroachdb-adapter"
7
- spec.version = "0.2.3"
7
+ spec.version = "6.0.0beta1"
8
8
  spec.licenses = ["Apache-2.0"]
9
9
  spec.authors = ["Cockroach Labs"]
10
10
  spec.email = ["cockroach-db@googlegroups.com"]
@@ -13,8 +13,8 @@ Gem::Specification.new do |spec|
13
13
  spec.description = "Allows the use of CockroachDB as a backend for ActiveRecord and Rails apps."
14
14
  spec.homepage = "https://github.com/cockroachdb/activerecord-cockroachdb-adapter"
15
15
 
16
- spec.add_dependency "activerecord", "~> 5.2"
17
- spec.add_dependency "pg", ">= 0.20", "< 0.22"
16
+ spec.add_dependency "activerecord", "~> 6.0.3"
17
+ spec.add_dependency "pg", ">= 0.20"
18
18
 
19
19
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
20
20
  # to allow pushing to a single host or delete this section to allow pushing to any host.
@@ -31,8 +31,4 @@ Gem::Specification.new do |spec|
31
31
  spec.bindir = "exe"
32
32
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
33
33
  spec.require_paths = ["lib"]
34
-
35
- spec.add_development_dependency "bundler", "~> 1.14"
36
- spec.add_development_dependency "rake", "~> 10.0"
37
- spec.add_development_dependency "minitest", "~> 5.0"
38
34
  end
@@ -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 cockroachdb/postgres-test:20170308-1644
4
+ FROM cockroachdb/example-orms-builder:20200413-1918
5
5
 
6
6
  # Native dependencies for libxml-ruby and sqlite3.
7
7
  RUN apt-get update -y && apt-get install -y \
@@ -1,16 +1,15 @@
1
1
  #!/usr/bin/env bash
2
2
 
3
- set -euo pipefail
3
+ set -euox pipefail
4
4
 
5
- # Download CockroachDB. NB: currently this uses an alpha, due to feature
6
- # requirements.
7
- VERSION=v2.0-alpha.20171218
5
+ # Download CockroachDB
6
+ VERSION=v20.2.1
8
7
  wget -qO- https://binaries.cockroachdb.com/cockroach-$VERSION.linux-amd64.tgz | tar xvz
9
8
  readonly COCKROACH=./cockroach-$VERSION.linux-amd64/cockroach
10
9
 
11
10
  # Make sure cockroach can be found on the path. This is required for the
12
11
  # ActiveRecord Rakefile that rebuilds the test database.
13
- export PATH=$(pwd)/cockroach-$VERSION.linux-amd64/:$PATH
12
+ export PATH=./cockroach-$VERSION.linux-amd64/:$PATH
14
13
  readonly urlfile=cockroach-url
15
14
 
16
15
  run_cockroach() {
@@ -22,7 +21,7 @@ run_cockroach() {
22
21
  cockroach quit --insecure || true
23
22
  rm -rf cockroach-data
24
23
  # Start CockroachDB.
25
- cockroach start --insecure --host=localhost --listening-url-file="$urlfile" >/dev/null 2>&1 &
24
+ cockroach start-single-node --max-sql-memory=25% --cache=25% --insecure --host=localhost --listening-url-file="$urlfile" >/dev/null 2>&1 &
26
25
  # Ensure CockroachDB is stopped on script exit.
27
26
  trap "echo 'Exit routine: Killing CockroachDB.' && kill -9 $! &> /dev/null" EXIT
28
27
  # Wait until CockroachDB has started.
@@ -32,45 +31,26 @@ run_cockroach() {
32
31
  echo "server not yet available; sleeping for $backoff seconds"
33
32
  sleep $backoff
34
33
  done
34
+ cockroach sql --insecure -e 'CREATE DATABASE activerecord_unittest;'
35
+ cockroach sql --insecure -e 'CREATE DATABASE activerecord_unittest2;'
36
+ cockroach sql --insecure -e 'SET CLUSTER SETTING sql.stats.automatic_collection.enabled = false;'
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';"
35
39
  }
36
40
 
37
- # Target the Rails dependency file.
38
- export BUNDLE_GEMFILE=$(pwd)/rails/Gemfile
39
-
40
41
  # Install ruby dependencies.
42
+ gem install bundler:2.1.4
41
43
  bundle install
42
44
 
43
- cp build/config.teamcity.yml rails/activerecord/test/config.yml
44
-
45
- # 'Install' our adapter. This involves symlinking it inside of
46
- # ActiveRecord. Normally the adapter will transitively install
47
- # ActiveRecord, but we need to execute tests from inside the Rails
48
- # context so we cannot rely on that. We also need previous links to make
49
- # tests idempotent.
50
- rm -f rails/activerecord/lib/active_record/connection_adapters/cockroachdb_adapter.rb
51
- ln -s $(pwd)/lib/active_record/connection_adapters/cockroachdb_adapter.rb rails/activerecord/lib/active_record/connection_adapters/cockroachdb_adapter.rb
52
- rm -rf rails/activerecord/lib/active_record/connection_adapters/cockroachdb
53
- ln -s $(pwd)/lib/active_record/connection_adapters/cockroachdb rails/activerecord/lib/active_record/connection_adapters/cockroachdb
45
+ run_cockroach
54
46
 
55
- # Get the test files with "# FILE(OK)". These should pass.
56
- TESTS=$(cd rails/activerecord && find test/cases -type f \( -name "*_test.rb" \) -exec grep -l "# FILE(OK)" {} +)
57
-
58
- for TESTFILE in ${TESTS}; do
59
- # Start CockroachDB
60
- run_cockroach
61
- # Run the tests.
62
- echo "Rebuilding database"
63
- (cd rails/activerecord && bundle exec rake db:cockroachdb:rebuild)
64
- echo "Running test: $TESTFILE"
65
- # Run the test. Continue testing even if this file fails.
66
- if ! (cd rails/activerecord && bundle exec rake test:cockroachdb TESTFILES=$TESTFILE); then
67
- echo "Test FAILED: $TESTFILE"
47
+ if ! (RUBYOPT="-W0" TESTOPTS="-v" bundle exec rake test); then
48
+ echo "Tests failed"
68
49
  HAS_FAILED=1
69
- else
70
- echo "Test PASSED: $TESTFILE"
50
+ else
51
+ echo "Tests passed"
71
52
  HAS_FAILED=0
72
- fi
73
- done
53
+ fi
74
54
 
75
55
  # Attempt a clean shutdown for good measure. We'll force-kill in the
76
56
  # exit trap if this script fails.
data/docker.sh CHANGED
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # This file is largely cargo-culted from cockroachdb/cockroach/build/builder.sh.
4
4
 
5
- set -euo pipefail
5
+ set -euox pipefail
6
6
 
7
7
  DOCKER_IMAGE_TAG=activerecord_test_container
8
8
 
@@ -0,0 +1,28 @@
1
+ module ActiveRecord
2
+ module CockroachDB
3
+ module AttributeMethodsMonkeyPatch
4
+
5
+ private
6
+
7
+ # Filter out rowid so it doesn't get inserted by ActiveRecord. rowid is a
8
+ # column added by CockroachDB for tables that don't define primary keys.
9
+ # CockroachDB will automatically insert rowid values. See
10
+ # https://www.cockroachlabs.com/docs/v19.2/create-table.html#create-a-table.
11
+ def attributes_for_create(attribute_names)
12
+ super.reject { |name| name == ConnectionAdapters::CockroachDBAdapter::DEFAULT_PRIMARY_KEY }
13
+ end
14
+
15
+ # Filter out rowid so it doesn't get updated by ActiveRecord. rowid is a
16
+ # column added by CockroachDB for tables that don't define primary keys.
17
+ # CockroachDB will automatically insert rowid values. See
18
+ # https://www.cockroachlabs.com/docs/v19.2/create-table.html#create-a-table.
19
+ def attributes_for_update(attribute_names)
20
+ super.reject { |name| name == ConnectionAdapters::CockroachDBAdapter::DEFAULT_PRIMARY_KEY }
21
+ end
22
+ end
23
+ end
24
+
25
+ class Base
26
+ prepend CockroachDB::AttributeMethodsMonkeyPatch
27
+ end
28
+ end
@@ -0,0 +1,15 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module CockroachDB
4
+ module PostgreSQLColumnMonkeyPatch
5
+ def serial?
6
+ default_function == "unique_rowid()"
7
+ end
8
+ end
9
+ end
10
+
11
+ class PostgreSQLColumn
12
+ prepend CockroachDB::PostgreSQLColumnMonkeyPatch
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,102 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module CockroachDB
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
+ }
17
+ end
18
+
19
+ # Overridden to avoid using transactions for schema creation.
20
+ def insert_fixtures_set(fixture_set, tables_to_delete = [])
21
+ fixture_inserts = build_fixture_statements(fixture_set)
22
+ table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name(table)}" }
23
+ statements = table_deletes + fixture_inserts
24
+
25
+ with_multi_statements do
26
+ disable_referential_integrity do
27
+ execute_batch(statements, "Fixtures Load")
28
+ end
29
+ end
30
+ end
31
+
32
+ private
33
+ def execute_batch(statements, name = nil)
34
+ statements.each do |statement|
35
+ execute(statement, name)
36
+ end
37
+ end
38
+
39
+ DEFAULT_INSERT_VALUE = Arel.sql("DEFAULT").freeze
40
+ private_constant :DEFAULT_INSERT_VALUE
41
+
42
+ def default_insert_value(column)
43
+ DEFAULT_INSERT_VALUE
44
+ end
45
+
46
+ def build_fixture_sql(fixtures, table_name)
47
+ columns = schema_cache.columns_hash(table_name)
48
+
49
+ values_list = fixtures.map do |fixture|
50
+ fixture = fixture.stringify_keys
51
+
52
+ unknown_columns = fixture.keys - columns.keys
53
+ if unknown_columns.any?
54
+ raise Fixture::FixtureError, %(table "#{table_name}" has no columns named #{unknown_columns.map(&:inspect).join(', ')}.)
55
+ end
56
+
57
+ columns.map do |name, column|
58
+ if fixture.key?(name)
59
+ type = lookup_cast_type_from_column(column)
60
+ with_yaml_fallback(type.serialize(fixture[name]))
61
+ else
62
+ default_insert_value(column)
63
+ end
64
+ end
65
+ end
66
+
67
+ table = Arel::Table.new(table_name)
68
+ manager = Arel::InsertManager.new
69
+ manager.into(table)
70
+
71
+ if values_list.size == 1
72
+ values = values_list.shift
73
+ new_values = []
74
+ columns.each_key.with_index { |column, i|
75
+ unless values[i].equal?(DEFAULT_INSERT_VALUE)
76
+ new_values << values[i]
77
+ manager.columns << table[column]
78
+ end
79
+ }
80
+ values_list << new_values
81
+ else
82
+ columns.each_key { |column| manager.columns << table[column] }
83
+ end
84
+
85
+ manager.values = manager.create_values_list(values_list)
86
+ manager.to_sql
87
+ end
88
+
89
+ def build_fixture_statements(fixture_set)
90
+ fixture_set.map do |table_name, fixtures|
91
+ next if fixtures.empty?
92
+ build_fixture_sql(fixtures, table_name)
93
+ end.compact
94
+ end
95
+
96
+ def with_multi_statements
97
+ yield
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,28 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module CockroachDB
4
+ module Quoting
5
+ private
6
+
7
+ # CockroachDB does not allow inserting integer values into string
8
+ # columns, but ActiveRecord expects this to work. CockroachDB will
9
+ # however allow inserting string values into integer columns. It will
10
+ # try to parse string values and convert them to integers so they can be
11
+ # inserted in integer columns.
12
+ #
13
+ # We take advantage of this behavior here by forcing numeric values to
14
+ # always be strings. Then, we won't have to make any additional changes
15
+ # to ActiveRecord to support inserting integer values into string
16
+ # columns.
17
+ def _quote(value)
18
+ case value
19
+ when Numeric
20
+ "'#{quote_string(value.to_s)}'"
21
+ else
22
+ super
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,51 +1,36 @@
1
1
  # frozen_string_literal: true
2
- # NOTE(joey): This is cradled from connection_adapters/postgresql/referential_integrity.rb
3
- # It is commonly used for setting up fixtures during tests.
2
+
3
+ # The PostgresSQL Adapter's ReferentialIntegrity module can disable and
4
+ # re-enable foreign key constraints by disabling all table triggers. Since
5
+ # triggers are not available in CockroachDB, we have to remove foreign keys and
6
+ # re-add them via the ActiveRecord API.
7
+ #
8
+ # This module is commonly used to load test fixture data without having to worry
9
+ # about the order in which that data is loaded.
4
10
  module ActiveRecord
5
11
  module ConnectionAdapters
6
12
  module CockroachDB
7
- module ReferentialIntegrity # :nodoc:
8
- def disable_referential_integrity # :nodoc:
9
- original_exception = nil
10
- fkeys = nil
13
+ module ReferentialIntegrity
14
+ def disable_referential_integrity
15
+ foreign_keys = tables.map { |table| foreign_keys(table) }.flatten
11
16
 
12
- begin
13
- transaction do
14
- tables.each do |table_name|
15
- fkeys = foreign_keys(table_name)
16
- fkeys.each do |fkey|
17
- remove_foreign_key table_name, name: fkey.options[:name]
18
- end
19
- end
20
- end
21
- rescue ActiveRecord::ActiveRecordError => e
22
- original_exception = e
17
+ foreign_keys.each do |foreign_key|
18
+ remove_foreign_key(foreign_key.from_table, name: foreign_key.options[:name])
23
19
  end
24
20
 
25
- begin
26
- yield
27
- rescue ActiveRecord::InvalidForeignKey => e
28
- warn <<-WARNING
29
- WARNING: Rails was not able to disable referential integrity.
30
-
31
- Please go to https://github.com/cockroachdb/activerecord-cockroachdb-adapter
32
- and report this issue.
33
-
34
- cause: #{original_exception.try(:message)}
35
-
36
- WARNING
37
- raise e
38
- end
21
+ yield
39
22
 
40
- begin
41
- transaction do
42
- if !fkeys.nil?
43
- fkeys.each do |fkey|
44
- add_foreign_key fkey.from_table, fkey.to_table, fkey.options
45
- end
23
+ foreign_keys.each do |foreign_key|
24
+ begin
25
+ add_foreign_key(foreign_key.from_table, foreign_key.to_table, foreign_key.options)
26
+ rescue ActiveRecord::StatementInvalid => error
27
+ if error.cause.class == PG::DuplicateObject
28
+ # This error is safe to ignore because the yielded caller
29
+ # already re-added the foreign key constraint.
30
+ else
31
+ raise error
46
32
  end
47
33
  end
48
- rescue ActiveRecord::ActiveRecordError
49
34
  end
50
35
  end
51
36
  end
@@ -1,17 +1,70 @@
1
- require 'active_record/connection_adapters/postgresql/schema_statements'
2
-
3
1
  module ActiveRecord
4
2
  module ConnectionAdapters
5
3
  module CockroachDB
6
4
  module SchemaStatements
7
5
  include ActiveRecord::ConnectionAdapters::PostgreSQL::SchemaStatements
8
- # NOTE(joey): This was ripped from PostgresSQL::SchemaStatements, with a
9
- # slight modification to change setval(string, int, bool) to just
10
- # setval(string, int) for CockroachDB compatbility.
11
- # See https://github.com/cockroachdb/cockroach/issues/19723
12
- #
6
+
7
+ def add_index(table_name, column_name, options = {})
8
+ super
9
+ rescue ActiveRecord::StatementInvalid => error
10
+ if debugging? && error.cause.class == PG::FeatureNotSupported
11
+ warn "#{error}\n\nThis error will be ignored and the index will not be created.\n\n"
12
+ else
13
+ raise error
14
+ end
15
+ end
16
+
17
+ # ActiveRecord allows for tables to exist without primary keys.
18
+ # Databases like PostgreSQL support this behavior, but CockroachDB does
19
+ # not. If a table is created without a primary key, CockroachDB will add
20
+ # a rowid column to serve as its primary key. This breaks a lot of
21
+ # ActiveRecord's assumptions so we'll treat tables with rowid primary
22
+ # keys as if they didn't have primary keys at all.
23
+ # https://www.cockroachlabs.com/docs/v19.2/create-table.html#create-a-table
24
+ # https://api.rubyonrails.org/v5.2.4/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-create_table
25
+ def primary_key(table_name)
26
+ pk = super
27
+
28
+ if pk == CockroachDBAdapter::DEFAULT_PRIMARY_KEY
29
+ nil
30
+ else
31
+ pk
32
+ end
33
+ end
34
+
35
+ # CockroachDB uses unique_rowid() for primary keys, not sequences. It's
36
+ # possible to force a table to use sequences, but since it's not the
37
+ # default behavior we'll always return nil for default_sequence_name.
38
+ def default_sequence_name(table_name, pk = "id")
39
+ nil
40
+ end
41
+
42
+ # CockroachDB will use INT8 if the SQL type is INTEGER, so we make it use
43
+ # INT4 explicitly when needed.
44
+ def type_to_sql(type, limit: nil, precision: nil, scale: nil, array: nil, **) # :nodoc:
45
+ sql = \
46
+ case type.to_s
47
+ when "integer"
48
+ case limit
49
+ when nil; "int"
50
+ when 1, 2; "int2"
51
+ when 3, 4; "int4"
52
+ when 5..8; "int8"
53
+ else super
54
+ end
55
+ else
56
+ super
57
+ end
58
+ # The call to super might have appeneded [] already.
59
+ if array && type != :primary_key && !sql.end_with?("[]")
60
+ sql = "#{sql}[]"
61
+ end
62
+ sql
63
+ end
64
+
65
+ # This overrides the method from PostegreSQL adapter
13
66
  # Resets the sequence of a table's primary key to the maximum value.
14
- def reset_pk_sequence!(table, pk = nil, sequence = nil) #:nodoc:
67
+ def reset_pk_sequence!(table, pk = nil, sequence = nil)
15
68
  unless pk && sequence
16
69
  default_pk, default_sequence = pk_and_sequence_for(table)
17
70
 
@@ -27,29 +80,10 @@ module ActiveRecord
27
80
  quoted_sequence = quote_table_name(sequence)
28
81
  max_pk = query_value("SELECT MAX(#{quote_column_name pk}) FROM #{quote_table_name(table)}", "SCHEMA")
29
82
  if max_pk.nil?
30
- if postgresql_version >= 100000
31
- minvalue = query_value("SELECT seqmin FROM pg_sequence WHERE seqrelid = #{quote(quoted_sequence)}::regclass", "SCHEMA")
32
- else
33
- minvalue = query_value("SELECT min_value FROM #{quoted_sequence}", "SCHEMA")
34
- end
83
+ minvalue = query_value("SELECT seqmin FROM pg_sequence WHERE seqrelid = #{quote(quoted_sequence)}::regclass", "SCHEMA")
35
84
  end
36
- if max_pk
37
- # NOTE(joey): This is done to replace the call:
38
- #
39
- # SELECT setval(..., max_pk, false)
40
- #
41
- # with
42
- #
43
- # SELECT setval(..., max_pk-1)
44
- #
45
- # These two statements are semantically equivilant, but
46
- # setval(string, int, bool) is not supported by CockroachDB.
47
- #
48
- # FIXME(joey): This is incorrect if the sequence is not 1
49
- # incremented. We would need to pull out the custom increment value.
50
- max_pk - 1
51
- end
52
- query_value("SELECT setval(#{quote(quoted_sequence)}, #{max_pk ? max_pk : minvalue})", "SCHEMA")
85
+
86
+ query_value("SELECT setval(#{quote(quoted_sequence)}, #{max_pk ? max_pk : minvalue}, #{max_pk ? true : false})", "SCHEMA")
53
87
  end
54
88
  end
55
89
  end
@@ -1,25 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_record/connection_adapters/abstract/transaction'
4
-
5
3
  module ActiveRecord
6
4
  module ConnectionAdapters
7
-
8
- # NOTE(joey): This is a very sad monkey patch. Unfortunately, it is
9
- # required in order to prevent doing more than 2 nested transactions
10
- # while still allowing a single nested transaction. This is because
11
- # CockroachDB only supports a single savepoint at the beginning of a
12
- # transaction. Allowing this works for the common case of testing.
13
5
  module CockroachDB
14
6
  module TransactionManagerMonkeyPatch
15
- def begin_transaction(options={})
16
- @connection.lock.synchronize do
17
- # If the transaction nesting is already 2 deep, raise an error.
18
- if @connection.adapter_name == "CockroachDB" && @stack.is_a?(ActiveRecord::ConnectionAdapters::SavepointTransaction)
19
- raise(ArgumentError, "cannot nest more than 1 transaction at a time. this is a CockroachDB limitation")
20
- end
21
- end
22
- super(options)
7
+ # Capture ActiveRecord::SerializationFailure errors caused by
8
+ # transactions that fail due to serialization errors. Failed
9
+ # transactions will be retried until they pass or the max retry limit is
10
+ # exceeded.
11
+ def within_new_transaction(options = {})
12
+ attempts = options.fetch(:attempts, 0)
13
+ super
14
+ rescue ActiveRecord::SerializationFailure => error
15
+ raise if attempts >= @connection.max_transaction_retries
16
+
17
+ attempts += 1
18
+ sleep_seconds = (2 ** attempts + rand) / 10
19
+ sleep(sleep_seconds)
20
+ within_new_transaction(options.merge(attempts: attempts)) { yield }
23
21
  end
24
22
  end
25
23
  end
@@ -0,0 +1,14 @@
1
+ module ActiveRecord
2
+ module Type
3
+ class << self
4
+ private
5
+
6
+ # Return :postgresql instead of :cockroachdb for current_adapter_name so
7
+ # we can continue using the ActiveRecord::Types defined in
8
+ # PostgreSQLAdapter.
9
+ def current_adapter_name
10
+ :postgresql
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,8 +1,12 @@
1
1
  require 'active_record/connection_adapters/postgresql_adapter'
2
- require "active_record/connection_adapters/postgresql/schema_statements"
3
2
  require "active_record/connection_adapters/cockroachdb/schema_statements"
4
3
  require "active_record/connection_adapters/cockroachdb/referential_integrity"
5
4
  require "active_record/connection_adapters/cockroachdb/transaction_manager"
5
+ require "active_record/connection_adapters/cockroachdb/column"
6
+ require "active_record/connection_adapters/cockroachdb/database_statements"
7
+ require "active_record/connection_adapters/cockroachdb/quoting"
8
+ require "active_record/connection_adapters/cockroachdb/type"
9
+ require "active_record/connection_adapters/cockroachdb/attribute_methods"
6
10
 
7
11
  module ActiveRecord
8
12
  module ConnectionHandling
@@ -23,7 +27,14 @@ module ActiveRecord
23
27
  # The postgres drivers don't allow the creation of an unconnected
24
28
  # PG::Connection object, so just pass a nil connection object for the
25
29
  # time being.
26
- ConnectionAdapters::CockroachDBAdapter.new(nil, logger, conn_params, config)
30
+ conn = PG.connect(conn_params)
31
+ ConnectionAdapters::CockroachDBAdapter.new(conn, logger, conn_params, config)
32
+ rescue ::PG::Error => error
33
+ if error.message.include?("does not exist")
34
+ raise ActiveRecord::NoDatabaseError
35
+ else
36
+ raise
37
+ end
27
38
  end
28
39
  end
29
40
  end
@@ -32,16 +43,29 @@ module ActiveRecord
32
43
  module ConnectionAdapters
33
44
  class CockroachDBAdapter < PostgreSQLAdapter
34
45
  ADAPTER_NAME = "CockroachDB".freeze
46
+ DEFAULT_PRIMARY_KEY = "rowid"
35
47
 
36
48
  include CockroachDB::SchemaStatements
37
49
  include CockroachDB::ReferentialIntegrity
50
+ include CockroachDB::DatabaseStatements
51
+ include CockroachDB::Quoting
52
+
53
+ def debugging?
54
+ !!ENV["DEBUG_COCKROACHDB_ADAPTER"]
55
+ end
38
56
 
57
+ def max_transaction_retries
58
+ @max_transaction_retries ||= @config.fetch(:max_transaction_retries, 3)
59
+ end
60
+
61
+ # CockroachDB 20.1 can run queries that work against PostgreSQL 10+.
62
+ def postgresql_version
63
+ 100000
64
+ end
39
65
 
40
- # Note that in the migration from ActiveRecord 5.0 to 5.1, the
41
- # `extract_schema_qualified_name` method was aliased in the PostgreSQLAdapter.
42
- # To ensure backward compatibility with both <5.1 and 5.1, we rename it here
43
- # to use the same original `Utils` module.
44
- Utils = PostgreSQL::Utils
66
+ def supports_bulk_alter?
67
+ false
68
+ end
45
69
 
46
70
  def supports_json?
47
71
  # FIXME(joey): Add a version check.
@@ -56,22 +80,12 @@ module ActiveRecord
56
80
  false
57
81
  end
58
82
 
59
- def supports_ranges?
60
- # See cockroachdb/cockroach#17022
61
- false
62
- end
63
-
64
83
  def supports_materialized_views?
65
84
  false
66
85
  end
67
86
 
68
- def supports_pg_crypto_uuid?
69
- false
70
- end
71
-
72
87
  def supports_partial_index?
73
- # See cockroachdb/cockroach#9683
74
- false
88
+ @crdb_version >= 202
75
89
  end
76
90
 
77
91
  def supports_expression_index?
@@ -94,8 +108,7 @@ module ActiveRecord
94
108
  end
95
109
 
96
110
  def supports_advisory_locks?
97
- # FIXME(joey): We may want to make this false.
98
- true
111
+ false
99
112
  end
100
113
 
101
114
  def supports_virtual_columns?
@@ -103,114 +116,8 @@ module ActiveRecord
103
116
  false
104
117
  end
105
118
 
106
- def supports_savepoints?
107
- # See cockroachdb/cockroach#10735.
108
- false
109
- end
110
-
111
- def transaction_isolation_levels
112
- {
113
- # Explicitly prevent READ UNCOMMITTED from being used. This
114
- # was due to the READ UNCOMMITTED test failing.
115
- # read_uncommitted: "READ UNCOMMITTED",
116
- read_committed: "READ COMMITTED",
117
- repeatable_read: "REPEATABLE READ",
118
- serializable: "SERIALIZABLE"
119
- }
120
- end
121
-
122
-
123
- # Sadly, we can only do savepoints at the beginning of
124
- # transactions. This means that we cannot use them for most cases
125
- # of transaction, so we just pretend they're usable.
126
- def create_savepoint(name = "COCKROACH_RESTART"); end
127
-
128
- def exec_rollback_to_savepoint(name = "COCKROACH_RESTART"); end
129
-
130
- def release_savepoint(name = "COCKROACH_RESTART"); end
131
-
132
- def indexes(table_name, name = nil) # :nodoc:
133
- # The PostgreSQL adapter uses a correlated subquery in the following query,
134
- # which CockroachDB does not yet support. That portion of the query fetches
135
- # any non-standard opclasses that each index uses. CockroachDB also doesn't
136
- # support opclasses at this time, so the query is modified to just remove
137
- # the section about opclasses entirely.
138
- if name
139
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
140
- Passing name to #indexes is deprecated without replacement.
141
- MSG
142
- end
143
-
144
- table = Utils.extract_schema_qualified_name(table_name.to_s)
145
-
146
- result = query(<<-SQL, "SCHEMA")
147
- SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid,
148
- pg_catalog.obj_description(i.oid, 'pg_class') AS comment
149
- FROM pg_class t
150
- INNER JOIN pg_index d ON t.oid = d.indrelid
151
- INNER JOIN pg_class i ON d.indexrelid = i.oid
152
- LEFT JOIN pg_namespace n ON n.oid = i.relnamespace
153
- WHERE i.relkind = 'i'
154
- AND d.indisprimary = 'f'
155
- AND t.relname = '#{table.identifier}'
156
- AND n.nspname = #{table.schema ? "'#{table.schema}'" : 'ANY (current_schemas(false))'}
157
- ORDER BY i.relname
158
- SQL
159
-
160
- result.map do |row|
161
- index_name = row[0]
162
- unique = row[1]
163
- indkey = row[2].split(" ").map(&:to_i)
164
- inddef = row[3]
165
- oid = row[4]
166
- comment = row[5]
167
-
168
- expressions, where = inddef.scan(/\((.+?)\)(?: WHERE (.+))?\z/).flatten
169
-
170
- if indkey.include?(0)
171
- columns = expressions
172
- else
173
- columns = Hash[query(<<-SQL.strip_heredoc, "SCHEMA")].values_at(*indkey).compact
174
- SELECT a.attnum, a.attname
175
- FROM pg_attribute a
176
- WHERE a.attrelid = #{oid}
177
- AND a.attnum IN (#{indkey.join(",")})
178
- SQL
179
-
180
- # add info on sort order for columns (only desc order is explicitly specified, asc is the default)
181
- orders = Hash[
182
- expressions.scan(/(\w+) DESC/).flatten.map { |order_column| [order_column, :desc] }
183
- ]
184
- end
185
-
186
- # FIXME(joey): This may be specific to ActiveRecord 5.2.
187
- IndexDefinition.new(
188
- table_name,
189
- index_name,
190
- unique,
191
- columns,
192
- orders: orders,
193
- where: where,
194
- comment: comment.presence
195
- )
196
- end.compact
197
- end
198
-
199
-
200
- def primary_keys(table_name)
201
- name = Utils.extract_schema_qualified_name(table_name.to_s)
202
- select_values(<<-SQL.strip_heredoc, "SCHEMA")
203
- SELECT column_name
204
- FROM information_schema.key_column_usage kcu
205
- JOIN information_schema.table_constraints tc
206
- ON kcu.table_name = tc.table_name
207
- AND kcu.table_schema = tc.table_schema
208
- AND kcu.constraint_name = tc.constraint_name
209
- WHERE constraint_type = 'PRIMARY KEY'
210
- AND kcu.table_name = #{quote(name.identifier)}
211
- AND kcu.table_schema = #{name.schema ? quote(name.schema) : "ANY (current_schemas(false))"}
212
- ORDER BY kcu.ordinal_position
213
- SQL
119
+ def supports_string_to_array_coercion?
120
+ @crdb_version >= 202
214
121
  end
215
122
 
216
123
  # This is hardcoded to 63 (as previously was in ActiveRecord 5.0) to aid in
@@ -228,6 +135,25 @@ module ActiveRecord
228
135
  alias index_name_length max_identifier_length
229
136
  alias table_alias_length max_identifier_length
230
137
 
138
+ def initialize(connection, logger, conn_params, config)
139
+ super(connection, logger, conn_params, config)
140
+ crdb_version_string = query_value("SHOW crdb_version")
141
+ if crdb_version_string.include? "v1."
142
+ version_num = 1
143
+ elsif crdb_version_string.include? "v2."
144
+ version_num 2
145
+ elsif crdb_version_string.include? "v19.1."
146
+ version_num = 191
147
+ elsif crdb_version_string.include? "v19.2."
148
+ version_num = 192
149
+ elsif crdb_version_string.include? "v20.1."
150
+ version_num = 201
151
+ else
152
+ version_num = 202
153
+ end
154
+ @crdb_version = version_num
155
+ end
156
+
231
157
  private
232
158
 
233
159
  def initialize_type_map(m = type_map)
@@ -295,6 +221,62 @@ module ActiveRecord
295
221
  end
296
222
  end
297
223
 
224
+ # Override extract_value_from_default because the upstream definition
225
+ # doesn't handle the variations in CockroachDB's behavior.
226
+ def extract_value_from_default(default)
227
+ super ||
228
+ extract_escaped_string_from_default(default) ||
229
+ extract_time_from_default(default) ||
230
+ extract_empty_array_from_default(default)
231
+ end
232
+
233
+ # Both PostgreSQL and CockroachDB use C-style string escapes under the
234
+ # covers. PostgreSQL obscures this for us and unescapes the strings, but
235
+ # CockroachDB does not. Here we'll use Ruby to unescape the string.
236
+ # See https://github.com/cockroachdb/cockroach/issues/47497 and
237
+ # https://www.postgresql.org/docs/9.2/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-ESCAPE.
238
+ def extract_escaped_string_from_default(default)
239
+ # Escaped strings start with an e followed by the string in quotes (e'…')
240
+ return unless default =~ /\A[\(B]?e'(.*)'.*::"?([\w. ]+)"?(?:\[\])?\z/m
241
+
242
+ # String#undump doesn't account for escaped single quote characters
243
+ "\"#{$1}\"".undump.gsub("\\'".freeze, "'".freeze)
244
+ end
245
+
246
+ # This method exists to extract the correct time and date defaults for a
247
+ # couple of reasons.
248
+ # 1) There's a bug in CockroachDB where the date type is missing from
249
+ # the column info query.
250
+ # https://github.com/cockroachdb/cockroach/issues/47285
251
+ # 2) PostgreSQL's timestamp without time zone type maps to CockroachDB's
252
+ # TIMESTAMP type. TIMESTAMP includes a UTC time zone while timestamp
253
+ # without time zone doesn't.
254
+ # https://www.cockroachlabs.com/docs/v19.2/timestamp.html#variants
255
+ def extract_time_from_default(default)
256
+ return unless default =~ /\A'(.*)'\z/
257
+
258
+ # If default has a UTC time zone, we'll drop the time zone information
259
+ # so it acts like PostgreSQL's timestamp without time zone. Then, try
260
+ # to parse the resulting string to verify if it's a time.
261
+ time = if default =~ /\A'(.*)(\+00:00)'\z/
262
+ $1
263
+ else
264
+ default
265
+ end
266
+
267
+ Time.parse(time).to_s
268
+ rescue
269
+ nil
270
+ end
271
+
272
+ # CockroachDB stores default values for arrays in the `ARRAY[...]` format.
273
+ # In general, it is hard to parse that, but it is easy to handle the common
274
+ # case of an empty array.
275
+ def extract_empty_array_from_default(default)
276
+ return unless supports_string_to_array_coercion?
277
+ return unless default =~ /\AARRAY\[\]\z/
278
+ return "{}"
279
+ end
298
280
 
299
281
  # end private
300
282
  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: 0.2.3
4
+ version: 6.0.0beta1
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: 2018-04-19 00:00:00.000000000 Z
11
+ date: 2020-12-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '5.2'
19
+ version: 6.0.3
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '5.2'
26
+ version: 6.0.3
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: pg
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -31,9 +31,6 @@ dependencies:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0.20'
34
- - - "<"
35
- - !ruby/object:Gem::Version
36
- version: '0.22'
37
34
  type: :runtime
38
35
  prerelease: false
39
36
  version_requirements: !ruby/object:Gem::Requirement
@@ -41,51 +38,6 @@ dependencies:
41
38
  - - ">="
42
39
  - !ruby/object:Gem::Version
43
40
  version: '0.20'
44
- - - "<"
45
- - !ruby/object:Gem::Version
46
- version: '0.22'
47
- - !ruby/object:Gem::Dependency
48
- name: bundler
49
- requirement: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - "~>"
52
- - !ruby/object:Gem::Version
53
- version: '1.14'
54
- type: :development
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - "~>"
59
- - !ruby/object:Gem::Version
60
- version: '1.14'
61
- - !ruby/object:Gem::Dependency
62
- name: rake
63
- requirement: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - "~>"
66
- - !ruby/object:Gem::Version
67
- version: '10.0'
68
- type: :development
69
- prerelease: false
70
- version_requirements: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - "~>"
73
- - !ruby/object:Gem::Version
74
- version: '10.0'
75
- - !ruby/object:Gem::Dependency
76
- name: minitest
77
- requirement: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - "~>"
80
- - !ruby/object:Gem::Version
81
- version: '5.0'
82
- type: :development
83
- prerelease: false
84
- version_requirements: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - "~>"
87
- - !ruby/object:Gem::Version
88
- version: '5.0'
89
41
  description: Allows the use of CockroachDB as a backend for ActiveRecord and Rails
90
42
  apps.
91
43
  email:
@@ -109,10 +61,15 @@ files:
109
61
  - build/local-test.sh
110
62
  - build/teamcity-test.sh
111
63
  - docker.sh
64
+ - lib/active_record/connection_adapters/cockroachdb/attribute_methods.rb
65
+ - lib/active_record/connection_adapters/cockroachdb/column.rb
66
+ - lib/active_record/connection_adapters/cockroachdb/database_statements.rb
112
67
  - lib/active_record/connection_adapters/cockroachdb/database_tasks.rb
68
+ - lib/active_record/connection_adapters/cockroachdb/quoting.rb
113
69
  - lib/active_record/connection_adapters/cockroachdb/referential_integrity.rb
114
70
  - lib/active_record/connection_adapters/cockroachdb/schema_statements.rb
115
71
  - lib/active_record/connection_adapters/cockroachdb/transaction_manager.rb
72
+ - lib/active_record/connection_adapters/cockroachdb/type.rb
116
73
  - lib/active_record/connection_adapters/cockroachdb_adapter.rb
117
74
  - lib/activerecord-cockroachdb-adapter.rb
118
75
  homepage: https://github.com/cockroachdb/activerecord-cockroachdb-adapter
@@ -120,7 +77,7 @@ licenses:
120
77
  - Apache-2.0
121
78
  metadata:
122
79
  allowed_push_host: https://rubygems.org
123
- post_install_message:
80
+ post_install_message:
124
81
  rdoc_options: []
125
82
  require_paths:
126
83
  - lib
@@ -131,13 +88,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
131
88
  version: '0'
132
89
  required_rubygems_version: !ruby/object:Gem::Requirement
133
90
  requirements:
134
- - - ">="
91
+ - - ">"
135
92
  - !ruby/object:Gem::Version
136
- version: '0'
93
+ version: 1.3.1
137
94
  requirements: []
138
- rubyforge_project:
139
- rubygems_version: 2.5.2
140
- signing_key:
95
+ rubygems_version: 3.1.4
96
+ signing_key:
141
97
  specification_version: 4
142
98
  summary: CockroachDB adapter for ActiveRecord.
143
99
  test_files: []