activerecord 4.2.0 → 6.1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (374) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1221 -796
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +15 -14
  5. data/examples/performance.rb +33 -32
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/aggregations.rb +267 -249
  8. data/lib/active_record/association_relation.rb +45 -7
  9. data/lib/active_record/associations/alias_tracker.rb +40 -43
  10. data/lib/active_record/associations/association.rb +172 -67
  11. data/lib/active_record/associations/association_scope.rb +105 -129
  12. data/lib/active_record/associations/belongs_to_association.rb +85 -59
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
  14. data/lib/active_record/associations/builder/association.rb +57 -43
  15. data/lib/active_record/associations/builder/belongs_to.rb +74 -57
  16. data/lib/active_record/associations/builder/collection_association.rb +15 -33
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +57 -70
  18. data/lib/active_record/associations/builder/has_many.rb +13 -5
  19. data/lib/active_record/associations/builder/has_one.rb +44 -6
  20. data/lib/active_record/associations/builder/singular_association.rb +16 -10
  21. data/lib/active_record/associations/collection_association.rb +168 -279
  22. data/lib/active_record/associations/collection_proxy.rb +263 -155
  23. data/lib/active_record/associations/foreign_association.rb +33 -0
  24. data/lib/active_record/associations/has_many_association.rb +57 -84
  25. data/lib/active_record/associations/has_many_through_association.rb +70 -82
  26. data/lib/active_record/associations/has_one_association.rb +74 -47
  27. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  28. data/lib/active_record/associations/join_dependency/join_association.rb +54 -73
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  31. data/lib/active_record/associations/join_dependency.rb +175 -164
  32. data/lib/active_record/associations/preloader/association.rb +107 -112
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  34. data/lib/active_record/associations/preloader.rb +99 -96
  35. data/lib/active_record/associations/singular_association.rb +18 -45
  36. data/lib/active_record/associations/through_association.rb +49 -24
  37. data/lib/active_record/associations.rb +1845 -1597
  38. data/lib/active_record/attribute_assignment.rb +59 -185
  39. data/lib/active_record/attribute_methods/before_type_cast.rb +20 -7
  40. data/lib/active_record/attribute_methods/dirty.rb +168 -138
  41. data/lib/active_record/attribute_methods/primary_key.rb +93 -83
  42. data/lib/active_record/attribute_methods/query.rb +8 -10
  43. data/lib/active_record/attribute_methods/read.rb +19 -79
  44. data/lib/active_record/attribute_methods/serialization.rb +49 -24
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +59 -36
  46. data/lib/active_record/attribute_methods/write.rb +25 -56
  47. data/lib/active_record/attribute_methods.rb +153 -162
  48. data/lib/active_record/attributes.rb +234 -70
  49. data/lib/active_record/autosave_association.rb +157 -69
  50. data/lib/active_record/base.rb +49 -50
  51. data/lib/active_record/callbacks.rb +234 -79
  52. data/lib/active_record/coders/json.rb +3 -1
  53. data/lib/active_record/coders/yaml_column.rb +46 -13
  54. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -317
  55. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
  56. data/lib/active_record/connection_adapters/abstract/database_statements.rb +301 -113
  57. data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
  58. data/lib/active_record/connection_adapters/abstract/quoting.rb +187 -60
  59. data/lib/active_record/connection_adapters/abstract/savepoints.rb +9 -7
  60. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
  61. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +485 -253
  62. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  63. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +909 -263
  64. data/lib/active_record/connection_adapters/abstract/transaction.rb +254 -92
  65. data/lib/active_record/connection_adapters/abstract_adapter.rb +492 -221
  66. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +580 -608
  67. data/lib/active_record/connection_adapters/column.rb +67 -40
  68. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  69. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  70. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  71. data/lib/active_record/connection_adapters/mysql/database_statements.rb +196 -0
  72. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
  73. data/lib/active_record/connection_adapters/mysql/quoting.rb +96 -0
  74. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +97 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +103 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +91 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +271 -0
  78. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
  79. data/lib/active_record/connection_adapters/mysql2_adapter.rb +81 -199
  80. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  81. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +44 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +78 -161
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -57
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +5 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +8 -6
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +17 -13
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +6 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -20
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  98. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  101. data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +67 -51
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  109. data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -25
  110. data/lib/active_record/connection_adapters/postgresql/quoting.rb +171 -48
  111. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  112. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
  114. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
  115. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +499 -293
  116. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
  117. data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
  118. data/lib/active_record/connection_adapters/postgresql_adapter.rb +595 -382
  119. data/lib/active_record/connection_adapters/schema_cache.rb +191 -29
  120. data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
  121. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
  122. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  123. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +21 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  126. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  127. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
  128. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +322 -389
  129. data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
  130. data/lib/active_record/connection_adapters.rb +52 -0
  131. data/lib/active_record/connection_handling.rb +314 -41
  132. data/lib/active_record/core.rb +488 -243
  133. data/lib/active_record/counter_cache.rb +71 -50
  134. data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
  135. data/lib/active_record/database_configurations/database_config.rb +80 -0
  136. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  137. data/lib/active_record/database_configurations/url_config.rb +53 -0
  138. data/lib/active_record/database_configurations.rb +273 -0
  139. data/lib/active_record/delegated_type.rb +209 -0
  140. data/lib/active_record/destroy_association_async_job.rb +36 -0
  141. data/lib/active_record/dynamic_matchers.rb +87 -106
  142. data/lib/active_record/enum.rb +212 -94
  143. data/lib/active_record/errors.rb +225 -54
  144. data/lib/active_record/explain.rb +27 -11
  145. data/lib/active_record/explain_registry.rb +4 -2
  146. data/lib/active_record/explain_subscriber.rb +11 -6
  147. data/lib/active_record/fixture_set/file.rb +33 -14
  148. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  149. data/lib/active_record/fixture_set/render_context.rb +17 -0
  150. data/lib/active_record/fixture_set/table_row.rb +152 -0
  151. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  152. data/lib/active_record/fixtures.rb +273 -496
  153. data/lib/active_record/gem_version.rb +6 -4
  154. data/lib/active_record/inheritance.rb +175 -110
  155. data/lib/active_record/insert_all.rb +212 -0
  156. data/lib/active_record/integration.rb +121 -29
  157. data/lib/active_record/internal_metadata.rb +64 -0
  158. data/lib/active_record/legacy_yaml_adapter.rb +52 -0
  159. data/lib/active_record/locale/en.yml +3 -2
  160. data/lib/active_record/locking/optimistic.rb +103 -95
  161. data/lib/active_record/locking/pessimistic.rb +22 -6
  162. data/lib/active_record/log_subscriber.rb +93 -31
  163. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  164. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  165. data/lib/active_record/middleware/database_selector.rb +77 -0
  166. data/lib/active_record/migration/command_recorder.rb +185 -90
  167. data/lib/active_record/migration/compatibility.rb +298 -0
  168. data/lib/active_record/migration/join_table.rb +8 -7
  169. data/lib/active_record/migration.rb +685 -309
  170. data/lib/active_record/model_schema.rb +420 -113
  171. data/lib/active_record/nested_attributes.rb +265 -216
  172. data/lib/active_record/no_touching.rb +15 -2
  173. data/lib/active_record/null_relation.rb +24 -38
  174. data/lib/active_record/persistence.rb +574 -135
  175. data/lib/active_record/query_cache.rb +29 -23
  176. data/lib/active_record/querying.rb +50 -31
  177. data/lib/active_record/railtie.rb +175 -54
  178. data/lib/active_record/railties/console_sandbox.rb +3 -3
  179. data/lib/active_record/railties/controller_runtime.rb +34 -33
  180. data/lib/active_record/railties/databases.rake +533 -216
  181. data/lib/active_record/readonly_attributes.rb +9 -4
  182. data/lib/active_record/reflection.rb +485 -310
  183. data/lib/active_record/relation/batches/batch_enumerator.rb +85 -0
  184. data/lib/active_record/relation/batches.rb +217 -59
  185. data/lib/active_record/relation/calculations.rb +326 -244
  186. data/lib/active_record/relation/delegation.rb +76 -84
  187. data/lib/active_record/relation/finder_methods.rb +318 -256
  188. data/lib/active_record/relation/from_clause.rb +30 -0
  189. data/lib/active_record/relation/merger.rb +99 -84
  190. data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -25
  191. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
  192. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  193. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +57 -0
  194. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  195. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  196. data/lib/active_record/relation/predicate_builder.rb +139 -96
  197. data/lib/active_record/relation/query_attribute.rb +50 -0
  198. data/lib/active_record/relation/query_methods.rb +757 -409
  199. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  200. data/lib/active_record/relation/spawn_methods.rb +23 -21
  201. data/lib/active_record/relation/where_clause.rb +239 -0
  202. data/lib/active_record/relation.rb +554 -342
  203. data/lib/active_record/result.rb +91 -47
  204. data/lib/active_record/runtime_registry.rb +6 -4
  205. data/lib/active_record/sanitization.rb +134 -122
  206. data/lib/active_record/schema.rb +21 -24
  207. data/lib/active_record/schema_dumper.rb +141 -92
  208. data/lib/active_record/schema_migration.rb +24 -26
  209. data/lib/active_record/scoping/default.rb +96 -82
  210. data/lib/active_record/scoping/named.rb +78 -36
  211. data/lib/active_record/scoping.rb +45 -27
  212. data/lib/active_record/secure_token.rb +48 -0
  213. data/lib/active_record/serialization.rb +8 -6
  214. data/lib/active_record/signed_id.rb +116 -0
  215. data/lib/active_record/statement_cache.rb +89 -36
  216. data/lib/active_record/store.rb +133 -43
  217. data/lib/active_record/suppressor.rb +61 -0
  218. data/lib/active_record/table_metadata.rb +81 -0
  219. data/lib/active_record/tasks/database_tasks.rb +366 -129
  220. data/lib/active_record/tasks/mysql_database_tasks.rb +68 -100
  221. data/lib/active_record/tasks/postgresql_database_tasks.rb +87 -39
  222. data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -19
  223. data/lib/active_record/test_databases.rb +24 -0
  224. data/lib/active_record/test_fixtures.rb +291 -0
  225. data/lib/active_record/timestamp.rb +86 -43
  226. data/lib/active_record/touch_later.rb +65 -0
  227. data/lib/active_record/transactions.rb +181 -152
  228. data/lib/active_record/translation.rb +3 -1
  229. data/lib/active_record/type/adapter_specific_registry.rb +126 -0
  230. data/lib/active_record/type/date.rb +4 -41
  231. data/lib/active_record/type/date_time.rb +4 -38
  232. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  233. data/lib/active_record/type/hash_lookup_type_map.rb +12 -5
  234. data/lib/active_record/type/internal/timezone.rb +17 -0
  235. data/lib/active_record/type/json.rb +30 -0
  236. data/lib/active_record/type/serialized.rb +33 -15
  237. data/lib/active_record/type/text.rb +2 -2
  238. data/lib/active_record/type/time.rb +21 -16
  239. data/lib/active_record/type/type_map.rb +16 -19
  240. data/lib/active_record/type/unsigned_integer.rb +9 -8
  241. data/lib/active_record/type.rb +84 -23
  242. data/lib/active_record/type_caster/connection.rb +33 -0
  243. data/lib/active_record/type_caster/map.rb +23 -0
  244. data/lib/active_record/type_caster.rb +9 -0
  245. data/lib/active_record/validations/absence.rb +25 -0
  246. data/lib/active_record/validations/associated.rb +12 -4
  247. data/lib/active_record/validations/length.rb +26 -0
  248. data/lib/active_record/validations/numericality.rb +35 -0
  249. data/lib/active_record/validations/presence.rb +14 -13
  250. data/lib/active_record/validations/uniqueness.rb +65 -48
  251. data/lib/active_record/validations.rb +39 -35
  252. data/lib/active_record/version.rb +3 -1
  253. data/lib/active_record.rb +44 -28
  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/and.rb +32 -0
  269. data/lib/arel/nodes/ascending.rb +23 -0
  270. data/lib/arel/nodes/binary.rb +126 -0
  271. data/lib/arel/nodes/bind_param.rb +44 -0
  272. data/lib/arel/nodes/case.rb +55 -0
  273. data/lib/arel/nodes/casted.rb +62 -0
  274. data/lib/arel/nodes/comment.rb +29 -0
  275. data/lib/arel/nodes/count.rb +12 -0
  276. data/lib/arel/nodes/delete_statement.rb +45 -0
  277. data/lib/arel/nodes/descending.rb +23 -0
  278. data/lib/arel/nodes/equality.rb +15 -0
  279. data/lib/arel/nodes/extract.rb +24 -0
  280. data/lib/arel/nodes/false.rb +16 -0
  281. data/lib/arel/nodes/full_outer_join.rb +8 -0
  282. data/lib/arel/nodes/function.rb +44 -0
  283. data/lib/arel/nodes/grouping.rb +11 -0
  284. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  285. data/lib/arel/nodes/in.rb +15 -0
  286. data/lib/arel/nodes/infix_operation.rb +92 -0
  287. data/lib/arel/nodes/inner_join.rb +8 -0
  288. data/lib/arel/nodes/insert_statement.rb +37 -0
  289. data/lib/arel/nodes/join_source.rb +20 -0
  290. data/lib/arel/nodes/matches.rb +18 -0
  291. data/lib/arel/nodes/named_function.rb +23 -0
  292. data/lib/arel/nodes/node.rb +51 -0
  293. data/lib/arel/nodes/node_expression.rb +13 -0
  294. data/lib/arel/nodes/ordering.rb +27 -0
  295. data/lib/arel/nodes/outer_join.rb +8 -0
  296. data/lib/arel/nodes/over.rb +15 -0
  297. data/lib/arel/nodes/regexp.rb +16 -0
  298. data/lib/arel/nodes/right_outer_join.rb +8 -0
  299. data/lib/arel/nodes/select_core.rb +67 -0
  300. data/lib/arel/nodes/select_statement.rb +41 -0
  301. data/lib/arel/nodes/sql_literal.rb +19 -0
  302. data/lib/arel/nodes/string_join.rb +11 -0
  303. data/lib/arel/nodes/table_alias.rb +31 -0
  304. data/lib/arel/nodes/terminal.rb +16 -0
  305. data/lib/arel/nodes/true.rb +16 -0
  306. data/lib/arel/nodes/unary.rb +44 -0
  307. data/lib/arel/nodes/unary_operation.rb +20 -0
  308. data/lib/arel/nodes/unqualified_column.rb +22 -0
  309. data/lib/arel/nodes/update_statement.rb +41 -0
  310. data/lib/arel/nodes/values_list.rb +9 -0
  311. data/lib/arel/nodes/window.rb +126 -0
  312. data/lib/arel/nodes/with.rb +11 -0
  313. data/lib/arel/nodes.rb +70 -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/dot.rb +308 -0
  321. data/lib/arel/visitors/mysql.rb +93 -0
  322. data/lib/arel/visitors/postgresql.rb +120 -0
  323. data/lib/arel/visitors/sqlite.rb +38 -0
  324. data/lib/arel/visitors/to_sql.rb +899 -0
  325. data/lib/arel/visitors/visitor.rb +45 -0
  326. data/lib/arel/visitors.rb +13 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/arel.rb +54 -0
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  330. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  331. data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -37
  332. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +26 -0
  333. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +13 -10
  334. data/lib/rails/generators/active_record/migration.rb +35 -1
  335. data/lib/rails/generators/active_record/model/model_generator.rb +55 -22
  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.tt +22 -0
  338. data/lib/rails/generators/active_record.rb +7 -5
  339. metadata +175 -65
  340. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  341. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  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 -23
  345. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  346. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  347. data/lib/active_record/attribute.rb +0 -149
  348. data/lib/active_record/attribute_decorators.rb +0 -66
  349. data/lib/active_record/attribute_set/builder.rb +0 -86
  350. data/lib/active_record/attribute_set.rb +0 -77
  351. data/lib/active_record/connection_adapters/connection_specification.rb +0 -275
  352. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  353. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  354. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  355. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  356. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  357. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  358. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  359. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  360. data/lib/active_record/type/big_integer.rb +0 -13
  361. data/lib/active_record/type/binary.rb +0 -50
  362. data/lib/active_record/type/boolean.rb +0 -30
  363. data/lib/active_record/type/decimal.rb +0 -40
  364. data/lib/active_record/type/decorator.rb +0 -14
  365. data/lib/active_record/type/float.rb +0 -19
  366. data/lib/active_record/type/integer.rb +0 -55
  367. data/lib/active_record/type/mutable.rb +0 -16
  368. data/lib/active_record/type/numeric.rb +0 -36
  369. data/lib/active_record/type/string.rb +0 -36
  370. data/lib/active_record/type/time_value.rb +0 -38
  371. data/lib/active_record/type/value.rb +0 -101
  372. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -22
  373. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
  374. /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,16 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "concurrent/map"
