activerecord 5.0.7.2 → 6.1.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 (363) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +829 -2015
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +11 -9
  5. data/examples/performance.rb +31 -29
  6. data/examples/simple.rb +5 -3
  7. data/lib/active_record.rb +37 -29
  8. data/lib/active_record/aggregations.rb +249 -247
  9. data/lib/active_record/association_relation.rb +30 -18
  10. data/lib/active_record/associations.rb +1714 -1596
  11. data/lib/active_record/associations/alias_tracker.rb +36 -42
  12. data/lib/active_record/associations/association.rb +143 -68
  13. data/lib/active_record/associations/association_scope.rb +98 -94
  14. data/lib/active_record/associations/belongs_to_association.rb +76 -46
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
  16. data/lib/active_record/associations/builder/association.rb +27 -28
  17. data/lib/active_record/associations/builder/belongs_to.rb +52 -60
  18. data/lib/active_record/associations/builder/collection_association.rb +12 -22
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +40 -62
  20. data/lib/active_record/associations/builder/has_many.rb +10 -2
  21. data/lib/active_record/associations/builder/has_one.rb +35 -2
  22. data/lib/active_record/associations/builder/singular_association.rb +5 -1
  23. data/lib/active_record/associations/collection_association.rb +104 -259
  24. data/lib/active_record/associations/collection_proxy.rb +169 -125
  25. data/lib/active_record/associations/foreign_association.rb +22 -0
  26. data/lib/active_record/associations/has_many_association.rb +46 -31
  27. data/lib/active_record/associations/has_many_through_association.rb +66 -46
  28. data/lib/active_record/associations/has_one_association.rb +71 -52
  29. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  30. data/lib/active_record/associations/join_dependency.rb +169 -180
  31. data/lib/active_record/associations/join_dependency/join_association.rb +53 -79
  32. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  33. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  34. data/lib/active_record/associations/preloader.rb +97 -104
  35. data/lib/active_record/associations/preloader/association.rb +109 -97
  36. data/lib/active_record/associations/preloader/through_association.rb +77 -76
  37. data/lib/active_record/associations/singular_association.rb +12 -45
  38. data/lib/active_record/associations/through_association.rb +27 -15
  39. data/lib/active_record/attribute_assignment.rb +55 -60
  40. data/lib/active_record/attribute_methods.rb +111 -141
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +17 -9
  42. data/lib/active_record/attribute_methods/dirty.rb +172 -112
  43. data/lib/active_record/attribute_methods/primary_key.rb +88 -91
  44. data/lib/active_record/attribute_methods/query.rb +6 -8
  45. data/lib/active_record/attribute_methods/read.rb +18 -50
  46. data/lib/active_record/attribute_methods/serialization.rb +38 -10
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +38 -66
  48. data/lib/active_record/attribute_methods/write.rb +25 -32
  49. data/lib/active_record/attributes.rb +69 -31
  50. data/lib/active_record/autosave_association.rb +102 -66
  51. data/lib/active_record/base.rb +16 -25
  52. data/lib/active_record/callbacks.rb +202 -43
  53. data/lib/active_record/coders/json.rb +2 -0
  54. data/lib/active_record/coders/yaml_column.rb +11 -12
  55. data/lib/active_record/connection_adapters.rb +50 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +661 -375
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +14 -38
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +269 -105
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +54 -35
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +137 -93
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +155 -113
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +328 -162
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +591 -259
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +229 -91
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +392 -244
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +457 -582
  69. data/lib/active_record/connection_adapters/column.rb +55 -13
  70. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  71. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +135 -49
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -23
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +79 -49
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +66 -56
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +20 -12
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +74 -37
  82. data/lib/active_record/connection_adapters/pool_config.rb +63 -0
  83. data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
  84. data/lib/active_record/connection_adapters/postgresql/column.rb +39 -28
  85. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +70 -101
  86. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
  87. data/lib/active_record/connection_adapters/postgresql/oid.rb +26 -21
  88. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -11
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
  90. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -6
  93. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +14 -4
  95. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  96. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
  97. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -18
  98. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  101. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
  104. data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +30 -9
  106. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -30
  107. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  108. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  109. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
  110. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  111. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  112. data/lib/active_record/connection_adapters/postgresql/quoting.rb +98 -38
  113. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +21 -27
  114. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
  115. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
  116. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +34 -32
  117. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +426 -324
  118. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +32 -23
  119. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -6
  120. data/lib/active_record/connection_adapters/postgresql_adapter.rb +418 -293
  121. data/lib/active_record/connection_adapters/schema_cache.rb +135 -18
  122. data/lib/active_record/connection_adapters/sql_type_metadata.rb +22 -7
  123. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
  124. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
  125. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +72 -18
  126. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -6
  127. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  128. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  129. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
  130. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +282 -290
  131. data/lib/active_record/connection_adapters/statement_pool.rb +9 -8
  132. data/lib/active_record/connection_handling.rb +287 -45
  133. data/lib/active_record/core.rb +385 -181
  134. data/lib/active_record/counter_cache.rb +60 -28
  135. data/lib/active_record/database_configurations.rb +272 -0
  136. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  137. data/lib/active_record/database_configurations/database_config.rb +80 -0
  138. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  139. data/lib/active_record/database_configurations/url_config.rb +53 -0
  140. data/lib/active_record/delegated_type.rb +209 -0
  141. data/lib/active_record/destroy_association_async_job.rb +36 -0
  142. data/lib/active_record/dynamic_matchers.rb +87 -87
  143. data/lib/active_record/enum.rb +122 -47
  144. data/lib/active_record/errors.rb +153 -22
  145. data/lib/active_record/explain.rb +13 -8
  146. data/lib/active_record/explain_registry.rb +3 -1
  147. data/lib/active_record/explain_subscriber.rb +9 -4
  148. data/lib/active_record/fixture_set/file.rb +20 -22
  149. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  150. data/lib/active_record/fixture_set/render_context.rb +17 -0
  151. data/lib/active_record/fixture_set/table_row.rb +152 -0
  152. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  153. data/lib/active_record/fixtures.rb +246 -507
  154. data/lib/active_record/gem_version.rb +6 -4
  155. data/lib/active_record/inheritance.rb +168 -95
  156. data/lib/active_record/insert_all.rb +208 -0
  157. data/lib/active_record/integration.rb +114 -25
  158. data/lib/active_record/internal_metadata.rb +30 -24
  159. data/lib/active_record/legacy_yaml_adapter.rb +11 -5
  160. data/lib/active_record/locking/optimistic.rb +81 -85
  161. data/lib/active_record/locking/pessimistic.rb +22 -6
  162. data/lib/active_record/log_subscriber.rb +68 -31
  163. data/lib/active_record/middleware/database_selector.rb +77 -0
  164. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  165. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  166. data/lib/active_record/migration.rb +439 -342
  167. data/lib/active_record/migration/command_recorder.rb +152 -98
  168. data/lib/active_record/migration/compatibility.rb +229 -60
  169. data/lib/active_record/migration/join_table.rb +8 -7
  170. data/lib/active_record/model_schema.rb +230 -122
  171. data/lib/active_record/nested_attributes.rb +213 -203
  172. data/lib/active_record/no_touching.rb +11 -2
  173. data/lib/active_record/null_relation.rb +12 -34
  174. data/lib/active_record/persistence.rb +471 -97
  175. data/lib/active_record/query_cache.rb +23 -12
  176. data/lib/active_record/querying.rb +43 -25
  177. data/lib/active_record/railtie.rb +155 -43
  178. data/lib/active_record/railties/console_sandbox.rb +2 -0
  179. data/lib/active_record/railties/controller_runtime.rb +34 -33
  180. data/lib/active_record/railties/databases.rake +507 -195
  181. data/lib/active_record/readonly_attributes.rb +9 -4
  182. data/lib/active_record/reflection.rb +245 -269
  183. data/lib/active_record/relation.rb +475 -324
  184. data/lib/active_record/relation/batches.rb +125 -72
  185. data/lib/active_record/relation/batches/batch_enumerator.rb +28 -10
  186. data/lib/active_record/relation/calculations.rb +267 -171
  187. data/lib/active_record/relation/delegation.rb +73 -69
  188. data/lib/active_record/relation/finder_methods.rb +238 -248
  189. data/lib/active_record/relation/from_clause.rb +7 -9
  190. data/lib/active_record/relation/merger.rb +95 -77
  191. data/lib/active_record/relation/predicate_builder.rb +109 -110
  192. data/lib/active_record/relation/predicate_builder/array_handler.rb +22 -17
  193. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
  194. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
  195. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +55 -0
  196. data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
  197. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  198. data/lib/active_record/relation/query_attribute.rb +33 -2
  199. data/lib/active_record/relation/query_methods.rb +654 -374
  200. data/lib/active_record/relation/record_fetch_warning.rb +8 -6
  201. data/lib/active_record/relation/spawn_methods.rb +15 -14
  202. data/lib/active_record/relation/where_clause.rb +171 -109
  203. data/lib/active_record/result.rb +88 -51
  204. data/lib/active_record/runtime_registry.rb +5 -3
  205. data/lib/active_record/sanitization.rb +73 -100
  206. data/lib/active_record/schema.rb +7 -14
  207. data/lib/active_record/schema_dumper.rb +101 -69
  208. data/lib/active_record/schema_migration.rb +16 -12
  209. data/lib/active_record/scoping.rb +20 -20
  210. data/lib/active_record/scoping/default.rb +92 -95
  211. data/lib/active_record/scoping/named.rb +39 -30
  212. data/lib/active_record/secure_token.rb +19 -9
  213. data/lib/active_record/serialization.rb +7 -3
  214. data/lib/active_record/signed_id.rb +116 -0
  215. data/lib/active_record/statement_cache.rb +80 -29
  216. data/lib/active_record/store.rb +122 -42
  217. data/lib/active_record/suppressor.rb +6 -3
  218. data/lib/active_record/table_metadata.rb +51 -39
  219. data/lib/active_record/tasks/database_tasks.rb +332 -115
  220. data/lib/active_record/tasks/mysql_database_tasks.rb +66 -104
  221. data/lib/active_record/tasks/postgresql_database_tasks.rb +84 -56
  222. data/lib/active_record/tasks/sqlite_database_tasks.rb +40 -19
  223. data/lib/active_record/test_databases.rb +24 -0
  224. data/lib/active_record/test_fixtures.rb +246 -0
  225. data/lib/active_record/timestamp.rb +70 -38
  226. data/lib/active_record/touch_later.rb +26 -24
  227. data/lib/active_record/transactions.rb +121 -184
  228. data/lib/active_record/translation.rb +3 -1
  229. data/lib/active_record/type.rb +29 -17
  230. data/lib/active_record/type/adapter_specific_registry.rb +44 -48
  231. data/lib/active_record/type/date.rb +2 -0
  232. data/lib/active_record/type/date_time.rb +2 -0
  233. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  234. data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
  235. data/lib/active_record/type/internal/timezone.rb +2 -0
  236. data/lib/active_record/type/json.rb +30 -0
  237. data/lib/active_record/type/serialized.rb +20 -9
  238. data/lib/active_record/type/text.rb +11 -0
  239. data/lib/active_record/type/time.rb +12 -1
  240. data/lib/active_record/type/type_map.rb +14 -17
  241. data/lib/active_record/type/unsigned_integer.rb +16 -0
  242. data/lib/active_record/type_caster.rb +4 -2
  243. data/lib/active_record/type_caster/connection.rb +17 -13
  244. data/lib/active_record/type_caster/map.rb +10 -6
  245. data/lib/active_record/validations.rb +8 -5
  246. data/lib/active_record/validations/absence.rb +2 -0
  247. data/lib/active_record/validations/associated.rb +4 -3
  248. data/lib/active_record/validations/length.rb +2 -0
  249. data/lib/active_record/validations/numericality.rb +35 -0
  250. data/lib/active_record/validations/presence.rb +4 -2
  251. data/lib/active_record/validations/uniqueness.rb +52 -45
  252. data/lib/active_record/version.rb +3 -1
  253. data/lib/arel.rb +54 -0
  254. data/lib/arel/alias_predication.rb +9 -0
  255. data/lib/arel/attributes/attribute.rb +41 -0
  256. data/lib/arel/collectors/bind.rb +29 -0
  257. data/lib/arel/collectors/composite.rb +39 -0
  258. data/lib/arel/collectors/plain_string.rb +20 -0
  259. data/lib/arel/collectors/sql_string.rb +27 -0
  260. data/lib/arel/collectors/substitute_binds.rb +35 -0
  261. data/lib/arel/crud.rb +42 -0
  262. data/lib/arel/delete_manager.rb +18 -0
  263. data/lib/arel/errors.rb +9 -0
  264. data/lib/arel/expressions.rb +29 -0
  265. data/lib/arel/factory_methods.rb +49 -0
  266. data/lib/arel/insert_manager.rb +49 -0
  267. data/lib/arel/math.rb +45 -0
  268. data/lib/arel/nodes.rb +70 -0
  269. data/lib/arel/nodes/and.rb +32 -0
  270. data/lib/arel/nodes/ascending.rb +23 -0
  271. data/lib/arel/nodes/binary.rb +126 -0
  272. data/lib/arel/nodes/bind_param.rb +44 -0
  273. data/lib/arel/nodes/case.rb +55 -0
  274. data/lib/arel/nodes/casted.rb +62 -0
  275. data/lib/arel/nodes/comment.rb +29 -0
  276. data/lib/arel/nodes/count.rb +12 -0
  277. data/lib/arel/nodes/delete_statement.rb +45 -0
  278. data/lib/arel/nodes/descending.rb +23 -0
  279. data/lib/arel/nodes/equality.rb +15 -0
  280. data/lib/arel/nodes/extract.rb +24 -0
  281. data/lib/arel/nodes/false.rb +16 -0
  282. data/lib/arel/nodes/full_outer_join.rb +8 -0
  283. data/lib/arel/nodes/function.rb +44 -0
  284. data/lib/arel/nodes/grouping.rb +11 -0
  285. data/lib/arel/nodes/homogeneous_in.rb +72 -0
  286. data/lib/arel/nodes/in.rb +15 -0
  287. data/lib/arel/nodes/infix_operation.rb +92 -0
  288. data/lib/arel/nodes/inner_join.rb +8 -0
  289. data/lib/arel/nodes/insert_statement.rb +37 -0
  290. data/lib/arel/nodes/join_source.rb +20 -0
  291. data/lib/arel/nodes/matches.rb +18 -0
  292. data/lib/arel/nodes/named_function.rb +23 -0
  293. data/lib/arel/nodes/node.rb +51 -0
  294. data/lib/arel/nodes/node_expression.rb +13 -0
  295. data/lib/arel/nodes/ordering.rb +27 -0
  296. data/lib/arel/nodes/outer_join.rb +8 -0
  297. data/lib/arel/nodes/over.rb +15 -0
  298. data/lib/arel/nodes/regexp.rb +16 -0
  299. data/lib/arel/nodes/right_outer_join.rb +8 -0
  300. data/lib/arel/nodes/select_core.rb +67 -0
  301. data/lib/arel/nodes/select_statement.rb +41 -0
  302. data/lib/arel/nodes/sql_literal.rb +19 -0
  303. data/lib/arel/nodes/string_join.rb +11 -0
  304. data/lib/arel/nodes/table_alias.rb +31 -0
  305. data/lib/arel/nodes/terminal.rb +16 -0
  306. data/lib/arel/nodes/true.rb +16 -0
  307. data/lib/arel/nodes/unary.rb +44 -0
  308. data/lib/arel/nodes/unary_operation.rb +20 -0
  309. data/lib/arel/nodes/unqualified_column.rb +22 -0
  310. data/lib/arel/nodes/update_statement.rb +41 -0
  311. data/lib/arel/nodes/values_list.rb +9 -0
  312. data/lib/arel/nodes/window.rb +126 -0
  313. data/lib/arel/nodes/with.rb +11 -0
  314. data/lib/arel/order_predications.rb +13 -0
  315. data/lib/arel/predications.rb +250 -0
  316. data/lib/arel/select_manager.rb +270 -0
  317. data/lib/arel/table.rb +118 -0
  318. data/lib/arel/tree_manager.rb +72 -0
  319. data/lib/arel/update_manager.rb +34 -0
  320. data/lib/arel/visitors.rb +13 -0
  321. data/lib/arel/visitors/dot.rb +308 -0
  322. data/lib/arel/visitors/mysql.rb +93 -0
  323. data/lib/arel/visitors/postgresql.rb +120 -0
  324. data/lib/arel/visitors/sqlite.rb +38 -0
  325. data/lib/arel/visitors/to_sql.rb +899 -0
  326. data/lib/arel/visitors/visitor.rb +45 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/rails/generators/active_record.rb +7 -5
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  330. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  331. data/lib/rails/generators/active_record/migration.rb +22 -3
  332. data/lib/rails/generators/active_record/migration/migration_generator.rb +38 -35
  333. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +3 -1
  334. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +7 -5
  335. data/lib/rails/generators/active_record/model/model_generator.rb +41 -25
  336. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  337. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
  338. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  339. metadata +141 -57
  340. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  341. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  342. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  343. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  344. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  345. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  346. data/lib/active_record/associations/preloader/singular_association.rb +0 -20
  347. data/lib/active_record/attribute.rb +0 -213
  348. data/lib/active_record/attribute/user_provided_default.rb +0 -28
  349. data/lib/active_record/attribute_decorators.rb +0 -67
  350. data/lib/active_record/attribute_mutation_tracker.rb +0 -70
  351. data/lib/active_record/attribute_set.rb +0 -110
  352. data/lib/active_record/attribute_set/builder.rb +0 -132
  353. data/lib/active_record/collection_cache_key.rb +0 -50
  354. data/lib/active_record/connection_adapters/connection_specification.rb +0 -263
  355. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -22
  356. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
  357. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  358. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  359. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -17
  360. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
  361. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
  362. data/lib/active_record/relation/where_clause_factory.rb +0 -38
  363. data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  class Relation
