activerecord 6.0.1 → 6.1.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (270) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1363 -647
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -4
  5. data/lib/active_record/aggregations.rb +5 -6
  6. data/lib/active_record/association_relation.rb +26 -15
  7. data/lib/active_record/associations/alias_tracker.rb +19 -16
  8. data/lib/active_record/associations/association.rb +55 -37
  9. data/lib/active_record/associations/association_scope.rb +19 -15
  10. data/lib/active_record/associations/belongs_to_association.rb +23 -10
  11. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -3
  12. data/lib/active_record/associations/builder/association.rb +32 -5
  13. data/lib/active_record/associations/builder/belongs_to.rb +10 -7
  14. data/lib/active_record/associations/builder/collection_association.rb +5 -4
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -3
  16. data/lib/active_record/associations/builder/has_many.rb +6 -2
  17. data/lib/active_record/associations/builder/has_one.rb +11 -14
  18. data/lib/active_record/associations/builder/singular_association.rb +1 -1
  19. data/lib/active_record/associations/collection_association.rb +38 -13
  20. data/lib/active_record/associations/collection_proxy.rb +14 -7
  21. data/lib/active_record/associations/foreign_association.rb +13 -0
  22. data/lib/active_record/associations/has_many_association.rb +24 -3
  23. data/lib/active_record/associations/has_many_through_association.rb +10 -4
  24. data/lib/active_record/associations/has_one_association.rb +15 -1
  25. data/lib/active_record/associations/join_dependency/join_association.rb +39 -16
  26. data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
  27. data/lib/active_record/associations/join_dependency.rb +73 -42
  28. data/lib/active_record/associations/preloader/association.rb +49 -25
  29. data/lib/active_record/associations/preloader/through_association.rb +2 -2
  30. data/lib/active_record/associations/preloader.rb +12 -7
  31. data/lib/active_record/associations/singular_association.rb +1 -1
  32. data/lib/active_record/associations/through_association.rb +1 -1
  33. data/lib/active_record/associations.rb +119 -12
  34. data/lib/active_record/attribute_assignment.rb +10 -9
  35. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -10
  36. data/lib/active_record/attribute_methods/dirty.rb +3 -13
  37. data/lib/active_record/attribute_methods/primary_key.rb +6 -4
  38. data/lib/active_record/attribute_methods/query.rb +3 -6
  39. data/lib/active_record/attribute_methods/read.rb +8 -12
  40. data/lib/active_record/attribute_methods/serialization.rb +11 -6
  41. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
  42. data/lib/active_record/attribute_methods/write.rb +12 -21
  43. data/lib/active_record/attribute_methods.rb +64 -54
  44. data/lib/active_record/attributes.rb +33 -9
  45. data/lib/active_record/autosave_association.rb +56 -41
  46. data/lib/active_record/base.rb +2 -14
  47. data/lib/active_record/callbacks.rb +153 -24
  48. data/lib/active_record/coders/yaml_column.rb +24 -3
  49. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +190 -136
  50. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
  51. data/lib/active_record/connection_adapters/abstract/database_statements.rb +83 -38
  52. data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -9
  53. data/lib/active_record/connection_adapters/abstract/quoting.rb +44 -35
  54. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  55. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +152 -116
  56. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +145 -52
  57. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
  58. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +267 -105
  59. data/lib/active_record/connection_adapters/abstract/transaction.rb +94 -36
  60. data/lib/active_record/connection_adapters/abstract_adapter.rb +63 -77
  61. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +136 -111
  62. data/lib/active_record/connection_adapters/column.rb +15 -1
  63. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  64. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  65. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  66. data/lib/active_record/connection_adapters/mysql/database_statements.rb +30 -36
  67. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  68. data/lib/active_record/connection_adapters/mysql/quoting.rb +18 -3
  69. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -7
  70. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
  71. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +5 -2
  72. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +20 -13
  73. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  74. data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -13
  75. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  76. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  77. data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
  78. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +21 -56
  79. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
  80. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  81. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  82. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
  83. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  84. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
  85. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
  87. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
  91. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -6
  92. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -2
  94. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/quoting.rb +30 -4
  96. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
  97. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +7 -3
  98. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
  99. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  100. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +72 -54
  101. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  102. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  103. data/lib/active_record/connection_adapters/postgresql_adapter.rb +80 -66
  104. data/lib/active_record/connection_adapters/schema_cache.rb +130 -15
  105. data/lib/active_record/connection_adapters/sql_type_metadata.rb +8 -0
  106. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +38 -12
  107. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -2
  108. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  109. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +38 -5
  110. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +57 -57
  111. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  112. data/lib/active_record/connection_adapters.rb +52 -0
  113. data/lib/active_record/connection_handling.rb +218 -87
  114. data/lib/active_record/core.rb +276 -68
  115. data/lib/active_record/counter_cache.rb +4 -1
  116. data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
  117. data/lib/active_record/database_configurations/database_config.rb +52 -9
  118. data/lib/active_record/database_configurations/hash_config.rb +54 -8
  119. data/lib/active_record/database_configurations/url_config.rb +15 -41
  120. data/lib/active_record/database_configurations.rb +125 -85
  121. data/lib/active_record/delegated_type.rb +209 -0
  122. data/lib/active_record/destroy_association_async_job.rb +36 -0
  123. data/lib/active_record/dynamic_matchers.rb +2 -3
  124. data/lib/active_record/enum.rb +80 -38
  125. data/lib/active_record/errors.rb +47 -12
  126. data/lib/active_record/explain.rb +9 -5
  127. data/lib/active_record/explain_subscriber.rb +1 -1
  128. data/lib/active_record/fixture_set/file.rb +10 -17
  129. data/lib/active_record/fixture_set/model_metadata.rb +1 -2
  130. data/lib/active_record/fixture_set/render_context.rb +1 -1
  131. data/lib/active_record/fixture_set/table_row.rb +2 -3
  132. data/lib/active_record/fixture_set/table_rows.rb +0 -1
  133. data/lib/active_record/fixtures.rb +58 -12
  134. data/lib/active_record/gem_version.rb +3 -3
  135. data/lib/active_record/inheritance.rb +40 -21
  136. data/lib/active_record/insert_all.rb +42 -9
  137. data/lib/active_record/integration.rb +3 -5
  138. data/lib/active_record/internal_metadata.rb +18 -7
  139. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  140. data/lib/active_record/locking/optimistic.rb +33 -18
  141. data/lib/active_record/locking/pessimistic.rb +6 -2
  142. data/lib/active_record/log_subscriber.rb +28 -9
  143. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  144. data/lib/active_record/middleware/database_selector/resolver.rb +6 -2
  145. data/lib/active_record/middleware/database_selector.rb +4 -2
  146. data/lib/active_record/migration/command_recorder.rb +53 -45
  147. data/lib/active_record/migration/compatibility.rb +75 -21
  148. data/lib/active_record/migration/join_table.rb +0 -1
  149. data/lib/active_record/migration.rb +115 -85
  150. data/lib/active_record/model_schema.rb +117 -15
  151. data/lib/active_record/nested_attributes.rb +2 -5
  152. data/lib/active_record/no_touching.rb +1 -1
  153. data/lib/active_record/null_relation.rb +0 -1
  154. data/lib/active_record/persistence.rb +50 -46
  155. data/lib/active_record/query_cache.rb +15 -5
  156. data/lib/active_record/querying.rb +12 -7
  157. data/lib/active_record/railtie.rb +65 -45
  158. data/lib/active_record/railties/console_sandbox.rb +2 -4
  159. data/lib/active_record/railties/databases.rake +280 -99
  160. data/lib/active_record/readonly_attributes.rb +4 -0
  161. data/lib/active_record/reflection.rb +77 -63
  162. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  163. data/lib/active_record/relation/batches.rb +38 -32
  164. data/lib/active_record/relation/calculations.rb +106 -45
  165. data/lib/active_record/relation/delegation.rb +9 -7
  166. data/lib/active_record/relation/finder_methods.rb +45 -16
  167. data/lib/active_record/relation/from_clause.rb +5 -1
  168. data/lib/active_record/relation/merger.rb +27 -26
  169. data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
  170. data/lib/active_record/relation/predicate_builder/association_query_value.rb +4 -5
  171. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -6
  172. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  173. data/lib/active_record/relation/predicate_builder.rb +59 -40
  174. data/lib/active_record/relation/query_methods.rb +341 -188
  175. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  176. data/lib/active_record/relation/spawn_methods.rb +8 -8
  177. data/lib/active_record/relation/where_clause.rb +111 -62
  178. data/lib/active_record/relation.rb +116 -83
  179. data/lib/active_record/result.rb +41 -34
  180. data/lib/active_record/runtime_registry.rb +2 -2
  181. data/lib/active_record/sanitization.rb +6 -17
  182. data/lib/active_record/schema_dumper.rb +34 -4
  183. data/lib/active_record/schema_migration.rb +2 -8
  184. data/lib/active_record/scoping/default.rb +1 -4
  185. data/lib/active_record/scoping/named.rb +7 -18
  186. data/lib/active_record/scoping.rb +0 -1
  187. data/lib/active_record/secure_token.rb +16 -8
  188. data/lib/active_record/serialization.rb +5 -3
  189. data/lib/active_record/signed_id.rb +116 -0
  190. data/lib/active_record/statement_cache.rb +20 -4
  191. data/lib/active_record/store.rb +9 -4
  192. data/lib/active_record/suppressor.rb +2 -2
  193. data/lib/active_record/table_metadata.rb +42 -36
  194. data/lib/active_record/tasks/database_tasks.rb +140 -113
  195. data/lib/active_record/tasks/mysql_database_tasks.rb +34 -36
  196. data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -27
  197. data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -10
  198. data/lib/active_record/test_databases.rb +5 -4
  199. data/lib/active_record/test_fixtures.rb +87 -20
  200. data/lib/active_record/timestamp.rb +4 -7
  201. data/lib/active_record/touch_later.rb +20 -21
  202. data/lib/active_record/transactions.rb +25 -72
  203. data/lib/active_record/type/adapter_specific_registry.rb +2 -5
  204. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  205. data/lib/active_record/type/serialized.rb +6 -3
  206. data/lib/active_record/type/time.rb +10 -0
  207. data/lib/active_record/type/type_map.rb +0 -1
  208. data/lib/active_record/type/unsigned_integer.rb +0 -1
  209. data/lib/active_record/type.rb +8 -2
  210. data/lib/active_record/type_caster/connection.rb +0 -1
  211. data/lib/active_record/type_caster/map.rb +8 -5
  212. data/lib/active_record/validations/associated.rb +1 -2
  213. data/lib/active_record/validations/numericality.rb +35 -0
  214. data/lib/active_record/validations/uniqueness.rb +24 -4
  215. data/lib/active_record/validations.rb +3 -3
  216. data/lib/active_record.rb +7 -13
  217. data/lib/arel/attributes/attribute.rb +4 -0
  218. data/lib/arel/collectors/bind.rb +5 -0
  219. data/lib/arel/collectors/composite.rb +8 -0
  220. data/lib/arel/collectors/sql_string.rb +7 -0
  221. data/lib/arel/collectors/substitute_binds.rb +7 -0
  222. data/lib/arel/nodes/binary.rb +82 -8
  223. data/lib/arel/nodes/bind_param.rb +8 -0
  224. data/lib/arel/nodes/casted.rb +21 -9
  225. data/lib/arel/nodes/equality.rb +6 -9
  226. data/lib/arel/nodes/grouping.rb +3 -0
  227. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  228. data/lib/arel/nodes/in.rb +8 -1
  229. data/lib/arel/nodes/infix_operation.rb +13 -1
  230. data/lib/arel/nodes/join_source.rb +1 -1
  231. data/lib/arel/nodes/node.rb +7 -6
  232. data/lib/arel/nodes/ordering.rb +27 -0
  233. data/lib/arel/nodes/sql_literal.rb +3 -0
  234. data/lib/arel/nodes/table_alias.rb +7 -3
  235. data/lib/arel/nodes/unary.rb +0 -1
  236. data/lib/arel/nodes.rb +3 -1
  237. data/lib/arel/predications.rb +17 -24
  238. data/lib/arel/select_manager.rb +1 -2
  239. data/lib/arel/table.rb +13 -5
  240. data/lib/arel/visitors/dot.rb +14 -3
  241. data/lib/arel/visitors/mysql.rb +11 -1
  242. data/lib/arel/visitors/postgresql.rb +15 -5
  243. data/lib/arel/visitors/sqlite.rb +0 -1
  244. data/lib/arel/visitors/to_sql.rb +89 -79
  245. data/lib/arel/visitors/visitor.rb +0 -1
  246. data/lib/arel/visitors.rb +0 -7
  247. data/lib/arel.rb +5 -9
  248. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  249. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  250. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
  251. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
  252. data/lib/rails/generators/active_record/migration.rb +6 -2
  253. data/lib/rails/generators/active_record/model/model_generator.rb +38 -2
  254. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  255. metadata +30 -29
  256. data/lib/active_record/attribute_decorators.rb +0 -90
  257. data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
  258. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  259. data/lib/active_record/define_callbacks.rb +0 -22
  260. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  261. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  262. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  263. data/lib/arel/attributes.rb +0 -22
  264. data/lib/arel/visitors/depth_first.rb +0 -204
  265. data/lib/arel/visitors/ibm_db.rb +0 -34
  266. data/lib/arel/visitors/informix.rb +0 -62
  267. data/lib/arel/visitors/mssql.rb +0 -157
  268. data/lib/arel/visitors/oracle.rb +0 -159
  269. data/lib/arel/visitors/oracle12.rb +0 -66
  270. data/lib/arel/visitors/where_sql.rb +0 -23
