activerecord 7.1.6 → 7.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +839 -2248
- data/README.rdoc +16 -16
- data/examples/performance.rb +2 -2
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/alias_tracker.rb +31 -23
- data/lib/active_record/associations/association.rb +15 -8
- data/lib/active_record/associations/belongs_to_association.rb +31 -8
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
- data/lib/active_record/associations/builder/belongs_to.rb +1 -0
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +2 -2
- data/lib/active_record/associations/builder/has_many.rb +3 -4
- data/lib/active_record/associations/builder/has_one.rb +3 -4
- data/lib/active_record/associations/collection_association.rb +16 -8
- data/lib/active_record/associations/collection_proxy.rb +14 -1
- data/lib/active_record/associations/errors.rb +265 -0
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +7 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +1 -1
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +2 -1
- data/lib/active_record/associations/preloader/branch.rb +7 -1
- data/lib/active_record/associations/preloader/through_association.rb +1 -3
- data/lib/active_record/associations/singular_association.rb +6 -0
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +59 -292
- data/lib/active_record/attribute_assignment.rb +0 -2
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/primary_key.rb +23 -55
- data/lib/active_record/attribute_methods/read.rb +1 -13
- data/lib/active_record/attribute_methods/serialization.rb +5 -25
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +7 -6
- data/lib/active_record/attribute_methods.rb +51 -60
- data/lib/active_record/attributes.rb +93 -68
- data/lib/active_record/autosave_association.rb +25 -32
- data/lib/active_record/base.rb +4 -5
- data/lib/active_record/callbacks.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +24 -107
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +1 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +294 -72
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +34 -17
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +201 -75
- data/lib/active_record/connection_adapters/abstract/quoting.rb +65 -91
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +6 -2
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +18 -6
- data/lib/active_record/connection_adapters/abstract/transaction.rb +125 -62
- data/lib/active_record/connection_adapters/abstract_adapter.rb +46 -44
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +53 -15
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +9 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +43 -48
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +6 -0
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +19 -18
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -23
- data/lib/active_record/connection_adapters/pool_config.rb +7 -6
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +27 -4
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +58 -58
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +30 -8
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +16 -12
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +36 -26
- data/lib/active_record/connection_adapters/schema_cache.rb +123 -128
- data/lib/active_record/connection_adapters/sqlite3/column.rb +14 -1
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +10 -6
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +57 -46
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +13 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +26 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +133 -78
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +15 -15
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +19 -48
- data/lib/active_record/connection_adapters.rb +121 -0
- data/lib/active_record/connection_handling.rb +68 -49
- data/lib/active_record/core.rb +112 -44
- data/lib/active_record/counter_cache.rb +19 -10
- data/lib/active_record/database_configurations/connection_url_resolver.rb +9 -2
- data/lib/active_record/database_configurations/database_config.rb +19 -4
- data/lib/active_record/database_configurations/hash_config.rb +38 -34
- data/lib/active_record/database_configurations/url_config.rb +20 -1
- data/lib/active_record/database_configurations.rb +1 -1
- data/lib/active_record/delegated_type.rb +42 -18
- data/lib/active_record/dynamic_matchers.rb +2 -2
- data/lib/active_record/encryption/encryptable_record.rb +4 -4
- data/lib/active_record/encryption/encrypted_attribute_type.rb +25 -5
- data/lib/active_record/encryption/encryptor.rb +35 -19
- data/lib/active_record/encryption/key_provider.rb +1 -1
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +4 -0
- data/lib/active_record/encryption/null_encryptor.rb +4 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
- data/lib/active_record/enum.rb +31 -13
- data/lib/active_record/errors.rb +49 -23
- data/lib/active_record/explain.rb +13 -24
- data/lib/active_record/fixture_set/table_row.rb +19 -2
- data/lib/active_record/fixtures.rb +37 -31
- data/lib/active_record/future_result.rb +8 -4
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +4 -2
- data/lib/active_record/insert_all.rb +18 -15
- data/lib/active_record/integration.rb +4 -1
- data/lib/active_record/internal_metadata.rb +48 -34
- data/lib/active_record/locking/optimistic.rb +7 -6
- data/lib/active_record/log_subscriber.rb +0 -21
- data/lib/active_record/message_pack.rb +1 -1
- data/lib/active_record/migration/command_recorder.rb +2 -3
- data/lib/active_record/migration/compatibility.rb +5 -3
- data/lib/active_record/migration/default_strategy.rb +4 -5
- data/lib/active_record/migration/pending_migration_connection.rb +2 -2
- data/lib/active_record/migration.rb +87 -77
- data/lib/active_record/model_schema.rb +31 -68
- data/lib/active_record/nested_attributes.rb +11 -3
- data/lib/active_record/normalization.rb +3 -7
- data/lib/active_record/persistence.rb +30 -352
- data/lib/active_record/query_cache.rb +19 -8
- data/lib/active_record/query_logs.rb +19 -0
- data/lib/active_record/querying.rb +25 -13
- data/lib/active_record/railtie.rb +39 -57
- data/lib/active_record/railties/controller_runtime.rb +13 -4
- data/lib/active_record/railties/databases.rake +42 -44
- data/lib/active_record/reflection.rb +98 -36
- data/lib/active_record/relation/batches/batch_enumerator.rb +15 -2
- data/lib/active_record/relation/batches.rb +14 -8
- data/lib/active_record/relation/calculations.rb +127 -89
- data/lib/active_record/relation/delegation.rb +8 -11
- data/lib/active_record/relation/finder_methods.rb +26 -12
- data/lib/active_record/relation/merger.rb +4 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +10 -2
- data/lib/active_record/relation/predicate_builder.rb +3 -3
- data/lib/active_record/relation/query_attribute.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +238 -65
- data/lib/active_record/relation/record_fetch_warning.rb +3 -0
- data/lib/active_record/relation/spawn_methods.rb +2 -18
- data/lib/active_record/relation/where_clause.rb +15 -21
- data/lib/active_record/relation.rb +508 -74
- data/lib/active_record/result.rb +31 -44
- data/lib/active_record/runtime_registry.rb +39 -0
- data/lib/active_record/sanitization.rb +24 -19
- data/lib/active_record/schema.rb +8 -6
- data/lib/active_record/schema_dumper.rb +48 -20
- data/lib/active_record/schema_migration.rb +30 -14
- data/lib/active_record/scoping/named.rb +1 -0
- data/lib/active_record/secure_token.rb +3 -3
- data/lib/active_record/signed_id.rb +27 -7
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/table_metadata.rb +1 -10
- data/lib/active_record/tasks/database_tasks.rb +69 -41
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +8 -1
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -1
- data/lib/active_record/test_fixtures.rb +86 -89
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +2 -2
- data/lib/active_record/token_for.rb +22 -12
- data/lib/active_record/touch_later.rb +1 -1
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +73 -15
- data/lib/active_record/translation.rb +0 -2
- data/lib/active_record/type/serialized.rb +1 -3
- data/lib/active_record/type_caster/connection.rb +4 -4
- data/lib/active_record/validations/associated.rb +9 -3
- data/lib/active_record/validations/uniqueness.rb +15 -10
- data/lib/active_record/validations.rb +4 -1
- data/lib/active_record.rb +148 -39
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/collectors/bind.rb +3 -1
- data/lib/arel/collectors/composite.rb +7 -0
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- data/lib/arel/crud.rb +2 -0
- data/lib/arel/delete_manager.rb +5 -0
- data/lib/arel/nodes/binary.rb +0 -6
- data/lib/arel/nodes/bound_sql_literal.rb +9 -5
- data/lib/arel/nodes/delete_statement.rb +4 -2
- data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
- data/lib/arel/nodes/node.rb +4 -3
- data/lib/arel/nodes/sql_literal.rb +7 -0
- data/lib/arel/nodes/update_statement.rb +4 -2
- data/lib/arel/nodes.rb +2 -2
- data/lib/arel/predications.rb +1 -1
- data/lib/arel/select_manager.rb +7 -3
- data/lib/arel/tree_manager.rb +3 -2
- data/lib/arel/update_manager.rb +7 -1
- data/lib/arel/visitors/dot.rb +3 -0
- data/lib/arel/visitors/mysql.rb +9 -4
- data/lib/arel/visitors/postgresql.rb +1 -12
- data/lib/arel/visitors/sqlite.rb +25 -0
- data/lib/arel/visitors/to_sql.rb +31 -16
- data/lib/arel.rb +7 -3
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
- metadata +16 -10
|
@@ -21,7 +21,7 @@ module ActiveRecord
|
|
|
21
21
|
SQLite3::ExplainPrettyPrinter.new.pp(result)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
def internal_exec_query(sql, name = nil, binds = [], prepare: false, async: false) # :nodoc:
|
|
24
|
+
def internal_exec_query(sql, name = nil, binds = [], prepare: false, async: false, allow_retry: false) # :nodoc:
|
|
25
25
|
sql = transform_query(sql)
|
|
26
26
|
check_if_write_query(sql)
|
|
27
27
|
|
|
@@ -29,7 +29,7 @@ module ActiveRecord
|
|
|
29
29
|
|
|
30
30
|
type_casted_binds = type_casted_binds(binds)
|
|
31
31
|
|
|
32
|
-
log(sql, name, binds, type_casted_binds, async: async) do
|
|
32
|
+
log(sql, name, binds, type_casted_binds, async: async) do |notification_payload|
|
|
33
33
|
with_raw_connection do |conn|
|
|
34
34
|
# Don't cache statements if they are not prepared
|
|
35
35
|
unless prepare
|
|
@@ -52,7 +52,9 @@ module ActiveRecord
|
|
|
52
52
|
end
|
|
53
53
|
verified!
|
|
54
54
|
|
|
55
|
-
build_result(columns: cols, rows: records)
|
|
55
|
+
result = build_result(columns: cols, rows: records)
|
|
56
|
+
notification_payload[:row_count] = result.length
|
|
57
|
+
result
|
|
56
58
|
end
|
|
57
59
|
end
|
|
58
60
|
end
|
|
@@ -104,7 +106,7 @@ module ActiveRecord
|
|
|
104
106
|
|
|
105
107
|
# https://stackoverflow.com/questions/17574784
|
|
106
108
|
# https://www.sqlite.org/lang_datefunc.html
|
|
107
|
-
HIGH_PRECISION_CURRENT_TIMESTAMP = Arel.sql("STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')").freeze # :nodoc:
|
|
109
|
+
HIGH_PRECISION_CURRENT_TIMESTAMP = Arel.sql("STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')", retryable: true).freeze # :nodoc:
|
|
108
110
|
private_constant :HIGH_PRECISION_CURRENT_TIMESTAMP
|
|
109
111
|
|
|
110
112
|
def high_precision_current_timestamp
|
|
@@ -113,10 +115,11 @@ module ActiveRecord
|
|
|
113
115
|
|
|
114
116
|
private
|
|
115
117
|
def raw_execute(sql, name, async: false, allow_retry: false, materialize_transactions: false)
|
|
116
|
-
log(sql, name, async: async) do
|
|
118
|
+
log(sql, name, async: async) do |notification_payload|
|
|
117
119
|
with_raw_connection(allow_retry: allow_retry, materialize_transactions: materialize_transactions) do |conn|
|
|
118
120
|
result = conn.execute(sql)
|
|
119
121
|
verified!
|
|
122
|
+
notification_payload[:row_count] = result.length
|
|
120
123
|
result
|
|
121
124
|
end
|
|
122
125
|
end
|
|
@@ -136,10 +139,11 @@ module ActiveRecord
|
|
|
136
139
|
check_if_write_query(sql)
|
|
137
140
|
mark_transaction_written_if_write(sql)
|
|
138
141
|
|
|
139
|
-
log(sql, name) do
|
|
142
|
+
log(sql, name) do |notification_payload|
|
|
140
143
|
with_raw_connection do |conn|
|
|
141
144
|
result = conn.execute_batch2(sql)
|
|
142
145
|
verified!
|
|
146
|
+
notification_payload[:row_count] = result.length
|
|
143
147
|
result
|
|
144
148
|
end
|
|
145
149
|
end
|
|
@@ -4,23 +4,71 @@ module ActiveRecord
|
|
|
4
4
|
module ConnectionAdapters
|
|
5
5
|
module SQLite3
|
|
6
6
|
module Quoting # :nodoc:
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
7
9
|
QUOTED_COLUMN_NAMES = Concurrent::Map.new # :nodoc:
|
|
8
10
|
QUOTED_TABLE_NAMES = Concurrent::Map.new # :nodoc:
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
module ClassMethods # :nodoc:
|
|
13
|
+
def column_name_matcher
|
|
14
|
+
/
|
|
15
|
+
\A
|
|
16
|
+
(
|
|
17
|
+
(?:
|
|
18
|
+
# "table_name"."column_name" | function(one or no argument)
|
|
19
|
+
((?:\w+\.|"\w+"\.)?(?:\w+|"\w+") | \w+\((?:|\g<2>)\))
|
|
20
|
+
)
|
|
21
|
+
(?:(?:\s+AS)?\s+(?:\w+|"\w+"))?
|
|
22
|
+
)
|
|
23
|
+
(?:\s*,\s*\g<1>)*
|
|
24
|
+
\z
|
|
25
|
+
/ix
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def column_name_with_order_matcher
|
|
29
|
+
/
|
|
30
|
+
\A
|
|
31
|
+
(
|
|
32
|
+
(?:
|
|
33
|
+
# "table_name"."column_name" | function(one or no argument)
|
|
34
|
+
((?:\w+\.|"\w+"\.)?(?:\w+|"\w+") | \w+\((?:|\g<2>)\))
|
|
35
|
+
)
|
|
36
|
+
(?:\s+COLLATE\s+(?:\w+|"\w+"))?
|
|
37
|
+
(?:\s+ASC|\s+DESC)?
|
|
38
|
+
)
|
|
39
|
+
(?:\s*,\s*\g<1>)*
|
|
40
|
+
\z
|
|
41
|
+
/ix
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def quote_column_name(name)
|
|
45
|
+
QUOTED_COLUMN_NAMES[name] ||= %Q("#{name.to_s.gsub('"', '""')}").freeze
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def quote_table_name(name)
|
|
49
|
+
QUOTED_TABLE_NAMES[name] ||= %Q("#{name.to_s.gsub('"', '""').gsub(".", "\".\"")}").freeze
|
|
50
|
+
end
|
|
12
51
|
end
|
|
13
52
|
|
|
14
|
-
def
|
|
15
|
-
|
|
53
|
+
def quote(value) # :nodoc:
|
|
54
|
+
case value
|
|
55
|
+
when Numeric
|
|
56
|
+
if value.finite?
|
|
57
|
+
super
|
|
58
|
+
else
|
|
59
|
+
"'#{value}'"
|
|
60
|
+
end
|
|
61
|
+
else
|
|
62
|
+
super
|
|
63
|
+
end
|
|
16
64
|
end
|
|
17
65
|
|
|
18
|
-
def
|
|
19
|
-
|
|
66
|
+
def quote_string(s)
|
|
67
|
+
::SQLite3::Database.quote(s)
|
|
20
68
|
end
|
|
21
69
|
|
|
22
|
-
def
|
|
23
|
-
|
|
70
|
+
def quote_table_name_for_assignment(table, attr)
|
|
71
|
+
quote_column_name(attr)
|
|
24
72
|
end
|
|
25
73
|
|
|
26
74
|
def quoted_time(value)
|
|
@@ -63,7 +111,7 @@ module ActiveRecord
|
|
|
63
111
|
|
|
64
112
|
def type_cast(value) # :nodoc:
|
|
65
113
|
case value
|
|
66
|
-
when BigDecimal
|
|
114
|
+
when BigDecimal, Rational
|
|
67
115
|
value.to_f
|
|
68
116
|
when String
|
|
69
117
|
if value.encoding == Encoding::ASCII_8BIT
|
|
@@ -75,43 +123,6 @@ module ActiveRecord
|
|
|
75
123
|
super
|
|
76
124
|
end
|
|
77
125
|
end
|
|
78
|
-
|
|
79
|
-
def column_name_matcher
|
|
80
|
-
COLUMN_NAME
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def column_name_with_order_matcher
|
|
84
|
-
COLUMN_NAME_WITH_ORDER
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
COLUMN_NAME = /
|
|
88
|
-
\A
|
|
89
|
-
(
|
|
90
|
-
(?:
|
|
91
|
-
# "table_name"."column_name" | function(one or no argument)
|
|
92
|
-
((?:\w+\.|"\w+"\.)?(?:\w+|"\w+") | \w+\((?:|\g<2>)\))
|
|
93
|
-
)
|
|
94
|
-
(?:(?:\s+AS)?\s+(?:\w+|"\w+"))?
|
|
95
|
-
)
|
|
96
|
-
(?:\s*,\s*\g<1>)*
|
|
97
|
-
\z
|
|
98
|
-
/ix
|
|
99
|
-
|
|
100
|
-
COLUMN_NAME_WITH_ORDER = /
|
|
101
|
-
\A
|
|
102
|
-
(
|
|
103
|
-
(?:
|
|
104
|
-
# "table_name"."column_name" | function(one or no argument)
|
|
105
|
-
((?:\w+\.|"\w+"\.)?(?:\w+|"\w+") | \w+\((?:|\g<2>)\))
|
|
106
|
-
)
|
|
107
|
-
(?:\s+COLLATE\s+(?:\w+|"\w+"))?
|
|
108
|
-
(?:\s+ASC|\s+DESC)?
|
|
109
|
-
)
|
|
110
|
-
(?:\s*,\s*\g<1>)*
|
|
111
|
-
\z
|
|
112
|
-
/ix
|
|
113
|
-
|
|
114
|
-
private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
|
|
115
126
|
end
|
|
116
127
|
end
|
|
117
128
|
end
|
|
@@ -5,6 +5,18 @@ module ActiveRecord
|
|
|
5
5
|
module SQLite3
|
|
6
6
|
class SchemaCreation < SchemaCreation # :nodoc:
|
|
7
7
|
private
|
|
8
|
+
def visit_AddForeignKey(o)
|
|
9
|
+
super.dup.tap do |sql|
|
|
10
|
+
sql << " DEFERRABLE INITIALLY #{o.options[:deferrable].to_s.upcase}" if o.deferrable
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def visit_ForeignKeyDefinition(o)
|
|
15
|
+
super.dup.tap do |sql|
|
|
16
|
+
sql << " DEFERRABLE INITIALLY #{o.deferrable.to_s.upcase}" if o.deferrable
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
8
20
|
def supports_index_using?
|
|
9
21
|
false
|
|
10
22
|
end
|
|
@@ -13,6 +25,16 @@ module ActiveRecord
|
|
|
13
25
|
if options[:collation]
|
|
14
26
|
sql << " COLLATE \"#{options[:collation]}\""
|
|
15
27
|
end
|
|
28
|
+
|
|
29
|
+
if as = options[:as]
|
|
30
|
+
sql << " GENERATED ALWAYS AS (#{as})"
|
|
31
|
+
|
|
32
|
+
if options[:stored]
|
|
33
|
+
sql << " STORED"
|
|
34
|
+
else
|
|
35
|
+
sql << " VIRTUAL"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
16
38
|
super
|
|
17
39
|
end
|
|
18
40
|
end
|
|
@@ -16,10 +16,23 @@ module ActiveRecord
|
|
|
16
16
|
end
|
|
17
17
|
alias :belongs_to :references
|
|
18
18
|
|
|
19
|
+
def new_column_definition(name, type, **options) # :nodoc:
|
|
20
|
+
case type
|
|
21
|
+
when :virtual
|
|
22
|
+
type = options[:type]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
super
|
|
26
|
+
end
|
|
27
|
+
|
|
19
28
|
private
|
|
20
29
|
def integer_like_primary_key_type(type, options)
|
|
21
30
|
:primary_key
|
|
22
31
|
end
|
|
32
|
+
|
|
33
|
+
def valid_column_definition_options
|
|
34
|
+
super + [:as, :type, :stored]
|
|
35
|
+
end
|
|
23
36
|
end
|
|
24
37
|
end
|
|
25
38
|
end
|
|
@@ -12,6 +12,22 @@ module ActiveRecord
|
|
|
12
12
|
def explicit_primary_key_default?(column)
|
|
13
13
|
column.bigint?
|
|
14
14
|
end
|
|
15
|
+
|
|
16
|
+
def prepare_column_options(column)
|
|
17
|
+
spec = super
|
|
18
|
+
|
|
19
|
+
if @connection.supports_virtual_columns? && column.virtual?
|
|
20
|
+
spec[:as] = extract_expression_for_virtual_column(column)
|
|
21
|
+
spec[:stored] = column.virtual_stored?
|
|
22
|
+
spec = { type: schema_type(column).inspect }.merge!(spec)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
spec
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def extract_expression_for_virtual_column(column)
|
|
29
|
+
column.default_function.inspect
|
|
30
|
+
end
|
|
15
31
|
end
|
|
16
32
|
end
|
|
17
33
|
end
|
|
@@ -53,6 +53,8 @@ module ActiveRecord
|
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
def add_foreign_key(from_table, to_table, **options)
|
|
56
|
+
assert_valid_deferrable(options[:deferrable])
|
|
57
|
+
|
|
56
58
|
alter_table(from_table) do |definition|
|
|
57
59
|
to_table = strip_table_name_prefix_and_suffix(to_table)
|
|
58
60
|
definition.foreign_key(to_table, **options)
|
|
@@ -72,6 +74,7 @@ module ActiveRecord
|
|
|
72
74
|
Base.pluralize_table_names ? table.pluralize : table
|
|
73
75
|
end
|
|
74
76
|
table = strip_table_name_prefix_and_suffix(table)
|
|
77
|
+
options = options.slice(*fk.options.keys)
|
|
75
78
|
fk_to_table = strip_table_name_prefix_and_suffix(fk.to_table)
|
|
76
79
|
fk_to_table == table && options.all? { |k, v| fk.options[k].to_s == v.to_s }
|
|
77
80
|
end || raise(ArgumentError, "Table '#{from_table}' has no foreign key for #{to_table || options}")
|
|
@@ -137,7 +140,14 @@ module ActiveRecord
|
|
|
137
140
|
|
|
138
141
|
type_metadata = fetch_type_metadata(field["type"])
|
|
139
142
|
default_value = extract_value_from_default(default)
|
|
140
|
-
|
|
143
|
+
generated_type = extract_generated_type(field)
|
|
144
|
+
|
|
145
|
+
if generated_type.present?
|
|
146
|
+
default_function = default
|
|
147
|
+
else
|
|
148
|
+
default_function = extract_default_function(default_value, default)
|
|
149
|
+
end
|
|
150
|
+
|
|
141
151
|
rowid = is_column_the_rowid?(field, definitions)
|
|
142
152
|
|
|
143
153
|
Column.new(
|
|
@@ -148,7 +158,8 @@ module ActiveRecord
|
|
|
148
158
|
default_function,
|
|
149
159
|
collation: field["collation"],
|
|
150
160
|
auto_increment: field["auto_increment"],
|
|
151
|
-
rowid: rowid
|
|
161
|
+
rowid: rowid,
|
|
162
|
+
generated_type: generated_type
|
|
152
163
|
)
|
|
153
164
|
end
|
|
154
165
|
|
|
@@ -185,6 +196,19 @@ module ActiveRecord
|
|
|
185
196
|
scope[:type] = type if type
|
|
186
197
|
scope
|
|
187
198
|
end
|
|
199
|
+
|
|
200
|
+
def assert_valid_deferrable(deferrable)
|
|
201
|
+
return if !deferrable || %i(immediate deferred).include?(deferrable)
|
|
202
|
+
|
|
203
|
+
raise ArgumentError, "deferrable must be `:immediate` or `:deferred`, got: `#{deferrable.inspect}`"
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def extract_generated_type(field)
|
|
207
|
+
case field["hidden"]
|
|
208
|
+
when 2 then :virtual
|
|
209
|
+
when 3 then :stored
|
|
210
|
+
end
|
|
211
|
+
end
|
|
188
212
|
end
|
|
189
213
|
end
|
|
190
214
|
end
|