3
5
  class FromClause # :nodoc:
@@ -8,14 +10,6 @@ module ActiveRecord
8
10
  @name = name
9
11
  end
10
12
 
11
- def binds
12
- if value.is_a?(Relation)
13
- value.bound_attributes
14
- else
15
- []
16
- end
17
- end
18
-
19
13
  def merge(other)
20
14
  self
21
15
  end
@@ -24,8 +18,12 @@ module ActiveRecord
24
18
  value.nil?
25
19
  end
26
20
 
21
+ def ==(other)
22
+ self.class == other.class && value == other.value && name == other.name
23
+ end
24
+
27
25
  def self.empty
28
- @empty ||= new(nil, nil)
26
+ @empty ||= new(nil, nil).freeze
29
27
  end
30
28
  end
31
29
  end
@@ -1,19 +1,22 @@
1
- require 'active_support/core_ext/hash/keys'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash/keys"
2
4
 
3
5
  module ActiveRecord
4
6
  class Relation
5
7
  class HashMerger # :nodoc:
6
8
  attr_reader :relation, :hash
7
9
 
8
- def initialize(relation, hash)
10
+ def initialize(relation, hash, rewhere = nil)
9
11
  hash.assert_valid_keys(*Relation::VALUE_METHODS)
10
12
 
