activerecord-spanner-adapter 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/acceptance-tests-on-emulator.yaml +1 -1
  3. data/.github/workflows/acceptance-tests-on-production.yaml +5 -3
  4. data/.github/workflows/ci.yaml +1 -1
  5. data/.github/workflows/nightly-acceptance-tests-on-emulator.yaml +1 -1
  6. data/.github/workflows/nightly-acceptance-tests-on-production.yaml +5 -3
  7. data/.github/workflows/nightly-unit-tests.yaml +1 -1
  8. data/.github/workflows/release-please-label.yml +1 -1
  9. data/.release-please-manifest.json +1 -1
  10. data/CHANGELOG.md +14 -0
  11. data/Gemfile +5 -2
  12. data/README.md +10 -10
  13. data/acceptance/cases/interleaved_associations/has_many_associations_using_interleaved_test.rb +6 -0
  14. data/acceptance/cases/migration/change_schema_test.rb +19 -3
  15. data/acceptance/cases/migration/schema_dumper_test.rb +10 -1
  16. data/acceptance/cases/models/insert_all_test.rb +22 -0
  17. data/acceptance/cases/models/interleave_test.rb +6 -0
  18. data/acceptance/cases/tasks/database_tasks_test.rb +340 -2
  19. data/acceptance/cases/transactions/optimistic_locking_test.rb +6 -0
  20. data/acceptance/cases/transactions/read_write_transactions_test.rb +24 -0
  21. data/acceptance/models/table_with_sequence.rb +10 -0
  22. data/acceptance/schema/schema.rb +65 -19
  23. data/acceptance/test_helper.rb +1 -1
  24. data/activerecord-spanner-adapter.gemspec +1 -1
  25. data/examples/snippets/bit-reversed-sequence/README.md +103 -0
  26. data/examples/snippets/bit-reversed-sequence/Rakefile +13 -0
  27. data/examples/snippets/bit-reversed-sequence/application.rb +68 -0
  28. data/examples/snippets/bit-reversed-sequence/config/database.yml +8 -0
  29. data/examples/snippets/bit-reversed-sequence/db/migrate/01_create_tables.rb +33 -0
  30. data/examples/snippets/bit-reversed-sequence/db/schema.rb +31 -0
  31. data/examples/snippets/bit-reversed-sequence/db/seeds.rb +31 -0
  32. data/examples/snippets/bit-reversed-sequence/models/album.rb +11 -0
  33. data/examples/snippets/bit-reversed-sequence/models/singer.rb +15 -0
  34. data/examples/snippets/interleaved-tables/README.md +44 -53
  35. data/examples/snippets/interleaved-tables/Rakefile +2 -2
  36. data/examples/snippets/interleaved-tables/application.rb +2 -2
  37. data/examples/snippets/interleaved-tables/db/migrate/01_create_tables.rb +12 -18
  38. data/examples/snippets/interleaved-tables/db/schema.rb +9 -7
  39. data/examples/snippets/interleaved-tables/db/seeds.rb +1 -1
  40. data/examples/snippets/interleaved-tables/models/album.rb +3 -7
  41. data/examples/snippets/interleaved-tables/models/singer.rb +1 -1
  42. data/examples/snippets/interleaved-tables/models/track.rb +6 -7
  43. data/examples/snippets/interleaved-tables-before-7.1/README.md +167 -0
  44. data/examples/snippets/interleaved-tables-before-7.1/Rakefile +13 -0
  45. data/examples/snippets/interleaved-tables-before-7.1/application.rb +126 -0
  46. data/examples/snippets/interleaved-tables-before-7.1/config/database.yml +8 -0
  47. data/examples/snippets/interleaved-tables-before-7.1/db/migrate/01_create_tables.rb +44 -0
  48. data/examples/snippets/interleaved-tables-before-7.1/db/schema.rb +37 -0
  49. data/examples/snippets/interleaved-tables-before-7.1/db/seeds.rb +40 -0
  50. data/examples/snippets/interleaved-tables-before-7.1/models/album.rb +20 -0
  51. data/examples/snippets/interleaved-tables-before-7.1/models/singer.rb +18 -0
  52. data/examples/snippets/interleaved-tables-before-7.1/models/track.rb +28 -0
  53. data/examples/snippets/query-logs/README.md +43 -0
  54. data/examples/snippets/query-logs/Rakefile +13 -0
  55. data/examples/snippets/query-logs/application.rb +63 -0
  56. data/examples/snippets/query-logs/config/database.yml +8 -0
  57. data/examples/snippets/query-logs/db/migrate/01_create_tables.rb +21 -0
  58. data/examples/snippets/query-logs/db/schema.rb +31 -0
  59. data/examples/snippets/query-logs/db/seeds.rb +24 -0
  60. data/examples/snippets/query-logs/models/album.rb +9 -0
  61. data/examples/snippets/query-logs/models/singer.rb +9 -0
  62. data/lib/active_record/connection_adapters/spanner/column.rb +13 -0
  63. data/lib/active_record/connection_adapters/spanner/database_statements.rb +144 -35
  64. data/lib/active_record/connection_adapters/spanner/schema_cache.rb +3 -21
  65. data/lib/active_record/connection_adapters/spanner/schema_creation.rb +11 -0
  66. data/lib/active_record/connection_adapters/spanner/schema_definitions.rb +4 -0
  67. data/lib/active_record/connection_adapters/spanner/schema_statements.rb +3 -2
  68. data/lib/active_record/connection_adapters/spanner_adapter.rb +28 -9
  69. data/lib/activerecord_spanner_adapter/base.rb +58 -21
  70. data/lib/activerecord_spanner_adapter/information_schema.rb +33 -24
  71. data/lib/activerecord_spanner_adapter/primary_key.rb +1 -1
  72. data/lib/activerecord_spanner_adapter/table/column.rb +4 -9
  73. data/lib/activerecord_spanner_adapter/version.rb +1 -1
  74. data/lib/arel/visitors/spanner.rb +3 -1
  75. metadata +33 -4
