activerecord 5.2.8.1 → 6.1.6.1

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 (316) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1255 -596
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +7 -5
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record/aggregations.rb +9 -8
  7. data/lib/active_record/association_relation.rb +30 -10
  8. data/lib/active_record/associations/alias_tracker.rb +19 -16
  9. data/lib/active_record/associations/association.rb +100 -41
  10. data/lib/active_record/associations/association_scope.rb +23 -21
  11. data/lib/active_record/associations/belongs_to_association.rb +55 -48
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -6
  13. data/lib/active_record/associations/builder/association.rb +45 -22
  14. data/lib/active_record/associations/builder/belongs_to.rb +29 -59
  15. data/lib/active_record/associations/builder/collection_association.rb +8 -17
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
  17. data/lib/active_record/associations/builder/has_many.rb +8 -2
  18. data/lib/active_record/associations/builder/has_one.rb +33 -2
  19. data/lib/active_record/associations/builder/singular_association.rb +3 -1
  20. data/lib/active_record/associations/collection_association.rb +44 -34
  21. data/lib/active_record/associations/collection_proxy.rb +25 -21
  22. data/lib/active_record/associations/foreign_association.rb +20 -0
  23. data/lib/active_record/associations/has_many_association.rb +26 -13
  24. data/lib/active_record/associations/has_many_through_association.rb +24 -18
  25. data/lib/active_record/associations/has_one_association.rb +43 -31
  26. data/lib/active_record/associations/has_one_through_association.rb +5 -5
  27. data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
  28. data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
  29. data/lib/active_record/associations/join_dependency.rb +91 -60
  30. data/lib/active_record/associations/preloader/association.rb +69 -43
  31. data/lib/active_record/associations/preloader/through_association.rb +49 -40
  32. data/lib/active_record/associations/preloader.rb +47 -34
  33. data/lib/active_record/associations/singular_association.rb +3 -17
  34. data/lib/active_record/associations/through_association.rb +1 -1
  35. data/lib/active_record/associations.rb +137 -25
  36. data/lib/active_record/attribute_assignment.rb +17 -19
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -7
  38. data/lib/active_record/attribute_methods/dirty.rb +101 -40
  39. data/lib/active_record/attribute_methods/primary_key.rb +20 -25
  40. data/lib/active_record/attribute_methods/query.rb +4 -8
  41. data/lib/active_record/attribute_methods/read.rb +14 -56
  42. data/lib/active_record/attribute_methods/serialization.rb +12 -7
  43. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
  44. data/lib/active_record/attribute_methods/write.rb +18 -34
  45. data/lib/active_record/attribute_methods.rb +81 -143
  46. data/lib/active_record/attributes.rb +46 -9
  47. data/lib/active_record/autosave_association.rb +57 -42
  48. data/lib/active_record/base.rb +4 -17
  49. data/lib/active_record/callbacks.rb +158 -43
  50. data/lib/active_record/coders/yaml_column.rb +1 -2
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +272 -130
  52. data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -36
  53. data/lib/active_record/connection_adapters/abstract/database_statements.rb +167 -146
  54. data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -14
  55. data/lib/active_record/connection_adapters/abstract/quoting.rb +98 -47
  56. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  57. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -110
  58. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +211 -90
  59. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -4
  60. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +385 -144
  61. data/lib/active_record/connection_adapters/abstract/transaction.rb +167 -69
  62. data/lib/active_record/connection_adapters/abstract_adapter.rb +229 -99
  63. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +243 -275
  64. data/lib/active_record/connection_adapters/column.rb +30 -12
  65. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  66. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  67. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  68. data/lib/active_record/connection_adapters/mysql/database_statements.rb +88 -32
  69. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  70. data/lib/active_record/connection_adapters/mysql/quoting.rb +59 -7
  71. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
  72. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
  73. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +18 -7
  74. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +142 -19
  75. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
  76. data/lib/active_record/connection_adapters/mysql2_adapter.rb +53 -18
  77. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  78. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  79. data/lib/active_record/connection_adapters/postgresql/column.rb +37 -28
  80. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +40 -54
  81. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  82. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  83. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  84. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
  90. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
  93. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
  94. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  95. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
  96. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
  97. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  98. data/lib/active_record/connection_adapters/postgresql/quoting.rb +47 -10
  99. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
  100. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +19 -4
  101. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
  102. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  103. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +120 -100
  104. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
  105. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  106. data/lib/active_record/connection_adapters/postgresql_adapter.rb +224 -120
  107. data/lib/active_record/connection_adapters/schema_cache.rb +159 -21
  108. data/lib/active_record/connection_adapters/sql_type_metadata.rb +17 -6
  109. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
  110. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
  111. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  112. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +77 -13
  113. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +174 -186
  114. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  115. data/lib/active_record/connection_adapters.rb +52 -0
  116. data/lib/active_record/connection_handling.rb +293 -33
  117. data/lib/active_record/core.rb +333 -98
  118. data/lib/active_record/counter_cache.rb +8 -30
  119. data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
  120. data/lib/active_record/database_configurations/database_config.rb +80 -0
  121. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  122. data/lib/active_record/database_configurations/url_config.rb +53 -0
  123. data/lib/active_record/database_configurations.rb +273 -0
  124. data/lib/active_record/delegated_type.rb +209 -0
  125. data/lib/active_record/destroy_association_async_job.rb +36 -0
  126. data/lib/active_record/dynamic_matchers.rb +3 -4
  127. data/lib/active_record/enum.rb +108 -36
  128. data/lib/active_record/errors.rb +62 -19
  129. data/lib/active_record/explain.rb +10 -6
  130. data/lib/active_record/explain_subscriber.rb +1 -1
  131. data/lib/active_record/fixture_set/file.rb +10 -17
  132. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  133. data/lib/active_record/fixture_set/render_context.rb +17 -0
  134. data/lib/active_record/fixture_set/table_row.rb +152 -0
  135. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  136. data/lib/active_record/fixtures.rb +200 -481
  137. data/lib/active_record/gem_version.rb +3 -3
  138. data/lib/active_record/inheritance.rb +53 -24
  139. data/lib/active_record/insert_all.rb +212 -0
  140. data/lib/active_record/integration.rb +67 -17
  141. data/lib/active_record/internal_metadata.rb +28 -9
  142. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  143. data/lib/active_record/locking/optimistic.rb +37 -23
  144. data/lib/active_record/locking/pessimistic.rb +9 -5
  145. data/lib/active_record/log_subscriber.rb +35 -35
  146. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  147. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  148. data/lib/active_record/middleware/database_selector.rb +77 -0
  149. data/lib/active_record/migration/command_recorder.rb +96 -44
  150. data/lib/active_record/migration/compatibility.rb +145 -64
  151. data/lib/active_record/migration/join_table.rb +0 -1
  152. data/lib/active_record/migration.rb +206 -157
  153. data/lib/active_record/model_schema.rb +148 -22
  154. data/lib/active_record/nested_attributes.rb +4 -7
  155. data/lib/active_record/no_touching.rb +8 -1
  156. data/lib/active_record/null_relation.rb +0 -1
  157. data/lib/active_record/persistence.rb +267 -59
  158. data/lib/active_record/query_cache.rb +21 -4
  159. data/lib/active_record/querying.rb +40 -23
  160. data/lib/active_record/railtie.rb +116 -59
  161. data/lib/active_record/railties/console_sandbox.rb +2 -4
  162. data/lib/active_record/railties/controller_runtime.rb +30 -35
  163. data/lib/active_record/railties/databases.rake +411 -80
  164. data/lib/active_record/readonly_attributes.rb +4 -0
  165. data/lib/active_record/reflection.rb +109 -93
  166. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  167. data/lib/active_record/relation/batches.rb +44 -35
  168. data/lib/active_record/relation/calculations.rb +157 -90
  169. data/lib/active_record/relation/delegation.rb +35 -50
  170. data/lib/active_record/relation/finder_methods.rb +64 -39
  171. data/lib/active_record/relation/from_clause.rb +5 -1
  172. data/lib/active_record/relation/merger.rb +32 -40
  173. data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
  174. data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
  175. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  176. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
  177. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  178. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  179. data/lib/active_record/relation/predicate_builder.rb +62 -45
  180. data/lib/active_record/relation/query_attribute.rb +13 -8
  181. data/lib/active_record/relation/query_methods.rb +476 -187
  182. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  183. data/lib/active_record/relation/spawn_methods.rb +9 -9
  184. data/lib/active_record/relation/where_clause.rb +115 -62
  185. data/lib/active_record/relation.rb +379 -115
  186. data/lib/active_record/result.rb +64 -38
  187. data/lib/active_record/runtime_registry.rb +2 -2
  188. data/lib/active_record/sanitization.rb +22 -41
  189. data/lib/active_record/schema.rb +2 -11
  190. data/lib/active_record/schema_dumper.rb +54 -9
  191. data/lib/active_record/schema_migration.rb +7 -9
  192. data/lib/active_record/scoping/default.rb +4 -8
  193. data/lib/active_record/scoping/named.rb +17 -24
  194. data/lib/active_record/scoping.rb +8 -9
  195. data/lib/active_record/secure_token.rb +16 -8
  196. data/lib/active_record/serialization.rb +5 -3
  197. data/lib/active_record/signed_id.rb +116 -0
  198. data/lib/active_record/statement_cache.rb +49 -6
  199. data/lib/active_record/store.rb +88 -9
  200. data/lib/active_record/suppressor.rb +2 -2
  201. data/lib/active_record/table_metadata.rb +42 -43
  202. data/lib/active_record/tasks/database_tasks.rb +277 -81
  203. data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
  204. data/lib/active_record/tasks/postgresql_database_tasks.rb +27 -32
  205. data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
  206. data/lib/active_record/test_databases.rb +24 -0
  207. data/lib/active_record/test_fixtures.rb +287 -0
  208. data/lib/active_record/timestamp.rb +43 -32
  209. data/lib/active_record/touch_later.rb +23 -22
  210. data/lib/active_record/transactions.rb +62 -118
  211. data/lib/active_record/translation.rb +1 -1
  212. data/lib/active_record/type/adapter_specific_registry.rb +3 -13
  213. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  214. data/lib/active_record/type/serialized.rb +6 -3
  215. data/lib/active_record/type/time.rb +10 -0
  216. data/lib/active_record/type/type_map.rb +0 -1
  217. data/lib/active_record/type/unsigned_integer.rb +0 -1
  218. data/lib/active_record/type.rb +10 -5
  219. data/lib/active_record/type_caster/connection.rb +15 -15
  220. data/lib/active_record/type_caster/map.rb +8 -8
  221. data/lib/active_record/validations/associated.rb +1 -2
  222. data/lib/active_record/validations/numericality.rb +35 -0
  223. data/lib/active_record/validations/uniqueness.rb +38 -30
  224. data/lib/active_record/validations.rb +4 -3
  225. data/lib/active_record.rb +13 -12
  226. data/lib/arel/alias_predication.rb +9 -0
  227. data/lib/arel/attributes/attribute.rb +41 -0
  228. data/lib/arel/collectors/bind.rb +29 -0
  229. data/lib/arel/collectors/composite.rb +39 -0
  230. data/lib/arel/collectors/plain_string.rb +20 -0
  231. data/lib/arel/collectors/sql_string.rb +27 -0
  232. data/lib/arel/collectors/substitute_binds.rb +35 -0
  233. data/lib/arel/crud.rb +42 -0
  234. data/lib/arel/delete_manager.rb +18 -0
  235. data/lib/arel/errors.rb +9 -0
  236. data/lib/arel/expressions.rb +29 -0
  237. data/lib/arel/factory_methods.rb +49 -0
  238. data/lib/arel/insert_manager.rb +49 -0
  239. data/lib/arel/math.rb +45 -0
  240. data/lib/arel/nodes/and.rb +32 -0
  241. data/lib/arel/nodes/ascending.rb +23 -0
  242. data/lib/arel/nodes/binary.rb +126 -0
  243. data/lib/arel/nodes/bind_param.rb +44 -0
  244. data/lib/arel/nodes/case.rb +55 -0
  245. data/lib/arel/nodes/casted.rb +62 -0
  246. data/lib/arel/nodes/comment.rb +29 -0
  247. data/lib/arel/nodes/count.rb +12 -0
  248. data/lib/arel/nodes/delete_statement.rb +45 -0
  249. data/lib/arel/nodes/descending.rb +23 -0
  250. data/lib/arel/nodes/equality.rb +15 -0
  251. data/lib/arel/nodes/extract.rb +24 -0
  252. data/lib/arel/nodes/false.rb +16 -0
  253. data/lib/arel/nodes/full_outer_join.rb +8 -0
  254. data/lib/arel/nodes/function.rb +44 -0
  255. data/lib/arel/nodes/grouping.rb +11 -0
  256. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  257. data/lib/arel/nodes/in.rb +15 -0
  258. data/lib/arel/nodes/infix_operation.rb +92 -0
  259. data/lib/arel/nodes/inner_join.rb +8 -0
  260. data/lib/arel/nodes/insert_statement.rb +37 -0
  261. data/lib/arel/nodes/join_source.rb +20 -0
  262. data/lib/arel/nodes/matches.rb +18 -0
  263. data/lib/arel/nodes/named_function.rb +23 -0
  264. data/lib/arel/nodes/node.rb +51 -0
  265. data/lib/arel/nodes/node_expression.rb +13 -0
  266. data/lib/arel/nodes/ordering.rb +27 -0
  267. data/lib/arel/nodes/outer_join.rb +8 -0
  268. data/lib/arel/nodes/over.rb +15 -0
  269. data/lib/arel/nodes/regexp.rb +16 -0
  270. data/lib/arel/nodes/right_outer_join.rb +8 -0
  271. data/lib/arel/nodes/select_core.rb +67 -0
  272. data/lib/arel/nodes/select_statement.rb +41 -0
  273. data/lib/arel/nodes/sql_literal.rb +19 -0
  274. data/lib/arel/nodes/string_join.rb +11 -0
  275. data/lib/arel/nodes/table_alias.rb +31 -0
  276. data/lib/arel/nodes/terminal.rb +16 -0
  277. data/lib/arel/nodes/true.rb +16 -0
  278. data/lib/arel/nodes/unary.rb +44 -0
  279. data/lib/arel/nodes/unary_operation.rb +20 -0
  280. data/lib/arel/nodes/unqualified_column.rb +22 -0
  281. data/lib/arel/nodes/update_statement.rb +41 -0
  282. data/lib/arel/nodes/values_list.rb +9 -0
  283. data/lib/arel/nodes/window.rb +126 -0
  284. data/lib/arel/nodes/with.rb +11 -0
  285. data/lib/arel/nodes.rb +70 -0
  286. data/lib/arel/order_predications.rb +13 -0
  287. data/lib/arel/predications.rb +250 -0
  288. data/lib/arel/select_manager.rb +270 -0
  289. data/lib/arel/table.rb +118 -0
  290. data/lib/arel/tree_manager.rb +72 -0
  291. data/lib/arel/update_manager.rb +34 -0
  292. data/lib/arel/visitors/dot.rb +308 -0
  293. data/lib/arel/visitors/mysql.rb +93 -0
  294. data/lib/arel/visitors/postgresql.rb +120 -0
  295. data/lib/arel/visitors/sqlite.rb +38 -0
  296. data/lib/arel/visitors/to_sql.rb +899 -0
  297. data/lib/arel/visitors/visitor.rb +45 -0
  298. data/lib/arel/visitors.rb +13 -0
  299. data/lib/arel/window_predications.rb +9 -0
  300. data/lib/arel.rb +54 -0
  301. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  302. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
  303. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
  304. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
  305. data/lib/rails/generators/active_record/migration.rb +19 -2
  306. data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
  307. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  308. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  309. metadata +116 -30
  310. data/lib/active_record/attribute_decorators.rb +0 -90
  311. data/lib/active_record/collection_cache_key.rb +0 -53
  312. data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
  313. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
  314. data/lib/active_record/define_callbacks.rb +0 -22
  315. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
  316. data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -0,0 +1,270 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arel # :nodoc: all