11
13
  @relation = relation
12
14
  @hash = hash
15
+ @rewhere = rewhere
13
16
  end
14
17
 
15
- def merge #:nodoc:
16
- Merger.new(relation, other).merge
18
+ def merge
19
+ Merger.new(relation, other, @rewhere).merge
17
20
  end
18
21
 
19
22
  # Applying values to a relation has some side effects. E.g.
@@ -21,20 +24,19 @@ module ActiveRecord
21
24
  # build a relation to merge in rather than directly merging
22
25
  # the values.
23
26
  def other
24
- other = Relation.create(relation.klass, relation.table, relation.predicate_builder)
25
- hash.each { |k, v|
26
- if k == :joins
27
- if Hash === v
28
- other.joins!(v)
29
- else
30
- other.joins!(*v)
31
- end
32
- elsif k == :select
33
- other._select!(v)
27
+ other = Relation.create(
28
+ relation.klass,
29
+ table: relation.table,
30
+ predicate_builder: relation.predicate_builder
31
+ )
32
+ hash.each do |k, v|
33
+ k = :_select if k == :select
34
+ if Array === v
35
+ other.public_send("#{k}!", *v)
34
36
  else
35
- other.send("#{k}!", v)
37
+ other.public_send("#{k}!", v)
36
38
  end
37
- }
39
+ end
38
40
  other
