activerecord-spanner-adapter 0.3.0 → 0.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 +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 +36 -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 +26 -0
- data/CODE_OF_CONDUCT.md +40 -0
- data/CONTRIBUTING.md +79 -0
- data/Gemfile +9 -4
- data/LICENSE +6 -6
- data/README.md +67 -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 +147 -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 +67 -0
- data/acceptance/cases/transactions/read_write_transactions_test.rb +248 -0
- data/acceptance/cases/type/all_types_test.rb +152 -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/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 +143 -0
- data/acceptance/test_helper.rb +260 -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/interleaved-tables/README.md +152 -0
- data/examples/snippets/interleaved-tables/Rakefile +13 -0
- data/examples/snippets/interleaved-tables/application.rb +109 -0
- data/examples/snippets/interleaved-tables/config/database.yml +8 -0
- data/examples/snippets/interleaved-tables/db/migrate/01_create_tables.rb +44 -0
- data/examples/snippets/interleaved-tables/db/schema.rb +32 -0
- data/examples/snippets/interleaved-tables/db/seeds.rb +40 -0
- data/examples/snippets/interleaved-tables/models/album.rb +15 -0
- data/examples/snippets/interleaved-tables/models/singer.rb +20 -0
- data/examples/snippets/interleaved-tables/models/track.rb +25 -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/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 +49 -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/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 +224 -269
- 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 +182 -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 +32 -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 +217 -0
- data/lib/activerecord_spanner_adapter/connection.rb +324 -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 +261 -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 +113 -0
- data/lib/activerecord_spanner_adapter/version.rb +9 -0
- data/lib/arel/visitors/spanner.rb +35 -0
- data/lib/spanner_client_ext.rb +82 -0
- data/renovate.json +5 -0
- metadata +387 -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,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 array data types in ActiveRecord."
|
|
11
|
+
task :run do
|
|
12
|
+
Dir.chdir("..") { sh "bundle exec rake run[array-data-type]" }
|
|
13
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
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/entity_with_array_types"
|
|
10
|
+
|
|
11
|
+
class Application
|
|
12
|
+
def self.run # rubocop:disable Metrics/AbcSize
|
|
13
|
+
# Create a record with all array types.
|
|
14
|
+
record = EntityWithArrayTypes.create \
|
|
15
|
+
col_array_string: ["value1", "value2", "value3"],
|
|
16
|
+
col_array_int64: [100, 200, 300],
|
|
17
|
+
col_array_float64: [3.14, 2.0 / 3.0],
|
|
18
|
+
col_array_numeric: [6.626, 3.20],
|
|
19
|
+
# All arrays can contain null elements.
|
|
20
|
+
col_array_bool: [true, false, nil, true],
|
|
21
|
+
col_array_bytes: [StringIO.new("value1"), StringIO.new("value2")],
|
|
22
|
+
col_array_date: [::Date.new(2021, 6, 23), ::Date.new(2021, 6, 28)],
|
|
23
|
+
# Timestamps can be specified in any timezone, but Cloud Spanner will always convert and store them in UTC.
|
|
24
|
+
col_array_timestamp: [::Time.new(2021, 6, 23, 17, 8, 21, "+02:00"), ::Time.utc(2021, 6, 23, 17, 8, 21)]
|
|
25
|
+
|
|
26
|
+
# Reload the record from Cloud Spanner and print out the values.
|
|
27
|
+
record = record.reload
|
|
28
|
+
puts ""
|
|
29
|
+
puts "Saved record #{record.id} with array values: "
|
|
30
|
+
puts "String array: #{record.col_array_string}"
|
|
31
|
+
puts "Int64 array: #{record.col_array_int64}"
|
|
32
|
+
puts "Float64 array: #{record.col_array_float64}"
|
|
33
|
+
puts "Numeric array: #{record.col_array_numeric}"
|
|
34
|
+
puts "Bool array: #{record.col_array_bool}"
|
|
35
|
+
puts "Bytes array: #{record.col_array_bytes.map(&:read)}"
|
|
36
|
+
puts "Date array: #{record.col_array_date}"
|
|
37
|
+
puts "Timestamp array: #{record.col_array_timestamp}"
|
|
38
|
+
|
|
39
|
+
puts ""
|
|
40
|
+
puts "Press any key to end the application"
|
|
41
|
+
STDIN.getch
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
Application.run
|
|
@@ -0,0 +1,24 @@
|
|
|
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
|
+
# Execute the entire migration as one DDL batch.
|
|
10
|
+
connection.ddl_batch do
|
|
11
|
+
create_table :entity_with_array_types do |t|
|
|
12
|
+
# Create a table with a column with each possible array type.
|
|
13
|
+
t.column :col_array_string, :string, array: true
|
|
14
|
+
t.column :col_array_int64, :bigint, array: true
|
|
15
|
+
t.column :col_array_float64, :float, array: true
|
|
16
|
+
t.column :col_array_numeric, :numeric, array: true
|
|
17
|
+
t.column :col_array_bool, :boolean, array: true
|
|
18
|
+
t.column :col_array_bytes, :binary, array: true
|
|
19
|
+
t.column :col_array_date, :date, array: true
|
|
20
|
+
t.column :col_array_timestamp, :datetime, array: true
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
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 "entity_with_array_types", force: :cascade do |t|
|
|
16
|
+
t.string "col_array_string"
|
|
17
|
+
t.integer "col_array_int64", limit: 8
|
|
18
|
+
t.float "col_array_float64"
|
|
19
|
+
t.decimal "col_array_numeric"
|
|
20
|
+
t.boolean "col_array_bool"
|
|
21
|
+
t.binary "col_array_bytes"
|
|
22
|
+
t.date "col_array_date"
|
|
23
|
+
t.time "col_array_timestamp"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
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 EntityWithArrayTypes < ActiveRecord::Base
|
|
8
|
+
# This entity has one attribute for each possible ARRAY data type in Cloud Spanner.
|
|
9
|
+
# col_array_string ARRAY<STRING(MAX)>
|
|
10
|
+
# col_array_int64 ARRAY<INT64>
|
|
11
|
+
# col_array_float64 ARRAY<FLOAT64>
|
|
12
|
+
# col_array_numeric ARRAY<NUMERIC>
|
|
13
|
+
# col_array_bool ARRAY<BOOL>
|
|
14
|
+
# col_array_bytes ARRAY<BYTES(MAX)>
|
|
15
|
+
# col_array_date ARRAY<DATE>
|
|
16
|
+
# col_array_timestamp ARRAY<TIMESTAMP>
|
|
17
|
+
#
|
|
18
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
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 "google/cloud/spanner"
|
|
8
|
+
|
|
9
|
+
spanner = Google::Cloud::Spanner.new project: "test-project", emulator_host: "localhost:9010"
|
|
10
|
+
job = spanner.create_instance "test-instance",
|
|
11
|
+
name: "Test Instance",
|
|
12
|
+
config: "emulator-config",
|
|
13
|
+
nodes: 1
|
|
14
|
+
job.wait_until_done!
|
|
15
|
+
|
|
16
|
+
instance = spanner.instance "test-instance"
|
|
17
|
+
job = instance.create_database "testdb", statements: []
|
|
18
|
+
job.wait_until_done!
|
|
@@ -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
|