activerecord-spanner-adapter 1.4.1 → 1.4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/release-please.yml +7 -0
- data/.github/release-trigger.yml +1 -0
- data/.github/workflows/acceptance-tests-on-emulator.yaml +3 -1
- data/.github/workflows/ci.yaml +3 -1
- data/.github/workflows/nightly-acceptance-tests-on-emulator.yaml +14 -2
- data/.github/workflows/nightly-unit-tests.yaml +14 -2
- data/.github/workflows/release-please.yml +0 -2
- data/.kokoro/release.cfg +9 -0
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +13 -0
- data/CONTRIBUTING.md +17 -1
- data/Gemfile +1 -1
- data/acceptance/cases/migration/change_table_test.rb +2 -2
- data/acceptance/cases/models/default_value_test.rb +54 -0
- data/acceptance/cases/models/interleave_test.rb +85 -14
- data/acceptance/models/album.rb +0 -2
- data/acceptance/test_helper.rb +1 -0
- data/acceptance/test_helpers/with_separate_database.rb +47 -0
- data/lib/activerecord_spanner_adapter/base.rb +3 -2
- data/lib/activerecord_spanner_adapter/information_schema.rb +76 -2
- data/lib/activerecord_spanner_adapter/version.rb +1 -1
- metadata +6 -3
- data/acceptance/models/album_partial_disabled.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ecc586f0beee665e45413d64af184d69ed9814b17465ab68be04767c3312d69a
|
4
|
+
data.tar.gz: 061c3c4b433b673ab848b8f5e67652a0e3f991b99fdae1ed7fdc118e622e3139
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6c69f17a06d188ca69fe942756ded71f245a0398d67fa0c1e0bb915cc03a8cd51147851edcf352697670b3999539b178c1d1542d30659ef6110b096faa3c36d9
|
7
|
+
data.tar.gz: 339ae0975ff7ac256cba1d98b68379a47de1d7187f82e2ebfdd83ad0c940c3ca3af52c4bc5e30f334ba63e48d001baebe373e9a121f4593ad09daf941f7e3e22
|
@@ -0,0 +1 @@
|
|
1
|
+
enabled: true
|
@@ -18,7 +18,7 @@ jobs:
|
|
18
18
|
strategy:
|
19
19
|
max-parallel: 4
|
20
20
|
matrix:
|
21
|
-
ruby: ["2.6", "2.7", "3.0", "3.1"]
|
21
|
+
ruby: ["2.6", "2.7", "3.0", "3.1", "3.2"]
|
22
22
|
ar: ["~> 6.0.6", "~> 6.1.7", "~> 7.0.4"]
|
23
23
|
# Exclude combinations that are not supported.
|
24
24
|
exclude:
|
@@ -26,6 +26,8 @@ jobs:
|
|
26
26
|
ar: "~> 6.0.6"
|
27
27
|
- ruby: "3.1"
|
28
28
|
ar: "~> 6.0.6"
|
29
|
+
- ruby: "3.2"
|
30
|
+
ar: "~> 6.0.6"
|
29
31
|
- ruby: "2.6"
|
30
32
|
ar: "~> 7.0.4"
|
31
33
|
env:
|
data/.github/workflows/ci.yaml
CHANGED
@@ -10,7 +10,7 @@ jobs:
|
|
10
10
|
strategy:
|
11
11
|
max-parallel: 4
|
12
12
|
matrix:
|
13
|
-
ruby: ["2.6", "2.7", "3.0", "3.1"]
|
13
|
+
ruby: ["2.6", "2.7", "3.0", "3.1", "3.2"]
|
14
14
|
ar: ["~> 6.0.6", "~> 6.1.7", "~> 7.0.4"]
|
15
15
|
# Exclude combinations that are not supported.
|
16
16
|
exclude:
|
@@ -18,6 +18,8 @@ jobs:
|
|
18
18
|
ar: "~> 6.0.6"
|
19
19
|
- ruby: "3.1"
|
20
20
|
ar: "~> 6.0.6"
|
21
|
+
- ruby: "3.2"
|
22
|
+
ar: "~> 6.0.6"
|
21
23
|
- ruby: "2.6"
|
22
24
|
ar: "~> 7.0.4"
|
23
25
|
env:
|
@@ -19,8 +19,8 @@ jobs:
|
|
19
19
|
max-parallel: 4
|
20
20
|
matrix:
|
21
21
|
# Run acceptance tests all supported combinations of Ruby and ActiveRecord.
|
22
|
-
ruby: [2.6, 2.7, 3.0, 3.1]
|
23
|
-
ar: [6.0.0, 6.0.1, 6.0.2.2, 6.0.3.7, 6.0.4, 6.1.3.2, 6.1.4.7, 6.1.5.1, 6.1.6.1, 7.0.2.4, 7.0.3.1, 7.0.4]
|
22
|
+
ruby: [2.6, 2.7, 3.0, 3.1, 3.2]
|
23
|
+
ar: [6.0.0, 6.0.1, 6.0.2.2, 6.0.3.7, 6.0.4, 6.1.3.2, 6.1.4.7, 6.1.5.1, 6.1.6.1, 7.0.2.4, 7.0.3.1, 7.0.4, 7.0.5]
|
24
24
|
# Exclude combinations that are not supported.
|
25
25
|
exclude:
|
26
26
|
- ruby: 3.0
|
@@ -43,12 +43,24 @@ jobs:
|
|
43
43
|
ar: 6.0.3.7
|
44
44
|
- ruby: 3.1
|
45
45
|
ar: 6.0.4
|
46
|
+
- ruby: 3.2
|
47
|
+
ar: 6.0.0
|
48
|
+
- ruby: 3.2
|
49
|
+
ar: 6.0.1
|
50
|
+
- ruby: 3.2
|
51
|
+
ar: 6.0.2.2
|
52
|
+
- ruby: 3.2
|
53
|
+
ar: 6.0.3.7
|
54
|
+
- ruby: 3.2
|
55
|
+
ar: 6.0.4
|
46
56
|
- ruby: 2.6
|
47
57
|
ar: 7.0.2.4
|
48
58
|
- ruby: 2.6
|
49
59
|
ar: 7.0.3.1
|
50
60
|
- ruby: 2.6
|
51
61
|
ar: 7.0.4
|
62
|
+
- ruby: 2.6
|
63
|
+
ar: 7.0.5
|
52
64
|
env:
|
53
65
|
AR_VERSION: ${{ matrix.ar }}
|
54
66
|
steps:
|
@@ -11,8 +11,8 @@ jobs:
|
|
11
11
|
max-parallel: 4
|
12
12
|
matrix:
|
13
13
|
# Run unit tests all supported combinations of Ruby and ActiveRecord.
|
14
|
-
ruby: [2.6, 2.7, 3.0, 3.1]
|
15
|
-
ar: [6.0.0, 6.0.1, 6.0.2.2, 6.0.3.7, 6.0.4, 6.1.3.2, 6.1.4.7, 6.1.5.1, 6.1.6.1, 7.0.2.4, 7.0.3.1, 7.0.4]
|
14
|
+
ruby: [2.6, 2.7, 3.0, 3.1, 3.2]
|
15
|
+
ar: [6.0.0, 6.0.1, 6.0.2.2, 6.0.3.7, 6.0.4, 6.1.3.2, 6.1.4.7, 6.1.5.1, 6.1.6.1, 7.0.2.4, 7.0.3.1, 7.0.4, 7.0.5]
|
16
16
|
# Exclude combinations that are not supported.
|
17
17
|
exclude:
|
18
18
|
- ruby: 3.0
|
@@ -35,12 +35,24 @@ jobs:
|
|
35
35
|
ar: 6.0.3.7
|
36
36
|
- ruby: 3.1
|
37
37
|
ar: 6.0.4
|
38
|
+
- ruby: 3.2
|
39
|
+
ar: 6.0.0
|
40
|
+
- ruby: 3.2
|
41
|
+
ar: 6.0.1
|
42
|
+
- ruby: 3.2
|
43
|
+
ar: 6.0.2.2
|
44
|
+
- ruby: 3.2
|
45
|
+
ar: 6.0.3.7
|
46
|
+
- ruby: 3.2
|
47
|
+
ar: 6.0.4
|
38
48
|
- ruby: 2.6
|
39
49
|
ar: 7.0.2.4
|
40
50
|
- ruby: 2.6
|
41
51
|
ar: 7.0.3.1
|
42
52
|
- ruby: 2.6
|
43
53
|
ar: 7.0.4
|
54
|
+
- ruby: 2.6
|
55
|
+
ar: 7.0.5
|
44
56
|
env:
|
45
57
|
AR_VERSION: ${{ matrix.ar }}
|
46
58
|
steps:
|
data/.kokoro/release.cfg
CHANGED
@@ -31,3 +31,12 @@ env_vars: {
|
|
31
31
|
key: "SECRET_MANAGER_KEYS"
|
32
32
|
value: "releasetool-publish-reporter-app,releasetool-publish-reporter-googleapis-installation,releasetool-publish-reporter-pem,docuploader_service_account"
|
33
33
|
}
|
34
|
+
|
35
|
+
# Store the packages uploaded to rubygems.org, which
|
36
|
+
# we can later use to generate SBOMs and attestations.
|
37
|
+
action {
|
38
|
+
define_artifacts {
|
39
|
+
regex: "github/ruby-spanner-activerecord/pkg/*.gem"
|
40
|
+
strip_prefix: "github"
|
41
|
+
}
|
42
|
+
}
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
### 1.4.3 (2023-06-09)
|
4
|
+
|
5
|
+
#### Bug Fixes
|
6
|
+
|
7
|
+
* unquote string default value ([#253](https://github.com/googleapis/ruby-spanner-activerecord/issues/253))
|
8
|
+
|
9
|
+
### 1.4.2 (2023-06-01)
|
10
|
+
|
11
|
+
#### Bug Fixes
|
12
|
+
|
13
|
+
* allow functions to be default values ([#252](https://github.com/googleapis/ruby-spanner-activerecord/issues/252))
|
14
|
+
* use original types for composite primary keys ([#246](https://github.com/googleapis/ruby-spanner-activerecord/issues/246))
|
15
|
+
|
3
16
|
### 1.4.1 (2023-03-01)
|
4
17
|
|
5
18
|
#### Bug Fixes
|
data/CONTRIBUTING.md
CHANGED
@@ -48,10 +48,26 @@ Variable|Description|Comment
|
|
48
48
|
`activerecord_tests`
|
49
49
|
|
50
50
|
#### Example
|
51
|
+
|
51
52
|
```shell
|
52
53
|
bundle exec rake acceptance[appdev-soda-spanner-staging,/home/Downloads/creds.json,activerecord_tests]
|
53
54
|
```
|
54
55
|
|
56
|
+
You can also use the [Cloud Spanner emulator](https://cloud.google.com/spanner/docs/emulator).
|
57
|
+
|
58
|
+
```shell
|
59
|
+
docker run -d --rm -p 9010:9010 gcr.io/cloud-spanner-emulator/emulator
|
60
|
+
export SPANNER_EMULATOR_HOST=localhost:9010
|
61
|
+
bundle exec rake "acceptance[dummy-project,,dummy-instance,]"
|
62
|
+
```
|
63
|
+
|
64
|
+
If you want to run only one test, you can specify a test file.
|
65
|
+
|
66
|
+
```shell
|
67
|
+
bundle exec rake "acceptance[dummy-project,,dummy-instance,]" \
|
68
|
+
TEST=acceptance/cases/models/default_value_test.rb
|
69
|
+
```
|
70
|
+
|
55
71
|
## Coding Style
|
56
72
|
|
57
73
|
Please follow the established coding style in the library. The style is is
|
@@ -76,4 +92,4 @@ The rubocop settings depend on [googleapis/ruby-style](https://github.com/google
|
|
76
92
|
|
77
93
|
Please note that this project is released with a Contributor Code of Conduct. By
|
78
94
|
participating in this project you agree to abide by its terms. See
|
79
|
-
{file:CODE_OF_CONDUCT.md Code of Conduct} for more information.
|
95
|
+
{file:CODE_OF_CONDUCT.md Code of Conduct} for more information.
|
data/Gemfile
CHANGED
@@ -86,7 +86,7 @@ module ActiveRecord
|
|
86
86
|
|
87
87
|
def test_index_exists
|
88
88
|
with_change_table do |t|
|
89
|
-
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3")
|
89
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3") && ActiveRecord::gem_version <= Gem::Version.create('7.0.4')
|
90
90
|
@connection.expect :index_exists?, nil, [:delete_me, :bar, {}]
|
91
91
|
t.index_exists?(:bar, {})
|
92
92
|
else
|
@@ -98,7 +98,7 @@ module ActiveRecord
|
|
98
98
|
|
99
99
|
def test_index_exists_with_options
|
100
100
|
with_change_table do |t|
|
101
|
-
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3")
|
101
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3") && ActiveRecord::gem_version <= Gem::Version.create('7.0.4')
|
102
102
|
@connection.expect :index_exists?, nil, [:delete_me, :bar, {unique: true}]
|
103
103
|
t.index_exists?(:bar, {unique: true})
|
104
104
|
else
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "test_helper"
|
4
|
+
require "test_helpers/with_separate_database"
|
5
|
+
|
6
|
+
module Models
|
7
|
+
class DefaultValueTest < SpannerAdapter::TestCase
|
8
|
+
include TestHelpers::WithSeparateDatabase
|
9
|
+
|
10
|
+
class LiteralValue < ActiveRecord::Base; end
|
11
|
+
class ExpressionValue < ActiveRecord::Base; end
|
12
|
+
|
13
|
+
def test_literal_default_values
|
14
|
+
default = OpenStruct.new(
|
15
|
+
col_string: "default",
|
16
|
+
col_int64: 123,
|
17
|
+
col_float64: 1.23,
|
18
|
+
col_numeric: BigDecimal("1.23"),
|
19
|
+
col_bool: true,
|
20
|
+
col_date: Date.new(2023, 5, 9),
|
21
|
+
col_timestamp: DateTime.new(2023, 5, 9, 1, 2, 3),
|
22
|
+
)
|
23
|
+
|
24
|
+
connection.create_table :literal_values do |t|
|
25
|
+
t.column :col_string, :string, default: default.col_string
|
26
|
+
t.column :col_int64, :bigint, default: default.col_int64
|
27
|
+
t.column :col_float64, :float, default: default.col_float64
|
28
|
+
t.column :col_numeric, :numeric, default: default.col_numeric
|
29
|
+
t.column :col_bool, :boolean, default: default.col_bool
|
30
|
+
t.column :col_date, :date, default: default.col_date
|
31
|
+
t.column :col_timestamp, :datetime, default: default.col_timestamp
|
32
|
+
end
|
33
|
+
|
34
|
+
item = LiteralValue.new
|
35
|
+
default.each_pair { |col, expected| assert_equal(expected, item[col]) }
|
36
|
+
item.save!
|
37
|
+
default.each_pair { |col, expected| assert_equal(expected, item[col]) }
|
38
|
+
item.reload
|
39
|
+
default.each_pair { |col, expected| assert_equal(expected, item[col]) }
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_expression_default_values
|
43
|
+
connection.create_table :expression_values do |t|
|
44
|
+
t.column :col_numeric, :numeric, default: -> { "NUMERIC '1.23'" }
|
45
|
+
t.column :col_timestamp, :datetime, default: -> { "CURRENT_TIMESTAMP()" }
|
46
|
+
end
|
47
|
+
|
48
|
+
item = ExpressionValue.create!
|
49
|
+
item.reload
|
50
|
+
assert_equal(BigDecimal("1.23"), item.col_numeric)
|
51
|
+
assert(item.col_timestamp)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -7,29 +7,100 @@
|
|
7
7
|
# frozen_string_literal: true
|
8
8
|
|
9
9
|
require "test_helper"
|
10
|
-
require "
|
11
|
-
require "models/album_partial_disabled"
|
10
|
+
require "test_helpers/with_separate_database"
|
12
11
|
|
13
12
|
module ActiveRecord
|
14
13
|
module Model
|
15
|
-
class InterleaveTest
|
16
|
-
|
14
|
+
class InterleaveTest
|
15
|
+
class WithPartialInsertsDisabledTest < SpannerAdapter::TestCase
|
16
|
+
include SpannerAdapter::Associations::TestHelper
|
17
17
|
|
18
|
-
|
18
|
+
class Singer < ActiveRecord::Base
|
19
|
+
has_many :albums, foreign_key: :singerid, dependent: :delete_all
|
20
|
+
has_many :tracks, foreign_key: :singerid
|
21
|
+
end
|
19
22
|
|
20
|
-
|
21
|
-
|
23
|
+
class Album < ActiveRecord::Base
|
24
|
+
self.primary_keys = :singerid, :albumid
|
22
25
|
|
23
|
-
|
24
|
-
|
26
|
+
belongs_to :singer, foreign_key: :singerid
|
27
|
+
|
28
|
+
if ActiveRecord::VERSION::MAJOR >= 7
|
29
|
+
self.partial_inserts = false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
attr_accessor :singer
|
34
|
+
|
35
|
+
def setup
|
36
|
+
super
|
25
37
|
|
26
|
-
|
27
|
-
|
28
|
-
|
38
|
+
@singer = Singer.create first_name: "FirstName", last_name: "LastName"
|
39
|
+
end
|
40
|
+
|
41
|
+
def teardown
|
42
|
+
Album.destroy_all
|
43
|
+
Singer.destroy_all
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_with_partial_inserts_disabled
|
47
|
+
Album.create! title: "Title3", singer: singer
|
48
|
+
end
|
29
49
|
end
|
30
50
|
|
31
|
-
|
32
|
-
|
51
|
+
class StringParentKeyTest < SpannerAdapter::TestCase
|
52
|
+
include TestHelpers::WithSeparateDatabase
|
53
|
+
|
54
|
+
class Singer < ActiveRecord::Base
|
55
|
+
has_many :albums, foreign_key: :singer_id
|
56
|
+
end
|
57
|
+
|
58
|
+
class Album < ActiveRecord::Base
|
59
|
+
self.primary_keys = [:singer_id, :album_id]
|
60
|
+
belongs_to :singer, foreign_key: :singer_id
|
61
|
+
end
|
62
|
+
|
63
|
+
def setup
|
64
|
+
super
|
65
|
+
|
66
|
+
connection.ddl_batch do
|
67
|
+
connection.create_table :singers, id: false do |t|
|
68
|
+
t.string :singer_id, limit: 36, primary_key: true, null: false
|
69
|
+
t.string :name, null: false
|
70
|
+
end
|
71
|
+
|
72
|
+
connection.create_table :albums, id: false do |t|
|
73
|
+
t.interleave_in :singers
|
74
|
+
t.string :singer_id, limit: 36, parent_key: true, primary_key: true, null: false
|
75
|
+
t.integer :album_id, primary_key: true, null: false
|
76
|
+
t.string :title, null: false
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
@singer = Singer.create!(id: SecureRandom.uuid, name: "a singer")
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_create_album
|
84
|
+
Album.create!(singer: @singer, title: "an album")
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_update_album
|
88
|
+
album = Album.create!(singer: @singer, title: "an album")
|
89
|
+
album.update!(title: "an album 2")
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_get_album
|
93
|
+
album = Album.create!(singer: @singer, title: "an album")
|
94
|
+
got_album = Album.find([@singer.singer_id, album.album_id])
|
95
|
+
assert_equal(album, got_album)
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_get_albums_as_children
|
99
|
+
album1 = Album.create!(singer: @singer, title: "album1")
|
100
|
+
album2 = Album.create!(singer: @singer, title: "album2")
|
101
|
+
albums = @singer.albums.order(:title)
|
102
|
+
assert_equal([album1, album2], albums)
|
103
|
+
end
|
33
104
|
end
|
34
105
|
end
|
35
106
|
end
|
data/acceptance/models/album.rb
CHANGED
@@ -4,8 +4,6 @@
|
|
4
4
|
# license that can be found in the LICENSE file or at
|
5
5
|
# https://opensource.org/licenses/MIT.
|
6
6
|
|
7
|
-
require "composite_primary_keys"
|
8
|
-
|
9
7
|
class Album < ActiveRecord::Base
|
10
8
|
# Register both primary key columns with composite_primary_keys
|
11
9
|
self.primary_keys = :singerid, :albumid
|
data/acceptance/test_helper.rb
CHANGED
@@ -0,0 +1,47 @@
|
|
1
|
+
# Copyright 2023 Google LLC
|
2
|
+
#
|
3
|
+
# Use of this source code is governed by an MIT-style
|
4
|
+
# license that can be found in the LICENSE file or at
|
5
|
+
# https://opensource.org/licenses/MIT.
|
6
|
+
|
7
|
+
require "securerandom"
|
8
|
+
|
9
|
+
require "active_record/tasks/spanner_database_tasks"
|
10
|
+
|
11
|
+
module TestHelpers
|
12
|
+
module WithSeparateDatabase
|
13
|
+
attr_reader :connection
|
14
|
+
|
15
|
+
def setup
|
16
|
+
spanner_adapter_connection.create_database
|
17
|
+
ActiveRecord::Base.establish_connection connection_config
|
18
|
+
@connection = ActiveRecord::Base.connection
|
19
|
+
end
|
20
|
+
|
21
|
+
def teardown
|
22
|
+
spanner_adapter_connection.database.drop
|
23
|
+
end
|
24
|
+
|
25
|
+
def connection_config
|
26
|
+
{
|
27
|
+
"adapter" => "spanner",
|
28
|
+
"emulator_host" => ENV["SPANNER_EMULATOR_HOST"],
|
29
|
+
"project" => ENV["SPANNER_TEST_PROJECT"],
|
30
|
+
"instance" => ENV["SPANNER_TEST_INSTANCE"],
|
31
|
+
"credentials" => ENV["SPANNER_TEST_KEYFILE"],
|
32
|
+
"database" => database_id,
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
def database_id
|
37
|
+
@database_id ||= "ar-test-#{SecureRandom.hex 4}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def spanner_adapter_connection
|
41
|
+
@spanner_adapter_connection ||=
|
42
|
+
ActiveRecordSpannerAdapter::Connection.new(
|
43
|
+
connection_config.symbolize_keys
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -148,8 +148,10 @@ module ActiveRecord
|
|
148
148
|
|
149
149
|
def self._set_composite_primary_key_value primary_key, values
|
150
150
|
value = values[primary_key]
|
151
|
+
type = ActiveModel::Type::BigInteger.new
|
151
152
|
|
152
153
|
if value.is_a? ActiveModel::Attribute
|
154
|
+
type = value.type
|
153
155
|
value = value.value
|
154
156
|
end
|
155
157
|
|
@@ -161,8 +163,7 @@ module ActiveRecord
|
|
161
163
|
|
162
164
|
values[primary_key] =
|
163
165
|
if ActiveRecord::VERSION::MAJOR >= 7
|
164
|
-
ActiveModel::Attribute.from_database primary_key, value,
|
165
|
-
ActiveModel::Type::BigInteger.new
|
166
|
+
ActiveModel::Attribute.from_database primary_key, value, type
|
166
167
|
else
|
167
168
|
value
|
168
169
|
end
|
@@ -79,6 +79,18 @@ module ActiveRecordSpannerAdapter
|
|
79
79
|
column_name = row["COLUMN_NAME"]
|
80
80
|
options = column_options[column_name]
|
81
81
|
|
82
|
+
default = row["COLUMN_DEFAULT"]
|
83
|
+
default_function = row["GENERATION_EXPRESSION"]
|
84
|
+
|
85
|
+
if /\w+\(.*\)/.match?(default)
|
86
|
+
default_function ||= default
|
87
|
+
default = nil
|
88
|
+
end
|
89
|
+
|
90
|
+
if default && type == "STRING"
|
91
|
+
default = unquote_string default
|
92
|
+
end
|
93
|
+
|
82
94
|
Table::Column.new \
|
83
95
|
table_name,
|
84
96
|
column_name,
|
@@ -87,8 +99,8 @@ module ActiveRecordSpannerAdapter
|
|
87
99
|
allow_commit_timestamp: options["allow_commit_timestamp"],
|
88
100
|
ordinal_position: row["ORDINAL_POSITION"],
|
89
101
|
nullable: row["IS_NULLABLE"] == "YES",
|
90
|
-
default:
|
91
|
-
default_function:
|
102
|
+
default: default,
|
103
|
+
default_function: default_function,
|
92
104
|
generated: row["GENERATION_EXPRESSION"].present?
|
93
105
|
end
|
94
106
|
end
|
@@ -278,8 +290,70 @@ module ActiveRecordSpannerAdapter
|
|
278
290
|
[matched[1], limit]
|
279
291
|
end
|
280
292
|
|
293
|
+
def unquote_string value
|
294
|
+
return unquote_raw_string value, 1 if value[0] == "r" || value[0] == "R"
|
295
|
+
unescape_string unquote_raw_string value
|
296
|
+
end
|
297
|
+
|
281
298
|
private
|
282
299
|
|
300
|
+
def unquote_raw_string value, prefix_length = 0
|
301
|
+
triple_quote_range = prefix_length..(prefix_length + 2)
|
302
|
+
if value[triple_quote_range] == '"""' || value[triple_quote_range] == "'''"
|
303
|
+
value[(prefix_length + 3)...-3]
|
304
|
+
else
|
305
|
+
value[(prefix_length + 1)...-1]
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
def unescape_string value # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
310
|
+
str = ""
|
311
|
+
i = 0
|
312
|
+
|
313
|
+
while i < value.length
|
314
|
+
case value[i]
|
315
|
+
when "\\"
|
316
|
+
i += 1
|
317
|
+
case value[i]
|
318
|
+
when "a" then str += "\a"
|
319
|
+
when "b" then str += "\b"
|
320
|
+
when "f" then str += "\f"
|
321
|
+
when "n" then str += "\n"
|
322
|
+
when "r" then str += "\r"
|
323
|
+
when "t" then str += "\t"
|
324
|
+
when "v" then str += "\v"
|
325
|
+
when "\\" then str += "\\"
|
326
|
+
when "?" then str += "?"
|
327
|
+
when "'" then str += "'"
|
328
|
+
when '"' then str += '"'
|
329
|
+
when "`" then str += "`"
|
330
|
+
when "0".."7"
|
331
|
+
str += unescape_unicode value, i, 3, 8
|
332
|
+
i += 2
|
333
|
+
when "x", "X"
|
334
|
+
str += unescape_unicode value, i + 1, 2, 16
|
335
|
+
i += 2
|
336
|
+
when "u"
|
337
|
+
str += unescape_unicode value, i + 1, 4, 16
|
338
|
+
i += 4
|
339
|
+
when "U"
|
340
|
+
str += unescape_unicode value, i + 1, 8, 16
|
341
|
+
i += 8
|
342
|
+
end
|
343
|
+
else
|
344
|
+
str += value[i]
|
345
|
+
end
|
346
|
+
|
347
|
+
i += 1
|
348
|
+
end
|
349
|
+
|
350
|
+
str
|
351
|
+
end
|
352
|
+
|
353
|
+
def unescape_unicode value, start, length, base
|
354
|
+
[value[start...(start + length)].to_i(base)].pack "U"
|
355
|
+
end
|
356
|
+
|
283
357
|
def column_options table_name, column_name
|
284
358
|
sql = +"SELECT COLUMN_NAME, OPTION_NAME, OPTION_TYPE, OPTION_VALUE"
|
285
359
|
sql << " FROM INFORMATION_SCHEMA.COLUMN_OPTIONS"
|
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.4.
|
4
|
+
version: 1.4.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: 2023-
|
11
|
+
date: 2023-06-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: google-cloud-spanner
|
@@ -221,6 +221,8 @@ extra_rdoc_files: []
|
|
221
221
|
files:
|
222
222
|
- ".github/CODEOWNERS"
|
223
223
|
- ".github/blunderbuss.yml"
|
224
|
+
- ".github/release-please.yml"
|
225
|
+
- ".github/release-trigger.yml"
|
224
226
|
- ".github/sync-repo-settings.yaml"
|
225
227
|
- ".github/workflows/acceptance-tests-on-emulator.yaml"
|
226
228
|
- ".github/workflows/acceptance-tests-on-production.yaml"
|
@@ -270,6 +272,7 @@ files:
|
|
270
272
|
- acceptance/cases/migration/rename_column_test.rb
|
271
273
|
- acceptance/cases/migration/schema_dumper_test.rb
|
272
274
|
- acceptance/cases/models/calculation_query_test.rb
|
275
|
+
- acceptance/cases/models/default_value_test.rb
|
273
276
|
- acceptance/cases/models/generated_column_test.rb
|
274
277
|
- acceptance/cases/models/insert_all_test.rb
|
275
278
|
- acceptance/cases/models/interleave_test.rb
|
@@ -296,7 +299,6 @@ files:
|
|
296
299
|
- acceptance/models/account.rb
|
297
300
|
- acceptance/models/address.rb
|
298
301
|
- acceptance/models/album.rb
|
299
|
-
- acceptance/models/album_partial_disabled.rb
|
300
302
|
- acceptance/models/all_types.rb
|
301
303
|
- acceptance/models/author.rb
|
302
304
|
- acceptance/models/club.rb
|
@@ -314,6 +316,7 @@ files:
|
|
314
316
|
- acceptance/models/transaction.rb
|
315
317
|
- acceptance/schema/schema.rb
|
316
318
|
- acceptance/test_helper.rb
|
319
|
+
- acceptance/test_helpers/with_separate_database.rb
|
317
320
|
- activerecord-spanner-adapter.gemspec
|
318
321
|
- assets/solidus-db.png
|
319
322
|
- benchmarks/README.md
|
@@ -1,17 +0,0 @@
|
|
1
|
-
# Copyright 2021 Google LLC
|
2
|
-
#
|
3
|
-
# Use of this source code is governed by an MIT-style
|
4
|
-
# license that can be found in the LICENSE file or at
|
5
|
-
# https://opensource.org/licenses/MIT.
|
6
|
-
|
7
|
-
# frozen_string_literal: true
|
8
|
-
|
9
|
-
require "models/album"
|
10
|
-
|
11
|
-
class AlbumPartialDisabled < Album
|
12
|
-
self.table_name = :albums
|
13
|
-
|
14
|
-
if ActiveRecord::VERSION::MAJOR >= 7
|
15
|
-
self.partial_inserts = false
|
16
|
-
end
|
17
|
-
end
|