@@ -3,6 +3,8 @@
3
3
  module Arel # :nodoc: all
4
4
  module Collectors
5
5
  class SubstituteBinds
6
+ attr_accessor :preparable
7
+
6
8
  def initialize(quoter, delegate_collector)
7
9
  @quoter = quoter
8
10
  @delegate = delegate_collector
@@ -14,9 +16,14 @@ module Arel # :nodoc: all
14
16
  end
15
17
 
16
18
  def add_bind(bind)
19
+ bind = bind.value_for_database if bind.respond_to?(:value_for_database)
17
20
  self << quoter.quote(bind)
18
21
  end
19
22
 
23
+ def add_binds(binds, proc_for_binds = nil)
24
+ self << binds.map { |bind| quoter.quote(bind) }.join(", ")
25
+ end
26
+
20
27
  def value
21
28
  delegate.value
22
29
  end
@@ -29,18 +29,92 @@ module Arel # :nodoc: all
29
29
  alias :== :eql?
30
30
  end
31
31
 
32
+ module FetchAttribute
33
+ def fetch_attribute
34
+ if left.is_a?(Arel::Attributes::Attribute)
35
+ yield left
36
+ elsif right.is_a?(Arel::Attributes::Attribute)
37
+ yield right
38
+ end
39
+ end
40
+ end
41
+
42
+ class Between < Binary; include FetchAttribute; end
43
+
44
+ class GreaterThan < Binary
45
+ include FetchAttribute
46
+
47
+ def invert
48
+ Arel::Nodes::LessThanOrEqual.new(left, right)
49
+ end
50
+ end
51
+
52
+ class GreaterThanOrEqual < Binary
53
+ include FetchAttribute
54
+
55
+ def invert
56
+ Arel::Nodes::LessThan.new(left, right)
57
+ end
58
+ end
59
+
60
+ class LessThan < Binary
61
+ include FetchAttribute
62
+
63
+ def invert
64
+ Arel::Nodes::GreaterThanOrEqual.new(left, right)
65
+ end
66
+ end
67
+
68
+ class LessThanOrEqual < Binary
69
+ include FetchAttribute
70
+
71
+ def invert
72
+ Arel::Nodes::GreaterThan.new(left, right)
73
+ end
74
+ end
75
+
76
+ class IsDistinctFrom < Binary
77
+ include FetchAttribute
78
+
79
+ def invert
80
+ Arel::Nodes::IsNotDistinctFrom.new(left, right)
81
+ end
82
+ end
83
+
84
+ class IsNotDistinctFrom < Binary
85
+ include FetchAttribute
86
+
87
+ def invert
88
+ Arel::Nodes::IsDistinctFrom.new(left, right)
89
+ end
90
+ end
91
+
92
+ class NotEqual < Binary
93
+ include FetchAttribute
94
+
95
+ def invert
96
+ Arel::Nodes::Equality.new(left, right)
97
+ end
98
+ end
99
+
100
+ class NotIn < Binary
101
+ include FetchAttribute
102
+
103
+ def invert
104
+ Arel::Nodes::In.new(left, right)
105
+ end
106
+ end
107
+
108
+ class Or < Binary
109
+ def fetch_attribute(&block)
110
+ left.fetch_attribute(&block) && right.fetch_attribute(&block)
111
+ end
112
+ end
113
+
32
114
  %w{
33
115
  As
34
116
  Assignment
35
- Between
36
- GreaterThan
37
- GreaterThanOrEqual
38
117
  Join
39
- LessThan
40
- LessThanOrEqual
41
- NotEqual
42
- NotIn
43
- Or
44
118
  Union
45
119
  UnionAll
46
120
  Intersect
@@ -24,6 +24,14 @@ module Arel # :nodoc: all
24
24
  value.nil?
25
25
  end
26
26
 
27
+ def value_before_type_cast
28
+ if value.respond_to?(:value_before_type_cast)
29
+ value.value_before_type_cast
30
+ else
31
+ value
32
+ end
33
+ end
34
+
27
35
  def infinite?
28
36
  value.respond_to?(:infinite?) && value.infinite?
29
37
  end
@@ -3,30 +3,42 @@
3
3
  module Arel # :nodoc: all
4
4
  module Nodes
5
5
  class Casted < Arel::Nodes::NodeExpression # :nodoc:
6
- attr_reader :val, :attribute
7
- def initialize(val, attribute)
8
- @val = val
6
+ attr_reader :value, :attribute
7
+ alias :value_before_type_cast :value
8
+
9
+ def initialize(value, attribute)
10
+ @value = value
9
11
  @attribute = attribute
10
12
  super()
11
13
  end
12
14
 
13
- def nil?; @val.nil?; end
15
+ def nil?; value.nil?; end
16
+
17
+ def value_for_database
18
+ if attribute.able_to_type_cast?
19
+ attribute.type_cast_for_database(value)
20
+ else
21
+ value
22
+ end
23
+ end
14
24
 
15
25
  def hash
16
- [self.class, val, attribute].hash
26
+ [self.class, value, attribute].hash
17
27
  end
18
28
 
19
29
  def eql?(other)
20
30
  self.class == other.class &&
21
- self.val == other.val &&
22
- self.attribute == other.attribute
31
+ self.value == other.value &&
32
+ self.attribute == other.attribute
23
33
  end
24
34
  alias :== :eql?
25
35
  end
26
36
 
27
37
  class Quoted < Arel::Nodes::Unary # :nodoc:
28
- alias :val :value
29
- def nil?; val.nil?; end
38
+ alias :value_for_database :value
39
+ alias :value_before_type_cast :value
40
+
41
+ def nil?; value.nil?; end
30
42
 
31
43
  def infinite?
32
44
  value.respond_to?(:infinite?) && value.infinite?
@@ -3,16 +3,13 @@
3
3
  module Arel # :nodoc: all
4
4
  module Nodes
5
5
  class Equality < Arel::Nodes::Binary
6
- def operator; :== end
7
- alias :operand1 :left
8
- alias :operand2 :right
9
- end
6
+ include FetchAttribute
7
+
8
+ def equality?; true; end
10
9
 
11
- %w{
12
- IsDistinctFrom
13
- IsNotDistinctFrom
14
- }.each do |name|
15
- const_set name, Class.new(Equality)
10
+ def invert
11
+ Arel::Nodes::NotEqual.new(left, right)
12
+ end
16
13
  end
17
14
  end
18
15
  end
@@ -3,6 +3,9 @@
3
3
  module Arel # :nodoc: all
4
4
  module Nodes
5
5
  class Grouping < Unary
6
+ def fetch_attribute(&block)
7
+ expr.fetch_attribute(&block)
8
+ end
6
9
  end
7
10
  end
8
11
  end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arel # :nodoc: all
4
+ module Nodes
5
+ class HomogeneousIn < Node
6
+ attr_reader :attribute, :values, :type
7
+
8
+ def initialize(values, attribute, type)
9
+ @values = values
10
+ @attribute = attribute
11
+ @type = type
12
+ end
13
+
14
+ def hash
15
+ ivars.hash
16
+ end
17
+
18
+ def eql?(other)
19
+ super || (self.class == other.class && self.ivars == other.ivars)
20
+ end
21
+ alias :== :eql?
22
+
23
+ def equality?
24
+ type == :in
25
+ end
26
+
27
+ def invert
28
+ Arel::Nodes::HomogeneousIn.new(values, attribute, type == :in ? :notin : :in)
29
+ end
30
+
31
+ def left
32
+ attribute
33
+ end
34
+
35
+ def right
36
+ attribute.quoted_array(values)
37
+ end
38
+
39
+ def table_name
40
+ attribute.relation.table_alias || attribute.relation.name
41
+ end
42
+
43
+ def column_name
44
+ attribute.name
45
+ end
46
+
47
+ def casted_values
48
+ type = attribute.type_caster
49
+
50
+ casted_values = values.map do |raw_value|
51
+ type.serialize(raw_value) if type.serializable?(raw_value)
52
+ end
53
+
54
+ casted_values.compact!
55
+ casted_values
56
+ end
57
+
58
+ def proc_for_binds
59
+ -> value { ActiveModel::Attribute.with_cast_value(attribute.name, value, attribute.type_caster) }
60
+ end
61
+
62
+ def fetch_attribute(&block)
63
+ if attribute
64
+ yield attribute
65
+ else
66
+ expr.fetch_attribute(&block)
67
+ end
68
+ end
69
+
70
+ protected
71
+ def ivars
72
+ [@attribute, @values, @type]
73
+ end
74
+ end
75
+ end
76
+ end
data/lib/arel/nodes/in.rb CHANGED
@@ -2,7 +2,14 @@
2
2
 
3
3
  module Arel # :nodoc: all
4
4
  module Nodes
5
- class In < Equality
5
+ class In < Arel::Nodes::Binary
6
+ include FetchAttribute
7
+
8
+ def equality?; true; end
9
+
10
+ def invert
11
+ Arel::Nodes::NotIn.new(left, right)
12
+ end
6
13
  end
7
14
  end
8
15
  end
@@ -43,7 +43,19 @@ module Arel # :nodoc: all
43
43
 
44
44
  class Concat < InfixOperation
45
45
  def initialize(left, right)
46
- super("||", left, right)
46
+ super(:"||", left, right)
47
+ end
48
+ end
49
+
50
+ class Contains < InfixOperation
51
+ def initialize(left, right)
52
+ super(:"@>", left, right)
53
+ end
54
+ end
55
+
56
+ class Overlaps < InfixOperation
57
+ def initialize(left, right)
58
+ super(:"&&", left, right)
47
59
  end
48
60
  end
49
61
 
@@ -5,7 +5,7 @@ module Arel # :nodoc: all
5
5
  ###
6
6
  # Class that represents a join source
7
7
  #
8
- # http://www.sqlite.org/syntaxdiagrams.html#join-source
8
+ # https://www.sqlite.org/syntaxdiagrams.html#join-source
9
9
 
10
10
  class JoinSource < Arel::Nodes::Binary
11
11
  def initialize(single_source, joinop = [])
@@ -6,7 +6,6 @@ module Arel # :nodoc: all
6
6
  # Abstract base class for all AST nodes
7
7
  class Node
8
8
  include Arel::FactoryMethods
9
- include Enumerable
10
9
 
11
10
  ###
12
11
  # Factory method to create a Nodes::Not node that has the recipient of
@@ -28,6 +27,10 @@ module Arel # :nodoc: all
28
27
  Nodes::And.new [self, right]
29
28
  end
30
29
 
30
+ def invert
31
+ Arel::Nodes::Not.new(self)
32
+ end
33
+
31
34
  # FIXME: this method should go away. I don't like people calling
32
35
  # to_sql on non-head nodes. This forces us to walk the AST until we
33
36
  # can find a node that has a "relation" member.
@@ -39,12 +42,10 @@ module Arel # :nodoc: all
39
42
  collector.value
40
43
  end
41
44
 
42
- # Iterate through AST, nodes will be yielded depth-first
43
- def each(&block)
44
- return enum_for(:each) unless block_given?
45
-
46
- ::Arel::Visitors::DepthFirst.new(block).accept self
45
+ def fetch_attribute
47
46
  end
47
+
48
+ def equality?; false; end
48
49
  end
49
50
  end
50
51
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arel # :nodoc: all
4
+ module Nodes
5
+ class Ordering < Unary
6
+ def nulls_first
7
+ NullsFirst.new(self)
8
+ end
9
+
10
+ def nulls_last
11
+ NullsLast.new(self)
12
+ end
13
+ end
14
+
15
+ class NullsFirst < Ordering
16
+ def reverse
17
+ NullsLast.new(expr.reverse)
18
+ end
19
+ end
20
+
21
+ class NullsLast < Ordering
22
+ def reverse
23
+ NullsFirst.new(expr.reverse)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -11,6 +11,9 @@ module Arel # :nodoc: all
11
11
  def encode_with(coder)
12
12
  coder.scalar = self.to_s
13
13
  end
14
+
15
+ def fetch_attribute
16
+ end
14
17
  end
15
18
  end
16
19
  end
@@ -8,15 +8,19 @@ module Arel # :nodoc: all
8
8
  alias :table_alias :name
9
9
 
10
10
  def [](name)
11
- Attribute.new(self, name)
11
+ relation.is_a?(Table) ? relation[name, self] : Attribute.new(self, name)
12
12
  end
13
13
 
14
14
  def table_name
15
15
  relation.respond_to?(:name) ? relation.name : name
16
16
  end
17
17
 
18
- def type_cast_for_database(*args)
19
- relation.type_cast_for_database(*args)
18
+ def type_cast_for_database(attr_name, value)
19
+ relation.type_cast_for_database(attr_name, value)
20
+ end
21
+
22
+ def type_for_attribute(name)
23
+ relation.type_for_attribute(name)
20
24
  end
21
25
 
22
26
  def able_to_type_cast?
@@ -36,7 +36,6 @@ module Arel # :nodoc: all
36
36
  Offset
37
37
  On
38
38
  OptimizerHints
39
- Ordering
40
39
  RollUp
41
40
  }.each do |name|
