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,23 +1,25 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  class Relation
3
5
  module RecordFetchWarning
4
6
  # When this module is prepended to ActiveRecord::Relation and
5
- # `config.active_record.warn_on_records_fetched_greater_than` is
7
+ # +config.active_record.warn_on_records_fetched_greater_than+ is
6
8
  # set to an integer, if the number of records a query returns is
7
- # greater than the value of `warn_on_records_fetched_greater_than`,
9
+ # greater than the value of +warn_on_records_fetched_greater_than+,
8
10
  # a warning is logged. This allows for the detection of queries that
9
11
  # return a large number of records, which could cause memory bloat.
10
12
  #
11
13
  # In most cases, fetching large number of records can be performed
12
14
  # efficiently using the ActiveRecord::Batches methods.
13
- # See active_record/lib/relation/batches.rb for more information.
15
+ # See ActiveRecord::Batches for more information.
14
16
  def exec_queries
15
17
  QueryRegistry.reset
16
18
 
17
- super.tap do
19
+ super.tap do |records|
18
20
  if logger && warn_on_records_fetched_greater_than
19
- if @records.length > warn_on_records_fetched_greater_than
20
- logger.warn "Query fetched #{@records.size} #{@klass} records: #{QueryRegistry.queries.join(";")}"
21
+ if records.length > warn_on_records_fetched_greater_than
22
+ logger.warn "Query fetched #{records.size} #{@klass} records: #{QueryRegistry.queries.join(";")}"
21
23
  end
22
24
  end
23
25
  end
@@ -1,13 +1,14 @@
1
- require 'active_support/core_ext/hash/except'
2
- require 'active_support/core_ext/hash/slice'
3
- require 'active_record/relation/merger'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash/except"
4
+ require "active_support/core_ext/hash/slice"
5
+ require "active_record/relation/merger"
4
6
 
5
7
  module ActiveRecord
6
8
  module SpawnMethods
7
-
8
9
  # This is overridden by Associations::CollectionProxy
9
10
  def spawn #:nodoc:
10
- clone
11
+ already_in_scope? ? klass.all : clone
11
12
  end
12
13
 
13
14
  # Merges in the conditions from <tt>other</tt>, if <tt>other</tt> is an ActiveRecord::Relation.
@@ -27,21 +28,22 @@ module ActiveRecord
27
28
  # # => Post.where(published: true).joins(:comments)
28
29
  #
29
30
  # This is mainly intended for sharing common conditions between multiple associations.
30
- def merge(other)
31
+ def merge(other, *rest)
31
32
  if other.is_a?(Array)
32
33
  records & other
33
34
  elsif other
34
- spawn.merge!(other)
35
+ spawn.merge!(other, *rest)
35
36
  else
36
37
  raise ArgumentError, "invalid argument: #{other.inspect}."
37
38
  end
38
39
  end
39
40
 
40
- def merge!(other) # :nodoc:
41
+ def merge!(other, *rest) # :nodoc:
42
+ options = rest.extract_options!
41
43
  if other.is_a?(Hash)
42
- Relation::HashMerger.new(self, other).merge
44
+ Relation::HashMerger.new(self, other, options[:rewhere]).merge
43
45
  elsif other.is_a?(Relation)
44
- Relation::Merger.new(self, other).merge
46
+ Relation::Merger.new(self, other, options[:rewhere]).merge
45
47
  elsif other.respond_to?(:to_proc)
46
48
  instance_exec(&other)
47
49
  else
@@ -66,10 +68,9 @@ module ActiveRecord
66
68
  end
67
69
 
68
70
  private
69
-
70
- def relation_with(values) # :nodoc:
71
- result = Relation.create(klass, table, predicate_builder, values)
72
- result.extend(*extending_values) if extending_values.any?
71
+ def relation_with(values)
72
+ result = spawn
73
+ result.instance_variable_set(:@values, values)
73
74
  result
74
75
  end
75
76
  end
@@ -1,174 +1,236 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/array/extract"
4
+
1
5
  module ActiveRecord
2
6
  class Relation
3
7
  class WhereClause # :nodoc:
4
- attr_reader :binds
5
-
6
8
  delegate :any?, :empty?, to: :predicates
7
9
 
8
- def initialize(predicates, binds)
10
+ def initialize(predicates)
9
11
  @predicates = predicates
10
- @binds = binds
11
12
  end
12
13
 
13
14
  def +(other)
