activerecord-spanner-adapter 0.3.0 → 1.0.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 +5 -5
- data/.github/CODEOWNERS +7 -0
- data/.github/sync-repo-settings.yaml +16 -0
- data/.github/workflows/acceptance-tests-on-emulator.yaml +45 -0
- data/.github/workflows/acceptance-tests-on-production.yaml +49 -0
- data/.github/workflows/ci.yaml +33 -0
- data/.github/workflows/nightly-acceptance-tests-on-emulator.yaml +52 -0
- data/.github/workflows/nightly-acceptance-tests-on-production.yaml +35 -0
- data/.github/workflows/nightly-unit-tests.yaml +40 -0
- data/.github/workflows/release-please-label.yml +25 -0
- data/.github/workflows/release-please.yml +39 -0
- data/.github/workflows/rubocop.yaml +31 -0
- data/.gitignore +67 -5
- data/.kokoro/populate-secrets.sh +77 -0
- data/.kokoro/release.cfg +33 -0
- data/.kokoro/release.sh +15 -0
- data/.kokoro/trampoline_v2.sh +489 -0
- data/.rubocop.yml +46 -0
- data/.toys/release.rb +18 -0
- data/.trampolinerc +48 -0
- data/.yardopts +11 -0
- data/CHANGELOG.md +55 -0
- data/CODE_OF_CONDUCT.md +40 -0
- data/CONTRIBUTING.md +79 -0
- data/Gemfile +9 -4
- data/LICENSE +6 -6
- data/README.md +66 -30
- data/Rakefile +79 -3
- data/SECURITY.md +7 -0
- data/acceptance/cases/associations/has_many_associations_test.rb +119 -0
- data/acceptance/cases/associations/has_many_through_associations_test.rb +63 -0
- data/acceptance/cases/associations/has_one_associations_test.rb +79 -0
- data/acceptance/cases/associations/has_one_through_associations_test.rb +98 -0
- data/acceptance/cases/interleaved_associations/has_many_associations_using_interleaved_test.rb +211 -0
- data/acceptance/cases/migration/change_schema_test.rb +433 -0
- data/acceptance/cases/migration/change_table_test.rb +115 -0
- data/acceptance/cases/migration/column_attributes_test.rb +122 -0
- data/acceptance/cases/migration/column_positioning_test.rb +48 -0
- data/acceptance/cases/migration/columns_test.rb +201 -0
- data/acceptance/cases/migration/command_recorder_test.rb +406 -0
- data/acceptance/cases/migration/create_join_table_test.rb +216 -0
- data/acceptance/cases/migration/ddl_batching_test.rb +80 -0
- data/acceptance/cases/migration/foreign_key_test.rb +297 -0
- data/acceptance/cases/migration/index_test.rb +211 -0
- data/acceptance/cases/migration/references_foreign_key_test.rb +259 -0
- data/acceptance/cases/migration/references_index_test.rb +135 -0
- data/acceptance/cases/migration/references_statements_test.rb +166 -0
- data/acceptance/cases/migration/rename_column_test.rb +96 -0
- data/acceptance/cases/models/calculation_query_test.rb +128 -0
- data/acceptance/cases/models/generated_column_test.rb +126 -0
- data/acceptance/cases/models/mutation_test.rb +122 -0
- data/acceptance/cases/models/query_test.rb +171 -0
- data/acceptance/cases/sessions/session_not_found_test.rb +121 -0
- data/acceptance/cases/transactions/optimistic_locking_test.rb +141 -0
- data/acceptance/cases/transactions/read_only_transactions_test.rb +130 -0
- data/acceptance/cases/transactions/read_write_transactions_test.rb +248 -0
- data/acceptance/cases/type/all_types_test.rb +172 -0
- data/acceptance/cases/type/binary_test.rb +59 -0
- data/acceptance/cases/type/boolean_test.rb +31 -0
- data/acceptance/cases/type/date_test.rb +32 -0
- data/acceptance/cases/type/date_time_test.rb +30 -0
- data/acceptance/cases/type/float_test.rb +27 -0
- data/acceptance/cases/type/integer_test.rb +44 -0
- data/acceptance/cases/type/json_test.rb +34 -0
- data/acceptance/cases/type/numeric_test.rb +27 -0
- data/acceptance/cases/type/string_test.rb +79 -0
- data/acceptance/cases/type/text_test.rb +30 -0
- data/acceptance/cases/type/time_test.rb +87 -0
- data/acceptance/models/account.rb +13 -0
- data/acceptance/models/address.rb +9 -0
- data/acceptance/models/album.rb +12 -0
- data/acceptance/models/all_types.rb +8 -0
- data/acceptance/models/author.rb +11 -0
- data/acceptance/models/club.rb +12 -0
- data/acceptance/models/comment.rb +9 -0
- data/acceptance/models/customer.rb +9 -0
- data/acceptance/models/department.rb +9 -0
- data/acceptance/models/firm.rb +10 -0
- data/acceptance/models/member.rb +13 -0
- data/acceptance/models/member_type.rb +9 -0
- data/acceptance/models/membership.rb +10 -0
- data/acceptance/models/organization.rb +9 -0
- data/acceptance/models/post.rb +10 -0
- data/acceptance/models/singer.rb +10 -0
- data/acceptance/models/track.rb +20 -0
- data/acceptance/models/transaction.rb +9 -0
- data/acceptance/schema/schema.rb +147 -0
- data/acceptance/test_helper.rb +261 -0
- data/activerecord-spanner-adapter.gemspec +32 -17
- data/assets/solidus-db.png +0 -0
- data/benchmarks/README.md +17 -0
- data/benchmarks/Rakefile +14 -0
- data/benchmarks/application.rb +308 -0
- data/benchmarks/config/database.yml +8 -0
- data/benchmarks/config/environment.rb +12 -0
- data/benchmarks/db/migrate/01_create_tables.rb +25 -0
- data/benchmarks/db/schema.rb +29 -0
- data/benchmarks/models/album.rb +9 -0
- data/benchmarks/models/singer.rb +9 -0
- data/bin/console +6 -7
- data/examples/rails/README.md +262 -0
- data/examples/snippets/README.md +29 -0
- data/examples/snippets/Rakefile +57 -0
- data/examples/snippets/array-data-type/README.md +45 -0
- data/examples/snippets/array-data-type/Rakefile +13 -0
- data/examples/snippets/array-data-type/application.rb +45 -0
- data/examples/snippets/array-data-type/config/database.yml +8 -0
- data/examples/snippets/array-data-type/db/migrate/01_create_tables.rb +24 -0
- data/examples/snippets/array-data-type/db/schema.rb +26 -0
- data/examples/snippets/array-data-type/db/seeds.rb +5 -0
- data/examples/snippets/array-data-type/models/entity_with_array_types.rb +18 -0
- data/examples/snippets/bin/create_emulator_instance.rb +18 -0
- data/examples/snippets/bulk-insert/README.md +21 -0
- data/examples/snippets/bulk-insert/Rakefile +13 -0
- data/examples/snippets/bulk-insert/application.rb +64 -0
- data/examples/snippets/bulk-insert/config/database.yml +8 -0
- data/examples/snippets/bulk-insert/db/migrate/01_create_tables.rb +21 -0
- data/examples/snippets/bulk-insert/db/schema.rb +26 -0
- data/examples/snippets/bulk-insert/db/seeds.rb +5 -0
- data/examples/snippets/bulk-insert/models/album.rb +9 -0
- data/examples/snippets/bulk-insert/models/singer.rb +9 -0
- data/examples/snippets/commit-timestamp/README.md +18 -0
- data/examples/snippets/commit-timestamp/Rakefile +13 -0
- data/examples/snippets/commit-timestamp/application.rb +53 -0
- data/examples/snippets/commit-timestamp/config/database.yml +8 -0
- data/examples/snippets/commit-timestamp/db/migrate/01_create_tables.rb +26 -0
- data/examples/snippets/commit-timestamp/db/schema.rb +29 -0
- data/examples/snippets/commit-timestamp/db/seeds.rb +5 -0
- data/examples/snippets/commit-timestamp/models/album.rb +9 -0
- data/examples/snippets/commit-timestamp/models/singer.rb +9 -0
- data/examples/snippets/config/environment.rb +21 -0
- data/examples/snippets/create-records/README.md +12 -0
- data/examples/snippets/create-records/Rakefile +13 -0
- data/examples/snippets/create-records/application.rb +42 -0
- data/examples/snippets/create-records/config/database.yml +8 -0
- data/examples/snippets/create-records/db/migrate/01_create_tables.rb +21 -0
- data/examples/snippets/create-records/db/schema.rb +26 -0
- data/examples/snippets/create-records/db/seeds.rb +5 -0
- data/examples/snippets/create-records/models/album.rb +9 -0
- data/examples/snippets/create-records/models/singer.rb +9 -0
- data/examples/snippets/date-data-type/README.md +19 -0
- data/examples/snippets/date-data-type/Rakefile +13 -0
- data/examples/snippets/date-data-type/application.rb +35 -0
- data/examples/snippets/date-data-type/config/database.yml +8 -0
- data/examples/snippets/date-data-type/db/migrate/01_create_tables.rb +20 -0
- data/examples/snippets/date-data-type/db/schema.rb +21 -0
- data/examples/snippets/date-data-type/db/seeds.rb +16 -0
- data/examples/snippets/date-data-type/models/singer.rb +8 -0
- data/examples/snippets/generated-column/README.md +41 -0
- data/examples/snippets/generated-column/Rakefile +13 -0
- data/examples/snippets/generated-column/application.rb +37 -0
- data/examples/snippets/generated-column/config/database.yml +8 -0
- data/examples/snippets/generated-column/db/migrate/01_create_tables.rb +23 -0
- data/examples/snippets/generated-column/db/schema.rb +21 -0
- data/examples/snippets/generated-column/db/seeds.rb +18 -0
- data/examples/snippets/generated-column/models/singer.rb +8 -0
- data/examples/snippets/hints/README.md +19 -0
- data/examples/snippets/hints/Rakefile +13 -0
- data/examples/snippets/hints/application.rb +47 -0
- data/examples/snippets/hints/config/database.yml +8 -0
- data/examples/snippets/hints/db/migrate/01_create_tables.rb +23 -0
- data/examples/snippets/hints/db/schema.rb +28 -0
- data/examples/snippets/hints/db/seeds.rb +29 -0
- data/examples/snippets/hints/models/album.rb +9 -0
- data/examples/snippets/hints/models/singer.rb +9 -0
- data/examples/snippets/migrations/README.md +43 -0
- data/examples/snippets/migrations/Rakefile +13 -0
- data/examples/snippets/migrations/application.rb +26 -0
- data/examples/snippets/migrations/config/database.yml +8 -0
- data/examples/snippets/migrations/db/migrate/01_create_tables.rb +28 -0
- data/examples/snippets/migrations/db/schema.rb +33 -0
- data/examples/snippets/migrations/db/seeds.rb +5 -0
- data/examples/snippets/migrations/models/album.rb +10 -0
- data/examples/snippets/migrations/models/singer.rb +10 -0
- data/examples/snippets/migrations/models/track.rb +9 -0
- data/examples/snippets/mutations/README.md +34 -0
- data/examples/snippets/mutations/Rakefile +13 -0
- data/examples/snippets/mutations/application.rb +47 -0
- data/examples/snippets/mutations/config/database.yml +8 -0
- data/examples/snippets/mutations/db/migrate/01_create_tables.rb +22 -0
- data/examples/snippets/mutations/db/schema.rb +27 -0
- data/examples/snippets/mutations/db/seeds.rb +25 -0
- data/examples/snippets/mutations/models/album.rb +9 -0
- data/examples/snippets/mutations/models/singer.rb +9 -0
- data/examples/snippets/optimistic-locking/README.md +12 -0
- data/examples/snippets/optimistic-locking/Rakefile +13 -0
- data/examples/snippets/optimistic-locking/application.rb +48 -0
- data/examples/snippets/optimistic-locking/config/database.yml +8 -0
- data/examples/snippets/optimistic-locking/db/migrate/01_create_tables.rb +26 -0
- data/examples/snippets/optimistic-locking/db/schema.rb +29 -0
- data/examples/snippets/optimistic-locking/db/seeds.rb +25 -0
- data/examples/snippets/optimistic-locking/models/album.rb +9 -0
- data/examples/snippets/optimistic-locking/models/singer.rb +9 -0
- data/examples/snippets/partitioned-dml/README.md +16 -0
- data/examples/snippets/partitioned-dml/Rakefile +13 -0
- data/examples/snippets/partitioned-dml/application.rb +48 -0
- data/examples/snippets/partitioned-dml/config/database.yml +8 -0
- data/examples/snippets/partitioned-dml/db/migrate/01_create_tables.rb +21 -0
- data/examples/snippets/partitioned-dml/db/schema.rb +26 -0
- data/examples/snippets/partitioned-dml/db/seeds.rb +29 -0
- data/examples/snippets/partitioned-dml/models/album.rb +9 -0
- data/examples/snippets/partitioned-dml/models/singer.rb +9 -0
- data/examples/snippets/quickstart/README.md +26 -0
- data/examples/snippets/quickstart/Rakefile +13 -0
- data/examples/snippets/quickstart/application.rb +51 -0
- data/examples/snippets/quickstart/config/database.yml +8 -0
- data/examples/snippets/quickstart/db/migrate/01_create_tables.rb +21 -0
- data/examples/snippets/quickstart/db/schema.rb +26 -0
- data/examples/snippets/quickstart/db/seeds.rb +24 -0
- data/examples/snippets/quickstart/models/album.rb +9 -0
- data/examples/snippets/quickstart/models/singer.rb +9 -0
- data/examples/snippets/read-only-transactions/README.md +13 -0
- data/examples/snippets/read-only-transactions/Rakefile +13 -0
- data/examples/snippets/read-only-transactions/application.rb +77 -0
- data/examples/snippets/read-only-transactions/config/database.yml +8 -0
- data/examples/snippets/read-only-transactions/db/migrate/01_create_tables.rb +21 -0
- data/examples/snippets/read-only-transactions/db/schema.rb +26 -0
- data/examples/snippets/read-only-transactions/db/seeds.rb +24 -0
- data/examples/snippets/read-only-transactions/models/album.rb +9 -0
- data/examples/snippets/read-only-transactions/models/singer.rb +9 -0
- data/examples/snippets/read-write-transactions/README.md +12 -0
- data/examples/snippets/read-write-transactions/Rakefile +13 -0
- data/examples/snippets/read-write-transactions/application.rb +39 -0
- data/examples/snippets/read-write-transactions/config/database.yml +8 -0
- data/examples/snippets/read-write-transactions/db/migrate/01_create_tables.rb +22 -0
- data/examples/snippets/read-write-transactions/db/schema.rb +27 -0
- data/examples/snippets/read-write-transactions/db/seeds.rb +25 -0
- data/examples/snippets/read-write-transactions/models/album.rb +9 -0
- data/examples/snippets/read-write-transactions/models/singer.rb +9 -0
- data/examples/snippets/stale-reads/README.md +27 -0
- data/examples/snippets/stale-reads/Rakefile +13 -0
- data/examples/snippets/stale-reads/application.rb +63 -0
- data/examples/snippets/stale-reads/config/database.yml +8 -0
- data/examples/snippets/stale-reads/db/migrate/01_create_tables.rb +21 -0
- data/examples/snippets/stale-reads/db/schema.rb +26 -0
- data/examples/snippets/stale-reads/db/seeds.rb +24 -0
- data/examples/snippets/stale-reads/models/album.rb +9 -0
- data/examples/snippets/stale-reads/models/singer.rb +9 -0
- data/examples/snippets/timestamp-data-type/README.md +17 -0
- data/examples/snippets/timestamp-data-type/Rakefile +13 -0
- data/examples/snippets/timestamp-data-type/application.rb +42 -0
- data/examples/snippets/timestamp-data-type/config/database.yml +8 -0
- data/examples/snippets/timestamp-data-type/db/migrate/01_create_tables.rb +21 -0
- data/examples/snippets/timestamp-data-type/db/schema.rb +21 -0
- data/examples/snippets/timestamp-data-type/db/seeds.rb +6 -0
- data/examples/snippets/timestamp-data-type/models/meeting.rb +19 -0
- data/examples/solidus/README.md +172 -0
- data/lib/active_record/connection_adapters/spanner/database_statements.rb +244 -266
- data/lib/active_record/connection_adapters/spanner/quoting.rb +42 -50
- data/lib/active_record/connection_adapters/spanner/schema_cache.rb +43 -0
- data/lib/active_record/connection_adapters/spanner/schema_creation.rb +125 -9
- data/lib/active_record/connection_adapters/spanner/schema_definitions.rb +122 -0
- data/lib/active_record/connection_adapters/spanner/schema_dumper.rb +19 -0
- data/lib/active_record/connection_adapters/spanner/schema_statements.rb +553 -139
- data/lib/active_record/connection_adapters/spanner/type_metadata.rb +37 -0
- data/lib/active_record/connection_adapters/spanner_adapter.rb +185 -78
- data/lib/active_record/tasks/spanner_database_tasks.rb +74 -0
- data/lib/active_record/type/spanner/array.rb +32 -0
- data/lib/active_record/type/spanner/bytes.rb +26 -0
- data/lib/active_record/type/spanner/spanner_active_record_converter.rb +33 -0
- data/lib/active_record/type/spanner/time.rb +37 -0
- data/lib/activerecord-spanner-adapter.rb +23 -0
- data/lib/activerecord_spanner_adapter/base.rb +238 -0
- data/lib/activerecord_spanner_adapter/connection.rb +350 -0
- data/lib/activerecord_spanner_adapter/errors.rb +13 -0
- data/lib/activerecord_spanner_adapter/foreign_key.rb +29 -0
- data/lib/activerecord_spanner_adapter/index/column.rb +38 -0
- data/lib/activerecord_spanner_adapter/index.rb +80 -0
- data/lib/activerecord_spanner_adapter/information_schema.rb +262 -0
- data/lib/activerecord_spanner_adapter/primary_key.rb +31 -0
- data/lib/activerecord_spanner_adapter/table/column.rb +59 -0
- data/lib/activerecord_spanner_adapter/table.rb +61 -0
- data/lib/activerecord_spanner_adapter/transaction.rb +154 -0
- data/lib/activerecord_spanner_adapter/version.rb +9 -0
- data/lib/arel/visitors/spanner.rb +111 -0
- data/lib/spanner_client_ext.rb +107 -0
- data/renovate.json +5 -0
- metadata +405 -34
- data/.travis.yml +0 -5
- data/lib/active_record/connection_adapters/spanner/client.rb +0 -190
- data/lib/active_record/connection_adapters/spanner.rb +0 -10
- data/lib/activerecord-spanner-adapter/version.rb +0 -3
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Sample - Bulk Insert
|
|
2
|
+
|
|
3
|
+
It is important to use the correct strategy when bulk creating new records in Spanner using ActiveRecord.
|
|
4
|
+
ActiveRecord will by default create a separate insert statement for each entity that you create. The Spanner
|
|
5
|
+
ActiveRecord adapter is able to translate this into a set of insert Mutations instead of a list of insert DML
|
|
6
|
+
statements, which will execute a lot faster.
|
|
7
|
+
|
|
8
|
+
There are two ways to achieve this:
|
|
9
|
+
1. Create a batch of entities without an explicit transaction.
|
|
10
|
+
2. Use a read/write transaction with isolation level `:buffered_mutations`
|
|
11
|
+
|
|
12
|
+
See also the `Mutations` sample in this repository.
|
|
13
|
+
|
|
14
|
+
The sample will automatically start a Spanner Emulator in a docker container and execute the sample
|
|
15
|
+
against that emulator. The emulator will automatically be stopped when the application finishes.
|
|
16
|
+
|
|
17
|
+
Run the application with the command
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
bundle exec rake run
|
|
21
|
+
```
|
|
@@ -0,0 +1,13 @@
|
|
|
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
|
+
require_relative "../config/environment"
|
|
8
|
+
require "sinatra/activerecord/rake"
|
|
9
|
+
|
|
10
|
+
desc "Sample showing how to best bulk insert new records in Spanner using ActiveRecord."
|
|
11
|
+
task :run do
|
|
12
|
+
Dir.chdir("..") { sh "bundle exec rake run[bulk-insert]" }
|
|
13
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
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
|
+
require "io/console"
|
|
8
|
+
require_relative "../config/environment"
|
|
9
|
+
require_relative "models/singer"
|
|
10
|
+
require_relative "models/album"
|
|
11
|
+
|
|
12
|
+
class Application
|
|
13
|
+
def self.run # rubocop:disable Metrics/AbcSize
|
|
14
|
+
# Creating multiple records without an explicit transaction will automatically save all the records using
|
|
15
|
+
# one Spanner transaction and return the ids of the created records. The implicit transaction that is created
|
|
16
|
+
# by the Spanner ActiveRecord adapter will automatically use Mutations for the bulk insert. This is a lot more
|
|
17
|
+
# efficient than a list of DML statements.
|
|
18
|
+
singers = Singer.create [
|
|
19
|
+
{ first_name: "Alice", last_name: "Wendelson" },
|
|
20
|
+
{ first_name: "Nick", last_name: "Rainbow" },
|
|
21
|
+
{ first_name: "Elena", last_name: "Quick" }
|
|
22
|
+
]
|
|
23
|
+
puts ""
|
|
24
|
+
puts "Created a batch of #{singers.length} singers using an implicit transaction:"
|
|
25
|
+
singers.each do |s|
|
|
26
|
+
puts " Created singer #{s.first_name} #{s.last_name} with id #{s.id}"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# If you need to create multiple records of different types, you can use an explicit transaction with isolation
|
|
30
|
+
# level `:buffered_mutations`. This Spanner-specific isolation level will instruct the read/write transaction to
|
|
31
|
+
# use Mutations instead of DML.
|
|
32
|
+
singers = nil
|
|
33
|
+
albums = nil
|
|
34
|
+
ActiveRecord::Base.transaction isolation: :buffered_mutations do
|
|
35
|
+
singers = Singer.create [
|
|
36
|
+
{ first_name: "Boris", last_name: "Carelia" },
|
|
37
|
+
{ first_name: "Yvonne", last_name: "McKenzie" },
|
|
38
|
+
{ first_name: "Wendy", last_name: "Bravo" }
|
|
39
|
+
]
|
|
40
|
+
albums = Album.create [
|
|
41
|
+
{ title: "Hot Potatoes", singer: singers[0] },
|
|
42
|
+
{ title: "Lazy Street", singer: singers[0] },
|
|
43
|
+
{ title: "Daily Glass", singer: singers[1] },
|
|
44
|
+
{ title: "Happy Windows", singer: singers[2] },
|
|
45
|
+
{ title: "Generous Street", singer: singers[2] }
|
|
46
|
+
]
|
|
47
|
+
end
|
|
48
|
+
puts ""
|
|
49
|
+
puts "Created a batch of #{singers.length} singers and #{albums.length} "\
|
|
50
|
+
"albums using a transaction with buffered mutations:"
|
|
51
|
+
singers.each do |s|
|
|
52
|
+
puts " Created singer #{s.first_name} #{s.last_name} with id #{s.id}"
|
|
53
|
+
s.albums.each do |a|
|
|
54
|
+
puts " with album #{a.title} with id #{a.id}"
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
puts ""
|
|
59
|
+
puts "Press any key to end the application"
|
|
60
|
+
STDIN.getch
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
Application.run
|
|
@@ -0,0 +1,21 @@
|
|
|
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
|
+
class CreateTables < ActiveRecord::Migration[6.0]
|
|
8
|
+
def change
|
|
9
|
+
connection.ddl_batch do
|
|
10
|
+
create_table :singers do |t|
|
|
11
|
+
t.string :first_name
|
|
12
|
+
t.string :last_name
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
create_table :albums do |t|
|
|
16
|
+
t.string :title
|
|
17
|
+
t.references :singer, index: false, foreign_key: true
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# This file is auto-generated from the current state of the database. Instead
|
|
2
|
+
# of editing this file, please use the migrations feature of Active Record to
|
|
3
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
|
4
|
+
#
|
|
5
|
+
# This file is the source Rails uses to define your schema when running `rails
|
|
6
|
+
# db:schema:load`. When creating a new database, `rails db:schema:load` tends to
|
|
7
|
+
# be faster and is potentially less error prone than running all of your
|
|
8
|
+
# migrations from scratch. Old migrations may fail to apply correctly if those
|
|
9
|
+
# migrations use external dependencies or application code.
|
|
10
|
+
#
|
|
11
|
+
# It's strongly recommended that you check this file into your version control system.
|
|
12
|
+
|
|
13
|
+
ActiveRecord::Schema.define(version: 1) do
|
|
14
|
+
|
|
15
|
+
create_table "albums", force: :cascade do |t|
|
|
16
|
+
t.string "title"
|
|
17
|
+
t.integer "singer_id", limit: 8
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
create_table "singers", force: :cascade do |t|
|
|
21
|
+
t.string "first_name"
|
|
22
|
+
t.string "last_name"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
add_foreign_key "albums", "singers"
|
|
26
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Sample - Commit Timestamps
|
|
2
|
+
|
|
3
|
+
This example shows how to set an attribute to the [commit timestamp of a transaction](https://cloud.google.com/spanner/docs/commit-timestamp)
|
|
4
|
+
using the Spanner ActiveRecord adapter. Setting the commit timestamp is different from the built-in
|
|
5
|
+
`created_at`/`updated_at` [feature](https://guides.rubyonrails.org/active_record_basics.html#schema-conventions) of
|
|
6
|
+
ActiveRecord. A `created_at`/`updated_at` column that is managed by ActiveRecord will be set to the date/time of the
|
|
7
|
+
__client__ when the record is created/updated. The commit timestamp of a transaction is generated by Cloud Spanner and
|
|
8
|
+
is set by the server when the transaction is committed. All records that are created or updated in the same transaction
|
|
9
|
+
will be assigned the exact same commit timestamp.
|
|
10
|
+
|
|
11
|
+
The sample will automatically start a Spanner Emulator in a docker container and execute the sample
|
|
12
|
+
against that emulator. The emulator will automatically be stopped when the application finishes.
|
|
13
|
+
|
|
14
|
+
Run the application with the command
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
bundle exec rake run
|
|
18
|
+
```
|
|
@@ -0,0 +1,13 @@
|
|
|
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
|
+
require_relative "../config/environment"
|
|
8
|
+
require "sinatra/activerecord/rake"
|
|
9
|
+
|
|
10
|
+
desc "Sample showing how to fill a commit timestamp column in Spanner with ActiveRecord."
|
|
11
|
+
task :run do
|
|
12
|
+
Dir.chdir("..") { sh "bundle exec rake run[commit-timestamp]" }
|
|
13
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
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
|
+
require "io/console"
|
|
8
|
+
require_relative "../config/environment"
|
|
9
|
+
require_relative "models/singer"
|
|
10
|
+
require_relative "models/album"
|
|
11
|
+
|
|
12
|
+
class Application
|
|
13
|
+
def self.run # rubocop:disable Metrics/AbcSize
|
|
14
|
+
format = "%Y-%m-%dT%k:%M:%S.%N"
|
|
15
|
+
singer = nil
|
|
16
|
+
album = nil
|
|
17
|
+
ActiveRecord::Base.transaction do
|
|
18
|
+
# Create a singer and album with a commit timestamp that is set by Cloud Spanner.
|
|
19
|
+
# Use the `:commit_timestamp` symbol to instruct the Spanner ActiveRecord adapter to update the attribute to the
|
|
20
|
+
# commit timestamp of the transaction. Note that the value is not readable before the transaction has been
|
|
21
|
+
# committed. The commit timestamp of the following two records will be equal, as they are created in the same
|
|
22
|
+
# transaction.
|
|
23
|
+
singer = Singer.create first_name: "Pete", last_name: "Allison", last_updated: :commit_timestamp
|
|
24
|
+
album = singer.albums.create title: "Dear Repayment", last_updated: :commit_timestamp
|
|
25
|
+
end
|
|
26
|
+
# Reload the records to get the actual commit timestamp values.
|
|
27
|
+
singer.reload
|
|
28
|
+
album.reload
|
|
29
|
+
|
|
30
|
+
puts ""
|
|
31
|
+
puts "Singer and album created:"
|
|
32
|
+
puts "#{singer.first_name} #{singer.last_name} (Last updated: #{singer.last_updated.strftime format})"
|
|
33
|
+
puts " #{album.title} (Last updated: #{album.last_updated.strftime format})"
|
|
34
|
+
|
|
35
|
+
# The commit timestamp can also be set in an implicit transaction. Note that the following two statements will
|
|
36
|
+
# create two separate (implicit) transactions, and the commit timestamps of the two records will now be slightly
|
|
37
|
+
# different.
|
|
38
|
+
singer.update last_updated: :commit_timestamp
|
|
39
|
+
album.update last_updated: :commit_timestamp
|
|
40
|
+
singer.reload
|
|
41
|
+
album.reload
|
|
42
|
+
puts ""
|
|
43
|
+
puts "Singer and album updated:"
|
|
44
|
+
puts "#{singer.first_name} #{singer.last_name} (Last updated: #{singer.last_updated.strftime format})"
|
|
45
|
+
puts " #{album.title} (Last updated: #{album.last_updated.strftime format})"
|
|
46
|
+
|
|
47
|
+
puts ""
|
|
48
|
+
puts "Press any key to end the application"
|
|
49
|
+
STDIN.getch
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
Application.run
|
|
@@ -0,0 +1,26 @@
|
|
|
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
|
+
class CreateTables < ActiveRecord::Migration[6.0]
|
|
8
|
+
def change
|
|
9
|
+
connection.ddl_batch do
|
|
10
|
+
create_table :singers do |t|
|
|
11
|
+
t.string :first_name
|
|
12
|
+
t.string :last_name
|
|
13
|
+
# Create a `last_updated` column that supports server side commit timestamps.
|
|
14
|
+
t.datetime :last_updated, allow_commit_timestamp: true
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
create_table :albums do |t|
|
|
18
|
+
t.string :title
|
|
19
|
+
t.numeric :marketing_budget
|
|
20
|
+
t.references :singer, index: false, foreign_key: true
|
|
21
|
+
# Create a `last_updated` column that supports server side commit timestamps.
|
|
22
|
+
t.datetime :last_updated, allow_commit_timestamp: true
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# This file is auto-generated from the current state of the database. Instead
|
|
2
|
+
# of editing this file, please use the migrations feature of Active Record to
|
|
3
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
|
4
|
+
#
|
|
5
|
+
# This file is the source Rails uses to define your schema when running `rails
|
|
6
|
+
# db:schema:load`. When creating a new database, `rails db:schema:load` tends to
|
|
7
|
+
# be faster and is potentially less error prone than running all of your
|
|
8
|
+
# migrations from scratch. Old migrations may fail to apply correctly if those
|
|
9
|
+
# migrations use external dependencies or application code.
|
|
10
|
+
#
|
|
11
|
+
# It's strongly recommended that you check this file into your version control system.
|
|
12
|
+
|
|
13
|
+
ActiveRecord::Schema.define(version: 1) do
|
|
14
|
+
|
|
15
|
+
create_table "albums", force: :cascade do |t|
|
|
16
|
+
t.string "title"
|
|
17
|
+
t.decimal "marketing_budget"
|
|
18
|
+
t.integer "singer_id", limit: 8
|
|
19
|
+
t.time "last_updated"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
create_table "singers", force: :cascade do |t|
|
|
23
|
+
t.string "first_name"
|
|
24
|
+
t.string "last_name"
|
|
25
|
+
t.time "last_updated"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
add_foreign_key "albums", "singers"
|
|
29
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
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
|
+
require "active_record"
|
|
8
|
+
require "bundler"
|
|
9
|
+
|
|
10
|
+
Dir["../../lib/*.rb"].each { |file| require file }
|
|
11
|
+
|
|
12
|
+
Bundler.require
|
|
13
|
+
|
|
14
|
+
ActiveRecord::Base.establish_connection(
|
|
15
|
+
adapter: "spanner",
|
|
16
|
+
emulator_host: "localhost:9010",
|
|
17
|
+
project: "test-project",
|
|
18
|
+
instance: "test-instance",
|
|
19
|
+
database: "testdb"
|
|
20
|
+
)
|
|
21
|
+
ActiveRecord::Base.logger = nil
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Sample - Create Records
|
|
2
|
+
|
|
3
|
+
This sample shows how to create and save entities using ActiveRecord.
|
|
4
|
+
|
|
5
|
+
The sample will automatically start a Spanner Emulator in a docker container and execute the sample
|
|
6
|
+
against that emulator. The emulator will automatically be stopped when the application finishes.
|
|
7
|
+
|
|
8
|
+
Run the application with the command
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
bundle exec rake run
|
|
12
|
+
```
|
|
@@ -0,0 +1,13 @@
|
|
|
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
|
+
require_relative "../config/environment"
|
|
8
|
+
require "sinatra/activerecord/rake"
|
|
9
|
+
|
|
10
|
+
desc "Sample showing how to create one or more records in Spanner using ActiveRecord."
|
|
11
|
+
task :run do
|
|
12
|
+
Dir.chdir("..") { sh "bundle exec rake run[create-records]" }
|
|
13
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
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
|
+
require "io/console"
|
|
8
|
+
require_relative "../config/environment"
|
|
9
|
+
require_relative "models/singer"
|
|
10
|
+
require_relative "models/album"
|
|
11
|
+
|
|
12
|
+
class Application
|
|
13
|
+
def self.run
|
|
14
|
+
# Creating a single record without an explicit transaction will automatically save it to the database.
|
|
15
|
+
# It is not recommended to call Entity.create repeatedly to insert multiple records, as each call will
|
|
16
|
+
# use a separate Spanner transaction. Instead multiple records should be created by passing an array of
|
|
17
|
+
# entities to the Entity.create method.
|
|
18
|
+
singer = Singer.create first_name: "Dave", last_name: "Allison"
|
|
19
|
+
puts ""
|
|
20
|
+
puts "Created singer #{singer.first_name} #{singer.last_name} with id #{singer.id}"
|
|
21
|
+
puts ""
|
|
22
|
+
|
|
23
|
+
# Creating multiple records without an explicit transaction will automatically save all the records using
|
|
24
|
+
# one Spanner transaction and return the ids of the created records. This is the recommended way to create
|
|
25
|
+
# a batch of entities.
|
|
26
|
+
singers = Singer.create [
|
|
27
|
+
{ first_name: "Alice", last_name: "Wendelson" },
|
|
28
|
+
{ first_name: "Nick", last_name: "Rainbow" },
|
|
29
|
+
{ first_name: "Elena", last_name: "Quick" }
|
|
30
|
+
]
|
|
31
|
+
puts "Created a batch of #{singers.length} singers:"
|
|
32
|
+
singers.each do |s|
|
|
33
|
+
puts " Created singer #{s.first_name} #{s.last_name} with id #{s.id}"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
puts ""
|
|
37
|
+
puts "Press any key to end the application"
|
|
38
|
+
STDIN.getch
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
Application.run
|
|
@@ -0,0 +1,21 @@
|
|
|
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
|
+
class CreateTables < ActiveRecord::Migration[6.0]
|
|
8
|
+
def change
|
|
9
|
+
connection.ddl_batch do
|
|
10
|
+
create_table :singers do |t|
|
|
11
|
+
t.string :first_name
|
|
12
|
+
t.string :last_name
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
create_table :albums do |t|
|
|
16
|
+
t.string :title
|
|
17
|
+
t.references :singer, index: false, foreign_key: true
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# This file is auto-generated from the current state of the database. Instead
|
|
2
|
+
# of editing this file, please use the migrations feature of Active Record to
|
|
3
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
|
4
|
+
#
|
|
5
|
+
# This file is the source Rails uses to define your schema when running `rails
|
|
6
|
+
# db:schema:load`. When creating a new database, `rails db:schema:load` tends to
|
|
7
|
+
# be faster and is potentially less error prone than running all of your
|
|
8
|
+
# migrations from scratch. Old migrations may fail to apply correctly if those
|
|
9
|
+
# migrations use external dependencies or application code.
|
|
10
|
+
#
|
|
11
|
+
# It's strongly recommended that you check this file into your version control system.
|
|
12
|
+
|
|
13
|
+
ActiveRecord::Schema.define(version: 1) do
|
|
14
|
+
|
|
15
|
+
create_table "albums", force: :cascade do |t|
|
|
16
|
+
t.string "title"
|
|
17
|
+
t.integer "singer_id", limit: 8
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
create_table "singers", force: :cascade do |t|
|
|
21
|
+
t.string "first_name"
|
|
22
|
+
t.string "last_name"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
add_foreign_key "albums", "singers"
|
|
26
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Sample - Date Data Type
|
|
2
|
+
|
|
3
|
+
This example shows how to use the `DATE` data type with the Spanner ActiveRecord adapter. A `DATE` is a
|
|
4
|
+
timezone-independent date. It does not designate a specific point in time, such as UTC midnight of the date.
|
|
5
|
+
If you create a timezone-specific date/time object in Ruby and assign it to a `DATE` attribute, all time and timezone
|
|
6
|
+
information will be lost after saving and reloading the object.
|
|
7
|
+
|
|
8
|
+
Use the `TIMESTAMP` data type for attributes that represent a specific point in time.
|
|
9
|
+
|
|
10
|
+
## Running the Sample
|
|
11
|
+
|
|
12
|
+
The sample will automatically start a Spanner Emulator in a docker container and execute the sample
|
|
13
|
+
against that emulator. The emulator will automatically be stopped when the application finishes.
|
|
14
|
+
|
|
15
|
+
Run the application with the command
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
bundle exec rake run
|
|
19
|
+
```
|
|
@@ -0,0 +1,13 @@
|
|
|
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
|
+
require_relative "../config/environment"
|
|
8
|
+
require "sinatra/activerecord/rake"
|
|
9
|
+
|
|
10
|
+
desc "Sample showing how to work with the DATE data type in ActiveRecord."
|
|
11
|
+
task :run do
|
|
12
|
+
Dir.chdir("..") { sh "bundle exec rake run[date-data-type]" }
|
|
13
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
require "io/console"
|
|
8
|
+
require_relative "../config/environment"
|
|
9
|
+
require_relative "models/singer"
|
|
10
|
+
|
|
11
|
+
class Application
|
|
12
|
+
def self.run
|
|
13
|
+
# Get all singers order by birthdate
|
|
14
|
+
puts ""
|
|
15
|
+
puts "Listing all singers order by birth date:"
|
|
16
|
+
Singer.all.order(:birth_date).each do |singer|
|
|
17
|
+
puts "#{"#{singer.first_name} #{singer.last_name}".ljust 30}#{singer.birth_date}"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Update the birth date of a random singer using the current system time. Any time and timezone information will be
|
|
21
|
+
# lost after saving the record as a DATE only contains the year, month and day-of-month information.
|
|
22
|
+
singer = Singer.all.sample
|
|
23
|
+
singer.update birth_date: Time.now
|
|
24
|
+
singer.reload
|
|
25
|
+
puts ""
|
|
26
|
+
puts "Updated birth date to current system time:"
|
|
27
|
+
puts "#{"#{singer.first_name} #{singer.last_name}".ljust 30}#{singer.birth_date}"
|
|
28
|
+
|
|
29
|
+
puts ""
|
|
30
|
+
puts "Press any key to end the application"
|
|
31
|
+
STDIN.getch
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
Application.run
|
|
@@ -0,0 +1,20 @@
|
|
|
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
|
+
class CreateTables < ActiveRecord::Migration[6.0]
|
|
8
|
+
def change
|
|
9
|
+
connection.ddl_batch do
|
|
10
|
+
create_table :singers do |t|
|
|
11
|
+
t.string :first_name
|
|
12
|
+
t.string :last_name
|
|
13
|
+
# A date in Cloud Spanner represents a timezone independent date. It does not designate a specific point in
|
|
14
|
+
# time, such as for example midnight UTC of the specified date.
|
|
15
|
+
# See https://cloud.google.com/spanner/docs/data-definition-language#data_types for more information.
|
|
16
|
+
t.date :birth_date
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|