activerecord-spanner-adapter 1.6.1 → 1.6.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +15 -0
- data/Gemfile +2 -2
- data/README.md +1 -0
- data/acceptance/cases/migration/schema_dumper_test.rb +14 -0
- data/acceptance/cases/tasks/database_tasks_test.rb +4 -0
- data/acceptance/schema/schema.rb +1 -0
- data/activerecord-spanner-adapter.gemspec +2 -0
- data/examples/snippets/bit-reversed-sequence/README.md +6 -0
- data/examples/snippets/bit-reversed-sequence/db/migrate/01_create_tables.rb +3 -6
- data/examples/snippets/bit-reversed-sequence/db/schema.rb +1 -1
- data/lib/active_record/connection_adapters/spanner/schema_dumper.rb +3 -1
- data/lib/active_record/type/spanner/spanner_active_record_converter.rb +3 -0
- data/lib/activerecord_spanner_adapter/version.rb +1 -1
- metadata +17 -5
- data/.github/workflows/release-please-label.yml +0 -25
- data/.github/workflows/release-please.yml +0 -38
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c2a9a0a36a471ac93bdb0d59e50cc9b8e5c6647655487dc55a1d9e398abcf46
|
4
|
+
data.tar.gz: de680bcac6cf0f491bd0007d80d48496cf5e74b5eddf17d13b58353f06b818da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0658d456b4d6377bf5f95f44296869404ac9ac1c65aaa25360080bab1df7c122c4b7aba28992f5030e6465e51fefa1b6630a4e79547c65446edd29c40954ca61'
|
7
|
+
data.tar.gz: 470e026052a753f08d59f2824044894afe84d5601735270250c09368c7541ef98d5356a6ca6810c10755033a81601afb40826656967bdf8cda132563a2e9b267
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
### 1.6.3 (2024-08-31)
|
4
|
+
|
5
|
+
#### Bug Fixes
|
6
|
+
|
7
|
+
* a few Ruby DSL schema dump bug fixes ([#308](https://github.com/googleapis/ruby-spanner-activerecord/issues/308))
|
8
|
+
#### Documentation
|
9
|
+
|
10
|
+
* update bit-reversed sequence sample ([#303](https://github.com/googleapis/ruby-spanner-activerecord/issues/303))
|
11
|
+
|
12
|
+
### 1.6.2 (2024-02-19)
|
13
|
+
|
14
|
+
#### Bug Fixes
|
15
|
+
|
16
|
+
* failed to convert active model type to spanner type under certain condition ([#299](https://github.com/googleapis/ruby-spanner-activerecord/issues/299))
|
17
|
+
|
3
18
|
### 1.6.1 (2024-02-05)
|
4
19
|
|
5
20
|
#### Bug Fixes
|
data/Gemfile
CHANGED
@@ -4,12 +4,12 @@ source "https://rubygems.org"
|
|
4
4
|
gemspec
|
5
5
|
|
6
6
|
gem "activerecord", ENV.fetch("AR_VERSION", "~> 6.1.6.1")
|
7
|
-
gem "minitest", "~> 5.
|
7
|
+
gem "minitest", "~> 5.25.0"
|
8
8
|
gem "minitest-rg", "~> 5.3.0"
|
9
9
|
gem "pry", "~> 0.13.0"
|
10
10
|
gem "pry-byebug", "~> 3.9.0"
|
11
11
|
# Add sqlite3 for testing for compatibility with other adapters.
|
12
|
-
gem
|
12
|
+
gem 'sqlite3', '~> 1.4'
|
13
13
|
|
14
14
|
# Required for samples and testing.
|
15
15
|
install_if -> { ENV.fetch("AR_VERSION", "~> 6.1.6.1").dup.to_s.sub("~>", "").strip < "7.1.0" && !ENV["SKIP_COMPOSITE_PK"] } do
|
data/README.md
CHANGED
@@ -77,6 +77,7 @@ __NOTE__: You do need to have [Docker](https://docs.docker.com/get-docker/) inst
|
|
77
77
|
Some noteworthy examples in the snippets directory:
|
78
78
|
- [quickstart](examples/snippets/quickstart): A simple application that shows how to create and query a simple database containing two tables.
|
79
79
|
- [migrations](examples/snippets/migrations): Shows a best-practice for executing migrations on Cloud Spanner.
|
80
|
+
- [bit-reversed-sequences](examples/snippets/bit-reversed-sequence): Shows how to use bit-reversed sequences for primary keys.
|
80
81
|
- [read-write-transactions](examples/snippets/read-write-transactions): Shows how to execute transactions on Cloud Spanner.
|
81
82
|
- [read-only-transactions](examples/snippets/read-only-transactions): Shows how to execute read-only transactions on Cloud Spanner.
|
82
83
|
- [bulk-insert](examples/snippets/bulk-insert): Shows the best way to insert a large number of new records.
|
@@ -73,6 +73,20 @@ module ActiveRecord
|
|
73
73
|
ActiveRecord::SchemaDumper.dump connection, schema
|
74
74
|
assert schema.string.include?("t.virtual \"full_name\", type: :string, as: \"COALESCE(first_name || ' ', '') || last_name\", stored: true"), schema.string
|
75
75
|
end
|
76
|
+
|
77
|
+
def test_dump_schema_contains_string_array
|
78
|
+
connection = ActiveRecord::Base.connection
|
79
|
+
schema = StringIO.new
|
80
|
+
ActiveRecord::SchemaDumper.dump connection, schema
|
81
|
+
assert schema.string.include?("t.string \"col_array_string\", array: true"), schema.string
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_dump_schema_index_storing
|
85
|
+
connection = ActiveRecord::Base.connection
|
86
|
+
schema = StringIO.new
|
87
|
+
ActiveRecord::SchemaDumper.dump connection, schema
|
88
|
+
assert schema.string.include?("t.index [\"last_name\"], name: \"index_singers_on_last_name\", order: { last_name: :asc }, storing: [\"first_name\", \"tracks_count\"]"), schema.string
|
89
|
+
end
|
76
90
|
end
|
77
91
|
end
|
78
92
|
end
|
@@ -226,6 +226,7 @@ CREATE TABLE singers (
|
|
226
226
|
lock_version INT64,
|
227
227
|
full_name STRING(MAX) AS (COALESCE(first_name || ' ', '') || last_name) STORED,
|
228
228
|
) PRIMARY KEY(singerid);
|
229
|
+
CREATE INDEX index_singers_on_last_name ON singers(last_name) STORING (tracks_count, first_name);
|
229
230
|
CREATE TABLE albums (
|
230
231
|
albumid INT64 NOT NULL,
|
231
232
|
singerid INT64 NOT NULL,
|
@@ -383,6 +384,7 @@ CREATE TABLE singers (
|
|
383
384
|
lock_version INT64,
|
384
385
|
full_name STRING(MAX) AS (COALESCE(first_name || ' ', '') || last_name) STORED,
|
385
386
|
) PRIMARY KEY(singerid);
|
387
|
+
CREATE INDEX index_singers_on_last_name ON singers(last_name) STORING (tracks_count, first_name);
|
386
388
|
CREATE TABLE albums (
|
387
389
|
singerid INT64 NOT NULL,
|
388
390
|
albumid INT64 NOT NULL,
|
@@ -547,6 +549,7 @@ CREATE TABLE singers (
|
|
547
549
|
lock_version INT64,
|
548
550
|
full_name STRING(MAX) AS (COALESCE(first_name || ' ', '') || last_name) STORED,
|
549
551
|
) PRIMARY KEY(singerid);
|
552
|
+
CREATE INDEX index_singers_on_last_name ON singers(last_name) STORING (tracks_count, first_name);
|
550
553
|
CREATE TABLE albums (
|
551
554
|
albumid INT64 NOT NULL,
|
552
555
|
singerid INT64 NOT NULL,
|
@@ -707,6 +710,7 @@ CREATE TABLE singers (
|
|
707
710
|
lock_version INT64,
|
708
711
|
full_name STRING(MAX) AS (COALESCE(first_name || ' ', '') || last_name) STORED,
|
709
712
|
) PRIMARY KEY(singerid);
|
713
|
+
CREATE INDEX index_singers_on_last_name ON singers(last_name) STORING (tracks_count, first_name);
|
710
714
|
CREATE TABLE albums (
|
711
715
|
singerid INT64 NOT NULL,
|
712
716
|
albumid INT64 NOT NULL,
|
data/acceptance/schema/schema.rb
CHANGED
@@ -126,6 +126,7 @@ def create_tables_in_test_schema
|
|
126
126
|
t.integer :lock_version
|
127
127
|
t.virtual :full_name, type: :string, as: "COALESCE(first_name || ' ', '') || last_name", stored: true
|
128
128
|
end
|
129
|
+
add_index :singers, :last_name, storing: %i[tracks_count first_name]
|
129
130
|
|
130
131
|
if is_7_1_or_higher?
|
131
132
|
create_table :albums, primary_key: [:singerid, :albumid] do |t|
|
@@ -25,6 +25,8 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.required_ruby_version = ">= 2.7"
|
26
26
|
|
27
27
|
spec.add_dependency "google-cloud-spanner", "~> 2.18"
|
28
|
+
# Pin gRPC to 1.64.3, as 1.65 and 1.66 cause test runs to hang randomly.
|
29
|
+
spec.add_dependency "grpc", "1.64.3"
|
28
30
|
spec.add_runtime_dependency "activerecord", [">= 6.0.0", "< 7.2"]
|
29
31
|
|
30
32
|
spec.add_development_dependency "autotest-suffix", "~> 1.1"
|
@@ -5,6 +5,12 @@ This example shows how to use a bit-reversed sequence to generate the primary ke
|
|
5
5
|
See https://cloud.google.com/spanner/docs/primary-key-default-value#bit-reversed-sequence for more information
|
6
6
|
about bit-reversed sequences in Cloud Spanner.
|
7
7
|
|
8
|
+
## Requirements
|
9
|
+
Using bit-reversed sequences for generating primary key values in ActiveRecord has the following requirements:
|
10
|
+
1. You must use __ActiveRecord version 7.1 or higher__.
|
11
|
+
2. Your models must include a sequence name like this: `self.sequence_name = :singer_sequence`
|
12
|
+
3. You must create the bit-reversed sequence using a SQL statement in your migrations.
|
13
|
+
|
8
14
|
## Creating Tables with Bit-Reversed Sequences in ActiveRecord
|
9
15
|
You can create bit-reversed sequences using migrations in ActiveRecord by executing a SQL statement using the underlying
|
10
16
|
connection.
|
@@ -8,15 +8,12 @@ class CreateTables < ActiveRecord::Migration[7.1]
|
|
8
8
|
def change
|
9
9
|
# Execute the entire migration as one DDL batch.
|
10
10
|
connection.ddl_batch do
|
11
|
-
|
12
|
-
# connection.execute "create sequence singer_sequence OPTIONS (sequence_kind = 'bit_reversed_positive')"
|
11
|
+
connection.execute "create sequence singer_sequence OPTIONS (sequence_kind = 'bit_reversed_positive')"
|
13
12
|
|
14
13
|
# Explicitly define the primary key.
|
15
14
|
create_table :singers, id: false, primary_key: :singerid do |t|
|
16
|
-
|
17
|
-
|
18
|
-
# default: -> { "GET_NEXT_SEQUENCE_VALUE(SEQUENCE singer_sequence)" }
|
19
|
-
t.integer :singerid, primary_key: true, null: false, default: -> { "FARM_FINGERPRINT(GENERATE_UUID())" }
|
15
|
+
t.integer :singerid, primary_key: true, null: false,
|
16
|
+
default: -> { "GET_NEXT_SEQUENCE_VALUE(SEQUENCE singer_sequence)" }
|
20
17
|
t.string :first_name
|
21
18
|
t.string :last_name
|
22
19
|
end
|
@@ -19,7 +19,7 @@ ActiveRecord::Schema[7.1].define(version: 1) do
|
|
19
19
|
t.string "title"
|
20
20
|
end
|
21
21
|
|
22
|
-
create_table "singers", primary_key: "singerid", default: -> { "
|
22
|
+
create_table "singers", primary_key: "singerid", default: -> { "GET_NEXT_SEQUENCE_VALUE(SEQUENCE singer_sequence)" }, force: :cascade do |t|
|
23
23
|
t.string "first_name"
|
24
24
|
t.string "last_name"
|
25
25
|
end
|
@@ -27,6 +27,8 @@ module ActiveRecord
|
|
27
27
|
spec = { type: schema_type(column).inspect }.merge! spec
|
28
28
|
end
|
29
29
|
|
30
|
+
spec[:array] = true if column.sql_type.start_with? "ARRAY<"
|
31
|
+
|
30
32
|
spec
|
31
33
|
end
|
32
34
|
|
@@ -54,7 +56,7 @@ module ActiveRecord
|
|
54
56
|
index_parts = super
|
55
57
|
index_parts << "null_filtered: #{index.null_filtered.inspect}" if index.null_filtered
|
56
58
|
index_parts << "interleave_in: #{index.interleave_in.inspect}" if index.interleave_in
|
57
|
-
index_parts << "storing: #{format_index_parts index.storing}" if index.storing.present?
|
59
|
+
index_parts << "storing: #{format_index_parts index.storing.sort}" if index.storing.present?
|
58
60
|
index_parts
|
59
61
|
end
|
60
62
|
|
@@ -23,6 +23,9 @@ module ActiveRecord
|
|
23
23
|
##
|
24
24
|
# Converts an ActiveModel::Type to a Spanner type code.
|
25
25
|
def self.convert_active_model_type_to_spanner type # rubocop:disable Metrics/CyclomaticComplexity
|
26
|
+
# Unwrap the underlying object if the type is a DelegateClass.
|
27
|
+
type = type.__getobj__ if type.respond_to? :__getobj__
|
28
|
+
|
26
29
|
case type
|
27
30
|
when NilClass then nil
|
28
31
|
when ActiveModel::Type::Integer, ActiveModel::Type::BigInteger then :INT64
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-spanner-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.6.
|
4
|
+
version: 1.6.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Google LLC
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-08-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: google-cloud-spanner
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '2.18'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: grpc
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.64.3
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.64.3
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: activerecord
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -230,8 +244,6 @@ files:
|
|
230
244
|
- ".github/workflows/nightly-acceptance-tests-on-emulator.yaml"
|
231
245
|
- ".github/workflows/nightly-acceptance-tests-on-production.yaml"
|
232
246
|
- ".github/workflows/nightly-unit-tests.yaml"
|
233
|
-
- ".github/workflows/release-please-label.yml"
|
234
|
-
- ".github/workflows/release-please.yml"
|
235
247
|
- ".github/workflows/rubocop.yaml"
|
236
248
|
- ".gitignore"
|
237
249
|
- ".kokoro/populate-secrets.sh"
|
@@ -577,7 +589,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
577
589
|
- !ruby/object:Gem::Version
|
578
590
|
version: '0'
|
579
591
|
requirements: []
|
580
|
-
rubygems_version: 3.5.
|
592
|
+
rubygems_version: 3.5.6
|
581
593
|
signing_key:
|
582
594
|
specification_version: 4
|
583
595
|
summary: Rails ActiveRecord connector for Google Spanner Database
|
@@ -1,25 +0,0 @@
|
|
1
|
-
name: release-please-label
|
2
|
-
on:
|
3
|
-
pull_request_target:
|
4
|
-
branches:
|
5
|
-
- main
|
6
|
-
types:
|
7
|
-
- opened
|
8
|
-
jobs:
|
9
|
-
release-please-label:
|
10
|
-
if: "${{ github.event.sender.login == 'yoshi-code-bot' && startsWith(github.event.pull_request.title, 'chore(main): release ') }}"
|
11
|
-
runs-on: ubuntu-latest
|
12
|
-
steps:
|
13
|
-
- name: ReleaseLabel
|
14
|
-
uses: actions/github-script@v7
|
15
|
-
with:
|
16
|
-
github-token: ${{secrets.YOSHI_APPROVER_TOKEN}}
|
17
|
-
script: |
|
18
|
-
core.info('Labeling release');
|
19
|
-
await github.rest.issues.addLabels({
|
20
|
-
owner: context.repo.owner,
|
21
|
-
repo: context.repo.repo,
|
22
|
-
issue_number: context.payload.pull_request.number,
|
23
|
-
labels: ['autorelease: pending']
|
24
|
-
});
|
25
|
-
core.info('Labeled');
|
@@ -1,38 +0,0 @@
|
|
1
|
-
name: Release-Please
|
2
|
-
on:
|
3
|
-
workflow_dispatch:
|
4
|
-
inputs:
|
5
|
-
gem:
|
6
|
-
description: "Name of single gem to release. Leave blank to check all gems."
|
7
|
-
required: false
|
8
|
-
args:
|
9
|
-
description: "Extra command line arguments."
|
10
|
-
required: false
|
11
|
-
|
12
|
-
jobs:
|
13
|
-
release-please:
|
14
|
-
if: ${{ github.repository == 'googleapis/ruby-spanner-activerecord' }}
|
15
|
-
runs-on: ubuntu-latest
|
16
|
-
env:
|
17
|
-
GITHUB_TOKEN: ${{ secrets.YOSHI_CODE_BOT_TOKEN }}
|
18
|
-
RELEASE_PLEASE_DISABLE: ${{ secrets.RELEASE_PLEASE_DISABLE }}
|
19
|
-
steps:
|
20
|
-
- name: Checkout repo
|
21
|
-
uses: actions/checkout@v4
|
22
|
-
- name: Install Ruby 3.0
|
23
|
-
uses: ruby/setup-ruby@v1
|
24
|
-
with:
|
25
|
-
ruby-version: "3.0"
|
26
|
-
- name: Install NodeJS 16.x
|
27
|
-
uses: actions/setup-node@v4
|
28
|
-
with:
|
29
|
-
node-version: "16.x"
|
30
|
-
- name: Install tools
|
31
|
-
run: "gem install --no-document toys"
|
32
|
-
- name: execute
|
33
|
-
run: |
|
34
|
-
toys release manifest -v \
|
35
|
-
--fork --skip-labeling \
|
36
|
-
--github-event-name=${{ github.event_name }} \
|
37
|
-
${{ github.event.inputs.args }} \
|
38
|
-
-- ${{ github.event.inputs.gem }}
|