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,53 +1,87 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module MySQL
4
- module ColumnDumper
5
- def column_spec_for_primary_key(column)
6
- if column.bigint?
7
- spec = { id: :bigint.inspect }
8
- spec[:default] = schema_default(column) || 'nil' unless column.auto_increment?
9
- else
6
+ class SchemaDumper < ConnectionAdapters::SchemaDumper # :nodoc:
7
+ private
8
+ def prepare_column_options(column)
9
+ spec = super
10
+ spec[:unsigned] = "true" if column.unsigned?
11
+ spec[:auto_increment] = "true" if column.auto_increment?
12
+
13
+ if /\A(?<size>tiny|medium|long)(?:text|blob)/ =~ column.sql_type
14
+ spec = { size: size.to_sym.inspect }.merge!(spec)
15
+ end
16
+
17
+ if @connection.supports_virtual_columns? && column.virtual?
18
+ spec[:as] = extract_expression_for_virtual_column(column)
19
+ spec[:stored] = "true" if /\b(?:STORED|PERSISTENT)\b/.match?(column.extra)
20
+ spec = { type: schema_type(column).inspect }.merge!(spec)
21
+ end
22
+
23
+ spec
24
+ end
25
+
26
+ def column_spec_for_primary_key(column)
10
27
  spec = super
28
+ spec.delete(:auto_increment) if column.type == :integer && column.auto_increment?
29
+ spec
11
30
  end
12
- spec[:unsigned] = 'true' if column.unsigned?
13
- spec
14
- end
15
31
 
16
- def prepare_column_options(column)
17
- spec = super
18
- spec[:unsigned] = 'true' if column.unsigned?
19
- spec
20
- end
32
+ def default_primary_key?(column)
33
+ super && column.auto_increment? && !column.unsigned?
34
+ end
21
35
 
22
- def migration_keys
23
- super + [:unsigned]
24
- end
36
+ def explicit_primary_key_default?(column)
37
+ column.type == :integer && !column.auto_increment?
38
+ end
25
39
 
26
- private
40
+ def schema_type(column)
41
+ case column.sql_type
42
+ when /\Atimestamp\b/
43
+ :timestamp
44
+ when /\A(?:enum|set)\b/
45
+ column.sql_type
46
+ else
47
+ super
48
+ end
49
+ end
27
50
 
28
- def default_primary_key?(column)
29
- super && column.auto_increment?
30
- end
51
+ def schema_limit(column)
52
+ super unless /\A(?:tiny|medium|long)?(?:text|blob)\b/.match?(column.sql_type)
53
+ end
31
54
 
32
- def schema_type(column)
33
- if column.sql_type == 'tinyblob'
34
- :blob
35
- else
36
- super
55
+ def schema_precision(column)
56
+ super unless /\A(?:date)?time(?:stamp)?\b/.match?(column.sql_type) && column.precision == 0
37
57
  end
38
- end
39
58
 
40
- def schema_precision(column)
41
- super unless /time/ === column.sql_type && column.precision == 0
42
- end
59
+ def schema_collation(column)
60
+ if column.collation
61
+ @table_collation_cache ||= {}
62
+ @table_collation_cache[table_name] ||=
63
+ @connection.exec_query("SHOW TABLE STATUS LIKE #{@connection.quote(table_name)}", "SCHEMA").first["Collation"]
64
+ column.collation.inspect if column.collation != @table_collation_cache[table_name]
65
+ end
66
+ end
43
67
 
44
- def schema_collation(column)
45
- if column.collation && table_name = column.table_name
46
- @table_collation_cache ||= {}
47
- @table_collation_cache[table_name] ||= select_one("SHOW TABLE STATUS LIKE '#{table_name}'")["Collation"]
48
- column.collation.inspect if column.collation != @table_collation_cache[table_name]
68
+ def extract_expression_for_virtual_column(column)
69
+ if @connection.mariadb? && @connection.database_version < "10.2.5"
70
+ create_table_info = @connection.send(:create_table_info, table_name)
71
+ column_name = @connection.quote_column_name(column.name)
72
+ if %r/#{column_name} #{Regexp.quote(column.sql_type)}(?: COLLATE \w+)? AS \((?<expression>.+?)\) #{column.extra}/ =~ create_table_info
73
+ $~[:expression].inspect
74
+ end
75
+ else
76
+ scope = @connection.send(:quoted_scope, table_name)
77
+ column_name = @connection.quote(column.name)
78
+ sql = "SELECT generation_expression FROM information_schema.columns" \
79
+ " WHERE table_schema = #{scope[:schema]}" \
80
+ " AND table_name = #{scope[:name]}" \
81
+ " AND column_name = #{column_name}"
82
+ @connection.query_value(sql, "SCHEMA").inspect
83
+ end
49
84
  end
