activerecord 6.0.3.4 → 6.1.2

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 (245) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +891 -695
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +3 -3
  5. data/lib/active_record.rb +7 -14
  6. data/lib/active_record/aggregations.rb +5 -5
  7. data/lib/active_record/association_relation.rb +30 -12
  8. data/lib/active_record/associations.rb +118 -11
  9. data/lib/active_record/associations/alias_tracker.rb +19 -15
  10. data/lib/active_record/associations/association.rb +44 -28
  11. data/lib/active_record/associations/association_scope.rb +19 -15
  12. data/lib/active_record/associations/belongs_to_association.rb +22 -8
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -3
  14. data/lib/active_record/associations/builder/association.rb +32 -5
  15. data/lib/active_record/associations/builder/belongs_to.rb +10 -7
  16. data/lib/active_record/associations/builder/collection_association.rb +5 -4
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -1
  18. data/lib/active_record/associations/builder/has_many.rb +6 -2
  19. data/lib/active_record/associations/builder/has_one.rb +11 -14
  20. data/lib/active_record/associations/builder/singular_association.rb +1 -1
  21. data/lib/active_record/associations/collection_association.rb +19 -6
  22. data/lib/active_record/associations/collection_proxy.rb +13 -5
  23. data/lib/active_record/associations/foreign_association.rb +13 -0
  24. data/lib/active_record/associations/has_many_association.rb +24 -2
  25. data/lib/active_record/associations/has_many_through_association.rb +10 -4
  26. data/lib/active_record/associations/has_one_association.rb +15 -1
  27. data/lib/active_record/associations/join_dependency.rb +72 -50
  28. data/lib/active_record/associations/join_dependency/join_association.rb +39 -16
  29. data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
  30. data/lib/active_record/associations/preloader.rb +11 -5
  31. data/lib/active_record/associations/preloader/association.rb +51 -25
  32. data/lib/active_record/associations/preloader/through_association.rb +2 -2
  33. data/lib/active_record/associations/singular_association.rb +1 -1
  34. data/lib/active_record/associations/through_association.rb +1 -1
  35. data/lib/active_record/attribute_assignment.rb +10 -8
  36. data/lib/active_record/attribute_methods.rb +64 -54
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -9
  38. data/lib/active_record/attribute_methods/dirty.rb +1 -11
  39. data/lib/active_record/attribute_methods/primary_key.rb +6 -2
  40. data/lib/active_record/attribute_methods/query.rb +3 -6
  41. data/lib/active_record/attribute_methods/read.rb +8 -11
  42. data/lib/active_record/attribute_methods/serialization.rb +11 -5
  43. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -13
  44. data/lib/active_record/attribute_methods/write.rb +12 -20
  45. data/lib/active_record/attributes.rb +33 -8
  46. data/lib/active_record/autosave_association.rb +57 -40
  47. data/lib/active_record/base.rb +2 -14
  48. data/lib/active_record/callbacks.rb +152 -22
  49. data/lib/active_record/coders/yaml_column.rb +1 -1
  50. data/lib/active_record/connection_adapters.rb +50 -0
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +191 -134
  52. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
  53. data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -22
  54. data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -8
  55. data/lib/active_record/connection_adapters/abstract/quoting.rb +34 -34
  56. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  57. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
  58. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +116 -27
  59. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
  60. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +228 -83
  61. data/lib/active_record/connection_adapters/abstract/transaction.rb +80 -32
  62. data/lib/active_record/connection_adapters/abstract_adapter.rb +54 -72
  63. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +133 -96
  64. data/lib/active_record/connection_adapters/column.rb +15 -1
  65. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  66. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
  67. data/lib/active_record/connection_adapters/mysql/database_statements.rb +23 -25
  68. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -1
  69. data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
  70. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -6
  71. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
  72. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +5 -2
  73. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +11 -7
  74. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  75. data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -12
  76. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  77. data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
  78. data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
  79. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +13 -54
  80. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  81. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  82. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  83. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
  84. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -5
  89. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -1
  90. data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
  91. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
  92. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +5 -1
  93. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +61 -29
  94. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  95. data/lib/active_record/connection_adapters/postgresql_adapter.rb +73 -58
  96. data/lib/active_record/connection_adapters/schema_cache.rb +98 -15
  97. data/lib/active_record/connection_adapters/sql_type_metadata.rb +10 -0
  98. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +31 -6
  99. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -1
  100. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  101. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +37 -4
  102. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +49 -50
  103. data/lib/active_record/connection_handling.rb +218 -71
  104. data/lib/active_record/core.rb +245 -61
  105. data/lib/active_record/database_configurations.rb +124 -85
  106. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  107. data/lib/active_record/database_configurations/database_config.rb +52 -9
  108. data/lib/active_record/database_configurations/hash_config.rb +54 -8
  109. data/lib/active_record/database_configurations/url_config.rb +15 -40
  110. data/lib/active_record/delegated_type.rb +209 -0
  111. data/lib/active_record/destroy_association_async_job.rb +36 -0
  112. data/lib/active_record/enum.rb +82 -38
  113. data/lib/active_record/errors.rb +47 -12
  114. data/lib/active_record/explain.rb +9 -4
  115. data/lib/active_record/explain_subscriber.rb +1 -1
  116. data/lib/active_record/fixture_set/file.rb +10 -17
  117. data/lib/active_record/fixture_set/model_metadata.rb +1 -2
  118. data/lib/active_record/fixture_set/render_context.rb +1 -1
  119. data/lib/active_record/fixture_set/table_row.rb +2 -2
  120. data/lib/active_record/fixtures.rb +58 -9
  121. data/lib/active_record/gem_version.rb +3 -3
  122. data/lib/active_record/inheritance.rb +40 -18
  123. data/lib/active_record/insert_all.rb +35 -6
  124. data/lib/active_record/integration.rb +3 -5
  125. data/lib/active_record/internal_metadata.rb +16 -7
  126. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  127. data/lib/active_record/locking/optimistic.rb +33 -17
  128. data/lib/active_record/locking/pessimistic.rb +6 -2
  129. data/lib/active_record/log_subscriber.rb +27 -8
  130. data/lib/active_record/middleware/database_selector.rb +4 -1
  131. data/lib/active_record/middleware/database_selector/resolver.rb +5 -0
  132. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  133. data/lib/active_record/migration.rb +113 -83
  134. data/lib/active_record/migration/command_recorder.rb +47 -27
  135. data/lib/active_record/migration/compatibility.rb +68 -17
  136. data/lib/active_record/model_schema.rb +117 -13
  137. data/lib/active_record/nested_attributes.rb +2 -3
  138. data/lib/active_record/no_touching.rb +1 -1
  139. data/lib/active_record/persistence.rb +50 -45
  140. data/lib/active_record/query_cache.rb +15 -5
  141. data/lib/active_record/querying.rb +11 -6
  142. data/lib/active_record/railtie.rb +64 -44
  143. data/lib/active_record/railties/console_sandbox.rb +2 -4
  144. data/lib/active_record/railties/databases.rake +276 -99
  145. data/lib/active_record/readonly_attributes.rb +4 -0
  146. data/lib/active_record/reflection.rb +71 -57
  147. data/lib/active_record/relation.rb +96 -67
  148. data/lib/active_record/relation/batches.rb +38 -31
  149. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  150. data/lib/active_record/relation/calculations.rb +101 -44
  151. data/lib/active_record/relation/delegation.rb +2 -1
  152. data/lib/active_record/relation/finder_methods.rb +45 -15
  153. data/lib/active_record/relation/from_clause.rb +1 -1
  154. data/lib/active_record/relation/merger.rb +27 -25
  155. data/lib/active_record/relation/predicate_builder.rb +59 -38
  156. data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
  157. data/lib/active_record/relation/predicate_builder/association_query_value.rb +4 -5
  158. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -6
  159. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  160. data/lib/active_record/relation/query_methods.rb +333 -195
  161. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  162. data/lib/active_record/relation/spawn_methods.rb +8 -7
  163. data/lib/active_record/relation/where_clause.rb +104 -57
  164. data/lib/active_record/result.rb +41 -33
  165. data/lib/active_record/runtime_registry.rb +2 -2
  166. data/lib/active_record/sanitization.rb +6 -17
  167. data/lib/active_record/schema_dumper.rb +34 -4
  168. data/lib/active_record/schema_migration.rb +2 -8
  169. data/lib/active_record/scoping/named.rb +6 -17
  170. data/lib/active_record/secure_token.rb +16 -8
  171. data/lib/active_record/serialization.rb +5 -3
  172. data/lib/active_record/signed_id.rb +116 -0
  173. data/lib/active_record/statement_cache.rb +20 -4
  174. data/lib/active_record/store.rb +2 -2
  175. data/lib/active_record/suppressor.rb +2 -2
  176. data/lib/active_record/table_metadata.rb +42 -51
  177. data/lib/active_record/tasks/database_tasks.rb +140 -113
  178. data/lib/active_record/tasks/mysql_database_tasks.rb +34 -35
  179. data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -26
  180. data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -9
  181. data/lib/active_record/test_databases.rb +5 -4
  182. data/lib/active_record/test_fixtures.rb +37 -16
  183. data/lib/active_record/timestamp.rb +4 -6
  184. data/lib/active_record/touch_later.rb +21 -21
  185. data/lib/active_record/transactions.rb +19 -66
  186. data/lib/active_record/type.rb +8 -1
  187. data/lib/active_record/type/serialized.rb +6 -2
  188. data/lib/active_record/type/time.rb +10 -0
  189. data/lib/active_record/type_caster/connection.rb +0 -1
  190. data/lib/active_record/type_caster/map.rb +8 -5
  191. data/lib/active_record/validations.rb +1 -0
  192. data/lib/active_record/validations/numericality.rb +35 -0
  193. data/lib/active_record/validations/uniqueness.rb +24 -4
  194. data/lib/arel.rb +5 -13
  195. data/lib/arel/attributes/attribute.rb +4 -0
  196. data/lib/arel/collectors/bind.rb +5 -0
  197. data/lib/arel/collectors/composite.rb +8 -0
  198. data/lib/arel/collectors/sql_string.rb +7 -0
  199. data/lib/arel/collectors/substitute_binds.rb +7 -0
  200. data/lib/arel/nodes.rb +3 -1
  201. data/lib/arel/nodes/binary.rb +82 -8
  202. data/lib/arel/nodes/bind_param.rb +8 -0
  203. data/lib/arel/nodes/casted.rb +21 -9
  204. data/lib/arel/nodes/equality.rb +6 -9
  205. data/lib/arel/nodes/grouping.rb +3 -0
  206. data/lib/arel/nodes/homogeneous_in.rb +72 -0
  207. data/lib/arel/nodes/in.rb +8 -1
  208. data/lib/arel/nodes/infix_operation.rb +13 -1
  209. data/lib/arel/nodes/join_source.rb +1 -1
  210. data/lib/arel/nodes/node.rb +7 -6
  211. data/lib/arel/nodes/ordering.rb +27 -0
  212. data/lib/arel/nodes/sql_literal.rb +3 -0
  213. data/lib/arel/nodes/table_alias.rb +7 -3
  214. data/lib/arel/nodes/unary.rb +0 -1
  215. data/lib/arel/predications.rb +12 -18
  216. data/lib/arel/select_manager.rb +1 -2
  217. data/lib/arel/table.rb +13 -5
  218. data/lib/arel/visitors.rb +0 -7
  219. data/lib/arel/visitors/dot.rb +14 -2
  220. data/lib/arel/visitors/mysql.rb +11 -1
  221. data/lib/arel/visitors/postgresql.rb +15 -4
  222. data/lib/arel/visitors/to_sql.rb +89 -78
  223. data/lib/rails/generators/active_record/migration.rb +6 -1
  224. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  225. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
  226. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +3 -3
  227. data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
  228. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  229. metadata +25 -26
  230. data/lib/active_record/advisory_lock_base.rb +0 -18
  231. data/lib/active_record/attribute_decorators.rb +0 -88
  232. data/lib/active_record/connection_adapters/connection_specification.rb +0 -296
  233. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  234. data/lib/active_record/define_callbacks.rb +0 -22
  235. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  236. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  237. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  238. data/lib/arel/attributes.rb +0 -22
  239. data/lib/arel/visitors/depth_first.rb +0 -203
  240. data/lib/arel/visitors/ibm_db.rb +0 -34
  241. data/lib/arel/visitors/informix.rb +0 -62
  242. data/lib/arel/visitors/mssql.rb +0 -156
  243. data/lib/arel/visitors/oracle.rb +0 -158
  244. data/lib/arel/visitors/oracle12.rb +0 -65
  245. data/lib/arel/visitors/where_sql.rb +0 -22
