Skip to content

Commit 615eba1

Browse files
authored
Merge pull request #176 from keithdoggett/activerecord-6.1
Add Activerecord 6.1 Support
2 parents df06ec2 + 6f68211 commit 615eba1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1239
-103
lines changed

CONTRIBUTING.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,26 @@ RAILS_SOURCE="path/to/local_copy" bundle exec rake test
7878

7979
`test/config.yml` assumes CockroachDB will be running at localhost:26257 with a root user. Make changes to `test/config.yml` as needed.
8080

81+
### Run Tests from a Backup
82+
83+
Loading the full test schema every time a test runs can take a while, so for cases where loading the schema sequentially is unimportant, it is possible to use a backup to set up the database. This is significantly faster than the standard method and is provided to run individual tests faster, but should not be used to validate a build.
84+
85+
First create the template database.
86+
87+
```bash
88+
bundle exec rake db:create_test_template
89+
```
90+
91+
This will create a template database for the current version (ex. `activerecord_test_template611` for version 6.1.1) and create a `BACKUP` in the `nodelocal://self/activerecord-crdb-adapter/#{activerecord_version}` directory.
92+
93+
To load from the template, use the `COCKROACH_LOAD_FROM_TEMPLATE` flag.
94+
95+
```bash
96+
COCKROACH_LOAD_FROM_TEMPLATE=1 TEST_FILES="test/cases/adapters/postgresql/ddl_test.rb" bundle exec rake test
97+
```
98+
99+
And the `activerecord_unittest` database will use the `RESTORE` command to load the schema from the template database.
100+
81101
# Improvements
82102

83103

Rakefile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,30 @@ require "bundler/gem_tasks"
22
require "rake/testtask"
33
require_relative 'test/support/paths_cockroachdb'
44
require_relative 'test/support/rake_helpers'
5+
require_relative 'test/support/template_creator'
56

67
task test: ["test:cockroachdb"]
78
task default: [:test]
89

10+
namespace :db do
11+
task "create_test_template" do
12+
ENV['DEBUG_COCKROACHDB_ADAPTER'] = "1"
13+
ENV['COCKROACH_SKIP_LOAD_SCHEMA'] = "1"
14+
ENV["ARCONN"] = "cockroachdb"
15+
16+
TemplateCreator.connect
17+
require_relative 'test/cases/helper'
18+
19+
# TODO: look into this more, but for some reason the blob alias
20+
# is not defined while running this task.
21+
ActiveRecord::ConnectionAdapters::CockroachDB::TableDefinition.class_eval do
22+
alias :blob :binary
23+
end
24+
25+
TemplateCreator.create_test_template
26+
end
27+
end
28+
929
namespace :test do
1030
Rake::TestTask.new("cockroachdb") do |t|
1131
t.libs = ARTest::CockroachDB.test_load_paths

activerecord-cockroachdb-adapter.gemspec

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
44

55
Gem::Specification.new do |spec|
66
spec.name = "activerecord-cockroachdb-adapter"
7-
spec.version = "6.0.0beta3"
7+
spec.version = "6.1.0beta1"
88
spec.licenses = ["Apache-2.0"]
99
spec.authors = ["Cockroach Labs"]
1010
spec.email = ["[email protected]"]
@@ -13,8 +13,8 @@ Gem::Specification.new do |spec|
1313
spec.description = "Allows the use of CockroachDB as a backend for ActiveRecord and Rails apps."
1414
spec.homepage = "https://github.com/cockroachdb/activerecord-cockroachdb-adapter"
1515

16-
spec.add_dependency "activerecord", "~> 6.0.3"
17-
spec.add_dependency "pg", ">= 0.20"
16+
spec.add_dependency "activerecord", "~> 6.1"
17+
spec.add_dependency "pg", ">= 1.2"
1818
spec.add_dependency "rgeo-activerecord", "~> 7.0.0"
1919

