activerecord 6.0.0

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 (340) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1013 -0
  3. data/MIT-LICENSE +22 -0
  4. data/README.rdoc +219 -0
  5. data/examples/performance.rb +185 -0
  6. data/examples/simple.rb +15 -0
  7. data/lib/active_record.rb +195 -0
  8. data/lib/active_record/aggregations.rb +285 -0
  9. data/lib/active_record/association_relation.rb +40 -0
  10. data/lib/active_record/associations.rb +1865 -0
  11. data/lib/active_record/associations/alias_tracker.rb +81 -0
  12. data/lib/active_record/associations/association.rb +332 -0
  13. data/lib/active_record/associations/association_scope.rb +166 -0
  14. data/lib/active_record/associations/belongs_to_association.rb +124 -0
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +36 -0
  16. data/lib/active_record/associations/builder/association.rb +136 -0
  17. data/lib/active_record/associations/builder/belongs_to.rb +130 -0
  18. data/lib/active_record/associations/builder/collection_association.rb +72 -0
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +114 -0
  20. data/lib/active_record/associations/builder/has_many.rb +19 -0
  21. data/lib/active_record/associations/builder/has_one.rb +64 -0
  22. data/lib/active_record/associations/builder/singular_association.rb +44 -0
  23. data/lib/active_record/associations/collection_association.rb +498 -0
  24. data/lib/active_record/associations/collection_proxy.rb +1128 -0
  25. data/lib/active_record/associations/foreign_association.rb +20 -0
  26. data/lib/active_record/associations/has_many_association.rb +136 -0
  27. data/lib/active_record/associations/has_many_through_association.rb +220 -0
  28. data/lib/active_record/associations/has_one_association.rb +118 -0
  29. data/lib/active_record/associations/has_one_through_association.rb +45 -0
  30. data/lib/active_record/associations/join_dependency.rb +258 -0
  31. data/lib/active_record/associations/join_dependency/join_association.rb +80 -0
  32. data/lib/active_record/associations/join_dependency/join_base.rb +23 -0
  33. data/lib/active_record/associations/join_dependency/join_part.rb +71 -0
  34. data/lib/active_record/associations/preloader.rb +201 -0
  35. data/lib/active_record/associations/preloader/association.rb +133 -0
  36. data/lib/active_record/associations/preloader/through_association.rb +116 -0
  37. data/lib/active_record/associations/singular_association.rb +59 -0
  38. data/lib/active_record/associations/through_association.rb +121 -0
  39. data/lib/active_record/attribute_assignment.rb +85 -0
  40. data/lib/active_record/attribute_decorators.rb +90 -0
  41. data/lib/active_record/attribute_methods.rb +420 -0
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +81 -0
  43. data/lib/active_record/attribute_methods/dirty.rb +221 -0
  44. data/lib/active_record/attribute_methods/primary_key.rb +136 -0
  45. data/lib/active_record/attribute_methods/query.rb +41 -0
  46. data/lib/active_record/attribute_methods/read.rb +47 -0
  47. data/lib/active_record/attribute_methods/serialization.rb +90 -0
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +91 -0
  49. data/lib/active_record/attribute_methods/write.rb +61 -0
  50. data/lib/active_record/attributes.rb +279 -0
  51. data/lib/active_record/autosave_association.rb +508 -0
  52. data/lib/active_record/base.rb +328 -0
  53. data/lib/active_record/callbacks.rb +339 -0
  54. data/lib/active_record/coders/json.rb +15 -0
  55. data/lib/active_record/coders/yaml_column.rb +50 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +1165 -0
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +85 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +512 -0
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +154 -0
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +251 -0
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +713 -0
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +93 -0
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1475 -0
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +323 -0
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +761 -0
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +821 -0
  69. data/lib/active_record/connection_adapters/column.rb +95 -0
  70. data/lib/active_record/connection_adapters/connection_specification.rb +297 -0
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +200 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +146 -0
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -0
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +182 -0
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +92 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +53 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +23 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +41 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +113 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +26 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +205 -0
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +222 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +776 -0
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +949 -0
  117. data/lib/active_record/connection_adapters/schema_cache.rb +141 -0
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
  119. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
  120. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  121. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  126. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +557 -0
  127. data/lib/active_record/connection_adapters/statement_pool.rb +61 -0
  128. data/lib/active_record/connection_handling.rb +267 -0
  129. data/lib/active_record/core.rb +599 -0
  130. data/lib/active_record/counter_cache.rb +193 -0
  131. data/lib/active_record/database_configurations.rb +233 -0
  132. data/lib/active_record/database_configurations/database_config.rb +37 -0
  133. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  134. data/lib/active_record/database_configurations/url_config.rb +79 -0
  135. data/lib/active_record/define_callbacks.rb +22 -0
  136. data/lib/active_record/dynamic_matchers.rb +122 -0
  137. data/lib/active_record/enum.rb +274 -0
  138. data/lib/active_record/errors.rb +388 -0
  139. data/lib/active_record/explain.rb +50 -0
  140. data/lib/active_record/explain_registry.rb +32 -0
  141. data/lib/active_record/explain_subscriber.rb +34 -0
  142. data/lib/active_record/fixture_set/file.rb +82 -0
  143. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  144. data/lib/active_record/fixture_set/render_context.rb +17 -0
  145. data/lib/active_record/fixture_set/table_row.rb +153 -0
  146. data/lib/active_record/fixture_set/table_rows.rb +47 -0
  147. data/lib/active_record/fixtures.rb +738 -0
  148. data/lib/active_record/gem_version.rb +17 -0
  149. data/lib/active_record/inheritance.rb +293 -0
  150. data/lib/active_record/insert_all.rb +179 -0
  151. data/lib/active_record/integration.rb +207 -0
  152. data/lib/active_record/internal_metadata.rb +53 -0
  153. data/lib/active_record/legacy_yaml_adapter.rb +48 -0
  154. data/lib/active_record/locale/en.yml +48 -0
  155. data/lib/active_record/locking/optimistic.rb +197 -0
  156. data/lib/active_record/locking/pessimistic.rb +89 -0
  157. data/lib/active_record/log_subscriber.rb +118 -0
  158. data/lib/active_record/middleware/database_selector.rb +75 -0
  159. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  160. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  161. data/lib/active_record/migration.rb +1397 -0
  162. data/lib/active_record/migration/command_recorder.rb +284 -0
  163. data/lib/active_record/migration/compatibility.rb +244 -0
  164. data/lib/active_record/migration/join_table.rb +17 -0
  165. data/lib/active_record/model_schema.rb +542 -0
  166. data/lib/active_record/nested_attributes.rb +600 -0
  167. data/lib/active_record/no_touching.rb +65 -0
  168. data/lib/active_record/null_relation.rb +68 -0
  169. data/lib/active_record/persistence.rb +967 -0
  170. data/lib/active_record/query_cache.rb +52 -0
  171. data/lib/active_record/querying.rb +82 -0
  172. data/lib/active_record/railtie.rb +263 -0
  173. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  174. data/lib/active_record/railties/console_sandbox.rb +7 -0
  175. data/lib/active_record/railties/controller_runtime.rb +51 -0
  176. data/lib/active_record/railties/databases.rake +527 -0
  177. data/lib/active_record/readonly_attributes.rb +24 -0
  178. data/lib/active_record/reflection.rb +1042 -0
  179. data/lib/active_record/relation.rb +859 -0
  180. data/lib/active_record/relation/batches.rb +290 -0
  181. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  182. data/lib/active_record/relation/calculations.rb +424 -0
  183. data/lib/active_record/relation/delegation.rb +130 -0
  184. data/lib/active_record/relation/finder_methods.rb +552 -0
  185. data/lib/active_record/relation/from_clause.rb +26 -0
  186. data/lib/active_record/relation/merger.rb +184 -0
  187. data/lib/active_record/relation/predicate_builder.rb +150 -0
  188. data/lib/active_record/relation/predicate_builder/array_handler.rb +49 -0
  189. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  190. data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
  191. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  192. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  193. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  194. data/lib/active_record/relation/predicate_builder/relation_handler.rb +19 -0
  195. data/lib/active_record/relation/query_attribute.rb +50 -0
  196. data/lib/active_record/relation/query_methods.rb +1359 -0
  197. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  198. data/lib/active_record/relation/spawn_methods.rb +77 -0
  199. data/lib/active_record/relation/where_clause.rb +190 -0
  200. data/lib/active_record/relation/where_clause_factory.rb +33 -0
  201. data/lib/active_record/result.rb +168 -0
  202. data/lib/active_record/runtime_registry.rb +24 -0
  203. data/lib/active_record/sanitization.rb +214 -0
  204. data/lib/active_record/schema.rb +61 -0
  205. data/lib/active_record/schema_dumper.rb +270 -0
  206. data/lib/active_record/schema_migration.rb +60 -0
  207. data/lib/active_record/scoping.rb +106 -0
  208. data/lib/active_record/scoping/default.rb +151 -0
  209. data/lib/active_record/scoping/named.rb +217 -0
  210. data/lib/active_record/secure_token.rb +40 -0
  211. data/lib/active_record/serialization.rb +22 -0
  212. data/lib/active_record/statement_cache.rb +148 -0
  213. data/lib/active_record/store.rb +290 -0
  214. data/lib/active_record/suppressor.rb +61 -0
  215. data/lib/active_record/table_metadata.rb +75 -0
  216. data/lib/active_record/tasks/database_tasks.rb +506 -0
  217. data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
  218. data/lib/active_record/tasks/postgresql_database_tasks.rb +141 -0
  219. data/lib/active_record/tasks/sqlite_database_tasks.rb +77 -0
  220. data/lib/active_record/test_databases.rb +23 -0
  221. data/lib/active_record/test_fixtures.rb +224 -0
  222. data/lib/active_record/timestamp.rb +167 -0
  223. data/lib/active_record/touch_later.rb +66 -0
  224. data/lib/active_record/transactions.rb +493 -0
  225. data/lib/active_record/translation.rb +24 -0
  226. data/lib/active_record/type.rb +78 -0
  227. data/lib/active_record/type/adapter_specific_registry.rb +129 -0
  228. data/lib/active_record/type/date.rb +9 -0
  229. data/lib/active_record/type/date_time.rb +9 -0
  230. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  231. data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
  232. data/lib/active_record/type/internal/timezone.rb +17 -0
  233. data/lib/active_record/type/json.rb +30 -0
  234. data/lib/active_record/type/serialized.rb +71 -0
  235. data/lib/active_record/type/text.rb +11 -0
  236. data/lib/active_record/type/time.rb +21 -0
  237. data/lib/active_record/type/type_map.rb +62 -0
  238. data/lib/active_record/type/unsigned_integer.rb +17 -0
  239. data/lib/active_record/type_caster.rb +9 -0
  240. data/lib/active_record/type_caster/connection.rb +34 -0
  241. data/lib/active_record/type_caster/map.rb +20 -0
  242. data/lib/active_record/validations.rb +94 -0
  243. data/lib/active_record/validations/absence.rb +25 -0
  244. data/lib/active_record/validations/associated.rb +60 -0
  245. data/lib/active_record/validations/length.rb +26 -0
  246. data/lib/active_record/validations/presence.rb +68 -0
  247. data/lib/active_record/validations/uniqueness.rb +226 -0
  248. data/lib/active_record/version.rb +10 -0
  249. data/lib/arel.rb +51 -0
  250. data/lib/arel/alias_predication.rb +9 -0
  251. data/lib/arel/attributes.rb +22 -0
  252. data/lib/arel/attributes/attribute.rb +37 -0
  253. data/lib/arel/collectors/bind.rb +24 -0
  254. data/lib/arel/collectors/composite.rb +31 -0
  255. data/lib/arel/collectors/plain_string.rb +20 -0
  256. data/lib/arel/collectors/sql_string.rb +20 -0
  257. data/lib/arel/collectors/substitute_binds.rb +28 -0
  258. data/lib/arel/crud.rb +42 -0
  259. data/lib/arel/delete_manager.rb +18 -0
  260. data/lib/arel/errors.rb +9 -0
  261. data/lib/arel/expressions.rb +29 -0
  262. data/lib/arel/factory_methods.rb +49 -0
  263. data/lib/arel/insert_manager.rb +49 -0
  264. data/lib/arel/math.rb +45 -0
  265. data/lib/arel/nodes.rb +68 -0
  266. data/lib/arel/nodes/and.rb +32 -0
  267. data/lib/arel/nodes/ascending.rb +23 -0
  268. data/lib/arel/nodes/binary.rb +52 -0
  269. data/lib/arel/nodes/bind_param.rb +36 -0
  270. data/lib/arel/nodes/case.rb +55 -0
  271. data/lib/arel/nodes/casted.rb +50 -0
  272. data/lib/arel/nodes/comment.rb +29 -0
  273. data/lib/arel/nodes/count.rb +12 -0
  274. data/lib/arel/nodes/delete_statement.rb +45 -0
  275. data/lib/arel/nodes/descending.rb +23 -0
  276. data/lib/arel/nodes/equality.rb +18 -0
  277. data/lib/arel/nodes/extract.rb +24 -0
  278. data/lib/arel/nodes/false.rb +16 -0
  279. data/lib/arel/nodes/full_outer_join.rb +8 -0
  280. data/lib/arel/nodes/function.rb +44 -0
  281. data/lib/arel/nodes/grouping.rb +8 -0
  282. data/lib/arel/nodes/in.rb +8 -0
  283. data/lib/arel/nodes/infix_operation.rb +80 -0
  284. data/lib/arel/nodes/inner_join.rb +8 -0
  285. data/lib/arel/nodes/insert_statement.rb +37 -0
  286. data/lib/arel/nodes/join_source.rb +20 -0
  287. data/lib/arel/nodes/matches.rb +18 -0
  288. data/lib/arel/nodes/named_function.rb +23 -0
  289. data/lib/arel/nodes/node.rb +50 -0
  290. data/lib/arel/nodes/node_expression.rb +13 -0
  291. data/lib/arel/nodes/outer_join.rb +8 -0
  292. data/lib/arel/nodes/over.rb +15 -0
  293. data/lib/arel/nodes/regexp.rb +16 -0
  294. data/lib/arel/nodes/right_outer_join.rb +8 -0
  295. data/lib/arel/nodes/select_core.rb +67 -0
  296. data/lib/arel/nodes/select_statement.rb +41 -0
  297. data/lib/arel/nodes/sql_literal.rb +16 -0
  298. data/lib/arel/nodes/string_join.rb +11 -0
  299. data/lib/arel/nodes/table_alias.rb +27 -0
  300. data/lib/arel/nodes/terminal.rb +16 -0
  301. data/lib/arel/nodes/true.rb +16 -0
  302. data/lib/arel/nodes/unary.rb +45 -0
  303. data/lib/arel/nodes/unary_operation.rb +20 -0
  304. data/lib/arel/nodes/unqualified_column.rb +22 -0
  305. data/lib/arel/nodes/update_statement.rb +41 -0
  306. data/lib/arel/nodes/values_list.rb +9 -0
  307. data/lib/arel/nodes/window.rb +126 -0
  308. data/lib/arel/nodes/with.rb +11 -0
  309. data/lib/arel/order_predications.rb +13 -0
  310. data/lib/arel/predications.rb +257 -0
  311. data/lib/arel/select_manager.rb +271 -0
  312. data/lib/arel/table.rb +110 -0
  313. data/lib/arel/tree_manager.rb +72 -0
  314. data/lib/arel/update_manager.rb +34 -0
  315. data/lib/arel/visitors.rb +20 -0
  316. data/lib/arel/visitors/depth_first.rb +204 -0
  317. data/lib/arel/visitors/dot.rb +297 -0
  318. data/lib/arel/visitors/ibm_db.rb +34 -0
  319. data/lib/arel/visitors/informix.rb +62 -0
  320. data/lib/arel/visitors/mssql.rb +157 -0
  321. data/lib/arel/visitors/mysql.rb +83 -0
  322. data/lib/arel/visitors/oracle.rb +159 -0
  323. data/lib/arel/visitors/oracle12.rb +66 -0
  324. data/lib/arel/visitors/postgresql.rb +110 -0
  325. data/lib/arel/visitors/sqlite.rb +39 -0
  326. data/lib/arel/visitors/to_sql.rb +889 -0
  327. data/lib/arel/visitors/visitor.rb +46 -0
  328. data/lib/arel/visitors/where_sql.rb +23 -0
  329. data/lib/arel/window_predications.rb +9 -0
  330. data/lib/rails/generators/active_record.rb +19 -0
  331. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  332. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  333. data/lib/rails/generators/active_record/migration.rb +48 -0
  334. data/lib/rails/generators/active_record/migration/migration_generator.rb +75 -0
  335. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  336. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +48 -0
  337. data/lib/rails/generators/active_record/model/model_generator.rb +49 -0
  338. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  339. data/lib/rails/generators/active_record/model/templates/module.rb.tt +7 -0
  340. metadata +415 -0