@@ -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))
@@ -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
@@ -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,6 +206,18 @@ Passing a range to `#not_in` is deprecated. Call `#not_between`, instead.
220
206
  Nodes::Concat.new self, other
221
207
  end
222
208
 
209
+ def contains(other)
210
+ Arel::Nodes::Contains.new(self, other)
211
+ end
212
+
213
+ def overlaps(other)
214
+ Arel::Nodes::Overlaps.new(self, other)
215
+ end
216
+
217
+ def quoted_array(others)
218
+ others.map { |v| quoted_node(v) }
219
+ end
220
+
223
221
  private
224
222
  def grouping_any(method_id, others, *extras)
225
223
  nodes = others.map { |expr| send(method_id, expr, *extras) }
@@ -237,10 +235,6 @@ Passing a range to `#not_in` is deprecated. Call `#not_between`, instead.
237
235
  Nodes.build_quoted(other, self)
238
236
  end
239
237
 
240
- def quoted_array(others)
241
- others.map { |v| quoted_node(v) }
242
- end
243
-
244
238
  def infinity?(value)
245
239
  value.respond_to?(:infinite?) && value.infinite?
246
240
  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?
data/lib/arel/visitors.rb CHANGED
@@ -1,18 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "arel/visitors/visitor"
4
- require "arel/visitors/depth_first"
5
4
  require "arel/visitors/to_sql"
