activerecord 5.0.7.2 → 5.1.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 +389 -2252
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/examples/performance.rb +28 -28
- data/examples/simple.rb +3 -3
- data/lib/active_record.rb +20 -20
- data/lib/active_record/aggregations.rb +244 -244
- data/lib/active_record/association_relation.rb +5 -5
- data/lib/active_record/associations.rb +1579 -1569
- data/lib/active_record/associations/alias_tracker.rb +1 -1
- data/lib/active_record/associations/association.rb +23 -15
- data/lib/active_record/associations/association_scope.rb +83 -81
- data/lib/active_record/associations/belongs_to_association.rb +0 -1
- data/lib/active_record/associations/builder/belongs_to.rb +16 -14
- data/lib/active_record/associations/builder/collection_association.rb +1 -2
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +27 -27
- data/lib/active_record/associations/collection_association.rb +74 -241
- data/lib/active_record/associations/collection_proxy.rb +144 -70
- data/lib/active_record/associations/has_many_association.rb +15 -19
- data/lib/active_record/associations/has_many_through_association.rb +12 -5
- data/lib/active_record/associations/has_one_association.rb +22 -28
- data/lib/active_record/associations/has_one_through_association.rb +5 -1
- data/lib/active_record/associations/join_dependency.rb +117 -115
- data/lib/active_record/associations/join_dependency/join_association.rb +16 -13
- data/lib/active_record/associations/join_dependency/join_base.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
- data/lib/active_record/associations/preloader.rb +94 -94
- data/lib/active_record/associations/preloader/association.rb +87 -64
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -2
- data/lib/active_record/associations/preloader/collection_association.rb +6 -6
- data/lib/active_record/associations/preloader/has_many.rb +0 -2
- data/lib/active_record/associations/preloader/singular_association.rb +6 -8
- data/lib/active_record/associations/preloader/through_association.rb +34 -41
- data/lib/active_record/associations/singular_association.rb +8 -25
- data/lib/active_record/associations/through_association.rb +3 -6
- data/lib/active_record/attribute.rb +98 -71
- data/lib/active_record/attribute/user_provided_default.rb +4 -2
- data/lib/active_record/attribute_assignment.rb +61 -61
- data/lib/active_record/attribute_decorators.rb +35 -13
- data/lib/active_record/attribute_methods.rb +56 -65
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
- data/lib/active_record/attribute_methods/dirty.rb +216 -34
- data/lib/active_record/attribute_methods/primary_key.rb +78 -73
- data/lib/active_record/attribute_methods/read.rb +39 -35
- data/lib/active_record/attribute_methods/serialization.rb +7 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +35 -58
- data/lib/active_record/attribute_methods/write.rb +36 -30
- data/lib/active_record/attribute_mutation_tracker.rb +53 -10
- data/lib/active_record/attribute_set.rb +9 -6
- data/lib/active_record/attribute_set/builder.rb +41 -49
- data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
- data/lib/active_record/attributes.rb +21 -21
- data/lib/active_record/autosave_association.rb +13 -13
- data/lib/active_record/base.rb +24 -22
- data/lib/active_record/callbacks.rb +52 -14
- data/lib/active_record/coders/yaml_column.rb +9 -11
- data/lib/active_record/collection_cache_key.rb +6 -17
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +320 -278
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +22 -34
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +44 -57
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +9 -19
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +78 -79
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +99 -93
- data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -5
- data/lib/active_record/connection_adapters/abstract_adapter.rb +156 -128
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +424 -382
- data/lib/active_record/connection_adapters/column.rb +27 -5
- data/lib/active_record/connection_adapters/connection_specification.rb +128 -118
- data/lib/active_record/connection_adapters/mysql/column.rb +6 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +45 -43
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +22 -22
- data/lib/active_record/connection_adapters/mysql/quoting.rb +6 -12
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +16 -19
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +49 -31
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +5 -6
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +24 -26
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +46 -35
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +22 -21
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +9 -9
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +16 -16
- data/lib/active_record/connection_adapters/postgresql/oid/{rails_5_1_point.rb → legacy_point.rb} +9 -16
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +28 -8
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +28 -30
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +51 -51
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +38 -36
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +37 -24
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +19 -23
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +161 -170
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +179 -152
- data/lib/active_record/connection_adapters/schema_cache.rb +16 -7
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +3 -3
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +16 -20
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +1 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +28 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +17 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +187 -130
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -7
- data/lib/active_record/connection_handling.rb +14 -26
- data/lib/active_record/core.rb +110 -93
- data/lib/active_record/counter_cache.rb +62 -13
- data/lib/active_record/define_callbacks.rb +20 -0
- data/lib/active_record/dynamic_matchers.rb +80 -79
- data/lib/active_record/enum.rb +8 -6
- data/lib/active_record/errors.rb +58 -15
- data/lib/active_record/explain.rb +1 -2
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +7 -4
- data/lib/active_record/fixture_set/file.rb +11 -8
- data/lib/active_record/fixtures.rb +66 -53
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +93 -79
- data/lib/active_record/integration.rb +7 -7
- data/lib/active_record/internal_metadata.rb +3 -16
- data/lib/active_record/legacy_yaml_adapter.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +64 -56
- data/lib/active_record/locking/pessimistic.rb +10 -1
- data/lib/active_record/log_subscriber.rb +29 -29
- data/lib/active_record/migration.rb +155 -172
- data/lib/active_record/migration/command_recorder.rb +94 -94
- data/lib/active_record/migration/compatibility.rb +76 -37
- data/lib/active_record/migration/join_table.rb +6 -6
- data/lib/active_record/model_schema.rb +85 -119
- data/lib/active_record/nested_attributes.rb +200 -199
- data/lib/active_record/null_relation.rb +10 -33
- data/lib/active_record/persistence.rb +45 -38
- data/lib/active_record/query_cache.rb +4 -8
- data/lib/active_record/querying.rb +2 -3
- data/lib/active_record/railtie.rb +16 -17
- data/lib/active_record/railties/controller_runtime.rb +6 -2
- data/lib/active_record/railties/databases.rake +125 -140
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/readonly_attributes.rb +2 -2
- data/lib/active_record/reflection.rb +79 -96
- data/lib/active_record/relation.rb +72 -115
- data/lib/active_record/relation/batches.rb +87 -58
- data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
- data/lib/active_record/relation/calculations.rb +154 -160
- data/lib/active_record/relation/delegation.rb +30 -29
- data/lib/active_record/relation/finder_methods.rb +195 -226
- data/lib/active_record/relation/merger.rb +58 -62
- data/lib/active_record/relation/predicate_builder.rb +92 -89
- data/lib/active_record/relation/predicate_builder/array_handler.rb +7 -5
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +23 -23
- data/lib/active_record/relation/predicate_builder/base_handler.rb +3 -1
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +0 -8
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +12 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +0 -8
- data/lib/active_record/relation/query_attribute.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +247 -295
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +4 -5
- data/lib/active_record/relation/where_clause.rb +79 -65
- data/lib/active_record/relation/where_clause_factory.rb +47 -8
- data/lib/active_record/result.rb +29 -31
- data/lib/active_record/runtime_registry.rb +3 -3
- data/lib/active_record/sanitization.rb +182 -197
- data/lib/active_record/schema.rb +3 -3
- data/lib/active_record/schema_dumper.rb +14 -37
- data/lib/active_record/schema_migration.rb +3 -3
- data/lib/active_record/scoping.rb +9 -10
- data/lib/active_record/scoping/default.rb +87 -91
- data/lib/active_record/scoping/named.rb +16 -28
- data/lib/active_record/secure_token.rb +2 -2
- data/lib/active_record/statement_cache.rb +13 -15
- data/lib/active_record/store.rb +31 -32
- data/lib/active_record/suppressor.rb +2 -1
- data/lib/active_record/table_metadata.rb +9 -5
- data/lib/active_record/tasks/database_tasks.rb +72 -65
- data/lib/active_record/tasks/mysql_database_tasks.rb +75 -72
- data/lib/active_record/tasks/postgresql_database_tasks.rb +53 -48
- data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
- data/lib/active_record/timestamp.rb +39 -25
- data/lib/active_record/touch_later.rb +1 -2
- data/lib/active_record/transactions.rb +98 -110
- data/lib/active_record/type.rb +17 -13
- data/lib/active_record/type/adapter_specific_registry.rb +46 -42
- data/lib/active_record/type/decimal_without_scale.rb +9 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
- data/lib/active_record/type/serialized.rb +8 -8
- data/lib/active_record/type/text.rb +9 -0
- data/lib/active_record/type/time.rb +0 -1
- data/lib/active_record/type/type_map.rb +11 -15
- data/lib/active_record/type/unsigned_integer.rb +15 -0
- data/lib/active_record/type_caster.rb +2 -2
- data/lib/active_record/type_caster/connection.rb +8 -6
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/validations.rb +4 -4
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/presence.rb +2 -2
- data/lib/active_record/validations/uniqueness.rb +8 -39
- data/lib/active_record/version.rb +1 -1
- data/lib/rails/generators/active_record.rb +4 -4
- data/lib/rails/generators/active_record/migration.rb +2 -2
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
- metadata +22 -13
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
@@ -1,7 +1,6 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module ConnectionAdapters # :nodoc:
|
3
3
|
module DatabaseLimits
|
4
|
-
|
5
4
|
# Returns the maximum length of a table alias.
|
6
5
|
def table_alias_length
|
7
6
|
255
|
@@ -47,7 +46,7 @@ module ActiveRecord
|
|
47
46
|
end
|
48
47
|
|
49
48
|
# Returns the maximum number of elements in an IN (x,y,z) clause.
|
50
|
-
# nil means no limit.
|
49
|
+
# +nil+ means no limit.
|
51
50
|
def in_clause_length
|
52
51
|
nil
|
53
52
|
end
|
@@ -61,7 +60,6 @@ module ActiveRecord
|
|
61
60
|
def joins_per_query
|
62
61
|
256
|
63
62
|
end
|
64
|
-
|
65
63
|
end
|
66
64
|
end
|
67
65
|
end
|
@@ -10,19 +10,20 @@ module ActiveRecord
|
|
10
10
|
def to_sql(arel, binds = [])
|
11
11
|
if arel.respond_to?(:ast)
|
12
12
|
collected = visitor.accept(arel.ast, collector)
|
13
|
-
collected.compile(binds
|
13
|
+
collected.compile(binds, self).freeze
|
14
14
|
else
|
15
|
-
arel
|
15
|
+
arel.dup.freeze
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
19
|
# This is used in the StatementCache object. It returns an object that
|
20
20
|
# can be used to query the database repeatedly.
|
21
|
-
def cacheable_query(arel) # :nodoc:
|
21
|
+
def cacheable_query(klass, arel) # :nodoc:
|
22
|
+
collected = visitor.accept(arel.ast, collector)
|
22
23
|
if prepared_statements
|
23
|
-
|
24
|
+
klass.query(collected.value)
|
24
25
|
else
|
25
|
-
|
26
|
+
klass.partial_query(collected.value)
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
@@ -50,8 +51,7 @@ module ActiveRecord
|
|
50
51
|
|
51
52
|
# Returns a single value from a record
|
52
53
|
def select_value(arel, name = nil, binds = [])
|
53
|
-
|
54
|
-
if result = select_rows(to_sql(arel, binds), name, binds).first
|
54
|
+
if result = select_rows(arel, name, binds).first
|
55
55
|
result.first
|
56
56
|
end
|
57
57
|
end
|
@@ -59,14 +59,13 @@ module ActiveRecord
|
|
59
59
|
# Returns an array of the values of the first column in a select:
|
60
60
|
# select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
|
61
61
|
def select_values(arel, name = nil, binds = [])
|
62
|
-
arel,
|
63
|
-
select_rows(to_sql(arel, binds), name, binds).map(&:first)
|
62
|
+
select_rows(arel, name, binds).map(&:first)
|
64
63
|
end
|
65
64
|
|
66
65
|
# Returns an array of arrays containing the field values.
|
67
66
|
# Order is the same as that returned by +columns+.
|
68
|
-
def select_rows(
|
69
|
-
|
67
|
+
def select_rows(arel, name = nil, binds = [])
|
68
|
+
select_all(arel, name, binds).rows
|
70
69
|
end
|
71
70
|
|
72
71
|
# Executes the SQL statement in the context of this connection and returns
|
@@ -81,21 +80,22 @@ module ActiveRecord
|
|
81
80
|
# Executes +sql+ statement in the context of this connection using
|
82
81
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
83
82
|
# the executed +sql+ statement.
|
84
|
-
def exec_query(sql, name =
|
83
|
+
def exec_query(sql, name = "SQL", binds = [], prepare: false)
|
85
84
|
raise NotImplementedError
|
86
85
|
end
|
87
86
|
|
88
87
|
# Executes insert +sql+ statement in the context of this connection using
|
89
88
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
90
89
|
# the executed +sql+ statement.
|
91
|
-
def exec_insert(sql, name, binds, pk = nil, sequence_name = nil)
|
90
|
+
def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
|
91
|
+
sql, binds = sql_for_insert(sql, pk, nil, sequence_name, binds)
|
92
92
|
exec_query(sql, name, binds)
|
93
93
|
end
|
94
94
|
|
95
95
|
# Executes delete +sql+ statement in the context of this connection using
|
96
96
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
97
97
|
# the executed +sql+ statement.
|
98
|
-
def exec_delete(sql, name, binds)
|
98
|
+
def exec_delete(sql, name = nil, binds = [])
|
99
99
|
exec_query(sql, name, binds)
|
100
100
|
end
|
101
101
|
|
@@ -107,40 +107,33 @@ module ActiveRecord
|
|
107
107
|
# Executes update +sql+ statement in the context of this connection using
|
108
108
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
109
109
|
# the executed +sql+ statement.
|
110
|
-
def exec_update(sql, name, binds)
|
110
|
+
def exec_update(sql, name = nil, binds = [])
|
111
111
|
exec_query(sql, name, binds)
|
112
112
|
end
|
113
113
|
|
114
114
|
# Executes an INSERT query and returns the new record's ID
|
115
115
|
#
|
116
|
-
# +id_value+ will be returned unless the value is nil
|
116
|
+
# +id_value+ will be returned unless the value is +nil+, in
|
117
117
|
# which case the database will attempt to calculate the last inserted
|
118
118
|
# id and return that value.
|
119
119
|
#
|
120
120
|
# If the next id was calculated in advance (as in Oracle), it should be
|
121
121
|
# passed in as +id_value+.
|
122
122
|
def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
|
123
|
-
|
124
|
-
value = exec_insert(sql, name, binds, pk, sequence_name)
|
123
|
+
value = exec_insert(to_sql(arel, binds), name, binds, pk, sequence_name)
|
125
124
|
id_value || last_inserted_id(value)
|
126
125
|
end
|
127
126
|
alias create insert
|
128
|
-
alias insert_sql insert
|
129
|
-
deprecate insert_sql: :insert
|
130
127
|
|
131
128
|
# Executes the update statement and returns the number of rows affected.
|
132
129
|
def update(arel, name = nil, binds = [])
|
133
130
|
exec_update(to_sql(arel, binds), name, binds)
|
134
131
|
end
|
135
|
-
alias update_sql update
|
136
|
-
deprecate update_sql: :update
|
137
132
|
|
138
133
|
# Executes the delete statement and returns the number of rows affected.
|
139
134
|
def delete(arel, name = nil, binds = [])
|
140
135
|
exec_delete(to_sql(arel, binds), name, binds)
|
141
136
|
end
|
142
|
-
alias delete_sql delete
|
143
|
-
deprecate delete_sql: :delete
|
144
137
|
|
145
138
|
# Returns +true+ when the connection adapter supports prepared statement
|
146
139
|
# caching, otherwise returns +false+
|
@@ -315,7 +308,7 @@ module ActiveRecord
|
|
315
308
|
end
|
316
309
|
end
|
317
310
|
key_list = fixture.keys.map { |name| quote_column_name(name) }
|
318
|
-
value_list =
|
311
|
+
value_list = binds.map(&:value_for_database).map do |value|
|
319
312
|
begin
|
320
313
|
quote(value)
|
321
314
|
rescue TypeError
|
@@ -323,7 +316,7 @@ module ActiveRecord
|
|
323
316
|
end
|
324
317
|
end
|
325
318
|
|
326
|
-
execute "INSERT INTO #{quote_table_name(table_name)} (#{key_list.join(', ')}) VALUES (#{value_list.join(', ')})",
|
319
|
+
execute "INSERT INTO #{quote_table_name(table_name)} (#{key_list.join(', ')}) VALUES (#{value_list.join(', ')})", "Fixture Insert"
|
327
320
|
end
|
328
321
|
|
329
322
|
def empty_insert_statement_value
|
@@ -333,17 +326,12 @@ module ActiveRecord
|
|
333
326
|
# Sanitizes the given LIMIT parameter in order to prevent SQL injection.
|
334
327
|
#
|
335
328
|
# The +limit+ may be anything that can evaluate to a string via #to_s. It
|
336
|
-
# should look like an integer, or
|
337
|
-
# an Arel SQL literal.
|
329
|
+
# should look like an integer, or an Arel SQL literal.
|
338
330
|
#
|
339
331
|
# Returns Integer and Arel::Nodes::SqlLiteral limits as is.
|
340
|
-
# Returns the sanitized limit parameter, either as an integer, or as a
|
341
|
-
# string which contains a comma-delimited list of integers.
|
342
332
|
def sanitize_limit(limit)
|
343
333
|
if limit.is_a?(Integer) || limit.is_a?(Arel::Nodes::SqlLiteral)
|
344
334
|
limit
|
345
|
-
elsif limit.to_s.include?(',')
|
346
|
-
Arel.sql limit.to_s.split(',').map{ |i| Integer(i) }.join(',')
|
347
335
|
else
|
348
336
|
Integer(limit)
|
349
337
|
end
|
@@ -359,7 +347,7 @@ module ActiveRecord
|
|
359
347
|
end
|
360
348
|
alias join_to_delete join_to_update
|
361
349
|
|
362
|
-
|
350
|
+
private
|
363
351
|
|
364
352
|
# Returns a subquery for the given key using the join information.
|
365
353
|
def subquery_for(key, select)
|
@@ -378,7 +366,7 @@ module ActiveRecord
|
|
378
366
|
end
|
379
367
|
|
380
368
|
def sql_for_insert(sql, pk, id_value, sequence_name, binds)
|
381
|
-
[sql, binds
|
369
|
+
[sql, binds]
|
382
370
|
end
|
383
371
|
|
384
372
|
def last_inserted_id(result)
|
@@ -46,7 +46,7 @@ module ActiveRecord
|
|
46
46
|
|
47
47
|
def initialize(*)
|
48
48
|
super
|
49
|
-
@query_cache = Hash.new { |h,sql| h[sql] = {} }
|
49
|
+
@query_cache = Hash.new { |h, sql| h[sql] = {} }
|
50
50
|
@query_cache_enabled = false
|
51
51
|
end
|
52
52
|
|
@@ -83,14 +83,16 @@ module ActiveRecord
|
|
83
83
|
# the same SQL query and repeatedly return the same result each time, silently
|
84
84
|
# undermining the randomness you were expecting.
|
85
85
|
def clear_query_cache
|
86
|
-
@
|
86
|
+
@lock.synchronize do
|
87
|
+
@query_cache.clear
|
88
|
+
end
|
87
89
|
end
|
88
90
|
|
89
91
|
def select_all(arel, name = nil, binds = [], preparable: nil)
|
90
92
|
if @query_cache_enabled && !locked?(arel)
|
91
93
|
arel, binds = binds_from_relation arel, binds
|
92
94
|
sql = to_sql(arel, binds)
|
93
|
-
cache_sql(sql, binds) { super(sql, name, binds, preparable: preparable) }
|
95
|
+
cache_sql(sql, name, binds) { super(sql, name, binds, preparable: preparable) }
|
94
96
|
else
|
95
97
|
super
|
96
98
|
end
|
@@ -98,33 +100,35 @@ module ActiveRecord
|
|
98
100
|
|
99
101
|
private
|
100
102
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
103
|
+
def cache_sql(sql, name, binds)
|
104
|
+
@lock.synchronize do
|
105
|
+
result =
|
106
|
+
if @query_cache[sql].key?(binds)
|
107
|
+
ActiveSupport::Notifications.instrument(
|
108
|
+
"sql.active_record",
|
109
|
+
sql: sql,
|
110
|
+
binds: binds,
|
111
|
+
name: name,
|
112
|
+
connection_id: object_id,
|
113
|
+
cached: true,
|
114
|
+
)
|
115
|
+
@query_cache[sql][binds]
|
116
|
+
else
|
117
|
+
@query_cache[sql][binds] = yield
|
118
|
+
end
|
119
|
+
result.dup
|
115
120
|
end
|
116
|
-
|
117
|
-
end
|
121
|
+
end
|
118
122
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
123
|
+
# If arel is locked this is a SELECT ... FOR UPDATE or somesuch. Such
|
124
|
+
# queries should not be cached.
|
125
|
+
def locked?(arel)
|
126
|
+
arel.respond_to?(:locked) && arel.locked
|
127
|
+
end
|
124
128
|
|
125
|
-
|
126
|
-
|
127
|
-
|
129
|
+
def configure_query_cache!
|
130
|
+
enable_query_cache! if pool.query_cache_enabled
|
131
|
+
end
|
128
132
|
end
|
129
133
|
end
|
130
134
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/core_ext/big_decimal/conversions"
|
2
2
|
require "active_support/multibyte/chars"
|
3
3
|
|
4
4
|
module ActiveRecord
|
@@ -6,20 +6,10 @@ module ActiveRecord
|
|
6
6
|
module Quoting
|
7
7
|
# Quotes the column value to help prevent
|
8
8
|
# {SQL injection attacks}[http://en.wikipedia.org/wiki/SQL_injection].
|
9
|
-
def quote(value
|
9
|
+
def quote(value)
|
10
10
|
# records are quoted as their primary key
|
11
11
|
return value.quoted_id if value.respond_to?(:quoted_id)
|
12
12
|
|
13
|
-
if column
|
14
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
15
|
-
Passing a column to `quote` has been deprecated. It is only used
|
16
|
-
for type casting, which should be handled elsewhere. See
|
17
|
-
https://github.com/rails/arel/commit/6160bfbda1d1781c3b08a33ec4955f170e95be11
|
18
|
-
for more information.
|
19
|
-
MSG
|
20
|
-
value = type_cast_from_column(column, value)
|
21
|
-
end
|
22
|
-
|
23
13
|
_quote(value)
|
24
14
|
end
|
25
15
|
|
@@ -117,7 +107,7 @@ module ActiveRecord
|
|
117
107
|
end
|
118
108
|
|
119
109
|
def unquoted_true
|
120
|
-
|
110
|
+
"t".freeze
|
121
111
|
end
|
122
112
|
|
123
113
|
def quoted_false
|
@@ -125,7 +115,7 @@ module ActiveRecord
|
|
125
115
|
end
|
126
116
|
|
127
117
|
def unquoted_false
|
128
|
-
|
118
|
+
"f".freeze
|
129
119
|
end
|
130
120
|
|
131
121
|
# Quote date/time values for use in SQL input. Includes microseconds
|
@@ -148,60 +138,57 @@ module ActiveRecord
|
|
148
138
|
end
|
149
139
|
|
150
140
|
def quoted_time(value) # :nodoc:
|
151
|
-
quoted_date(value).sub(/\
|
141
|
+
quoted_date(value).sub(/\A2000-01-01 /, "")
|
152
142
|
end
|
153
143
|
|
154
|
-
def
|
155
|
-
|
144
|
+
def quoted_binary(value) # :nodoc:
|
145
|
+
"'#{quote_string(value.to_s)}'"
|
156
146
|
end
|
157
147
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
else
|
148
|
+
private
|
149
|
+
|
150
|
+
def type_casted_binds(binds)
|
162
151
|
binds.map { |attr| type_cast(attr.value_for_database) }
|
163
152
|
end
|
164
|
-
end
|
165
153
|
|
166
|
-
|
154
|
+
def types_which_need_no_typecasting
|
155
|
+
[nil, Numeric, String]
|
156
|
+
end
|
167
157
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
when Class then "'#{value}'"
|
186
|
-
else raise TypeError, "can't quote #{value.class.name}"
|
158
|
+
def _quote(value)
|
159
|
+
case value
|
160
|
+
when String, ActiveSupport::Multibyte::Chars
|
161
|
+
"'#{quote_string(value.to_s)}'"
|
162
|
+
when true then quoted_true
|
163
|
+
when false then quoted_false
|
164
|
+
when nil then "NULL"
|
165
|
+
# BigDecimals need to be put in a non-normalized form and quoted.
|
166
|
+
when BigDecimal then value.to_s("F")
|
167
|
+
when Numeric, ActiveSupport::Duration then value.to_s
|
168
|
+
when Type::Binary::Data then quoted_binary(value)
|
169
|
+
when Type::Time::Value then "'#{quoted_time(value)}'"
|
170
|
+
when Date, Time then "'#{quoted_date(value)}'"
|
171
|
+
when Symbol then "'#{quote_string(value.to_s)}'"
|
172
|
+
when Class then "'#{value}'"
|
173
|
+
else raise TypeError, "can't quote #{value.class.name}"
|
174
|
+
end
|
187
175
|
end
|
188
|
-
end
|
189
176
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
177
|
+
def _type_cast(value)
|
178
|
+
case value
|
179
|
+
when Symbol, ActiveSupport::Multibyte::Chars, Type::Binary::Data
|
180
|
+
value.to_s
|
181
|
+
when true then unquoted_true
|
182
|
+
when false then unquoted_false
|
183
|
+
# BigDecimals need to be put in a non-normalized form and quoted.
|
184
|
+
when BigDecimal then value.to_s("F")
|
185
|
+
when Type::Time::Value then quoted_time(value)
|
186
|
+
when Date, Time then quoted_date(value)
|
187
|
+
when *types_which_need_no_typecasting
|
188
|
+
value
|
189
|
+
else raise TypeError
|
190
|
+
end
|
203
191
|
end
|
204
|
-
end
|
205
192
|
end
|
206
193
|
end
|
207
194
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/core_ext/string/strip"
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module ConnectionAdapters
|
@@ -15,21 +15,21 @@ module ActiveRecord
|
|
15
15
|
end
|
16
16
|
|
17
17
|
delegate :quote_column_name, :quote_table_name, :quote_default_expression, :type_to_sql,
|
18
|
-
:options_include_default?, :supports_indexes_in_create?, :
|
18
|
+
:options_include_default?, :supports_indexes_in_create?, :supports_foreign_keys_in_create?, :foreign_key_options, to: :@conn
|
19
19
|
private :quote_column_name, :quote_table_name, :quote_default_expression, :type_to_sql,
|
20
|
-
:options_include_default?, :supports_indexes_in_create?, :
|
20
|
+
:options_include_default?, :supports_indexes_in_create?, :supports_foreign_keys_in_create?, :foreign_key_options
|
21
21
|
|
22
22
|
private
|
23
23
|
|
24
24
|
def visit_AlterTable(o)
|
25
25
|
sql = "ALTER TABLE #{quote_table_name(o.name)} "
|
26
|
-
sql << o.adds.map { |col| accept col }.join(
|
27
|
-
sql << o.foreign_key_adds.map { |fk| visit_AddForeignKey fk }.join(
|
28
|
-
sql << o.foreign_key_drops.map { |fk| visit_DropForeignKey fk }.join(
|
26
|
+
sql << o.adds.map { |col| accept col }.join(" ")
|
27
|
+
sql << o.foreign_key_adds.map { |fk| visit_AddForeignKey fk }.join(" ")
|
28
|
+
sql << o.foreign_key_drops.map { |fk| visit_DropForeignKey fk }.join(" ")
|
29
29
|
end
|
30
30
|
|
31
31
|
def visit_ColumnDefinition(o)
|
32
|
-
o.sql_type
|
32
|
+
o.sql_type = type_to_sql(o.type, o.options)
|
33
33
|
column_sql = "#{quote_column_name(o.name)} #{o.sql_type}"
|
34
34
|
add_column_options!(column_sql, column_options(o)) unless o.type == :primary_key
|
35
35
|
column_sql
|
@@ -49,7 +49,7 @@ module ActiveRecord
|
|
49
49
|
statements.concat(o.indexes.map { |column_name, options| index_in_create(o.name, column_name, options) })
|
50
50
|
end
|
51
51
|
|
52
|
-
if
|
52
|
+
if supports_foreign_keys_in_create?
|
53
53
|
statements.concat(o.foreign_keys.map { |to_table, options| foreign_key_in_create(o.name, to_table, options) })
|
54
54
|
end
|
55
55
|
|
@@ -96,17 +96,7 @@ module ActiveRecord
|
|
96
96
|
end
|
97
97
|
|
98
98
|
def column_options(o)
|
99
|
-
|
100
|
-
column_options[:null] = o.null unless o.null.nil?
|
101
|
-
column_options[:default] = o.default unless o.default.nil?
|
102
|
-
column_options[:column] = o
|
103
|
-
column_options[:first] = o.first
|
104
|
-
column_options[:after] = o.after
|
105
|
-
column_options[:auto_increment] = o.auto_increment
|
106
|
-
column_options[:primary_key] = o.primary_key
|
107
|
-
column_options[:collation] = o.collation
|
108
|
-
column_options[:comment] = o.comment
|
109
|
-
column_options
|
99
|
+
o.options.merge(column: o)
|
110
100
|
end
|
111
101
|
|
112
102
|
def add_column_options!(sql, options)
|