42
41
  const_set(name, Class.new(Unary))
data/lib/arel/nodes.rb CHANGED
@@ -18,6 +18,8 @@ require "arel/nodes/false"
18
18
  # unary
19
19
  require "arel/nodes/unary"
20
20
  require "arel/nodes/grouping"
21
+ require "arel/nodes/homogeneous_in"
22
+ require "arel/nodes/ordering"
21
23
  require "arel/nodes/ascending"
22
24
  require "arel/nodes/descending"
23
25
  require "arel/nodes/unqualified_column"
@@ -26,7 +28,7 @@ require "arel/nodes/with"
26
28
  # binary
27
29
  require "arel/nodes/binary"
28
30
  require "arel/nodes/equality"
29
- require "arel/nodes/in" # Why is this subclassed from equality?
31
+ require "arel/nodes/in"
30
32
  require "arel/nodes/join_source"
31
33
  require "arel/nodes/delete_statement"
32
34
  require "arel/nodes/table_alias"
@@ -38,14 +38,14 @@ module Arel # :nodoc: all
38
38
  if unboundable?(other.begin) == 1 || unboundable?(other.end) == -1
39
39
  self.in([])
40
40
  elsif open_ended?(other.begin)
41
- if other.end.nil? || open_ended?(other.end)
41
+ if open_ended?(other.end)
42
42
  not_in([])
