activerecord-cockroachdb-adapter 0.2.3 → 6.0.0beta1

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
- 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: []