39
41
  end
40
42
  end
@@ -42,15 +44,16 @@ module ActiveRecord
42
44
  class Merger # :nodoc:
43
45
  attr_reader :relation, :values, :other
44
46
 
45
- def initialize(relation, other)
47
+ def initialize(relation, other, rewhere = nil)
46
48
  @relation = relation
47
49
  @values = other.values
48
50
  @other = other
51
+ @rewhere = rewhere
49
52
  end
50
53
 
51
54
  NORMAL_VALUES = Relation::VALUE_METHODS -
52
55
  Relation::CLAUSE_METHODS -
53
- [:includes, :preload, :joins, :order, :reverse_order, :lock, :create_with, :reordering] # :nodoc:
56
+ [:includes, :preload, :joins, :left_outer_joins, :order, :reverse_order, :lock, :create_with, :reordering] # :nodoc:
54
57
 
55
58
  def normal_values
56
59
  NORMAL_VALUES
@@ -67,7 +70,7 @@ module ActiveRecord
67
70
  if name == :select
68
71
  relation._select!(*value)
69
72
  else
70
- relation.send("#{name}!", *value)
73
+ relation.public_send("#{name}!", *value)
71
74
  end
72
75
  end
73
76
  end
@@ -77,91 +80,106 @@ module ActiveRecord
77
80
  merge_clauses