4
+
1
5
  module ActiveRecord
2
6
  module ConnectionAdapters # :nodoc:
3
7
  module QueryCache
4
8
  class << self
5
9
  def included(base) #:nodoc:
6
- dirties_query_cache base, :insert, :update, :delete
10
+ dirties_query_cache base, :create, :insert, :update, :delete, :truncate, :truncate_tables,
11
+ :rollback_to_savepoint, :rollback_db_transaction, :exec_insert_all
12
+
13
+ base.set_callback :checkout, :after, :configure_query_cache!
14
+ base.set_callback :checkin, :after, :disable_query_cache!
7
15
  end
8
16
 
9
17
  def dirties_query_cache(base, *method_names)
10
18
  method_names.each do |method_name|
11
19
  base.class_eval <<-end_code, __FILE__, __LINE__ + 1
12
20
  def #{method_name}(*)
13
- clear_query_cache if @query_cache_enabled
21
+ ActiveRecord::Base.clear_query_caches_for_current_thread
14
22
  super
15
23
  end
16
24
  end_code
@@ -18,11 +26,32 @@ module ActiveRecord
18
26
  end
19
27
  end
20
28
 
29
+ module ConnectionPoolConfiguration
30
+ def initialize(*)
31
+ super
32
+ @query_cache_enabled = Concurrent::Map.new { false }
33
+ end
34
+
35
+ def enable_query_cache!
36
+ @query_cache_enabled[connection_cache_key(current_thread)] = true
37
+ connection.enable_query_cache! if active_connection?
38
+ end
39
+
40
+ def disable_query_cache!
41
+ @query_cache_enabled.delete connection_cache_key(current_thread)
42
+ connection.disable_query_cache! if active_connection?
43
+ end
44
+
45
+ def query_cache_enabled
46
+ @query_cache_enabled[connection_cache_key(current_thread)]
47
+ end
48
+ end
49
+
21
50
  attr_reader :query_cache, :query_cache_enabled
