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.

Files changed (259) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +221 -900
  3. data/README.rdoc +3 -3
  4. data/examples/performance.rb +2 -0
  5. data/examples/simple.rb +2 -0
  6. data/lib/active_record.rb +10 -3
  7. data/lib/active_record/aggregations.rb +2 -0
  8. data/lib/active_record/association_relation.rb +2 -0
  9. data/lib/active_record/associations.rb +13 -42
  10. data/lib/active_record/associations/alias_tracker.rb +17 -17
  11. data/lib/active_record/associations/association.rb +11 -22
  12. data/lib/active_record/associations/association_scope.rb +32 -44
  13. data/lib/active_record/associations/belongs_to_association.rb +6 -4
  14. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -1
  15. data/lib/active_record/associations/builder/association.rb +2 -5
  16. data/lib/active_record/associations/builder/belongs_to.rb +7 -12
  17. data/lib/active_record/associations/builder/collection_association.rb +1 -1
  18. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
  19. data/lib/active_record/associations/builder/has_many.rb +2 -0
  20. data/lib/active_record/associations/builder/has_one.rb +2 -0
  21. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  22. data/lib/active_record/associations/collection_association.rb +41 -33
  23. data/lib/active_record/associations/collection_proxy.rb +11 -14
  24. data/lib/active_record/associations/foreign_association.rb +2 -0
  25. data/lib/active_record/associations/has_many_association.rb +4 -2
  26. data/lib/active_record/associations/has_many_through_association.rb +4 -2
  27. data/lib/active_record/associations/has_one_association.rb +3 -1
  28. data/lib/active_record/associations/has_one_through_association.rb +3 -1
  29. data/lib/active_record/associations/join_dependency.rb +22 -40
  30. data/lib/active_record/associations/join_dependency/join_association.rb +17 -56
  31. data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
  32. data/lib/active_record/associations/join_dependency/join_part.rb +2 -9
  33. data/lib/active_record/associations/preloader.rb +17 -37
  34. data/lib/active_record/associations/preloader/association.rb +42 -58
  35. data/lib/active_record/associations/preloader/through_association.rb +71 -79
  36. data/lib/active_record/associations/singular_association.rb +14 -10
  37. data/lib/active_record/associations/through_association.rb +3 -1
  38. data/lib/active_record/attribute_assignment.rb +2 -0
  39. data/lib/active_record/attribute_decorators.rb +3 -2
  40. data/lib/active_record/attribute_methods.rb +47 -7
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
  42. data/lib/active_record/attribute_methods/dirty.rb +25 -214
  43. data/lib/active_record/attribute_methods/primary_key.rb +7 -6
  44. data/lib/active_record/attribute_methods/query.rb +2 -0
  45. data/lib/active_record/attribute_methods/read.rb +8 -2
  46. data/lib/active_record/attribute_methods/serialization.rb +23 -0
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
  48. data/lib/active_record/attribute_methods/write.rb +21 -9
  49. data/lib/active_record/attributes.rb +7 -6
  50. data/lib/active_record/autosave_association.rb +5 -11
  51. data/lib/active_record/base.rb +2 -0
  52. data/lib/active_record/callbacks.rb +6 -8
  53. data/lib/active_record/coders/json.rb +2 -0
  54. data/lib/active_record/coders/yaml_column.rb +2 -0
  55. data/lib/active_record/collection_cache_key.rb +10 -5
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +110 -35
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +120 -28
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +7 -2
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +14 -33
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +13 -5
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +40 -2
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +103 -63
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +62 -90
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +75 -138
  69. data/lib/active_record/connection_adapters/column.rb +3 -1
  70. data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +3 -1
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -6
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +91 -1
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +2 -0
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -0
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -1
  86. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -11
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -1
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
  99. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +3 -5
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  107. data/lib/active_record/connection_adapters/postgresql/quoting.rb +10 -0
  108. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
  109. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +2 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +11 -7
  111. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
  112. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +79 -65
  113. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
  114. data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -0
  115. data/lib/active_record/connection_adapters/postgresql_adapter.rb +47 -82
  116. data/lib/active_record/connection_adapters/schema_cache.rb +2 -0
  117. data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
  118. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
  119. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +19 -2
  120. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
  121. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
  122. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
  123. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +71 -1
  124. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +34 -89
  125. data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
  126. data/lib/active_record/connection_handling.rb +4 -2
  127. data/lib/active_record/core.rb +27 -57
  128. data/lib/active_record/counter_cache.rb +15 -12
  129. data/lib/active_record/define_callbacks.rb +5 -3
  130. data/lib/active_record/dynamic_matchers.rb +9 -9
  131. data/lib/active_record/enum.rb +15 -13
  132. data/lib/active_record/errors.rb +54 -21
  133. data/lib/active_record/explain.rb +3 -1
  134. data/lib/active_record/explain_registry.rb +2 -0
  135. data/lib/active_record/explain_subscriber.rb +2 -0
  136. data/lib/active_record/fixture_set/file.rb +2 -0
  137. data/lib/active_record/fixtures.rb +40 -24
  138. data/lib/active_record/gem_version.rb +5 -3
  139. data/lib/active_record/inheritance.rb +6 -5
  140. data/lib/active_record/integration.rb +58 -19
  141. data/lib/active_record/internal_metadata.rb +2 -0
  142. data/lib/active_record/legacy_yaml_adapter.rb +3 -1
  143. data/lib/active_record/locking/optimistic.rb +31 -20
  144. data/lib/active_record/locking/pessimistic.rb +10 -7
  145. data/lib/active_record/log_subscriber.rb +2 -0
  146. data/lib/active_record/migration.rb +47 -21
  147. data/lib/active_record/migration/command_recorder.rb +11 -9
  148. data/lib/active_record/migration/compatibility.rb +20 -2
  149. data/lib/active_record/migration/join_table.rb +2 -0
  150. data/lib/active_record/model_schema.rb +29 -38
  151. data/lib/active_record/nested_attributes.rb +18 -6
  152. data/lib/active_record/no_touching.rb +3 -1
  153. data/lib/active_record/null_relation.rb +2 -0
  154. data/lib/active_record/persistence.rb +184 -40
  155. data/lib/active_record/query_cache.rb +17 -12
  156. data/lib/active_record/querying.rb +3 -1
  157. data/lib/active_record/railtie.rb +54 -1
  158. data/lib/active_record/railties/console_sandbox.rb +2 -0
  159. data/lib/active_record/railties/controller_runtime.rb +2 -0
  160. data/lib/active_record/railties/databases.rake +41 -28
  161. data/lib/active_record/readonly_attributes.rb +3 -2
  162. data/lib/active_record/reflection.rb +100 -182
  163. data/lib/active_record/relation.rb +61 -193
  164. data/lib/active_record/relation/batches.rb +20 -5
  165. data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
  166. data/lib/active_record/relation/calculations.rb +40 -23
  167. data/lib/active_record/relation/delegation.rb +10 -27
  168. data/lib/active_record/relation/finder_methods.rb +53 -49
  169. data/lib/active_record/relation/from_clause.rb +2 -8
  170. data/lib/active_record/relation/merger.rb +22 -19
  171. data/lib/active_record/relation/predicate_builder.rb +42 -79
  172. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
  173. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  174. data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
  175. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
  176. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +54 -0
  177. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -6
  178. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  179. data/lib/active_record/relation/query_attribute.rb +9 -2
  180. data/lib/active_record/relation/query_methods.rb +80 -69
  181. data/lib/active_record/relation/record_fetch_warning.rb +2 -0
  182. data/lib/active_record/relation/spawn_methods.rb +2 -0
  183. data/lib/active_record/relation/where_clause.rb +50 -67
  184. data/lib/active_record/relation/where_clause_factory.rb +4 -46
  185. data/lib/active_record/result.rb +2 -0
  186. data/lib/active_record/runtime_registry.rb +2 -0
  187. data/lib/active_record/sanitization.rb +15 -9
  188. data/lib/active_record/schema.rb +3 -1
  189. data/lib/active_record/schema_dumper.rb +24 -23
  190. data/lib/active_record/schema_migration.rb +2 -0
  191. data/lib/active_record/scoping.rb +9 -8
  192. data/lib/active_record/scoping/default.rb +6 -7
  193. data/lib/active_record/scoping/named.rb +15 -7
  194. data/lib/active_record/secure_token.rb +2 -0
  195. data/lib/active_record/serialization.rb +2 -0
  196. data/lib/active_record/statement_cache.rb +22 -12
  197. data/lib/active_record/store.rb +2 -0
  198. data/lib/active_record/suppressor.rb +2 -0
  199. data/lib/active_record/table_metadata.rb +3 -1
  200. data/lib/active_record/tasks/database_tasks.rb +23 -12
  201. data/lib/active_record/tasks/mysql_database_tasks.rb +9 -48
  202. data/lib/active_record/tasks/postgresql_database_tasks.rb +10 -2
  203. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
  204. data/lib/active_record/timestamp.rb +5 -12
  205. data/lib/active_record/touch_later.rb +2 -0
  206. data/lib/active_record/transactions.rb +9 -7
  207. data/lib/active_record/translation.rb +2 -0
  208. data/lib/active_record/type.rb +4 -1
  209. data/lib/active_record/type/adapter_specific_registry.rb +2 -0
  210. data/lib/active_record/type/date.rb +2 -0
  211. data/lib/active_record/type/date_time.rb +2 -0
  212. data/lib/active_record/type/decimal_without_scale.rb +2 -0
  213. data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
  214. data/lib/active_record/type/internal/timezone.rb +2 -0
  215. data/lib/active_record/type/json.rb +30 -0
  216. data/lib/active_record/type/serialized.rb +2 -4
  217. data/lib/active_record/type/text.rb +2 -0
  218. data/lib/active_record/type/time.rb +2 -0
  219. data/lib/active_record/type/type_map.rb +2 -0
  220. data/lib/active_record/type/unsigned_integer.rb +2 -0
  221. data/lib/active_record/type_caster.rb +2 -0
  222. data/lib/active_record/type_caster/connection.rb +2 -0
  223. data/lib/active_record/type_caster/map.rb +2 -0
  224. data/lib/active_record/validations.rb +2 -0
  225. data/lib/active_record/validations/absence.rb +2 -0
  226. data/lib/active_record/validations/associated.rb +2 -0
  227. data/lib/active_record/validations/length.rb +2 -0
  228. data/lib/active_record/validations/presence.rb +2 -0
  229. data/lib/active_record/validations/uniqueness.rb +36 -6
  230. data/lib/active_record/version.rb +2 -0
  231. data/lib/rails/generators/active_record.rb +3 -1
  232. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  233. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  234. data/lib/rails/generators/active_record/migration.rb +2 -0
  235. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
  236. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
  237. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
  238. data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
  239. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
  240. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  241. metadata +25 -38
  242. data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
  243. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  244. data/lib/active_record/associations/preloader/has_many.rb +0 -15
  245. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  246. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  247. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  248. data/lib/active_record/associations/preloader/singular_association.rb +0 -18
  249. data/lib/active_record/attribute.rb +0 -240
  250. data/lib/active_record/attribute/user_provided_default.rb +0 -30
  251. data/lib/active_record/attribute_mutation_tracker.rb +0 -122
  252. data/lib/active_record/attribute_set.rb +0 -113
  253. data/lib/active_record/attribute_set/builder.rb +0 -126
  254. data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
  255. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
  256. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  257. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  258. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
  259. 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
  class Relation