@@ -15,6 +15,8 @@ module ActiveRecordSpannerAdapter
15
15
  class InformationSchema
16
16
  include ActiveRecord::ConnectionAdapters::Quoting
17
17
 
18
+ IsRails71OrLater = ActiveRecord.gem_version >= Gem::Version.create("7.1.0")
19
+
18
20
  attr_reader :connection
19
21
 
20
22
  def initialize connection
@@ -62,6 +64,7 @@ module ActiveRecordSpannerAdapter
62
64
  end
63
65
 
64
66
  def table_columns table_name, column_name: nil
67
+ primary_keys = table_primary_keys(table_name).map(&:name)
65
68
  sql = +"SELECT COLUMN_NAME, SPANNER_TYPE, IS_NULLABLE, GENERATION_EXPRESSION,"
66
69
  sql << " CAST(COLUMN_DEFAULT AS STRING) AS COLUMN_DEFAULT, ORDINAL_POSITION"
67
70
  sql << " FROM INFORMATION_SCHEMA.COLUMNS"
@@ -75,34 +78,40 @@ module ActiveRecordSpannerAdapter
75
78
  table_name: table_name,
76
79
  column_name: column_name
77
80
  ).map do |row|
78
- type, limit = parse_type_and_limit row["SPANNER_TYPE"]
79
- column_name = row["COLUMN_NAME"]
80
- options = column_options[column_name]
81
+ _create_column table_name, row, primary_keys, column_options
82
+ end
83
+ end
81
84
 
82
- default = row["COLUMN_DEFAULT"]
83
- default_function = row["GENERATION_EXPRESSION"]
85
+ def _create_column table_name, row, primary_keys, column_options
86
+ type, limit = parse_type_and_limit row["SPANNER_TYPE"]
87
+ column_name = row["COLUMN_NAME"]
88
+ options = column_options[column_name]
89
+ primary_key = primary_keys.include? column_name
84
90
 
85
- if /\w+\(.*\)/.match?(default)
86
- default_function ||= default
87
- default = nil
88
- end
91
+ default = row["COLUMN_DEFAULT"]
92
+ default_function = row["GENERATION_EXPRESSION"]
89
93
 
90
- if default && type == "STRING"
91
- default = unquote_string default
92
- end
94
+ if default && default.length < 200 && /\w+\(.*\)/.match?(default)
95
+ default_function ||= default
96
+ default = nil
97
+ end
93
98
 
94
- Table::Column.new \
95
- table_name,
96
- column_name,
97
- type,
98
- limit: limit,
99
- allow_commit_timestamp: options["allow_commit_timestamp"],
100
- ordinal_position: row["ORDINAL_POSITION"],
101
- nullable: row["IS_NULLABLE"] == "YES",
102
- default: default,
103
- default_function: default_function,
104
- generated: row["GENERATION_EXPRESSION"].present?
99
+ if default && type == "STRING"
100
+ default = unquote_string default
105
101
  end