22
51
 
23
52
  def initialize(*)
24
53
  super
25
- @query_cache = Hash.new { |h,sql| h[sql] = {} }
54
+ @query_cache = Hash.new { |h, sql| h[sql] = {} }
26
55
  @query_cache_enabled = false
27
56
  end
28
57
 
@@ -41,6 +70,7 @@ module ActiveRecord
41
70
 
42
71
  def disable_query_cache!
43
72
  @query_cache_enabled = false
73
+ clear_query_cache
44
74
  end
45
75
 
46
76
  # Disable the query cache within the block.
@@ -58,38 +88,62 @@ module ActiveRecord
58
88
  # the same SQL query and repeatedly return the same result each time, silently
59
89
  # undermining the randomness you were expecting.
60
90
  def clear_query_cache
61
- @query_cache.clear
91
+ @lock.synchronize do
92
+ @query_cache.clear
93
+ end
62
94
  end
63
95
 
64
- def select_all(arel, name = nil, binds = [])
96
+ def select_all(arel, name = nil, binds = [], preparable: nil)
65
97
  if @query_cache_enabled && !locked?(arel)
66
- arel, binds = binds_from_relation arel, binds
67
- sql = to_sql(arel, binds)
68
- cache_sql(sql, binds) { super(sql, name, binds) }
98
+ arel = arel_from_relation(arel)
99
+ sql, binds, preparable = to_sql_and_binds(arel, binds, preparable)
100
+
101
+ cache_sql(sql, name, binds) { super(sql, name, binds, preparable: preparable) }
69
102
  else
