activerecord 5.1.7 → 5.2.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +221 -900
- data/README.rdoc +3 -3
- data/examples/performance.rb +2 -0
- data/examples/simple.rb +2 -0
- data/lib/active_record.rb +10 -3
- data/lib/active_record/aggregations.rb +2 -0
- data/lib/active_record/association_relation.rb +2 -0
- data/lib/active_record/associations.rb +13 -42
- data/lib/active_record/associations/alias_tracker.rb +17 -17
- data/lib/active_record/associations/association.rb +11 -22
- data/lib/active_record/associations/association_scope.rb +32 -44
- data/lib/active_record/associations/belongs_to_association.rb +6 -4
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -1
- data/lib/active_record/associations/builder/association.rb +2 -5
- data/lib/active_record/associations/builder/belongs_to.rb +7 -12
- data/lib/active_record/associations/builder/collection_association.rb +1 -1
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
- data/lib/active_record/associations/builder/has_many.rb +2 -0
- data/lib/active_record/associations/builder/has_one.rb +2 -0
- data/lib/active_record/associations/builder/singular_association.rb +2 -0
- data/lib/active_record/associations/collection_association.rb +41 -33
- data/lib/active_record/associations/collection_proxy.rb +11 -14
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +4 -2
- data/lib/active_record/associations/has_many_through_association.rb +4 -2
- data/lib/active_record/associations/has_one_association.rb +3 -1
- data/lib/active_record/associations/has_one_through_association.rb +3 -1
- data/lib/active_record/associations/join_dependency.rb +22 -40
- data/lib/active_record/associations/join_dependency/join_association.rb +17 -56
- data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -9
- data/lib/active_record/associations/preloader.rb +17 -37
- data/lib/active_record/associations/preloader/association.rb +42 -58
- data/lib/active_record/associations/preloader/through_association.rb +71 -79
- data/lib/active_record/associations/singular_association.rb +14 -10
- data/lib/active_record/associations/through_association.rb +3 -1
- data/lib/active_record/attribute_assignment.rb +2 -0
- data/lib/active_record/attribute_decorators.rb +3 -2
- data/lib/active_record/attribute_methods.rb +47 -7
- data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
- data/lib/active_record/attribute_methods/dirty.rb +25 -214
- data/lib/active_record/attribute_methods/primary_key.rb +7 -6
- data/lib/active_record/attribute_methods/query.rb +2 -0
- data/lib/active_record/attribute_methods/read.rb +8 -2
- data/lib/active_record/attribute_methods/serialization.rb +23 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
- data/lib/active_record/attribute_methods/write.rb +21 -9
- data/lib/active_record/attributes.rb +7 -6
- data/lib/active_record/autosave_association.rb +5 -11
- data/lib/active_record/base.rb +2 -0
- data/lib/active_record/callbacks.rb +6 -8
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +2 -0
- data/lib/active_record/collection_cache_key.rb +10 -5
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +110 -35
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +120 -28
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +7 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +14 -33
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +13 -5
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +40 -2
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +103 -63
- data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
- data/lib/active_record/connection_adapters/abstract_adapter.rb +62 -90
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +75 -138
- data/lib/active_record/connection_adapters/column.rb +3 -1
- data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +3 -1
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -6
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +91 -1
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/column.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +11 -7
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +79 -65
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +47 -82
- data/lib/active_record/connection_adapters/schema_cache.rb +2 -0
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +19 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +71 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +34 -89
- data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
- data/lib/active_record/connection_handling.rb +4 -2
- data/lib/active_record/core.rb +27 -57
- data/lib/active_record/counter_cache.rb +15 -12
- data/lib/active_record/define_callbacks.rb +5 -3
- data/lib/active_record/dynamic_matchers.rb +9 -9
- data/lib/active_record/enum.rb +15 -13
- data/lib/active_record/errors.rb +54 -21
- data/lib/active_record/explain.rb +3 -1
- data/lib/active_record/explain_registry.rb +2 -0
- data/lib/active_record/explain_subscriber.rb +2 -0
- data/lib/active_record/fixture_set/file.rb +2 -0
- data/lib/active_record/fixtures.rb +40 -24
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +6 -5
- data/lib/active_record/integration.rb +58 -19
- data/lib/active_record/internal_metadata.rb +2 -0
- data/lib/active_record/legacy_yaml_adapter.rb +3 -1
- data/lib/active_record/locking/optimistic.rb +31 -20
- data/lib/active_record/locking/pessimistic.rb +10 -7
- data/lib/active_record/log_subscriber.rb +2 -0
- data/lib/active_record/migration.rb +47 -21
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +20 -2
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/model_schema.rb +29 -38
- data/lib/active_record/nested_attributes.rb +18 -6
- data/lib/active_record/no_touching.rb +3 -1
- data/lib/active_record/null_relation.rb +2 -0
- data/lib/active_record/persistence.rb +184 -40
- data/lib/active_record/query_cache.rb +17 -12
- data/lib/active_record/querying.rb +3 -1
- data/lib/active_record/railtie.rb +54 -1
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +2 -0
- data/lib/active_record/railties/databases.rake +41 -28
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +100 -182
- data/lib/active_record/relation.rb +61 -193
- data/lib/active_record/relation/batches.rb +20 -5
- data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
- data/lib/active_record/relation/calculations.rb +40 -23
- data/lib/active_record/relation/delegation.rb +10 -27
- data/lib/active_record/relation/finder_methods.rb +53 -49
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +22 -19
- data/lib/active_record/relation/predicate_builder.rb +42 -79
- data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +54 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/query_attribute.rb +9 -2
- data/lib/active_record/relation/query_methods.rb +80 -69
- data/lib/active_record/relation/record_fetch_warning.rb +2 -0
- data/lib/active_record/relation/spawn_methods.rb +2 -0
- data/lib/active_record/relation/where_clause.rb +50 -67
- data/lib/active_record/relation/where_clause_factory.rb +4 -46
- data/lib/active_record/result.rb +2 -0
- data/lib/active_record/runtime_registry.rb +2 -0
- data/lib/active_record/sanitization.rb +15 -9
- data/lib/active_record/schema.rb +3 -1
- data/lib/active_record/schema_dumper.rb +24 -23
- data/lib/active_record/schema_migration.rb +2 -0
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/scoping/default.rb +6 -7
- data/lib/active_record/scoping/named.rb +15 -7
- data/lib/active_record/secure_token.rb +2 -0
- data/lib/active_record/serialization.rb +2 -0
- data/lib/active_record/statement_cache.rb +22 -12
- data/lib/active_record/store.rb +2 -0
- data/lib/active_record/suppressor.rb +2 -0
- data/lib/active_record/table_metadata.rb +3 -1
- data/lib/active_record/tasks/database_tasks.rb +23 -12
- data/lib/active_record/tasks/mysql_database_tasks.rb +9 -48
- data/lib/active_record/tasks/postgresql_database_tasks.rb +10 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
- data/lib/active_record/timestamp.rb +5 -12
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +9 -7
- data/lib/active_record/translation.rb +2 -0
- data/lib/active_record/type.rb +4 -1
- data/lib/active_record/type/adapter_specific_registry.rb +2 -0
- data/lib/active_record/type/date.rb +2 -0
- data/lib/active_record/type/date_time.rb +2 -0
- data/lib/active_record/type/decimal_without_scale.rb +2 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
- data/lib/active_record/type/internal/timezone.rb +2 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +2 -4
- data/lib/active_record/type/text.rb +2 -0
- data/lib/active_record/type/time.rb +2 -0
- data/lib/active_record/type/type_map.rb +2 -0
- data/lib/active_record/type/unsigned_integer.rb +2 -0
- data/lib/active_record/type_caster.rb +2 -0
- data/lib/active_record/type_caster/connection.rb +2 -0
- data/lib/active_record/type_caster/map.rb +2 -0
- data/lib/active_record/validations.rb +2 -0
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +2 -0
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/presence.rb +2 -0
- data/lib/active_record/validations/uniqueness.rb +36 -6
- data/lib/active_record/version.rb +2 -0
- data/lib/rails/generators/active_record.rb +3 -1
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration.rb +2 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- metadata +25 -38
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
- data/lib/active_record/associations/preloader/collection_association.rb +0 -17
- data/lib/active_record/associations/preloader/has_many.rb +0 -15
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -15
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -18
- data/lib/active_record/attribute.rb +0 -240
- data/lib/active_record/attribute/user_provided_default.rb +0 -30
- data/lib/active_record/attribute_mutation_tracker.rb +0 -122
- data/lib/active_record/attribute_set.rb +0 -113
- data/lib/active_record/attribute_set/builder.rb +0 -126
- data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
- data/lib/active_record/type/internal/abstract_json.rb +0 -37
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters # :nodoc:
|
3
5
|
module DatabaseStatements
|
@@ -7,30 +9,43 @@ module ActiveRecord
|
|
7
9
|
end
|
8
10
|
|
9
11
|
# Converts an arel AST to SQL
|
10
|
-
def to_sql(
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
def to_sql(arel_or_sql_string, binds = [])
|
13
|
+
sql, _ = to_sql_and_binds(arel_or_sql_string, binds)
|
14
|
+
sql
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_sql_and_binds(arel_or_sql_string, binds = []) # :nodoc:
|
18
|
+
if arel_or_sql_string.respond_to?(:ast)
|
19
|
+
unless binds.empty?
|
20
|
+
raise "Passing bind parameters with an arel AST is forbidden. " \
|
21
|
+
"The values must be stored on the AST directly"
|
22
|
+
end
|
23
|
+
sql, binds = visitor.accept(arel_or_sql_string.ast, collector).value
|
24
|
+
[sql.freeze, binds || []]
|
14
25
|
else
|
15
|
-
|
26
|
+
[arel_or_sql_string.dup.freeze, binds]
|
16
27
|
end
|
17
28
|
end
|
29
|
+
private :to_sql_and_binds
|
18
30
|
|
19
31
|
# This is used in the StatementCache object. It returns an object that
|
20
32
|
# can be used to query the database repeatedly.
|
21
33
|
def cacheable_query(klass, arel) # :nodoc:
|
22
|
-
collected = visitor.accept(arel.ast, collector)
|
23
34
|
if prepared_statements
|
24
|
-
|
35
|
+
sql, binds = visitor.accept(arel.ast, collector).value
|
36
|
+
query = klass.query(sql)
|
25
37
|
else
|
26
|
-
|
38
|
+
collector = PartialQueryCollector.new
|
39
|
+
parts, binds = visitor.accept(arel.ast, collector).value
|
40
|
+
query = klass.partial_query(parts)
|
27
41
|
end
|
42
|
+
[query, binds]
|
28
43
|
end
|
29
44
|
|
30
45
|
# Returns an ActiveRecord::Result instance.
|
31
46
|
def select_all(arel, name = nil, binds = [], preparable: nil)
|
32
|
-
arel
|
33
|
-
sql =
|
47
|
+
arel = arel_from_relation(arel)
|
48
|
+
sql, binds = to_sql_and_binds(arel, binds)
|
34
49
|
if !prepared_statements || (arel.is_a?(String) && preparable.nil?)
|
35
50
|
preparable = false
|
36
51
|
else
|
@@ -130,26 +145,30 @@ module ActiveRecord
|
|
130
145
|
# If the next id was calculated in advance (as in Oracle), it should be
|
131
146
|
# passed in as +id_value+.
|
132
147
|
def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
|
133
|
-
|
148
|
+
sql, binds = to_sql_and_binds(arel, binds)
|
149
|
+
value = exec_insert(sql, name, binds, pk, sequence_name)
|
134
150
|
id_value || last_inserted_id(value)
|
135
151
|
end
|
136
152
|
alias create insert
|
137
153
|
|
138
154
|
# Executes the update statement and returns the number of rows affected.
|
139
155
|
def update(arel, name = nil, binds = [])
|
140
|
-
|
156
|
+
sql, binds = to_sql_and_binds(arel, binds)
|
157
|
+
exec_update(sql, name, binds)
|
141
158
|
end
|
142
159
|
|
143
160
|
# Executes the delete statement and returns the number of rows affected.
|
144
161
|
def delete(arel, name = nil, binds = [])
|
145
|
-
|
162
|
+
sql, binds = to_sql_and_binds(arel, binds)
|
163
|
+
exec_delete(sql, name, binds)
|
146
164
|
end
|
147
165
|
|
148
166
|
# Returns +true+ when the connection adapter supports prepared statement
|
149
167
|
# caching, otherwise returns +false+
|
150
|
-
def supports_statement_cache?
|
151
|
-
|
168
|
+
def supports_statement_cache? # :nodoc:
|
169
|
+
true
|
152
170
|
end
|
171
|
+
deprecate :supports_statement_cache?
|
153
172
|
|
154
173
|
# Runs the given block in a database transaction, and returns the result
|
155
174
|
# of the block.
|
@@ -162,7 +181,7 @@ module ActiveRecord
|
|
162
181
|
#
|
163
182
|
# In order to get around this problem, #transaction will emulate the effect
|
164
183
|
# of nested transactions, by using savepoints:
|
165
|
-
#
|
184
|
+
# https://dev.mysql.com/doc/refman/5.7/en/savepoint.html
|
166
185
|
# Savepoints are supported by MySQL and PostgreSQL. SQLite3 version >= '3.6.8'
|
167
186
|
# supports savepoints.
|
168
187
|
#
|
@@ -214,7 +233,7 @@ module ActiveRecord
|
|
214
233
|
# You should consult the documentation for your database to understand the
|
215
234
|
# semantics of these different levels:
|
216
235
|
#
|
217
|
-
# *
|
236
|
+
# * https://www.postgresql.org/docs/current/static/transaction-iso.html
|
218
237
|
# * https://dev.mysql.com/doc/refman/5.7/en/set-transaction.html
|
219
238
|
#
|
220
239
|
# An ActiveRecord::TransactionIsolationError will be raised if:
|
@@ -305,6 +324,9 @@ module ActiveRecord
|
|
305
324
|
|
306
325
|
# Inserts the given fixture into the table. Overridden in adapters that require
|
307
326
|
# something beyond a simple insert (eg. Oracle).
|
327
|
+
# Most of adapters should implement `insert_fixtures` that leverages bulk SQL insert.
|
328
|
+
# We keep this method to provide fallback
|
329
|
+
# for databases like sqlite that do not support bulk inserts.
|
308
330
|
def insert_fixture(fixture, table_name)
|
309
331
|
fixture = fixture.stringify_keys
|
310
332
|
|
@@ -317,16 +339,52 @@ module ActiveRecord
|
|
317
339
|
raise Fixture::FixtureError, %(table "#{table_name}" has no column named #{name.inspect}.)
|
318
340
|
end
|
319
341
|
end
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
342
|
+
|
343
|
+
table = Arel::Table.new(table_name)
|
344
|
+
|
345
|
+
values = binds.map do |bind|
|
346
|
+
value = with_yaml_fallback(bind.value_for_database)
|
347
|
+
[table[bind.name], value]
|
348
|
+
end
|
349
|
+
|
350
|
+
manager = Arel::InsertManager.new
|
351
|
+
manager.into(table)
|
352
|
+
manager.insert(values)
|
353
|
+
execute manager.to_sql, "Fixture Insert"
|
354
|
+
end
|
355
|
+
|
356
|
+
# Inserts a set of fixtures into the table. Overridden in adapters that require
|
357
|
+
# something beyond a simple insert (eg. Oracle).
|
358
|
+
def insert_fixtures(fixtures, table_name)
|
359
|
+
return if fixtures.empty?
|
360
|
+
|
361
|
+
columns = schema_cache.columns_hash(table_name)
|
362
|
+
|
363
|
+
values = fixtures.map do |fixture|
|
364
|
+
fixture = fixture.stringify_keys
|
365
|
+
|
366
|
+
unknown_columns = fixture.keys - columns.keys
|
367
|
+
if unknown_columns.any?
|
368
|
+
raise Fixture::FixtureError, %(table "#{table_name}" has no columns named #{unknown_columns.map(&:inspect).join(', ')}.)
|
369
|
+
end
|
370
|
+
|
371
|
+
columns.map do |name, column|
|
372
|
+
if fixture.key?(name)
|
373
|
+
type = lookup_cast_type_from_column(column)
|
374
|
+
bind = Relation::QueryAttribute.new(name, fixture[name], type)
|
375
|
+
with_yaml_fallback(bind.value_for_database)
|
376
|
+
else
|
377
|
+
Arel.sql("DEFAULT")
|
378
|
+
end
|
326
379
|
end
|
327
380
|
end
|
328
381
|
|
329
|
-
|
382
|
+
table = Arel::Table.new(table_name)
|
383
|
+
manager = Arel::InsertManager.new
|
384
|
+
manager.into(table)
|
385
|
+
columns.each_key { |column| manager.columns << table[column] }
|
386
|
+
manager.values = manager.create_values_list(values)
|
387
|
+
execute manager.to_sql, "Fixtures Insert"
|
330
388
|
end
|
331
389
|
|
332
390
|
def empty_insert_statement_value
|
@@ -388,11 +446,45 @@ module ActiveRecord
|
|
388
446
|
row && row.first
|
389
447
|
end
|
390
448
|
|
391
|
-
def
|
392
|
-
if relation.is_a?(Relation)
|
393
|
-
relation
|
449
|
+
def arel_from_relation(relation)
|
450
|
+
if relation.is_a?(Relation)
|
451
|
+
relation.arel
|
452
|
+
else
|
453
|
+
relation
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
457
|
+
# Fixture value is quoted by Arel, however scalar values
|
458
|
+
# are not quotable. In this case we want to convert
|
459
|
+
# the column value to YAML.
|
460
|
+
def with_yaml_fallback(value)
|
461
|
+
if value.is_a?(Hash) || value.is_a?(Array)
|
462
|
+
YAML.dump(value)
|
463
|
+
else
|
464
|
+
value
|
465
|
+
end
|
466
|
+
end
|
467
|
+
|
468
|
+
class PartialQueryCollector
|
469
|
+
def initialize
|
470
|
+
@parts = []
|
471
|
+
@binds = []
|
472
|
+
end
|
473
|
+
|
474
|
+
def <<(str)
|
475
|
+
@parts << str
|
476
|
+
self
|
477
|
+
end
|
478
|
+
|
479
|
+
def add_bind(obj)
|
480
|
+
@binds << obj
|
481
|
+
@parts << Arel::Nodes::BindParam.new(1)
|
482
|
+
self
|
483
|
+
end
|
484
|
+
|
485
|
+
def value
|
486
|
+
[@parts, @binds]
|
394
487
|
end
|
395
|
-
[relation, binds]
|
396
488
|
end
|
397
489
|
end
|
398
490
|
end
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "concurrent/map"
|
4
|
+
|
1
5
|
module ActiveRecord
|
2
6
|
module ConnectionAdapters # :nodoc:
|
3
7
|
module QueryCache
|
@@ -90,8 +94,8 @@ module ActiveRecord
|
|
90
94
|
|
91
95
|
def select_all(arel, name = nil, binds = [], preparable: nil)
|
92
96
|
if @query_cache_enabled && !locked?(arel)
|
93
|
-
arel
|
94
|
-
sql =
|
97
|
+
arel = arel_from_relation(arel)
|
98
|
+
sql, binds = to_sql_and_binds(arel, binds)
|
95
99
|
cache_sql(sql, name, binds) { super(sql, name, binds, preparable: preparable) }
|
96
100
|
else
|
97
101
|
super
|
@@ -124,6 +128,7 @@ module ActiveRecord
|
|
124
128
|
# If arel is locked this is a SELECT ... FOR UPDATE or somesuch. Such
|
125
129
|
# queries should not be cached.
|
126
130
|
def locked?(arel)
|
131
|
+
arel = arel.arel if arel.is_a?(Relation)
|
127
132
|
arel.respond_to?(:locked) && arel.locked
|
128
133
|
end
|
129
134
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/big_decimal/conversions"
|
2
4
|
require "active_support/multibyte/chars"
|
3
5
|
|
@@ -5,21 +7,12 @@ module ActiveRecord
|
|
5
7
|
module ConnectionAdapters # :nodoc:
|
6
8
|
module Quoting
|
7
9
|
# Quotes the column value to help prevent
|
8
|
-
# {SQL injection attacks}[
|
10
|
+
# {SQL injection attacks}[https://en.wikipedia.org/wiki/SQL_injection].
|
9
11
|
def quote(value)
|
10
12
|
value = id_value_for_database(value) if value.is_a?(Base)
|
11
13
|
|
12
|
-
if value.respond_to?(:
|
13
|
-
|
14
|
-
at &&= " at %s:%d" % at
|
15
|
-
|
16
|
-
owner = value.method(:quoted_id).owner.to_s
|
17
|
-
klass = value.class.to_s
|
18
|
-
klass += "(#{owner})" unless owner == klass
|
19
|
-
|
20
|
-
ActiveSupport::Deprecation.warn \
|
21
|
-
"Defining #quoted_id is deprecated and will be ignored in Rails 5.2. (defined on #{klass}#{at})"
|
22
|
-
return value.quoted_id
|
14
|
+
if value.respond_to?(:value_for_database)
|
15
|
+
value = value.value_for_database
|
23
16
|
end
|
24
17
|
|
25
18
|
_quote(value)
|
@@ -31,10 +24,6 @@ module ActiveRecord
|
|
31
24
|
def type_cast(value, column = nil)
|
32
25
|
value = id_value_for_database(value) if value.is_a?(Base)
|
33
26
|
|
34
|
-
if value.respond_to?(:quoted_id) && value.respond_to?(:id)
|
35
|
-
return value.id
|
36
|
-
end
|
37
|
-
|
38
27
|
if column
|
39
28
|
value = type_cast_from_column(column, value)
|
40
29
|
end
|
@@ -68,17 +57,6 @@ module ActiveRecord
|
|
68
57
|
lookup_cast_type(column.sql_type)
|
69
58
|
end
|
70
59
|
|
71
|
-
def fetch_type_metadata(sql_type)
|
72
|
-
cast_type = lookup_cast_type(sql_type)
|
73
|
-
SqlTypeMetadata.new(
|
74
|
-
sql_type: sql_type,
|
75
|
-
type: cast_type.type,
|
76
|
-
limit: cast_type.limit,
|
77
|
-
precision: cast_type.precision,
|
78
|
-
scale: cast_type.scale,
|
79
|
-
)
|
80
|
-
end
|
81
|
-
|
82
60
|
# Quotes a string, escaping any ' (single quote) and \ (backslash)
|
83
61
|
# characters.
|
84
62
|
def quote_string(s)
|
@@ -117,19 +95,19 @@ module ActiveRecord
|
|
117
95
|
end
|
118
96
|
|
119
97
|
def quoted_true
|
120
|
-
"
|
98
|
+
"TRUE".freeze
|
121
99
|
end
|
122
100
|
|
123
101
|
def unquoted_true
|
124
|
-
|
102
|
+
true
|
125
103
|
end
|
126
104
|
|
127
105
|
def quoted_false
|
128
|
-
"
|
106
|
+
"FALSE".freeze
|
129
107
|
end
|
130
108
|
|
131
109
|
def unquoted_false
|
132
|
-
|
110
|
+
false
|
133
111
|
end
|
134
112
|
|
135
113
|
# Quote date/time values for use in SQL input. Includes microseconds
|
@@ -152,8 +130,7 @@ module ActiveRecord
|
|
152
130
|
end
|
153
131
|
|
154
132
|
def quoted_time(value) # :nodoc:
|
155
|
-
value
|
156
|
-
quoted_date(value).sub(/\A\d\d\d\d-\d\d-\d\d /, "")
|
133
|
+
quoted_date(value).sub(/\A2000-01-01 /, "")
|
157
134
|
end
|
158
135
|
|
159
136
|
def quoted_binary(value) # :nodoc:
|
@@ -169,6 +146,10 @@ module ActiveRecord
|
|
169
146
|
end
|
170
147
|
|
171
148
|
private
|
149
|
+
def lookup_cast_type(sql_type)
|
150
|
+
type_map.lookup(sql_type)
|
151
|
+
end
|
152
|
+
|
172
153
|
def id_value_for_database(value)
|
173
154
|
if primary_key = value.class.primary_key
|
174
155
|
value.instance_variable_get(:@attributes)[primary_key].value_for_database
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/string/strip"
|
2
4
|
|
3
5
|
module ActiveRecord
|
@@ -22,7 +24,7 @@ module ActiveRecord
|
|
22
24
|
private
|
23
25
|
|
24
26
|
def visit_AlterTable(o)
|
25
|
-
sql = "ALTER TABLE #{quote_table_name(o.name)} "
|
27
|
+
sql = "ALTER TABLE #{quote_table_name(o.name)} ".dup
|
26
28
|
sql << o.adds.map { |col| accept col }.join(" ")
|
27
29
|
sql << o.foreign_key_adds.map { |fk| visit_AddForeignKey fk }.join(" ")
|
28
30
|
sql << o.foreign_key_drops.map { |fk| visit_DropForeignKey fk }.join(" ")
|
@@ -30,17 +32,17 @@ module ActiveRecord
|
|
30
32
|
|
31
33
|
def visit_ColumnDefinition(o)
|
32
34
|
o.sql_type = type_to_sql(o.type, o.options)
|
33
|
-
column_sql = "#{quote_column_name(o.name)} #{o.sql_type}"
|
35
|
+
column_sql = "#{quote_column_name(o.name)} #{o.sql_type}".dup
|
34
36
|
add_column_options!(column_sql, column_options(o)) unless o.type == :primary_key
|
35
37
|
column_sql
|
36
38
|
end
|
37
39
|
|
38
40
|
def visit_AddColumnDefinition(o)
|
39
|
-
"ADD #{accept(o.column)}"
|
41
|
+
"ADD #{accept(o.column)}".dup
|
40
42
|
end
|
41
43
|
|
42
44
|
def visit_TableDefinition(o)
|
43
|
-
create_sql = "CREATE#{' TEMPORARY' if o.temporary} TABLE #{quote_table_name(o.name)} "
|
45
|
+
create_sql = "CREATE#{' TEMPORARY' if o.temporary} TABLE #{quote_table_name(o.name)} ".dup
|
44
46
|
|
45
47
|
statements = o.columns.map { |c| accept c }
|
46
48
|
statements << accept(o.primary_keys) if o.primary_keys
|
@@ -55,7 +57,7 @@ module ActiveRecord
|
|
55
57
|
|
56
58
|
create_sql << "(#{statements.join(', ')})" if statements.present?
|
57
59
|
add_table_options!(create_sql, table_options(o))
|
58
|
-
create_sql << " AS #{
|
60
|
+
create_sql << " AS #{to_sql(o.as)}" if o.as
|
59
61
|
create_sql
|
60
62
|
end
|
61
63
|
|
@@ -114,6 +116,11 @@ module ActiveRecord
|
|
114
116
|
sql
|
115
117
|
end
|
116
118
|
|
119
|
+
def to_sql(sql)
|
120
|
+
sql = sql.to_sql if sql.respond_to?(:to_sql)
|
121
|
+
sql
|
122
|
+
end
|
123
|
+
|
117
124
|
def foreign_key_in_create(from_table, to_table, options)
|
118
125
|
options = foreign_key_options(from_table, to_table, options)
|
119
126
|
accept ForeignKeyDefinition.new(from_table, to_table, options)
|
@@ -133,5 +140,6 @@ module ActiveRecord
|
|
133
140
|
end
|
134
141
|
end
|
135
142
|
end
|
143
|
+
SchemaCreation = AbstractAdapter::SchemaCreation # :nodoc:
|
136
144
|
end
|
137
145
|
end
|
@@ -1,9 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters #:nodoc:
|
3
5
|
# Abstract representation of an index definition on a table. Instances of
|
4
6
|
# this type are typically created and returned by methods in database
|
5
|
-
# adapters. e.g. ActiveRecord::ConnectionAdapters::
|
6
|
-
IndexDefinition
|
7
|
+
# adapters. e.g. ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements#indexes
|
8
|
+
class IndexDefinition # :nodoc:
|
9
|
+
attr_reader :table, :name, :unique, :columns, :lengths, :orders, :where, :type, :using, :comment
|
10
|
+
|
11
|
+
def initialize(
|
12
|
+
table, name,
|
13
|
+
unique = false,
|
14
|
+
columns = [],
|
15
|
+
lengths: {},
|
16
|
+
orders: {},
|
17
|
+
where: nil,
|
18
|
+
type: nil,
|
19
|
+
using: nil,
|
20
|
+
comment: nil
|
21
|
+
)
|
22
|
+
@table = table
|
23
|
+
@name = name
|
24
|
+
@unique = unique
|
25
|
+
@columns = columns
|
26
|
+
@lengths = lengths
|
27
|
+
@orders = orders
|
28
|
+
@where = where
|
29
|
+
@type = type
|
30
|
+
@using = using
|
31
|
+
@comment = comment
|
32
|
+
end
|
33
|
+
end
|
7
34
|
|
8
35
|
# Abstract representation of a column definition. Instances of this type
|
9
36
|
# are typically created by methods in TableDefinition, and added to the
|
@@ -369,6 +396,9 @@ module ActiveRecord
|
|
369
396
|
alias :belongs_to :references
|
370
397
|
|
371
398
|
def new_column_definition(name, type, **options) # :nodoc:
|
399
|
+
if integer_like_primary_key?(type, options)
|
400
|
+
type = integer_like_primary_key_type(type, options)
|
401
|
+
end
|
372
402
|
type = aliased_types(type.to_s, type)
|
373
403
|
options[:primary_key] ||= type == :primary_key
|
374
404
|
options[:null] = false if options[:primary_key]
|
@@ -383,6 +413,14 @@ module ActiveRecord
|
|
383
413
|
def aliased_types(name, fallback)
|
384
414
|
"timestamp" == name ? :datetime : fallback
|
385
415
|
end
|
416
|
+
|
417
|
+
def integer_like_primary_key?(type, options)
|
418
|
+
options[:primary_key] && [:integer, :bigint].include?(type) && !options.key?(:default)
|
419
|
+
end
|
420
|
+
|
421
|
+
def integer_like_primary_key_type(type, options)
|
422
|
+
type
|
423
|
+
end
|
386
424
|
end
|
387
425
|
|
388
426
|
class AlterTable # :nodoc:
|