14
- WhereClause.new(
15
- predicates + other.predicates,
16
- binds + other.binds,
17
- )
15
+ WhereClause.new(predicates + other.predicates)
16
+ end
17
+
18
+ def -(other)
19
+ WhereClause.new(predicates - other.predicates)
18
20
  end
19
21
 
20
- def merge(other)
21
- WhereClause.new(
22
- predicates_unreferenced_by(other) + other.predicates,
23
- non_conflicting_binds(other) + other.binds,
24
- )
22
+ def |(other)
23
+ WhereClause.new(predicates | other.predicates)
24
+ end
25
+
26
+ def merge(other, rewhere = nil)
27
+ predicates = if rewhere
28
+ except_predicates(other.extract_attributes)
29
+ else
30
+ predicates_unreferenced_by(other)
31
+ end
32
+
33
+ WhereClause.new(predicates | other.predicates)
25
34
  end
26
35
 
27
36
  def except(*columns)
28
- WhereClause.new(
29
- predicates_except(columns),
30
- binds_except(columns),
31
- )
37
+ WhereClause.new(except_predicates(columns))
32
38
  end
33
39
 
34
40
  def or(other)
35
- if empty?
36
- self
37
- elsif other.empty?
38
- other
41
+ left = self - other
42
+ common = self - left
43
+ right = other - common
44
+
45
+ if left.empty? || right.empty?
46
+ common
39
47
  else
40
- WhereClause.new(
41
- [ast.or(other.ast)],
42
- binds + other.binds
43
- )
48
+ left = left.ast
49
+ left = left.expr if left.is_a?(Arel::Nodes::Grouping)
50
+
51
+ right = right.ast
52
+ right = right.expr if right.is_a?(Arel::Nodes::Grouping)
53
+
54
+ or_clause = Arel::Nodes::Or.new(left, right)
55
+
56
+ common.predicates << Arel::Nodes::Grouping.new(or_clause)
57
+ common
44
58
  end
45
59
  end
46
60
 
47
61
  def to_h(table_name = nil)
48
- equalities = predicates.grep(Arel::Nodes::Equality)
49
- if table_name
50
- equalities = equalities.select do |node|
51
- node.left.relation.name == table_name
52
- end
62
+ equalities(predicates).each_with_object({}) do |node, hash|
63
+ next if table_name&.!= node.left.relation.name
64
+ name = node.left.name.to_s
65
+ value = extract_node_value(node.right)
66
+ hash[name] = value
53
67
  end
54
-
55
- binds = self.binds.map { |attr| [attr.name, attr.value] }.to_h
56
-
57
- equalities.map { |node|
58
- name = node.left.name
59
- [name, binds.fetch(name.to_s) {
60
- case node.right
61
- when Array then node.right.map(&:val)
62
- when Arel::Nodes::Casted, Arel::Nodes::Quoted
63
- node.right.val
64
- end
65
- }]
66
- }.to_h
67
68
  end
68
69
 
69
70
  def ast
70
- Arel::Nodes::And.new(predicates_with_wrapped_sql_literals)
71
+ predicates = predicates_with_wrapped_sql_literals
72
+ predicates.one? ? predicates.first : Arel::Nodes::And.new(predicates)
71
73
  end
72
74
 
73
75
  def ==(other)
74
76
  other.is_a?(WhereClause) &&
75
- predicates == other.predicates &&
76
- binds == other.binds
77
+ predicates == other.predicates
77
78
  end
78
79
 
79
80
  def invert
80
- WhereClause.new(inverted_predicates, binds)
81
+ if predicates.size == 1
82
+ inverted_predicates = [ invert_predicate(predicates.first) ]
83
+ else
84
+ inverted_predicates = [ Arel::Nodes::Not.new(ast) ]
85
+ end
86
+
87
+ WhereClause.new(inverted_predicates)
81
88
  end
82
89
 
83
90
  def self.empty
84
- @empty ||= new([], [])
91
+ @empty ||= new([]).freeze
92
+ end
93
+
94
+ def contradiction?
95
+ predicates.any? do |x|
96
+ case x
97
+ when Arel::Nodes::In
98
+ Array === x.right && x.right.empty?
99
+ when Arel::Nodes::Equality
100
+ x.right.respond_to?(:unboundable?) && x.right.unboundable?
101
+ end
102
+ end
103
+ end
104
+
105
+ def extract_attributes
106
+ predicates.each_with_object([]) do |node, attrs|
107
+ attr = extract_attribute(node) || begin
108
+ node.left if node.equality? && node.left.is_a?(Arel::Predications)
109
+ end
110
+ attrs << attr if attr
111
+ end
85
112
  end