43
43
  elsif other.exclude_end?
44
44
  lt(other.end)
45
45
  else
46
46
  lteq(other.end)
47
47
  end
48
- elsif other.end.nil? || open_ended?(other.end)
48
+ elsif open_ended?(other.end)
49
49
  gteq(other.begin)
50
50
  elsif other.exclude_end?
51
51
  gteq(other.begin).and(lt(other.end))
@@ -60,13 +60,6 @@ module Arel # :nodoc: all
60
60
  case other
61
61
  when Arel::SelectManager
62
62
  Arel::Nodes::In.new(self, other.ast)
63
- when Range
64
- if $VERBOSE
65
- warn <<-eowarn
66
- Passing a range to `#in` is deprecated. Call `#between`, instead.
67
- eowarn
68
- end
69
- between(other)
70
63
  when Enumerable
71
64
  Nodes::In.new self, quoted_array(other)
72
65
  else
@@ -86,14 +79,14 @@ Passing a range to `#in` is deprecated. Call `#between`, instead.
86
79
  if unboundable?(other.begin) == 1 || unboundable?(other.end) == -1
87
80
  not_in([])
88
81
  elsif open_ended?(other.begin)
89
- if other.end.nil? || open_ended?(other.end)
82
+ if open_ended?(other.end)
90
83
  self.in([])