50
- end
51
85
  end
52
86
  end
53
87
  end
@@ -0,0 +1,268 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ module MySQL
6
+ module SchemaStatements # :nodoc:
7
+ # Returns an array of indexes for the given table.
8
+ def indexes(table_name)
9
+ indexes = []
10
+ current_index = nil
11
+ execute_and_free("SHOW KEYS FROM #{quote_table_name(table_name)}", "SCHEMA") do |result|
12
+ each_hash(result) do |row|
13
+ if current_index != row[:Key_name]
14
+ next if row[:Key_name] == "PRIMARY" # skip the primary key
15
+ current_index = row[:Key_name]
16
+
17
+ mysql_index_type = row[:Index_type].downcase.to_sym
18
+ case mysql_index_type
19
+ when :fulltext, :spatial
20
+ index_type = mysql_index_type
21
+ when :btree, :hash
22
+ index_using = mysql_index_type
23
+ end
24
+
25
+ indexes << [
26
+ row[:Table],
27
+ row[:Key_name],
28
+ row[:Non_unique].to_i == 0,
29
+ [],
30
+ lengths: {},
31
+ orders: {},
32
+ type: index_type,
33
+ using: index_using,
34
+ comment: row[:Index_comment].presence
35
+ ]
36
+ end
37
+
38
+ if row[:Expression]
39
+ expression = row[:Expression]
40
+ expression = +"(#{expression})" unless expression.start_with?("(")
41
+ indexes.last[-2] << expression
42
+ indexes.last[-1][:expressions] ||= {}
43
+ indexes.last[-1][:expressions][expression] = expression
44
+ indexes.last[-1][:orders][expression] = :desc if row[:Collation] == "D"
45
+ else
46
+ indexes.last[-2] << row[:Column_name]
47
+ indexes.last[-1][:lengths][row[:Column_name]] = row[:Sub_part].to_i if row[:Sub_part]
48
+ indexes.last[-1][:orders][row[:Column_name]] = :desc if row[:Collation] == "D"
49
+ end
50
+ end
51
+ end
52
+
53
+ indexes.map do |index|
54
+ options = index.pop
55
+
56
+ if expressions = options.delete(:expressions)
57
+ orders = options.delete(:orders)
58
+ lengths = options.delete(:lengths)
59
+
60
+ columns = index[-1].map { |name|
61
+ [ name.to_sym, expressions[name] || +quote_column_name(name) ]
62
+ }.to_h
63
+
64
+ index[-1] = add_options_for_index_columns(
65
+ columns, order: orders, length: lengths
66
+ ).values.join(", ")
67
+ end
68
+
69
+ IndexDefinition.new(*index, **options)
70
+ end
71
+ end
72
+
73
+ def remove_column(table_name, column_name, type = nil, **options)
74
+ if foreign_key_exists?(table_name, column: column_name)
75
+ remove_foreign_key(table_name, column: column_name)
76
+ end
77
+ super
78
+ end
79
+
80
+ def create_table(table_name, options: default_row_format, **)
81
+ super
82
+ end
83
+
84
+ def internal_string_options_for_primary_key
85
+ super.tap do |options|
86
+ if !row_format_dynamic_by_default? && CHARSETS_OF_4BYTES_MAXLEN.include?(charset)
87
+ options[:collation] = collation.sub(/\A[^_]+/, "utf8")
88
+ end
89
+ end
90
+ end
91
+
92
+ def update_table_definition(table_name, base)
93
+ MySQL::Table.new(table_name, base)
94
+ end
95
+
96
+ def create_schema_dumper(options)
97
+ MySQL::SchemaDumper.create(self, options)
98
+ end
99
+
100
+ # Maps logical Rails types to MySQL-specific data types.
101
+ def type_to_sql(type, limit: nil, precision: nil, scale: nil, size: limit_to_size(limit, type), unsigned: nil, **)
102
+ sql =
103
+ case type.to_s
104
+ when "integer"
105
+ integer_to_sql(limit)
106
+ when "text"
107
+ type_with_size_to_sql("text", size)
108
+ when "blob"
109
+ type_with_size_to_sql("blob", size)
110
+ when "binary"
111
+ if (0..0xfff) === limit
112
+ "varbinary(#{limit})"
113
+ else
114
+ type_with_size_to_sql("blob", size)
115
+ end
116
+ else
117
+ super
118
+ end
119
+
120
+ sql = "#{sql} unsigned" if unsigned && type != :primary_key
121
+ sql
122
+ end
123
+
124
+ def table_alias_length
125
+ 256 # https://dev.mysql.com/doc/refman/en/identifiers.html
126
+ end
127
+
128
+ private
129
+ CHARSETS_OF_4BYTES_MAXLEN = ["utf8mb4", "utf16", "utf16le", "utf32"]
130
+
131
+ def row_format_dynamic_by_default?
132
+ if mariadb?
133
+ database_version >= "10.2.2"
134
+ else
135
+ database_version >= "5.7.9"
136
+ end
137
+ end
138
+
139
+ def default_row_format
140
+ return if row_format_dynamic_by_default?
141
+
142
+ unless defined?(@default_row_format)
143
+ if query_value("SELECT @@innodb_file_per_table = 1 AND @@innodb_file_format = 'Barracuda'") == 1
144
+ @default_row_format = "ROW_FORMAT=DYNAMIC"
145
+ else
146
+ @default_row_format = nil
147
+ end
148
+ end
149
+
150
+ @default_row_format
151
+ end
152
+
153
+ def schema_creation
154
+ MySQL::SchemaCreation.new(self)
155
+ end
156
+
157
+ def create_table_definition(name, **options)
158
+ MySQL::TableDefinition.new(self, name, **options)
159
+ end
160
+
161
+ def new_column_from_field(table_name, field)
162
+ type_metadata = fetch_type_metadata(field[:Type], field[:Extra])
163
+ default, default_function = field[:Default], nil
164
+
165
+ if type_metadata.type == :datetime && /\ACURRENT_TIMESTAMP(?:\([0-6]?\))?\z/i.match?(default)
166
+ default, default_function = nil, default
167
+ elsif type_metadata.extra == "DEFAULT_GENERATED"
168
+ default = +"(#{default})" unless default.start_with?("(")
169
+ default, default_function = nil, default
170
+ end
171
+
172
+ MySQL::Column.new(
173
+ field[:Field],
174
+ default,
175
+ type_metadata,
176
+ field[:Null] == "YES",
177
+ default_function,
178
+ collation: field[:Collation],
179
+ comment: field[:Comment].presence
180
+ )
181
+ end
182
+
183
+ def fetch_type_metadata(sql_type, extra = "")
184
+ MySQL::TypeMetadata.new(super(sql_type), extra: extra)
185
+ end
186
+
187
+ def extract_foreign_key_action(specifier)
188
+ super unless specifier == "RESTRICT"
189
+ end
190
+
191
+ def add_index_length(quoted_columns, **options)
192
+ lengths = options_for_index_columns(options[:length])
193
+ quoted_columns.each do |name, column|
194
+ column << "(#{lengths[name]})" if lengths[name].present?
195
+ end
196
+ end
197
+
198
+ def add_options_for_index_columns(quoted_columns, **options)
199
+ quoted_columns = add_index_length(quoted_columns, **options)
200
+ super
201
+ end
202
+
203
+ def data_source_sql(name = nil, type: nil)
204
+ scope = quoted_scope(name, type: type)
205
+
206
+ sql = +"SELECT table_name FROM (SELECT * FROM information_schema.tables "
207
+ sql << " WHERE table_schema = #{scope[:schema]}) _subquery"
208
+ if scope[:type] || scope[:name]
209
+ conditions = []
210
+ conditions << "_subquery.table_type = #{scope[:type]}" if scope[:type]
211
+ conditions << "_subquery.table_name = #{scope[:name]}" if scope[:name]
212
+ sql << " WHERE #{conditions.join(" AND ")}"
213
+ end
214
+ sql
215
+ end
216
+
217
+ def quoted_scope(name = nil, type: nil)
218
+ schema, name = extract_schema_qualified_name(name)
219
+ scope = {}
220
+ scope[:schema] = schema ? quote(schema) : "database()"
221
+ scope[:name] = quote(name) if name
222
+ scope[:type] = quote(type) if type
223
+ scope
224
+ end
225
+
226
+ def extract_schema_qualified_name(string)
227
+ schema, name = string.to_s.scan(/[^`.\s]+|`[^`]*`/)
228
+ schema, name = nil, schema unless name
229
+ [schema, name]
230
+ end
231
+
232
+ def type_with_size_to_sql(type, size)
233
+ case size&.to_s
234
+ when nil, "tiny", "medium", "long"
235
+ "#{size}#{type}"
236
+ else
237
+ raise ArgumentError,
238
+ "#{size.inspect} is invalid :size value. Only :tiny, :medium, and :long are allowed."
239
+ end
240
+ end
241
+
242
+ def limit_to_size(limit, type)
243
+ case type.to_s
244
+ when "text", "blob", "binary"
245
+ case limit
246
+ when 0..0xff; "tiny"
247
+ when nil, 0x100..0xffff; nil
248
+ when 0x10000..0xffffff; "medium"
249
+ when 0x1000000..0xffffffff; "long"
250
+ else raise ArgumentError, "No #{type} type has byte size #{limit}"
251
+ end
252
+ end
253
+ end
254
+
255
+ def integer_to_sql(limit)
256
+ case limit
257
+ when 1; "tinyint"
258
+ when 2; "smallint"
259
+ when 3; "mediumint"
260
+ when nil, 4; "int"
261
+ when 5..8; "bigint"
262
+ else raise ArgumentError, "No integer type has byte size #{limit}. Use a decimal with scale 0 instead."
263
+ end
264
+ end
265
+ end
266
+ end
267
+ end
268
+ end
@@ -1,31 +1,39 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module MySQL
4
6
  class TypeMetadata < DelegateClass(SqlTypeMetadata) # :nodoc:
5
- attr_reader :extra, :strict
7
+ undef to_yaml if method_defined?(:to_yaml)
8
+
9
+ include Deduplicable
10
+
11
+ attr_reader :extra
6
12
 
7
- def initialize(type_metadata, extra: "", strict: false)
13
+ def initialize(type_metadata, extra: nil)
8
14
  super(type_metadata)
9
- @type_metadata = type_metadata
10
15
  @extra = extra
11
- @strict = strict
12
16
  end
13
17
 
14
18
  def ==(other)
15
- other.is_a?(MySQL::TypeMetadata) &&
16
- attributes_for_hash == other.attributes_for_hash
19
+ other.is_a?(TypeMetadata) &&
20
+ __getobj__ == other.__getobj__ &&
21
+ extra == other.extra
17
22
  end
18
23
  alias eql? ==
19
24
 
20
25
  def hash
21
- attributes_for_hash.hash
26
+ TypeMetadata.hash ^
27
+ __getobj__.hash ^
28
+ extra.hash
22
29
  end
23
30
 
24
- protected
25
-
26
- def attributes_for_hash
27
- [self.class, @type_metadata, extra, strict]
28
- end
31
+ private
32
+ def deduplicated
33
+ __setobj__(__getobj__.deduplicate)
34
+ @extra = -extra if extra
35
+ super
36
+ end
29
37
  end
30
38
  end
31
39
  end
@@ -1,52 +1,66 @@
1
- require 'active_record/connection_adapters/abstract_mysql_adapter'
2
- require 'active_record/connection_adapters/mysql/database_statements'
1
+ # frozen_string_literal: true
3
2
 
4
- gem 'mysql2', '>= 0.3.18', '< 0.6.0'
5
- require 'mysql2'
6
- raise 'mysql2 0.4.3 is not supported. Please upgrade to 0.4.4+' if Mysql2::VERSION == '0.4.3'
3
+ require "active_record/connection_adapters/abstract_mysql_adapter"
4
+ require "active_record/connection_adapters/mysql/database_statements"
5
+
6
+ gem "mysql2", "~> 0.5"
7
+ require "mysql2"
7
8
 
8
9
  module ActiveRecord
9
10
  module ConnectionHandling # :nodoc:
10
11
  # Establishes a connection to the database that's used by all Active Record objects.
11
12
  def mysql2_connection(config)
12
13
  config = config.symbolize_keys
13
-
14
- config[:username] = 'root' if config[:username].nil?
15
14
  config[:flags] ||= 0
16
15
 
17
- if Mysql2::Client.const_defined? :FOUND_ROWS
18
- if config[:flags].kind_of? Array
19
- config[:flags].push "FOUND_ROWS".freeze
20
- else
21
- config[:flags] |= Mysql2::Client::FOUND_ROWS
22
- end
23
- end
24
-
25
- client = Mysql2::Client.new(config)
26
- ConnectionAdapters::Mysql2Adapter.new(client, logger, nil, config)
27
- rescue Mysql2::Error => error
28
- if error.message.include?("Unknown database")
29
- raise ActiveRecord::NoDatabaseError
16
+ if config[:flags].kind_of? Array
17
+ config[:flags].push "FOUND_ROWS"
30
18
  else
31
- raise
19
+ config[:flags] |= Mysql2::Client::FOUND_ROWS
32
20
  end
21
+
22
+ ConnectionAdapters::Mysql2Adapter.new(
23
+ ConnectionAdapters::Mysql2Adapter.new_client(config),
24
+ logger,
25
+ nil,
26
+ config,
27
+ )
33
28
  end
34
29
  end
35
30
 
36
31
  module ConnectionAdapters
37
32
  class Mysql2Adapter < AbstractMysqlAdapter
38
- ADAPTER_NAME = 'Mysql2'.freeze
33
+ ER_BAD_DB_ERROR = 1049
34
+ ADAPTER_NAME = "Mysql2"
39
35
 
40
36
  include MySQL::DatabaseStatements
41
37
 
38
+ class << self
39
+ def new_client(config)
40
+ Mysql2::Client.new(config)
41
+ rescue Mysql2::Error => error
42
+ if error.error_number == ConnectionAdapters::Mysql2Adapter::ER_BAD_DB_ERROR
43
+ raise ActiveRecord::NoDatabaseError
44
+ else
45
+ raise ActiveRecord::ConnectionNotEstablished, error.message
46
+ end
47
+ end
48
+ end
49
+
42
50
  def initialize(connection, logger, connection_options, config)
43
- super
44
- @prepared_statements = false unless config.key?(:prepared_statements)
51
+ superclass_config = config.reverse_merge(prepared_statements: false)
52
+ super(connection, logger, connection_options, superclass_config)
45
53
  configure_connection
46
54
  end
47
55
 
56
+ def self.database_exists?(config)
57
+ !!ActiveRecord::Base.mysql2_connection(config)
58
+ rescue ActiveRecord::NoDatabaseError
59
+ false
60
+ end
61
+
48
62
  def supports_json?
49
- !mariadb? && version >= '5.7.8'
63
+ !mariadb? && database_version >= "5.7.8"
50
64
  end
51
65
 
52
66
  def supports_comments?
@@ -61,11 +75,15 @@ module ActiveRecord
61
75
  true
62
76
  end
63
77
 
78
+ def supports_lazy_transactions?
79
+ true
80
+ end
81
+
64
82
  # HELPER METHODS ===========================================
65
83
 
66
84
  def each_hash(result) # :nodoc:
67
85
  if block_given?
68
- result.each(:as => :hash, :symbolize_keys => true) do |row|
86
+ result.each(as: :hash, symbolize_keys: true) do |row|
69
87
  yield row
70
88
  end
71
89
  else
@@ -83,6 +101,8 @@ module ActiveRecord
83
101
 
84
102
  def quote_string(string)
85
103
  @connection.escape(string)
104
+ rescue Mysql2::Error => error
105
+ raise translate_exception(error, message: error.message, sql: "<escape>", binds: [])
86
106
  end
87
107
 
88
108
  #--
@@ -107,21 +127,38 @@ module ActiveRecord
107
127
  @connection.close
108
128
  end
109
129
 
130
+ def discard! # :nodoc:
131
+ super
132
+ @connection.automatic_close = false
133
+ @connection = nil
134
+ end
135
+
110
136
  private
137
+ def connect
138
+ @connection = self.class.new_client(@config)
139
+ configure_connection
140
+ end
111
141
 
112
- def connect
113
- @connection = Mysql2::Client.new(@config)
114
- configure_connection
115
- end
142
+ def configure_connection
143
+ @connection.query_options[:as] = :array
144
+ super
145
+ end
116
146
 
117
- def configure_connection
118
- @connection.query_options.merge!(:as => :array)
119
- super
120
- end
147
+ def full_version
148
+ schema_cache.database_version.full_version_string
149
+ end
121
150
 
122
- def full_version
123
- @full_version ||= @connection.server_info[:version]
124
- end
151
+ def get_full_version
152
+ @connection.server_info[:version]
153
+ end
154
+
155
+ def translate_exception(exception, message:, sql:, binds:)
156
+ if exception.is_a?(Mysql2::Error::TimeoutError) && !exception.error_number
157
+ ActiveRecord::AdapterTimeout.new(message, sql: sql, binds: binds)
158
+ else
159
+ super
160
+ end
161
+ end
125
162
  end
126
163
  end
127
164
  end