activerecord-spanner-adapter 2.4.0 → 2.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cb3f5f2106d42a64cf32616e119f188cc13a1b81acfa040765ae4b5cb2838cf1
4
- data.tar.gz: 5ff65bbec67470ddc479f6ba985e9d31c0562848b9f0739e697ceb1d6715e3dc
3
+ metadata.gz: e5132b6ef0337fa324c42c5b61ff6bee8e745352c58c46afc5f583a253fc6571
4
+ data.tar.gz: 699d2b993d739c78fc95fc12b30189e512517111aa9ae787d929b9d3ac828576
5
5
  SHA512:
6
- metadata.gz: 939b508009ff79969637045e526dab1a73ed2f9b979fc6812447b2b98e673dce42e2d55bbf924fc6b372c35e481a374f8fc556c853b7861b8344735549ca3521
7
- data.tar.gz: f9c2dc8d41a7748a12daa8e342ae020c5109f793f62f0d2c506842d7030cac9d9578e169e356728f80e7c590e0a48bfa75fd05c235b121c25c9858e84cd25463
6
+ metadata.gz: 3d97e90c71f7dad83a35fc6cfb1921c24989d88b050c88b75ff444dbc58d4c0c2a9abbde2f8197d700dca121dda5c12853e4f6cae6c27bfc0520c7facbff3338
7
+ data.tar.gz: 5dbb5523a45941eff16db888d0af3c5ab7ea3e54af9e94d0f0943cef2a9b6d5e39078df1a1761e05a436910906cd19825f84f298d8e2b9043d79981dff51b4f7
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 @olavloite @rahul2393 @ansh0l
7
+ * @googleapis/cloud-sdk-ruby-team @olavloite @rahul2393 @ansh0l
@@ -19,11 +19,13 @@ jobs:
19
19
  max-parallel: 4
20
20
  matrix:
21
21
  ruby: ["3.1", "3.2", "3.3", "3.4"]
22
- ar: ["~> 7.0.0", "~> 7.1.0", "~> 7.2.0", "~> 8.0.0"]
22
+ ar: ["~> 7.0.0", "~> 7.1.0", "~> 7.2.0", "~> 8.0.0", "~> 8.1.0"]
23
23
  # Exclude combinations that are not supported.
24
24
  exclude:
25
25
  - ruby: "3.1"
26
26
  ar: "~> 8.0.0"
27
+ - ruby: "3.1"
28
+ ar: "~> 8.1.0"
27
29
  - ruby: "3.4"
28
30
  ar: "~> 7.0.0"
29
31
  - ruby: "3.4"
@@ -11,11 +11,13 @@ jobs:
11
11
  max-parallel: 4
12
12
  matrix:
13
13
  ruby: ["3.1", "3.2", "3.3", "3.4"]
14
- ar: ["~> 7.0.0", "~> 7.1.0", "~> 7.2.0", "~> 8.0.0"]
14
+ ar: ["~> 7.0.0", "~> 7.1.0", "~> 7.2.0", "~> 8.0.0", "~> 8.1.0"]
15
15
  # Exclude combinations that are not supported.
16
16
  exclude:
17
17
  - ruby: "3.1"
18
18
  ar: "~> 8.0.0"
19
+ - ruby: "3.1"
20
+ ar: "~> 8.1.0"
19
21
  - ruby: "3.4"
20
22
  ar: "~> 7.0.0"
21
23
  - ruby: "3.4"
@@ -19,11 +19,13 @@ jobs:
19
19
  max-parallel: 4
20
20
  matrix:
21
21
  ruby: ["3.1", "3.2", "3.3", "3.4"]
22
- ar: ["~> 7.0.0", "~> 7.1.0", "~> 7.2.0", "~> 8.0.0"]
22
+ ar: ["~> 7.0.0", "~> 7.1.0", "~> 7.2.0", "~> 8.0.0", "~> 8.1.0"]
23
23
  # Exclude combinations that are not supported.
24
24
  exclude:
25
25
  - ruby: "3.1"
26
26
  ar: "~> 8.0.0"
27
+ - ruby: "3.1"
28
+ ar: "~> 8.1.0"
27
29
  - ruby: "3.4"
28
30
  ar: "~> 7.0.0"