70
103
  super
71
104
  end
72
105
  end
73
106
 
74
107
  private
75
-
76
- def cache_sql(sql, binds)
77
- result =
78
- if @query_cache[sql].key?(binds)
79
- ActiveSupport::Notifications.instrument("sql.active_record",
80
- :sql => sql, :binds => binds, :name => "CACHE", :connection_id => object_id)
81
- @query_cache[sql][binds]
82
- else
83
- @query_cache[sql][binds] = yield
108
+ def cache_sql(sql, name, binds)
109
+ @lock.synchronize do
110
+ result =
111
+ if @query_cache[sql].key?(binds)
112
+ ActiveSupport::Notifications.instrument(
113
+ "sql.active_record",
114
+ cache_notification_info(sql, name, binds)
115
+ )
116
+ @query_cache[sql][binds]
117
+ else
118
+ @query_cache[sql][binds] = yield
119
+ end
120
+ result.dup
84
121
  end
85
- result.dup
86
- end
122
+ end
87
123
 
88
- # If arel is locked this is a SELECT ... FOR UPDATE or somesuch. Such
89
- # queries should not be cached.
90
- def locked?(arel)
91
- arel.respond_to?(:locked) && arel.locked
92
- end
124
+ # Database adapters can override this method to
125
+ # provide custom cache information.
126
+ def cache_notification_info(sql, name, binds)
127
+ {
128
+ sql: sql,
129
+ binds: binds,
130
+ type_casted_binds: -> { type_casted_binds(binds) },
131
+ name: name,
132
+ connection: self,
133
+ cached: true
134
+ }
135
+ end
136
+
137
+ # If arel is locked this is a SELECT ... FOR UPDATE or somesuch. Such
138
+ # queries should not be cached.
139
+ def locked?(arel)
140
+ arel = arel.arel if arel.is_a?(Relation)
141
+ arel.respond_to?(:locked) && arel.locked
142
+ end
143
+
144
+ def configure_query_cache!
145
+ enable_query_cache! if pool.query_cache_enabled
146
+ end
93
147
  end
