activerecord-spanner-adapter 1.2.2 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -1
  3. data/.github/blunderbuss.yml +1 -1
  4. data/.github/workflows/acceptance-tests-on-emulator.yaml +8 -8
  5. data/.github/workflows/ci.yaml +6 -4
  6. data/.github/workflows/nightly-acceptance-tests-on-emulator.yaml +14 -6
  7. data/.github/workflows/nightly-unit-tests.yaml +14 -6
  8. data/.release-please-manifest.json +1 -1
  9. data/CHANGELOG.md +28 -0
  10. data/Gemfile +1 -1
  11. data/README.md +4 -0
  12. data/acceptance/cases/migration/change_table_test.rb +23 -13
  13. data/acceptance/cases/migration/schema_dumper_test.rb +69 -0
  14. data/acceptance/cases/models/generated_column_test.rb +21 -7
  15. data/acceptance/cases/models/interleave_test.rb +36 -0
  16. data/acceptance/cases/models/logging_test.rb +57 -0
  17. data/acceptance/cases/models/query_test.rb +6 -1
  18. data/acceptance/cases/tasks/database_tasks_test.rb +407 -0
  19. data/acceptance/models/album_partial_disabled.rb +17 -0
  20. data/acceptance/schema/schema.rb +139 -134
  21. data/acceptance/test_helper.rb +2 -0
  22. data/examples/snippets/array-data-type/db/schema.rb +8 -3
  23. data/examples/snippets/bulk-insert/db/schema.rb +9 -4
  24. data/examples/snippets/commit-timestamp/db/schema.rb +11 -6
  25. data/examples/snippets/create-records/db/schema.rb +9 -4
  26. data/examples/snippets/date-data-type/db/schema.rb +8 -3
  27. data/examples/snippets/generated-column/db/schema.rb +6 -1
  28. data/examples/snippets/hints/db/schema.rb +6 -1
  29. data/examples/snippets/interleaved-tables/README.md +2 -2
  30. data/examples/snippets/interleaved-tables/db/schema.rb +5 -0
  31. data/examples/snippets/migrations/db/schema.rb +10 -5
  32. data/examples/snippets/mutations/db/schema.rb +9 -4
  33. data/examples/snippets/optimistic-locking/db/schema.rb +9 -4
  34. data/examples/snippets/partitioned-dml/db/schema.rb +5 -0
  35. data/examples/snippets/quickstart/db/schema.rb +9 -4
  36. data/examples/snippets/read-only-transactions/db/schema.rb +5 -0
  37. data/examples/snippets/read-write-transactions/db/schema.rb +9 -4
  38. data/examples/snippets/stale-reads/db/schema.rb +5 -0
  39. data/examples/snippets/timestamp-data-type/db/schema.rb +8 -3
  40. data/lib/active_record/connection_adapters/spanner/column.rb +23 -0
  41. data/lib/active_record/connection_adapters/spanner/database_statements.rb +7 -4
  42. data/lib/active_record/connection_adapters/spanner/quoting.rb +9 -0
  43. data/lib/active_record/connection_adapters/spanner/schema_creation.rb +17 -4
  44. data/lib/active_record/connection_adapters/spanner/schema_definitions.rb +11 -2
  45. data/lib/active_record/connection_adapters/spanner/schema_dumper.rb +56 -0
  46. data/lib/active_record/connection_adapters/spanner/schema_statements.rb +56 -9
  47. data/lib/active_record/connection_adapters/spanner/type_metadata.rb +19 -4
  48. data/lib/active_record/connection_adapters/spanner_adapter.rb +11 -0
  49. data/lib/active_record/tasks/spanner_database_tasks.rb +18 -4
  50. data/lib/active_record/type/spanner/spanner_active_record_converter.rb +10 -0
  51. data/lib/active_record/type/spanner/time.rb +10 -3
  52. data/lib/activerecord_spanner_adapter/base.rb +41 -27
  53. data/lib/activerecord_spanner_adapter/connection.rb +8 -3
  54. data/lib/activerecord_spanner_adapter/information_schema.rb +52 -3
  55. data/lib/activerecord_spanner_adapter/table/column.rb +7 -2
  56. data/lib/activerecord_spanner_adapter/version.rb +1 -1
  57. data/lib/arel/visitors/spanner.rb +8 -2
  58. metadata +9 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5796cf16ff55f858459e9d87da1cdd362b8b8a097161e3e7bda6283b56f6036a