6
5
  require "arel/visitors/sqlite"
7
6
  require "arel/visitors/postgresql"
8
7
  require "arel/visitors/mysql"
9
- require "arel/visitors/mssql"
10
- require "arel/visitors/oracle"
11
- require "arel/visitors/oracle12"
12
- require "arel/visitors/where_sql"
13
8
  require "arel/visitors/dot"
14
- require "arel/visitors/ibm_db"
15
- require "arel/visitors/informix"
16
9
 
17
10
  module Arel # :nodoc: all
18
11
  module Visitors
@@ -157,7 +157,13 @@ module Arel # :nodoc: all
157
157
  end
158
158
 
159
159
  def visit_Arel_Nodes_Casted(o)
160
- 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"
161
167
  visit_edge o, "attribute"
162
168
  end
163
169
 
@@ -218,7 +224,13 @@ module Arel # :nodoc: all
218
224
  alias :visit_Symbol :visit_String
219
225
  alias :visit_Arel_Nodes_SqlLiteral :visit_String
220
226
 
221
- 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
222
234
 
223
235
  def visit_Hash(o)
224
236
  o.each_with_index do |pair, i|
@@ -15,7 +15,9 @@ module Arel # :nodoc: all
15
15
 
16
16
  ###
17
17
  # :'(