3
5
  module RecordFetchWarning
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/hash/except"
2
4
  require "active_support/core_ext/hash/slice"
3
5
  require "active_record/relation/merger"
@@ -1,43 +1,48 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  class Relation
3
5
  class WhereClause # :nodoc:
4
- attr_reader :binds
5
-
6
6
  delegate :any?, :empty?, to: :predicates
7
7
 
8
- def initialize(predicates, binds)
8
+ def initialize(predicates)
9
9
  @predicates = predicates
10
- @binds = binds
11
10
  end
12
11
 
13
12
  def +(other)
14
13
  WhereClause.new(
15
14
  predicates + other.predicates,
16
- binds + other.binds,
15
+ )
16
+ end
17
+
18
+ def -(other)
19
+ WhereClause.new(
20
+ predicates - other.predicates,
17
21
  )
18
22
  end
19
23
 
20
24
  def merge(other)
21
25
  WhereClause.new(
22
26
  predicates_unreferenced_by(other) + other.predicates,
23
- non_conflicting_binds(other) + other.binds,
24
27
  )
25
28
  end
26
29
 
27
30
  def except(*columns)
28
- WhereClause.new(*except_predicates_and_binds(columns))
31
+ WhereClause.new(except_predicates(columns))
29
32
  end
30
33
 