102
+
103
+ Table::Column.new \
104
+ table_name,
105
+ column_name,
106
+ type,
107
+ limit: limit,
108
+ allow_commit_timestamp: options["allow_commit_timestamp"],
109
+ ordinal_position: row["ORDINAL_POSITION"],
110
+ nullable: row["IS_NULLABLE"] == "YES",
111
+ default: default,
112
+ default_function: default_function,
113
+ generated: row["GENERATION_EXPRESSION"].present?,
114
+ primary_key: primary_key
106
115
  end
107
116
 
108
117
  def table_column table_name, column_name
@@ -114,7 +123,7 @@ module ActiveRecordSpannerAdapter
114
123
  # ActiveRecord. The parent primary key columns are filtered out by default to allow interleaved tables to be
115
124
  # considered as tables with a single-column primary key by ActiveRecord. The actual primary key of the table will
116
125
  # include both the parent primary key columns and the 'own' primary key columns of a table.
117
- def table_primary_keys table_name, include_parent_keys = false
126
+ def table_primary_keys table_name, include_parent_keys = IsRails71OrLater
118
127
  sql = +"WITH TABLE_PK_COLS AS ( "
119
128
  sql << "SELECT C.TABLE_NAME, C.COLUMN_NAME, C.INDEX_NAME, C.COLUMN_ORDERING, C.ORDINAL_POSITION "
120
129
  sql << "FROM INFORMATION_SCHEMA.INDEX_COLUMNS C "
@@ -18,7 +18,7 @@ module ActiveRecord
18
18
  end
19
19
 
20
20
  def fetch_primary_and_parent_key
21
- return connection.schema_cache.primary_and_parent_keys table_name \
21
+ return connection.spanner_schema_cache.primary_and_parent_keys table_name \
22
22
  if ActiveRecord::Base != self && table_exists?
23
23
  end
24
24
 
@@ -9,8 +9,7 @@ module ActiveRecordSpannerAdapter
9
9
  class Column
10
10
  attr_accessor :table_name, :name, :type, :limit, :ordinal_position,
11
11
  :allow_commit_timestamp, :default, :default_function, :generated,
12
- :primary_key
13
- attr_writer :nullable
12
+ :primary_key, :nullable
14
13
 
15
14
  def initialize \
16
15
  table_name,
@@ -22,7 +21,8 @@ module ActiveRecordSpannerAdapter
22
21
  allow_commit_timestamp: nil,
23
22
  default: nil,
24
23
  default_function: nil,
25
- generated: nil
24
+ generated: nil,
25
+ primary_key: false
26
26
  @table_name = table_name.to_s
27
27
  @name = name.to_s
28
28
  @type = type
@@ -33,12 +33,7 @@ module ActiveRecordSpannerAdapter
33
33
  @default = default
34
34
  @default_function = default_function
35
35
  @generated = generated == true
36
- @primary_key = false
37
- end
38
-
39
- def nullable
40
- return false if primary_key
41
- @nullable
36
+ @primary_key = primary_key
42
37
  end
43
38
 
44
39
  def spanner_type
@@ -5,5 +5,5 @@
5
5
  # https://opensource.org/licenses/MIT.
6
6
 
7
7
  module ActiveRecordSpannerAdapter
8
- VERSION = "1.5.0".freeze
8
+ VERSION = "1.6.0".freeze
9
9
  end
@@ -139,7 +139,9 @@ module Arel # :nodoc: all
139
139
  # Do not generate a query parameter if the value should be set to the PENDING_COMMIT_TIMESTAMP(), as that is
140
140
  # not supported as a parameter value by Cloud Spanner.
141
141
  return collector << "PENDING_COMMIT_TIMESTAMP()" \
142
- if o.value.type.is_a?(ActiveRecord::Type::Spanner::Time) && o.value.value == :commit_timestamp
142
+ if o.value.respond_to?(:type) \
143
+ && o.value.type.is_a?(ActiveRecord::Type::Spanner::Time) \
144
+ && o.value.value == :commit_timestamp
143
145
  collector.add_bind(o.value, &bind_block)
144
146
  end
145
147
  # rubocop:enable Naming/MethodName
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.5.0
4
+ version: 1.6.0
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-03 00:00:00.000000000 Z
11
+ date: 2023-12-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: google-cloud-spanner
@@ -33,7 +33,7 @@ dependencies:
33
33
  version: 6.0.0