18
- # http://dev.mysql.com/doc/refman/5.0/en/select.html#id3482214
18
+ # To retrieve all rows from a certain offset up to the end of the result set,
19
+ # you can use some large number for the second parameter.
20
+ # https://dev.mysql.com/doc/refman/en/select.html
19
21
  def visit_Arel_Nodes_SelectStatement(o, collector)
20
22
  if o.offset && !o.limit
21
23
  o.limit = Arel::Nodes::Limit.new(18446744073709551615)
@@ -48,6 +50,14 @@ module Arel # :nodoc: all
48
50
  visit_Arel_Nodes_IsNotDistinctFrom o, collector
49
51
  end
50
52
 
53
+ def visit_Arel_Nodes_Regexp(o, collector)
54
+ infix_value o, collector, " REGEXP "
55
+ end
56
+
57
+ def visit_Arel_Nodes_NotRegexp(o, collector)
58
+ infix_value o, collector, " NOT REGEXP "
59
+ end
60
+
51
61
  # In the simple case, MySQL allows us to place JOINs directly into the UPDATE
52
62
  # query. However, this does not allow for LIMIT, OFFSET and ORDER. To support
53
63
  # these, we must use a subquery.
@@ -41,10 +41,6 @@ module Arel # :nodoc: all
41
41
  visit(o.expr, collector) << " )"