31
34
  def or(other)
32
- if empty?
33
- self
34
- elsif other.empty?
35
- other
35
+ left = self - other
36
+ common = self - left
37
+ right = other - common
38
+
39
+ if left.empty? || right.empty?
40
+ common
36
41
  else
37
- WhereClause.new(
38
- [ast.or(other.ast)],
39
- binds + other.binds
42
+ or_clause = WhereClause.new(
43
+ [left.ast.or(right.ast)],
40
44
  )
45
+ common + or_clause
41
46
  end
42
47
  end
43
48
 
@@ -49,17 +54,10 @@ module ActiveRecord
49
54
  end
50
55
  end
51
56
 
52
- binds = self.binds.map { |attr| [attr.name, attr.value] }.to_h
53
-
54
57
  equalities.map { |node|
55
- name = node.left.name
56
- [name, binds.fetch(name.to_s) {
57
- case node.right
58
- when Array then node.right.map(&:val)
59
- when Arel::Nodes::Casted, Arel::Nodes::Quoted
60
- node.right.val
61
- end
62
- }]
58
+ name = node.left.name.to_s
59
+ value = extract_node_value(node.right)
60
+ [name, value]
63
61
  }.to_h
64
62
  end
65
63
 
@@ -69,20 +67,17 @@ module ActiveRecord
69
67
 
70
68
  def ==(other)
71
69
  other.is_a?(WhereClause) &&
72
- predicates == other.predicates &&
73
- binds == other.binds
70
+ predicates == other.predicates
74
71
  end
75
72
 
76
73
  def invert
77
- WhereClause.new(inverted_predicates, binds)
74
+ WhereClause.new(inverted_predicates)
78
75
  end
79
76
 
80
77
  def self.empty
81
- @empty ||= new([], [])
78
+ @empty ||= new([])
82
79
  end
83
80
 
84
- # TODO Change this to private once we've dropped Ruby 2.2 support.
85
- # Workaround for Ruby 2.2 "private attribute?" warning.
86
81
  protected
87
82
 
88
83
  attr_reader :predicates
@@ -106,12 +101,6 @@ module ActiveRecord
106
101
  node.respond_to?(:operator) && node.operator == :==
107
102
  end
108
103
 
109
- def non_conflicting_binds(other)
110
- conflicts = referenced_columns & other.referenced_columns
111
- conflicts.map! { |node| node.name.to_s }
112
- binds.reject { |attr| conflicts.include?(attr.name) }
113
- end
114
-
115
104
  def inverted_predicates
116
105
  predicates.map { |node| invert_predicate(node) }
117
106
  end
@@ -131,44 +120,22 @@ module ActiveRecord
131
120
  end
132
121
  end
133
122
 
134
- def except_predicates_and_binds(columns)
135
- except_binds = []
136
- binds_index = 0
137
-
138
- predicates = self.predicates.reject do |node|
139
- binds_contains = node.grep(Arel::Nodes::BindParam).size if node.is_a?(Arel::Nodes::Node)
140
-
141
- except = \
142
- case node
143
- when Arel::Nodes::Between, Arel::Nodes::In, Arel::Nodes::NotIn, Arel::Nodes::Equality, Arel::Nodes::NotEqual, Arel::Nodes::LessThan, Arel::Nodes::LessThanOrEqual, Arel::Nodes::GreaterThan, Arel::Nodes::GreaterThanOrEqual
144
- subrelation = (node.left.kind_of?(Arel::Attributes::Attribute) ? node.left : node.right)
145
- columns.include?(subrelation.name.to_s)
146
- end
147
-
148
- if except && binds_contains > 0
149
- (binds_index...(binds_index + binds_contains)).each do |i|
150
- except_binds[i] = true
151
- end
123
+ def except_predicates(columns)
124
+ self.predicates.reject do |node|
125
+ case node
126
+ when Arel::Nodes::Between, Arel::Nodes::In, Arel::Nodes::NotIn, Arel::Nodes::Equality, Arel::Nodes::NotEqual, Arel::Nodes::LessThan, Arel::Nodes::LessThanOrEqual, Arel::Nodes::GreaterThan, Arel::Nodes::GreaterThanOrEqual
127
+ subrelation = (node.left.kind_of?(Arel::Attributes::Attribute) ? node.left : node.right)
128
+ columns.include?(subrelation.name.to_s)
152
129
  end
153
-
154
- binds_index += binds_contains if binds_contains
155
-
156
- except
157
130
  end
158
-
159
- binds = self.binds.reject.with_index do |_, i|
160
- except_binds[i]
161
- end
162
-
163
- [predicates, binds]
164
131
  end
165
132
 
166
133
  def predicates_with_wrapped_sql_literals
167
134
  non_empty_predicates.map do |node|
168
- if Arel::Nodes::Equality === node
169
- node
170
- else
135
+ case node
136
+ when Arel::Nodes::SqlLiteral, ::String
171
137
  wrap_sql_literal(node)
138
+ else node
172
139
  end
173
140
  end
174
141
  end
@@ -184,6 +151,22 @@ module ActiveRecord
184
151
  end
185
152
  Arel::Nodes::Grouping.new(node)
186
153
  end
154
+
155
+ def extract_node_value(node)
156
+ case node
157
+ when Array
158
+ node.map { |v| extract_node_value(v) }
159
+ when Arel::Nodes::Casted, Arel::Nodes::Quoted
160
+ node.val
161
+ when Arel::Nodes::BindParam
162
+ value = node.value
163
+ if value.respond_to?(:value_before_type_cast)
164
+ value.value_before_type_cast
165
+ else
166
+ value
167
+ end
168
+ end
169
+ end
187
170
  end
188
171
  end
189
172
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  class Relation
3
5
  class WhereClauseFactory # :nodoc:
@@ -15,63 +17,19 @@ module ActiveRecord
15
17
  attributes = klass.send(:expand_hash_conditions_for_aggregates, attributes)
16
18
  attributes.stringify_keys!
17
19
 
18
- if perform_case_sensitive?(options = other.last)
19
- parts, binds = build_for_case_sensitive(attributes, options)
20
- else
21
- attributes, binds = predicate_builder.create_binds(attributes)
22
- parts = predicate_builder.build_from_hash(attributes)
23
- end
20
+ parts = predicate_builder.build_from_hash(attributes)
24
21
  when Arel::Nodes::Node
25
22
  parts = [opts]
26
23
  else
27
24
  raise ArgumentError, "Unsupported argument type: #{opts} (#{opts.class})"
28
25
  end
29
26
 
30
- WhereClause.new(parts, binds || [])
27
+ WhereClause.new(parts)
31
28
  end
32
29
 
33
- # TODO Change this to private once we've dropped Ruby 2.2 support.
34
- # Workaround for Ruby 2.2 "private attribute?" warning.
35
30
  protected
36
31
 
37
32
  attr_reader :klass, :predicate_builder
38
-
39
- private
40
-
41
- def perform_case_sensitive?(options)
42
- options && options.key?(:case_sensitive)
43
- end
44
-
45
- def build_for_case_sensitive(attributes, options)
46
- parts, binds = [], []
47
- table = klass.arel_table
48
-
49
- attributes.each do |attribute, value|
50
- if reflection = klass._reflect_on_association(attribute)
51
- attribute = reflection.foreign_key.to_s
52
- value = value[reflection.klass.primary_key] unless value.nil?
53
- end
54
-
55
- if value.nil?
56
- parts << table[attribute].eq(value)
57
- else
58
- column = klass.column_for_attribute(attribute)
59
-
60
- binds << predicate_builder.send(:build_bind_param, attribute, value)
61
- value = Arel::Nodes::BindParam.new
62
-
63
- predicate = if options[:case_sensitive]
64
- klass.connection.case_sensitive_comparison(table, attribute, column, value)
65
- else
66
- klass.connection.case_insensitive_comparison(table, attribute, column, value)
67
- end
68
-
69
- parts << predicate
70
- end
71
- end
72
-
73
- [parts, binds]
74
- end
75
33
  end
76
34
  end
77
35
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  ###
3
5
  # This class encapsulates a result returned from calling
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/per_thread_registry"
2
4
 
3
5
  module ActiveRecord
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Sanitization
3
5
  extend ActiveSupport::Concern
@@ -28,8 +30,6 @@ module ActiveRecord
28
30
  end
29
31
  end
30
32
  alias :sanitize_sql :sanitize_sql_for_conditions
31
- alias :sanitize_conditions :sanitize_sql
32
- deprecate sanitize_conditions: :sanitize_sql
33
33
 
34
34
  # Accepts an array, hash, or string of SQL conditions and sanitizes
35
35
  # them into a valid SQL fragment for a SET clause.
@@ -63,7 +63,17 @@ module ActiveRecord
63
63
  # # => "id ASC"
64
64
  def sanitize_sql_for_order(condition) # :doc:
65
65
  if condition.is_a?(Array) && condition.first.to_s.include?("?")
66
- sanitize_sql_array(condition)
66
+ enforce_raw_sql_whitelist([condition.first],
67
+ whitelist: AttributeMethods::ClassMethods::COLUMN_NAME_ORDER_WHITELIST
68
+ )
69
+
70
+ # Ensure we aren't dealing with a subclass of String that might
71
+ # override methods we use (eg. Arel::Nodes::SqlLiteral).
72
+ if condition.first.kind_of?(String) && !condition.first.instance_of?(String)
73
+ condition = [String.new(condition.first), *condition[1..-1]]
74
+ end
75
+
76
+ Arel.sql(sanitize_sql_array(condition))
67
77
  else
68
78
  condition
69
79
  end
@@ -110,7 +120,8 @@ module ActiveRecord
110
120
  def sanitize_sql_hash_for_assignment(attrs, table) # :doc:
111
121
  c = connection
112
122
  attrs.map do |attr, value|
113
- value = type_for_attribute(attr.to_s).serialize(value)
123
+ type = type_for_attribute(attr.to_s)
124
+ value = type.serialize(type.cast(value))
114
125
  "#{c.quote_table_name_for_assignment(table, attr)} = #{c.quote(value)}"
115
126
  end.join(", ")
116
127
  end
@@ -205,10 +216,5 @@ module ActiveRecord
205
216
  end
206
217
  end
207
218
  end
208
-
209
- def quoted_id # :nodoc:
210
- self.class.connection.quote(@attributes[self.class.primary_key].value_for_database)
211
- end
212
- deprecate :quoted_id
213
219
  end
214
220
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # = Active Record \Schema
3
5
  #
@@ -37,7 +39,7 @@ module ActiveRecord
37
39
  # The +info+ hash is optional, and if given is used to define metadata
38
40
  # about the current schema (currently, only the schema's version):
39
41
  #
40
- # ActiveRecord::Schema.define(version: 20380119000001) do
42
+ # ActiveRecord::Schema.define(version: 2038_01_19_000001) do
41
43
  # ...
42
44
  # end
43
45
  def self.define(info = {}, &block)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "stringio"
2
4
 
3
5
  module ActiveRecord
@@ -11,14 +13,13 @@ module ActiveRecord
11
13
  ##
12
14
  # :singleton-method:
13
15
  # A list of tables which should not be dumped to the schema.
14
- # Acceptable values are strings as well as regexp.
15
- # This setting is only used if ActiveRecord::Base.schema_format == :ruby
16
- cattr_accessor :ignore_tables
17
- @@ignore_tables = []
16
+ # Acceptable values are strings as well as regexp if ActiveRecord::Base.schema_format == :ruby.
17
+ # Only strings are accepted if ActiveRecord::Base.schema_format == :sql.
18
+ cattr_accessor :ignore_tables, default: []
18
19
 
19
20
  class << self
20
21
  def dump(connection = ActiveRecord::Base.connection, stream = STDOUT, config = ActiveRecord::Base)
21
- new(connection, generate_options(config)).dump(stream)
22
+ connection.create_schema_dumper(generate_options(config)).dump(stream)
22
23
  stream
23
24
  end
24
25
 
@@ -47,9 +48,18 @@ module ActiveRecord
47
48
  @options = options
48
49
  end
49
50
 
50
- def header(stream)
51
- define_params = @version ? "version: #{@version}" : ""
51
+ # turns 20170404131909 into "2017_04_04_131909"
52
+ def formatted_version
53
+ stringified = @version.to_s
54
+ return stringified unless stringified.length == 14
55
+ stringified.insert(4, "_").insert(7, "_").insert(10, "_")
56
+ end
52
57
 
58
+ def define_params
59
+ @version ? "version: #{formatted_version}" : ""
60
+ end
61
+
62
+ def header(stream)
53
63
  stream.puts <<HEADER
54
64
  # This file is auto-generated from the current state of the database. Instead
55
65
  # of editing this file, please use the migrations feature of Active Record to
@@ -72,16 +82,8 @@ HEADER
72
82
  stream.puts "end"
73
83
  end
74
84
 
85
+ # extensions are only supported by PostgreSQL
75
86
  def extensions(stream)
76
- return unless @connection.supports_extensions?
77
- extensions = @connection.extensions
78
- if extensions.any?
79
- stream.puts " # These are extensions that must be enabled in order to support this database"
80
- extensions.each do |extension|
81
- stream.puts " enable_extension #{extension.inspect}"
82
- end
83
- stream.puts
84
- end
85
87
  end
86
88
 
87
89
  def tables(stream)
@@ -113,7 +115,7 @@ HEADER
113
115
  when String
114
116
  tbl.print ", primary_key: #{pk.inspect}" unless pk == "id"
115
117
  pkcol = columns.detect { |c| c.name == pk }
116
- pkcolspec = @connection.column_spec_for_primary_key(pkcol)
118
+ pkcolspec = column_spec_for_primary_key(pkcol)
117
119
  if pkcolspec.present?
118
120
  tbl.print ", #{format_colspec(pkcolspec)}"
119
121
  end
@@ -122,20 +124,19 @@ HEADER
122
124
  else
123
125
  tbl.print ", id: false"
124
126
  end
125
- tbl.print ", force: :cascade"
126
127
 
127
128
  table_options = @connection.table_options(table)
128
129
  if table_options.present?
129
130
  tbl.print ", #{format_options(table_options)}"
130
131
  end
131
132
 
132
- tbl.puts " do |t|"
133
+ tbl.puts ", force: :cascade do |t|"
133
134
 
134
135
  # then dump all non-primary key columns
135
136
  columns.each do |column|
136
137
  raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
137
138
  next if column.name == pk
138
- type, colspec = @connection.column_spec(column)
139
+ type, colspec = column_spec(column)
139
140
  tbl.print " t.#{type} #{column.name.inspect}"
140
141
  tbl.print ", #{format_colspec(colspec)}" if colspec.present?
141
142
  tbl.puts
@@ -153,8 +154,6 @@ HEADER
153
154
  stream.puts "# #{e.message}"
154
155
  stream.puts
155
156
  end
156
-
157
- stream
158
157
  end
159
158
 
160
159
  # Keep it for indexing materialized views
@@ -233,7 +232,9 @@ HEADER
233
232
  end
234
233
 
235
234
  def remove_prefix_and_suffix(table)
236
- table.gsub(/^(#{@options[:table_name_prefix]})(.+)(#{@options[:table_name_suffix]})$/, "\\2")
235
+ prefix = Regexp.escape(@options[:table_name_prefix].to_s)
236
+ suffix = Regexp.escape(@options[:table_name_suffix].to_s)
237
+ table.sub(/\A#{prefix}(.+)#{suffix}\z/, "\\1")
237
238
  end
238
239
 
239
240
  def ignored?(table_name)