2020
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# frozen-string-literal: true
2+
3+
require "active_support/duration"
4+
5+
module ActiveRecord
6+
module ConnectionAdapters
7+
module CockroachDB
8+
module OID
9+
module Interval # :nodoc:
10+
DEFAULT_PRECISION = 6 # microseconds
11+
12+
def cast_value(value)
13+
case value
14+
when ::ActiveSupport::Duration
15+
value
16+
when ::String
17+
begin
18+
PostgresqlInterval::Parser.parse(value)
19+
rescue PostgresqlInterval::ParseError
20+
# Try ISO 8601
21+
super
22+
end
23+
else
24+
super
25+
end
26+
end
27+
28+
def serialize(value)
29+
precision = self.precision || DEFAULT_PRECISION
30+
case value
31+
when ::ActiveSupport::Duration
32+
serialize_duration(value, precision)
33+
when ::Numeric
34+
serialize_duration(value.seconds, precision)
35+
else
36+
super
37+
end
38+
end
39+
40+
def type_cast_for_schema(value)
41+
serialize(value).inspect
42+
end
43+
44+
private
45+
46+
# Convert an ActiveSupport::Duration to
47+
# the postgres interval style
48+
# ex. 1 year 2 mons 3 days 4 hours 5 minutes 6 seconds
49+
def serialize_duration(value, precision)
50+
yrs = value.parts.fetch(:years, 0)
51+
mons = value.parts.fetch(:months, 0)
52+
days = value.parts.fetch(:days, 0)
53+
hrs = value.parts.fetch(:hours, 0)
54+
mins = value.parts.fetch(:minutes, 0)
55+
secs = value.parts.fetch(:seconds, 0).round(precision)
56+
57+
"#{yrs} years #{mons} mons #{days} days #{hrs} hours #{mins} minutes #{secs} seconds"
58+
end
59+
end
60+
61+
PostgreSQL::OID::Interval.prepend(Interval)
62+
end
63+
64+
module PostgresqlInterval
65+
class Parser
66+
PARTS = ActiveSupport::Duration::PARTS
67+
PARTS_IN_SECONDS = ActiveSupport::Duration::PARTS_IN_SECONDS
68+
69+
# modified regex from https://github.com/jeremyevans/sequel/blob/master/lib/sequel/extensions/pg_interval.rb#L86
70+
REGEX = /\A([+-]?\d+ years?\s?)?([+-]?\d+ mons?\s?)?([+-]?\d+ days?\s?)?(?:([+-])?(\d{2,10}):(\d\d):(\d\d(\.\d+)?))?\z/
71+
72+
def self.parse(string)
73+
matches = REGEX.match(string)
74+
raise(ParseError) unless matches
75+
76+
# 1 => years, 2 => months, 3 => days, 4 => nil, 5 => hours,
77+
# 6 => minutes, 7 => seconds with fraction digits, 8 => fractional portion of 7
78+
duration = 0
79+
parts = {}
80+
81+
if matches[1]
82+
val = matches[1].to_i
83+
duration += val * PARTS_IN_SECONDS[:years]
84+
parts[:years] = val
85+
end
86+
87+
if matches[2]
88+
val = matches[2].to_i
89+
duration += val * PARTS_IN_SECONDS[:months]
90+
parts[:months] = val
91+
end
92+
93+
if matches[3]
94+
val = matches[3].to_i
95+
duration += val * PARTS_IN_SECONDS[:days]
96+
parts[:days] = val
97+
end
98+
99+
if matches[5]
100+
val = matches[5].to_i
101+
duration += val * PARTS_IN_SECONDS[:hours]
102+
parts[:hours] = val
103+
end
104+
105+
if matches[6]
106+
val = matches[6].to_i
107+
duration += val * PARTS_IN_SECONDS[:minutes]
108+
parts[:minutes] = val
109+
end
110+
111+
if matches[7]
112+
val = matches[7].to_f
113+
duration += val * PARTS_IN_SECONDS[:seconds]
114+
parts[:seconds] = val
115+
end
116+
117+
ActiveSupport::Duration.new(duration, parts)
118+
end
119+
end
120+
121+
class ParseError < StandardError
122+
end
123+
end
124+
end
125+
end
126+
end

lib/active_record/connection_adapters/cockroachdb/schema_statements.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module CockroachDB
44
module SchemaStatements
55
include ActiveRecord::ConnectionAdapters::PostgreSQL::SchemaStatements
66

7-
def add_index(table_name, column_name, options = {})
7+
def add_index(table_name, column_name, **options)
88
super
99
rescue ActiveRecord::StatementInvalid => error
1010
if debugging? && error.cause.class == PG::FeatureNotSupported

lib/active_record/connection_adapters/cockroachdb/transaction_manager.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ module TransactionManagerMonkeyPatch
99
# transactions will be retried until they pass or the max retry limit is
1010
# exceeded.
1111
def within_new_transaction(isolation: nil, joinable: true, attempts: 0)
12-
super
12+
super(isolation: isolation, joinable: joinable)
1313
rescue ActiveRecord::StatementInvalid => error
1414
raise unless retryable? error
1515
raise if attempts >= @connection.max_transaction_retries

lib/active_record/connection_adapters/cockroachdb/type.rb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
module ActiveRecord
22
module Type
33
class << self
4-
private
5-
64
# Return :postgresql instead of :cockroachdb for current_adapter_name so
75
# we can continue using the ActiveRecord::Types defined in
86
# PostgreSQLAdapter.
9-
def current_adapter_name
7+
def adapter_name_from(_model)
108
:postgresql
119
end
1210
end

0 commit comments

Comments
 (0)