42
42
  end
43
43
 
44
- def visit_Arel_Nodes_BindParam(o, collector)
45
- collector.add_bind(o.value) { |i| "$#{i}" }
46
- end
47
-
48
44
  def visit_Arel_Nodes_GroupingElement(o, collector)
49
45
  collector << "( "
50
46
  visit(o.expr, collector) << " )"
@@ -82,6 +78,21 @@ module Arel # :nodoc: all
82
78
  visit o.right, collector
83
79
  end
84
80
 
81
+ def visit_Arel_Nodes_NullsFirst(o, collector)
82
+ visit o.expr, collector
83
+ collector << " NULLS FIRST"
84
+ end
85
+
86
+ def visit_Arel_Nodes_NullsLast(o, collector)
87
+ visit o.expr, collector
88
+ collector << " NULLS LAST"
89
+ end
90
+
91
+ BIND_BLOCK = proc { |i| "$#{i}" }
92
+ private_constant :BIND_BLOCK
93
+
94
+ def bind_block; BIND_BLOCK; end
95
+
85
96
  # Used by Lateral visitor to enclose select queries in parentheses
86
97
  def grouping_parentheses(o, collector)
87
98
  if o.expr.is_a? Nodes::SelectStatement
@@ -82,12 +82,9 @@ module Arel # :nodoc: all
82
82
  end
83
83
 
84
84
  def visit_Arel_Nodes_Casted(o, collector)
85
- collector << quoted(o.val, o.attribute).to_s
86
- end
87
-
88
- def visit_Arel_Nodes_Quoted(o, collector)
89
- collector << quoted(o.expr, nil).to_s
85
+ collector << quote(o.value_for_database).to_s
90
86
  end
87
+ alias :visit_Arel_Nodes_Quoted :visit_Arel_Nodes_Casted
91
88
 
92
89
  def visit_Arel_Nodes_True(o, collector)
93
90
  collector << "TRUE"
@@ -195,12 +192,12 @@ module Arel # :nodoc: all
195
192
 
196
193
  def visit_Arel_Nodes_With(o, collector)
197
194
  collector << "WITH "
198
- inject_join o.children, collector, ", "
195
+ collect_ctes(o.children, collector)
199
196
  end
200
197
 
201
198
  def visit_Arel_Nodes_WithRecursive(o, collector)
202
199
  collector << "WITH RECURSIVE "
203
- inject_join o.children, collector, ", "
200
+ collect_ctes(o.children, collector)
204
201
  end
205
202
 
206
203
  def visit_Arel_Nodes_Union(o, collector)
@@ -324,6 +321,29 @@ module Arel # :nodoc: all
324
321
  end
325
322
  end
326
323
 