78
81
  merge_preloads
79
82
  merge_joins
83
+ merge_outer_joins
80
84
 
81
85
  relation
82
86
  end
83
87
 
84
88
  private
89
+ def merge_preloads
90
+ return if other.preload_values.empty? && other.includes_values.empty?
85
91
 
86
- def merge_preloads
87
- return if other.preload_values.empty? && other.includes_values.empty?
92
+ if other.klass == relation.klass
93
+ relation.preload_values |= other.preload_values unless other.preload_values.empty?
94
+ relation.includes_values |= other.includes_values unless other.includes_values.empty?
95
+ else
96
+ reflection = relation.klass.reflect_on_all_associations.find do |r|
97
+ r.class_name == other.klass.name
98
+ end || return
88
99
 
89
- if other.klass == relation.klass
90
- relation.preload!(*other.preload_values) unless other.preload_values.empty?
91
- relation.includes!(other.includes_values) unless other.includes_values.empty?
92
- else
93
- reflection = relation.klass.reflect_on_all_associations.find do |r|
94
- r.class_name == other.klass.name
95
- end || return
100
+ unless other.preload_values.empty?
101
+ relation.preload! reflection.name => other.preload_values
102
+ end
96
103
 
97
- unless other.preload_values.empty?
98
- relation.preload! reflection.name => other.preload_values
104
+ unless other.includes_values.empty?
105
+ relation.includes! reflection.name => other.includes_values
106
+ end
99
107
  end
108
+ end
100
109
 
101
- unless other.includes_values.empty?
102
- relation.includes! reflection.name => other.includes_values
110
+ def merge_joins
111
+ return if other.joins_values.empty?
112
+
113
+ if other.klass == relation.klass
114
+ relation.joins_values |= other.joins_values
115
+ else
116
+ associations, others = other.joins_values.partition do |join|
117
+ case join
118
+ when Hash, Symbol, Array; true
119
+ end
120
+ end
121
+
122
+ join_dependency = other.construct_join_dependency(
123
+ associations, Arel::Nodes::InnerJoin
124
+ )
125
+ relation.joins!(join_dependency, *others)
103
126
  end