86
113
 
87
114
  protected
115
+ attr_reader :predicates
88
116
 
89
- attr_reader :predicates
117
+ def referenced_columns
118
+ predicates.each_with_object({}) do |node, hash|
119
+ attr = extract_attribute(node) || begin
120
+ node.left if equality_node?(node) && node.left.is_a?(Arel::Predications)
121
+ end
90
122
 
91
- def referenced_columns
92
- @referenced_columns ||= begin
93
- equality_nodes = predicates.select { |n| equality_node?(n) }
94
- Set.new(equality_nodes, &:left)
123
+ hash[attr] = node if attr
124
+ end
95
125
  end
96
- end
97
126
 
98
127
  private
99
-
100
- def predicates_unreferenced_by(other)
101
- predicates.reject do |n|
102
- equality_node?(n) && other.referenced_columns.include?(n.left)
128
+ def extract_attribute(node)
129
+ attr_node = nil
130
+ Arel.fetch_attribute(node) do |attr|
131
+ return if attr_node&.!= attr # all attr nodes should be the same
132
+ attr_node = attr
133
+ end
134
+ attr_node
103
135
  end
104
- end
105
136
 
106
- def equality_node?(node)
107
- node.respond_to?(:operator) && node.operator == :==
108
- end
137
+ def equalities(predicates)
138
+ equalities = []
109
139
 
110
- def non_conflicting_binds(other)
111
- conflicts = referenced_columns & other.referenced_columns
112
- conflicts.map! { |node| node.name.to_s }
113
- binds.reject { |attr| conflicts.include?(attr.name) }
114
- end
140
+ predicates.each do |node|
141
+ if equality_node?(node)
142
+ equalities << node
143
+ elsif node.is_a?(Arel::Nodes::And)
144
+ equalities.concat equalities(node.children)
145
+ end
146
+ end
115
147
 
116
- def inverted_predicates
117
- predicates.map { |node| invert_predicate(node) }
118
- end
148
+ equalities
149
+ end
119
150
 