324
+ def visit_Arel_Nodes_HomogeneousIn(o, collector)
325
+ collector.preparable = false
326
+
327
+ collector << quote_table_name(o.table_name) << "." << quote_column_name(o.column_name)
328
+
329
+ if o.type == :in
330
+ collector << " IN ("
331
+ else
332
+ collector << " NOT IN ("
333
+ end
334
+
335
+ values = o.casted_values
336
+
337
+ if values.empty?
338
+ collector << @connection.quote(nil)
339
+ else
340
+ collector.add_binds(values, &bind_block)
341
+ end
342
+
343
+ collector << ")"
344
+ collector
345
+ end
346
+
327
347
  def visit_Arel_SelectManager(o, collector)
328
348
  collector << "("
329
349
  visit(o.ast, collector) << ")"
@@ -513,64 +533,35 @@ module Arel # :nodoc: all
513
533
  end
514
534
 
515
535
  def visit_Arel_Nodes_In(o, collector)
516
- unless Array === o.right
517
- return collect_in_clause(o.left, o.right, collector)
518
- end
519
-
520
- unless o.right.empty?
521
- o.right.delete_if { |value| unboundable?(value) }
522
- end
536
+ collector.preparable = false
537
+ attr, values = o.left, o.right
523
538
 
524
- return collector << "1=0" if o.right.empty?
525
-
526
- in_clause_length = @connection.in_clause_length
527
-
528
- if !in_clause_length || o.right.length <= in_clause_length
529
- collect_in_clause(o.left, o.right, collector)
530
- else
531
- collector << "("
532
- o.right.each_slice(in_clause_length).each_with_index do |right, i|
533
- collector << " OR " unless i == 0
534
- collect_in_clause(o.left, right, collector)
539
+ if Array === values
540
+ unless values.empty?
541
+ values.delete_if { |value| unboundable?(value) }
535
542
  end
536
- collector << ")"
543
+
544
+ return collector << "1=0" if values.empty?
537
545
  end
538
- end
539
546
 
540
- def collect_in_clause(left, right, collector)
541
- collector = visit left, collector
542
- collector << " IN ("
543
- visit(right, collector) << ")"
547
+ visit(attr, collector) << " IN ("
548
+ visit(values, collector) << ")"
544
549
  end
545
550
 
546
551
  def visit_Arel_Nodes_NotIn(o, collector)
547
- unless Array === o.right
548
- return collect_not_in_clause(o.left, o.right, collector)
549
- end
550
-
551
- unless o.right.empty?
552
- o.right.delete_if { |value| unboundable?(value) }
553
- end
552
+ collector.preparable = false
553
+ attr, values = o.left, o.right
554
554
 
555
- return collector << "1=1" if o.right.empty?
556
-
557
- in_clause_length = @connection.in_clause_length
558
-
559
- if !in_clause_length || o.right.length <= in_clause_length
560
- collect_not_in_clause(o.left, o.right, collector)
561
- else
562
- o.right.each_slice(in_clause_length).each_with_index do |right, i|
563
- collector << " AND " unless i == 0
564
- collect_not_in_clause(o.left, right, collector)
555
+ if Array === values
556
+ unless values.empty?
557
+ values.delete_if { |value| unboundable?(value) }
565
558
  end
566
- collector
559
+
560
+ return collector << "1=1" if values.empty?
567
561
  end
568
- end
569
562
 
570
- def collect_not_in_clause(left, right, collector)
571
- collector = visit left, collector
572
- collector << " NOT IN ("
573
- visit(right, collector) << ")"
563
+ visit(attr, collector) << " NOT IN ("
564
+ visit(values, collector) << ")"
574
565
  end
575
566
 
576
567
  def visit_Arel_Nodes_And(o, collector)
@@ -578,9 +569,18 @@ module Arel # :nodoc: all
578
569
  end
579
570
 
580
571
  def visit_Arel_Nodes_Or(o, collector)
