activerecord-spanner-adapter 2.3.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 +4 -4
- data/.github/CODEOWNERS +1 -1
- data/.github/workflows/acceptance-tests-on-emulator.yaml +4 -2
- data/.github/workflows/acceptance-tests-on-production.yaml +4 -4
- data/.github/workflows/ci.yaml +4 -2
- data/.github/workflows/nightly-acceptance-tests-on-emulator.yaml +4 -2
- data/.github/workflows/nightly-acceptance-tests-on-production.yaml +3 -3
- data/.github/workflows/nightly-unit-tests.yaml +4 -2
- data/.github/workflows/rubocop.yaml +3 -3
- data/.github/workflows/samples.yaml +1 -1
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +19 -0
- data/Gemfile +3 -2
- data/README.md +1 -0
- data/acceptance/cases/migration/index_test.rb +2 -2
- data/acceptance/cases/tasks/database_tasks_test.rb +25 -4
- data/acceptance/cases/transactions/read_write_transactions_test.rb +29 -0
- data/acceptance/cases/type/all_types_test.rb +15 -4
- data/acceptance/schema/schema.rb +2 -0
- data/activerecord-spanner-adapter.gemspec +2 -2
- data/examples/snippets/batch-dml/README.md +13 -0
- data/examples/snippets/batch-dml/Rakefile +13 -0
- data/examples/snippets/batch-dml/application.rb +54 -0
- data/examples/snippets/batch-dml/config/database.yml +11 -0
- data/examples/snippets/batch-dml/db/migrate/01_create_tables.rb +23 -0
- data/examples/snippets/batch-dml/db/seeds.rb +8 -0
- data/examples/snippets/batch-dml/models/album.rb +9 -0
- data/examples/snippets/batch-dml/models/singer.rb +9 -0
- data/examples/snippets/partitioned-dml/application.rb +31 -0
- data/lib/active_record/connection_adapters/spanner/column.rb +20 -7
- data/lib/active_record/connection_adapters/spanner/database_statements.rb +79 -24
- data/lib/active_record/connection_adapters/spanner/errors/transaction_mutation_limit_exceeded_error.rb +25 -0
- data/lib/active_record/connection_adapters/spanner/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/spanner/schema_statements.rb +32 -12
- data/lib/active_record/connection_adapters/spanner/type_mapping.rb +26 -0
- data/lib/active_record/connection_adapters/spanner_adapter.rb +10 -18
- data/lib/active_record/type/spanner/spanner_active_record_converter.rb +1 -0
- data/lib/active_record/type/spanner/uuid.rb +19 -0
- data/lib/activerecord_spanner_adapter/base.rb +4 -0
- data/lib/activerecord_spanner_adapter/connection.rb +129 -11
- data/lib/activerecord_spanner_adapter/transaction.rb +25 -4
- data/lib/activerecord_spanner_adapter/version.rb +1 -1
- data/lib/spanner_client_ext.rb +3 -2
- metadata +22 -5
|
@@ -6,9 +6,13 @@
|
|
|
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"
|
|
11
|
+
require_relative "../active_record/connection_adapters/spanner/errors/transaction_mutation_limit_exceeded_error"
|
|
10
12
|
|
|
11
13
|
module ActiveRecordSpannerAdapter
|
|
14
|
+
TransactionMutationLimitExceededError = Google::Cloud::Spanner::Errors::TransactionMutationLimitExceededError
|
|
15
|
+
|
|
12
16
|
class Connection
|
|
13
17
|
attr_reader :instance_id
|
|
14
18
|
attr_reader :database_id
|
|
@@ -40,10 +44,16 @@ module ActiveRecordSpannerAdapter
|
|
|
40
44
|
end
|
|
41
45
|
end
|
|
42
46
|
|
|
47
|
+
def native_database_types
|
|
48
|
+
NATIVE_DATABASE_TYPES
|
|
49
|
+
end
|
|
50
|
+
|
|
43
51
|
# Clears the cached information about the underlying information schemas.
|
|
44
52
|
# Call this method if you drop and recreate a database with the same name
|
|
45
53
|
# to prevent the cached information to be used for the new database.
|
|
46
54
|
def self.reset_information_schemas!
|
|
55
|
+
return unless @database
|
|
56
|
+
|
|
47
57
|
@information_schemas.each_value do |info_schema|
|
|
48
58
|
info_schema.connection.disconnect!
|
|
49
59
|
end
|
|
@@ -159,6 +169,12 @@ module ActiveRecordSpannerAdapter
|
|
|
159
169
|
false
|
|
160
170
|
end
|
|
161
171
|
|
|
172
|
+
# Returns true if this connection is currently executing a DML batch, and otherwise false.
|
|
173
|
+
def dml_batch?
|
|
174
|
+
return true if @dml_batch
|
|
175
|
+
false
|
|
176
|
+
end
|
|
177
|
+
|
|
162
178
|
##
|
|
163
179
|
# Starts a manual DDL batch. The batch must be ended by calling either run_batch or abort_batch.
|
|
164
180
|
#
|
|
@@ -173,18 +189,39 @@ module ActiveRecordSpannerAdapter
|
|
|
173
189
|
# raise
|
|
174
190
|
# end
|
|
175
191
|
def start_batch_ddl
|
|
176
|
-
if @ddl_batch
|
|
177
|
-
raise Google::Cloud::FailedPreconditionError, "
|
|
192
|
+
if @ddl_batch && @dml_batch
|
|
193
|
+
raise Google::Cloud::FailedPreconditionError, "Batch is already active on this connection"
|
|
178
194
|
end
|
|
179
195
|
@ddl_batch = []
|
|
180
196
|
end
|
|
181
197
|
|
|
198
|
+
##
|
|
199
|
+
# Starts a manual DML batch. The batch must be ended by calling either run_batch or abort_batch.
|
|
200
|
+
#
|
|
201
|
+
# @example
|
|
202
|
+
# begin
|
|
203
|
+
# connection.start_batch_dml
|
|
204
|
+
# connection.execute_query "insert into `Users` (Id, Name) VALUES (1, 'Test 1')"
|
|
205
|
+
# connection.execute_query "insert into `Users` (Id, Name) VALUES (2, 'Test 2')"
|
|
206
|
+
# connection.run_batch
|
|
207
|
+
# rescue StandardError
|
|
208
|
+
# connection.abort_batch
|
|
209
|
+
# raise
|
|
210
|
+
# end
|
|
211
|
+
def start_batch_dml
|
|
212
|
+
if @ddl_batch || @dml_batch
|
|
213
|
+
raise Google::Cloud::FailedPreconditionError, "A batch is already active on this connection"
|
|
214
|
+
end
|
|
215
|
+
@dml_batch = []
|
|
216
|
+
end
|
|
217
|
+
|
|
182
218
|
##
|
|
183
219
|
# Aborts the current batch on this connection. This is a no-op if there is no batch on this connection.
|
|
184
220
|
#
|
|
185
221
|
# @see start_batch_ddl
|
|
186
222
|
def abort_batch
|
|
187
223
|
@ddl_batch = nil
|
|
224
|
+
@dml_batch = nil
|
|
188
225
|
end
|
|
189
226
|
|
|
190
227
|
##
|
|
@@ -193,10 +230,21 @@ module ActiveRecordSpannerAdapter
|
|
|
193
230
|
#
|
|
194
231
|
# @see start_batch_ddl
|
|
195
232
|
def run_batch
|
|
196
|
-
unless @ddl_batch
|
|
233
|
+
unless @ddl_batch || @dml_batch
|
|
197
234
|
raise Google::Cloud::FailedPreconditionError, "There is no batch active on this connection"
|
|
198
235
|
end
|
|
199
236
|
# Just return if the batch is empty.
|
|
237
|
+
return true if @ddl_batch&.empty? || @dml_batch&.empty?
|
|
238
|
+
begin
|
|
239
|
+
if @ddl_batch
|
|
240
|
+
run_ddl_batch
|
|
241
|
+
else
|
|
242
|
+
run_dml_batch
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def run_ddl_batch
|
|
200
248
|
return true if @ddl_batch.empty?
|
|
201
249
|
begin
|
|
202
250
|
execute_ddl_statements @ddl_batch, nil, true
|
|
@@ -205,9 +253,43 @@ module ActiveRecordSpannerAdapter
|
|
|
205
253
|
end
|
|
206
254
|
end
|
|
207
255
|
|
|
256
|
+
def run_dml_batch
|
|
257
|
+
return true if @dml_batch.empty?
|
|
258
|
+
begin
|
|
259
|
+
# Execute the DML statements in the batch.
|
|
260
|
+
execute_dml_statements_in_batch @dml_batch
|
|
261
|
+
ensure
|
|
262
|
+
@dml_batch = nil
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
##
|
|
267
|
+
# Executes a set of DML statements as one batch. This method raises an error if no block is given.
|
|
268
|
+
def dml_batch
|
|
269
|
+
raise Google::Cloud::FailedPreconditionError, "No block given for the DML batch" unless block_given?
|
|
270
|
+
begin
|
|
271
|
+
start_batch_dml
|
|
272
|
+
yield
|
|
273
|
+
run_batch
|
|
274
|
+
rescue StandardError
|
|
275
|
+
abort_batch
|
|
276
|
+
raise
|
|
277
|
+
ensure
|
|
278
|
+
@dml_batch = nil
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
|
|
208
282
|
# DQL, DML Statements
|
|
209
283
|
|
|
210
|
-
def execute_query sql, params: nil, types: nil, single_use_selector: nil, request_options: nil
|
|
284
|
+
def execute_query sql, params: nil, types: nil, single_use_selector: nil, request_options: nil, statement_type: nil
|
|
285
|
+
# Clear the transaction from the previous statement.
|
|
286
|
+
unless current_transaction&.active?
|
|
287
|
+
self.current_transaction = nil
|
|
288
|
+
end
|
|
289
|
+
if statement_type == :dml && dml_batch?
|
|
290
|
+
@dml_batch.push({ sql: sql, params: params, types: types })
|
|
291
|
+
return
|
|
292
|
+
end
|
|
211
293
|
if params
|
|
212
294
|
converted_params, types =
|
|
213
295
|
Google::Cloud::Spanner::Convert.to_input_params_and_types(
|
|
@@ -215,11 +297,6 @@ module ActiveRecordSpannerAdapter
|
|
|
215
297
|
)
|
|
216
298
|
end
|
|
217
299
|
|
|
218
|
-
# Clear the transaction from the previous statement.
|
|
219
|
-
unless current_transaction&.active?
|
|
220
|
-
self.current_transaction = nil
|
|
221
|
-
end
|
|
222
|
-
|
|
223
300
|
selector = transaction_selector || single_use_selector
|
|
224
301
|
execute_sql_request sql, converted_params, types, selector, request_options
|
|
225
302
|
end
|
|
@@ -250,6 +327,9 @@ module ActiveRecordSpannerAdapter
|
|
|
250
327
|
end
|
|
251
328
|
raise
|
|
252
329
|
rescue Google::Cloud::Error => e
|
|
330
|
+
if TransactionMutationLimitExceededError.is_mutation_limit_error? e
|
|
331
|
+
raise
|
|
332
|
+
end
|
|
253
333
|
# Check if it was the first statement in a transaction that included a BeginTransaction
|
|
254
334
|
# option in the request. If so, execute an explicit BeginTransaction and then retry the
|
|
255
335
|
# request without the BeginTransaction option.
|
|
@@ -274,9 +354,11 @@ module ActiveRecordSpannerAdapter
|
|
|
274
354
|
|
|
275
355
|
# Transactions
|
|
276
356
|
|
|
277
|
-
def begin_transaction isolation = nil
|
|
357
|
+
def begin_transaction isolation = nil, **options
|
|
278
358
|
raise "Nested transactions are not allowed" if current_transaction&.active?
|
|
279
|
-
|
|
359
|
+
exclude_from_streams = options.fetch :exclude_txn_from_change_streams, false
|
|
360
|
+
self.current_transaction = Transaction.new self, isolation || @isolation_level,
|
|
361
|
+
exclude_txn_from_change_streams: exclude_from_streams
|
|
280
362
|
current_transaction.begin
|
|
281
363
|
current_transaction
|
|
282
364
|
end
|
|
@@ -343,6 +425,42 @@ module ActiveRecordSpannerAdapter
|
|
|
343
425
|
job.done?
|
|
344
426
|
end
|
|
345
427
|
|
|
428
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
429
|
+
def execute_dml_statements_in_batch statements
|
|
430
|
+
selector = transaction_selector
|
|
431
|
+
response = session.batch_update selector, current_transaction&.next_sequence_number do |batch|
|
|
432
|
+
statements.each do |statement|
|
|
433
|
+
batch.batch_update statement[:sql], params: statement[:params], types: statement[:types]
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
batch_update_results = Google::Cloud::Spanner::BatchUpdateResults.new response
|
|
437
|
+
first_res = response.result_sets.first
|
|
438
|
+
current_transaction.grpc_transaction = first_res.metadata.transaction \
|
|
439
|
+
if current_transaction && first_res&.metadata&.transaction
|
|
440
|
+
batch_update_results.row_counts
|
|
441
|
+
rescue Google::Cloud::AbortedError
|
|
442
|
+
# Mark the current transaction as aborted to prevent any unnecessary further requests on the transaction.
|
|
443
|
+
current_transaction&.mark_aborted
|
|
444
|
+
raise
|
|
445
|
+
rescue Google::Cloud::Spanner::BatchUpdateError => e
|
|
446
|
+
# Check if the status is ABORTED, and if it is, just propagate an AbortedError.
|
|
447
|
+
if e.cause&.code == GRPC::Core::StatusCodes::ABORTED
|
|
448
|
+
current_transaction&.mark_aborted
|
|
449
|
+
raise e.cause
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
# Check if the request returned a transaction or not.
|
|
453
|
+
# BatchDML is capable of returning BOTH an error and a transaction.
|
|
454
|
+
if current_transaction && !current_transaction.grpc_transaction? && selector&.begin&.read_write
|
|
455
|
+
selector = create_transaction_after_failed_first_statement e
|
|
456
|
+
retry
|
|
457
|
+
end
|
|
458
|
+
# It was not the first statement, or it returned a transaction, so propagate the error.
|
|
459
|
+
raise
|
|
460
|
+
end
|
|
461
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
462
|
+
|
|
463
|
+
|
|
346
464
|
##
|
|
347
465
|
# Retrieves the delay value from Google::Cloud::AbortedError or
|
|
348
466
|
# GRPC::Aborted
|
|
@@ -7,14 +7,21 @@
|
|
|
7
7
|
module ActiveRecordSpannerAdapter
|
|
8
8
|
class Transaction
|
|
9
9
|
attr_reader :state
|
|
10
|
+
attr_reader :commit_options
|
|
11
|
+
attr_reader :begin_transaction_selector
|
|
12
|
+
attr_accessor :exclude_txn_from_change_streams
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def initialize connection, isolation, commit_options = nil, exclude_txn_from_change_streams: false
|
|
12
17
|
@connection = connection
|
|
13
18
|
@isolation = isolation
|
|
14
19
|
@committable = ![:read_only, :pdml].include?(isolation) && !isolation.is_a?(Hash)
|
|
15
20
|
@state = :INITIALIZED
|
|
16
21
|
@sequence_number = 0
|
|
17
22
|
@mutations = []
|
|
23
|
+
@commit_options = commit_options
|
|
24
|
+
@exclude_txn_from_change_streams = exclude_txn_from_change_streams
|
|
18
25
|
end
|
|
19
26
|
|
|
20
27
|
def active?
|
|
@@ -59,7 +66,8 @@ module ActiveRecordSpannerAdapter
|
|
|
59
66
|
@begin_transaction_selector = Google::Cloud::Spanner::V1::TransactionSelector.new \
|
|
60
67
|
begin: Google::Cloud::Spanner::V1::TransactionOptions.new(
|
|
61
68
|
read_write: Google::Cloud::Spanner::V1::TransactionOptions::ReadWrite.new,
|
|
62
|
-
isolation_level: grpc_isolation
|
|
69
|
+
isolation_level: grpc_isolation,
|
|
70
|
+
exclude_txn_from_change_streams: @exclude_txn_from_change_streams
|
|
63
71
|
)
|
|
64
72
|
end
|
|
65
73
|
@state = :STARTED
|
|
@@ -95,14 +103,23 @@ module ActiveRecordSpannerAdapter
|
|
|
95
103
|
@sequence_number += 1 if @committable
|
|
96
104
|
end
|
|
97
105
|
|
|
106
|
+
# Sets the commit options for this transaction.
|
|
107
|
+
# This is used to set the options for the commit RPC, such as return_commit_stats and max_commit_delay.
|
|
108
|
+
def set_commit_options options # rubocop:disable Naming/AccessorMethodName
|
|
109
|
+
@commit_options = options&.dup
|
|
110
|
+
end
|
|
111
|
+
|
|
98
112
|
def commit
|
|
99
113
|
raise "This transaction is not active" unless active?
|
|
100
114
|
|
|
101
115
|
begin
|
|
102
116
|
# Start a transaction with an explicit BeginTransaction RPC if the transaction only contains mutations.
|
|
103
117
|
force_begin_read_write if @committable && !@mutations.empty? && !@grpc_transaction
|
|
104
|
-
|
|
105
|
-
|
|
118
|
+
if @committable && @grpc_transaction
|
|
119
|
+
@connection.session.commit_transaction @grpc_transaction,
|
|
120
|
+
@mutations,
|
|
121
|
+
commit_options: commit_options
|
|
122
|
+
end
|
|
106
123
|
@state = :COMMITTED
|
|
107
124
|
rescue Google::Cloud::NotFoundError => e
|
|
108
125
|
if @connection.session_not_found? e
|
|
@@ -148,6 +165,10 @@ module ActiveRecordSpannerAdapter
|
|
|
148
165
|
@grpc_transaction = Google::Cloud::Spanner::Transaction.from_grpc grpc, @connection.session
|
|
149
166
|
end
|
|
150
167
|
|
|
168
|
+
def grpc_transaction?
|
|
169
|
+
@grpc_transaction if @grpc_transaction
|
|
170
|
+
end
|
|
171
|
+
|
|
151
172
|
def transaction_selector
|
|
152
173
|
return unless active?
|
|
153
174
|
|
data/lib/spanner_client_ext.rb
CHANGED
|
@@ -23,13 +23,14 @@ module Google
|
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
class Session
|
|
26
|
-
def commit_transaction transaction, mutations = []
|
|
26
|
+
def commit_transaction transaction, mutations = [], commit_options: nil
|
|
27
27
|
ensure_service!
|
|
28
28
|
|
|
29
29
|
resp = service.commit(
|
|
30
30
|
path,
|
|
31
31
|
mutations,
|
|
32
|
-
transaction_id: transaction.transaction_id
|
|
32
|
+
transaction_id: transaction.transaction_id,
|
|
33
|
+
commit_options: commit_options
|
|
33
34
|
)
|
|
34
35
|
@last_updated_at = Time.now
|
|
35
36
|
Convert.timestamp_to_time resp.commit_timestamp
|
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
|
+
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.
|
|
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.
|
|
163
|
+
version: '5.4'
|
|
158
164
|
- !ruby/object:Gem::Dependency
|
|
159
165
|
name: rake
|
|
160
166
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -365,6 +371,14 @@ files:
|
|
|
365
371
|
- examples/snippets/auto-generated-primary-key/db/seeds.rb
|
|
366
372
|
- examples/snippets/auto-generated-primary-key/models/album.rb
|
|
367
373
|
- examples/snippets/auto-generated-primary-key/models/singer.rb
|
|
374
|
+
- examples/snippets/batch-dml/README.md
|
|
375
|
+
- examples/snippets/batch-dml/Rakefile
|
|
376
|
+
- examples/snippets/batch-dml/application.rb
|
|
377
|
+
- examples/snippets/batch-dml/config/database.yml
|
|
378
|
+
- examples/snippets/batch-dml/db/migrate/01_create_tables.rb
|
|
379
|
+
- examples/snippets/batch-dml/db/seeds.rb
|
|
380
|
+
- examples/snippets/batch-dml/models/album.rb
|
|
381
|
+
- examples/snippets/batch-dml/models/singer.rb
|
|
368
382
|
- examples/snippets/bin/create_emulator_instance.rb
|
|
369
383
|
- examples/snippets/bit-reversed-sequence/README.md
|
|
370
384
|
- examples/snippets/bit-reversed-sequence/Rakefile
|
|
@@ -538,12 +552,14 @@ files:
|
|
|
538
552
|
- examples/solidus/README.md
|
|
539
553
|
- lib/active_record/connection_adapters/spanner/column.rb
|
|
540
554
|
- lib/active_record/connection_adapters/spanner/database_statements.rb
|
|
555
|
+
- lib/active_record/connection_adapters/spanner/errors/transaction_mutation_limit_exceeded_error.rb
|
|
541
556
|
- lib/active_record/connection_adapters/spanner/quoting.rb
|
|
542
557
|
- lib/active_record/connection_adapters/spanner/schema_cache.rb
|
|
543
558
|
- lib/active_record/connection_adapters/spanner/schema_creation.rb
|
|
544
559
|
- lib/active_record/connection_adapters/spanner/schema_definitions.rb
|
|
545
560
|
- lib/active_record/connection_adapters/spanner/schema_dumper.rb
|
|
546
561
|
- lib/active_record/connection_adapters/spanner/schema_statements.rb
|
|
562
|
+
- lib/active_record/connection_adapters/spanner/type_mapping.rb
|
|
547
563
|
- lib/active_record/connection_adapters/spanner/type_metadata.rb
|
|
548
564
|
- lib/active_record/connection_adapters/spanner_adapter.rb
|
|
549
565
|
- lib/active_record/tasks/spanner_database_tasks.rb
|
|
@@ -551,6 +567,7 @@ files:
|
|
|
551
567
|
- lib/active_record/type/spanner/bytes.rb
|
|
552
568
|
- lib/active_record/type/spanner/spanner_active_record_converter.rb
|
|
553
569
|
- lib/active_record/type/spanner/time.rb
|
|
570
|
+
- lib/active_record/type/spanner/uuid.rb
|
|
554
571
|
- lib/activerecord-spanner-adapter.rb
|
|
555
572
|
- lib/activerecord_spanner_adapter/base.rb
|
|
556
573
|
- lib/activerecord_spanner_adapter/connection.rb
|