94
148
  end
95
149
  end
@@ -1,16 +1,20 @@
1
- require 'active_support/core_ext/big_decimal/conversions'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/big_decimal/conversions"
4
+ require "active_support/multibyte/chars"
2
5
 
3
6
  module ActiveRecord
4
7
  module ConnectionAdapters # :nodoc:
5
8
  module Quoting
6
9
  # Quotes the column value to help prevent
7
- # {SQL injection attacks}[http://en.wikipedia.org/wiki/SQL_injection].
8
- def quote(value, column = nil)
9
- # records are quoted as their primary key
10
- return value.quoted_id if value.respond_to?(:quoted_id)
11
-
12
- if column
13
- value = column.cast_type.type_cast_for_database(value)
10
+ # {SQL injection attacks}[https://en.wikipedia.org/wiki/SQL_injection].
11
+ def quote(value)
12
+ if value.is_a?(Base)
13
+ ActiveSupport::Deprecation.warn(<<~MSG)
14
+ Passing an Active Record object to `quote` directly is deprecated
15
+ and will be no longer quoted as id value in Rails 7.0.
16
+ MSG
17
+ value = value.id_for_database
14
18
  end
15
19
 
16
20
  _quote(value)
@@ -19,30 +23,48 @@ module ActiveRecord
19
23
  # Cast a +value+ to a type that the database understands. For example,