581
- collector = visit o.left, collector
582
- collector << " OR "
583
- visit o.right, collector
572
+ stack = [o.right, o.left]
573
+
574
+ while o = stack.pop
575
+ if o.is_a?(Arel::Nodes::Or)
576
+ stack.push o.right, o.left
577
+ else
578
+ visit o, collector
579
+ collector << " OR " unless stack.empty?
580
+ end
581
+ end
582
+
583
+ collector
584
584
  end
585
585
 
586
586
  def visit_Arel_Nodes_Assignment(o, collector)
@@ -689,28 +689,23 @@ module Arel # :nodoc: all
689
689
  join_name = o.relation.table_alias || o.relation.name
690
690
  collector << quote_table_name(join_name) << "." << quote_column_name(o.name)
691
691
  end
692
- alias :visit_Arel_Attributes_Integer :visit_Arel_Attributes_Attribute
693
- alias :visit_Arel_Attributes_Float :visit_Arel_Attributes_Attribute
694
- alias :visit_Arel_Attributes_Decimal :visit_Arel_Attributes_Attribute
695
- alias :visit_Arel_Attributes_String :visit_Arel_Attributes_Attribute
696
- alias :visit_Arel_Attributes_Time :visit_Arel_Attributes_Attribute
697
- alias :visit_Arel_Attributes_Boolean :visit_Arel_Attributes_Attribute
698
692
 
699
- def literal(o, collector); collector << o.to_s; end
693
+ BIND_BLOCK = proc { "?" }
694
+ private_constant :BIND_BLOCK
695
+
696
+ def bind_block; BIND_BLOCK; end
700
697
 
701
698
  def visit_Arel_Nodes_BindParam(o, collector)
702
- collector.add_bind(o.value) { "?" }
699
+ collector.add_bind(o.value, &bind_block)
703
700
  end
704
701
 
705
- alias :visit_Arel_Nodes_SqlLiteral :literal
706
- alias :visit_Integer :literal
702
+ def visit_Arel_Nodes_SqlLiteral(o, collector)
703
+ collector.preparable = false
704
+ collector << o.to_s
705
+ end
707
706
 
708
- def quoted(o, a)
709
- if a && a.able_to_type_cast?
710
- quote(a.type_cast_for_database(o))
711
- else
712
- quote(o)
713
- end
707
+ def visit_Integer(o, collector)
708
+ collector << o.to_s
714
709
  end
715
710
 
716
711
  def unsupported(o, collector)
@@ -738,11 +733,6 @@ module Arel # :nodoc: all
738
733
  visit o.right, collector
739
734
  end
740
735
 
741
- alias :visit_Arel_Nodes_Addition :visit_Arel_Nodes_InfixOperation
742
- alias :visit_Arel_Nodes_Subtraction :visit_Arel_Nodes_InfixOperation
743
- alias :visit_Arel_Nodes_Multiplication :visit_Arel_Nodes_InfixOperation
744
- alias :visit_Arel_Nodes_Division :visit_Arel_Nodes_InfixOperation
745
-
746
736
  def visit_Arel_Nodes_UnaryOperation(o, collector)
747
737
  collector << " #{o.operator} "
748
738
  visit o.expr, collector
@@ -883,6 +873,27 @@ module Arel # :nodoc: all
883
873
  collector << " IS NULL)"
884
874
  collector << " THEN 0 ELSE 1 END"
885
875
  end
876
+
877
+ def collect_ctes(children, collector)
878
+ children.each_with_index do |child, i|
879
+ collector << ", " unless i == 0
880
+
881
+ case child
882
+ when Arel::Nodes::As
883
+ name = child.left.name
884
+ relation = child.right
885
+ when Arel::Nodes::TableAlias
886
+ name = child.name
887
+ relation = child.relation
888
+ end
889
+
890
+ collector << quote_table_name(name)
891
+ collector << " AS "
892
+ visit relation, collector
893
+ end
894
+
895
+ collector
896
+ end
886
897
  end
887
898
  end
888
899
  end