104
127
  end
105
- end
106
128
 
107
- def merge_joins
108
- return if other.joins_values.blank?
129
+ def merge_outer_joins
130
+ return if other.left_outer_joins_values.empty?
109
131
 
110
- if other.klass == relation.klass
111
- relation.joins!(*other.joins_values)
112
- else
113
- joins_dependency, rest = other.joins_values.partition do |join|
114
- case join
115
- when Hash, Symbol, Array
116
- true
117
- else
118
- false
132
+ if other.klass == relation.klass
133
+ relation.left_outer_joins_values |= other.left_outer_joins_values
134
+ else
135
+ associations, others = other.left_outer_joins_values.partition do |join|
136
+ case join
137
+ when Hash, Symbol, Array; true
138
+ end
119
139
  end
140
+
141
+ join_dependency = other.construct_join_dependency(
142
+ associations, Arel::Nodes::OuterJoin
143
+ )
144
+ relation.left_outer_joins!(join_dependency, *others)
120
145
  end
146
+ end
121
147
 
122
- join_dependency = ActiveRecord::Associations::JoinDependency.new(other.klass,
123
- joins_dependency,
124
- [])
125
- relation.joins! rest
148
+ def merge_multi_values
149
+ if other.reordering_value
150
+ # override any order specified in the original relation
151
+ relation.reorder!(*other.order_values)
152
+ elsif other.order_values.any?
153
+ # merge in order_values from relation
154
+ relation.order!(*other.order_values)
155
+ end
126
156
 
127
- @relation = relation.joins join_dependency
157
+ extensions = other.extensions - relation.extensions
158
+ relation.extending!(*extensions) if extensions.any?
128
159
  end
129
- end
130
160
 
131
- def merge_multi_values
132
- if other.reordering_value
133
- # override any order specified in the original relation
134
- relation.reorder! other.order_values
135
- elsif other.order_values
136
- # merge in order_values from relation
137
- relation.order! other.order_values
161
+ def merge_single_values
162
+ relation.lock_value ||= other.lock_value if other.lock_value
163
+
164
+ unless other.create_with_value.blank?
165
+ relation.create_with_value = (relation.create_with_value || {}).merge(other.create_with_value)
166
+ end
138
167
  end
139
168
 
140
- relation.extend(*other.extending_values) unless other.extending_values.blank?
141
- end
169
+ def merge_clauses
170
+ relation.from_clause = other.from_clause if replace_from_clause?
142
171
 
143
- def merge_single_values
144
- if relation.from_clause.empty?
145
- relation.from_clause = other.from_clause
146
- end
147
- relation.lock_value ||= other.lock_value
172
+ where_clause = relation.where_clause.merge(other.where_clause, @rewhere)
173
+ relation.where_clause = where_clause unless where_clause.empty?
148
174
 
149
- unless other.create_with_value.blank?
150
- relation.create_with_value = (relation.create_with_value || {}).merge(other.create_with_value)
175
+ having_clause = relation.having_clause.merge(other.having_clause)
176
+ relation.having_clause = having_clause unless having_clause.empty?
151
177
  end
152
- end
153
178
 
154
- CLAUSE_METHOD_NAMES = CLAUSE_METHODS.map do |name|
155
- ["#{name}_clause", "#{name}_clause="]
156
- end
157
-
158
- def merge_clauses
159
- CLAUSE_METHOD_NAMES.each do |(reader, writer)|
160
- clause = relation.send(reader)
161
- other_clause = other.send(reader)
162
- relation.send(writer, clause.merge(other_clause))
179
+ def replace_from_clause?
180
+ relation.from_clause.empty? && !other.from_clause.empty? &&
181
+ relation.klass.base_class == other.klass.base_class
163
182
  end
164
- end
165
183
  end
166
184
  end
167
185
  end
@@ -1,60 +1,42 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  class PredicateBuilder # :nodoc:
3
- require 'active_record/relation/predicate_builder/array_handler'
4
- require 'active_record/relation/predicate_builder/association_query_handler'
5
- require 'active_record/relation/predicate_builder/base_handler'
6
- require 'active_record/relation/predicate_builder/basic_object_handler'
7
- require 'active_record/relation/predicate_builder/class_handler'
8
- require 'active_record/relation/predicate_builder/polymorphic_array_handler'
9
- require 'active_record/relation/predicate_builder/range_handler'
10
- require 'active_record/relation/predicate_builder/relation_handler'
5
+ require "active_record/relation/predicate_builder/array_handler"
6
+ require "active_record/relation/predicate_builder/basic_object_handler"
7
+ require "active_record/relation/predicate_builder/range_handler"
8
+ require "active_record/relation/predicate_builder/relation_handler"
9
+ require "active_record/relation/predicate_builder/association_query_value"
10
+ require "active_record/relation/predicate_builder/polymorphic_array_value"
11
11
 
