activerecord 5.0.7 → 5.1.7
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 +657 -2080
- 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/aggregations.rb +244 -244
- data/lib/active_record/association_relation.rb +5 -5
- data/lib/active_record/associations/alias_tracker.rb +10 -11
- data/lib/active_record/associations/association.rb +23 -5
- data/lib/active_record/associations/association_scope.rb +95 -81
- data/lib/active_record/associations/belongs_to_association.rb +7 -4
- data/lib/active_record/associations/builder/belongs_to.rb +30 -16
- 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 +36 -205
- data/lib/active_record/associations/collection_proxy.rb +132 -63
- data/lib/active_record/associations/has_many_association.rb +10 -19
- data/lib/active_record/associations/has_many_through_association.rb +12 -4
- data/lib/active_record/associations/has_one_association.rb +24 -28
- data/lib/active_record/associations/has_one_through_association.rb +5 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +4 -28
- 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/join_dependency.rb +121 -118
- data/lib/active_record/associations/preloader/association.rb +64 -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 +41 -41
- data/lib/active_record/associations/preloader.rb +94 -94
- data/lib/active_record/associations/singular_association.rb +8 -25
- data/lib/active_record/associations/through_association.rb +2 -5
- data/lib/active_record/associations.rb +1591 -1562
- data/lib/active_record/attribute/user_provided_default.rb +4 -2
- data/lib/active_record/attribute.rb +98 -71
- data/lib/active_record/attribute_assignment.rb +61 -61
- data/lib/active_record/attribute_decorators.rb +35 -13
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
- data/lib/active_record/attribute_methods/dirty.rb +229 -46
- data/lib/active_record/attribute_methods/primary_key.rb +74 -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 +30 -33
- data/lib/active_record/attribute_methods.rb +56 -65
- data/lib/active_record/attribute_mutation_tracker.rb +63 -11
- data/lib/active_record/attribute_set/builder.rb +27 -33
- data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
- data/lib/active_record/attribute_set.rb +9 -6
- data/lib/active_record/attributes.rb +22 -22
- data/lib/active_record/autosave_association.rb +18 -13
- data/lib/active_record/base.rb +24 -22
- data/lib/active_record/callbacks.rb +56 -14
- data/lib/active_record/coders/yaml_column.rb +9 -11
- data/lib/active_record/collection_cache_key.rb +3 -4
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +330 -284
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +39 -37
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +32 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +62 -51
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +10 -20
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +74 -79
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +120 -100
- data/lib/active_record/connection_adapters/abstract/transaction.rb +49 -43
- data/lib/active_record/connection_adapters/abstract_adapter.rb +165 -135
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +404 -424
- data/lib/active_record/connection_adapters/column.rb +26 -4
- 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 +36 -49
- 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 +54 -28
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +43 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +7 -6
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +23 -27
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +32 -53
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
- 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/decimal.rb +1 -1
- 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/jsonb.rb +0 -10
- 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 +32 -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/oid.rb +22 -21
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +40 -35
- 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 +182 -222
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +6 -4
- data/lib/active_record/connection_adapters/postgresql/utils.rb +7 -5
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +198 -167
- 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 -19
- 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/schema_statements.rb +32 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +184 -167
- 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 +109 -93
- data/lib/active_record/counter_cache.rb +60 -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 +64 -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 +1 -1
- 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 +69 -74
- data/lib/active_record/locking/pessimistic.rb +10 -1
- data/lib/active_record/log_subscriber.rb +23 -28
- data/lib/active_record/migration/command_recorder.rb +94 -94
- data/lib/active_record/migration/compatibility.rb +100 -47
- data/lib/active_record/migration/join_table.rb +6 -6
- data/lib/active_record/migration.rb +153 -155
- data/lib/active_record/model_schema.rb +94 -107
- data/lib/active_record/nested_attributes.rb +200 -199
- data/lib/active_record/null_relation.rb +11 -34
- data/lib/active_record/persistence.rb +65 -50
- data/lib/active_record/query_cache.rb +2 -6
- data/lib/active_record/querying.rb +3 -4
- 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 +105 -133
- 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 +154 -108
- data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
- data/lib/active_record/relation/batches.rb +80 -51
- data/lib/active_record/relation/calculations.rb +169 -162
- data/lib/active_record/relation/delegation.rb +32 -31
- data/lib/active_record/relation/finder_methods.rb +197 -231
- data/lib/active_record/relation/merger.rb +58 -62
- 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/predicate_builder.rb +92 -89
- data/lib/active_record/relation/query_attribute.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +255 -293
- 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 +80 -65
- data/lib/active_record/relation/where_clause_factory.rb +47 -8
- data/lib/active_record/relation.rb +93 -119
- data/lib/active_record/result.rb +41 -32
- data/lib/active_record/runtime_registry.rb +3 -3
- data/lib/active_record/sanitization.rb +176 -192
- data/lib/active_record/schema.rb +3 -3
- data/lib/active_record/schema_dumper.rb +15 -38
- data/lib/active_record/schema_migration.rb +8 -4
- data/lib/active_record/scoping/default.rb +90 -90
- data/lib/active_record/scoping/named.rb +11 -11
- data/lib/active_record/scoping.rb +6 -6
- 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 +65 -55
- data/lib/active_record/tasks/mysql_database_tasks.rb +76 -73
- data/lib/active_record/tasks/postgresql_database_tasks.rb +72 -47
- data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
- data/lib/active_record/timestamp.rb +46 -25
- data/lib/active_record/touch_later.rb +1 -2
- data/lib/active_record/transactions.rb +97 -109
- data/lib/active_record/type/adapter_specific_registry.rb +46 -42
- data/lib/active_record/type/decimal_without_scale.rb +13 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
- data/lib/active_record/type/internal/abstract_json.rb +4 -0
- data/lib/active_record/type/serialized.rb +14 -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.rb +17 -13
- data/lib/active_record/type_caster/connection.rb +8 -6
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/type_caster.rb +2 -2
- 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/validations.rb +4 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +20 -20
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
- data/lib/rails/generators/active_record/migration.rb +1 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
- data/lib/rails/generators/active_record.rb +4 -4
- metadata +24 -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,23 +51,31 @@ module ActiveRecord
|
|
50
51
|
|
51
52
|
# Returns a single value from a record
|
52
53
|
def select_value(arel, name = nil, binds = [])
|
53
|
-
arel,
|
54
|
-
if result = select_rows(to_sql(arel, binds), name, binds).first
|
55
|
-
result.first
|
56
|
-
end
|
54
|
+
single_value_from_rows(select_rows(arel, name, binds))
|
57
55
|
end
|
58
56
|
|
59
57
|
# Returns an array of the values of the first column in a select:
|
60
58
|
# select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
|
61
59
|
def select_values(arel, name = nil, binds = [])
|
62
|
-
arel,
|
63
|
-
select_rows(to_sql(arel, binds), name, binds).map(&:first)
|
60
|
+
select_rows(arel, name, binds).map(&:first)
|
64
61
|
end
|
65
62
|
|
66
63
|
# Returns an array of arrays containing the field values.
|
67
64
|
# Order is the same as that returned by +columns+.
|
68
|
-
def select_rows(
|
69
|
-
|
65
|
+
def select_rows(arel, name = nil, binds = [])
|
66
|
+
select_all(arel, name, binds).rows
|
67
|
+
end
|
68
|
+
|
69
|
+
def query_value(sql, name = nil) # :nodoc:
|
70
|
+
single_value_from_rows(query(sql, name))
|
71
|
+
end
|
72
|
+
|
73
|
+
def query_values(sql, name = nil) # :nodoc:
|
74
|
+
query(sql, name).map(&:first)
|
75
|
+
end
|
76
|
+
|
77
|
+
def query(sql, name = nil) # :nodoc:
|
78
|
+
exec_query(sql, name).rows
|
70
79
|
end
|
71
80
|
|
72
81
|
# Executes the SQL statement in the context of this connection and returns
|
@@ -81,21 +90,22 @@ module ActiveRecord
|
|
81
90
|
# Executes +sql+ statement in the context of this connection using
|
82
91
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
83
92
|
# the executed +sql+ statement.
|
84
|
-
def exec_query(sql, name =
|
93
|
+
def exec_query(sql, name = "SQL", binds = [], prepare: false)
|
85
94
|
raise NotImplementedError
|
86
95
|
end
|
87
96
|
|
88
97
|
# Executes insert +sql+ statement in the context of this connection using
|
89
98
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
90
99
|
# the executed +sql+ statement.
|
91
|
-
def exec_insert(sql, name, binds, pk = nil, sequence_name = nil)
|
100
|
+
def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
|
101
|
+
sql, binds = sql_for_insert(sql, pk, nil, sequence_name, binds)
|
92
102
|
exec_query(sql, name, binds)
|
93
103
|
end
|
94
104
|
|
95
105
|
# Executes delete +sql+ statement in the context of this connection using
|
96
106
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
97
107
|
# the executed +sql+ statement.
|
98
|
-
def exec_delete(sql, name, binds)
|
108
|
+
def exec_delete(sql, name = nil, binds = [])
|
99
109
|
exec_query(sql, name, binds)
|
100
110
|
end
|
101
111
|
|
@@ -107,40 +117,33 @@ module ActiveRecord
|
|
107
117
|
# Executes update +sql+ statement in the context of this connection using
|
108
118
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
109
119
|
# the executed +sql+ statement.
|
110
|
-
def exec_update(sql, name, binds)
|
120
|
+
def exec_update(sql, name = nil, binds = [])
|
111
121
|
exec_query(sql, name, binds)
|
112
122
|
end
|
113
123
|
|
114
124
|
# Executes an INSERT query and returns the new record's ID
|
115
125
|
#
|
116
|
-
# +id_value+ will be returned unless the value is nil
|
126
|
+
# +id_value+ will be returned unless the value is +nil+, in
|
117
127
|
# which case the database will attempt to calculate the last inserted
|
118
128
|
# id and return that value.
|
119
129
|
#
|
120
130
|
# If the next id was calculated in advance (as in Oracle), it should be
|
121
131
|
# passed in as +id_value+.
|
122
132
|
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)
|
133
|
+
value = exec_insert(to_sql(arel, binds), name, binds, pk, sequence_name)
|
125
134
|
id_value || last_inserted_id(value)
|
126
135
|
end
|
127
136
|
alias create insert
|
128
|
-
alias insert_sql insert
|
129
|
-
deprecate insert_sql: :insert
|
130
137
|
|
131
138
|
# Executes the update statement and returns the number of rows affected.
|
132
139
|
def update(arel, name = nil, binds = [])
|
133
140
|
exec_update(to_sql(arel, binds), name, binds)
|
134
141
|
end
|
135
|
-
alias update_sql update
|
136
|
-
deprecate update_sql: :update
|
137
142
|
|
138
143
|
# Executes the delete statement and returns the number of rows affected.
|
139
144
|
def delete(arel, name = nil, binds = [])
|
140
145
|
exec_delete(to_sql(arel, binds), name, binds)
|
141
146
|
end
|
142
|
-
alias delete_sql delete
|
143
|
-
deprecate delete_sql: :delete
|
144
147
|
|
145
148
|
# Returns +true+ when the connection adapter supports prepared statement
|
146
149
|
# caching, otherwise returns +false+
|
@@ -315,7 +318,7 @@ module ActiveRecord
|
|
315
318
|
end
|
316
319
|
end
|
317
320
|
key_list = fixture.keys.map { |name| quote_column_name(name) }
|
318
|
-
value_list =
|
321
|
+
value_list = binds.map(&:value_for_database).map do |value|
|
319
322
|
begin
|
320
323
|
quote(value)
|
321
324
|
rescue TypeError
|
@@ -323,7 +326,7 @@ module ActiveRecord
|
|
323
326
|
end
|
324
327
|
end
|
325
328
|
|
326
|
-
execute "INSERT INTO #{quote_table_name(table_name)} (#{key_list.join(', ')}) VALUES (#{value_list.join(', ')})",
|
329
|
+
execute "INSERT INTO #{quote_table_name(table_name)} (#{key_list.join(', ')}) VALUES (#{value_list.join(', ')})", "Fixture Insert"
|
327
330
|
end
|
328
331
|
|
329
332
|
def empty_insert_statement_value
|
@@ -333,17 +336,12 @@ module ActiveRecord
|
|
333
336
|
# Sanitizes the given LIMIT parameter in order to prevent SQL injection.
|
334
337
|
#
|
335
338
|
# 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.
|
339
|
+
# should look like an integer, or an Arel SQL literal.
|
338
340
|
#
|
339
341
|
# 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
342
|
def sanitize_limit(limit)
|
343
343
|
if limit.is_a?(Integer) || limit.is_a?(Arel::Nodes::SqlLiteral)
|
344
344
|
limit
|
345
|
-
elsif limit.to_s.include?(',')
|
346
|
-
Arel.sql limit.to_s.split(',').map{ |i| Integer(i) }.join(',')
|
347
345
|
else
|
348
346
|
Integer(limit)
|
349
347
|
end
|
@@ -359,7 +357,7 @@ module ActiveRecord
|
|
359
357
|
end
|
360
358
|
alias join_to_delete join_to_update
|
361
359
|
|
362
|
-
|
360
|
+
private
|
363
361
|
|
364
362
|
# Returns a subquery for the given key using the join information.
|
365
363
|
def subquery_for(key, select)
|
@@ -378,11 +376,15 @@ module ActiveRecord
|
|
378
376
|
end
|
379
377
|
|
380
378
|
def sql_for_insert(sql, pk, id_value, sequence_name, binds)
|
381
|
-
[sql, binds
|
379
|
+
[sql, binds]
|
382
380
|
end
|
383
381
|
|
384
382
|
def last_inserted_id(result)
|
385
|
-
|
383
|
+
single_value_from_rows(result.rows)
|
384
|
+
end
|
385
|
+
|
386
|
+
def single_value_from_rows(rows)
|
387
|
+
row = rows.first
|
386
388
|
row && row.first
|
387
389
|
end
|
388
390
|
|
@@ -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,36 @@ 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
|
+
type_casted_binds: -> { type_casted_binds(binds) },
|
112
|
+
name: name,
|
113
|
+
connection_id: object_id,
|
114
|
+
cached: true,
|
115
|
+
)
|
116
|
+
@query_cache[sql][binds]
|
117
|
+
else
|
118
|
+
@query_cache[sql][binds] = yield
|
119
|
+
end
|
120
|
+
result.dup
|
115
121
|
end
|
116
|
-
|
117
|
-
end
|
122
|
+
end
|
118
123
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
+
# If arel is locked this is a SELECT ... FOR UPDATE or somesuch. Such
|
125
|
+
# queries should not be cached.
|
126
|
+
def locked?(arel)
|
127
|
+
arel.respond_to?(:locked) && arel.locked
|
128
|
+
end
|
124
129
|
|
125
|
-
|
126
|
-
|
127
|
-
|
130
|
+
def configure_query_cache!
|
131
|
+
enable_query_cache! if pool.query_cache_enabled
|
132
|
+
end
|
128
133
|
end
|
129
134
|
end
|
130
135
|
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,18 +6,20 @@ 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
|
10
|
-
|
11
|
-
return value.quoted_id if value.respond_to?(:quoted_id)
|
9
|
+
def quote(value)
|
10
|
+
value = id_value_for_database(value) if value.is_a?(Base)
|
12
11
|
|
13
|
-
if
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
12
|
+
if value.respond_to?(:quoted_id)
|
13
|
+
at = value.method(:quoted_id).source_location
|
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
|
21
23
|
end
|
22
24
|
|
23
25
|
_quote(value)
|
@@ -27,6 +29,8 @@ module ActiveRecord
|
|
27
29
|
# SQLite does not understand dates, so this method will convert a Date
|
28
30
|
# to a String.
|
29
31
|
def type_cast(value, column = nil)
|
32
|
+
value = id_value_for_database(value) if value.is_a?(Base)
|
33
|
+
|
30
34
|
if value.respond_to?(:quoted_id) && value.respond_to?(:id)
|
31
35
|
return value.id
|
32
36
|
end
|
@@ -117,7 +121,7 @@ module ActiveRecord
|
|
117
121
|
end
|
118
122
|
|
119
123
|
def unquoted_true
|
120
|
-
|
124
|
+
"t".freeze
|
121
125
|
end
|
122
126
|
|
123
127
|
def quoted_false
|
@@ -125,7 +129,7 @@ module ActiveRecord
|
|
125
129
|
end
|
126
130
|
|
127
131
|
def unquoted_false
|
128
|
-
|
132
|
+
"f".freeze
|
129
133
|
end
|
130
134
|
|
131
135
|
# Quote date/time values for use in SQL input. Includes microseconds
|
@@ -148,11 +152,12 @@ module ActiveRecord
|
|
148
152
|
end
|
149
153
|
|
150
154
|
def quoted_time(value) # :nodoc:
|
151
|
-
|
155
|
+
value = value.change(year: 2000, month: 1, day: 1)
|
156
|
+
quoted_date(value).sub(/\A\d\d\d\d-\d\d-\d\d /, "")
|
152
157
|
end
|
153
158
|
|
154
|
-
def
|
155
|
-
|
159
|
+
def quoted_binary(value) # :nodoc:
|
160
|
+
"'#{quote_string(value.to_s)}'"
|
156
161
|
end
|
157
162
|
|
158
163
|
def type_casted_binds(binds) # :nodoc:
|
@@ -164,44 +169,50 @@ module ActiveRecord
|
|
164
169
|
end
|
165
170
|
|
166
171
|
private
|
172
|
+
def id_value_for_database(value)
|
173
|
+
if primary_key = value.class.primary_key
|
174
|
+
value.instance_variable_get(:@attributes)[primary_key].value_for_database
|
175
|
+
end
|
176
|
+
end
|
167
177
|
|
168
|
-
|
169
|
-
|
170
|
-
end
|
171
|
-
|
172
|
-
def _quote(value)
|
173
|
-
case value
|
174
|
-
when String, ActiveSupport::Multibyte::Chars, Type::Binary::Data
|
175
|
-
"'#{quote_string(value.to_s)}'"
|
176
|
-
when true then quoted_true
|
177
|
-
when false then quoted_false
|
178
|
-
when nil then "NULL"
|
179
|
-
# BigDecimals need to be put in a non-normalized form and quoted.
|
180
|
-
when BigDecimal then value.to_s('F')
|
181
|
-
when Numeric, ActiveSupport::Duration then value.to_s
|
182
|
-
when Type::Time::Value then "'#{quoted_time(value)}'"
|
183
|
-
when Date, Time then "'#{quoted_date(value)}'"
|
184
|
-
when Symbol then "'#{quote_string(value.to_s)}'"
|
185
|
-
when Class then "'#{value}'"
|
186
|
-
else raise TypeError, "can't quote #{value.class.name}"
|
178
|
+
def types_which_need_no_typecasting
|
179
|
+
[nil, Numeric, String]
|
187
180
|
end
|
188
|
-
end
|
189
181
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
value
|
202
|
-
|
182
|
+
def _quote(value)
|
183
|
+
case value
|
184
|
+
when String, ActiveSupport::Multibyte::Chars
|
185
|
+
"'#{quote_string(value.to_s)}'"
|
186
|
+
when true then quoted_true
|
187
|
+
when false then quoted_false
|
188
|
+
when nil then "NULL"
|
189
|
+
# BigDecimals need to be put in a non-normalized form and quoted.
|
190
|
+
when BigDecimal then value.to_s("F")
|
191
|
+
when Numeric, ActiveSupport::Duration then value.to_s
|
192
|
+
when Type::Binary::Data then quoted_binary(value)
|
193
|
+
when Type::Time::Value then "'#{quoted_time(value)}'"
|
194
|
+
when Date, Time then "'#{quoted_date(value)}'"
|
195
|
+
when Symbol then "'#{quote_string(value.to_s)}'"
|
196
|
+
when Class then "'#{value}'"
|
197
|
+
else raise TypeError, "can't quote #{value.class.name}"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def _type_cast(value)
|
202
|
+
case value
|
203
|
+
when Symbol, ActiveSupport::Multibyte::Chars, Type::Binary::Data
|
204
|
+
value.to_s
|
205
|
+
when true then unquoted_true
|
206
|
+
when false then unquoted_false
|
207
|
+
# BigDecimals need to be put in a non-normalized form and quoted.
|
208
|
+
when BigDecimal then value.to_s("F")
|
209
|
+
when Type::Time::Value then quoted_time(value)
|
210
|
+
when Date, Time then quoted_date(value)
|
211
|
+
when *types_which_need_no_typecasting
|
212
|
+
value
|
213
|
+
else raise TypeError
|
214
|
+
end
|
203
215
|
end
|
204
|
-
end
|
205
216
|
end
|
206
217
|
end
|
207
218
|
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
|
|
@@ -60,7 +60,7 @@ module ActiveRecord
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def visit_PrimaryKeyDefinition(o)
|
63
|
-
"PRIMARY KEY (#{o.name.join(', ')})"
|
63
|
+
"PRIMARY KEY (#{o.name.map { |name| quote_column_name(name) }.join(', ')})"
|
64
64
|
end
|
65
65
|
|
66
66
|
def visit_ForeignKeyDefinition(o)
|
@@ -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)
|