91
84
  elsif other.exclude_end?
92
85
  gteq(other.end)
93
86
  else
94
87
  gt(other.end)
95
88
  end
96
- elsif other.end.nil? || open_ended?(other.end)
89
+ elsif open_ended?(other.end)
97
90
  lt(other.begin)
98
91
  else
99
92
  left = lt(other.begin)
@@ -110,13 +103,6 @@ Passing a range to `#in` is deprecated. Call `#between`, instead.
110
103
  case other
111
104
  when Arel::SelectManager
112
105
  Arel::Nodes::NotIn.new(self, other.ast)
113
- when Range
114
- if $VERBOSE
115
- warn <<-eowarn
116
- Passing a range to `#not_in` is deprecated. Call `#not_between`, instead.
117
- eowarn
118
- end
119
- not_between(other)
120
106
  when Enumerable
121
107
  Nodes::NotIn.new self, quoted_array(other)
122
108
  else
@@ -220,8 +206,19 @@ Passing a range to `#not_in` is deprecated. Call `#not_between`, instead.
220
206
  Nodes::Concat.new self, other
221
207
  end
222
208
 
223
- private
209
+ def contains(other)
210
+ Arel::Nodes::Contains.new self, quoted_node(other)
211
+ end
212
+
213
+ def overlaps(other)
214
+ Arel::Nodes::Overlaps.new self, quoted_node(other)
215
+ end
224
216
 