12
- delegate :resolve_column_aliases, to: :table
12
+ # No-op BaseHandler to work Mashal.load(File.read("legacy_relation.dump")).
13
+ # TODO: Remove the constant alias once Rails 6.1 has released.
14
+ BaseHandler = BasicObjectHandler
13
15
 
14
16
  def initialize(table)
15
17
  @table = table
16
18
  @handlers = []
17
19
 
18
20
  register_handler(BasicObject, BasicObjectHandler.new(self))
19
- register_handler(Class, ClassHandler.new(self))
20
- register_handler(Base, BaseHandler.new(self))
21
21
  register_handler(Range, RangeHandler.new(self))
22
- register_handler(RangeHandler::RangeWithBinds, RangeHandler.new(self))
23
22
  register_handler(Relation, RelationHandler.new)
24
23
  register_handler(Array, ArrayHandler.new(self))
25
- register_handler(AssociationQueryValue, AssociationQueryHandler.new(self))
26
- register_handler(PolymorphicArrayValue, PolymorphicArrayHandler.new(self))
24
+ register_handler(Set, ArrayHandler.new(self))
27
25
  end
28
26
 
29
- def build_from_hash(attributes)
27
+ def build_from_hash(attributes, &block)
30
28
  attributes = convert_dot_notation_to_hash(attributes)
31
- expand_from_hash(attributes)
32
- end
33
-
34
- def create_binds(attributes)
35
- attributes = convert_dot_notation_to_hash(attributes)
36
- create_binds_for_hash(attributes)
37
- end
38
-
39
- def expand(column, value)
40
- # Find the foreign key when using queries such as:
41
- # Post.where(author: author)
42
- #
43
- # For polymorphic relationships, find the foreign key and type:
44
- # PriceEstimate.where(estimate_of: treasure)
45
- value = AssociationQueryHandler.value_for(table, column, value) if table.associated_with?(column)
46
- build(table.arel_attribute(column), value)
29
+ expand_from_hash(attributes, &block)
47
30
  end
48
31
 
49
32
  def self.references(attributes)
50
- attributes.map do |key, value|
33
+ attributes.each_with_object([]) do |(key, value), result|
51
34
  if value.is_a?(Hash)
52
- key
53
- else
54
- key = key.to_s
55
- key.split('.'.freeze).first if key.include?('.'.freeze)
35
+ result << Arel.sql(key)
36
+ elsif key.include?(".")
37
+ result << Arel.sql(key.split(".").first)
56
38
  end
57
- end.compact
39
+ end
58
40
  end
59
41
 
60
42
  # Define how a class is converted to Arel nodes when passed to +where+.
@@ -72,97 +54,114 @@ module ActiveRecord
72
54
  @handlers.unshift([klass, handler])
73
55
  end
74
56
 
75
- def build(attribute, value)
76
- handler_for(value).call(attribute, value)
57
+ def [](attr_name, value, operator = nil)
58
+ build(table.arel_table[attr_name], value, operator)
77
59
  end
78
60
 
79
- protected
80
-
81
- attr_reader :table
82
-
83
- def expand_from_hash(attributes)
84
- return ["1=0"] if attributes.empty?
85
-
86
- attributes.flat_map do |key, value|
87
- if value.is_a?(Hash)
88
- associated_predicate_builder(key).expand_from_hash(value)
89
- else
90
- expand(key, value)
91
- end
61
+ def build(attribute, value, operator = nil)
62
+ value = value.id if value.respond_to?(:id)
63
+ if operator ||= table.type(attribute.name).force_equality?(value) && :eq
64
+ bind = build_bind_attribute(attribute.name, value)
65
+ attribute.public_send(operator, bind)
66
+ else
67
+ handler_for(value).call(attribute, value)
92
68
  end
93
69
  end
94
70
 
71
+ def build_bind_attribute(column_name, value)
72
+ attr = Relation::QueryAttribute.new(column_name, value, table.type(column_name))
73
+ Arel::Nodes::BindParam.new(attr)
74
+ end
95
75
 
96
- def create_binds_for_hash(attributes)
97
- result = attributes.dup
98
- binds = []
99
-
100
- attributes.each do |column_name, value|
101
- case value
102
- when Hash
103
- attrs, bvs = associated_predicate_builder(column_name).create_binds_for_hash(value)
104
- result[column_name] = attrs
105
- binds += bvs
106
- when Relation
107
- binds += value.bound_attributes
108
- when Range
109
- first = value.begin
110
- last = value.end
111
- unless first.respond_to?(:infinite?) && first.infinite?
112
- binds << build_bind_param(column_name, first)
113
- first = Arel::Nodes::BindParam.new
114
- end
115
- unless last.respond_to?(:infinite?) && last.infinite?
116
- binds << build_bind_param(column_name, last)
117
- last = Arel::Nodes::BindParam.new
118
- end
76
+ def resolve_arel_attribute(table_name, column_name, &block)
77
+ table.associated_table(table_name, &block).arel_table[column_name]
78
+ end
119
79
 
