activerecord 5.2.4.4 → 6.0.3.4

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 (292) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +777 -552
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +5 -3
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record.rb +10 -2
  7. data/lib/active_record/advisory_lock_base.rb +18 -0
  8. data/lib/active_record/aggregations.rb +4 -3
  9. data/lib/active_record/association_relation.rb +10 -8
  10. data/lib/active_record/associations.rb +21 -16
  11. data/lib/active_record/associations/alias_tracker.rb +0 -1
  12. data/lib/active_record/associations/association.rb +56 -19
  13. data/lib/active_record/associations/association_scope.rb +4 -6
  14. data/lib/active_record/associations/belongs_to_association.rb +36 -42
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
  16. data/lib/active_record/associations/builder/association.rb +14 -18
  17. data/lib/active_record/associations/builder/belongs_to.rb +19 -52
  18. data/lib/active_record/associations/builder/collection_association.rb +3 -13
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -40
  20. data/lib/active_record/associations/builder/has_many.rb +2 -0
  21. data/lib/active_record/associations/builder/has_one.rb +35 -1
  22. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  23. data/lib/active_record/associations/collection_association.rb +12 -23
  24. data/lib/active_record/associations/collection_proxy.rb +13 -17
  25. data/lib/active_record/associations/foreign_association.rb +7 -0
  26. data/lib/active_record/associations/has_many_association.rb +2 -11
  27. data/lib/active_record/associations/has_many_through_association.rb +14 -14
  28. data/lib/active_record/associations/has_one_association.rb +28 -30
  29. data/lib/active_record/associations/has_one_through_association.rb +5 -5
  30. data/lib/active_record/associations/join_dependency.rb +37 -28
  31. data/lib/active_record/associations/join_dependency/join_association.rb +9 -10
  32. data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
  33. data/lib/active_record/associations/preloader.rb +39 -32
  34. data/lib/active_record/associations/preloader/association.rb +38 -36
  35. data/lib/active_record/associations/preloader/through_association.rb +48 -39
  36. data/lib/active_record/associations/singular_association.rb +2 -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.rb +28 -100
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +4 -2
  41. data/lib/active_record/attribute_methods/dirty.rb +111 -40
  42. data/lib/active_record/attribute_methods/primary_key.rb +15 -24
  43. data/lib/active_record/attribute_methods/query.rb +2 -3
  44. data/lib/active_record/attribute_methods/read.rb +15 -54
  45. data/lib/active_record/attribute_methods/serialization.rb +1 -2
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -3
  47. data/lib/active_record/attribute_methods/write.rb +17 -25
  48. data/lib/active_record/attributes.rb +13 -1
  49. data/lib/active_record/autosave_association.rb +3 -5
  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 +0 -1
  53. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +103 -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 +68 -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 +100 -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 +191 -43
  64. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +142 -215
  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 +132 -16
  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/enum.rb +0 -1
  83. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
  84. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -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 +1 -2
  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 +135 -146
  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 +103 -61
  110. data/lib/active_record/counter_cache.rb +8 -30
  111. data/lib/active_record/database_configurations.rb +233 -0
  112. data/lib/active_record/database_configurations/database_config.rb +37 -0
  113. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  114. data/lib/active_record/database_configurations/url_config.rb +78 -0
  115. data/lib/active_record/dynamic_matchers.rb +3 -4
  116. data/lib/active_record/enum.rb +37 -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 +5 -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.rb +74 -0
  133. data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
  134. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  135. data/lib/active_record/migration.rb +104 -85
  136. data/lib/active_record/migration/command_recorder.rb +54 -22
  137. data/lib/active_record/migration/compatibility.rb +79 -52
  138. data/lib/active_record/migration/join_table.rb +0 -1
  139. data/lib/active_record/model_schema.rb +33 -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 -43
  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 +40 -38
  151. data/lib/active_record/relation.rb +322 -80
  152. data/lib/active_record/relation/batches.rb +13 -11
  153. data/lib/active_record/relation/calculations.rb +54 -48
  154. data/lib/active_record/relation/delegation.rb +33 -49
  155. data/lib/active_record/relation/finder_methods.rb +23 -28
  156. data/lib/active_record/relation/from_clause.rb +4 -0
  157. data/lib/active_record/relation/merger.rb +11 -21
  158. data/lib/active_record/relation/predicate_builder.rb +5 -11
  159. data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
  160. data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
  161. data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
  162. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  163. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
  164. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  165. data/lib/active_record/relation/query_attribute.rb +13 -8
  166. data/lib/active_record/relation/query_methods.rb +221 -70
  167. data/lib/active_record/relation/spawn_methods.rb +1 -2
  168. data/lib/active_record/relation/where_clause.rb +14 -11
  169. data/lib/active_record/relation/where_clause_factory.rb +1 -2
  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.rb +8 -9
  176. data/lib/active_record/scoping/default.rb +4 -6
  177. data/lib/active_record/scoping/named.rb +21 -17
  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 +225 -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.rb +3 -5
  193. data/lib/active_record/type/adapter_specific_registry.rb +3 -13
  194. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  195. data/lib/active_record/type/serialized.rb +0 -1
  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_caster/connection.rb +15 -14
  199. data/lib/active_record/type_caster/map.rb +1 -4
  200. data/lib/active_record/validations.rb +3 -3
  201. data/lib/active_record/validations/associated.rb +1 -2
  202. data/lib/active_record/validations/uniqueness.rb +15 -27
  203. data/lib/arel.rb +62 -0
  204. data/lib/arel/alias_predication.rb +9 -0
  205. data/lib/arel/attributes.rb +22 -0
  206. data/lib/arel/attributes/attribute.rb +37 -0
  207. data/lib/arel/collectors/bind.rb +24 -0
  208. data/lib/arel/collectors/composite.rb +31 -0
  209. data/lib/arel/collectors/plain_string.rb +20 -0
  210. data/lib/arel/collectors/sql_string.rb +20 -0
  211. data/lib/arel/collectors/substitute_binds.rb +28 -0
  212. data/lib/arel/crud.rb +42 -0
  213. data/lib/arel/delete_manager.rb +18 -0
  214. data/lib/arel/errors.rb +9 -0
  215. data/lib/arel/expressions.rb +29 -0
  216. data/lib/arel/factory_methods.rb +49 -0
  217. data/lib/arel/insert_manager.rb +49 -0
  218. data/lib/arel/math.rb +45 -0
  219. data/lib/arel/nodes.rb +68 -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/order_predications.rb +13 -0
  264. data/lib/arel/predications.rb +256 -0
  265. data/lib/arel/select_manager.rb +271 -0
  266. data/lib/arel/table.rb +110 -0
  267. data/lib/arel/tree_manager.rb +72 -0
  268. data/lib/arel/update_manager.rb +34 -0
  269. data/lib/arel/visitors.rb +20 -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/window_predications.rb +9 -0
  284. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  285. data/lib/rails/generators/active_record/migration.rb +14 -2
  286. data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
  287. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +1 -1
  288. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -2
  289. data/lib/rails/generators/active_record/model/model_generator.rb +1 -1
  290. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  291. metadata +115 -29
  292. data/lib/active_record/collection_cache_key.rb +0 -53