120
- def invert_predicate(node)
121
- case node
122
- when NilClass
123
- raise ArgumentError, 'Invalid argument for .where.not(), got nil.'
124
- when Arel::Nodes::In
125
- Arel::Nodes::NotIn.new(node.left, node.right)
126
- when Arel::Nodes::Equality
127
- Arel::Nodes::NotEqual.new(node.left, node.right)
128
- when String
129
- Arel::Nodes::Not.new(Arel::Nodes::SqlLiteral.new(node))
130
- else
131
- Arel::Nodes::Not.new(node)
151
+ def predicates_unreferenced_by(other)
152
+ referenced_columns = other.referenced_columns
153
+
154
+ predicates.reject do |node|
155
+ attr = extract_attribute(node) || begin
156
+ node.left if equality_node?(node) && node.left.is_a?(Arel::Predications)
157
+ end
158
+ next false unless attr
159
+
160
+ ref = referenced_columns[attr]
161
+ next false unless ref
162
+
163
+ if equality_node?(node) && equality_node?(ref) || node == ref
164
+ true
165
+ else
166
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
167
+ Merging (#{node.to_sql}) and (#{ref.to_sql}) no longer maintain
168
+ both conditions, and will be replaced by the latter in Rails 6.2.
169
+ To migrate to Rails 6.2's behavior, use `relation.merge(other, rewhere: true)`.
170
+ MSG
171
+ false
172
+ end
173
+ end
174
+ end
175
+
176
+ def equality_node?(node)
177
+ !node.is_a?(String) && node.equality?
132
178
  end
133
- end
134
179
 
135
- def predicates_except(columns)
136
- predicates.reject do |node|
180
+ def invert_predicate(node)
137
181
  case node
138
- when Arel::Nodes::Between, Arel::Nodes::In, Arel::Nodes::NotIn, Arel::Nodes::Equality, Arel::Nodes::NotEqual, Arel::Nodes::LessThan, Arel::Nodes::LessThanOrEqual, Arel::Nodes::GreaterThan, Arel::Nodes::GreaterThanOrEqual
139
- subrelation = (node.left.kind_of?(Arel::Attributes::Attribute) ? node.left : node.right)
140
- columns.include?(subrelation.name.to_s)
182
+ when NilClass
183
+ raise ArgumentError, "Invalid argument for .where.not(), got nil."
184
+ when String
185
+ Arel::Nodes::Not.new(Arel::Nodes::SqlLiteral.new(node))
186
+ else
187
+ node.invert
141
188
  end
142
189
  end
143
- end
144
190
 
145
- def binds_except(columns)
146
- binds.reject do |attr|
147
- columns.include?(attr.name)
191
+ def except_predicates(columns)
192
+ attrs = columns.extract! { |node| node.is_a?(Arel::Attribute) }
193
+ non_attrs = columns.extract! { |node| node.is_a?(Arel::Predications) }
194
+
195
+ predicates.reject do |node|
196
+ if !non_attrs.empty? && node.equality? && node.left.is_a?(Arel::Predications)
197
+ non_attrs.include?(node.left)
198
+ end || Arel.fetch_attribute(node) do |attr|
199
+ attrs.include?(attr) || columns.include?(attr.name.to_s)
200
+ end
201
+ end
148
202
  end
149
- end
150
203
 
151
- def predicates_with_wrapped_sql_literals
152
- non_empty_predicates.map do |node|
153
- if Arel::Nodes::Equality === node
154
- node
155
- else
156
- wrap_sql_literal(node)
204
+ def predicates_with_wrapped_sql_literals
205
+ non_empty_predicates.map do |node|
206
+ case node
207
+ when Arel::Nodes::SqlLiteral, ::String
208
+ wrap_sql_literal(node)
209
+ else node
210
+ end
157
211
  end
158
212
  end
159
- end
160
213
 
161
- ARRAY_WITH_EMPTY_STRING = ['']
162
- def non_empty_predicates
163
- predicates - ARRAY_WITH_EMPTY_STRING
164
- end
214
+ ARRAY_WITH_EMPTY_STRING = [""]
215
+ def non_empty_predicates
216
+ predicates - ARRAY_WITH_EMPTY_STRING
217
+ end
165
218
 
166
- def wrap_sql_literal(node)
167
- if ::String === node
168
- node = Arel.sql(node)
219
+ def wrap_sql_literal(node)
220
+ if ::String === node
221
+ node = Arel.sql(node)
222
+ end
223
+ Arel::Nodes::Grouping.new(node)
224
+ end
225
+
226
+ def extract_node_value(node)
227
+ case node
228
+ when Array
229
+ node.map { |v| extract_node_value(v) }
230
+ when Arel::Nodes::BindParam, Arel::Nodes::Casted, Arel::Nodes::Quoted
231
+ node.value_before_type_cast
232
+ end
169
233
  end
170
- Arel::Nodes::Grouping.new(node)
171
- end
172
234
  end
173
235
  end
174
236
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  ###
3
5
  # This class encapsulates a result returned from calling
@@ -19,7 +21,7 @@ module ActiveRecord
19
21
  # ]
20
22
  #
21
23
  # # Get an array of hashes representing the result (column => value):
22
- # result.to_hash
24
+ # result.to_a
23
25
  # # => [{"id" => 1, "title" => "title_1", "body" => "body_1"},
24
26
  # {"id" => 2, "title" => "title_2", "body" => "body_2"},
25
27
  # ...
@@ -32,8 +34,6 @@ module ActiveRecord
32
34
  class Result
33
35
  include Enumerable
34
36
 
35
- IDENTITY_TYPE = Type::Value.new # :nodoc:
36
-
37
37
  attr_reader :columns, :rows, :column_types
38
38
 
39
39
  def initialize(columns, rows, column_types = {})
@@ -43,10 +43,20 @@ module ActiveRecord
43
43
  @column_types = column_types
44
44
  end
45
45
 
46
+ # Returns true if this result set includes the column named +name+
47
+ def includes_column?(name)
48
+ @columns.include? name
49
+ end
50
+
51
+ # Returns the number of elements in the rows array.
46
52
  def length
47
53
  @rows.length
48
54
  end
49
55
 
56
+ # Calls the given block once for each element in row collection, passing
57
+ # row as parameter.
58
+ #
59
+ # Returns an +Enumerator+ if no block is given.
50
60
  def each
51
61
  if block_given?
52
62
  hash_rows.each { |row| yield row }
@@ -55,43 +65,56 @@ module ActiveRecord
55
65
  end
56
66
  end
57
67
 
58
- def to_hash
59
- hash_rows
60
- end
61
-
62
68
  alias :map! :map
63
69
  alias :collect! :map
70
+ deprecate "map!": :map
71
+ deprecate "collect!": :map
64
72
 
65
- # Returns true if there are no records.
73
+ # Returns true if there are no records, otherwise false.
66
74
  def empty?
67
75
  rows.empty?
68
76
  end
69
77
 
78
+ # Returns an array of hashes representing each row record.
70
79
  def to_ary
71
80
  hash_rows
72
81
  end
73
82
 
83
+ alias :to_a :to_ary
84
+
74
85
  def [](idx)
75
86
  hash_rows[idx]
76
87
  end
77
88
 
78
- def first
79
- return nil if @rows.empty?
80
- Hash[@columns.zip(@rows.first)]
81
- end
82
-
83
- def last
84
- return nil if @rows.empty?
85
- Hash[@columns.zip(@rows.last)]
89
+ # Returns the last record from the rows collection.
90
+ def last(n = nil)
91
+ n ? hash_rows.last(n) : hash_rows.last
86
92
  end
87
93
 
88
94
  def cast_values(type_overrides = {}) # :nodoc:
89
- types = columns.map { |name| column_type(name, type_overrides) }
90
- result = rows.map do |values|
91
- types.zip(values).map { |type, value| type.deserialize(value) }
92
- end
95
+ if columns.one?
96
+ # Separated to avoid allocating an array per row
97
+
98
+ type = if type_overrides.is_a?(Array)
99
+ type_overrides.first
100
+ else
101
+ column_type(columns.first, type_overrides)
102
+ end
93
103
 
94
- columns.one? ? result.map!(&:first) : result
104
+ rows.map do |(value)|
105
+ type.deserialize(value)
106
+ end
107
+ else
108
+ types = if type_overrides.is_a?(Array)
109
+ type_overrides
110
+ else
111
+ columns.map { |name| column_type(name, type_overrides) }
112
+ end
113
+
114
+ rows.map do |values|
115
+ Array.new(values.size) { |i| types[i].deserialize(values[i]) }
116
+ end
117
+ end
95
118
  end
96
119
 
97
120
  def initialize_copy(other)
@@ -102,37 +125,51 @@ module ActiveRecord
102
125
  end
103
126
 
104
127
  private
105
-
106
- def column_type(name, type_overrides = {})
107
- type_overrides.fetch(name) do
108
- column_types.fetch(name, IDENTITY_TYPE)
128
+ def column_type(name, type_overrides = {})
129
+ type_overrides.fetch(name) do
130
+ column_types.fetch(name, Type.default_value)
131
+ end
109
132
  end
110
- end
111
133
 
112
- def hash_rows
113
- @hash_rows ||=
114
- begin
115
- # We freeze the strings to prevent them getting duped when
116
- # used as keys in ActiveRecord::Base's @attributes hash
117
- columns = @columns.map { |c| c.dup.freeze }
118
- @rows.map { |row|
119
- # In the past we used Hash[columns.zip(row)]
120
- # though elegant, the verbose way is much more efficient
121
- # both time and memory wise cause it avoids a big array allocation
122
- # this method is called a lot and needs to be micro optimised
123
- hash = {}
124
-
125
- index = 0
126
- length = columns.length
127
-
128
- while index < length
129
- hash[columns[index]] = row[index]
130
- index += 1
131
- end
132
-
133
- hash
134
- }
135
- end
136
- end
134
+ def hash_rows
135
+ @hash_rows ||=
136
+ begin
137
+ # We freeze the strings to prevent them getting duped when
138
+ # used as keys in ActiveRecord::Base's @attributes hash
139
+ columns = @columns.map(&:-@)
140
+ length = columns.length
141
+ template = nil
142
+
143
+ @rows.map { |row|
144
+ if template
145
+ # We use transform_values to build subsequent rows from the
146
+ # hash of the first row. This is faster because we avoid any
147
+ # reallocs and in Ruby 2.7+ avoid hashing entirely.
148
+ index = -1
149
+ template.transform_values do
150
+ row[index += 1]
151
+ end
152
+ else
153
+ # In the past we used Hash[columns.zip(row)]
154
+ # though elegant, the verbose way is much more efficient
155
+ # both time and memory wise cause it avoids a big array allocation
156
+ # this method is called a lot and needs to be micro optimised
157
+ hash = {}
158
+
159
+ index = 0
160
+ while index < length
161
+ hash[columns[index]] = row[index]
162
+ index += 1
163
+ end
164
+
165
+ # It's possible to select the same column twice, in which case
166
+ # we can't use a template
167
+ template = hash if hash.length == length
168
+
169
+ hash
170
+ end
171
+ }
172
+ end
173
+ end
137
174
  end
138
175
  end