20
24
  # SQLite does not understand dates, so this method will convert a Date
21
25
  # to a String.
22
- def type_cast(value, column)
23
- if value.respond_to?(:quoted_id) && value.respond_to?(:id)
24
- return value.id
26
+ def type_cast(value, column = nil)
27
+ if value.is_a?(Base)
28
+ ActiveSupport::Deprecation.warn(<<~MSG)
29
+ Passing an Active Record object to `type_cast` directly is deprecated
30
+ and will be no longer type casted as id value in Rails 7.0.
31
+ MSG
32
+ value = value.id_for_database
25
33
  end
26
34
 
27
35
  if column
28
- value = column.cast_type.type_cast_for_database(value)
36
+ ActiveSupport::Deprecation.warn(<<~MSG)
37
+ Passing a column to `type_cast` is deprecated and will be removed in Rails 7.0.
38
+ MSG
39
+ type = lookup_cast_type_from_column(column)
40
+ value = type.serialize(value)
29
41
  end
30
42
 
31
43
  _type_cast(value)
32
- rescue TypeError
33
- to_type = column ? " to #{column.type}" : ""
34
- raise TypeError, "can't cast #{value.class}#{to_type}"
44
+ end
45
+
46
+ # If you are having to call this function, you are likely doing something
47
+ # wrong. The column does not have sufficient type information if the user
48
+ # provided a custom type on the class level either explicitly (via
49
+ # Attributes::ClassMethods#attribute) or implicitly (via
50
+ # AttributeMethods::Serialization::ClassMethods#serialize, +time_zone_aware_attributes+).
51
+ # In almost all cases, the sql type should only be used to change quoting behavior, when the primitive to
52
+ # represent the type doesn't sufficiently reflect the differences
53
+ # (varchar vs binary) for example. The type used to get this primitive
54
+ # should have been provided before reaching the connection adapter.
55
+ def lookup_cast_type_from_column(column) # :nodoc:
56
+ lookup_cast_type(column.sql_type)
35
57
  end
36
58
 
37
59
  # Quotes a string, escaping any ' (single quote) and \ (backslash)
38
60
  # characters.
39
61
  def quote_string(s)