@@ -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,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "arel/visitors/visitor"
4
+ require "arel/visitors/depth_first"
5
+ require "arel/visitors/to_sql"
6
+ require "arel/visitors/sqlite"
7
+ require "arel/visitors/postgresql"
8
+ 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
+ require "arel/visitors/dot"
14
+ require "arel/visitors/ibm_db"
15
+ require "arel/visitors/informix"
16
+
17
+ module Arel # :nodoc: all
18
+ module Visitors
19
+ end
20
+ 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
@@ -0,0 +1,296 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arel # :nodoc: all
4
+ module Visitors
5
+ class Dot < Arel::Visitors::Visitor
6
+ class Node # :nodoc:
7
+ attr_accessor :name, :id, :fields
8
+
9
+ def initialize(name, id, fields = [])
10
+ @name = name
11
+ @id = id
12
+ @fields = fields
13
+ end
14
+ end
15
+
16
+ class Edge < Struct.new :name, :from, :to # :nodoc:
17
+ end
18
+
19
+ def initialize
20
+ super()
21
+ @nodes = []
22
+ @edges = []
23
+ @node_stack = []
24
+ @edge_stack = []
25
+ @seen = {}
26
+ end
27
+
28
+ def accept(object, collector)
29
+ visit object
30
+ collector << to_dot
31
+ end
32
+
33
+ private
34
+ def visit_Arel_Nodes_Ordering(o)
35
+ visit_edge o, "expr"
36
+ end
37
+
38
+ def visit_Arel_Nodes_TableAlias(o)
39
+ visit_edge o, "name"
40
+ visit_edge o, "relation"
41
+ end
42
+
43
+ def visit_Arel_Nodes_Count(o)
44
+ visit_edge o, "expressions"
45
+ visit_edge o, "distinct"
46
+ end
47
+
48
+ def visit_Arel_Nodes_ValuesList(o)
49
+ visit_edge o, "rows"
50
+ end
51
+
52
+ def visit_Arel_Nodes_StringJoin(o)
53
+ visit_edge o, "left"
54
+ end
55
+
56
+ def visit_Arel_Nodes_InnerJoin(o)
57
+ visit_edge o, "left"
58
+ visit_edge o, "right"
59
+ end
60
+ alias :visit_Arel_Nodes_FullOuterJoin :visit_Arel_Nodes_InnerJoin
61
+ alias :visit_Arel_Nodes_OuterJoin :visit_Arel_Nodes_InnerJoin
62
+ alias :visit_Arel_Nodes_RightOuterJoin :visit_Arel_Nodes_InnerJoin
63
+
64
+ def visit_Arel_Nodes_DeleteStatement(o)
65
+ visit_edge o, "relation"
66
+ visit_edge o, "wheres"
67
+ end
68
+
69
+ def unary(o)
70
+ visit_edge o, "expr"
71
+ end
72
+ alias :visit_Arel_Nodes_Group :unary
73
+ alias :visit_Arel_Nodes_Cube :unary
74
+ alias :visit_Arel_Nodes_RollUp :unary
75
+ alias :visit_Arel_Nodes_GroupingSet :unary
76
+ alias :visit_Arel_Nodes_GroupingElement :unary
77
+ alias :visit_Arel_Nodes_Grouping :unary
78
+ alias :visit_Arel_Nodes_Having :unary
79
+ alias :visit_Arel_Nodes_Limit :unary
80
+ alias :visit_Arel_Nodes_Not :unary
81
+ alias :visit_Arel_Nodes_Offset :unary
82
+ alias :visit_Arel_Nodes_On :unary
83
+ alias :visit_Arel_Nodes_UnqualifiedColumn :unary
84
+ alias :visit_Arel_Nodes_OptimizerHints :unary
85
+ alias :visit_Arel_Nodes_Preceding :unary
86
+ alias :visit_Arel_Nodes_Following :unary
87
+ alias :visit_Arel_Nodes_Rows :unary
88
+ alias :visit_Arel_Nodes_Range :unary
89
+
90
+ def window(o)
91
+ visit_edge o, "partitions"
92
+ visit_edge o, "orders"
93
+ visit_edge o, "framing"
94
+ end
95
+ alias :visit_Arel_Nodes_Window :window
96
+
97
+ def named_window(o)
98
+ visit_edge o, "partitions"
99
+ visit_edge o, "orders"
100
+ visit_edge o, "framing"
101
+ visit_edge o, "name"
102
+ end
103
+ alias :visit_Arel_Nodes_NamedWindow :named_window
104
+
105
+ def function(o)
106
+ visit_edge o, "expressions"
107
+ visit_edge o, "distinct"
108
+ visit_edge o, "alias"
109
+ end
110
+ alias :visit_Arel_Nodes_Exists :function
111
+ alias :visit_Arel_Nodes_Min :function
112
+ alias :visit_Arel_Nodes_Max :function
113
+ alias :visit_Arel_Nodes_Avg :function
114
+ alias :visit_Arel_Nodes_Sum :function
115
+
116
+ def extract(o)
117
+ visit_edge o, "expressions"
118
+ visit_edge o, "alias"
119
+ end
120
+ alias :visit_Arel_Nodes_Extract :extract
121
+
122
+ def visit_Arel_Nodes_NamedFunction(o)
123
+ visit_edge o, "name"
124
+ visit_edge o, "expressions"
125
+ visit_edge o, "distinct"
126
+ visit_edge o, "alias"
127
+ end
128
+
129
+ def visit_Arel_Nodes_InsertStatement(o)
130
+ visit_edge o, "relation"
131
+ visit_edge o, "columns"
132
+ visit_edge o, "values"
133
+ end
134
+
135
+ def visit_Arel_Nodes_SelectCore(o)
136
+ visit_edge o, "source"
137
+ visit_edge o, "projections"
138
+ visit_edge o, "wheres"
139
+ visit_edge o, "windows"
140
+ end
141
+
142
+ def visit_Arel_Nodes_SelectStatement(o)
143
+ visit_edge o, "cores"
144
+ visit_edge o, "limit"
145
+ visit_edge o, "orders"
146
+ visit_edge o, "offset"
147
+ end
148
+
149
+ def visit_Arel_Nodes_UpdateStatement(o)
150
+ visit_edge o, "relation"
151
+ visit_edge o, "wheres"
152
+ visit_edge o, "values"
153
+ end
154
+
155
+ def visit_Arel_Table(o)
156
+ visit_edge o, "name"
157
+ end
158
+
159
+ def visit_Arel_Nodes_Casted(o)
160
+ visit_edge o, "val"
161
+ visit_edge o, "attribute"
162
+ end
163
+
164
+ def visit_Arel_Attribute(o)
165
+ visit_edge o, "relation"
166
+ visit_edge o, "name"
167
+ end
168
+ alias :visit_Arel_Attributes_Integer :visit_Arel_Attribute
169
+ alias :visit_Arel_Attributes_Float :visit_Arel_Attribute
170
+ alias :visit_Arel_Attributes_String :visit_Arel_Attribute
171
+ alias :visit_Arel_Attributes_Time :visit_Arel_Attribute
172
+ alias :visit_Arel_Attributes_Boolean :visit_Arel_Attribute
173
+ alias :visit_Arel_Attributes_Attribute :visit_Arel_Attribute
174
+
175
+ def nary(o)
176
+ o.children.each_with_index do |x, i|
177
+ edge(i) { visit x }
178
+ end
179
+ end
180
+ alias :visit_Arel_Nodes_And :nary
181
+
182
+ def binary(o)
183
+ visit_edge o, "left"
184
+ visit_edge o, "right"
185
+ end
186
+ alias :visit_Arel_Nodes_As :binary
187
+ alias :visit_Arel_Nodes_Assignment :binary
188
+ alias :visit_Arel_Nodes_Between :binary
189
+ alias :visit_Arel_Nodes_Concat :binary
190
+ alias :visit_Arel_Nodes_DoesNotMatch :binary
191
+ alias :visit_Arel_Nodes_Equality :binary
192
+ alias :visit_Arel_Nodes_GreaterThan :binary
193
+ alias :visit_Arel_Nodes_GreaterThanOrEqual :binary
194
+ alias :visit_Arel_Nodes_In :binary
195
+ alias :visit_Arel_Nodes_JoinSource :binary
196
+ alias :visit_Arel_Nodes_LessThan :binary
197
+ alias :visit_Arel_Nodes_LessThanOrEqual :binary
198
+ alias :visit_Arel_Nodes_IsNotDistinctFrom :binary
199
+ alias :visit_Arel_Nodes_IsDistinctFrom :binary
200
+ alias :visit_Arel_Nodes_Matches :binary
201
+ alias :visit_Arel_Nodes_NotEqual :binary
202
+ alias :visit_Arel_Nodes_NotIn :binary
203
+ alias :visit_Arel_Nodes_Or :binary
204
+ alias :visit_Arel_Nodes_Over :binary
205
+
206
+ def visit_String(o)
207
+ @node_stack.last.fields << o
208
+ end
209
+ alias :visit_Time :visit_String
210
+ alias :visit_Date :visit_String
211
+ alias :visit_DateTime :visit_String
212
+ alias :visit_NilClass :visit_String
213
+ alias :visit_TrueClass :visit_String
214
+ alias :visit_FalseClass :visit_String
215
+ alias :visit_Integer :visit_String
216
+ alias :visit_BigDecimal :visit_String
217
+ alias :visit_Float :visit_String
218
+ alias :visit_Symbol :visit_String
219
+ alias :visit_Arel_Nodes_SqlLiteral :visit_String
220
+
221
+ def visit_Arel_Nodes_BindParam(o); end
222
+
223
+ def visit_Hash(o)
224
+ o.each_with_index do |pair, i|
225
+ edge("pair_#{i}") { visit pair }
226
+ end
227
+ end
228
+
229
+ def visit_Array(o)
230
+ o.each_with_index do |x, i|
231
+ edge(i) { visit x }
232
+ end
233
+ end
234
+ alias :visit_Set :visit_Array
235
+
236
+ def visit_Arel_Nodes_Comment(o)
237
+ visit_edge(o, "values")
238
+ end
239
+
240
+ def visit_edge(o, method)
241
+ edge(method) { visit o.send(method) }
242
+ end
243
+
244
+ def visit(o)
245
+ if node = @seen[o.object_id]
246
+ @edge_stack.last.to = node
247
+ return
248
+ end
249
+
250
+ node = Node.new(o.class.name, o.object_id)
251
+ @seen[node.id] = node
252
+ @nodes << node
253
+ with_node node do
254
+ super
255
+ end
256
+ end
257
+
258
+ def edge(name)
259
+ edge = Edge.new(name, @node_stack.last)
260
+ @edge_stack.push edge
261
+ @edges << edge
262
+ yield
263
+ @edge_stack.pop
264
+ end
265
+
266
+ def with_node(node)
267
+ if edge = @edge_stack.last
268
+ edge.to = node
269
+ end
270
+
271
+ @node_stack.push node
272
+ yield
273
+ @node_stack.pop
274
+ end
275
+
276
+ def quote(string)
277
+ string.to_s.gsub('"', '\"')
278
+ end
279
+
280
+ def to_dot
281
+ "digraph \"Arel\" {\nnode [width=0.375,height=0.25,shape=record];\n" +
282
+ @nodes.map { |node|
283
+ label = "<f0>#{node.name}"
284
+
285
+ node.fields.each_with_index do |field, i|
286
+ label += "|<f#{i + 1}>#{quote field}"
287
+ end
288
+
289
+ "#{node.id} [label=\"#{label}\"];"
290
+ }.join("\n") + "\n" + @edges.map { |edge|
291
+ "#{edge.from.id} -> #{edge.to.id} [label=\"#{edge.name}\"];"
292
+ }.join("\n") + "\n}"
293
+ end
294
+ end
295
+ end
296
+ end