29
31
  - ruby: "3.4"
@@ -12,11 +12,13 @@ jobs:
12
12
  matrix:
13
13
  # Run acceptance tests all supported combinations of Ruby and ActiveRecord.
14
14
  ruby: ["3.1", "3.2", "3.3", "3.4"]
15
- ar: ["~> 7.0.0", "~> 7.1.0", "~> 7.2.0", "~> 8.0.0"]
15
+ ar: ["~> 7.0.0", "~> 7.1.0", "~> 7.2.0", "~> 8.0.0", "~> 8.1.0"]
16
16
  # Exclude combinations that are not supported.
17
17
  exclude:
18
18
  - ruby: "3.1"
19
19
  ar: "~> 8.0.0"
20
+ - ruby: "3.1"
21
+ ar: "~> 8.1.0"
20
22
  - ruby: "3.4"
21
23
  ar: "~> 7.0.0"
22
24
  - ruby: "3.4"
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "2.4.0"
2
+ ".": "2.5.0"
3
3
  }
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ### 2.5.0 (2026-02-11)
4
+
5
+ #### Features
6
+
7
+ * add support for the UUID data type ([#387](https://github.com/googleapis/ruby-spanner-activerecord/issues/387))
8
+ * support ActiveRecord 8.1.x ([#385](https://github.com/googleapis/ruby-spanner-activerecord/issues/385))
9
+ #### Documentation
10
+
11
+ * update README to reflect support for Rails 8.1.x ([#388](https://github.com/googleapis/ruby-spanner-activerecord/issues/388))
12
+
3
13
  ### 2.4.0 (2026-02-04)
4
14
 
5
15
  #### Features
data/Gemfile CHANGED
@@ -7,7 +7,7 @@ ar_version = ENV.fetch("AR_VERSION", "~> 7.1.0")
7
7
  gem "activerecord", ar_version
8
8
  gem "ostruct"
9
9
  gem "minitest", "~> 5.27.0"
10
- gem "minitest-rg", "~> 5.3.0"
10
+ gem "minitest-rg", "~> 5.4.0"
11
11
  gem "pry", "~> 0.14.2"
12
12
  gem "pry-byebug", "~> 3.11.0"
13
13
  gem "mutex_m"
data/README.md CHANGED
@@ -15,6 +15,7 @@ This project provides a Spanner adapter for ActiveRecord. It supports the follow
15
15
  - ActiveRecord 7.1.x with Ruby 3.1 and higher.
16
16
  - ActiveRecord 7.2.x with Ruby 3.1 and higher.
17
17
  - ActiveRecord 8.0.x with Ruby 3.2 and higher.
18
+ - ActiveRecord 8.1.x with Ruby 3.2 and higher.
18
19
 
19
20
  Known limitations are listed in the [Limitations](#limitations) section.
20
21
  Please report any problems that you might encounter by [creating a new issue](https://github.com/googleapis/ruby-spanner-activerecord/issues/new).
@@ -57,7 +57,7 @@ module ActiveRecord
57
57
  e = assert_raises(ArgumentError) {
58
58
  connection.rename_index(table_name, "old_idx", too_long_index_name)
59
59
  }
60
- assert_match(/too long; the limit is #{connection.index_name_length} characters/, e.message)
60
+ assert_match(/too long/, e.message)
61
61
 
62
62
  assert connection.index_name_exists?(table_name, "old_idx")
63
63
  end
@@ -79,7 +79,7 @@ module ActiveRecord
79
79
  e = assert_raises(ArgumentError) {
80
80
  connection.add_index(table_name, "foo", name: too_long_index_name)
81
81
  }
82
- assert_match(/too long; the limit is #{connection.index_name_length} characters/, e.message)
82
+ assert_match(/too long/, e.message)
83
83
 
84
84
  assert_not connection.index_name_exists?(table_name, too_long_index_name)
85
85
  connection.add_index(table_name, "foo", name: good_index_name)
@@ -129,6 +129,7 @@ module ActiveRecord
129
129
  col_date DATE,
130
130
  col_timestamp TIMESTAMP,
131
131
  col_json JSON,
132
+ col_uuid UUID,
132
133
  col_array_string ARRAY<STRING(MAX)>,
133
134
  col_array_int64 ARRAY<INT64>,
134
135
  col_array_float64 ARRAY<FLOAT64>,
@@ -138,6 +139,7 @@ module ActiveRecord
138
139
  col_array_date ARRAY<DATE>,
139
140
  col_array_timestamp ARRAY<TIMESTAMP>,
140
141
  col_array_json ARRAY<JSON>,
142
+ col_array_uuid ARRAY<UUID>,
141
143
  ) PRIMARY KEY(id);
142
144
  CREATE TABLE firms (
143
145
  id INT64 NOT NULL GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE),
@@ -287,6 +289,7 @@ INSERT INTO `schema_migrations` (version) VALUES
287
289
  col_date DATE,
288
290
  col_timestamp TIMESTAMP,
289
291
  col_json JSON,
292
+ col_uuid UUID,
290
293
  col_array_string ARRAY<STRING(MAX)>,
291
294
  col_array_int64 ARRAY<INT64>,
292
295
  col_array_float64 ARRAY<FLOAT64>,
@@ -296,6 +299,7 @@ INSERT INTO `schema_migrations` (version) VALUES
296
299
  col_array_date ARRAY<DATE>,
297
300
  col_array_timestamp ARRAY<TIMESTAMP>,
298
301
  col_array_json ARRAY<JSON>,
302
+ col_array_uuid ARRAY<UUID>,
299
303
  ) PRIMARY KEY(id);
300
304
  CREATE TABLE firms (
301
305
  id INT64 NOT NULL GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE),
@@ -463,6 +467,7 @@ CREATE TABLE all_types (
463
467
  col_date DATE,
464
468
  col_timestamp TIMESTAMP,
465
469
  col_json JSON,
470
+ col_uuid UUID,
466
471
  col_array_string ARRAY<STRING(MAX)>,
467
472
  col_array_int64 ARRAY<INT64>,
468
473
  col_array_float64 ARRAY<FLOAT64>,
@@ -472,6 +477,7 @@ CREATE TABLE all_types (
472
477
  col_array_date ARRAY<DATE>,
473
478
  col_array_timestamp ARRAY<TIMESTAMP>,
474
479
  col_array_json ARRAY<JSON>,
480
+ col_array_uuid ARRAY<UUID>,
475
481
  ) PRIMARY KEY(id);
476
482
  CREATE TABLE ar_internal_metadata (
477
483
  key STRING(MAX) NOT NULL,
@@ -624,6 +630,7 @@ CREATE TABLE all_types (
624
630
  col_date DATE,
625
631
  col_timestamp TIMESTAMP,
626
632
  col_json JSON,
633
+ col_uuid UUID,
627
634
  col_array_string ARRAY<STRING(MAX)>,
628
635
  col_array_int64 ARRAY<INT64>,
629
636
  col_array_float64 ARRAY<FLOAT64>,
@@ -633,6 +640,7 @@ CREATE TABLE all_types (
633
640
  col_array_date ARRAY<DATE>,
634
641
  col_array_timestamp ARRAY<TIMESTAMP>,
635
642
  col_array_json ARRAY<JSON>,
643
+ col_array_uuid ARRAY<UUID>,
636
644
  ) PRIMARY KEY(id);
637
645
  CREATE TABLE ar_internal_metadata (
638
646
  key STRING(MAX) NOT NULL,
@@ -30,7 +30,8 @@ module ActiveRecord
30
30
  AllTypes.create col_string: "string", col_int64: 100, col_float64: 3.14, col_numeric: 6.626, col_bool: true,
31
31
  col_bytes: StringIO.new("bytes"), col_date: ::Date.new(2021, 6, 23),
32
32
  col_timestamp: ::Time.new(2021, 6, 23, 17, 8, 21, "+02:00"),
33
- col_json: { kind: "user_renamed", change: %w[jack john]},
33
+ col_json: { kind: "user_renamed", change: %w[jack john] },
34
+ col_uuid: "3840ba25-55df-4cb7-a210-1fe37278954f",
34
35
  col_array_string: ["string1", nil, "string2"],
35
36
  col_array_int64: [100, nil, 200, "300"],
36
37
  col_array_float64: [3.14, nil, 2.0/3.0, "3.14"],
@@ -42,7 +43,8 @@ module ActiveRecord
42
43
  ::Time.new(2021, 6, 24, 17, 8, 21, "+02:00"), "2021-06-25 17:08:21 +02:00"],
43
44
  col_array_json: [{ kind: "user_renamed", change: %w[jack john]}, nil, \
44
45
  { kind: "user_renamed", change: %w[alice meredith]},
45
- "{\"kind\":\"user_renamed\",\"change\":[\"bob\",\"carol\"]}"]
46
+ "{\"kind\":\"user_renamed\",\"change\":[\"bob\",\"carol\"]}"],
47
+ col_array_uuid: ["e986c19c-9bf3-44f8-851d-710ad3d0067b", nil, "a02f50b6-2860-48dc-acd6-49b42abc3094"]
46
48
  end
47
49
 
48
50
  def test_create_record
@@ -67,6 +69,7 @@ module ActiveRecord
67
69
  assert_equal ::Time.new(2021, 6, 23, 17, 8, 21, "+02:00").utc, record.col_timestamp.utc
68
70
  assert_equal ({"kind" => "user_renamed", "change" => %w[jack john]}),
69
71
  record.col_json
72
+ assert_equal "3840ba25-55df-4cb7-a210-1fe37278954f", record.col_uuid
70
73
 
71
74
  assert_equal ["string1", nil, "string2"], record.col_array_string
72
75
  assert_equal [100, nil, 200, 300], record.col_array_int64
@@ -85,6 +88,7 @@ module ActiveRecord
85
88
  {"kind" => "user_renamed", "change" => %w[alice meredith]}, \
86
89
  "{\"kind\":\"user_renamed\",\"change\":[\"bob\",\"carol\"]}"],
87
90
  record.col_array_json
91
+ assert_equal ["e986c19c-9bf3-44f8-851d-710ad3d0067b", nil, "a02f50b6-2860-48dc-acd6-49b42abc3094"], record.col_array_uuid
88
92
  end
89
93
  end
90
94
 
@@ -100,6 +104,7 @@ module ActiveRecord
100
104
  col_date: ::Date.new(2021, 6, 28),
101
105
  col_timestamp: ::Time.new(2021, 6, 28, 11, 22, 21, "+02:00"),
102
106
  col_json: { kind: "user_created", change: %w[jack alice]},
107
+ col_uuid: "b493579f-f4f6-41f6-a520-8373ecf1cde4",
103
108
  col_array_string: ["new string 1", "new string 2"],
104
109
  col_array_int64: [300, 200, 100],
105
110
  col_array_float64: [1.1, 2.2, 3.3],
@@ -108,7 +113,8 @@ module ActiveRecord
108
113
  col_array_bytes: [StringIO.new("new bytes 1"), StringIO.new("new bytes 2")],
109
114
  col_array_date: [::Date.new(2021, 6, 28)],
110
115
  col_array_timestamp: [::Time.utc(2020, 12, 31, 0, 0, 0)],
111
- col_array_json: [{ kind: "user_created", change: %w[jack alice]}]
116
+ col_array_json: [{ kind: "user_created", change: %w[jack alice]}],
117
+ col_array_uuid: ["a664b1eb-4dc7-4795-9ed8-28fab6644cea", nil, "1c794d81-bc6d-4771-9c92-a920d28a7aaa"]
112
118
  end
113
119
 
114
120
  # Verify that the record was updated.
@@ -123,6 +129,7 @@ module ActiveRecord
123
129
  assert_equal ::Time.new(2021, 6, 28, 11, 22, 21, "+02:00").utc, record.col_timestamp.utc
124
130
  assert_equal ({"kind" => "user_created", "change" => %w[jack alice]}),
125
131
  record.col_json
132
+ assert_equal "b493579f-f4f6-41f6-a520-8373ecf1cde4", record.col_uuid
126
133
 
127
134
  assert_equal ["new string 1", "new string 2"], record.col_array_string
128
135
  assert_equal [300, 200, 100], record.col_array_int64
@@ -135,6 +142,8 @@ module ActiveRecord
135
142
  assert_equal [::Time.utc(2020, 12, 31, 0, 0, 0)], record.col_array_timestamp.map(&:utc)
136
143
  assert_equal [{"kind" => "user_created", "change" => %w[jack alice]}],
137
144
  record.col_array_json
145
+ assert_equal ["a664b1eb-4dc7-4795-9ed8-28fab6644cea", nil, "1c794d81-bc6d-4771-9c92-a920d28a7aaa"],
146
+ record.col_array_uuid
138
147
  end
139
148
  end
140
149
 
@@ -151,7 +160,8 @@ module ActiveRecord
151
160
  col_array_bytes: [],
152
161
  col_array_date: [],
153
162
  col_array_timestamp: [],
154
- col_array_json: []
163
+ col_array_json: [],
164
+ col_array_uuid: []
155
165
  end
156
166
 
157
167
  record = AllTypes.find record.id
@@ -164,6 +174,7 @@ module ActiveRecord
164
174
  assert_equal [], record.col_array_date
165
175
  assert_equal [], record.col_array_timestamp
166
176
  assert_equal [], record.col_array_json
177
+ assert_equal [], record.col_array_uuid
167
178
  end
168
179
  end
169
180
  end
@@ -24,6 +24,7 @@ def create_tables_in_test_schema
24
24
  t.column :col_date, :date
25
25
  t.column :col_timestamp, :datetime
26
26
  t.column :col_json, :json
27
+ t.column :col_uuid, :uuid
27
28
 
28
29
  t.column :col_array_string, :string, array: true
29
30
  t.column :col_array_int64, :bigint, array: true
@@ -34,6 +35,7 @@ def create_tables_in_test_schema
34
35
  t.column :col_array_date, :date, array: true
35
36
  t.column :col_array_timestamp, :datetime, array: true
36
37
  t.column :col_array_json, :json, array: true
38
+ t.column :col_array_uuid, :uuid, array: true
37
39
  end
38
40
 
39
41
  create_table :firms do |t|
@@ -29,12 +29,12 @@ Gem::Specification.new do |spec|
29
29
  spec.add_runtime_dependency "activerecord", [">= 7.0", "< 9"]
30
30
 
31
31
  spec.add_development_dependency "autotest-suffix", "~> 1.1"
32
- spec.add_development_dependency "bundler", "~> 2.0"
32
+ spec.add_development_dependency "bundler", [">= 2.0", "< 5.0"]
33
33
  spec.add_development_dependency "google-style", "~> 1.31.0"
34
34
  spec.add_development_dependency "minitest", "~> 5.10"
35
35
  spec.add_development_dependency "minitest-autotest", "~> 1.0"
36
36
  spec.add_development_dependency "minitest-focus", "~> 1.1"
37
- spec.add_development_dependency "minitest-rg", "~> 5.2"
37
+ spec.add_development_dependency "minitest-rg", "~> 5.4"
38
38
  spec.add_development_dependency "rake", "~> 13.0"
39
39
  spec.add_development_dependency "redcarpet", "~> 3.0"
40
40
  spec.add_development_dependency "simplecov", "~> 0.9"
@@ -10,13 +10,26 @@ module ActiveRecord
10
10
  module ConnectionAdapters
11
11
  module Spanner
12
12
  class Column < ConnectionAdapters::Column
13
- # rubocop:disable Style/OptionalBooleanParameter
14
- def initialize(name, default, sql_type_metadata = nil, null = true,
15
- default_function = nil, collation: nil, comment: nil,
16
- primary_key: false, **)
17
- # rubocop:enable Style/OptionalBooleanParameter
18
- super
19
- @primary_key = primary_key
13
+ VERSION_8_1 = Gem::Version.create "8.1.0"
14
+
15
+ if ActiveRecord.gem_version < VERSION_8_1
16
+ # rubocop:disable Style/OptionalBooleanParameter
17
+ def initialize(name, default, sql_type_metadata = nil, null = true,
18
+ default_function = nil, collation: nil, comment: nil,
19
+ primary_key: false, **)
20
+ # rubocop:enable Style/OptionalBooleanParameter
21
+ super
22
+ @primary_key = primary_key
23
+ end
24
+ else
25
+ # rubocop:disable Style/OptionalBooleanParameter
26
+ def initialize(name, cast_type, default, sql_type_metadata = nil, null = true,
27
+ default_function = nil, collation: nil, comment: nil,
28
+ primary_key: false, **)
29
+ # rubocop:enable Style/OptionalBooleanParameter
30
+ super
31
+ @primary_key = primary_key
32
+ end
20
33
  end
21
34
 
22
35
  def auto_incremented_by_db?
@@ -138,7 +138,11 @@ module ActiveRecord
138
138
  sql << " NOT NULL"
139
139
  end
140
140
  if options.key? :default
141
- sql << " DEFAULT (#{quote_default_expression options[:default], column})"
141
+ sql << if respond_to? :quote_default_expression_for_column_definition, :include_private
142
+ " DEFAULT (#{quote_default_expression_for_column_definition options[:default], column})"
143
+ else
144
+ " DEFAULT (#{quote_default_expression options[:default], column})"
145
+ end
142
146
  elsif column.type == :primary_key
143
147
  if @connection.use_auto_increment?
144
148
  sql << " AUTO_INCREMENT"
@@ -22,6 +22,7 @@ module ActiveRecord
22
22
  #
23
23
  module SchemaStatements
24
24
  VERSION_7_2 = Gem::Version.create "7.2.0"
25
+ VERSION_8_1 = Gem::Version.create "8.1.0"
25
26
 
26
27
  def current_database
27
28
  @connection.database_id
@@ -116,18 +117,37 @@ module ActiveRecord
116
117
  information_schema { |i| i.table_columns table_name }
117
118
  end
118
119
 
119
- def new_column_from_field _table_name, field, _definitions = nil
120
- Spanner::Column.new \
121
- field.name,
122
- field.default,
123
- fetch_type_metadata(field.spanner_type,
124
- field.ordinal_position,
125
- field.allow_commit_timestamp,
126
- field.generated,
127
- is_identity: field.is_identity),
128
- field.nullable,
129
- field.default_function,
130
- primary_key: field.primary_key
120
+ if ActiveRecord.gem_version < VERSION_8_1
121
+ def new_column_from_field _table_name, field, _definitions = nil
122
+ Spanner::Column.new \
123
+ field.name,
124
+ field.default,
125
+ fetch_type_metadata(field.spanner_type,
126
+ field.ordinal_position,
127
+ field.allow_commit_timestamp,
128
+ field.generated,
129
+ is_identity: field.is_identity),
130
+ field.nullable,
131
+ field.default_function,
132
+ primary_key: field.primary_key
133
+ end
134
+ else
135
+ def new_column_from_field _table_name, field, _definitions = nil
136
+ cast_type = type_map.lookup field.type
137
+ raise ArgumentError, "unknown type: `#{field.type}`" if cast_type.nil?
138
+ Spanner::Column.new \
139
+ field.name,
140
+ cast_type,
141
+ field.default,
142
+ fetch_type_metadata(field.spanner_type,
143
+ field.ordinal_position,
144
+ field.allow_commit_timestamp,
145
+ field.generated,
146
+ is_identity: field.is_identity),
147
+ field.nullable,
148
+ field.default_function,
149
+ primary_key: field.primary_key
150
+ end
131
151
  end
132
152
 
133
153
  def fetch_type_metadata sql_type, ordinal_position = nil, allow_commit_timestamp = nil, generated = nil,
@@ -0,0 +1,26 @@
1
+ # Copyright 2026 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
+ NATIVE_DATABASE_TYPES = {
10
+ primary_key: "INT64",
11
+ parent_key: "INT64",
12
+ string: { name: "STRING", limit: "MAX" },
13
+ text: { name: "STRING", limit: "MAX" },
14
+ integer: { name: "INT64" },
15
+ bigint: { name: "INT64" },
16
+ float: { name: "FLOAT64" },
17
+ decimal: { name: "NUMERIC" },
18
+ numeric: { name: "NUMERIC" },
19
+ datetime: { name: "TIMESTAMP" },
20
+ time: { name: "TIMESTAMP" },
21
+ date: { name: "DATE" },
22
+ binary: { name: "BYTES", limit: "MAX" },
23
+ boolean: { name: "BOOL" },
24
+ json: { name: "JSON" },
25
+ uuid: { name: "UUID" }
26
+ }.freeze
@@ -13,12 +13,14 @@ require "active_record/connection_adapters/spanner/database_statements"
13
13
  require "active_record/connection_adapters/spanner/schema_statements"
14
14
  require "active_record/connection_adapters/spanner/schema_cache"
15
15
  require "active_record/connection_adapters/spanner/schema_definitions"
16
+ require "active_record/connection_adapters/spanner/type_mapping"
16
17
  require "active_record/connection_adapters/spanner/type_metadata"
17
18
  require "active_record/connection_adapters/spanner/quoting"
18
19
  require "active_record/type/spanner/array"
19
20
  require "active_record/type/spanner/bytes"
20
21
  require "active_record/type/spanner/spanner_active_record_converter"
21
22
  require "active_record/type/spanner/time"
23
+ require "active_record/type/spanner/uuid"
22
24
  require "arel/visitors/spanner"
23
25
  require "activerecord_spanner_adapter/base"
24
26
  require "activerecord_spanner_adapter/connection"
@@ -46,23 +48,6 @@ module ActiveRecord
46
48
  module ConnectionAdapters
47
49
  class SpannerAdapter < AbstractAdapter
48
50
  ADAPTER_NAME = "spanner".freeze
49
- NATIVE_DATABASE_TYPES = {
50
- primary_key: "INT64",
51
- parent_key: "INT64",
52
- string: { name: "STRING", limit: "MAX" },
53
- text: { name: "STRING", limit: "MAX" },
54
- integer: { name: "INT64" },
55
- bigint: { name: "INT64" },
56
- float: { name: "FLOAT64" },
57
- decimal: { name: "NUMERIC" },
58
- numeric: { name: "NUMERIC" },
59
- datetime: { name: "TIMESTAMP" },
60
- time: { name: "TIMESTAMP" },
61
- date: { name: "DATE" },
62
- binary: { name: "BYTES", limit: "MAX" },
63
- boolean: { name: "BOOL" },
64
- json: { name: "JSON" }
65
- }.freeze
66
51
 
67
52
  include Spanner::Quoting
68
53
  include Spanner::DatabaseStatements
@@ -118,6 +103,10 @@ module ActiveRecord
118
103
  NATIVE_DATABASE_TYPES
119
104
  end
120
105
 
106
+ def self.native_database_types
107
+ NATIVE_DATABASE_TYPES
108
+ end
109
+
121
110
  # Database
122
111
 
123
112
  def self.database_exists? config
@@ -262,6 +251,7 @@ module ActiveRecord
262
251
  register_class_with_limit m, %r{^STRING}i, Type::String
263
252
  m.register_type "TIMESTAMP", ActiveRecord::Type::Spanner::Time.new
264
253
  m.register_type "JSON", ActiveRecord::Type::Json.new
254
+ m.register_type "UUID", ActiveRecord::Type::Spanner::Uuid.new
265
255
 
266
256
  register_array_types m
267
257
  end
@@ -277,6 +267,7 @@ module ActiveRecord
277
267
  m.register_type %r{^ARRAY<STRING\((MAX|d+)\)>}i, Type::Spanner::Array.new(Type::String.new)
278
268
  m.register_type %r{^ARRAY<TIMESTAMP>}i, Type::Spanner::Array.new(ActiveRecord::Type::Spanner::Time.new)
279
269
  m.register_type %r{^ARRAY<JSON>}i, Type::Spanner::Array.new(ActiveRecord::Type::Json.new)
270
+ m.register_type %r{^ARRAY<UUID>}i, Type::Spanner::Array.new(ActiveRecord::Type::Spanner::Uuid.new)
280
271
  end
281
272
 
282
273
  def extract_limit sql_type
@@ -37,6 +37,7 @@ module ActiveRecord
37
37
  when ActiveModel::Type::DateTime, ActiveModel::Type::Time, ActiveRecord::Type::Spanner::Time then :TIMESTAMP
38
38
  when ActiveModel::Type::Date then :DATE
39
39
  when ActiveRecord::Type::Json then :JSON
40
+ when ActiveRecord::Type::Spanner::Uuid then :UUID
40
41
  when ActiveRecord::Type::Spanner::Array then [convert_active_model_type_to_spanner(type.element_type)]
41
42
  end
42
43
  end
@@ -0,0 +1,19 @@
1
+ # Copyright 2026 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
+ module ActiveRecord
10
+ module Type
11
+ module Spanner
12
+ class Uuid < ActiveModel::Type::Value
13
+ def type
14
+ :uuid
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -6,6 +6,7 @@
6
6
 
7
7
  require "google/cloud/spanner"
8
8
  require "spanner_client_ext"
9
+ require "active_record/connection_adapters/spanner/type_mapping"
9
10
  require "activerecord_spanner_adapter/information_schema"
10
11
  require_relative "../active_record/connection_adapters/spanner/errors/transaction_mutation_limit_exceeded_error"
11
12
 
@@ -43,6 +44,10 @@ module ActiveRecordSpannerAdapter
43
44
  end
44
45
  end
45
46
 
47
+ def native_database_types
48
+ NATIVE_DATABASE_TYPES
49
+ end
50
+
46
51
  # Clears the cached information about the underlying information schemas.
47
52
  # Call this method if you drop and recreate a database with the same name
48
53
  # to prevent the cached information to be used for the new database.
@@ -5,5 +5,5 @@
5
5
  # https://opensource.org/licenses/MIT.
6
6
 
7
7
  module ActiveRecordSpannerAdapter
8
- VERSION = "2.4.0".freeze
8
+ VERSION = "2.5.0".freeze
9
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-spanner-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Google LLC
@@ -75,16 +75,22 @@ dependencies:
75
75
  name: bundler
76
76
  requirement: !ruby/object:Gem::Requirement
77
77
  requirements:
78
- - - "~>"
78
+ - - ">="
79
79
  - !ruby/object:Gem::Version
80
80
  version: '2.0'
81
+ - - "<"
82
+ - !ruby/object:Gem::Version
83
+ version: '5.0'
81
84
  type: :development
82
85
  prerelease: false
83
86
  version_requirements: !ruby/object:Gem::Requirement
84
87
  requirements:
85
- - - "~>"
88
+ - - ">="
86
89
  - !ruby/object:Gem::Version
87
90
  version: '2.0'
91
+ - - "<"
92
+ - !ruby/object:Gem::Version
93
+ version: '5.0'
88
94
  - !ruby/object:Gem::Dependency
89
95
  name: google-style
90
96
  requirement: !ruby/object:Gem::Requirement
@@ -147,14 +153,14 @@ dependencies:
147
153
  requirements:
148
154
  - - "~>"
149
155
  - !ruby/object:Gem::Version
150
- version: '5.2'
156
+ version: '5.4'
151
157
  type: :development
152
158
  prerelease: false
153
159
  version_requirements: !ruby/object:Gem::Requirement
154
160
  requirements:
155
161
  - - "~>"
156
162
  - !ruby/object:Gem::Version
157
- version: '5.2'
163
+ version: '5.4'
158
164
  - !ruby/object:Gem::Dependency
159
165
  name: rake
160
166
  requirement: !ruby/object:Gem::Requirement
@@ -553,6 +559,7 @@ files:
553
559
  - lib/active_record/connection_adapters/spanner/schema_definitions.rb
554
560
  - lib/active_record/connection_adapters/spanner/schema_dumper.rb
555
561
  - lib/active_record/connection_adapters/spanner/schema_statements.rb
562
+ - lib/active_record/connection_adapters/spanner/type_mapping.rb
556
563
  - lib/active_record/connection_adapters/spanner/type_metadata.rb
557
564
  - lib/active_record/connection_adapters/spanner_adapter.rb
558
565
  - lib/active_record/tasks/spanner_database_tasks.rb
@@ -560,6 +567,7 @@ files:
560
567
  - lib/active_record/type/spanner/bytes.rb
561
568
  - lib/active_record/type/spanner/spanner_active_record_converter.rb
562
569
  - lib/active_record/type/spanner/time.rb
570
+ - lib/active_record/type/spanner/uuid.rb
563
571
  - lib/activerecord-spanner-adapter.rb
564
572
  - lib/activerecord_spanner_adapter/base.rb
565
573
  - lib/activerecord_spanner_adapter/connection.rb