4
- data.tar.gz: 9e2b8b7f9f4a72b7fe70d139281b82468d019cc46065368bd9fc0dc9e687a722
3
+ metadata.gz: 499376d85989274623aa1cda4cb9197e14636b42cd5cf5d5bda4b3fbdb2a6494
4
+ data.tar.gz: 4e0f7e384b4450b28581523a79540416567aa44745e44377a1f7744e11ff95e7
5
5
  SHA512:
6
- metadata.gz: 4899a089f30648b42a68386da0c43553c560c620178ff5609153cc67c42a08ada041b2dba565870c1b63cc067d3bbcd2208f97f290db93cda4dc2ba8c0dccb6a
7
- data.tar.gz: f3f3fca35b1e83a02fbd073cf5a8d969d411ac93588cb41c828e5a596d74cb8485f8bc23956e205ea1737a30bada65f65812ca0b24c8f02bb1287ed2106c6134
6
+ metadata.gz: a3d5ff8b79e774c6eb6c74431162366543d2476a8f2e7eb3f3f2d81dac249b0493a773b09cd787cdf5a8dd5b287d85170021b2e7c47c2aba9d06f76a77c2b9d6
7
+ data.tar.gz: 28bebd4c40535b80239992f66aed5030744623c21c00f875b548fac2c0318280871e83c294e8b87681a2376d34446050cee60283da469ff4fe175b2ad78685a6
data/.github/CODEOWNERS CHANGED
@@ -4,4 +4,4 @@
4
4
  # For syntax help see:
5
5
  # https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax
6
6
 
7
- * @googleapis/ruby-team @skuruppu @hengfengli @olavloite @xiangshen-dk
7
+ * @googleapis/ruby-team @olavloite @rahul2393 @ansh0l
@@ -1,2 +1,2 @@
1
1
  assign_issues:
2
- - hengfengli
2
+ - olavloite
@@ -18,16 +18,16 @@ jobs:
18
18
  strategy:
19
19
  max-parallel: 4
20
20
  matrix:
21
- ruby: [2.6, 2.7, 3.0]
22
- ar: [6.0.5.1, 6.1.6.1, 7.0.2.4, 7.0.3.1]
21
+ ruby: ["2.6", "2.7", "3.0", "3.1"]
22
+ ar: ["~> 6.0.6", "~> 6.1.7", "~> 7.0.4"]
23
23
  # Exclude combinations that are not supported.
24
24
  exclude:
25
- - ruby: 3.0
26
- ar: 6.0.5.1
27
- - ruby: 2.6
28
- ar: 7.0.2.4
29
- - ruby: 2.6
30
- ar: 7.0.3.1
25
+ - ruby: "3.0"
26
+ ar: "~> 6.0.6"
27
+ - ruby: "3.1"
28
+ ar: "~> 6.0.6"
29
+ - ruby: "2.6"
30
+ ar: "~> 7.0.4"
31
31
  env:
32
32
  AR_VERSION: ${{ matrix.ar }}
33
33
  steps:
@@ -10,14 +10,16 @@ jobs:
10
10
  strategy:
11
11
  max-parallel: 4
12
12
  matrix:
13
- ruby: ["2.6", "2.7", "3.0"]
14
- ar: ["6.0.4", "6.1.4", "7.0.2.4"]
13
+ ruby: ["2.6", "2.7", "3.0", "3.1"]
14
+ ar: ["~> 6.0.6", "~> 6.1.7", "~> 7.0.4"]
15
15
  # Exclude combinations that are not supported.
16
16
  exclude:
17
17
  - ruby: "3.0"
18
- ar: "6.0.4"
18
+ ar: "~> 6.0.6"
19
+ - ruby: "3.1"
20
+ ar: "~> 6.0.6"
19
21
  - ruby: "2.6"
20
- ar: "7.0.2.4"
22
+ ar: "~> 7.0.4"
21
23
  env:
22
24
  AR_VERSION: ${{ matrix.ar }}
23
25
  steps:
@@ -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.5, 2.6, 2.7, 3.0]
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]
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]
24
24
  # Exclude combinations that are not supported.
25
25
  exclude:
26
26
  - ruby: 3.0
@@ -33,14 +33,22 @@ jobs:
33
33
  ar: 6.0.3.7
34
34
  - ruby: 3.0
35
35
  ar: 6.0.4
36
- - ruby: 2.5
37
- ar: 7.0.2.4
36
+ - ruby: 3.1
37
+ ar: 6.0.0
38
+ - ruby: 3.1
39
+ ar: 6.0.1
40
+ - ruby: 3.1
41
+ ar: 6.0.2.2
42
+ - ruby: 3.1
43
+ ar: 6.0.3.7
44
+ - ruby: 3.1
45
+ ar: 6.0.4
38
46
  - ruby: 2.6
39
47
  ar: 7.0.2.4
40
- - ruby: 2.5
41
- ar: 7.0.3.1
42
48
  - ruby: 2.6
43
49
  ar: 7.0.3.1
50
+ - ruby: 2.6
51
+ ar: 7.0.4
44
52
  env:
45
53
  AR_VERSION: ${{ matrix.ar }}
46
54
  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.5, 2.6, 2.7, 3.0]
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]
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]
16
16
  # Exclude combinations that are not supported.
17
17
  exclude:
18
18
  - ruby: 3.0
@@ -25,14 +25,22 @@ jobs:
25
25
  ar: 6.0.3.7
26
26
  - ruby: 3.0
27
27
  ar: 6.0.4
28
- - ruby: 2.5
29
- ar: 7.0.2.4
28
+ - ruby: 3.1
29
+ ar: 6.0.0
30
+ - ruby: 3.1
31
+ ar: 6.0.1
32
+ - ruby: 3.1
33
+ ar: 6.0.2.2
34
+ - ruby: 3.1
35
+ ar: 6.0.3.7
36
+ - ruby: 3.1
37
+ ar: 6.0.4
30
38
  - ruby: 2.6
31
39
  ar: 7.0.2.4
32
- - ruby: 2.5
33
- ar: 7.0.3.1
34
40
  - ruby: 2.6
35
41
  ar: 7.0.3.1
42
+ - ruby: 2.6
43
+ ar: 7.0.4
36
44
  env:
37
45
  AR_VERSION: ${{ matrix.ar }}
38
46
  steps:
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "1.2.2"
2
+ ".": "1.4.0"
3
3
  }
data/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # Changelog
2
2
 