217
+ def quoted_array(others)
218
+ others.map { |v| quoted_node(v) }
219
+ end
220
+
221
+ private
225
222
  def grouping_any(method_id, others, *extras)
226
223
  nodes = others.map { |expr| send(method_id, expr, *extras) }
227
224
  Nodes::Grouping.new nodes.inject { |memo, node|
@@ -238,10 +235,6 @@ Passing a range to `#not_in` is deprecated. Call `#not_between`, instead.
238
235
  Nodes.build_quoted(other, self)
239
236
  end
240
237
 
241
- def quoted_array(others)
242
- others.map { |v| quoted_node(v) }
243
- end
244
-
245
238
  def infinity?(value)
246
239
  value.respond_to?(:infinite?) && value.infinite?
247
240
  end
@@ -251,7 +244,7 @@ Passing a range to `#not_in` is deprecated. Call `#not_between`, instead.
251
244
  end
252
245
 
253
246
  def open_ended?(value)
254
- infinity?(value) || unboundable?(value)
247
+ value.nil? || infinity?(value) || unboundable?(value)
255
248
  end
256
249
  end
257
250
  end
@@ -186,8 +186,7 @@ module Arel # :nodoc: all
186
186
  def where_sql(engine = Table.engine)
187
187
  return if @ctx.wheres.empty?
188
188
 
189
- viz = Visitors::WhereSql.new(engine.connection.visitor, engine.connection)
190
- Nodes::SqlLiteral.new viz.accept(@ctx, Collectors::SQLString.new).value
189
+ Nodes::SqlLiteral.new("WHERE #{Nodes::And.new(@ctx.wheres).to_sql(engine)}")
191
190
  end
192
191
 
193
192
  def union(operation, other = nil)
data/lib/arel/table.rb CHANGED
@@ -4,6 +4,7 @@ module Arel # :nodoc: all
4
4
  class Table
5
5
  include Arel::Crud
6
6
  include Arel::FactoryMethods
7
+ include Arel::AliasPredication
7
8
 
8
9
  @engine = nil
9
10
  class << self; attr_accessor :engine; end
@@ -13,8 +14,9 @@ module Arel # :nodoc: all
13
14
  # TableAlias and Table both have a #table_name which is the name of the underlying table
14
15
  alias :table_name :name
15
16
 
16
- def initialize(name, as: nil, type_caster: nil)
17
+ def initialize(name, as: nil, klass: nil, type_caster: klass&.type_caster)
17
18
  @name = name.to_s
19
+ @klass = klass
18
20
  @type_caster = type_caster
19
21
 
20
22
  # Sometime AR sends an :as parameter to table, to let the table know
@@ -78,8 +80,10 @@ module Arel # :nodoc: all
78
80
  from.having expr
79
81
  end
80
82
 
81
- def [](name)
82
- ::Arel::Attribute.new self, name
83
+ def [](name, table = self)
84
+ name = name.to_s if name.is_a?(Symbol)
85
+ name = @klass.attribute_aliases[name] || name if @klass
86
+ Attribute.new(table, name)
83
87
  end
84
88
 
85
89
  def hash
@@ -96,8 +100,12 @@ module Arel # :nodoc: all
96
100
  end
97
101
  alias :== :eql?
98
102
 
99
- def type_cast_for_database(attribute_name, value)
100
- type_caster.type_cast_for_database(attribute_name, value)
103
+ def type_cast_for_database(attr_name, value)
104
+ type_caster.type_cast_for_database(attr_name, value)
105
+ end
106
+
107
+ def type_for_attribute(name)
108
+ type_caster.type_for_attribute(name)
101
109
  end
102
110
 
103
111
  def able_to_type_cast?
@@ -31,7 +31,6 @@ module Arel # :nodoc: all
31
31
  end
32
32
 
33
33
  private
34
-
35
34
  def visit_Arel_Nodes_Ordering(o)
36
35
  visit_edge o, "expr"
37
36
  end
@@ -158,7 +157,13 @@ module Arel # :nodoc: all
158
157
  end
159
158
 
160
159
  def visit_Arel_Nodes_Casted(o)
161
- visit_edge o, "val"
160
+ visit_edge o, "value"
161
+ visit_edge o, "attribute"
162
+ end
163
+
164
+ def visit_Arel_Nodes_HomogeneousIn(o)
165
+ visit_edge o, "values"
166
+ visit_edge o, "type"
162
167
  visit_edge o, "attribute"
163
168
  end
164
169
 
@@ -219,7 +224,13 @@ module Arel # :nodoc: all
219
224
  alias :visit_Symbol :visit_String
220
225
  alias :visit_Arel_Nodes_SqlLiteral :visit_String
221
226
 
222
- def visit_Arel_Nodes_BindParam(o); end
227
+ def visit_Arel_Nodes_BindParam(o)
228
+ edge("value") { visit o.value }
229
+ end
230
+
231
+ def visit_ActiveModel_Attribute(o)
232
+ edge("value_before_type_cast") { visit o.value_before_type_cast }
233
+ end
223
234
 
224
235
  def visit_Hash(o)
225
236
  o.each_with_index do |pair, i|