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
|
@@ -1,173 +1,587 @@
|
|
|
1
|
+
# Copyright 2020 Google LLC
|
|
2
|
+
#
|
|
3
|
+
# Use of this source code is governed by an MIT-style
|
|
4
|
+
# license that can be found in the LICENSE file or at
|
|
5
|
+
# https://opensource.org/licenses/MIT.
|
|
6
|
+
|
|
7
|
+
# frozen_string_literal: true
|
|
8
|
+
|
|
9
|
+
require "active_record/connection_adapters/spanner/schema_creation"
|
|
10
|
+
require "active_record/connection_adapters/spanner/schema_dumper"
|
|
11
|
+
|
|
1
12
|
module ActiveRecord
|
|
2
13
|
module ConnectionAdapters
|
|
3
14
|
module Spanner
|
|
15
|
+
#
|
|
16
|
+
# # SchemaStatements
|
|
17
|
+
#
|
|
18
|
+
# Collection of methods to handle database schema.
|
|
19
|
+
#
|
|
20
|
+
# [Schema Doc](https://cloud.google.com/spanner/docs/information-schema)
|
|
21
|
+
#
|
|
4
22
|
module SchemaStatements
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
NATIVE_DATABASE_TYPES = {
|
|
8
|
-
primary_key: 'STRING(36)',
|
|
9
|
-
string: { name: 'STRING', limit: 255 },
|
|
10
|
-
text: { name: 'STRING', limit: 'MAX' },
|
|
11
|
-
integer: { name: 'INT64' },
|
|
12
|
-
float: { name: 'FLOAT64' },
|
|
13
|
-
datetime: { name: 'TIMESTAMP' },
|
|
14
|
-
date: { name: 'DATE' },
|
|
15
|
-
binary: { name: 'BYTES', limit: 'MAX' },
|
|
16
|
-
boolean: { name: 'BOOL' },
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
def native_database_types # :nodoc:
|
|
20
|
-
NATIVE_DATABASE_TYPES
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def tables
|
|
24
|
-
# https://cloud.google.com/spanner/docs/information-schema
|
|
25
|
-
select_values(<<-SQL, 'SCHEMA')
|
|
26
|
-
SELECT
|
|
27
|
-
t.table_name
|
|
28
|
-
FROM
|
|
29
|
-
information_schema.tables AS t
|
|
30
|
-
WHERE
|
|
31
|
-
t.table_catalog = '' AND t.table_schema = ''
|
|
32
|
-
SQL
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def views
|
|
36
|
-
[]
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def indexes(table, name = :ignored)
|
|
40
|
-
params = {table: table}
|
|
41
|
-
results = exec_query(<<-"SQL", 'SCHEMA', params, prepare: false)
|
|
42
|
-
SELECT
|
|
43
|
-
idx.index_name,
|
|
44
|
-
idx.index_type,
|
|
45
|
-
idx.parent_table_name,
|
|
46
|
-
idx.is_unique,
|
|
47
|
-
idx.is_null_filtered
|
|
48
|
-
FROM
|
|
49
|
-
information_schema.indexes AS idx
|
|
50
|
-
WHERE
|
|
51
|
-
idx.table_catalog = '' AND
|
|
52
|
-
idx.table_schema = '' AND
|
|
53
|
-
idx.table_name = @table
|
|
54
|
-
SQL
|
|
55
|
-
|
|
56
|
-
results.map do |row|
|
|
57
|
-
col_params = { table: table, index: row['index_name'] }
|
|
58
|
-
col_results = exec_query(<<-"SQL", 'SCHEMA', col_params, prepare: false)
|
|
59
|
-
SELECT
|
|
60
|
-
col.column_name,
|
|
61
|
-
col.column_ordering
|
|
62
|
-
FROM
|
|
63
|
-
information_schema.index_columns AS col
|
|
64
|
-
WHERE
|
|
65
|
-
col.table_catalog = '' AND
|
|
66
|
-
col.table_schema = '' AND
|
|
67
|
-
col.table_name = @table AND
|
|
68
|
-
col.index_name = @index
|
|
69
|
-
ORDER BY
|
|
70
|
-
col.ordinal_position
|
|
71
|
-
SQL
|
|
23
|
+
VERSION_6_1_0 = Gem::Version.create "6.1.0"
|
|
24
|
+
VERSION_6_0_3 = Gem::Version.create "6.0.3"
|
|
72
25
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
26
|
+
def current_database
|
|
27
|
+
@connection.database_id
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Table
|
|
31
|
+
|
|
32
|
+
def data_sources
|
|
33
|
+
information_schema { |i| i.tables.map(&:name) }
|
|
34
|
+
end
|
|
35
|
+
alias tables data_sources
|
|
36
|
+
|
|
37
|
+
def table_exists? table_name
|
|
38
|
+
information_schema { |i| i.table table_name }.present?
|
|
39
|
+
end
|
|
40
|
+
alias data_source_exists? table_exists?
|
|
41
|
+
|
|
42
|
+
def create_table table_name, **options
|
|
43
|
+
td = create_table_definition table_name, options
|
|
44
|
+
|
|
45
|
+
if options[:id] != false
|
|
46
|
+
pk = options.fetch :primary_key do
|
|
47
|
+
Base.get_primary_key table_name.to_s.singularize
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
if pk.is_a? Array
|
|
51
|
+
td.primary_keys pk
|
|
52
|
+
else
|
|
53
|
+
td.primary_key pk, options.fetch(:id, :primary_key), **{}
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
yield td if block_given?
|
|
58
|
+
|
|
59
|
+
statements = []
|
|
60
|
+
|
|
61
|
+
if options[:force]
|
|
62
|
+
statements.concat drop_table_with_indexes_sql(table_name, options)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
statements << schema_creation.accept(td)
|
|
66
|
+
|
|
67
|
+
td.indexes.each do |column_name, index_options|
|
|
68
|
+
id = create_index_definition table_name, column_name, **index_options
|
|
69
|
+
statements << schema_creation.accept(id)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
execute_schema_statements statements
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def drop_table table_name, options = {}
|
|
76
|
+
statements = drop_table_with_indexes_sql table_name, options
|
|
77
|
+
execute_schema_statements statements
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Creates a join table that uses all the columns in the table as the primary key by default, unless
|
|
81
|
+
# an explicit primary key has been defined for the table. ActiveRecord will by default generate join
|
|
82
|
+
# tables without a primary key. Cloud Spanner however requires all tables to have a primary key.
|
|
83
|
+
# Instead of adding an additional column to the table only for the purpose of being the primary key,
|
|
84
|
+
# the Spanner ActiveRecord adapter defines a primary key that contains all the columns in the join
|
|
85
|
+
# table, as all values in the table should be unique anyways.
|
|
86
|
+
def create_join_table table_1, table_2, column_options: {}, **options
|
|
87
|
+
super do |td|
|
|
88
|
+
unless td.columns.any?(&:primary_key?)
|
|
89
|
+
td.columns.each do |col|
|
|
90
|
+
def col.primary_key?
|
|
91
|
+
true
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
yield td if block_given?
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def rename_table _table_name, _new_name
|
|
100
|
+
raise ActiveRecordSpannerAdapter::NotSupportedError, \
|
|
101
|
+
"rename_table is not implemented"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Column
|
|
105
|
+
|
|
106
|
+
def column_definitions table_name
|
|
107
|
+
information_schema { |i| i.table_columns table_name }
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def new_column_from_field _table_name, field
|
|
111
|
+
ConnectionAdapters::Column.new \
|
|
112
|
+
field.name,
|
|
113
|
+
field.default,
|
|
114
|
+
fetch_type_metadata(field.spanner_type, field.ordinal_position),
|
|
115
|
+
field.nullable
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def fetch_type_metadata sql_type, ordinal_position = nil
|
|
119
|
+
Spanner::TypeMetadata.new \
|
|
120
|
+
super(sql_type), ordinal_position: ordinal_position
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def add_column table_name, column_name, type, **options
|
|
124
|
+
# Add column with NOT NULL not supported by spanner.
|
|
125
|
+
# It is currently un-implemented state in spanner service.
|
|
126
|
+
nullable = options.delete(:null) == false
|
|
127
|
+
|
|
128
|
+
at = create_alter_table table_name
|
|
129
|
+
at.add_column column_name, type, **options
|
|
130
|
+
|
|
131
|
+
statements = [schema_creation.accept(at)]
|
|
132
|
+
|
|
133
|
+
# Alter NOT NULL
|
|
134
|
+
if nullable
|
|
135
|
+
cd = at.adds.first.column
|
|
136
|
+
cd.null = false
|
|
137
|
+
ccd = Spanner::ChangeColumnDefinition.new(
|
|
138
|
+
table_name, cd, column_name
|
|
82
139
|
)
|
|
140
|
+
statements << schema_creation.accept(ccd)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
execute_schema_statements statements
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def remove_column table_name, column_name, _type = nil, _options = {}
|
|
147
|
+
statements = drop_column_sql table_name, column_name
|
|
148
|
+
execute_schema_statements statements
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
if ActiveRecord.gem_version < VERSION_6_1_0
|
|
152
|
+
def remove_columns table_name, *column_names
|
|
153
|
+
_remove_columns table_name, *column_names
|
|
154
|
+
end
|
|
155
|
+
else
|
|
156
|
+
def remove_columns table_name, *column_names, _type: nil, **_options
|
|
157
|
+
_remove_columns table_name, *column_names
|
|
83
158
|
end
|
|
84
159
|
end
|
|
85
160
|
|
|
86
|
-
def
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
161
|
+
def _remove_columns table_name, *column_names
|
|
162
|
+
if column_names.empty?
|
|
163
|
+
raise ArgumentError, "You must specify at least one column name. "\
|
|
164
|
+
"Example: remove_columns(:people, :first_name)"
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
statements = []
|
|
168
|
+
|
|
169
|
+
column_names.each do |column_name|
|
|
170
|
+
statements.concat drop_column_sql(table_name, column_name)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
execute_schema_statements statements
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
if ActiveRecord.gem_version < VERSION_6_1_0
|
|
177
|
+
def change_column table_name, column_name, type, options = {}
|
|
178
|
+
_change_column table_name, column_name, type, **options
|
|
179
|
+
end
|
|
180
|
+
else
|
|
181
|
+
def change_column table_name, column_name, type, **options
|
|
182
|
+
_change_column table_name, column_name, type, **options
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def change_column_null table_name, column_name, null, _default = nil
|
|
187
|
+
change_column table_name, column_name, nil, null: null
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def change_column_default _table_name, _column_name, _default_or_changes
|
|
191
|
+
raise ActiveRecordSpannerAdapter::NotSupportedError, \
|
|
192
|
+
"change column with default value not supported."
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def rename_column table_name, column_name, new_column_name
|
|
196
|
+
if ActiveRecord::Base.connection.ddl_batch?
|
|
197
|
+
raise ActiveRecordSpannerAdapter::NotSupportedError, \
|
|
198
|
+
"rename_column in a DDL Batch is not supported."
|
|
199
|
+
end
|
|
200
|
+
column = information_schema do |i|
|
|
201
|
+
i.table_column table_name, column_name
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
unless column
|
|
205
|
+
raise ArgumentError,
|
|
206
|
+
"Column '#{column_name}' not exist for table '#{table_name}'"
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# Add Column
|
|
210
|
+
cast_type = lookup_cast_type column.spanner_type
|
|
211
|
+
add_column table_name, new_column_name, cast_type.type, **column.options
|
|
212
|
+
|
|
213
|
+
# Copy data
|
|
214
|
+
copy_data table_name, column_name, new_column_name
|
|
215
|
+
|
|
216
|
+
# Recreate Indexes
|
|
217
|
+
recreate_indexes table_name, column_name, new_column_name
|
|
218
|
+
|
|
219
|
+
# Recreate Foreign keys
|
|
220
|
+
recreate_foreign_keys table_name, column_name, new_column_name
|
|
221
|
+
|
|
222
|
+
# Drop Indexes, Drop Foreign keys and columns
|
|
223
|
+
remove_column table_name, column_name
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# Index
|
|
227
|
+
|
|
228
|
+
def indexes table_name
|
|
229
|
+
result = information_schema do |i|
|
|
230
|
+
i.indexes table_name, index_type: "INDEX"
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
result.map do |index|
|
|
234
|
+
IndexDefinition.new(
|
|
235
|
+
index.table,
|
|
236
|
+
index.name,
|
|
237
|
+
index.columns.map(&:name),
|
|
238
|
+
unique: index.unique,
|
|
239
|
+
null_filtered: index.null_filtered,
|
|
240
|
+
interleave_in: index.interleave_in,
|
|
241
|
+
storing: index.storing,
|
|
242
|
+
orders: index.orders
|
|
111
243
|
)
|
|
112
244
|
end
|
|
113
245
|
end
|
|
114
246
|
|
|
115
|
-
def
|
|
116
|
-
|
|
117
|
-
index.type == 'PRIMARY_KEY'
|
|
118
|
-
}.columns
|
|
247
|
+
def index_name_exists? table_name, index_name
|
|
248
|
+
information_schema { |i| i.index table_name, index_name }.present?
|
|
119
249
|
end
|
|
120
250
|
|
|
121
|
-
def
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
251
|
+
def add_index table_name, column_name, options = {}
|
|
252
|
+
id = create_index_definition table_name, column_name, **options
|
|
253
|
+
|
|
254
|
+
if data_source_exists?(table_name) &&
|
|
255
|
+
index_name_exists?(table_name, id.name)
|
|
256
|
+
raise ArgumentError, "Index name '#{id.name}' on table" \
|
|
257
|
+
"'#{table_name}' already exists"
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
execute_schema_statements schema_creation.accept(id)
|
|
126
261
|
end
|
|
127
262
|
|
|
128
|
-
|
|
129
|
-
|
|
263
|
+
if ActiveRecord.gem_version < VERSION_6_1_0
|
|
264
|
+
def remove_index table_name, options = {}
|
|
265
|
+
index_name = index_name_for_remove table_name, options
|
|
266
|
+
execute "DROP INDEX #{quote_table_name index_name}"
|
|
267
|
+
end
|
|
268
|
+
else
|
|
269
|
+
def remove_index table_name, column_name = nil, **options
|
|
270
|
+
index_name = index_name_for_remove table_name, column_name, options
|
|
271
|
+
execute "DROP INDEX #{quote_table_name index_name}"
|
|
272
|
+
end
|
|
130
273
|
end
|
|
131
274
|
|
|
132
|
-
def
|
|
133
|
-
|
|
134
|
-
raise NotImplementedError, 'force in drop_table' if options[:force]
|
|
275
|
+
def rename_index table_name, old_name, new_name
|
|
276
|
+
validate_index_length! table_name, new_name
|
|
135
277
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
278
|
+
old_index = information_schema { |i| i.index table_name, old_name }
|
|
279
|
+
return unless old_index
|
|
280
|
+
|
|
281
|
+
statements = [
|
|
282
|
+
schema_creation.accept(DropIndexDefinition.new(old_name))
|
|
283
|
+
]
|
|
284
|
+
|
|
285
|
+
id = IndexDefinition.new \
|
|
286
|
+
old_index.table,
|
|
287
|
+
new_name,
|
|
288
|
+
old_index.columns.map(&:name),
|
|
289
|
+
unique: old_index.unique,
|
|
290
|
+
null_filtered: old_index.null_filtered,
|
|
291
|
+
interleave_in: old_index.interleave_in,
|
|
292
|
+
storing: old_index.storing,
|
|
293
|
+
orders: old_index.orders
|
|
294
|
+
|
|
295
|
+
statements << schema_creation.accept(id)
|
|
296
|
+
execute_schema_statements statements
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
# Primary Keys
|
|
300
|
+
|
|
301
|
+
def primary_keys table_name
|
|
302
|
+
columns = information_schema do |i|
|
|
303
|
+
i.table_primary_keys table_name
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
columns.map(&:name)
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def primary_and_parent_keys table_name
|
|
310
|
+
columns = information_schema do |i|
|
|
311
|
+
i.table_primary_keys table_name, true
|
|
312
|
+
end
|
|
141
313
|
|
|
142
|
-
|
|
143
|
-
execute_ddl(*ddls)
|
|
314
|
+
columns.map(&:name)
|
|
144
315
|
end
|
|
145
316
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
317
|
+
# Foreign Keys
|
|
318
|
+
|
|
319
|
+
def foreign_keys table_name, column: nil
|
|
320
|
+
raise ArgumentError if table_name.blank?
|
|
321
|
+
|
|
322
|
+
result = information_schema { |i| i.foreign_keys table_name }
|
|
323
|
+
|
|
324
|
+
if column
|
|
325
|
+
result = result.select { |fk| fk.columns.include? column.to_s }
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
result.map do |fk|
|
|
329
|
+
options = {
|
|
330
|
+
column: fk.columns.first,
|
|
331
|
+
name: fk.name,
|
|
332
|
+
primary_key: fk.ref_columns.first,
|
|
333
|
+
on_delete: fk.on_update,
|
|
334
|
+
on_update: fk.on_update
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
ForeignKeyDefinition.new table_name, fk.ref_table, options
|
|
338
|
+
end
|
|
155
339
|
end
|
|
156
340
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
341
|
+
if ActiveRecord.gem_version < VERSION_6_0_3
|
|
342
|
+
def add_foreign_key from_table, to_table, options = {}
|
|
343
|
+
_add_foreign_key from_table, to_table, **options
|
|
344
|
+
end
|
|
345
|
+
else
|
|
346
|
+
def add_foreign_key from_table, to_table, **options
|
|
347
|
+
_add_foreign_key from_table, to_table, **options
|
|
162
348
|
end
|
|
163
349
|
end
|
|
164
350
|
|
|
351
|
+
def _add_foreign_key from_table, to_table, **options
|
|
352
|
+
options = foreign_key_options from_table, to_table, options
|
|
353
|
+
at = create_alter_table from_table
|
|
354
|
+
at.add_foreign_key to_table, options
|
|
355
|
+
|
|
356
|
+
execute_schema_statements schema_creation.accept(at)
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
def remove_foreign_key from_table, to_table = nil, **options
|
|
360
|
+
fk_name_to_delete = foreign_key_for!(
|
|
361
|
+
from_table, to_table: to_table, **options
|
|
362
|
+
).name
|
|
363
|
+
|
|
364
|
+
at = create_alter_table from_table
|
|
365
|
+
at.drop_foreign_key fk_name_to_delete
|
|
366
|
+
|
|
367
|
+
execute_schema_statements schema_creation.accept(at)
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
# Reference Column
|
|
371
|
+
|
|
372
|
+
def add_reference table_name, ref_name, **options
|
|
373
|
+
ReferenceDefinition.new(ref_name, **options).add_to(
|
|
374
|
+
update_table_definition(table_name, self)
|
|
375
|
+
)
|
|
376
|
+
end
|
|
377
|
+
alias add_belongs_to add_reference
|
|
378
|
+
|
|
379
|
+
def quoted_scope name = nil, type: nil
|
|
380
|
+
scope = { schema: quote("") }
|
|
381
|
+
scope[:name] = quote name if name
|
|
382
|
+
scope[:type] = quote type if type
|
|
383
|
+
scope
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
def create_schema_dumper options
|
|
387
|
+
SchemaDumper.create self, options
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
|
391
|
+
def type_to_sql type, limit: nil, precision: nil, scale: nil, **opts
|
|
392
|
+
type = type.to_sym if type
|
|
393
|
+
native = native_database_types[type]
|
|
394
|
+
|
|
395
|
+
return type.to_s unless native
|
|
396
|
+
|
|
397
|
+
sql_type = (native.is_a?(Hash) ? native[:name] : native).dup
|
|
398
|
+
|
|
399
|
+
sql_type = "#{sql_type}(#{limit || native[:limit]})" if [:string, :text, :binary].include? type
|
|
400
|
+
sql_type = "ARRAY<#{sql_type}>" if opts[:array]
|
|
401
|
+
|
|
402
|
+
sql_type
|
|
403
|
+
end
|
|
404
|
+
# rubocop:enable Lint/UnusedMethodArgument
|
|
405
|
+
|
|
165
406
|
private
|
|
166
|
-
|
|
167
|
-
|
|
407
|
+
|
|
408
|
+
def schema_creation
|
|
409
|
+
SchemaCreation.new self
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
def create_table_definition *args
|
|
413
|
+
TableDefinition.new self, args[0], options: args[1]
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
def able_to_ddl_batch? table_name
|
|
417
|
+
[ActiveRecord::InternalMetadata.table_name, ActiveRecord::SchemaMigration.table_name].exclude? table_name.to_s
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
def _change_column table_name, column_name, type, **options # rubocop:disable Metrics/AbcSize
|
|
421
|
+
column = information_schema do |i|
|
|
422
|
+
i.table_column table_name, column_name
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
unless column
|
|
426
|
+
raise ArgumentError,
|
|
427
|
+
"Column '#{column_name}' not exist for table '#{table_name}'"
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
indexes = information_schema do |i|
|
|
431
|
+
i.indexes_by_columns table_name, column_name
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
statements = indexes.map do |index|
|
|
435
|
+
schema_creation.accept DropIndexDefinition.new(index.name)
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
column = new_column_from_field table_name, column
|
|
439
|
+
|
|
440
|
+
type ||= column.type
|
|
441
|
+
options[:null] = column.null unless options.key? :null
|
|
442
|
+
|
|
443
|
+
if ["STRING", "BYTES"].include? type
|
|
444
|
+
options[:limit] = column.limit unless options.key? :limit
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
# Only timestamp type can set commit timestamp
|
|
448
|
+
if type == "TIMESTAMP" && options.key?(:allow_commit_timestamp) == false
|
|
449
|
+
options[:allow_commit_timestamp] = column.allow_commit_timestamp
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
td = create_table_definition table_name
|
|
453
|
+
cd = td.new_column_definition column.name, type, **options
|
|
454
|
+
|
|
455
|
+
ccd = Spanner::ChangeColumnDefinition.new table_name, cd, column.name
|
|
456
|
+
statements << schema_creation.accept(ccd)
|
|
457
|
+
|
|
458
|
+
# Recreate indexes
|
|
459
|
+
indexes.each do |index|
|
|
460
|
+
id = create_index_definition(
|
|
461
|
+
table_name,
|
|
462
|
+
index.column_names,
|
|
463
|
+
**index.options
|
|
464
|
+
)
|
|
465
|
+
statements << schema_creation.accept(id)
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
execute_schema_statements statements
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
def copy_data table_name, src_column_name, dest_column_name
|
|
472
|
+
sql = "UPDATE %<table>s SET %<dest_column_name>s = %<src_column_name>s WHERE true"
|
|
473
|
+
values = {
|
|
474
|
+
table: table_name,
|
|
475
|
+
dest_column_name: quote_column_name(dest_column_name),
|
|
476
|
+
src_column_name: quote_column_name(src_column_name)
|
|
477
|
+
}
|
|
478
|
+
ActiveRecord::Base.connection.transaction isolation: :pdml do
|
|
479
|
+
execute sql % values
|
|
480
|
+
end
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
def recreate_indexes table_name, column_name, new_column_name
|
|
484
|
+
indexes = information_schema.indexes_by_columns table_name, column_name
|
|
485
|
+
indexes.each do |index|
|
|
486
|
+
remove_index table_name, name: index.name
|
|
487
|
+
options = index.rename_column_options column_name, new_column_name
|
|
488
|
+
options[:options][:name] = options[:options][:name].to_s.gsub(
|
|
489
|
+
column_name.to_s, new_column_name.to_s
|
|
490
|
+
)
|
|
491
|
+
add_index table_name, options[:columns], **options[:options]
|
|
492
|
+
end
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
def recreate_foreign_keys table_name, column_name, new_column_name
|
|
496
|
+
fkeys = foreign_keys table_name, column: column_name
|
|
497
|
+
fkeys.each do |fk|
|
|
498
|
+
remove_foreign_key table_name, name: fk.name
|
|
499
|
+
options = fk.options.except :column, :name
|
|
500
|
+
options[:column] = new_column_name
|
|
501
|
+
add_foreign_key table_name, fk.to_table, **options
|
|
502
|
+
end
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
def create_index_definition table_name, column_name, **options
|
|
506
|
+
column_names = index_column_names column_name
|
|
507
|
+
|
|
508
|
+
options.assert_valid_keys(
|
|
509
|
+
:unique, :order, :name, :where, :length, :internal, :using,
|
|
510
|
+
:algorithm, :type, :opclass, :interleave_in, :storing,
|
|
511
|
+
:null_filtered
|
|
512
|
+
)
|
|
513
|
+
|
|
514
|
+
index_name = options[:name].to_s if options.key? :name
|
|
515
|
+
index_name ||= index_name table_name, column_names
|
|
516
|
+
|
|
517
|
+
validate_index_length! table_name, index_name
|
|
518
|
+
|
|
519
|
+
IndexDefinition.new \
|
|
520
|
+
table_name,
|
|
521
|
+
index_name,
|
|
522
|
+
column_names,
|
|
523
|
+
unique: options[:unique],
|
|
524
|
+
null_filtered: options[:null_filtered],
|
|
525
|
+
interleave_in: options[:interleave_in],
|
|
526
|
+
storing: options[:storing],
|
|
527
|
+
orders: options[:order]
|
|
528
|
+
end
|
|
529
|
+
|
|
530
|
+
def drop_table_with_indexes_sql table_name, options
|
|
531
|
+
statements = []
|
|
532
|
+
|
|
533
|
+
table = information_schema { |i| i.table table_name, view: :indexes }
|
|
534
|
+
return statements unless table
|
|
535
|
+
|
|
536
|
+
table.indexes.each do |index|
|
|
537
|
+
next if index.primary?
|
|
538
|
+
|
|
539
|
+
statements << schema_creation.accept(
|
|
540
|
+
DropIndexDefinition.new(index.name)
|
|
541
|
+
)
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
statements << schema_creation.accept(
|
|
545
|
+
DropTableDefinition.new(table_name, options)
|
|
546
|
+
)
|
|
547
|
+
statements
|
|
548
|
+
end
|
|
549
|
+
|
|
550
|
+
def drop_column_sql table_name, column_name
|
|
551
|
+
indexes = information_schema do |i|
|
|
552
|
+
i.indexes_by_columns table_name, column_name
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
statements = indexes.map do |index|
|
|
556
|
+
schema_creation.accept DropIndexDefinition.new(index.name)
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
foreign_keys(table_name, column: column_name).each do |fk|
|
|
560
|
+
at = create_alter_table table_name
|
|
561
|
+
at.drop_foreign_key fk.name
|
|
562
|
+
statements << schema_creation.accept(at)
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
statements << schema_creation.accept(
|
|
566
|
+
DropColumnDefinition.new(table_name, column_name)
|
|
567
|
+
)
|
|
568
|
+
|
|
569
|
+
statements
|
|
570
|
+
end
|
|
571
|
+
|
|
572
|
+
def execute_schema_statements statements
|
|
573
|
+
execute_ddl statements
|
|
574
|
+
end
|
|
575
|
+
|
|
576
|
+
def information_schema
|
|
577
|
+
info_schema = \
|
|
578
|
+
ActiveRecordSpannerAdapter::Connection.information_schema @config
|
|
579
|
+
|
|
580
|
+
return info_schema unless block_given?
|
|
581
|
+
|
|
582
|
+
yield info_schema
|
|
168
583
|
end
|
|
169
584
|
end
|
|
170
585
|
end
|
|
171
586
|
end
|
|
172
587
|
end
|
|
173
|
-
|