3
+ ### 1.4.0 (2023-01-18)
4
+
5
+ #### Features
6
+
7
+ * dropped support for Ruby 2.5 ([#236](https://github.com/googleapis/ruby-spanner-activerecord/issues/236))
8
+
9
+ ### 1.3.1 (2022-12-15)
10
+
11
+ #### Bug Fixes
12
+
13
+ * build error for ruby 2.5 ([#216](https://github.com/googleapis/ruby-spanner-activerecord/issues/216))
14
+
15
+ ### 1.3.0 (2022-12-08)
16
+
17
+ #### Features
18
+
19
+ * add check constraint support to migrations ([#205](https://github.com/googleapis/ruby-spanner-activerecord/issues/205))
20
+ * allows passing of type parameter when creating parent_key column ([#195](https://github.com/googleapis/ruby-spanner-activerecord/issues/195))
21
+ * include index options in the output of SchemaDumper ([#203](https://github.com/googleapis/ruby-spanner-activerecord/issues/203))
22
+ * schema_dumper should use DDL batch ([#207](https://github.com/googleapis/ruby-spanner-activerecord/issues/207))
23
+ * support column DEFAULT expressions in migrations ([#196](https://github.com/googleapis/ruby-spanner-activerecord/issues/196))
24
+ #### Bug Fixes
25
+
26
+ * ignore no database when recreating ([#208](https://github.com/googleapis/ruby-spanner-activerecord/issues/208))
27
+ #### Documentation
28
+
29
+ * fix typo in example of interleaved-tables ([#209](https://github.com/googleapis/ruby-spanner-activerecord/issues/209))
30
+
3
31
  ### 1.2.2 (2022-08-29)
4
32
 
5
33
  #### Documentation
data/Gemfile CHANGED
@@ -4,7 +4,7 @@ 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.15.0"
7
+ gem "minitest", "~> 5.16.3"
8
8
  gem "pry", "~> 0.13.0"
9
9
  gem "pry-byebug", "~> 3.9.0"
10
10
 
data/README.md CHANGED
@@ -13,6 +13,9 @@ This project provides a Cloud Spanner adapter for ActiveRecord. It supports the
13
13
  Known limitations are listed in the [Limitations](#limitations) section.
14
14
  Please report any problems that you might encounter by [creating a new issue](https://github.com/googleapis/ruby-spanner-activerecord/issues/new).
15
15
 
16
+ This adapter only supports GoogleSQL-dialect Cloud Spanner databases. PostgreSQL-dialect
17
+ databases are not supported.
18
+
16
19
  ## Installation
17
20
 
18
21
  Add this line to your application's Gemfile:
@@ -83,6 +86,7 @@ Table without Primary Key| Cloud Spanner support does not support tables without
83
86
  Table names CANNOT have spaces within them whether back-ticked or not|Cloud Spanner DOES NOT support tables with spaces in them for example `Entity ID`|Ensure that your table names don't contain spaces.
84
87
  Table names CANNOT have punctuation marks and MUST contain valid UTF-8|Cloud Spanner DOES NOT support punctuation marks e.g. periods ".", question marks "?" in table names|Ensure that your table names don't contain punctuation marks.
85
88
  Index with fields length [add_index](https://apidock.com/rails/v5.2.3/ActiveRecord/ConnectionAdapters/SchemaStatements/add_index)|Cloud Spanner does not support index with fields length | Ensure that your database definition does not include index definitions with field lengths.
89
+ Only GoogleSQL-dialect databases| Cloud Spanner supports both GoogleSQL- and PostgreSQL-dialect databases. This adapter only supports GoogleSQL-dialect databases. | Ensure that your database uses the GoogleSQL dialect.
86
90
 
87
91
  ## Contributing
88
92
 
@@ -30,77 +30,87 @@ module ActiveRecord
30
30
 
31
31
  def test_remove_references_column_type_with_polymorphic_removes_type
32
32
  with_change_table do |t|
33
- @connection.expect :remove_reference, nil, [:delete_me, :taggable, polymorphic: true]
33
+ @connection.expect :remove_reference, nil, [:delete_me, :taggable], polymorphic: true
34
34
  t.remove_references :taggable, polymorphic: true
35
35
  end
36
36
  end
37
37
 
38
38
  def test_references_column_type_with_polymorphic_and_options_null_is_false_adds_table_flag
39
39
  with_change_table do |t|
40
- @connection.expect :add_reference, nil, [:delete_me, :taggable, polymorphic: true, null: false]
40
+ @connection.expect :add_reference, nil, [:delete_me, :taggable], polymorphic: true, null: false
41
41
  t.references :taggable, polymorphic: true, null: false
42
42
  end
43
43
  end
44
44
 
45
45
  def test_remove_references_column_type_with_polymorphic_and_options_null_is_false_removes_table_flag
46
46
  with_change_table do |t|
47
- @connection.expect :remove_reference, nil, [:delete_me, :taggable, polymorphic: true, null: false]
47
+ @connection.expect :remove_reference, nil, [:delete_me, :taggable], polymorphic: true, null: false
48
48
  t.remove_references :taggable, polymorphic: true, null: false
49
49
  end
50
50
  end
51
51
 
52
52
  def test_references_column_type_with_polymorphic_and_type
53
53
  with_change_table do |t|
54
- @connection.expect :add_reference, nil, [:delete_me, :taggable, polymorphic: true, type: :string]
54
+ @connection.expect :add_reference, nil, [:delete_me, :taggable], polymorphic: true, type: :string
55
55
  t.references :taggable, polymorphic: true, type: :string
56
56
  end
57
57
  end
58
58
 
59
59
  def test_remove_references_column_type_with_polymorphic_and_type
60
60
  with_change_table do |t|
61
- @connection.expect :remove_reference, nil, [:delete_me, :taggable, polymorphic: true, type: :string]
61
+ @connection.expect :remove_reference, nil, [:delete_me, :taggable], polymorphic: true, type: :string
62
62
  t.remove_references :taggable, polymorphic: true, type: :string
63
63
  end
64
64
  end
65
65
 
66
66
  def test_timestamps_creates_updated_at_and_created_at
67
67
  with_change_table do |t|
68
- @connection.expect :add_timestamps, nil, [:delete_me, null: true]
68
+ @connection.expect :add_timestamps, nil, [:delete_me], null: true
69
69
  t.timestamps null: true
70
70
  end
71
71
  end
72
72
 
73
73
  def test_remove_timestamps_creates_updated_at_and_created_at
74
74
  with_change_table do |t|
75
- @connection.expect :remove_timestamps, nil, [:delete_me, { null: true }]
75
+ @connection.expect :remove_timestamps, nil, [:delete_me], null: true
76
76
  t.remove_timestamps(null: true)
77
77
  end
78
78
  end
79
79
 
80
80
  def test_primary_key_creates_primary_key_column
81
81
  with_change_table do |t|
82
- @connection.expect :add_column, nil, [:delete_me, :id, :primary_key, primary_key: true, first: true]
82
+ @connection.expect :add_column, nil, [:delete_me, :id, :primary_key], primary_key: true, first: true
83
83
  t.primary_key :id, first: true
84
84
  end
85
85
  end
86
86
 
87
87
  def test_index_exists
88
88
  with_change_table do |t|
89
- @connection.expect :index_exists?, nil, [:delete_me, :bar, {}]
90
- t.index_exists?(:bar)
89
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3")
90
+ @connection.expect :index_exists?, nil, [:delete_me, :bar, {}]
91
+ t.index_exists?(:bar, {})
92
+ else
93
+ @connection.expect :index_exists?, nil, [:delete_me, :bar]
94
+ t.index_exists?(:bar)
95
+ end
91
96
  end
92
97
  end
93
98
 
94
99
  def test_index_exists_with_options
95
100
  with_change_table do |t|
96
- @connection.expect :index_exists?, nil, [:delete_me, :bar, { unique: true }]
97
- t.index_exists?(:bar, unique: true)
101
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3")
102
+ @connection.expect :index_exists?, nil, [:delete_me, :bar, {unique: true}]
103
+ t.index_exists?(:bar, {unique: true})
104
+ else
105
+ @connection.expect :index_exists?, nil, [:delete_me, :bar], unique: true
106
+ t.index_exists?(:bar, unique: true)
107
+ end
98
108
  end
99
109
  end
100
110
 
101
111
  def test_remove_drops_multiple_columns_when_column_options_are_given
102
112
  with_change_table do |t|
103
- @connection.expect :remove_columns, nil, [:delete_me, :bar, :baz, type: :string, null: false]
113
+ @connection.expect :remove_columns, nil, [:delete_me, :bar, :baz], type: :string, null: false
104
114
  t.remove :bar, :baz, type: :string, null: false
105
115
  end
106
116
  end
@@ -0,0 +1,69 @@
1
+ # Copyright 2022 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 "test_helper"
10
+
11
+ module ActiveRecord
12
+ class Migration
13
+ class IndexTest < SpannerAdapter::TestCase
14
+ include SpannerAdapter::Migration::TestHelper
15
+
16
+ def test_dump_schema_contains_start_batch_ddl
17
+ connection = ActiveRecord::Base.connection
18
+ schema = StringIO.new
19
+ ActiveRecord::SchemaDumper.dump connection, schema
20
+ assert schema.string.include?("connection.start_batch_ddl")
21
+ end
22
+
23
+ def test_dump_schema_contains_run_batch
24
+ connection = ActiveRecord::Base.connection
25
+ schema = StringIO.new
26
+ ActiveRecord::SchemaDumper.dump connection, schema
27
+ assert schema.string.include?(" connection.run_batch\n"\
28
+ "rescue\n"\
29
+ " abort_batch\n"\
30
+ " raise")
31
+ end
32
+
33
+ def test_dump_schema_contains_albums_table
34
+ connection = ActiveRecord::Base.connection
35
+ schema = StringIO.new
36
+ ActiveRecord::SchemaDumper.dump connection, schema
37
+ assert schema.string.include?("create_table \"albums\", primary_key: \"albumid\"")
38
+ end
39
+
40
+ def test_dump_schema_contains_interleaved_index
41
+ connection = ActiveRecord::Base.connection
42
+ schema = StringIO.new
43
+ ActiveRecord::SchemaDumper.dump connection, schema
44
+ assert schema.string.include?("t.index [\"singerid\", \"albumid\", \"title\"], name: \"index_tracks_on_singerid_and_albumid_and_title\", order: { singerid: :asc, albumid: :asc, title: :asc }, null_filtered: true, interleave_in: \"albums\""), schema.string
45
+ end
46
+
47
+ def test_dump_schema_should_not_contain_id_limit
48
+ connection = ActiveRecord::Base.connection
49
+ schema = StringIO.new
50
+ ActiveRecord::SchemaDumper.dump connection, schema
51
+ assert !schema.string.include?("id: { limit: 8 }")
52
+ end
53
+
54
+ def test_dump_schema_contains_commit_timestamp
55
+ connection = ActiveRecord::Base.connection
56
+ schema = StringIO.new
57
+ ActiveRecord::SchemaDumper.dump connection, schema
58
+ assert schema.string.include?("t.time \"last_updated\", allow_commit_timestamp: true"), schema.string
59
+ end
60
+
61
+ def test_dump_schema_contains_virtual_column
62
+ connection = ActiveRecord::Base.connection
63
+ schema = StringIO.new
64
+ ActiveRecord::SchemaDumper.dump connection, schema
65
+ assert schema.string.include?("t.virtual \"full_name\", type: :string, as: \"COALESCE(first_name || ' ', '') || last_name\", stored: true"), schema.string
66
+ end
67
+ end
68
+ end
69
+ end
@@ -76,13 +76,24 @@ module ActiveRecord
76
76
  end
77
77
  end
78
78
 
79
+ VERSION_7 = ActiveRecord.gem_version >= Gem::Version.create("7.0.0")
80
+
81
+ def assert_raises_below_ar_7(ex, &test)
82
+ if VERSION_7
83
+ assert_nothing_raised &test
84
+ else
85
+ assert_raises ex, &test
86
+ end
87
+ end
88
+
79
89
  def test_create_with_value_for_generated_column
80
90
  # Note: The statement itself will not fail for an explicit transaction that uses buffered transactions.
81
91
  # Instead, the commit will fail. That is tested in a separate test case.
82
92
  [nil, :serializable].each do |isolation|
83
93
  run_in_transaction isolation do
84
- assert_raises ActiveRecord::StatementInvalid do
85
- Singer.create first_name: "Pete", last_name: "Allison", full_name: "Alice Peterson"
94
+ assert_raises_below_ar_7 ActiveRecord::StatementInvalid do
95
+ singer = Singer.create first_name: "Pete", last_name: "Allison", full_name: "Alice Peterson"
96
+ assert_equal "Pete Allison", singer.reload.full_name
86
97
  end
87
98
  end
88
99
  end
@@ -90,10 +101,11 @@ module ActiveRecord
90
101
 
91
102
  def test_create_with_value_for_generated_column_buffered_mutations
92
103
  # The transaction itself will raise an error, as the failure occurs during the commit.
93
- assert_raises ActiveRecord::StatementInvalid do
94
- Singer.transaction isolation: :buffered_mutations do
104
+ assert_raises_below_ar_7 ActiveRecord::StatementInvalid do
105
+ singer = run_in_transaction :buffered_mutations do
95
106
  Singer.create first_name: "Pete", last_name: "Allison", full_name: "Alice Peterson"
96
107
  end
108
+ assert_equal "Pete Allison", singer.reload.full_name
97
109
  end
98
110
  end
99
111
 
@@ -104,10 +116,11 @@ module ActiveRecord
104
116
  singer = Singer.create first_name: "Pete", last_name: "Allison"
105
117
  singer.reload # reload to ensure the full_name attribute is populated.
106
118
  run_in_transaction isolation do
107
- assert_raises ActiveRecord::StatementInvalid do
119
+ assert_raises_below_ar_7 ActiveRecord::StatementInvalid do
108
120
  Singer.update full_name: "Alice Peterson"
109
121
  end
110
122
  end
123
+ assert_equal "Pete Allison", singer.reload.full_name
111
124
  end
112
125
  end
113
126
 
@@ -115,11 +128,12 @@ module ActiveRecord
115
128
  singer = Singer.create first_name: "Pete", last_name: "Allison"
116
129
  singer.reload # reload to ensure the full_name attribute is populated.
117
130
  # The transaction itself will raise an error, as the failure occurs during the commit.
118
- assert_raises ActiveRecord::StatementInvalid do
119
- Singer.transaction isolation: :buffered_mutations do
131
+ assert_raises_below_ar_7 ActiveRecord::StatementInvalid do
132
+ run_in_transaction :buffered_mutations do
120
133
  Singer.update full_name: "Alice Peterson"
121
134
  end
122
135
  end
136
+ assert_equal "Pete Allison", singer.reload.full_name
123
137
  end
124
138
  end
125
139
  end
@@ -0,0 +1,36 @@
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 "test_helper"
10
+ require "models/singer"
11
+ require "models/album_partial_disabled"
12
+
13
+ module ActiveRecord
14
+ module Model
15
+ class InterleaveTest < SpannerAdapter::TestCase
16
+ include SpannerAdapter::Associations::TestHelper
17
+
18
+ attr_accessor :singer
19
+
20
+ def setup
21
+ super
22
+
23
+ @singer = Singer.create first_name: "FirstName", last_name: "LastName"
24
+ end
25
+
26
+ def teardown
27
+ Album.destroy_all
28
+ Singer.destroy_all
29
+ end
30
+
31
+ def test_with_partial_inserts_disabled
32
+ AlbumPartialDisabled.create! title: "Title3", singer: singer
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,57 @@
1
+ # Copyright 2022 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 "active_support/log_subscriber/test_helper"
10
+ require "test_helper"
11
+ require "models/post"
12
+
13
+ module ActiveRecord
14
+ module Model
15
+ class LoggingTest < SpannerAdapter::TestCase
16
+ include ActiveSupport::LogSubscriber::TestHelper
17
+
18
+ setup do
19
+ ActiveRecord::LogSubscriber.attach_to(:active_record)
20
+ end
21
+
22
+ def test_logs_without_binds
23
+ skip "This test sometimes fails because nothing is logged (or marked as logged by the test logger)"
24
+
25
+ published_time = Time.new(2016, 05, 11, 19, 0, 0)
26
+ Post.where(published_time: published_time, title: 'Title - 1').first
27
+
28
+ wait
29
+ assert @logger.logged(:debug).length >= 1
30
+ assert_no_match "[[\"published_time\", \"#{published_time.utc.iso8601(9)}\"], [\"title\", \"Title - 1\"]",
31
+ @logger.logged(:debug).last
32
+ end
33
+
34
+ def test_logs_with_binds
35
+ skip "This test sometimes fails because nothing is logged (or marked as logged by the test logger)"
36
+
37
+ ActiveRecord::ConnectionAdapters::SpannerAdapter.log_statement_binds = true
38
+
39
+ published_time = Time.new(2016, 05, 11, 19, 0, 0)
40
+ Post.where(published_time: published_time, title: 'Title - 1').first
41
+
42
+ wait
43
+ assert @logger.logged(:debug).length >= 1
44
+ assert_match "[[\"published_time\", \"#{published_time.utc.iso8601(9)}\"], [\"title\", \"Title - 1\"]",
45
+ @logger.logged(:debug).last
46
+ ensure
47
+ ActiveRecord::ConnectionAdapters::SpannerAdapter.log_statement_binds = false
48
+ end
49
+
50
+ private
51
+
52
+ def set_logger(logger)
53
+ ActiveRecord::Base.logger = logger
54
+ end
55
+ end
56
+ end
57
+ end
@@ -166,6 +166,11 @@ module ActiveRecord
166
166
  assert_nil post.id
167
167
  assert_equal "Title - 1", post.title
168
168
  end
169
+
170
+ def test_to_sql
171
+ assert_equal "SELECT `comments`.* FROM `comments` WHERE `comments`.`comment` = 'Comment - 2'",
172
+ Comment.where(comment: 'Comment - 2').to_sql
173
+ end
169
174
  end
170
175
  end
171
- end
176
+ end