activerecord 5.2.8.1 → 6.0.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 (294) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +938 -573
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +5 -3
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record/advisory_lock_base.rb +18 -0
  7. data/lib/active_record/aggregations.rb +4 -3
  8. data/lib/active_record/association_relation.rb +10 -8
  9. data/lib/active_record/associations/alias_tracker.rb +0 -1
  10. data/lib/active_record/associations/association.rb +55 -19
  11. data/lib/active_record/associations/association_scope.rb +11 -7
  12. data/lib/active_record/associations/belongs_to_association.rb +36 -42
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
  14. data/lib/active_record/associations/builder/association.rb +14 -18
  15. data/lib/active_record/associations/builder/belongs_to.rb +19 -52
  16. data/lib/active_record/associations/builder/collection_association.rb +3 -13
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -40
  18. data/lib/active_record/associations/builder/has_many.rb +2 -0
  19. data/lib/active_record/associations/builder/has_one.rb +35 -1
  20. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  21. data/lib/active_record/associations/collection_association.rb +19 -23
  22. data/lib/active_record/associations/collection_proxy.rb +14 -17
  23. data/lib/active_record/associations/foreign_association.rb +7 -0
  24. data/lib/active_record/associations/has_many_association.rb +2 -11
  25. data/lib/active_record/associations/has_many_through_association.rb +14 -14
  26. data/lib/active_record/associations/has_one_association.rb +28 -30
  27. data/lib/active_record/associations/has_one_through_association.rb +5 -5
  28. data/lib/active_record/associations/join_dependency/join_association.rb +16 -10
  29. data/lib/active_record/associations/join_dependency/join_part.rb +4 -4
  30. data/lib/active_record/associations/join_dependency.rb +47 -30
  31. data/lib/active_record/associations/preloader/association.rb +61 -41
  32. data/lib/active_record/associations/preloader/through_association.rb +48 -39
  33. data/lib/active_record/associations/preloader.rb +44 -33
  34. data/lib/active_record/associations/singular_association.rb +2 -16
  35. data/lib/active_record/associations/through_association.rb +1 -1
  36. data/lib/active_record/associations.rb +21 -16
  37. data/lib/active_record/attribute_assignment.rb +7 -11
  38. data/lib/active_record/attribute_decorators.rb +0 -2
  39. data/lib/active_record/attribute_methods/before_type_cast.rb +4 -2
  40. data/lib/active_record/attribute_methods/dirty.rb +111 -40
  41. data/lib/active_record/attribute_methods/primary_key.rb +15 -24
  42. data/lib/active_record/attribute_methods/query.rb +2 -3
  43. data/lib/active_record/attribute_methods/read.rb +15 -54
  44. data/lib/active_record/attribute_methods/serialization.rb +1 -2
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -3
  46. data/lib/active_record/attribute_methods/write.rb +17 -25
  47. data/lib/active_record/attribute_methods.rb +28 -100
  48. data/lib/active_record/attributes.rb +13 -1
  49. data/lib/active_record/autosave_association.rb +12 -14
  50. data/lib/active_record/base.rb +2 -3
  51. data/lib/active_record/callbacks.rb +6 -21
  52. data/lib/active_record/coders/yaml_column.rb +15 -6
  53. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +109 -18
  54. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -4
  55. data/lib/active_record/connection_adapters/abstract/database_statements.rb +102 -124
  56. data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -9
  57. data/lib/active_record/connection_adapters/abstract/quoting.rb +77 -17
  58. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +20 -14
  59. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +105 -72
  60. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -3
  61. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +175 -79
  62. data/lib/active_record/connection_adapters/abstract/transaction.rb +96 -57
  63. data/lib/active_record/connection_adapters/abstract_adapter.rb +197 -43
  64. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +149 -217
  65. data/lib/active_record/connection_adapters/column.rb +17 -13
  66. data/lib/active_record/connection_adapters/connection_specification.rb +54 -45
  67. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +6 -10
  68. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  69. data/lib/active_record/connection_adapters/mysql/database_statements.rb +70 -14
  70. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +0 -1
  71. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
  72. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +4 -6
  73. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +40 -32
  74. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +14 -6
  75. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +139 -19
  76. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +6 -10
  77. data/lib/active_record/connection_adapters/mysql2_adapter.rb +26 -10
  78. data/lib/active_record/connection_adapters/postgresql/column.rb +17 -31
  79. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +26 -1
  80. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  81. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  82. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +8 -0
  83. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  84. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
  89. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
  91. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +5 -3
  92. data/lib/active_record/connection_adapters/postgresql/quoting.rb +44 -7
  93. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
  94. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -3
  95. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
  96. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  97. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +63 -75
  98. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +24 -27
  99. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  100. data/lib/active_record/connection_adapters/postgresql_adapter.rb +168 -75
  101. data/lib/active_record/connection_adapters/schema_cache.rb +37 -14
  102. data/lib/active_record/connection_adapters/sql_type_metadata.rb +11 -8
  103. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
  104. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
  105. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -12
  106. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +137 -147
  107. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  108. data/lib/active_record/connection_handling.rb +139 -26
  109. data/lib/active_record/core.rb +108 -67
  110. data/lib/active_record/counter_cache.rb +8 -30
  111. data/lib/active_record/database_configurations/database_config.rb +37 -0
  112. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  113. data/lib/active_record/database_configurations/url_config.rb +78 -0
  114. data/lib/active_record/database_configurations.rb +233 -0
  115. data/lib/active_record/dynamic_matchers.rb +3 -4
  116. data/lib/active_record/enum.rb +44 -7
  117. data/lib/active_record/errors.rb +15 -7
  118. data/lib/active_record/explain.rb +1 -2
  119. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  120. data/lib/active_record/fixture_set/render_context.rb +17 -0
  121. data/lib/active_record/fixture_set/table_row.rb +152 -0
  122. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  123. data/lib/active_record/fixtures.rb +144 -474
  124. data/lib/active_record/gem_version.rb +3 -3
  125. data/lib/active_record/inheritance.rb +13 -6
  126. data/lib/active_record/insert_all.rb +179 -0
  127. data/lib/active_record/integration.rb +68 -16
  128. data/lib/active_record/internal_metadata.rb +11 -3
  129. data/lib/active_record/locking/optimistic.rb +14 -7
  130. data/lib/active_record/locking/pessimistic.rb +3 -3
  131. data/lib/active_record/log_subscriber.rb +8 -27
  132. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  133. data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
  134. data/lib/active_record/middleware/database_selector.rb +74 -0
  135. data/lib/active_record/migration/command_recorder.rb +54 -22
  136. data/lib/active_record/migration/compatibility.rb +79 -52
  137. data/lib/active_record/migration/join_table.rb +0 -1
  138. data/lib/active_record/migration.rb +104 -85
  139. data/lib/active_record/model_schema.rb +62 -11
  140. data/lib/active_record/nested_attributes.rb +2 -4
  141. data/lib/active_record/no_touching.rb +9 -2
  142. data/lib/active_record/null_relation.rb +0 -1
  143. data/lib/active_record/persistence.rb +232 -29
  144. data/lib/active_record/query_cache.rb +11 -4
  145. data/lib/active_record/querying.rb +33 -21
  146. data/lib/active_record/railtie.rb +80 -61
  147. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  148. data/lib/active_record/railties/controller_runtime.rb +30 -35
  149. data/lib/active_record/railties/databases.rake +199 -46
  150. data/lib/active_record/reflection.rb +51 -51
  151. data/lib/active_record/relation/batches.rb +13 -11
  152. data/lib/active_record/relation/calculations.rb +55 -49
  153. data/lib/active_record/relation/delegation.rb +35 -50
  154. data/lib/active_record/relation/finder_methods.rb +23 -28
  155. data/lib/active_record/relation/from_clause.rb +4 -0
  156. data/lib/active_record/relation/merger.rb +12 -17
  157. data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
  158. data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
  159. data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
  160. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  161. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
  162. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  163. data/lib/active_record/relation/predicate_builder.rb +5 -11
  164. data/lib/active_record/relation/query_attribute.rb +13 -8
  165. data/lib/active_record/relation/query_methods.rb +234 -69
  166. data/lib/active_record/relation/spawn_methods.rb +1 -2
  167. data/lib/active_record/relation/where_clause.rb +14 -11
  168. data/lib/active_record/relation/where_clause_factory.rb +1 -2
  169. data/lib/active_record/relation.rb +326 -81
  170. data/lib/active_record/result.rb +30 -12
  171. data/lib/active_record/sanitization.rb +32 -40
  172. data/lib/active_record/schema.rb +2 -11
  173. data/lib/active_record/schema_dumper.rb +22 -7
  174. data/lib/active_record/schema_migration.rb +6 -2
  175. data/lib/active_record/scoping/default.rb +4 -6
  176. data/lib/active_record/scoping/named.rb +25 -16
  177. data/lib/active_record/scoping.rb +8 -9
  178. data/lib/active_record/statement_cache.rb +30 -3
  179. data/lib/active_record/store.rb +87 -8
  180. data/lib/active_record/suppressor.rb +2 -2
  181. data/lib/active_record/table_metadata.rb +23 -15
  182. data/lib/active_record/tasks/database_tasks.rb +194 -25
  183. data/lib/active_record/tasks/mysql_database_tasks.rb +5 -6
  184. data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -8
  185. data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -9
  186. data/lib/active_record/test_databases.rb +23 -0
  187. data/lib/active_record/test_fixtures.rb +243 -0
  188. data/lib/active_record/timestamp.rb +39 -26
  189. data/lib/active_record/touch_later.rb +5 -4
  190. data/lib/active_record/transactions.rb +64 -73
  191. data/lib/active_record/translation.rb +1 -1
  192. data/lib/active_record/type/adapter_specific_registry.rb +3 -13
  193. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  194. data/lib/active_record/type/serialized.rb +0 -1
  195. data/lib/active_record/type/time.rb +10 -0
  196. data/lib/active_record/type/type_map.rb +0 -1
  197. data/lib/active_record/type/unsigned_integer.rb +0 -1
  198. data/lib/active_record/type.rb +3 -5
  199. data/lib/active_record/type_caster/connection.rb +15 -14
  200. data/lib/active_record/type_caster/map.rb +1 -4
  201. data/lib/active_record/validations/associated.rb +0 -1
  202. data/lib/active_record/validations/uniqueness.rb +15 -27
  203. data/lib/active_record/validations.rb +3 -3
  204. data/lib/active_record.rb +10 -2
  205. data/lib/arel/alias_predication.rb +9 -0
  206. data/lib/arel/attributes/attribute.rb +37 -0
  207. data/lib/arel/attributes.rb +22 -0
  208. data/lib/arel/collectors/bind.rb +24 -0
  209. data/lib/arel/collectors/composite.rb +31 -0
  210. data/lib/arel/collectors/plain_string.rb +20 -0
  211. data/lib/arel/collectors/sql_string.rb +20 -0
  212. data/lib/arel/collectors/substitute_binds.rb +28 -0
  213. data/lib/arel/crud.rb +42 -0
  214. data/lib/arel/delete_manager.rb +18 -0
  215. data/lib/arel/errors.rb +9 -0
  216. data/lib/arel/expressions.rb +29 -0
  217. data/lib/arel/factory_methods.rb +49 -0
  218. data/lib/arel/insert_manager.rb +49 -0
  219. data/lib/arel/math.rb +45 -0
  220. data/lib/arel/nodes/and.rb +32 -0
  221. data/lib/arel/nodes/ascending.rb +23 -0
  222. data/lib/arel/nodes/binary.rb +52 -0
  223. data/lib/arel/nodes/bind_param.rb +36 -0
  224. data/lib/arel/nodes/case.rb +55 -0
  225. data/lib/arel/nodes/casted.rb +50 -0
  226. data/lib/arel/nodes/comment.rb +29 -0
  227. data/lib/arel/nodes/count.rb +12 -0
  228. data/lib/arel/nodes/delete_statement.rb +45 -0
  229. data/lib/arel/nodes/descending.rb +23 -0
  230. data/lib/arel/nodes/equality.rb +18 -0
  231. data/lib/arel/nodes/extract.rb +24 -0
  232. data/lib/arel/nodes/false.rb +16 -0
  233. data/lib/arel/nodes/full_outer_join.rb +8 -0
  234. data/lib/arel/nodes/function.rb +44 -0
  235. data/lib/arel/nodes/grouping.rb +8 -0
  236. data/lib/arel/nodes/in.rb +8 -0
  237. data/lib/arel/nodes/infix_operation.rb +80 -0
  238. data/lib/arel/nodes/inner_join.rb +8 -0
  239. data/lib/arel/nodes/insert_statement.rb +37 -0
  240. data/lib/arel/nodes/join_source.rb +20 -0
  241. data/lib/arel/nodes/matches.rb +18 -0
  242. data/lib/arel/nodes/named_function.rb +23 -0
  243. data/lib/arel/nodes/node.rb +50 -0
  244. data/lib/arel/nodes/node_expression.rb +13 -0
  245. data/lib/arel/nodes/outer_join.rb +8 -0
  246. data/lib/arel/nodes/over.rb +15 -0
  247. data/lib/arel/nodes/regexp.rb +16 -0
  248. data/lib/arel/nodes/right_outer_join.rb +8 -0
  249. data/lib/arel/nodes/select_core.rb +67 -0
  250. data/lib/arel/nodes/select_statement.rb +41 -0
  251. data/lib/arel/nodes/sql_literal.rb +16 -0
  252. data/lib/arel/nodes/string_join.rb +11 -0
  253. data/lib/arel/nodes/table_alias.rb +27 -0
  254. data/lib/arel/nodes/terminal.rb +16 -0
  255. data/lib/arel/nodes/true.rb +16 -0
  256. data/lib/arel/nodes/unary.rb +45 -0
  257. data/lib/arel/nodes/unary_operation.rb +20 -0
  258. data/lib/arel/nodes/unqualified_column.rb +22 -0
  259. data/lib/arel/nodes/update_statement.rb +41 -0
  260. data/lib/arel/nodes/values_list.rb +9 -0
  261. data/lib/arel/nodes/window.rb +126 -0
  262. data/lib/arel/nodes/with.rb +11 -0
  263. data/lib/arel/nodes.rb +68 -0
  264. data/lib/arel/order_predications.rb +13 -0
  265. data/lib/arel/predications.rb +256 -0
  266. data/lib/arel/select_manager.rb +271 -0
  267. data/lib/arel/table.rb +110 -0
  268. data/lib/arel/tree_manager.rb +72 -0
  269. data/lib/arel/update_manager.rb +34 -0
  270. data/lib/arel/visitors/depth_first.rb +203 -0
  271. data/lib/arel/visitors/dot.rb +296 -0
  272. data/lib/arel/visitors/ibm_db.rb +34 -0
  273. data/lib/arel/visitors/informix.rb +62 -0
  274. data/lib/arel/visitors/mssql.rb +156 -0
  275. data/lib/arel/visitors/mysql.rb +83 -0
  276. data/lib/arel/visitors/oracle.rb +158 -0
  277. data/lib/arel/visitors/oracle12.rb +65 -0
  278. data/lib/arel/visitors/postgresql.rb +109 -0
  279. data/lib/arel/visitors/sqlite.rb +38 -0
  280. data/lib/arel/visitors/to_sql.rb +888 -0
  281. data/lib/arel/visitors/visitor.rb +45 -0
  282. data/lib/arel/visitors/where_sql.rb +22 -0
  283. data/lib/arel/visitors.rb +20 -0
  284. data/lib/arel/window_predications.rb +9 -0
  285. data/lib/arel.rb +62 -0
  286. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  287. data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
  288. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +1 -1
  289. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -2
  290. data/lib/rails/generators/active_record/migration.rb +14 -2
  291. data/lib/rails/generators/active_record/model/model_generator.rb +1 -1
  292. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  293. metadata +113 -26
  294. data/lib/active_record/collection_cache_key.rb +0 -53