120
- result[column_name] = RangeHandler::RangeWithBinds.new(first, last, value.exclude_end?)
121
- else
122
- if can_be_bound?(column_name, value)
123
- result[column_name] = Arel::Nodes::BindParam.new
124
- binds << build_bind_param(column_name, value)
80
+ protected
81
+ def expand_from_hash(attributes, &block)
82
+ return ["1=0"] if attributes.empty?
83
+
84
+ attributes.flat_map do |key, value|
85
+ if value.is_a?(Hash) && !table.has_column?(key)
86
+ table.associated_table(key, &block)
87
+ .predicate_builder.expand_from_hash(value.stringify_keys)
88
+ elsif table.associated_with?(key)
89
+ # Find the foreign key when using queries such as:
90
+ # Post.where(author: author)
91
+ #
92
+ # For polymorphic relationships, find the foreign key and type:
93
+ # PriceEstimate.where(estimate_of: treasure)
94
+ associated_table = table.associated_table(key)
95
+ if associated_table.polymorphic_association?
96
+ value = [value] unless value.is_a?(Array)
97
+ klass = PolymorphicArrayValue
98
+ elsif associated_table.through_association?
99
+ next associated_table.predicate_builder.expand_from_hash(
100
+ associated_table.primary_key => value
101
+ )
102
+ end
103
+
104
+ klass ||= AssociationQueryValue
105
+ queries = klass.new(associated_table, value).queries.map! do |query|
106
+ expand_from_hash(query)
107
+ end
108
+
109
+ grouping_queries(queries)
110
+ elsif table.aggregated_with?(key)
111
+ mapping = table.reflect_on_aggregation(key).mapping
112
+ values = value.nil? ? [nil] : Array.wrap(value)
113
+ if mapping.length == 1 || values.empty?
114
+ column_name, aggr_attr = mapping.first
115
+ values = values.map do |object|
116
+ object.respond_to?(aggr_attr) ? object.public_send(aggr_attr) : object
117
+ end
118
+ self[column_name, values]
119
+ else
120
+ queries = values.map do |object|
121
+ mapping.map do |field_attr, aggregate_attr|
122
+ self[field_attr, object.try!(aggregate_attr)]
123
+ end
124
+ end
125
+
126
+ grouping_queries(queries)
127
+ end
128
+ else
129
+ self[key, value]
125
130
  end
126
131
  end
127
132
  end
128
133
 
129
- [result, binds]
130
- end
131
-
132
134
  private
135
+ attr_reader :table
133
136
 
134
- def associated_predicate_builder(association_name)
135
- self.class.new(table.associated_table(association_name))
136
- end
137
-
138
- def convert_dot_notation_to_hash(attributes)
139
- dot_notation = attributes.select do |k, v|
140
- k.include?(".".freeze) && !v.is_a?(Hash)
137
+ def grouping_queries(queries)
138
+ if queries.one?
139
+ queries.first
140
+ else
141
+ queries.map! { |query| query.reduce(&:and) }
142
+ queries = queries.reduce { |result, query| Arel::Nodes::Or.new(result, query) }
143
+ Arel::Nodes::Grouping.new(queries)
144
+ end
141
145
  end
142
146
 
143
- dot_notation.each_key do |key|
144
- table_name, column_name = key.split(".".freeze)
145
- value = attributes.delete(key)
146
- attributes[table_name] ||= {}
147
-
148
- attributes[table_name] = attributes[table_name].merge(column_name => value)
149
- end
147
+ def convert_dot_notation_to_hash(attributes)
148
+ dot_notation = attributes.select do |k, v|
149
+ k.include?(".") && !v.is_a?(Hash)
150
+ end
150
151
 
151
- attributes
152
- end
152
+ dot_notation.each_key do |key|
153
+ table_name, column_name = key.split(".")
154
+ value = attributes.delete(key)
155
+ attributes[table_name] ||= {}
153
156
 
154
- def handler_for(object)
155
- @handlers.detect { |klass, _| klass === object }.last
156
- end
157
+ attributes[table_name] = attributes[table_name].merge(column_name => value)
158
+ end
157
159
 
158
- def can_be_bound?(column_name, value)
159
- !value.nil? &&
160
- handler_for(value).is_a?(BasicObjectHandler) &&
161
- !table.associated_with?(column_name)
162
- end
160
+ attributes
161
+ end
163
162
 
164
- def build_bind_param(column_name, value)
165
- Relation::QueryAttribute.new(column_name.to_s, value, table.type(column_name))
166
- end
163
+ def handler_for(object)
164
+ @handlers.detect { |klass, _| klass === object }.last
165
+ end
167
166
  end
168
167
  end