34
34
  - - "<"
35
35
  - !ruby/object:Gem::Version
36
- version: '7.1'
36
+ version: '7.2'
37
37
  type: :runtime
38
38
  prerelease: false
39
39
  version_requirements: !ruby/object:Gem::Requirement
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: 6.0.0
44
44
  - - "<"
45
45
  - !ruby/object:Gem::Version
46
- version: '7.1'
46
+ version: '7.2'
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: autotest-suffix
49
49
  requirement: !ruby/object:Gem::Requirement
@@ -312,6 +312,7 @@ files:
312
312
  - acceptance/models/organization.rb
313
313
  - acceptance/models/post.rb
314
314
  - acceptance/models/singer.rb
315
+ - acceptance/models/table_with_sequence.rb
315
316
  - acceptance/models/track.rb
316
317
  - acceptance/models/transaction.rb
317
318
  - acceptance/schema/schema.rb
@@ -342,6 +343,15 @@ files:
342
343
  - examples/snippets/array-data-type/db/seeds.rb
343
344
  - examples/snippets/array-data-type/models/entity_with_array_types.rb
344
345
  - examples/snippets/bin/create_emulator_instance.rb
346
+ - examples/snippets/bit-reversed-sequence/README.md
347
+ - examples/snippets/bit-reversed-sequence/Rakefile
348
+ - examples/snippets/bit-reversed-sequence/application.rb
349
+ - examples/snippets/bit-reversed-sequence/config/database.yml
350
+ - examples/snippets/bit-reversed-sequence/db/migrate/01_create_tables.rb
351
+ - examples/snippets/bit-reversed-sequence/db/schema.rb
352
+ - examples/snippets/bit-reversed-sequence/db/seeds.rb
353
+ - examples/snippets/bit-reversed-sequence/models/album.rb
354
+ - examples/snippets/bit-reversed-sequence/models/singer.rb
345
355
  - examples/snippets/bulk-insert/README.md
346
356
  - examples/snippets/bulk-insert/Rakefile
347
357
  - examples/snippets/bulk-insert/application.rb
@@ -395,6 +405,16 @@ files:
395
405
  - examples/snippets/hints/db/seeds.rb
396
406
  - examples/snippets/hints/models/album.rb
397
407
  - examples/snippets/hints/models/singer.rb
408
+ - examples/snippets/interleaved-tables-before-7.1/README.md
409
+ - examples/snippets/interleaved-tables-before-7.1/Rakefile
410
+ - examples/snippets/interleaved-tables-before-7.1/application.rb
411
+ - examples/snippets/interleaved-tables-before-7.1/config/database.yml
412
+ - examples/snippets/interleaved-tables-before-7.1/db/migrate/01_create_tables.rb
413
+ - examples/snippets/interleaved-tables-before-7.1/db/schema.rb
414
+ - examples/snippets/interleaved-tables-before-7.1/db/seeds.rb
415
+ - examples/snippets/interleaved-tables-before-7.1/models/album.rb
416
+ - examples/snippets/interleaved-tables-before-7.1/models/singer.rb
417
+ - examples/snippets/interleaved-tables-before-7.1/models/track.rb
398
418
  - examples/snippets/interleaved-tables/README.md
399
419
  - examples/snippets/interleaved-tables/Rakefile
400
420
  - examples/snippets/interleaved-tables/application.rb
@@ -442,6 +462,15 @@ files:
442
462
  - examples/snippets/partitioned-dml/db/seeds.rb
443
463
  - examples/snippets/partitioned-dml/models/album.rb
444
464
  - examples/snippets/partitioned-dml/models/singer.rb
465
+ - examples/snippets/query-logs/README.md
466
+ - examples/snippets/query-logs/Rakefile
467
+ - examples/snippets/query-logs/application.rb
468
+ - examples/snippets/query-logs/config/database.yml
469
+ - examples/snippets/query-logs/db/migrate/01_create_tables.rb
470
+ - examples/snippets/query-logs/db/schema.rb
471
+ - examples/snippets/query-logs/db/seeds.rb
472
+ - examples/snippets/query-logs/models/album.rb
473
+ - examples/snippets/query-logs/models/singer.rb
445
474
  - examples/snippets/quickstart/README.md
446
475
  - examples/snippets/quickstart/Rakefile
447
476
  - examples/snippets/quickstart/application.rb