activerecord-cockroachdb-adapter 7.0.2 → 7.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +86 -0
- data/CHANGELOG.md +9 -0
- data/CONTRIBUTING.md +6 -26
- data/Gemfile +34 -43
- data/README.md +1 -1
- data/Rakefile +5 -15
- data/activerecord-cockroachdb-adapter.gemspec +2 -5
- data/bin/console +43 -7
- data/bin/start-cockroachdb +48 -0
- data/build/teamcity-test.sh +2 -7
- data/lib/active_record/connection_adapters/cockroachdb/column.rb +1 -5
- data/lib/active_record/connection_adapters/cockroachdb/database_tasks.rb +79 -2
- data/lib/active_record/connection_adapters/cockroachdb/quoting.rb +6 -0
- data/lib/active_record/connection_adapters/cockroachdb/schema_statements.rb +2 -2
- data/lib/active_record/connection_adapters/cockroachdb/type.rb +5 -2
- data/lib/active_record/connection_adapters/cockroachdb_adapter.rb +2 -0
- data/lib/active_record/relation/query_methods_ext.rb +98 -0
- data/lib/activerecord-cockroachdb-adapter.rb +1 -1
- data/lib/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 594ac59a7a678d5619ea771e3130a481481560adcc88032d7c17d61b6dabc279
|
4
|
+
data.tar.gz: 0cd6ea6bd6a1fe808142a91e35a24d4e15a59b48f56e4dba37d8a25584dd7a8a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 56205a247976012b6a25691045a773ca9fefecc1b98bb47ee83fb85dffede72a8aed5bc605a332d00b31fb57f67ee1018b850d14638581454980a6b96d2e8865
|
7
|
+
data.tar.gz: 92515e498cc8cedfe284cfe4cf9b3cb87eae72630aa5828e5983dfabe488ad214386561a0fb8072963b0796559209ee033cb010495d263d44eb1abf048afaa37
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# Inspired from:
|
2
|
+
# - https://github.com/cockroachdb/sqlalchemy-cockroachdb/blob/master/.github/workflows/ci.yml
|
3
|
+
# - https://github.com/rgeo/activerecord-postgis-adapter/blob/master/.github/workflows/tests.yml
|
4
|
+
name: Test
|
5
|
+
|
6
|
+
on:
|
7
|
+
# Triggers the workflow on push or pull request events.
|
8
|
+
push:
|
9
|
+
# This should disable running the workflow on tags, according to the
|
10
|
+
# on.<push|pull_request>.<branches|tags> GitHub Actions docs.
|
11
|
+
branches:
|
12
|
+
- "*"
|
13
|
+
pull_request:
|
14
|
+
types: [opened, reopened, synchronize]
|
15
|
+
|
16
|
+
# Allows you to run this workflow manually from the Actions tab
|
17
|
+
workflow_dispatch:
|
18
|
+
|
19
|
+
# This allows a subsequently queued workflow run to interrupt previous runs.
|
20
|
+
concurrency:
|
21
|
+
group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'
|
22
|
+
cancel-in-progress: true
|
23
|
+
|
24
|
+
jobs:
|
25
|
+
test:
|
26
|
+
runs-on: ubuntu-latest
|
27
|
+
strategy:
|
28
|
+
matrix:
|
29
|
+
crdb: [v23.1.5]
|
30
|
+
ruby: [ruby-head]
|
31
|
+
name: Test (crdb=${{ matrix.crdb }} ruby=${{ matrix.ruby }})
|
32
|
+
steps:
|
33
|
+
- name: Set Up Actions
|
34
|
+
uses: actions/checkout@v3
|
35
|
+
- name: Install GEOS
|
36
|
+
run: sudo apt-get install libgeos-dev
|
37
|
+
- name: Set Up Ruby
|
38
|
+
uses: ruby/setup-ruby@v1
|
39
|
+
with:
|
40
|
+
ruby-version: ${{ matrix.ruby }}
|
41
|
+
bundler-cache: true
|
42
|
+
- name: Install and Start Cockroachdb
|
43
|
+
run: |
|
44
|
+
# Download CockroachDB
|
45
|
+
wget -qO- https://binaries.cockroachdb.com/cockroach-${{ matrix.crdb }}.linux-amd64.tgz | tar xvz
|
46
|
+
|
47
|
+
export PATH=./cockroach-${{ matrix.crdb }}.linux-amd64/:$PATH
|
48
|
+
readonly urlfile=cockroach-url
|
49
|
+
|
50
|
+
# Start a CockroachDB server and wait for it to become ready.
|
51
|
+
rm -f "$urlfile"
|
52
|
+
rm -rf cockroach-data
|
53
|
+
# Start CockroachDB.
|
54
|
+
cockroach start-single-node --max-sql-memory=25% --cache=25% --insecure --host=localhost --spatial-libs=./cockroach-${{ matrix.crdb }}.linux-amd64/lib --listening-url-file="$urlfile" >/dev/null 2>&1 &
|
55
|
+
# Ensure CockroachDB is stopped on script exit.
|
56
|
+
# Wait until CockroachDB has started.
|
57
|
+
for i in {0..3}; do
|
58
|
+
[[ -f "$urlfile" ]] && break
|
59
|
+
backoff=$((2 ** i))
|
60
|
+
echo "server not yet available; sleeping for $backoff seconds"
|
61
|
+
sleep $backoff
|
62
|
+
done
|
63
|
+
cockroach sql --insecure -e "
|
64
|
+
CREATE DATABASE activerecord_unittest;
|
65
|
+
CREATE DATABASE activerecord_unittest2;
|
66
|
+
SET CLUSTER SETTING sql.stats.automatic_collection.enabled = false;
|
67
|
+
SET CLUSTER SETTING sql.stats.histogram_collection.enabled = false;
|
68
|
+
SET CLUSTER SETTING jobs.retention_time = '180s';
|
69
|
+
SET CLUSTER SETTING sql.defaults.experimental_alter_column_type.enabled = 'true';
|
70
|
+
|
71
|
+
ALTER RANGE default CONFIGURE ZONE USING num_replicas = 1, gc.ttlseconds = 30;
|
72
|
+
ALTER TABLE system.public.jobs CONFIGURE ZONE USING num_replicas = 1, gc.ttlseconds = 30;
|
73
|
+
ALTER RANGE meta CONFIGURE ZONE USING num_replicas = 1, gc.ttlseconds = 30;
|
74
|
+
ALTER RANGE system CONFIGURE ZONE USING num_replicas = 1, gc.ttlseconds = 30;
|
75
|
+
ALTER RANGE liveness CONFIGURE ZONE USING num_replicas = 1, gc.ttlseconds = 30;
|
76
|
+
|
77
|
+
SET CLUSTER SETTING kv.range_merge.queue_interval = '50ms';
|
78
|
+
SET CLUSTER SETTING kv.raft_log.disable_synchronization_unsafe = 'true';
|
79
|
+
SET CLUSTER SETTING jobs.registry.interval.cancel = '180s';
|
80
|
+
SET CLUSTER SETTING jobs.registry.interval.gc = '30s';
|
81
|
+
SET CLUSTER SETTING kv.range_split.by_load_merge_delay = '5s';
|
82
|
+
|
83
|
+
SET CLUSTER SETTING sql.defaults.experimental_temporary_tables.enabled = 'true';
|
84
|
+
"
|
85
|
+
- name: Test
|
86
|
+
run: bundle exec rake test
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## Ongoing
|
4
|
+
|
5
|
+
## 7.0.3 - 2023-08-23
|
6
|
+
|
7
|
+
- Fix Multiple Database connections ([#283](https://github.com/cockroachdb/activerecord-cockroachdb-adapter/pull/)).
|
8
|
+
- Add support for sql load in rake tasks ([#275](https://github.com/cockroachdb/activerecord-cockroachdb-adapter/pull/)).
|
9
|
+
- Add support for sql dump in rake tasks ([#273](https://github.com/cockroachdb/activerecord-cockroachdb-adapter/pull/)).
|
10
|
+
- Add support for table optimize hints ([#266](https://github.com/cockroachdb/activerecord-cockroachdb-adapter/pull/)).
|
11
|
+
|
3
12
|
## 7.0.2 - 2023-05-23
|
4
13
|
|
5
14
|
- Fix default numbers test to expect the correct result after
|
data/CONTRIBUTING.md
CHANGED
@@ -15,12 +15,15 @@ override and monkey-patch functionality.
|
|
15
15
|
|
16
16
|
## Setup and running tests
|
17
17
|
|
18
|
-
|
18
|
+
### CockroachDB
|
19
|
+
|
20
|
+
First, You should setup a cockroachdb local instance. You can use the
|
21
|
+
`bin/start-cockroachdb` to help you with that task. Otherwise, once setup,
|
22
|
+
create two databases to be used by the ActiveRecord test suite:
|
19
23
|
activerecord_unittest and activerecord_unittest2.
|
20
24
|
|
21
25
|
```sql
|
22
26
|
CREATE DATABASE activerecord_unittest;
|
23
|
-
|
24
27
|
CREATE DATABASE activerecord_unittest2;
|
25
28
|
```
|
26
29
|
|
@@ -87,12 +90,6 @@ To run a specific test case, use minitest's `-n` option to run tests that match
|
|
87
90
|
TEST_FILES="test/cases/adapter_test.rb" TESTOPTS=`-n=/test_indexes/` bundle exec rake test
|
88
91
|
```
|
89
92
|
|
90
|
-
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.
|
91
|
-
|
92
|
-
```bash
|
93
|
-
RAILS_SOURCE="path/to/local_copy" bundle exec rake test
|
94
|
-
```
|
95
|
-
|
96
93
|
`test/config.yml` assumes CockroachDB will be running at localhost:26257 with a root user. Make changes to `test/config.yml` as needed.
|
97
94
|
|
98
95
|
### Run Tests from a Backup
|
@@ -117,23 +114,6 @@ And the `activerecord_unittest` database will use the `RESTORE` command to load
|
|
117
114
|
|
118
115
|
# Improvements
|
119
116
|
|
120
|
-
|
121
|
-
## Support past Rails versions
|
122
|
-
|
123
|
-
Currently, only a beta version of Rails is tested. This means that the
|
124
|
-
adapter has been modified in to accommodate unreleased changes. In order
|
125
|
-
to run the tests for Rails 5.1 or 4.2, the test changes will need to be
|
126
|
-
cherry-picked back. Conflicts are mostly only expected for tests that
|
127
|
-
have not yet been added.
|
128
|
-
|
129
|
-
Sadly, this does mean that we will have to have multiple versions of the
|
130
|
-
driver for the multiple versions of Rails.
|
131
|
-
|
132
|
-
A proposal for the CockroachDB adapter versioning would be to follow
|
133
|
-
ActiveRecord minor versions. For example, if you use Rails 4.2.5, you
|
134
|
-
would specify the CockroachDB version `~> 4.2.0`.
|
135
|
-
|
136
|
-
|
137
117
|
## Running CI automatically
|
138
118
|
|
139
119
|
Currently the fork is set up to run using TeamCity only on the current
|
@@ -247,7 +227,7 @@ need to be cleaned up.
|
|
247
227
|
|
248
228
|
# Notes for the non-Rubyer
|
249
229
|
|
250
|
-
|
230
|
+
rbenv is an environment manager that lets you manage and swap between
|
251
231
|
multiple versions of Ruby and their dependencies.
|
252
232
|
|
253
233
|
bundle is dependency manager that uses a projects `Gemfile` (and often
|
data/Gemfile
CHANGED
@@ -1,58 +1,49 @@
|
|
1
|
-
|
2
|
-
source 'https://rubygems.org'
|
3
|
-
gemspec
|
1
|
+
# frozen_string_literal: true
|
4
2
|
|
5
|
-
|
6
|
-
gemspec path: ENV['RAILS_SOURCE']
|
7
|
-
else
|
8
|
-
def get_version_from_gemspec
|
9
|
-
gemspec = eval(File.read('activerecord-cockroachdb-adapter.gemspec'))
|
3
|
+
source "https://rubygems.org"
|
10
4
|
|
11
|
-
|
12
|
-
find { |dep| dep.name == 'activerecord' }.
|
13
|
-
requirement.
|
14
|
-
requirements.
|
15
|
-
first.
|
16
|
-
last
|
5
|
+
gemspec
|
17
6
|
|
18
|
-
major, minor, tiny, pre = gem_version.segments
|
19
7
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
8
|
+
module RailsTag
|
9
|
+
class << self
|
10
|
+
def call
|
11
|
+
req = gemspec_requirement
|
12
|
+
"v" + all_activerecord_versions.find { req.satisfied_by?(_1) }.version
|
24
13
|
end
|
25
|
-
end
|
26
14
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
15
|
+
def gemspec_requirement
|
16
|
+
File
|
17
|
+
.foreach(File.expand_path("activerecord-cockroachdb-adapter.gemspec", __dir__), chomp: true)
|
18
|
+
.find { _1[/add_dependency\s.activerecord.,\s.(.*)./] }
|
19
|
+
|
20
|
+
Gem::Requirement.new(Regexp.last_match(1))
|
21
|
+
end
|
35
22
|
|
36
|
-
|
37
|
-
|
38
|
-
|
23
|
+
def all_activerecord_versions
|
24
|
+
require 'net/http'
|
25
|
+
require 'yaml'
|
39
26
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
27
|
+
uri = URI.parse "https://rubygems.org/api/v1/versions/activerecord.yaml"
|
28
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
29
|
+
http.use_ssl = true
|
30
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
44
31
|
|
45
|
-
|
46
|
-
|
47
|
-
|
32
|
+
YAML.load(
|
33
|
+
http.request(Net::HTTP::Get.new(uri.request_uri)).body
|
34
|
+
).map { Gem::Version.new(_1["number"]) }
|
35
|
+
end
|
48
36
|
end
|
49
|
-
|
50
|
-
# Get Rails from source because 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
37
|
end
|
54
38
|
|
55
|
-
|
39
|
+
|
40
|
+
group :development, :test do
|
41
|
+
# We need to load the gem from git to have access to activerecord's test files.
|
42
|
+
# You can use `path: "some/local/rails"` if you want to test the gem against
|
43
|
+
# a specific rails codebase.
|
44
|
+
gem "rails", github: "rails/rails", tag: RailsTag.call
|
45
|
+
|
46
|
+
gem "rake"
|
56
47
|
gem "byebug"
|
57
48
|
gem "minitest-excludes", "~> 2.0.1"
|
58
49
|
|
data/README.md
CHANGED
@@ -321,7 +321,7 @@ p modified_fac.parse_wkt(wkt)
|
|
321
321
|
#=> #<RGeo::Geographic::SphericalPolygonImpl>
|
322
322
|
```
|
323
323
|
|
324
|
-
Be careful when performing calculations on potentially invalid geometries, as the results might be nonsensical. For example, the area returned of an hourglass made of 2 equivalent triangles with a self-intersection in the middle is 0.
|
324
|
+
Be careful when performing calculations on potentially invalid geometries, as the results might be nonsensical. For example, the area returned of an hourglass made of 2 equivalent triangles with a self-intersection in the middle is 0.
|
325
325
|
|
326
326
|
Note that when using the `spherical_factory`, there is a chance that valid geometries will be interpreted as invalid due to floating point issues with small geometries.
|
327
327
|
|
data/Rakefile
CHANGED
@@ -4,14 +4,12 @@ require_relative 'test/support/paths_cockroachdb'
|
|
4
4
|
require_relative 'test/support/rake_helpers'
|
5
5
|
require_relative 'test/support/template_creator'
|
6
6
|
|
7
|
-
task test: ["test:cockroachdb"]
|
8
7
|
task default: [:test]
|
9
8
|
|
10
9
|
namespace :db do
|
11
10
|
task "create_test_template" do
|
12
11
|
ENV['DEBUG_COCKROACHDB_ADAPTER'] = "1"
|
13
12
|
ENV['COCKROACH_SKIP_LOAD_SCHEMA'] = "1"
|
14
|
-
ENV["ARCONN"] = "cockroachdb"
|
15
13
|
|
16
14
|
TemplateCreator.connect
|
17
15
|
require_relative 'test/cases/helper'
|
@@ -26,17 +24,9 @@ namespace :db do
|
|
26
24
|
end
|
27
25
|
end
|
28
26
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
t.verbose = false
|
35
|
-
end
|
36
|
-
|
37
|
-
task "cockroachdb:env" do
|
38
|
-
ENV["ARCONN"] = "cockroachdb"
|
39
|
-
end
|
27
|
+
Rake::TestTask.new do |t|
|
28
|
+
t.libs = ARTest::CockroachDB.test_load_paths
|
29
|
+
t.test_files = RakeHelpers.test_files
|
30
|
+
t.warning = !!ENV["WARNING"]
|
31
|
+
t.verbose = false
|
40
32
|
end
|
41
|
-
|
42
|
-
task 'test:cockroachdb' => 'test:cockroachdb:env'
|
@@ -1,9 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
-
|
6
|
-
require './lib/version.rb'
|
3
|
+
require_relative 'lib/version'
|
7
4
|
version = ActiveRecord::COCKROACH_DB_ADAPTER_VERSION
|
8
5
|
|
9
6
|
Gem::Specification.new do |spec|
|
data/bin/console
CHANGED
@@ -1,14 +1,50 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
require "activerecord/cockroachdb"
|
3
|
+
$:.unshift(File.expand_path("../lib", __dir__))
|
5
4
|
|
6
|
-
#
|
7
|
-
#
|
5
|
+
# require "bundler/setup"
|
6
|
+
# Bundler.require :development
|
8
7
|
|
9
|
-
|
10
|
-
#
|
11
|
-
#
|
8
|
+
require "active_record"
|
9
|
+
# This allows playing with the rake task as well. Ex:
|
10
|
+
#
|
11
|
+
# ActiveRecord::Tasks::DatabaseTasks.
|
12
|
+
# structure_load(Post.connection_db_config, "awesome-file.sql")
|
13
|
+
require "active_record/connection_adapters/cockroachdb/database_tasks"
|
14
|
+
|
15
|
+
begin
|
16
|
+
retried = false
|
17
|
+
ActiveRecord::Base.establish_connection(
|
18
|
+
#Alternative version: "cockroachdb://root@localhost:26257/ar_crdb_console"
|
19
|
+
adapter: "cockroachdb",
|
20
|
+
host: "localhost",
|
21
|
+
port: 26257,
|
22
|
+
user: "root",
|
23
|
+
database: "ar_crdb_console"
|
24
|
+
)
|
25
|
+
ActiveRecord::Base.connection
|
26
|
+
rescue ActiveRecord::NoDatabaseError
|
27
|
+
raise if retried
|
28
|
+
system("cockroach sql --insecure --host=localhost:26257 --execute='create database ar_crdb_console'",
|
29
|
+
exception: true)
|
30
|
+
retried = true
|
31
|
+
retry
|
32
|
+
end
|
33
|
+
|
34
|
+
class Post < ActiveRecord::Base
|
35
|
+
end
|
36
|
+
|
37
|
+
unless Post.table_exists?
|
38
|
+
migration = Class.new(ActiveRecord::Migration::Current) do
|
39
|
+
def up
|
40
|
+
create_table("posts") do |t|
|
41
|
+
t.string :title
|
42
|
+
t.text :body
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
migration.migrate(:up)
|
47
|
+
end
|
12
48
|
|
13
49
|
require "irb"
|
14
50
|
IRB.start(__FILE__)
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#!/usr/bin/env zsh
|
2
|
+
|
3
|
+
set -eu
|
4
|
+
|
5
|
+
die() { echo "$0: $*" 1>&2 ; false; }
|
6
|
+
|
7
|
+
root_dir="$(dirname $(dirname "$0:A"))"
|
8
|
+
pid_file="$root_dir/tmp/cockroach.pid"
|
9
|
+
log_file="$root_dir/tmp/cockroachdb.log"
|
10
|
+
|
11
|
+
mkdir -p "$root_dir/tmp"
|
12
|
+
rm -f "$pid_file"
|
13
|
+
|
14
|
+
if ! (( ${+commands[cockroach]} )); then
|
15
|
+
die 'the `cockroach` toolchain is not installed.
|
16
|
+
See https://www.cockroachlabs.com/docs/stable/install-cockroachdb.html'
|
17
|
+
fi
|
18
|
+
|
19
|
+
cockroach start-single-node \
|
20
|
+
--insecure --store=type=mem,size=0.25 --advertise-addr=localhost --pid-file "$pid_file" \
|
21
|
+
&> "$log_file" &
|
22
|
+
|
23
|
+
cockroach_pid=$!
|
24
|
+
|
25
|
+
until [[ -f "$pid_file" ]]; do
|
26
|
+
sleep 1
|
27
|
+
done
|
28
|
+
|
29
|
+
|
30
|
+
cat <<-SQL | cockroach sql --insecure --host=localhost:26257 > /dev/null
|
31
|
+
-- https://www.cockroachlabs.com/docs/stable/local-testing.html
|
32
|
+
SET CLUSTER SETTING kv.raft_log.disable_synchronization_unsafe = true;
|
33
|
+
SET CLUSTER SETTING kv.range_merge.queue_interval = '50ms';
|
34
|
+
SET CLUSTER SETTING jobs.registry.interval.gc = '30s';
|
35
|
+
SET CLUSTER SETTING jobs.registry.interval.cancel = '180s';
|
36
|
+
SET CLUSTER SETTING jobs.retention_time = '15s';
|
37
|
+
SET CLUSTER SETTING sql.stats.automatic_collection.enabled = false;
|
38
|
+
SET CLUSTER SETTING kv.range_split.by_load_merge_delay = '5s';
|
39
|
+
ALTER RANGE default CONFIGURE ZONE USING "gc.ttlseconds" = 600;
|
40
|
+
ALTER DATABASE system CONFIGURE ZONE USING "gc.ttlseconds" = 600;
|
41
|
+
|
42
|
+
CREATE DATABASE activerecord_unittest;
|
43
|
+
CREATE DATABASE activerecord_unittest2;
|
44
|
+
SQL
|
45
|
+
|
46
|
+
tail -f "$log_file"
|
47
|
+
|
48
|
+
trap "kill $cockroach_pid" EXIT
|
data/build/teamcity-test.sh
CHANGED
@@ -70,12 +70,7 @@ run_cockroach
|
|
70
70
|
|
71
71
|
if ! (RUBYOPT="-W0" TESTOPTS="-v" bundle exec rake test); then
|
72
72
|
echo "Tests failed"
|
73
|
-
|
74
|
-
else
|
75
|
-
echo "Tests passed"
|
76
|
-
HAS_FAILED=0
|
73
|
+
exit 1
|
77
74
|
fi
|
78
75
|
|
79
|
-
|
80
|
-
exit 1
|
81
|
-
fi
|
76
|
+
echo "Tests passed"
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module ConnectionAdapters
|
3
3
|
module CockroachDB
|
4
|
-
|
4
|
+
class Column < PostgreSQLColumn
|
5
5
|
# most functions taken from activerecord-postgis-adapter spatial_column
|
6
6
|
# https://github.com/rgeo/activerecord-postgis-adapter/blob/master/lib/active_record/connection_adapters/postgis/spatial_column.rb
|
7
7
|
def initialize(name, default, sql_type_metadata = nil, null = true,
|
@@ -93,9 +93,5 @@ module ActiveRecord
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
end
|
96
|
-
|
97
|
-
class PostgreSQLColumn
|
98
|
-
prepend CockroachDB::PostgreSQLColumnMonkeyPatch
|
99
|
-
end
|
100
96
|
end
|
101
97
|
end
|
@@ -5,12 +5,89 @@ module ActiveRecord
|
|
5
5
|
module CockroachDB
|
6
6
|
class DatabaseTasks < ActiveRecord::Tasks::PostgreSQLDatabaseTasks
|
7
7
|
def structure_dump(filename, extra_flags=nil)
|
8
|
-
|
8
|
+
if extra_flags
|
9
|
+
raise "No flag supported yet, please raise an issue if needed. " \
|
10
|
+
"https://github.com/cockroachdb/activerecord-cockroachdb-adapter/issues/new"
|
11
|
+
end
|
12
|
+
|
13
|
+
case ActiveRecord.dump_schemas
|
14
|
+
when :all, String
|
15
|
+
raise "Custom schemas are not supported in CockroachDB. " \
|
16
|
+
"See https://github.com/cockroachdb/cockroach/issues/26443."
|
17
|
+
when :schema_search_path
|
18
|
+
if configuration_hash[:schema_search_path]
|
19
|
+
raise "Custom schemas are not supported in CockroachDB. " \
|
20
|
+
"See https://github.com/cockroachdb/cockroach/issues/26443."
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
conn = ActiveRecord::Base.connection
|
25
|
+
File.open(filename, "w") do |file|
|
26
|
+
%w(SCHEMAS TYPES).each do |object_kind|
|
27
|
+
ActiveRecord::Base.connection.execute("SHOW CREATE ALL #{object_kind}").each_row { file.puts _1 }
|
28
|
+
end
|
29
|
+
|
30
|
+
ignore_tables = ActiveRecord::SchemaDumper.ignore_tables.to_set
|
31
|
+
|
32
|
+
conn.execute("SHOW CREATE ALL TABLES").each_row do |(sql)|
|
33
|
+
if sql.start_with?("CREATE")
|
34
|
+
table_name = sql[/CREATE TABLE (?:.*?\.)?\"?(.*?)[\" ]/, 1]
|
35
|
+
next if ignore_tables.member?(table_name)
|
36
|
+
elsif sql.start_with?("ALTER")
|
37
|
+
table_name = sql[/ALTER TABLE (?:.*?\.)?\"?(.*?)[\" ]/, 1]
|
38
|
+
ref_table_name = sql[/REFERENCES (?:.*?\.)?\"?(.*?)[\" ]/, 1]
|
39
|
+
next if ignore_tables.member?(table_name) || ignore_tables.member?(ref_table_name)
|
40
|
+
end
|
41
|
+
|
42
|
+
file.puts sql
|
43
|
+
end
|
44
|
+
end
|
9
45
|
end
|
10
46
|
|
11
47
|
def structure_load(filename, extra_flags=nil)
|
12
|
-
|
48
|
+
if extra_flags
|
49
|
+
raise "No flag supported yet, please raise an issue if needed. " \
|
50
|
+
"https://github.com/cockroachdb/activerecord-cockroachdb-adapter/issues/new"
|
51
|
+
end
|
52
|
+
|
53
|
+
run_cmd("cockroach", ["sql", "--set", "errexit=false", "--file", filename], "loading")
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
# Adapted from https://github.com/rails/rails/blob/a5fc471b3/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb#L106.
|
59
|
+
# Using https://www.cockroachlabs.com/docs/stable/connection-parameters.html#additional-connection-parameters.
|
60
|
+
def cockroach_env
|
61
|
+
usr_pwd = ""
|
62
|
+
if configuration_hash[:username]
|
63
|
+
usr_pwd += configuration_hash[:username].to_s
|
64
|
+
if configuration_hash[:password]
|
65
|
+
usr_pwd += ":"
|
66
|
+
usr_pwd += configuration_hash[:password].to_s
|
67
|
+
end
|
68
|
+
usr_pwd += "@"
|
69
|
+
end
|
70
|
+
|
71
|
+
port = ""
|
72
|
+
port = ":#{configuration_hash[:port]}" if configuration_hash[:port]
|
73
|
+
|
74
|
+
params = %i(sslmode sslrootcert sslcert sslkey).filter_map do |key|
|
75
|
+
"#{key}=#{configuration_hash[key]}" if configuration_hash[key]
|
76
|
+
end.join("&")
|
77
|
+
params = "?#{params}" unless params.empty?
|
78
|
+
|
79
|
+
url = "postgres://#{usr_pwd}#{db_config.host}#{port}/#{db_config.database}#{params}"
|
80
|
+
|
81
|
+
{
|
82
|
+
# NOTE: sslmode in the url will take precedence over this setting, hence
|
83
|
+
# we don't need to conditionally set it.
|
84
|
+
"COCKROACH_INSECURE" => "true",
|
85
|
+
"COCKROACH_URL" => url
|
86
|
+
}
|
13
87
|
end
|
88
|
+
# The `#run_cmd` method use `psql_env` to set environments variables.
|
89
|
+
# We override it with cockroach env variables.
|
90
|
+
alias_method :psql_env, :cockroach_env
|
14
91
|
end
|
15
92
|
end
|
16
93
|
end
|
@@ -19,6 +19,12 @@ module ActiveRecord
|
|
19
19
|
# converting to WKB, so this does it automatically.
|
20
20
|
def quote(value)
|
21
21
|
if value.is_a?(Numeric)
|
22
|
+
# NOTE: The fact that integers are quoted is important and helps
|
23
|
+
# mitigate a potential vulnerability.
|
24
|
+
#
|
25
|
+
# See
|
26
|
+
# - https://nvd.nist.gov/vuln/detail/CVE-2022-44566
|
27
|
+
# - https://github.com/cockroachdb/activerecord-cockroachdb-adapter/pull/280#discussion_r1288692977
|
22
28
|
"'#{quote_string(value.to_s)}'"
|
23
29
|
elsif RGeo::Feature::Geometry.check_type(value)
|
24
30
|
"'#{RGeo::WKRep::WKBGenerator.new(hex_format: true, type_format: :ewkb, emit_ewkb_srid: true).generate(value)}'"
|
@@ -90,7 +90,7 @@ module ActiveRecord
|
|
90
90
|
# {:dimension=>2, :has_m=>false, :has_z=>false, :name=>"latlon", :srid=>0, :type=>"GEOMETRY"}
|
91
91
|
spatial = spatial_column_info(table_name).get(column_name, type_metadata.sql_type)
|
92
92
|
|
93
|
-
|
93
|
+
CockroachDB::Column.new(
|
94
94
|
column_name,
|
95
95
|
default_value,
|
96
96
|
type_metadata,
|
@@ -112,7 +112,7 @@ module ActiveRecord
|
|
112
112
|
# since type alone is not enough to format the column.
|
113
113
|
# Ex. type_to_sql(:geography, limit: "Point,4326")
|
114
114
|
# => "geography(Point,4326)"
|
115
|
-
#
|
115
|
+
#
|
116
116
|
def type_to_sql(type, limit: nil, precision: nil, scale: nil, array: nil, **) # :nodoc:
|
117
117
|
sql = \
|
118
118
|
case type.to_s
|
@@ -4,8 +4,11 @@ module ActiveRecord
|
|
4
4
|
# Return :postgresql instead of :cockroachdb for current_adapter_name so
|
5
5
|
# we can continue using the ActiveRecord::Types defined in
|
6
6
|
# PostgreSQLAdapter.
|
7
|
-
def adapter_name_from(
|
8
|
-
|
7
|
+
def adapter_name_from(model)
|
8
|
+
name = model.connection_db_config.adapter.to_sym
|
9
|
+
return :postgresql if name == :cockroachdb
|
10
|
+
|
11
|
+
name
|
9
12
|
end
|
10
13
|
end
|
11
14
|
end
|
@@ -23,6 +23,8 @@ require "active_record/connection_adapters/cockroachdb/arel_tosql"
|
|
23
23
|
require_relative "../migration/cockroachdb/compatibility"
|
24
24
|
require_relative "../../version"
|
25
25
|
|
26
|
+
require_relative "../relation/query_methods_ext"
|
27
|
+
|
26
28
|
# Run to ignore spatial tables that will break schemna dumper.
|
27
29
|
# Defined in ./setup.rb
|
28
30
|
ActiveRecord::ConnectionAdapters::CockroachDB.initial_setup
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class Relation
|
5
|
+
module QueryMethodsExt
|
6
|
+
def from!(...) # :nodoc:
|
7
|
+
@force_index = nil
|
8
|
+
@index_hint = nil
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
# Set table index hint for the query to the
|
13
|
+
# given `index_name`, and `direction` (either
|
14
|
+
# `ASC` or `DESC`).
|
15
|
+
#
|
16
|
+
# Any call to `ActiveRecord::QueryMethods#from`
|
17
|
+
# will reset the index hint. Index hints are
|
18
|
+
# not set if the `from` clause is not a table
|
19
|
+
# name.
|
20
|
+
#
|
21
|
+
# @see https://www.cockroachlabs.com/docs/v22.2/table-expressions#force-index-selection
|
22
|
+
def force_index(index_name, direction: nil)
|
23
|
+
spawn.force_index!(index_name, direction: direction)
|
24
|
+
end
|
25
|
+
|
26
|
+
def force_index!(index_name, direction: nil)
|
27
|
+
return self unless from_clause_is_a_table_name?
|
28
|
+
|
29
|
+
index_name = sanitize_sql(index_name.to_s)
|
30
|
+
direction = direction.to_s.upcase
|
31
|
+
direction = %w[ASC DESC].include?(direction) ? ",#{direction}" : ""
|
32
|
+
|
33
|
+
@force_index = "FORCE_INDEX=#{index_name}#{direction}"
|
34
|
+
self.from_clause = build_from_clause_with_hints
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
# Set table index hint for the query with the
|
39
|
+
# given `hint`. This allows more control over
|
40
|
+
# the hint than `ActiveRecord::Relation#force_index`.
|
41
|
+
# For instance, you could set it to `NO_FULL_SCAN`.
|
42
|
+
#
|
43
|
+
# Any call to `ActiveRecord::QueryMethods#from`
|
44
|
+
# will reset the index hint. Index hints are
|
45
|
+
# not set if the `from` clause is not a table
|
46
|
+
# name.
|
47
|
+
#
|
48
|
+
# @see https://www.cockroachlabs.com/docs/v22.2/table-expressions#force-index-selection
|
49
|
+
def index_hint(hint)
|
50
|
+
spawn.index_hint!(hint)
|
51
|
+
end
|
52
|
+
|
53
|
+
def index_hint!(hint)
|
54
|
+
return self unless from_clause_is_a_table_name?
|
55
|
+
|
56
|
+
hint = sanitize_sql(hint.to_s)
|
57
|
+
@index_hint = hint.to_s
|
58
|
+
self.from_clause = build_from_clause_with_hints
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def from_clause_is_a_table_name?
|
65
|
+
# if empty, we are just dealing with the current table.
|
66
|
+
return true if from_clause.empty?
|
67
|
+
# `from_clause` can be a subquery.
|
68
|
+
return false unless from_clause.value.is_a?(String)
|
69
|
+
# `from_clause` can be a list of tables or a function.
|
70
|
+
# A simple way to check is to see if the string
|
71
|
+
# contains special characters. But we have to
|
72
|
+
# not check against an existing table hint.
|
73
|
+
return !from_clause.value.gsub(/\@{.*?\}/, "").match?(/[,\(]/)
|
74
|
+
end
|
75
|
+
|
76
|
+
def build_from_clause_with_hints
|
77
|
+
table_hints = [@index_hint, @force_index].compact.join(",")
|
78
|
+
|
79
|
+
table_name =
|
80
|
+
if from_clause.empty?
|
81
|
+
quoted_table_name
|
82
|
+
else
|
83
|
+
# Remove previous table hints if any. And spaces.
|
84
|
+
from_clause.value.partition("@").first.strip
|
85
|
+
end
|
86
|
+
Relation::FromClause.new("#{table_name}@{#{table_hints}}", nil)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
QueryMethods.prepend(QueryMethodsExt)
|
91
|
+
end
|
92
|
+
# `ActiveRecord::Base` ancestors do not include `QueryMethods`.
|
93
|
+
# But the `#all` method returns a relation, which has `QueryMethods`
|
94
|
+
# as ancestor. That is how active_record is doing is as well.
|
95
|
+
#
|
96
|
+
# @see https://github.com/rails/rails/blob/914130a9f/activerecord/lib/active_record/querying.rb#L23
|
97
|
+
Querying.delegate(:force_index, :index_hint, to: :all)
|
98
|
+
end
|
data/lib/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-cockroachdb-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.0.
|
4
|
+
version: 7.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cockroach Labs
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-08-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -74,6 +74,7 @@ executables: []
|
|
74
74
|
extensions: []
|
75
75
|
extra_rdoc_files: []
|
76
76
|
files:
|
77
|
+
- ".github/workflows/ci.yml"
|
77
78
|
- ".github/workflows/docker.yml"
|
78
79
|
- ".gitignore"
|
79
80
|
- ".gitmodules"
|
@@ -87,6 +88,7 @@ files:
|
|
87
88
|
- activerecord-cockroachdb-adapter.gemspec
|
88
89
|
- bin/console
|
89
90
|
- bin/setup
|
91
|
+
- bin/start-cockroachdb
|
90
92
|
- build/Dockerfile
|
91
93
|
- build/config.teamcity.yml
|
92
94
|
- build/local-test.sh
|
@@ -114,6 +116,7 @@ files:
|
|
114
116
|
- lib/active_record/connection_adapters/cockroachdb/type.rb
|
115
117
|
- lib/active_record/connection_adapters/cockroachdb_adapter.rb
|
116
118
|
- lib/active_record/migration/cockroachdb/compatibility.rb
|
119
|
+
- lib/active_record/relation/query_methods_ext.rb
|
117
120
|
- lib/activerecord-cockroachdb-adapter.rb
|
118
121
|
- lib/version.rb
|
119
122
|
homepage: https://github.com/cockroachdb/activerecord-cockroachdb-adapter
|