@@ -0,0 +1,271 @@
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
+ viz = Visitors::WhereSql.new(engine.connection.visitor, engine.connection)
190
+ Nodes::SqlLiteral.new viz.accept(@ctx, Collectors::SQLString.new).value
191
+ end
192
+
193
+ def union(operation, other = nil)
194
+ if other
195
+ node_class = Nodes.const_get("Union#{operation.to_s.capitalize}")
196
+ else
197
+ other = operation
198
+ node_class = Nodes::Union
199
+ end
200
+
201
+ node_class.new self.ast, other.ast
202
+ end
203
+
204
+ def intersect(other)
205
+ Nodes::Intersect.new ast, other.ast
206
+ end
207
+
208
+ def except(other)
209
+ Nodes::Except.new ast, other.ast
210
+ end
211
+ alias :minus :except
212
+
213
+ def lateral(table_name = nil)
214
+ base = table_name.nil? ? ast : as(table_name)
215
+ Nodes::Lateral.new(base)
216
+ end
217
+
218
+ def with(*subqueries)
219
+ if subqueries.first.is_a? Symbol
220
+ node_class = Nodes.const_get("With#{subqueries.shift.to_s.capitalize}")
221
+ else
222
+ node_class = Nodes::With
223
+ end
224
+ @ast.with = node_class.new(subqueries.flatten)
225
+
226
+ self
227
+ end
228
+
229
+ def take(limit)
230
+ if limit
231
+ @ast.limit = Nodes::Limit.new(limit)
232
+ else
233
+ @ast.limit = nil
234
+ end
235
+ self
236
+ end
237
+ alias limit= take
238
+
239
+ def join_sources
240
+ @ctx.source.right
241
+ end
242
+
243
+ def source
244
+ @ctx.source
245
+ end
246
+
247
+ def comment(*values)
248
+ @ctx.comment = Nodes::Comment.new(values)
249
+ self
250
+ end
251
+
252
+ private
253
+ def collapse(exprs)
254
+ exprs = exprs.compact
255
+ exprs.map! { |expr|
256
+ if String === expr
257
+ # FIXME: Don't do this automatically
258
+ Arel.sql(expr)
259
+ else
260
+ expr
261
+ end
262
+ }
263
+
264
+ if exprs.length == 1
265
+ exprs.first
266
+ else
267
+ create_and exprs
268
+ end
269
+ end
270
+ end
271
+ end
data/lib/arel/table.rb ADDED
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arel # :nodoc: all
4
+ class Table
5
+ include Arel::Crud
6
+ include Arel::FactoryMethods
7
+
8
+ @engine = nil
9
+ class << self; attr_accessor :engine; end
10
+
11
+ attr_accessor :name, :table_alias
12
+
13
+ # TableAlias and Table both have a #table_name which is the name of the underlying table
14
+ alias :table_name :name
15
+
16
+ def initialize(name, as: nil, type_caster: nil)
17
+ @name = name.to_s
18
+ @type_caster = type_caster
19
+
20
+ # Sometime AR sends an :as parameter to table, to let the table know
21
+ # that it is an Alias. We may want to override new, and return a
22
+ # TableAlias node?
23
+ if as.to_s == @name
24
+ as = nil
25
+ end
26
+ @table_alias = as
27
+ end
28
+
29
+ def alias(name = "#{self.name}_2")
30
+ Nodes::TableAlias.new(self, name)
31
+ end
32
+
33
+ def from
34
+ SelectManager.new(self)
35
+ end
36
+
37
+ def join(relation, klass = Nodes::InnerJoin)
38
+ return from unless relation
39
+
40
+ case relation
41
+ when String, Nodes::SqlLiteral
42
+ raise EmptyJoinError if relation.empty?
43
+ klass = Nodes::StringJoin
44
+ end
45
+
46
+ from.join(relation, klass)
47
+ end
48
+
49
+ def outer_join(relation)
50
+ join(relation, Nodes::OuterJoin)
51
+ end
52
+
53
+ def group(*columns)
54
+ from.group(*columns)
55
+ end
56
+
57
+ def order(*expr)
58
+ from.order(*expr)
59
+ end
60
+
61
+ def where(condition)
62
+ from.where condition
63
+ end
64
+
65
+ def project(*things)
66
+ from.project(*things)
67
+ end
68
+
69
+ def take(amount)
70
+ from.take amount
71
+ end
72
+
73
+ def skip(amount)
74
+ from.skip amount
75
+ end
76
+
77
+ def having(expr)
78
+ from.having expr
79
+ end
80
+
81
+ def [](name)
82
+ ::Arel::Attribute.new self, name
83
+ end
84
+
85
+ def hash
86
+ # Perf note: aliases and table alias is excluded from the hash
87
+ # aliases can have a loop back to this table breaking hashes in parent
88
+ # relations, for the vast majority of cases @name is unique to a query
89
+ @name.hash
90
+ end
91
+
92
+ def eql?(other)
93
+ self.class == other.class &&
94
+ self.name == other.name &&
95
+ self.table_alias == other.table_alias
96
+ end
97
+ alias :== :eql?
98
+
99
+ def type_cast_for_database(attribute_name, value)
100
+ type_caster.type_cast_for_database(attribute_name, value)
101
+ end
102
+
103
+ def able_to_type_cast?
104
+ !type_caster.nil?
105
+ end
106
+
107
+ private
108
+ attr_reader :type_caster
109
+ end
110
+ 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
@@ -0,0 +1,203 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arel # :nodoc: all
4
+ module Visitors
5
+ class DepthFirst < Arel::Visitors::Visitor
6
+ def initialize(block = nil)
7
+ @block = block || Proc.new
8
+ super()
9
+ end
10
+
11
+ private
12
+ def visit(o, _ = nil)
13
+ super
14
+ @block.call o
15
+ end
16
+
17
+ def unary(o)
18
+ visit o.expr
19
+ end
20
+ alias :visit_Arel_Nodes_Else :unary
21
+ alias :visit_Arel_Nodes_Group :unary
22
+ alias :visit_Arel_Nodes_Cube :unary
23
+ alias :visit_Arel_Nodes_RollUp :unary
24
+ alias :visit_Arel_Nodes_GroupingSet :unary
25
+ alias :visit_Arel_Nodes_GroupingElement :unary
26
+ alias :visit_Arel_Nodes_Grouping :unary
27
+ alias :visit_Arel_Nodes_Having :unary
28
+ alias :visit_Arel_Nodes_Lateral :unary
29
+ alias :visit_Arel_Nodes_Limit :unary
30
+ alias :visit_Arel_Nodes_Not :unary
31
+ alias :visit_Arel_Nodes_Offset :unary
32
+ alias :visit_Arel_Nodes_On :unary
33
+ alias :visit_Arel_Nodes_Ordering :unary
34
+ alias :visit_Arel_Nodes_Ascending :unary
35
+ alias :visit_Arel_Nodes_Descending :unary
36
+ alias :visit_Arel_Nodes_UnqualifiedColumn :unary
37
+ alias :visit_Arel_Nodes_OptimizerHints :unary
38
+ alias :visit_Arel_Nodes_ValuesList :unary
39
+
40
+ def function(o)
41
+ visit o.expressions
42
+ visit o.alias
43
+ visit o.distinct
44
+ end
45
+ alias :visit_Arel_Nodes_Avg :function
46
+ alias :visit_Arel_Nodes_Exists :function
47
+ alias :visit_Arel_Nodes_Max :function
48
+ alias :visit_Arel_Nodes_Min :function
49
+ alias :visit_Arel_Nodes_Sum :function
50
+
51
+ def visit_Arel_Nodes_NamedFunction(o)
52
+ visit o.name
53
+ visit o.expressions
54
+ visit o.distinct
55
+ visit o.alias
56
+ end
57
+
58
+ def visit_Arel_Nodes_Count(o)
59
+ visit o.expressions
60
+ visit o.alias
61
+ visit o.distinct
62
+ end
63
+
64
+ def visit_Arel_Nodes_Case(o)
65
+ visit o.case
66
+ visit o.conditions
67
+ visit o.default
68
+ end
69
+
70
+ def nary(o)
71
+ o.children.each { |child| visit child }
72
+ end
73
+ alias :visit_Arel_Nodes_And :nary
74
+
75
+ def binary(o)
76
+ visit o.left
77
+ visit o.right
78
+ end
79
+ alias :visit_Arel_Nodes_As :binary
80
+ alias :visit_Arel_Nodes_Assignment :binary
81
+ alias :visit_Arel_Nodes_Between :binary
82
+ alias :visit_Arel_Nodes_Concat :binary
83
+ alias :visit_Arel_Nodes_DeleteStatement :binary
84
+ alias :visit_Arel_Nodes_DoesNotMatch :binary
85
+ alias :visit_Arel_Nodes_Equality :binary
86
+ alias :visit_Arel_Nodes_FullOuterJoin :binary
87
+ alias :visit_Arel_Nodes_GreaterThan :binary
88
+ alias :visit_Arel_Nodes_GreaterThanOrEqual :binary
89
+ alias :visit_Arel_Nodes_In :binary
90
+ alias :visit_Arel_Nodes_InfixOperation :binary
91
+ alias :visit_Arel_Nodes_JoinSource :binary
92
+ alias :visit_Arel_Nodes_InnerJoin :binary
93
+ alias :visit_Arel_Nodes_LessThan :binary
94
+ alias :visit_Arel_Nodes_LessThanOrEqual :binary
95
+ alias :visit_Arel_Nodes_Matches :binary
96
+ alias :visit_Arel_Nodes_NotEqual :binary
97
+ alias :visit_Arel_Nodes_NotIn :binary
98
+ alias :visit_Arel_Nodes_NotRegexp :binary
99
+ alias :visit_Arel_Nodes_IsNotDistinctFrom :binary
100
+ alias :visit_Arel_Nodes_IsDistinctFrom :binary
101
+ alias :visit_Arel_Nodes_Or :binary
102
+ alias :visit_Arel_Nodes_OuterJoin :binary
103
+ alias :visit_Arel_Nodes_Regexp :binary
104
+ alias :visit_Arel_Nodes_RightOuterJoin :binary
105
+ alias :visit_Arel_Nodes_TableAlias :binary
106
+ alias :visit_Arel_Nodes_When :binary
107
+
108
+ def visit_Arel_Nodes_StringJoin(o)
109
+ visit o.left
110
+ end
111
+
112
+ def visit_Arel_Attribute(o)
113
+ visit o.relation
114
+ visit o.name
115
+ end
116
+ alias :visit_Arel_Attributes_Integer :visit_Arel_Attribute
117
+ alias :visit_Arel_Attributes_Float :visit_Arel_Attribute
118
+ alias :visit_Arel_Attributes_String :visit_Arel_Attribute
119
+ alias :visit_Arel_Attributes_Time :visit_Arel_Attribute
120
+ alias :visit_Arel_Attributes_Boolean :visit_Arel_Attribute
121
+ alias :visit_Arel_Attributes_Attribute :visit_Arel_Attribute
122
+ alias :visit_Arel_Attributes_Decimal :visit_Arel_Attribute
123
+
124
+ def visit_Arel_Table(o)
125
+ visit o.name
126
+ end
127
+
128
+ def terminal(o)
129
+ end
130
+ alias :visit_ActiveSupport_Multibyte_Chars :terminal
131
+ alias :visit_ActiveSupport_StringInquirer :terminal
132
+ alias :visit_Arel_Nodes_Lock :terminal
133
+ alias :visit_Arel_Nodes_Node :terminal
134
+ alias :visit_Arel_Nodes_SqlLiteral :terminal
135
+ alias :visit_Arel_Nodes_BindParam :terminal
136
+ alias :visit_Arel_Nodes_Window :terminal
137
+ alias :visit_Arel_Nodes_True :terminal
138
+ alias :visit_Arel_Nodes_False :terminal
139
+ alias :visit_BigDecimal :terminal
140
+ alias :visit_Class :terminal
141
+ alias :visit_Date :terminal
142
+ alias :visit_DateTime :terminal
143
+ alias :visit_FalseClass :terminal
144
+ alias :visit_Float :terminal
145
+ alias :visit_Integer :terminal
146
+ alias :visit_NilClass :terminal
147
+ alias :visit_String :terminal
148
+ alias :visit_Symbol :terminal
149
+ alias :visit_Time :terminal
150
+ alias :visit_TrueClass :terminal
151
+
152
+ def visit_Arel_Nodes_InsertStatement(o)
153
+ visit o.relation
154
+ visit o.columns
155
+ visit o.values
156
+ end
157
+
158
+ def visit_Arel_Nodes_SelectCore(o)
159
+ visit o.projections
160
+ visit o.source
161
+ visit o.wheres
162
+ visit o.groups
163
+ visit o.windows
164
+ visit o.havings
165
+ end
166
+
167
+ def visit_Arel_Nodes_SelectStatement(o)
168
+ visit o.cores
169
+ visit o.orders
170
+ visit o.limit
171
+ visit o.lock
172
+ visit o.offset
173
+ end
174
+
175
+ def visit_Arel_Nodes_UpdateStatement(o)
176
+ visit o.relation
177
+ visit o.values
178
+ visit o.wheres
179
+ visit o.orders
180
+ visit o.limit
181
+ end
182
+
183
+ def visit_Arel_Nodes_Comment(o)
184
+ visit o.values
185
+ end
186
+
187
+ def visit_Array(o)
188
+ o.each { |i| visit i }
189
+ end
190
+ alias :visit_Set :visit_Array
191
+
192
+ def visit_Hash(o)
193
+ o.each { |k, v| visit(k); visit(v) }
194
+ end
195
+
196
+ DISPATCH = dispatch_cache
197
+
198
+ def get_dispatch_cache
199
+ DISPATCH
200
+ end
201
+ end
202
+ end
203
+ end