40
- s.gsub(/\\/, '\&\&').gsub(/'/, "''") # ' (for ruby-mode)
62
+ s.gsub('\\', '\&\&').gsub("'", "''") # ' (for ruby-mode)
41
63
  end
42
64
 
43
65
  # Quotes the column name. Defaults to no quoting.
44
66
  def quote_column_name(column_name)
45
- column_name
67
+ column_name.to_s
46
68
  end
47
69
 
48
70
  # Quotes the table name. Defaults to column name quoting.
@@ -53,7 +75,7 @@ module ActiveRecord
53
75
  # Override to return the quoted table name for assignment. Defaults to
54
76
  # table quoting.
55
77
  #
56
- # This works for mysql and mysql2 where table.column can be used to
78
+ # This works for mysql2 where table.column can be used to
57
79
  # resolve ambiguity.
58
80
  #
59
81
  # We override this in the sqlite3 and postgresql adapters to use only
@@ -62,72 +84,177 @@ module ActiveRecord
62
84
  quote_table_name("#{table}.#{attr}")
63
85
  end
64
86
 
87
+ def quote_default_expression(value, column) # :nodoc:
88
+ if value.is_a?(Proc)
89
+ value.call
90
+ else
91
+ value = lookup_cast_type(column.sql_type).serialize(value)
92
+ quote(value)
93
+ end
94
+ end
95
+
65
96
  def quoted_true
66
- "'t'"
97
+ "TRUE"
67
98
  end
68
99
 
69
100
  def unquoted_true
70
- 't'
101
+ true
71
102
  end
72
103
 
73
104
  def quoted_false
74
- "'f'"
105
+ "FALSE"
75
106
  end
76
107
 
77
108
  def unquoted_false
78
- 'f'
109
+ false
79
110
  end
80
111
 
112
+ # Quote date/time values for use in SQL input. Includes microseconds
113
+ # if the value is a Time responding to usec.
81
114
  def quoted_date(value)
82
115
  if value.acts_like?(:time)
83
- zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
84
-
85
- if value.respond_to?(zone_conversion_method)
86
- value = value.send(zone_conversion_method)
116
+ if ActiveRecord::Base.default_timezone == :utc
117
+ value = value.getutc if value.respond_to?(:getutc) && !value.utc?
118
+ else
119
+ value = value.getlocal if value.respond_to?(:getlocal)
87
120
  end
88
121
  end
89
122
 
90
- value.to_s(:db)
123
+ result = value.to_s(:db)
124
+ if value.respond_to?(:usec) && value.usec > 0
125
+ result << "." << sprintf("%06d", value.usec)
126
+ else
127
+ result
128
+ end
129
+ end
130
+
131
+ def quoted_time(value) # :nodoc:
132
+ value = value.change(year: 2000, month: 1, day: 1)
133
+ quoted_date(value).sub(/\A\d\d\d\d-\d\d-\d\d /, "")
134
+ end
135
+
136
+ def quoted_binary(value) # :nodoc:
137
+ "'#{quote_string(value.to_s)}'"
138
+ end
139
+
140
+ def sanitize_as_sql_comment(value) # :nodoc:
141
+ # Sanitize a string to appear within a SQL comment
142
+ # For compatibility, this also surrounding "/*+", "/*", and "*/"
143
+ # charcacters, possibly with single surrounding space.
144
+ # Then follows that by replacing any internal "*/" or "/ *" with
145
+ # "* /" or "/ *"
146
+ comment = value.to_s.dup
147
+ comment.gsub!(%r{\A\s*/\*\+?\s?|\s?\*/\s*\Z}, "")
148
+ comment.gsub!("*/", "* /")
149
+ comment.gsub!("/*", "/ *")
150
+ comment
91
151
  end
92
152
 
153
+ def column_name_matcher # :nodoc:
154
+ COLUMN_NAME
155
+ end
156
+
157
+ def column_name_with_order_matcher # :nodoc:
158
+ COLUMN_NAME_WITH_ORDER
159
+ end
160
+
161
+ # Regexp for column names (with or without a table name prefix).
162
+ # Matches the following:
163
+ #
164
+ # "#{table_name}.#{column_name}"
165
+ # "#{column_name}"
166
+ COLUMN_NAME = /
167
+ \A
168
+ (
169
+ (?:
170
+ # table_name.column_name | function(one or no argument)
171
+ ((?:\w+\.)?\w+) | \w+\((?:|\g<2>)\)
172
+ )
173
+ (?:(?:\s+AS)?\s+\w+)?
174
+ )
175
+ (?:\s*,\s*\g<1>)*
176
+ \z
177
+ /ix
178
+
179
+ # Regexp for column names with order (with or without a table name prefix,
180
+ # with or without various order modifiers). Matches the following:
181
+ #
182
+ # "#{table_name}.#{column_name}"
183
+ # "#{table_name}.#{column_name} #{direction}"
184
+ # "#{table_name}.#{column_name} #{direction} NULLS FIRST"
185
+ # "#{table_name}.#{column_name} NULLS LAST"
186
+ # "#{column_name}"
187
+ # "#{column_name} #{direction}"
188
+ # "#{column_name} #{direction} NULLS FIRST"
189
+ # "#{column_name} NULLS LAST"
190
+ COLUMN_NAME_WITH_ORDER = /
191
+ \A
192
+ (
193
+ (?:
194
+ # table_name.column_name | function(one or no argument)
195
+ ((?:\w+\.)?\w+) | \w+\((?:|\g<2>)\)
196
+ )
197
+ (?:\s+ASC|\s+DESC)?
198
+ (?:\s+NULLS\s+(?:FIRST|LAST))?
199
+ )
200
+ (?:\s*,\s*\g<1>)*
201
+ \z
202
+ /ix
203
+
204
+ private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
205
+
93
206
  private
207
+ def type_casted_binds(binds)
208
+ case binds.first
209
+ when Array
210
+ binds.map { |column, value| type_cast(value, column) }
211
+ else
212
+ binds.map do |value|
213
+ if ActiveModel::Attribute === value
214
+ type_cast(value.value_for_database)
215
+ else
216
+ type_cast(value)
217
+ end
218
+ end
219
+ end
220
+ end
94
221
 
95
- def types_which_need_no_typecasting
96
- [nil, Numeric, String]
97
- end
98
-
99
- def _quote(value)
100
- case value
101
- when String, ActiveSupport::Multibyte::Chars, Type::Binary::Data
102
- "'#{quote_string(value.to_s)}'"
103
- when true then quoted_true
104
- when false then quoted_false
105
- when nil then "NULL"
106
- # BigDecimals need to be put in a non-normalized form and quoted.
107
- when BigDecimal then value.to_s('F')
108
- when Numeric, ActiveSupport::Duration then value.to_s
109
- when Date, Time then "'#{quoted_date(value)}'"
110
- when Symbol then "'#{quote_string(value.to_s)}'"
111
- when Class then "'#{value}'"
112
- else
113
- "'#{quote_string(YAML.dump(value))}'"
222
+ def lookup_cast_type(sql_type)
223
+ type_map.lookup(sql_type)
114
224
  end
115
- end
116
225
 
117
- def _type_cast(value)
118
- case value
119
- when Symbol, ActiveSupport::Multibyte::Chars, Type::Binary::Data
120
- value.to_s
121
- when true then unquoted_true
122
- when false then unquoted_false
123
- # BigDecimals need to be put in a non-normalized form and quoted.
124
- when BigDecimal then value.to_s('F')
125
- when Date, Time then quoted_date(value)
126
- when *types_which_need_no_typecasting
127
- value
128
- else raise TypeError
226
+ def _quote(value)
227
+ case value
228
+ when String, Symbol, ActiveSupport::Multibyte::Chars
229
+ "'#{quote_string(value.to_s)}'"
230
+ when true then quoted_true
231
+ when false then quoted_false
232
+ when nil then "NULL"
233
+ # BigDecimals need to be put in a non-normalized form and quoted.
234
+ when BigDecimal then value.to_s("F")
235
+ when Numeric, ActiveSupport::Duration then value.to_s
236
+ when Type::Binary::Data then quoted_binary(value)
237
+ when Type::Time::Value then "'#{quoted_time(value)}'"
238
+ when Date, Time then "'#{quoted_date(value)}'"
239
+ when Class then "'#{value}'"
240
+ else raise TypeError, "can't quote #{value.class.name}"
241
+ end
242
+ end
243
+
244
+ def _type_cast(value)
245
+ case value
246
+ when Symbol, ActiveSupport::Multibyte::Chars, Type::Binary::Data
247
+ value.to_s
248
+ when true then unquoted_true
249
+ when false then unquoted_false
250
+ # BigDecimals need to be put in a non-normalized form and quoted.
251
+ when BigDecimal then value.to_s("F")
252
+ when nil, Numeric, String then value
253
+ when Type::Time::Value then quoted_time(value)
254
+ when Date, Time then quoted_date(value)
255
+ else raise TypeError, "can't cast #{value.class.name}"
256
+ end
129
257
  end
130
- end
131
258
  end
132
259
  end
133
260
  end
@@ -1,20 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
- module Savepoints #:nodoc:
4
- def supports_savepoints?
5
- true
5
+ module Savepoints
6
+ def current_savepoint_name
7
+ current_transaction.savepoint_name
6
8
  end
7
9
 
8
10
  def create_savepoint(name = current_savepoint_name)
9
- execute("SAVEPOINT #{name}")
11
+ execute("SAVEPOINT #{name}", "TRANSACTION")
10
12
  end
11
13
 
12
- def rollback_to_savepoint(name = current_savepoint_name)
13
- execute("ROLLBACK TO SAVEPOINT #{name}")
14
+ def exec_rollback_to_savepoint(name = current_savepoint_name)
15
+ execute("ROLLBACK TO SAVEPOINT #{name}", "TRANSACTION")
14
16
  end
15
17
 
16
18
  def release_savepoint(name = current_savepoint_name)
17
- execute("RELEASE SAVEPOINT #{name}")
19
+ execute("RELEASE SAVEPOINT #{name}", "TRANSACTION")
18
20
  end
19
21
  end
20
22
  end