activerecord 6.1.7 → 7.1.5
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 +2030 -1020
- data/MIT-LICENSE +1 -1
- data/README.rdoc +18 -18
- data/lib/active_record/aggregations.rb +17 -14
- data/lib/active_record/association_relation.rb +1 -11
- data/lib/active_record/associations/association.rb +51 -19
- data/lib/active_record/associations/association_scope.rb +17 -12
- data/lib/active_record/associations/belongs_to_association.rb +28 -9
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
- data/lib/active_record/associations/builder/association.rb +11 -5
- data/lib/active_record/associations/builder/belongs_to.rb +40 -14
- data/lib/active_record/associations/builder/collection_association.rb +10 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
- data/lib/active_record/associations/builder/has_many.rb +3 -2
- data/lib/active_record/associations/builder/has_one.rb +2 -1
- data/lib/active_record/associations/builder/singular_association.rb +6 -2
- data/lib/active_record/associations/collection_association.rb +39 -35
- data/lib/active_record/associations/collection_proxy.rb +30 -15
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +28 -18
- data/lib/active_record/associations/has_many_through_association.rb +12 -7
- data/lib/active_record/associations/has_one_association.rb +20 -10
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +3 -2
- data/lib/active_record/associations/join_dependency.rb +28 -20
- data/lib/active_record/associations/preloader/association.rb +210 -52
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +50 -14
- data/lib/active_record/associations/preloader.rb +50 -121
- data/lib/active_record/associations/singular_association.rb +9 -3
- data/lib/active_record/associations/through_association.rb +25 -14
- data/lib/active_record/associations.rb +446 -306
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +1 -3
- data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
- data/lib/active_record/attribute_methods/dirty.rb +73 -22
- data/lib/active_record/attribute_methods/primary_key.rb +78 -26
- data/lib/active_record/attribute_methods/query.rb +31 -19
- data/lib/active_record/attribute_methods/read.rb +27 -12
- data/lib/active_record/attribute_methods/serialization.rb +194 -37
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +8 -3
- data/lib/active_record/attribute_methods/write.rb +12 -15
- data/lib/active_record/attribute_methods.rb +161 -40
- data/lib/active_record/attributes.rb +27 -38
- data/lib/active_record/autosave_association.rb +65 -31
- data/lib/active_record/base.rb +25 -2
- data/lib/active_record/callbacks.rb +18 -34
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -46
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +367 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +78 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +113 -597
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +172 -50
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +87 -73
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +367 -141
- data/lib/active_record/connection_adapters/abstract/transaction.rb +281 -59
- data/lib/active_record/connection_adapters/abstract_adapter.rb +631 -150
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +317 -164
- data/lib/active_record/connection_adapters/column.rb +13 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +25 -134
- data/lib/active_record/connection_adapters/mysql/quoting.rb +56 -25
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +39 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +151 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +112 -55
- data/lib/active_record/connection_adapters/pool_config.rb +20 -11
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +89 -52
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +12 -3
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -56
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +153 -3
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +397 -75
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +508 -246
- data/lib/active_record/connection_adapters/schema_cache.rb +319 -90
- data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +72 -53
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +37 -21
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -22
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +296 -104
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +258 -0
- data/lib/active_record/connection_adapters.rb +9 -6
- data/lib/active_record/connection_handling.rb +108 -137
- data/lib/active_record/core.rb +242 -233
- data/lib/active_record/counter_cache.rb +52 -27
- data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -2
- data/lib/active_record/database_configurations/database_config.rb +21 -12
- data/lib/active_record/database_configurations/hash_config.rb +88 -16
- data/lib/active_record/database_configurations/url_config.rb +18 -12
- data/lib/active_record/database_configurations.rb +95 -59
- data/lib/active_record/delegated_type.rb +66 -20
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +4 -2
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +1 -1
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +68 -0
- data/lib/active_record/encryption/configurable.rb +60 -0
- data/lib/active_record/encryption/context.rb +42 -0
- data/lib/active_record/encryption/contexts.rb +76 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +230 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +155 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +155 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +53 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_serializer.rb +92 -0
- data/lib/active_record/encryption/null_encryptor.rb +21 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
- data/lib/active_record/encryption/scheme.rb +100 -0
- data/lib/active_record/encryption.rb +58 -0
- data/lib/active_record/enum.rb +154 -63
- data/lib/active_record/errors.rb +172 -15
- data/lib/active_record/explain.rb +23 -3
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +15 -1
- data/lib/active_record/fixture_set/model_metadata.rb +14 -4
- data/lib/active_record/fixture_set/render_context.rb +2 -0
- data/lib/active_record/fixture_set/table_row.rb +70 -14
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +147 -86
- data/lib/active_record/future_result.rb +174 -0
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +81 -29
- data/lib/active_record/insert_all.rb +135 -22
- data/lib/active_record/integration.rb +11 -10
- data/lib/active_record/internal_metadata.rb +119 -33
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +37 -22
- data/lib/active_record/locking/pessimistic.rb +15 -6
- data/lib/active_record/log_subscriber.rb +52 -19
- data/lib/active_record/marshalling.rb +59 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +10 -10
- data/lib/active_record/middleware/database_selector.rb +23 -13
- data/lib/active_record/middleware/shard_selector.rb +62 -0
- data/lib/active_record/migration/command_recorder.rb +112 -14
- data/lib/active_record/migration/compatibility.rb +233 -46
- data/lib/active_record/migration/default_strategy.rb +23 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +361 -173
- data/lib/active_record/model_schema.rb +125 -101
- data/lib/active_record/nested_attributes.rb +50 -20
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/normalization.rb +167 -0
- data/lib/active_record/persistence.rb +409 -88
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +4 -22
- data/lib/active_record/query_logs.rb +174 -0
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +29 -6
- data/lib/active_record/railtie.rb +220 -44
- data/lib/active_record/railties/controller_runtime.rb +15 -10
- data/lib/active_record/railties/databases.rake +188 -252
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +41 -3
- data/lib/active_record/reflection.rb +248 -81
- data/lib/active_record/relation/batches/batch_enumerator.rb +23 -7
- data/lib/active_record/relation/batches.rb +192 -63
- data/lib/active_record/relation/calculations.rb +246 -90
- data/lib/active_record/relation/delegation.rb +28 -14
- data/lib/active_record/relation/finder_methods.rb +108 -51
- data/lib/active_record/relation/merger.rb +22 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -3
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +27 -20
- data/lib/active_record/relation/query_attribute.rb +30 -12
- data/lib/active_record/relation/query_methods.rb +670 -129
- data/lib/active_record/relation/record_fetch_warning.rb +7 -9
- data/lib/active_record/relation/spawn_methods.rb +20 -3
- data/lib/active_record/relation/where_clause.rb +10 -19
- data/lib/active_record/relation.rb +287 -120
- data/lib/active_record/result.rb +37 -11
- data/lib/active_record/runtime_registry.rb +32 -13
- data/lib/active_record/sanitization.rb +65 -20
- data/lib/active_record/schema.rb +36 -22
- data/lib/active_record/schema_dumper.rb +73 -24
- data/lib/active_record/schema_migration.rb +68 -33
- data/lib/active_record/scoping/default.rb +72 -15
- data/lib/active_record/scoping/named.rb +5 -13
- data/lib/active_record/scoping.rb +65 -34
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/serialization.rb +6 -1
- data/lib/active_record/signed_id.rb +10 -8
- data/lib/active_record/store.rb +10 -10
- data/lib/active_record/suppressor.rb +13 -15
- data/lib/active_record/table_metadata.rb +16 -3
- data/lib/active_record/tasks/database_tasks.rb +251 -140
- data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
- data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
- data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +117 -96
- data/lib/active_record/timestamp.rb +32 -19
- data/lib/active_record/token_for.rb +113 -0
- data/lib/active_record/touch_later.rb +11 -6
- data/lib/active_record/transactions.rb +48 -27
- data/lib/active_record/translation.rb +3 -3
- data/lib/active_record/type/adapter_specific_registry.rb +32 -14
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +9 -5
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/type/type_map.rb +17 -20
- data/lib/active_record/type.rb +1 -2
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +4 -4
- data/lib/active_record/validations/numericality.rb +5 -4
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +51 -6
- data/lib/active_record/validations.rb +8 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +335 -32
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/crud.rb +28 -22
- data/lib/arel/delete_manager.rb +18 -4
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/and.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -1
- data/lib/arel/nodes/bound_sql_literal.rb +61 -0
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/delete_statement.rb +12 -13
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/homogeneous_in.rb +1 -9
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/node.rb +111 -2
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +6 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes/update_statement.rb +8 -3
- data/lib/arel/nodes.rb +5 -0
- data/lib/arel/predications.rb +13 -3
- data/lib/arel/select_manager.rb +10 -4
- data/lib/arel/table.rb +9 -6
- data/lib/arel/tree_manager.rb +5 -13
- data/lib/arel/update_manager.rb +18 -4
- data/lib/arel/visitors/dot.rb +80 -90
- data/lib/arel/visitors/mysql.rb +16 -3
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +141 -20
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +18 -3
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration.rb +3 -1
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
- data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
- data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
- metadata +96 -16
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -67
data/lib/active_record/result.rb
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
###
|
5
|
+
# = Active Record \Result
|
6
|
+
#
|
5
7
|
# This class encapsulates a result returned from calling
|
6
8
|
# {#exec_query}[rdoc-ref:ConnectionAdapters::DatabaseStatements#exec_query]
|
7
9
|
# on any database connection adapter. For example:
|
@@ -36,6 +38,14 @@ module ActiveRecord
|
|
36
38
|
|
37
39
|
attr_reader :columns, :rows, :column_types
|
38
40
|
|
41
|
+
def self.empty(async: false) # :nodoc:
|
42
|
+
if async
|
43
|
+
EMPTY_ASYNC
|
44
|
+
else
|
45
|
+
EMPTY
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
39
49
|
def initialize(columns, rows, column_types = {})
|
40
50
|
@columns = columns
|
41
51
|
@rows = rows
|
@@ -57,19 +67,14 @@ module ActiveRecord
|
|
57
67
|
# row as parameter.
|
58
68
|
#
|
59
69
|
# Returns an +Enumerator+ if no block is given.
|
60
|
-
def each
|
70
|
+
def each(&block)
|
61
71
|
if block_given?
|
62
|
-
hash_rows.each
|
72
|
+
hash_rows.each(&block)
|
63
73
|
else
|
64
74
|
hash_rows.to_enum { @rows.size }
|
65
75
|
end
|
66
76
|
end
|
67
77
|
|
68
|
-
alias :map! :map
|
69
|
-
alias :collect! :map
|
70
|
-
deprecate "map!": :map
|
71
|
-
deprecate "collect!": :map
|
72
|
-
|
73
78
|
# Returns true if there are no records, otherwise false.
|
74
79
|
def empty?
|
75
80
|
rows.empty?
|
@@ -91,6 +96,14 @@ module ActiveRecord
|
|
91
96
|
n ? hash_rows.last(n) : hash_rows.last
|
92
97
|
end
|
93
98
|
|
99
|
+
def result # :nodoc:
|
100
|
+
self
|
101
|
+
end
|
102
|
+
|
103
|
+
def cancel # :nodoc:
|
104
|
+
self
|
105
|
+
end
|
106
|
+
|
94
107
|
def cast_values(type_overrides = {}) # :nodoc:
|
95
108
|
if columns.one?
|
96
109
|
# Separated to avoid allocating an array per row
|
@@ -98,7 +111,7 @@ module ActiveRecord
|
|
98
111
|
type = if type_overrides.is_a?(Array)
|
99
112
|
type_overrides.first
|
100
113
|
else
|
101
|
-
column_type(columns.first, type_overrides)
|
114
|
+
column_type(columns.first, 0, type_overrides)
|
102
115
|
end
|
103
116
|
|
104
117
|
rows.map do |(value)|
|
@@ -108,7 +121,7 @@ module ActiveRecord
|
|
108
121
|
types = if type_overrides.is_a?(Array)
|
109
122
|
type_overrides
|
110
123
|
else
|
111
|
-
columns.map { |name| column_type(name, type_overrides) }
|
124
|
+
columns.map.with_index { |name, i| column_type(name, i, type_overrides) }
|
112
125
|
end
|
113
126
|
|
114
127
|
rows.map do |values|
|
@@ -124,10 +137,17 @@ module ActiveRecord
|
|
124
137
|
@hash_rows = nil
|
125
138
|
end
|
126
139
|
|
140
|
+
def freeze # :nodoc:
|
141
|
+
hash_rows.freeze
|
142
|
+
super
|
143
|
+
end
|
144
|
+
|
127
145
|
private
|
128
|
-
def column_type(name, type_overrides
|
146
|
+
def column_type(name, index, type_overrides)
|
129
147
|
type_overrides.fetch(name) do
|
130
|
-
column_types.fetch(
|
148
|
+
column_types.fetch(index) do
|
149
|
+
column_types.fetch(name, Type.default_value)
|
150
|
+
end
|
131
151
|
end
|
132
152
|
end
|
133
153
|
|
@@ -171,5 +191,11 @@ module ActiveRecord
|
|
171
191
|
}
|
172
192
|
end
|
173
193
|
end
|
194
|
+
|
195
|
+
EMPTY = new([].freeze, [].freeze, {}.freeze).freeze
|
196
|
+
private_constant :EMPTY
|
197
|
+
|
198
|
+
EMPTY_ASYNC = FutureResult.wrap(EMPTY).freeze
|
199
|
+
private_constant :EMPTY_ASYNC
|
174
200
|
end
|
175
201
|
end
|
@@ -1,24 +1,43 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/per_thread_registry"
|
4
|
-
|
5
3
|
module ActiveRecord
|
6
4
|
# This is a thread locals registry for Active Record. For example:
|
7
5
|
#
|
8
|
-
# ActiveRecord::RuntimeRegistry.
|
9
|
-
#
|
10
|
-
# returns the connection handler local to the current thread.
|
6
|
+
# ActiveRecord::RuntimeRegistry.sql_runtime
|
11
7
|
#
|
12
|
-
#
|
13
|
-
|
14
|
-
|
15
|
-
|
8
|
+
# returns the connection handler local to the current unit of execution (either thread of fiber).
|
9
|
+
module RuntimeRegistry # :nodoc:
|
10
|
+
extend self
|
11
|
+
|
12
|
+
def sql_runtime
|
13
|
+
ActiveSupport::IsolatedExecutionState[:active_record_sql_runtime] ||= 0.0
|
14
|
+
end
|
16
15
|
|
17
|
-
|
16
|
+
def sql_runtime=(runtime)
|
17
|
+
ActiveSupport::IsolatedExecutionState[:active_record_sql_runtime] = runtime
|
18
|
+
end
|
19
|
+
|
20
|
+
def async_sql_runtime
|
21
|
+
ActiveSupport::IsolatedExecutionState[:active_record_async_sql_runtime] ||= 0.0
|
22
|
+
end
|
18
23
|
|
19
|
-
|
20
|
-
|
21
|
-
class_eval %{ def self.#{val}=(x); instance.#{val}=x; end }, __FILE__, __LINE__
|
24
|
+
def async_sql_runtime=(runtime)
|
25
|
+
ActiveSupport::IsolatedExecutionState[:active_record_async_sql_runtime] = runtime
|
22
26
|
end
|
27
|
+
|
28
|
+
def reset
|
29
|
+
rt, self.sql_runtime = sql_runtime, 0.0
|
30
|
+
self.async_sql_runtime = 0.0
|
31
|
+
rt
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
ActiveSupport::Notifications.monotonic_subscribe("sql.active_record") do |name, start, finish, id, payload|
|
37
|
+
runtime = (finish - start) * 1_000.0
|
38
|
+
|
39
|
+
if payload[:async]
|
40
|
+
ActiveRecord::RuntimeRegistry.async_sql_runtime += (runtime - payload[:lock_wait])
|
23
41
|
end
|
42
|
+
ActiveRecord::RuntimeRegistry.sql_runtime += runtime
|
24
43
|
end
|
@@ -5,8 +5,8 @@ module ActiveRecord
|
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
7
|
module ClassMethods
|
8
|
-
# Accepts an array
|
9
|
-
#
|
8
|
+
# Accepts an array of SQL conditions and sanitizes them into a valid
|
9
|
+
# SQL fragment for a WHERE clause.
|
10
10
|
#
|
11
11
|
# sanitize_sql_for_conditions(["name=? and group_id=?", "foo'bar", 4])
|
12
12
|
# # => "name='foo''bar' and group_id=4"
|
@@ -17,8 +17,19 @@ module ActiveRecord
|
|
17
17
|
# sanitize_sql_for_conditions(["name='%s' and group_id='%s'", "foo'bar", 4])
|
18
18
|
# # => "name='foo''bar' and group_id='4'"
|
19
19
|
#
|
20
|
+
# This method will NOT sanitize a SQL string since it won't contain
|
21
|
+
# any conditions in it and will return the string as is.
|
22
|
+
#
|
20
23
|
# sanitize_sql_for_conditions("name='foo''bar' and group_id='4'")
|
21
24
|
# # => "name='foo''bar' and group_id='4'"
|
25
|
+
#
|
26
|
+
# Note that this sanitization method is not schema-aware, hence won't do any type casting
|
27
|
+
# and will directly use the database adapter's +quote+ method.
|
28
|
+
# For MySQL specifically this means that numeric parameters will be quoted as strings
|
29
|
+
# to prevent query manipulation attacks.
|
30
|
+
#
|
31
|
+
# sanitize_sql_for_conditions(["role = ?", 0])
|
32
|
+
# # => "role = '0'"
|
22
33
|
def sanitize_sql_for_conditions(condition)
|
23
34
|
return nil if condition.blank?
|
24
35
|
|
@@ -29,8 +40,8 @@ module ActiveRecord
|
|
29
40
|
end
|
30
41
|
alias :sanitize_sql :sanitize_sql_for_conditions
|
31
42
|
|
32
|
-
# Accepts an array
|
33
|
-
#
|
43
|
+
# Accepts an array or hash of SQL conditions and sanitizes them into
|
44
|
+
# a valid SQL fragment for a SET clause.
|
34
45
|
#
|
35
46
|
# sanitize_sql_for_assignment(["name=? and group_id=?", nil, 4])
|
36
47
|
# # => "name=NULL and group_id=4"
|
@@ -41,8 +52,19 @@ module ActiveRecord
|
|
41
52
|
# Post.sanitize_sql_for_assignment({ name: nil, group_id: 4 })
|
42
53
|
# # => "`posts`.`name` = NULL, `posts`.`group_id` = 4"
|
43
54
|
#
|
55
|
+
# This method will NOT sanitize a SQL string since it won't contain
|
56
|
+
# any conditions in it and will return the string as is.
|
57
|
+
#
|
44
58
|
# sanitize_sql_for_assignment("name=NULL and group_id='4'")
|
45
59
|
# # => "name=NULL and group_id='4'"
|
60
|
+
#
|
61
|
+
# Note that this sanitization method is not schema-aware, hence won't do any type casting
|
62
|
+
# and will directly use the database adapter's +quote+ method.
|
63
|
+
# For MySQL specifically this means that numeric parameters will be quoted as strings
|
64
|
+
# to prevent query manipulation attacks.
|
65
|
+
#
|
66
|
+
# sanitize_sql_for_assignment(["role = ?", 0])
|
67
|
+
# # => "role = '0'"
|
46
68
|
def sanitize_sql_for_assignment(assignments, default_table_name = table_name)
|
47
69
|
case assignments
|
48
70
|
when Array; sanitize_sql_array(assignments)
|
@@ -54,7 +76,7 @@ module ActiveRecord
|
|
54
76
|
# Accepts an array, or string of SQL conditions and sanitizes
|
55
77
|
# them into a valid SQL fragment for an ORDER clause.
|
56
78
|
#
|
57
|
-
# sanitize_sql_for_order(["field(id, ?)", [1,3,2]])
|
79
|
+
# sanitize_sql_for_order([Arel.sql("field(id, ?)"), [1,3,2]])
|
58
80
|
# # => "field(id, 1,3,2)"
|
59
81
|
#
|
60
82
|
# sanitize_sql_for_order("id ASC")
|
@@ -92,26 +114,32 @@ module ActiveRecord
|
|
92
114
|
end
|
93
115
|
|
94
116
|
# Sanitizes a +string+ so that it is safe to use within an SQL
|
95
|
-
# LIKE statement. This method uses +escape_character+ to escape all
|
117
|
+
# LIKE statement. This method uses +escape_character+ to escape all
|
118
|
+
# occurrences of itself, "_" and "%".
|
96
119
|
#
|
97
|
-
# sanitize_sql_like("100%")
|
98
|
-
# # => "100\\%"
|
120
|
+
# sanitize_sql_like("100% true!")
|
121
|
+
# # => "100\\% true!"
|
99
122
|
#
|
100
123
|
# sanitize_sql_like("snake_cased_string")
|
101
124
|
# # => "snake\\_cased\\_string"
|
102
125
|
#
|
103
|
-
# sanitize_sql_like("100%", "!")
|
104
|
-
# # => "100!%"
|
126
|
+
# sanitize_sql_like("100% true!", "!")
|
127
|
+
# # => "100!% true!!"
|
105
128
|
#
|
106
129
|
# sanitize_sql_like("snake_cased_string", "!")
|
107
130
|
# # => "snake!_cased!_string"
|
108
131
|
def sanitize_sql_like(string, escape_character = "\\")
|
109
|
-
|
110
|
-
|
132
|
+
if string.include?(escape_character) && escape_character != "%" && escape_character != "_"
|
133
|
+
string = string.gsub(escape_character, '\0\0')
|
134
|
+
end
|
135
|
+
|
136
|
+
string.gsub(/(?=[%_])/, escape_character)
|
111
137
|
end
|
112
138
|
|
113
139
|
# Accepts an array of conditions. The array has each value
|
114
|
-
# sanitized and interpolated into the SQL statement.
|
140
|
+
# sanitized and interpolated into the SQL statement. If using named bind
|
141
|
+
# variables in SQL statements where a colon is required verbatim use a
|
142
|
+
# backslash to escape.
|
115
143
|
#
|
116
144
|
# sanitize_sql_array(["name=? and group_id=?", "foo'bar", 4])
|
117
145
|
# # => "name='foo''bar' and group_id=4"
|
@@ -119,8 +147,19 @@ module ActiveRecord
|
|
119
147
|
# sanitize_sql_array(["name=:name and group_id=:group_id", name: "foo'bar", group_id: 4])
|
120
148
|
# # => "name='foo''bar' and group_id=4"
|
121
149
|
#
|
150
|
+
# sanitize_sql_array(["TO_TIMESTAMP(:date, 'YYYY/MM/DD HH12\\:MI\\:SS')", date: "foo"])
|
151
|
+
# # => "TO_TIMESTAMP('foo', 'YYYY/MM/DD HH12:MI:SS')"
|
152
|
+
#
|
122
153
|
# sanitize_sql_array(["name='%s' and group_id='%s'", "foo'bar", 4])
|
123
154
|
# # => "name='foo''bar' and group_id='4'"
|
155
|
+
#
|
156
|
+
# Note that this sanitization method is not schema-aware, hence won't do any type casting
|
157
|
+
# and will directly use the database adapter's +quote+ method.
|
158
|
+
# For MySQL specifically this means that numeric parameters will be quoted as strings
|
159
|
+
# to prevent query manipulation attacks.
|
160
|
+
#
|
161
|
+
# sanitize_sql_array(["role = ?", 0])
|
162
|
+
# # => "role = '0'"
|
124
163
|
def sanitize_sql_array(ary)
|
125
164
|
statement, *values = ary
|
126
165
|
if values.first.is_a?(Hash) && /:\w+/.match?(statement)
|
@@ -137,14 +176,18 @@ module ActiveRecord
|
|
137
176
|
def disallow_raw_sql!(args, permit: connection.column_name_matcher) # :nodoc:
|
138
177
|
unexpected = nil
|
139
178
|
args.each do |arg|
|
140
|
-
next if arg.is_a?(Symbol) || Arel.arel_node?(arg) || permit.match?(arg.to_s)
|
179
|
+
next if arg.is_a?(Symbol) || Arel.arel_node?(arg) || permit.match?(arg.to_s.strip)
|
141
180
|
(unexpected ||= []) << arg
|
142
181
|
end
|
143
182
|
|
144
183
|
if unexpected
|
145
184
|
raise(ActiveRecord::UnknownAttributeReference,
|
146
|
-
"
|
147
|
-
|
185
|
+
"Dangerous query method (method whose arguments are used as raw " \
|
186
|
+
"SQL) called with non-attribute argument(s): " \
|
187
|
+
"#{unexpected.map(&:inspect).join(", ")}." \
|
188
|
+
"This method should not be called with user-provided values, such as request " \
|
189
|
+
"parameters or model attributes. Known-safe values can be passed " \
|
190
|
+
"by wrapping them in Arel.sql()."
|
148
191
|
)
|
149
192
|
end
|
150
193
|
end
|
@@ -168,9 +211,11 @@ module ActiveRecord
|
|
168
211
|
end
|
169
212
|
|
170
213
|
def replace_named_bind_variables(statement, bind_vars)
|
171
|
-
statement.gsub(/(
|
214
|
+
statement.gsub(/([:\\]?):([a-zA-Z]\w*)/) do |match|
|
172
215
|
if $1 == ":" # skip postgresql casts
|
173
216
|
match # return the whole match
|
217
|
+
elsif $1 == "\\" # escaped literal colon
|
218
|
+
match[1..-1] # return match with escaping backlash char removed
|
174
219
|
elsif bind_vars.include?(match = $2.to_sym)
|
175
220
|
replace_bind_variable(bind_vars[match])
|
176
221
|
else
|
@@ -183,13 +228,13 @@ module ActiveRecord
|
|
183
228
|
if value.respond_to?(:map) && !value.acts_like?(:string)
|
184
229
|
values = value.map { |v| v.respond_to?(:id_for_database) ? v.id_for_database : v }
|
185
230
|
if values.empty?
|
186
|
-
c.quote(nil)
|
231
|
+
c.quote(c.cast_bound_value(nil))
|
187
232
|
else
|
188
|
-
values.map! { |v| c.quote(v) }.join(",")
|
233
|
+
values.map! { |v| c.quote(c.cast_bound_value(v)) }.join(",")
|
189
234
|
end
|
190
235
|
else
|
191
236
|
value = value.id_for_database if value.respond_to?(:id_for_database)
|
192
|
-
c.quote(value)
|
237
|
+
c.quote(c.cast_bound_value(value))
|
193
238
|
end
|
194
239
|
end
|
195
240
|
|
data/lib/active_record/schema.rb
CHANGED
@@ -10,7 +10,7 @@ module ActiveRecord
|
|
10
10
|
#
|
11
11
|
# Usage:
|
12
12
|
#
|
13
|
-
# ActiveRecord::Schema.define do
|
13
|
+
# ActiveRecord::Schema[7.0].define do
|
14
14
|
# create_table :authors do |t|
|
15
15
|
# t.string :name, null: false
|
16
16
|
# end
|
@@ -30,32 +30,46 @@ module ActiveRecord
|
|
30
30
|
# ActiveRecord::Schema is only supported by database adapters that also
|
31
31
|
# support migrations, the two features being very similar.
|
32
32
|
class Schema < Migration::Current
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
33
|
+
module Definition
|
34
|
+
extend ActiveSupport::Concern
|
35
|
+
|
36
|
+
module ClassMethods
|
37
|
+
# Eval the given block. All methods available to the current connection
|
38
|
+
# adapter are available within the block, so you can easily use the
|
39
|
+
# database definition DSL to build up your schema (
|
40
|
+
# {create_table}[rdoc-ref:ConnectionAdapters::SchemaStatements#create_table],
|
41
|
+
# {add_index}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_index], etc.).
|
42
|
+
#
|
43
|
+
# The +info+ hash is optional, and if given is used to define metadata
|
44
|
+
# about the current schema (currently, only the schema's version):
|
45
|
+
#
|
46
|
+
# ActiveRecord::Schema[7.0].define(version: 2038_01_19_000001) do
|
47
|
+
# ...
|
48
|
+
# end
|
49
|
+
def define(info = {}, &block)
|
50
|
+
new.define(info, &block)
|
51
|
+
end
|
52
|
+
end
|
48
53
|
|
49
|
-
|
50
|
-
|
54
|
+
def define(info, &block) # :nodoc:
|
55
|
+
instance_eval(&block)
|
51
56
|
|
52
|
-
if info[:version].present?
|
53
57
|
connection.schema_migration.create_table
|
54
|
-
|
58
|
+
if info[:version].present?
|
59
|
+
connection.assume_migrated_upto_version(info[:version])
|
60
|
+
end
|
61
|
+
|
62
|
+
connection.internal_metadata.create_table_and_set_flags(connection.migration_context.current_environment)
|
55
63
|
end
|
64
|
+
end
|
65
|
+
|
66
|
+
include Definition
|
56
67
|
|
57
|
-
|
58
|
-
|
68
|
+
def self.[](version)
|
69
|
+
@class_for_version ||= {}
|
70
|
+
@class_for_version[version] ||= Class.new(Migration::Compatibility.find(version)) do
|
71
|
+
include Definition
|
72
|
+
end
|
59
73
|
end
|
60
74
|
end
|
61
75
|
end
|
@@ -7,14 +7,13 @@ module ActiveRecord
|
|
7
7
|
#
|
8
8
|
# This class is used to dump the database schema for some connection to some
|
9
9
|
# output format (i.e., ActiveRecord::Schema).
|
10
|
-
class SchemaDumper
|
10
|
+
class SchemaDumper # :nodoc:
|
11
11
|
private_class_method :new
|
12
12
|
|
13
13
|
##
|
14
14
|
# :singleton-method:
|
15
15
|
# A list of tables which should not be dumped to the schema.
|
16
|
-
# Acceptable values are strings
|
17
|
-
# Only strings are accepted if ActiveRecord::Base.schema_format == :sql.
|
16
|
+
# Acceptable values are strings and regexps.
|
18
17
|
cattr_accessor :ignore_tables, default: []
|
19
18
|
|
20
19
|
##
|
@@ -29,6 +28,18 @@ module ActiveRecord
|
|
29
28
|
# should not be dumped to db/schema.rb.
|
30
29
|
cattr_accessor :chk_ignore_pattern, default: /^chk_rails_[0-9a-f]{10}$/
|
31
30
|
|
31
|
+
##
|
32
|
+
# :singleton-method:
|
33
|
+
# Specify a custom regular expression matching exclusion constraints which name
|
34
|
+
# should not be dumped to db/schema.rb.
|
35
|
+
cattr_accessor :excl_ignore_pattern, default: /^excl_rails_[0-9a-f]{10}$/
|
36
|
+
|
37
|
+
##
|
38
|
+
# :singleton-method:
|
39
|
+
# Specify a custom regular expression matching unique constraints which name
|
40
|
+
# should not be dumped to db/schema.rb.
|
41
|
+
cattr_accessor :unique_ignore_pattern, default: /^uniq_rails_[0-9a-f]{10}$/
|
42
|
+
|
32
43
|
class << self
|
33
44
|
def dump(connection = ActiveRecord::Base.connection, stream = STDOUT, config = ActiveRecord::Base)
|
34
45
|
connection.create_schema_dumper(generate_options(config)).dump(stream)
|
@@ -46,7 +57,9 @@ module ActiveRecord
|
|
46
57
|
|
47
58
|
def dump(stream)
|
48
59
|
header(stream)
|
60
|
+
schemas(stream)
|
49
61
|
extensions(stream)
|
62
|
+
types(stream)
|
50
63
|
tables(stream)
|
51
64
|
trailer(stream)
|
52
65
|
stream
|
@@ -59,6 +72,11 @@ module ActiveRecord
|
|
59
72
|
@connection = connection
|
60
73
|
@version = connection.migration_context.current_version rescue nil
|
61
74
|
@options = options
|
75
|
+
@ignore_tables = [
|
76
|
+
ActiveRecord::Base.schema_migrations_table_name,
|
77
|
+
ActiveRecord::Base.internal_metadata_table_name,
|
78
|
+
self.class.ignore_tables
|
79
|
+
].flatten
|
62
80
|
end
|
63
81
|
|
64
82
|
# turns 20170404131909 into "2017_04_04_131909"
|
@@ -73,22 +91,21 @@ module ActiveRecord
|
|
73
91
|
end
|
74
92
|
|
75
93
|
def header(stream)
|
76
|
-
stream.puts
|
77
|
-
# This file is auto-generated from the current state of the database. Instead
|
78
|
-
# of editing this file, please use the migrations feature of Active Record to
|
79
|
-
# incrementally modify your database, and then regenerate this schema definition.
|
80
|
-
#
|
81
|
-
# This file is the source Rails uses to define your schema when running `bin/rails
|
82
|
-
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
|
83
|
-
# be faster and is potentially less error prone than running all of your
|
84
|
-
# migrations from scratch. Old migrations may fail to apply correctly if those
|
85
|
-
# migrations use external dependencies or application code.
|
86
|
-
#
|
87
|
-
# It's strongly recommended that you check this file into your version control system.
|
88
|
-
|
89
|
-
ActiveRecord::Schema.define(#{define_params}) do
|
90
|
-
|
91
|
-
HEADER
|
94
|
+
stream.puts <<~HEADER
|
95
|
+
# This file is auto-generated from the current state of the database. Instead
|
96
|
+
# of editing this file, please use the migrations feature of Active Record to
|
97
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
98
|
+
#
|
99
|
+
# This file is the source Rails uses to define your schema when running `bin/rails
|
100
|
+
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
|
101
|
+
# be faster and is potentially less error prone than running all of your
|
102
|
+
# migrations from scratch. Old migrations may fail to apply correctly if those
|
103
|
+
# migrations use external dependencies or application code.
|
104
|
+
#
|
105
|
+
# It's strongly recommended that you check this file into your version control system.
|
106
|
+
|
107
|
+
ActiveRecord::Schema[#{ActiveRecord::Migration.current_version}].define(#{define_params}) do
|
108
|
+
HEADER
|
92
109
|
end
|
93
110
|
|
94
111
|
def trailer(stream)
|
@@ -99,6 +116,14 @@ HEADER
|
|
99
116
|
def extensions(stream)
|
100
117
|
end
|
101
118
|
|
119
|
+
# (enum) types are only supported by PostgreSQL
|
120
|
+
def types(stream)
|
121
|
+
end
|
122
|
+
|
123
|
+
# schemas are only supported by PostgreSQL
|
124
|
+
def schemas(stream)
|
125
|
+
end
|
126
|
+
|
102
127
|
def tables(stream)
|
103
128
|
sorted_tables = @connection.tables.sort
|
104
129
|
|
@@ -107,7 +132,7 @@ HEADER
|
|
107
132
|
end
|
108
133
|
|
109
134
|
# dump foreign keys at the end to make sure all dependent tables exist.
|
110
|
-
if @connection.
|
135
|
+
if @connection.use_foreign_keys?
|
111
136
|
sorted_tables.each do |tbl|
|
112
137
|
foreign_keys(tbl, stream) unless ignored?(tbl)
|
113
138
|
end
|
@@ -154,6 +179,7 @@ HEADER
|
|
154
179
|
columns.each do |column|
|
155
180
|
raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
|
156
181
|
next if column.name == pk
|
182
|
+
|
157
183
|
type, colspec = column_spec(column)
|
158
184
|
if type.is_a?(Symbol)
|
159
185
|
tbl.print " t.#{type} #{column.name.inspect}"
|
@@ -166,12 +192,13 @@ HEADER
|
|
166
192
|
|
167
193
|
indexes_in_create(table, tbl)
|
168
194
|
check_constraints_in_create(table, tbl) if @connection.supports_check_constraints?
|
195
|
+
exclusion_constraints_in_create(table, tbl) if @connection.supports_exclusion_constraints?
|
196
|
+
unique_constraints_in_create(table, tbl) if @connection.supports_unique_constraints?
|
169
197
|
|
170
198
|
tbl.puts " end"
|
171
199
|
tbl.puts
|
172
200
|
|
173
|
-
tbl.
|
174
|
-
stream.print tbl.read
|
201
|
+
stream.print tbl.string
|
175
202
|
rescue => e
|
176
203
|
stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}"
|
177
204
|
stream.puts "# #{e.message}"
|
@@ -196,6 +223,18 @@ HEADER
|
|
196
223
|
|
197
224
|
def indexes_in_create(table, stream)
|
198
225
|
if (indexes = @connection.indexes(table)).any?
|
226
|
+
if @connection.supports_exclusion_constraints? && (exclusion_constraints = @connection.exclusion_constraints(table)).any?
|
227
|
+
exclusion_constraint_names = exclusion_constraints.collect(&:name)
|
228
|
+
|
229
|
+
indexes = indexes.reject { |index| exclusion_constraint_names.include?(index.name) }
|
230
|
+
end
|
231
|
+
|
232
|
+
if @connection.supports_unique_constraints? && (unique_constraints = @connection.unique_constraints(table)).any?
|
233
|
+
unique_constraint_names = unique_constraints.collect(&:name)
|
234
|
+
|
235
|
+
indexes = indexes.reject { |index| unique_constraint_names.include?(index.name) }
|
236
|
+
end
|
237
|
+
|
199
238
|
index_statements = indexes.map do |index|
|
200
239
|
" t.index #{index_parts(index).join(', ')}"
|
201
240
|
end
|
@@ -214,6 +253,8 @@ HEADER
|
|
214
253
|
index_parts << "opclass: #{format_index_parts(index.opclasses)}" if index.opclasses.present?
|
215
254
|
index_parts << "where: #{index.where.inspect}" if index.where
|
216
255
|
index_parts << "using: #{index.using.inspect}" if !@connection.default_index_type?(index)
|
256
|
+
index_parts << "include: #{index.include.inspect}" if index.include
|
257
|
+
index_parts << "nulls_not_distinct: #{index.nulls_not_distinct.inspect}" if index.nulls_not_distinct
|
217
258
|
index_parts << "type: #{index.type.inspect}" if index.type
|
218
259
|
index_parts << "comment: #{index.comment.inspect}" if index.comment
|
219
260
|
index_parts
|
@@ -230,6 +271,8 @@ HEADER
|
|
230
271
|
parts << "name: #{check_constraint.name.inspect}"
|
231
272
|
end
|
232
273
|
|
274
|
+
parts << "validate: #{check_constraint.validate?.inspect}" unless check_constraint.validate?
|
275
|
+
|
233
276
|
" #{parts.join(', ')}"
|
234
277
|
end
|
235
278
|
|
@@ -245,7 +288,7 @@ HEADER
|
|
245
288
|
remove_prefix_and_suffix(foreign_key.to_table).inspect,
|
246
289
|
]
|
247
290
|
|
248
|
-
if foreign_key.column != @connection.foreign_key_column_for(foreign_key.to_table)
|
291
|
+
if foreign_key.column != @connection.foreign_key_column_for(foreign_key.to_table, "id")
|
249
292
|
parts << "column: #{foreign_key.column.inspect}"
|
250
293
|
end
|
251
294
|
|
@@ -259,6 +302,8 @@ HEADER
|
|
259
302
|
|
260
303
|
parts << "on_update: #{foreign_key.on_update.inspect}" if foreign_key.on_update
|
261
304
|
parts << "on_delete: #{foreign_key.on_delete.inspect}" if foreign_key.on_delete
|
305
|
+
parts << "deferrable: #{foreign_key.deferrable.inspect}" if foreign_key.deferrable
|
306
|
+
parts << "validate: #{foreign_key.validate?.inspect}" unless foreign_key.validate?
|
262
307
|
|
263
308
|
" #{parts.join(', ')}"
|
264
309
|
end
|
@@ -286,13 +331,17 @@ HEADER
|
|
286
331
|
end
|
287
332
|
|
288
333
|
def remove_prefix_and_suffix(table)
|
334
|
+
# This method appears at the top when profiling active_record test cases run.
|
335
|
+
# Avoid costly calculation when there are no prefix and suffix.
|
336
|
+
return table if @options[:table_name_prefix].blank? && @options[:table_name_suffix].blank?
|
337
|
+
|
289
338
|
prefix = Regexp.escape(@options[:table_name_prefix].to_s)
|
290
339
|
suffix = Regexp.escape(@options[:table_name_suffix].to_s)
|
291
340
|
table.sub(/\A#{prefix}(.+)#{suffix}\z/, "\\1")
|
292
341
|
end
|
293
342
|
|
294
343
|
def ignored?(table_name)
|
295
|
-
|
344
|
+
@ignore_tables.any? do |ignored|
|
296
345
|
ignored === remove_prefix_and_suffix(table_name)
|
297
346
|
end
|
298
347
|
end
|