4
+ class SelectManager < Arel::TreeManager
5
+ include Arel::Crud
6
+
7
+ STRING_OR_SYMBOL_CLASS = [Symbol, String]
8
+
9
+ def initialize(table = nil)
10
+ super()
11
+ @ast = Nodes::SelectStatement.new
12
+ @ctx = @ast.cores.last
13
+ from table
14
+ end
15
+
16
+ def initialize_copy(other)
17
+ super
18
+ @ctx = @ast.cores.last
19
+ end
20
+
21
+ def limit
22
+ @ast.limit && @ast.limit.expr
23
+ end
24
+ alias :taken :limit
25
+
26
+ def constraints
27
+ @ctx.wheres
28
+ end
29
+
30
+ def offset
31
+ @ast.offset && @ast.offset.expr
32
+ end
33
+
34
+ def skip(amount)
35
+ if amount
36
+ @ast.offset = Nodes::Offset.new(amount)
37
+ else
38
+ @ast.offset = nil
39
+ end
40
+ self
41
+ end
42
+ alias :offset= :skip
43
+
44
+ ###
45
+ # Produces an Arel::Nodes::Exists node
46
+ def exists
47
+ Arel::Nodes::Exists.new @ast
48
+ end
49
+
50
+ def as(other)
51
+ create_table_alias grouping(@ast), Nodes::SqlLiteral.new(other)
52
+ end
53
+
54
+ def lock(locking = Arel.sql("FOR UPDATE"))
55
+ case locking
56
+ when true
57
+ locking = Arel.sql("FOR UPDATE")
58
+ when Arel::Nodes::SqlLiteral
59
+ when String
60
+ locking = Arel.sql locking
61
+ end
62
+
63
+ @ast.lock = Nodes::Lock.new(locking)
64
+ self
65
+ end
66
+
67
+ def locked
68
+ @ast.lock
69
+ end
70
+
71
+ def on(*exprs)
72
+ @ctx.source.right.last.right = Nodes::On.new(collapse(exprs))
73
+ self
74
+ end
75
+
76
+ def group(*columns)
77
+ columns.each do |column|
78
+ # FIXME: backwards compat
79
+ column = Nodes::SqlLiteral.new(column) if String === column
80
+ column = Nodes::SqlLiteral.new(column.to_s) if Symbol === column
81
+
82
+ @ctx.groups.push Nodes::Group.new column
83
+ end
84
+ self
85
+ end
86
+
87
+ def from(table)
88
+ table = Nodes::SqlLiteral.new(table) if String === table
89
+
90
+ case table
91
+ when Nodes::Join
92
+ @ctx.source.right << table
93
+ else
94
+ @ctx.source.left = table
95
+ end
96
+
97
+ self
98
+ end
99
+
100
+ def froms
101
+ @ast.cores.map { |x| x.from }.compact
102
+ end
103
+
104
+ def join(relation, klass = Nodes::InnerJoin)
105
+ return self unless relation
106
+
107
+ case relation
108
+ when String, Nodes::SqlLiteral
109
+ raise EmptyJoinError if relation.empty?
110
+ klass = Nodes::StringJoin
111
+ end
112
+
113
+ @ctx.source.right << create_join(relation, nil, klass)
114
+ self
115
+ end
116
+
117
+ def outer_join(relation)
118
+ join(relation, Nodes::OuterJoin)
119
+ end
120
+
121
+ def having(expr)
122
+ @ctx.havings << expr
123
+ self
124
+ end
125
+
126
+ def window(name)
127
+ window = Nodes::NamedWindow.new(name)
128
+ @ctx.windows.push window
129
+ window
130
+ end
131
+
132
+ def project(*projections)
133
+ # FIXME: converting these to SQLLiterals is probably not good, but
134
+ # rails tests require it.
135
+ @ctx.projections.concat projections.map { |x|
136
+ STRING_OR_SYMBOL_CLASS.include?(x.class) ? Nodes::SqlLiteral.new(x.to_s) : x
137
+ }
138
+ self
139
+ end
140
+
141
+ def projections
142
+ @ctx.projections
143
+ end
144
+
145
+ def projections=(projections)
146
+ @ctx.projections = projections
147
+ end
148
+
149
+ def optimizer_hints(*hints)
150
+ unless hints.empty?
151
+ @ctx.optimizer_hints = Arel::Nodes::OptimizerHints.new(hints)
152
+ end
153
+ self
154
+ end
155
+
156
+ def distinct(value = true)
157
+ if value
158
+ @ctx.set_quantifier = Arel::Nodes::Distinct.new
159
+ else
160
+ @ctx.set_quantifier = nil
161
+ end
162
+ self
163
+ end
164
+
165
+ def distinct_on(value)
166
+ if value
167
+ @ctx.set_quantifier = Arel::Nodes::DistinctOn.new(value)
168
+ else
169
+ @ctx.set_quantifier = nil
170
+ end
171
+ self
172
+ end
173
+
174
+ def order(*expr)
175
+ # FIXME: We SHOULD NOT be converting these to SqlLiteral automatically
176
+ @ast.orders.concat expr.map { |x|
177
+ STRING_OR_SYMBOL_CLASS.include?(x.class) ? Nodes::SqlLiteral.new(x.to_s) : x
178
+ }
179
+ self
180
+ end
181
+
182
+ def orders
183
+ @ast.orders
184
+ end
185
+
186
+ def where_sql(engine = Table.engine)
187
+ return if @ctx.wheres.empty?
188
+
189
+ Nodes::SqlLiteral.new("WHERE #{Nodes::And.new(@ctx.wheres).to_sql(engine)}")
190
+ end
191
+
192
+ def union(operation, other = nil)
193
+ if other
194
+ node_class = Nodes.const_get("Union#{operation.to_s.capitalize}")
195
+ else
196
+ other = operation
197
+ node_class = Nodes::Union
198
+ end
199
+
200
+ node_class.new self.ast, other.ast
201
+ end
202
+
203
+ def intersect(other)
204
+ Nodes::Intersect.new ast, other.ast
205
+ end
206
+
207
+ def except(other)
208
+ Nodes::Except.new ast, other.ast
209
+ end
210
+ alias :minus :except
211
+
212
+ def lateral(table_name = nil)
213
+ base = table_name.nil? ? ast : as(table_name)
214
+ Nodes::Lateral.new(base)
215
+ end
216
+
217
+ def with(*subqueries)
218
+ if subqueries.first.is_a? Symbol
219
+ node_class = Nodes.const_get("With#{subqueries.shift.to_s.capitalize}")
220
+ else
221
+ node_class = Nodes::With
222
+ end
223
+ @ast.with = node_class.new(subqueries.flatten)
224
+
225
+ self
226
+ end
227
+
228
+ def take(limit)
229
+ if limit
230
+ @ast.limit = Nodes::Limit.new(limit)
231
+ else
232
+ @ast.limit = nil
233
+ end
234
+ self
235
+ end
236
+ alias limit= take
237
+
238
+ def join_sources
239
+ @ctx.source.right
240
+ end
241
+
242
+ def source
243
+ @ctx.source
244
+ end
245
+
246
+ def comment(*values)
247
+ @ctx.comment = Nodes::Comment.new(values)
248
+ self
249
+ end
250
+
251
+ private
252
+ def collapse(exprs)
253
+ exprs = exprs.compact
254
+ exprs.map! { |expr|
255
+ if String === expr
256
+ # FIXME: Don't do this automatically
257
+ Arel.sql(expr)
258
+ else
259
+ expr
260
+ end
261
+ }
262
+
263
+ if exprs.length == 1
264
+ exprs.first
265
+ else
266
+ create_and exprs
267
+ end
268
+ end
269
+ end
270
+ end
data/lib/arel/table.rb ADDED
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arel # :nodoc: all
4
+ class Table
5
+ include Arel::Crud
6
+ include Arel::FactoryMethods
7
+ include Arel::AliasPredication
8
+
9
+ @engine = nil
10
+ class << self; attr_accessor :engine; end
11
+
12
+ attr_accessor :name, :table_alias
13
+
14
+ # TableAlias and Table both have a #table_name which is the name of the underlying table
15
+ alias :table_name :name
16
+
17
+ def initialize(name, as: nil, klass: nil, type_caster: klass&.type_caster)
18
+ @name = name.to_s
19
+ @klass = klass
20
+ @type_caster = type_caster
21
+
22
+ # Sometime AR sends an :as parameter to table, to let the table know
23
+ # that it is an Alias. We may want to override new, and return a
24
+ # TableAlias node?
25
+ if as.to_s == @name
26
+ as = nil
27
+ end
28
+ @table_alias = as
29
+ end
30
+
31
+ def alias(name = "#{self.name}_2")
32
+ Nodes::TableAlias.new(self, name)
33
+ end
34
+
35
+ def from
36
+ SelectManager.new(self)
37
+ end
38
+
39
+ def join(relation, klass = Nodes::InnerJoin)
40
+ return from unless relation
41
+
42
+ case relation
43
+ when String, Nodes::SqlLiteral
44
+ raise EmptyJoinError if relation.empty?
45
+ klass = Nodes::StringJoin
46
+ end
47
+
48
+ from.join(relation, klass)
49
+ end
50
+
51
+ def outer_join(relation)
52
+ join(relation, Nodes::OuterJoin)
53
+ end
54
+
55
+ def group(*columns)
56
+ from.group(*columns)
57
+ end
58
+
59
+ def order(*expr)
60
+ from.order(*expr)
61
+ end
62
+
63
+ def where(condition)
64
+ from.where condition
65
+ end
66
+
67
+ def project(*things)
68
+ from.project(*things)
69
+ end
70
+
71
+ def take(amount)
72
+ from.take amount
73
+ end
74
+
75
+ def skip(amount)
76
+ from.skip amount
77
+ end
78
+
79
+ def having(expr)
80
+ from.having expr
81
+ end
82
+
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)
87
+ end
88
+
89
+ def hash
90
+ # Perf note: aliases and table alias is excluded from the hash
91
+ # aliases can have a loop back to this table breaking hashes in parent
92
+ # relations, for the vast majority of cases @name is unique to a query
93
+ @name.hash
94
+ end
95
+
96
+ def eql?(other)
97
+ self.class == other.class &&
98
+ self.name == other.name &&
99
+ self.table_alias == other.table_alias
100
+ end
101
+ alias :== :eql?
102
+
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)
109
+ end
110
+
111
+ def able_to_type_cast?
112
+ !type_caster.nil?
113
+ end
114
+
115
+ private
116
+ attr_reader :type_caster
117
+ end
118
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arel # :nodoc: all
4
+ class TreeManager
5
+ include Arel::FactoryMethods
6
+
7
+ module StatementMethods
8
+ def take(limit)
9
+ @ast.limit = Nodes::Limit.new(Nodes.build_quoted(limit)) if limit
10
+ self
11
+ end
12
+
13
+ def offset(offset)
14
+ @ast.offset = Nodes::Offset.new(Nodes.build_quoted(offset)) if offset
15
+ self
16
+ end
17
+
18
+ def order(*expr)
19
+ @ast.orders = expr
20
+ self
21
+ end
22
+
23
+ def key=(key)
24
+ @ast.key = Nodes.build_quoted(key)
25
+ end
26
+
27
+ def key
28
+ @ast.key
29
+ end
30
+
31
+ def wheres=(exprs)
32
+ @ast.wheres = exprs
33
+ end
34
+
35
+ def where(expr)
36
+ @ast.wheres << expr
37
+ self
38
+ end
39
+ end
40
+
41
+ attr_reader :ast
42
+
43
+ def initialize
44
+ @ctx = nil
45
+ end
46
+
47
+ def to_dot
48
+ collector = Arel::Collectors::PlainString.new
49
+ collector = Visitors::Dot.new.accept @ast, collector
50
+ collector.value
51
+ end
52
+
53
+ def to_sql(engine = Table.engine)
54
+ collector = Arel::Collectors::SQLString.new
55
+ collector = engine.connection.visitor.accept @ast, collector
56
+ collector.value
57
+ end
58
+
59
+ def initialize_copy(other)
60
+ super
61
+ @ast = @ast.clone
62
+ end
63
+
64
+ def where(expr)
65
+ if Arel::TreeManager === expr
66
+ expr = expr.ast
67
+ end
68
+ @ctx.wheres << expr
69
+ self
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arel # :nodoc: all
4
+ class UpdateManager < Arel::TreeManager
5
+ include TreeManager::StatementMethods
6
+
7
+ def initialize
8
+ super
9
+ @ast = Nodes::UpdateStatement.new
10
+ @ctx = @ast
11
+ end
12
+
13
+ ###
14
+ # UPDATE +table+
15
+ def table(table)
16
+ @ast.relation = table
17
+ self
18
+ end
19
+
20
+ def set(values)
21
+ if String === values
22
+ @ast.values = [values]
23
+ else
24
+ @ast.values = values.map { |column, value|
25
+ Nodes::Assignment.new(
26
+ Nodes::UnqualifiedColumn.new(column),
27
+ value
28
+ )
29
+ }
30
+ end
31
+ self
32
+ end
33
+ end
34
+ end