@@ -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,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,204 @@
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
+
13
+ def visit(o, _ = nil)
14
+ super
15
+ @block.call o
16
+ end
17
+
18
+ def unary(o)
19
+ visit o.expr
20
+ end
21
+ alias :visit_Arel_Nodes_Else :unary
22
+ alias :visit_Arel_Nodes_Group :unary
23
+ alias :visit_Arel_Nodes_Cube :unary
24
+ alias :visit_Arel_Nodes_RollUp :unary
25
+ alias :visit_Arel_Nodes_GroupingSet :unary
26
+ alias :visit_Arel_Nodes_GroupingElement :unary
27
+ alias :visit_Arel_Nodes_Grouping :unary
28
+ alias :visit_Arel_Nodes_Having :unary
29
+ alias :visit_Arel_Nodes_Lateral :unary
30
+ alias :visit_Arel_Nodes_Limit :unary
31
+ alias :visit_Arel_Nodes_Not :unary
32
+ alias :visit_Arel_Nodes_Offset :unary
33
+ alias :visit_Arel_Nodes_On :unary
34
+ alias :visit_Arel_Nodes_Ordering :unary
35
+ alias :visit_Arel_Nodes_Ascending :unary
36
+ alias :visit_Arel_Nodes_Descending :unary
37
+ alias :visit_Arel_Nodes_UnqualifiedColumn :unary
38
+ alias :visit_Arel_Nodes_OptimizerHints :unary
39
+ alias :visit_Arel_Nodes_ValuesList :unary
40
+
41
+ def function(o)
42
+ visit o.expressions
43
+ visit o.alias
44
+ visit o.distinct
45
+ end
46
+ alias :visit_Arel_Nodes_Avg :function
47
+ alias :visit_Arel_Nodes_Exists :function
48
+ alias :visit_Arel_Nodes_Max :function
49
+ alias :visit_Arel_Nodes_Min :function
50
+ alias :visit_Arel_Nodes_Sum :function
51
+
52
+ def visit_Arel_Nodes_NamedFunction(o)
53
+ visit o.name
54
+ visit o.expressions
55
+ visit o.distinct
56
+ visit o.alias
57
+ end
58
+
59
+ def visit_Arel_Nodes_Count(o)
60
+ visit o.expressions
61
+ visit o.alias
62
+ visit o.distinct
63
+ end
64
+
65
+ def visit_Arel_Nodes_Case(o)
66
+ visit o.case
67
+ visit o.conditions
68
+ visit o.default
69
+ end
70
+
71
+ def nary(o)
72
+ o.children.each { |child| visit child }
73
+ end
74
+ alias :visit_Arel_Nodes_And :nary
75
+
76
+ def binary(o)
77
+ visit o.left
78
+ visit o.right
79
+ end
80
+ alias :visit_Arel_Nodes_As :binary
81
+ alias :visit_Arel_Nodes_Assignment :binary
82
+ alias :visit_Arel_Nodes_Between :binary
83
+ alias :visit_Arel_Nodes_Concat :binary
84
+ alias :visit_Arel_Nodes_DeleteStatement :binary
85
+ alias :visit_Arel_Nodes_DoesNotMatch :binary
86
+ alias :visit_Arel_Nodes_Equality :binary
87
+ alias :visit_Arel_Nodes_FullOuterJoin :binary
88
+ alias :visit_Arel_Nodes_GreaterThan :binary
89
+ alias :visit_Arel_Nodes_GreaterThanOrEqual :binary
90
+ alias :visit_Arel_Nodes_In :binary
91
+ alias :visit_Arel_Nodes_InfixOperation :binary
92
+ alias :visit_Arel_Nodes_JoinSource :binary
93
+ alias :visit_Arel_Nodes_InnerJoin :binary
94
+ alias :visit_Arel_Nodes_LessThan :binary
95
+ alias :visit_Arel_Nodes_LessThanOrEqual :binary
96
+ alias :visit_Arel_Nodes_Matches :binary
97
+ alias :visit_Arel_Nodes_NotEqual :binary
98
+ alias :visit_Arel_Nodes_NotIn :binary
99
+ alias :visit_Arel_Nodes_NotRegexp :binary
100
+ alias :visit_Arel_Nodes_IsNotDistinctFrom :binary
101
+ alias :visit_Arel_Nodes_IsDistinctFrom :binary
102
+ alias :visit_Arel_Nodes_Or :binary
103
+ alias :visit_Arel_Nodes_OuterJoin :binary
104
+ alias :visit_Arel_Nodes_Regexp :binary
105
+ alias :visit_Arel_Nodes_RightOuterJoin :binary
106
+ alias :visit_Arel_Nodes_TableAlias :binary
107
+ alias :visit_Arel_Nodes_When :binary
108
+
109
+ def visit_Arel_Nodes_StringJoin(o)
110
+ visit o.left
111
+ end
112
+
113
+ def visit_Arel_Attribute(o)
114
+ visit o.relation
115
+ visit o.name
116
+ end
117
+ alias :visit_Arel_Attributes_Integer :visit_Arel_Attribute
118
+ alias :visit_Arel_Attributes_Float :visit_Arel_Attribute
119
+ alias :visit_Arel_Attributes_String :visit_Arel_Attribute
120
+ alias :visit_Arel_Attributes_Time :visit_Arel_Attribute
121
+ alias :visit_Arel_Attributes_Boolean :visit_Arel_Attribute
122
+ alias :visit_Arel_Attributes_Attribute :visit_Arel_Attribute
123
+ alias :visit_Arel_Attributes_Decimal :visit_Arel_Attribute
124
+
125
+ def visit_Arel_Table(o)
126
+ visit o.name
127
+ end
128
+
129
+ def terminal(o)
130
+ end
131
+ alias :visit_ActiveSupport_Multibyte_Chars :terminal
132
+ alias :visit_ActiveSupport_StringInquirer :terminal
133
+ alias :visit_Arel_Nodes_Lock :terminal
134
+ alias :visit_Arel_Nodes_Node :terminal
135
+ alias :visit_Arel_Nodes_SqlLiteral :terminal
136
+ alias :visit_Arel_Nodes_BindParam :terminal
137
+ alias :visit_Arel_Nodes_Window :terminal
138
+ alias :visit_Arel_Nodes_True :terminal
139
+ alias :visit_Arel_Nodes_False :terminal
140
+ alias :visit_BigDecimal :terminal
141
+ alias :visit_Class :terminal
142
+ alias :visit_Date :terminal
143
+ alias :visit_DateTime :terminal
144
+ alias :visit_FalseClass :terminal
145
+ alias :visit_Float :terminal
146
+ alias :visit_Integer :terminal
147
+ alias :visit_NilClass :terminal
148
+ alias :visit_String :terminal
149
+ alias :visit_Symbol :terminal
150
+ alias :visit_Time :terminal
151
+ alias :visit_TrueClass :terminal
152
+
153
+ def visit_Arel_Nodes_InsertStatement(o)
154
+ visit o.relation
155
+ visit o.columns
156
+ visit o.values
157
+ end
158
+
159
+ def visit_Arel_Nodes_SelectCore(o)
160
+ visit o.projections
161
+ visit o.source
162
+ visit o.wheres
163
+ visit o.groups
164
+ visit o.windows
165
+ visit o.havings
166
+ end
167
+
168
+ def visit_Arel_Nodes_SelectStatement(o)
169
+ visit o.cores
170
+ visit o.orders
171
+ visit o.limit
172
+ visit o.lock
173
+ visit o.offset
174
+ end
175
+
176
+ def visit_Arel_Nodes_UpdateStatement(o)
177
+ visit o.relation
178
+ visit o.values
179
+ visit o.wheres
180
+ visit o.orders
181
+ visit o.limit
182
+ end
183
+
184
+ def visit_Arel_Nodes_Comment(o)
185
+ visit o.values
186
+ end
187
+
188
+ def visit_Array(o)
189
+ o.each { |i| visit i }
190
+ end
191
+ alias :visit_Set :visit_Array
192
+
193
+ def visit_Hash(o)
194
+ o.each { |k, v| visit(k); visit(v) }
195
+ end
196
+
197
+ DISPATCH = dispatch_cache
198
+
199
+ def get_dispatch_cache
200
+ DISPATCH
201
+ end
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,297 @@
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
+
35
+ def visit_Arel_Nodes_Ordering(o)
36
+ visit_edge o, "expr"
37
+ end
38
+
39
+ def visit_Arel_Nodes_TableAlias(o)
40
+ visit_edge o, "name"
41
+ visit_edge o, "relation"
42
+ end
43
+
44
+ def visit_Arel_Nodes_Count(o)
45
+ visit_edge o, "expressions"
46
+ visit_edge o, "distinct"
47
+ end
48
+
49
+ def visit_Arel_Nodes_ValuesList(o)
50
+ visit_edge o, "rows"
51
+ end
52
+
53
+ def visit_Arel_Nodes_StringJoin(o)
54
+ visit_edge o, "left"
55
+ end
56
+
57
+ def visit_Arel_Nodes_InnerJoin(o)
58
+ visit_edge o, "left"
59
+ visit_edge o, "right"
60
+ end
61
+ alias :visit_Arel_Nodes_FullOuterJoin :visit_Arel_Nodes_InnerJoin
62
+ alias :visit_Arel_Nodes_OuterJoin :visit_Arel_Nodes_InnerJoin
63
+ alias :visit_Arel_Nodes_RightOuterJoin :visit_Arel_Nodes_InnerJoin
64
+
65
+ def visit_Arel_Nodes_DeleteStatement(o)
66
+ visit_edge o, "relation"
67
+ visit_edge o, "wheres"
68
+ end
69
+
70
+ def unary(o)
71
+ visit_edge o, "expr"
72
+ end
73
+ alias :visit_Arel_Nodes_Group :unary
74
+ alias :visit_Arel_Nodes_Cube :unary
75
+ alias :visit_Arel_Nodes_RollUp :unary
76
+ alias :visit_Arel_Nodes_GroupingSet :unary
77
+ alias :visit_Arel_Nodes_GroupingElement :unary
78
+ alias :visit_Arel_Nodes_Grouping :unary
79
+ alias :visit_Arel_Nodes_Having :unary
80
+ alias :visit_Arel_Nodes_Limit :unary
81
+ alias :visit_Arel_Nodes_Not :unary
82
+ alias :visit_Arel_Nodes_Offset :unary
83
+ alias :visit_Arel_Nodes_On :unary
84
+ alias :visit_Arel_Nodes_UnqualifiedColumn :unary
85
+ alias :visit_Arel_Nodes_OptimizerHints :unary
86
+ alias :visit_Arel_Nodes_Preceding :unary
87
+ alias :visit_Arel_Nodes_Following :unary
88
+ alias :visit_Arel_Nodes_Rows :unary
89
+ alias :visit_Arel_Nodes_Range :unary
90
+
91
+ def window(o)
92
+ visit_edge o, "partitions"
93
+ visit_edge o, "orders"
94
+ visit_edge o, "framing"
95
+ end
96
+ alias :visit_Arel_Nodes_Window :window
97
+
98
+ def named_window(o)
99
+ visit_edge o, "partitions"
100
+ visit_edge o, "orders"
101
+ visit_edge o, "framing"
102
+ visit_edge o, "name"
103
+ end
104
+ alias :visit_Arel_Nodes_NamedWindow :named_window
105
+
106
+ def function(o)
107
+ visit_edge o, "expressions"
108
+ visit_edge o, "distinct"
109
+ visit_edge o, "alias"
110
+ end
111
+ alias :visit_Arel_Nodes_Exists :function
112
+ alias :visit_Arel_Nodes_Min :function
113
+ alias :visit_Arel_Nodes_Max :function
114
+ alias :visit_Arel_Nodes_Avg :function
115
+ alias :visit_Arel_Nodes_Sum :function
116
+
117
+ def extract(o)
118
+ visit_edge o, "expressions"
119
+ visit_edge o, "alias"
120
+ end
121
+ alias :visit_Arel_Nodes_Extract :extract
122
+
123
+ def visit_Arel_Nodes_NamedFunction(o)
124
+ visit_edge o, "name"
125
+ visit_edge o, "expressions"
126
+ visit_edge o, "distinct"
127
+ visit_edge o, "alias"
128
+ end
129
+
130
+ def visit_Arel_Nodes_InsertStatement(o)
131
+ visit_edge o, "relation"
132
+ visit_edge o, "columns"
133
+ visit_edge o, "values"
134
+ end
135
+
136
+ def visit_Arel_Nodes_SelectCore(o)
137
+ visit_edge o, "source"
138
+ visit_edge o, "projections"
139
+ visit_edge o, "wheres"
140
+ visit_edge o, "windows"
141
+ end
142
+
143
+ def visit_Arel_Nodes_SelectStatement(o)
144
+ visit_edge o, "cores"
145
+ visit_edge o, "limit"
146
+ visit_edge o, "orders"
147
+ visit_edge o, "offset"
148
+ end
149
+
150
+ def visit_Arel_Nodes_UpdateStatement(o)
151
+ visit_edge o, "relation"
152
+ visit_edge o, "wheres"
153
+ visit_edge o, "values"
154
+ end
155
+
156
+ def visit_Arel_Table(o)
157
+ visit_edge o, "name"
158
+ end
159
+
160
+ def visit_Arel_Nodes_Casted(o)
161
+ visit_edge o, "val"
162
+ visit_edge o, "attribute"
163
+ end
164
+
165
+ def visit_Arel_Attribute(o)
166
+ visit_edge o, "relation"
167
+ visit_edge o, "name"
168
+ end
169
+ alias :visit_Arel_Attributes_Integer :visit_Arel_Attribute
170
+ alias :visit_Arel_Attributes_Float :visit_Arel_Attribute
171
+ alias :visit_Arel_Attributes_String :visit_Arel_Attribute
172
+ alias :visit_Arel_Attributes_Time :visit_Arel_Attribute
173
+ alias :visit_Arel_Attributes_Boolean :visit_Arel_Attribute
174
+ alias :visit_Arel_Attributes_Attribute :visit_Arel_Attribute
175
+
176
+ def nary(o)
177
+ o.children.each_with_index do |x, i|
178
+ edge(i) { visit x }
179
+ end
180
+ end
181
+ alias :visit_Arel_Nodes_And :nary
182
+
183
+ def binary(o)
184
+ visit_edge o, "left"
185
+ visit_edge o, "right"
186
+ end
187
+ alias :visit_Arel_Nodes_As :binary
188
+ alias :visit_Arel_Nodes_Assignment :binary
189
+ alias :visit_Arel_Nodes_Between :binary
190
+ alias :visit_Arel_Nodes_Concat :binary
191
+ alias :visit_Arel_Nodes_DoesNotMatch :binary
192
+ alias :visit_Arel_Nodes_Equality :binary
193
+ alias :visit_Arel_Nodes_GreaterThan :binary
194
+ alias :visit_Arel_Nodes_GreaterThanOrEqual :binary
195
+ alias :visit_Arel_Nodes_In :binary
196
+ alias :visit_Arel_Nodes_JoinSource :binary
197
+ alias :visit_Arel_Nodes_LessThan :binary
198
+ alias :visit_Arel_Nodes_LessThanOrEqual :binary
199
+ alias :visit_Arel_Nodes_IsNotDistinctFrom :binary
200
+ alias :visit_Arel_Nodes_IsDistinctFrom :binary
201
+ alias :visit_Arel_Nodes_Matches :binary
202
+ alias :visit_Arel_Nodes_NotEqual :binary
203
+ alias :visit_Arel_Nodes_NotIn :binary
204
+ alias :visit_Arel_Nodes_Or :binary
205
+ alias :visit_Arel_Nodes_Over :binary
206
+
207
+ def visit_String(o)
208
+ @node_stack.last.fields << o
209
+ end
210
+ alias :visit_Time :visit_String
211
+ alias :visit_Date :visit_String
212
+ alias :visit_DateTime :visit_String
213
+ alias :visit_NilClass :visit_String
214
+ alias :visit_TrueClass :visit_String
215
+ alias :visit_FalseClass :visit_String
216
+ alias :visit_Integer :visit_String
217
+ alias :visit_BigDecimal :visit_String
218
+ alias :visit_Float :visit_String
219
+ alias :visit_Symbol :visit_String
220
+ alias :visit_Arel_Nodes_SqlLiteral :visit_String
221
+
222
+ def visit_Arel_Nodes_BindParam(o); end
223
+
224
+ def visit_Hash(o)
225
+ o.each_with_index do |pair, i|
226
+ edge("pair_#{i}") { visit pair }
227
+ end
228
+ end
229
+
230
+ def visit_Array(o)
231
+ o.each_with_index do |x, i|
232
+ edge(i) { visit x }
233
+ end
234
+ end
235
+ alias :visit_Set :visit_Array
236
+
237
+ def visit_Arel_Nodes_Comment(o)
238
+ visit_edge(o, "values")
239
+ end
240
+
241
+ def visit_edge(o, method)
242
+ edge(method) { visit o.send(method) }
243
+ end
244
+
245
+ def visit(o)
246
+ if node = @seen[o.object_id]
247
+ @edge_stack.last.to = node
248
+ return
249
+ end
250
+
251
+ node = Node.new(o.class.name, o.object_id)
252
+ @seen[node.id] = node
253
+ @nodes << node
254
+ with_node node do
255
+ super
256
+ end
257
+ end
258
+
259
+ def edge(name)
260
+ edge = Edge.new(name, @node_stack.last)
261
+ @edge_stack.push edge
262
+ @edges << edge
263
+ yield
264
+ @edge_stack.pop
265
+ end
266
+
267
+ def with_node(node)
268
+ if edge = @edge_stack.last
269
+ edge.to = node
270
+ end
271
+
272
+ @node_stack.push node
273
+ yield
274
+ @node_stack.pop
275
+ end
276
+
277
+ def quote(string)
278
+ string.to_s.gsub('"', '\"')
279
+ end
280
+
281
+ def to_dot
282
+ "digraph \"Arel\" {\nnode [width=0.375,height=0.25,shape=record];\n" +
283
+ @nodes.map { |node|
284
+ label = "<f0>#{node.name}"
285
+
286
+ node.fields.each_with_index do |field, i|
287
+ label += "|<f#{i + 1}>#{quote field}"
288
+ end
289
+
290
+ "#{node.id} [label=\"#{label}\"];"
291
+ }.join("\n") + "\n" + @edges.map { |edge|
292
+ "#{edge.from.id} -> #{edge.to.id} [label=\"#{edge.name}\"];"
293
+ }.join("\n") + "\n}"
294
+ end
295
+ end
296
+ end
297
+ end