activerecord 4.2.11.3 → 6.0.2.2

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 (372) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +675 -1587
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +13 -12
  5. data/examples/performance.rb +33 -32
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record.rb +41 -22
  8. data/lib/active_record/aggregations.rb +267 -251
  9. data/lib/active_record/association_relation.rb +26 -12
  10. data/lib/active_record/associations.rb +1737 -1597
  11. data/lib/active_record/associations/alias_tracker.rb +29 -35
  12. data/lib/active_record/associations/association.rb +133 -58
  13. data/lib/active_record/associations/association_scope.rb +103 -132
  14. data/lib/active_record/associations/belongs_to_association.rb +65 -60
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
  16. data/lib/active_record/associations/builder/association.rb +27 -40
  17. data/lib/active_record/associations/builder/belongs_to.rb +69 -55
  18. data/lib/active_record/associations/builder/collection_association.rb +10 -33
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +52 -66
  20. data/lib/active_record/associations/builder/has_many.rb +8 -4
  21. data/lib/active_record/associations/builder/has_one.rb +46 -5
  22. data/lib/active_record/associations/builder/singular_association.rb +16 -10
  23. data/lib/active_record/associations/collection_association.rb +136 -288
  24. data/lib/active_record/associations/collection_proxy.rb +241 -146
  25. data/lib/active_record/associations/foreign_association.rb +10 -1
  26. data/lib/active_record/associations/has_many_association.rb +34 -97
  27. data/lib/active_record/associations/has_many_through_association.rb +60 -87
  28. data/lib/active_record/associations/has_one_association.rb +61 -49
  29. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  30. data/lib/active_record/associations/join_dependency.rb +141 -167
  31. data/lib/active_record/associations/join_dependency/join_association.rb +38 -86
  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 +90 -92
  35. data/lib/active_record/associations/preloader/association.rb +90 -123
  36. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  37. data/lib/active_record/associations/singular_association.rb +18 -39
  38. data/lib/active_record/associations/through_association.rb +38 -18
  39. data/lib/active_record/attribute_assignment.rb +56 -183
  40. data/lib/active_record/attribute_decorators.rb +39 -15
  41. data/lib/active_record/attribute_methods.rb +120 -135
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -8
  43. data/lib/active_record/attribute_methods/dirty.rb +174 -144
  44. data/lib/active_record/attribute_methods/primary_key.rb +91 -83
  45. data/lib/active_record/attribute_methods/query.rb +6 -5
  46. data/lib/active_record/attribute_methods/read.rb +20 -76
  47. data/lib/active_record/attribute_methods/serialization.rb +40 -20
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +58 -36
  49. data/lib/active_record/attribute_methods/write.rb +32 -54
  50. data/lib/active_record/attributes.rb +214 -82
  51. data/lib/active_record/autosave_association.rb +96 -38
  52. data/lib/active_record/base.rb +57 -45
  53. data/lib/active_record/callbacks.rb +100 -74
  54. data/lib/active_record/coders/json.rb +3 -1
  55. data/lib/active_record/coders/yaml_column.rb +24 -12
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +806 -296
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +26 -8
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +238 -115
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +83 -23
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +170 -53
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +74 -46
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +356 -227
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +664 -243
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +191 -83
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +469 -202
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +517 -633
  69. data/lib/active_record/connection_adapters/column.rb +56 -43
  70. data/lib/active_record/connection_adapters/connection_specification.rb +174 -152
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +202 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +58 -180
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +21 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +66 -114
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
  86. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -58
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +4 -2
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +5 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -22
  93. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  94. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
  95. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -19
  96. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -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 +45 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  100. data/lib/active_record/connection_adapters/postgresql/oid/{integer.rb → oid.rb} +6 -2
  101. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +33 -11
  102. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -34
  103. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
  104. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  105. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +10 -5
  106. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +144 -47
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +470 -290
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +12 -8
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +555 -356
  117. data/lib/active_record/connection_adapters/schema_cache.rb +72 -25
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
  119. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +120 -0
  120. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  121. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  126. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +294 -345
  127. data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
  128. data/lib/active_record/connection_handling.rb +183 -41
  129. data/lib/active_record/core.rb +253 -229
  130. data/lib/active_record/counter_cache.rb +67 -49
  131. data/lib/active_record/database_configurations.rb +233 -0
  132. data/lib/active_record/database_configurations/database_config.rb +37 -0
  133. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  134. data/lib/active_record/database_configurations/url_config.rb +79 -0
  135. data/lib/active_record/define_callbacks.rb +22 -0
  136. data/lib/active_record/dynamic_matchers.rb +87 -105
  137. data/lib/active_record/enum.rb +163 -86
  138. data/lib/active_record/errors.rb +188 -53
  139. data/lib/active_record/explain.rb +23 -11
  140. data/lib/active_record/explain_registry.rb +4 -2
  141. data/lib/active_record/explain_subscriber.rb +10 -5
  142. data/lib/active_record/fixture_set/file.rb +35 -9
  143. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  144. data/lib/active_record/fixture_set/render_context.rb +17 -0
  145. data/lib/active_record/fixture_set/table_row.rb +153 -0
  146. data/lib/active_record/fixture_set/table_rows.rb +47 -0
  147. data/lib/active_record/fixtures.rb +228 -499
  148. data/lib/active_record/gem_version.rb +6 -4
  149. data/lib/active_record/inheritance.rb +158 -112
  150. data/lib/active_record/insert_all.rb +179 -0
  151. data/lib/active_record/integration.rb +123 -29
  152. data/lib/active_record/internal_metadata.rb +53 -0
  153. data/lib/active_record/legacy_yaml_adapter.rb +21 -3
  154. data/lib/active_record/locale/en.yml +3 -2
  155. data/lib/active_record/locking/optimistic.rb +87 -96
  156. data/lib/active_record/locking/pessimistic.rb +18 -6
  157. data/lib/active_record/log_subscriber.rb +76 -33
  158. data/lib/active_record/middleware/database_selector.rb +75 -0
  159. data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
  160. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  161. data/lib/active_record/migration.rb +621 -303
  162. data/lib/active_record/migration/command_recorder.rb +177 -90
  163. data/lib/active_record/migration/compatibility.rb +244 -0
  164. data/lib/active_record/migration/join_table.rb +8 -6
  165. data/lib/active_record/model_schema.rb +315 -112
  166. data/lib/active_record/nested_attributes.rb +264 -222
  167. data/lib/active_record/no_touching.rb +14 -1
  168. data/lib/active_record/null_relation.rb +24 -37
  169. data/lib/active_record/persistence.rb +557 -125
  170. data/lib/active_record/query_cache.rb +19 -23
  171. data/lib/active_record/querying.rb +43 -29
  172. data/lib/active_record/railtie.rb +143 -44
  173. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  174. data/lib/active_record/railties/console_sandbox.rb +2 -0
  175. data/lib/active_record/railties/controller_runtime.rb +34 -33
  176. data/lib/active_record/railties/databases.rake +331 -185
  177. data/lib/active_record/readonly_attributes.rb +5 -4
  178. data/lib/active_record/reflection.rb +428 -279
  179. data/lib/active_record/relation.rb +519 -341
  180. data/lib/active_record/relation/batches.rb +207 -55
  181. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  182. data/lib/active_record/relation/calculations.rb +267 -253
  183. data/lib/active_record/relation/delegation.rb +70 -80
  184. data/lib/active_record/relation/finder_methods.rb +286 -241
  185. data/lib/active_record/relation/from_clause.rb +26 -0
  186. data/lib/active_record/relation/merger.rb +78 -87
  187. data/lib/active_record/relation/predicate_builder.rb +114 -119
  188. data/lib/active_record/relation/predicate_builder/array_handler.rb +27 -26
  189. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  190. data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
  191. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  192. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  193. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  194. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  195. data/lib/active_record/relation/query_attribute.rb +50 -0
  196. data/lib/active_record/relation/query_methods.rb +597 -393
  197. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  198. data/lib/active_record/relation/spawn_methods.rb +11 -13
  199. data/lib/active_record/relation/where_clause.rb +190 -0
  200. data/lib/active_record/relation/where_clause_factory.rb +33 -0
  201. data/lib/active_record/result.rb +79 -42
  202. data/lib/active_record/runtime_registry.rb +6 -4
  203. data/lib/active_record/sanitization.rb +144 -121
  204. data/lib/active_record/schema.rb +21 -24
  205. data/lib/active_record/schema_dumper.rb +112 -93
  206. data/lib/active_record/schema_migration.rb +24 -17
  207. data/lib/active_record/scoping.rb +45 -26
  208. data/lib/active_record/scoping/default.rb +101 -85
  209. data/lib/active_record/scoping/named.rb +87 -33
  210. data/lib/active_record/secure_token.rb +40 -0
  211. data/lib/active_record/serialization.rb +5 -5
  212. data/lib/active_record/statement_cache.rb +73 -36
  213. data/lib/active_record/store.rb +127 -42
  214. data/lib/active_record/suppressor.rb +61 -0
  215. data/lib/active_record/table_metadata.rb +75 -0
  216. data/lib/active_record/tasks/database_tasks.rb +307 -100
  217. data/lib/active_record/tasks/mysql_database_tasks.rb +55 -99
  218. data/lib/active_record/tasks/postgresql_database_tasks.rb +81 -41
  219. data/lib/active_record/tasks/sqlite_database_tasks.rb +38 -16
  220. data/lib/active_record/test_databases.rb +23 -0
  221. data/lib/active_record/test_fixtures.rb +225 -0
  222. data/lib/active_record/timestamp.rb +86 -40
  223. data/lib/active_record/touch_later.rb +66 -0
  224. data/lib/active_record/transactions.rb +217 -151
  225. data/lib/active_record/translation.rb +3 -1
  226. data/lib/active_record/type.rb +78 -23
  227. data/lib/active_record/type/adapter_specific_registry.rb +129 -0
  228. data/lib/active_record/type/date.rb +4 -45
  229. data/lib/active_record/type/date_time.rb +4 -49
  230. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  231. data/lib/active_record/type/hash_lookup_type_map.rb +5 -3
  232. data/lib/active_record/type/internal/timezone.rb +17 -0
  233. data/lib/active_record/type/json.rb +30 -0
  234. data/lib/active_record/type/serialized.rb +24 -15
  235. data/lib/active_record/type/text.rb +2 -2
  236. data/lib/active_record/type/time.rb +11 -16
  237. data/lib/active_record/type/type_map.rb +15 -17
  238. data/lib/active_record/type/unsigned_integer.rb +9 -7
  239. data/lib/active_record/type_caster.rb +9 -0
  240. data/lib/active_record/type_caster/connection.rb +34 -0
  241. data/lib/active_record/type_caster/map.rb +20 -0
  242. data/lib/active_record/validations.rb +39 -35
  243. data/lib/active_record/validations/absence.rb +25 -0
  244. data/lib/active_record/validations/associated.rb +13 -4
  245. data/lib/active_record/validations/length.rb +26 -0
  246. data/lib/active_record/validations/presence.rb +14 -13
  247. data/lib/active_record/validations/uniqueness.rb +42 -55
  248. data/lib/active_record/version.rb +3 -1
  249. data/lib/arel.rb +58 -0
  250. data/lib/arel/alias_predication.rb +9 -0
  251. data/lib/arel/attributes.rb +22 -0
  252. data/lib/arel/attributes/attribute.rb +37 -0
  253. data/lib/arel/collectors/bind.rb +24 -0
  254. data/lib/arel/collectors/composite.rb +31 -0
  255. data/lib/arel/collectors/plain_string.rb +20 -0
  256. data/lib/arel/collectors/sql_string.rb +20 -0
  257. data/lib/arel/collectors/substitute_binds.rb +28 -0
  258. data/lib/arel/crud.rb +42 -0
  259. data/lib/arel/delete_manager.rb +18 -0
  260. data/lib/arel/errors.rb +9 -0
  261. data/lib/arel/expressions.rb +29 -0
  262. data/lib/arel/factory_methods.rb +49 -0
  263. data/lib/arel/insert_manager.rb +49 -0
  264. data/lib/arel/math.rb +45 -0
  265. data/lib/arel/nodes.rb +68 -0
  266. data/lib/arel/nodes/and.rb +32 -0
  267. data/lib/arel/nodes/ascending.rb +23 -0
  268. data/lib/arel/nodes/binary.rb +52 -0
  269. data/lib/arel/nodes/bind_param.rb +36 -0
  270. data/lib/arel/nodes/case.rb +55 -0
  271. data/lib/arel/nodes/casted.rb +50 -0
  272. data/lib/arel/nodes/comment.rb +29 -0
  273. data/lib/arel/nodes/count.rb +12 -0
  274. data/lib/arel/nodes/delete_statement.rb +45 -0
  275. data/lib/arel/nodes/descending.rb +23 -0
  276. data/lib/arel/nodes/equality.rb +18 -0
  277. data/lib/arel/nodes/extract.rb +24 -0
  278. data/lib/arel/nodes/false.rb +16 -0
  279. data/lib/arel/nodes/full_outer_join.rb +8 -0
  280. data/lib/arel/nodes/function.rb +44 -0
  281. data/lib/arel/nodes/grouping.rb +8 -0
  282. data/lib/arel/nodes/in.rb +8 -0
  283. data/lib/arel/nodes/infix_operation.rb +80 -0
  284. data/lib/arel/nodes/inner_join.rb +8 -0
  285. data/lib/arel/nodes/insert_statement.rb +37 -0
  286. data/lib/arel/nodes/join_source.rb +20 -0
  287. data/lib/arel/nodes/matches.rb +18 -0
  288. data/lib/arel/nodes/named_function.rb +23 -0
  289. data/lib/arel/nodes/node.rb +50 -0
  290. data/lib/arel/nodes/node_expression.rb +13 -0
  291. data/lib/arel/nodes/outer_join.rb +8 -0
  292. data/lib/arel/nodes/over.rb +15 -0
  293. data/lib/arel/nodes/regexp.rb +16 -0
  294. data/lib/arel/nodes/right_outer_join.rb +8 -0
  295. data/lib/arel/nodes/select_core.rb +67 -0
  296. data/lib/arel/nodes/select_statement.rb +41 -0
  297. data/lib/arel/nodes/sql_literal.rb +16 -0
  298. data/lib/arel/nodes/string_join.rb +11 -0
  299. data/lib/arel/nodes/table_alias.rb +27 -0
  300. data/lib/arel/nodes/terminal.rb +16 -0
  301. data/lib/arel/nodes/true.rb +16 -0
  302. data/lib/arel/nodes/unary.rb +45 -0
  303. data/lib/arel/nodes/unary_operation.rb +20 -0
  304. data/lib/arel/nodes/unqualified_column.rb +22 -0
  305. data/lib/arel/nodes/update_statement.rb +41 -0
  306. data/lib/arel/nodes/values_list.rb +9 -0
  307. data/lib/arel/nodes/window.rb +126 -0
  308. data/lib/arel/nodes/with.rb +11 -0
  309. data/lib/arel/order_predications.rb +13 -0
  310. data/lib/arel/predications.rb +257 -0
  311. data/lib/arel/select_manager.rb +271 -0
  312. data/lib/arel/table.rb +110 -0
  313. data/lib/arel/tree_manager.rb +72 -0
  314. data/lib/arel/update_manager.rb +34 -0
  315. data/lib/arel/visitors.rb +20 -0
  316. data/lib/arel/visitors/depth_first.rb +204 -0
  317. data/lib/arel/visitors/dot.rb +297 -0
  318. data/lib/arel/visitors/ibm_db.rb +34 -0
  319. data/lib/arel/visitors/informix.rb +62 -0
  320. data/lib/arel/visitors/mssql.rb +157 -0
  321. data/lib/arel/visitors/mysql.rb +83 -0
  322. data/lib/arel/visitors/oracle.rb +159 -0
  323. data/lib/arel/visitors/oracle12.rb +66 -0
  324. data/lib/arel/visitors/postgresql.rb +110 -0
  325. data/lib/arel/visitors/sqlite.rb +39 -0
  326. data/lib/arel/visitors/to_sql.rb +889 -0
  327. data/lib/arel/visitors/visitor.rb +46 -0
  328. data/lib/arel/visitors/where_sql.rb +23 -0
  329. data/lib/arel/window_predications.rb +9 -0
  330. data/lib/rails/generators/active_record.rb +7 -5
  331. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  332. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  333. data/lib/rails/generators/active_record/migration.rb +31 -1
  334. data/lib/rails/generators/active_record/migration/migration_generator.rb +42 -37
  335. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  336. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +11 -2
  337. data/lib/rails/generators/active_record/model/model_generator.rb +19 -22
  338. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  339. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  340. metadata +166 -58
  341. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  342. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  343. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  344. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  345. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  346. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  347. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  348. data/lib/active_record/attribute.rb +0 -163
  349. data/lib/active_record/attribute_set.rb +0 -81
  350. data/lib/active_record/attribute_set/builder.rb +0 -106
  351. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
  352. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  353. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  354. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  355. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  356. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  357. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  358. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  359. data/lib/active_record/type/big_integer.rb +0 -13
  360. data/lib/active_record/type/binary.rb +0 -50
  361. data/lib/active_record/type/boolean.rb +0 -31
  362. data/lib/active_record/type/decimal.rb +0 -64
  363. data/lib/active_record/type/decorator.rb +0 -14
  364. data/lib/active_record/type/float.rb +0 -19
  365. data/lib/active_record/type/integer.rb +0 -59
  366. data/lib/active_record/type/mutable.rb +0 -16
  367. data/lib/active_record/type/numeric.rb +0 -36
  368. data/lib/active_record/type/string.rb +0 -40
  369. data/lib/active_record/type/time_value.rb +0 -38
  370. data/lib/active_record/type/value.rb +0 -110
  371. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -19
  372. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
@@ -1,13 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  class TransactionState
4
- attr_reader :parent
5
-
6
- VALID_STATES = Set.new([:committed, :rolledback, nil])
7
-
8
6
  def initialize(state = nil)
9
7
  @state = state
10
- @parent = nil
8
+ @children = []
9
+ end
10
+
11
+ def add_child(state)
12
+ @children << state
11
13
  end
12
14
 
13
15
  def finalized?
@@ -15,27 +17,55 @@ module ActiveRecord
15
17
  end
16
18
 
17
19
  def committed?
18
- @state == :committed
20
+ @state == :committed || @state == :fully_committed
21
+ end
22
+
23
+ def fully_committed?
24
+ @state == :fully_committed
19
25
  end
20
26
 
21
27
  def rolledback?
22
- @state == :rolledback
28
+ @state == :rolledback || @state == :fully_rolledback
29
+ end
30
+
31
+ def fully_rolledback?
32
+ @state == :fully_rolledback
33
+ end
34
+
35
+ def fully_completed?
36
+ completed?
23
37
  end
24
38
 
25
39
  def completed?
26
40
  committed? || rolledback?
27
41
  end
28
42
 
29
- def set_state(state)
30
- if !VALID_STATES.include?(state)
31
- raise ArgumentError, "Invalid transaction state: #{state}"
32
- end
33
- @state = state
43
+ def rollback!
44
+ @children.each { |c| c.rollback! }
45
+ @state = :rolledback
46
+ end
47
+
48
+ def full_rollback!
49
+ @children.each { |c| c.rollback! }
50
+ @state = :fully_rolledback
51
+ end
52
+
53
+ def commit!
54
+ @state = :committed
55
+ end
56
+
57
+ def full_commit!
58
+ @state = :fully_committed
59
+ end
60
+
61
+ def nullify!
62
+ @state = nil
34
63
  end
35
64
  end
36
65
 
37
66
  class NullTransaction #:nodoc:
38
67
  def initialize; end
68
+ def state; end
39
69
  def closed?; true; end
40
70
  def open?; false; end
41
71
  def joinable?; false; end
@@ -43,59 +73,65 @@ module ActiveRecord
43
73
  end
44
74
 
45
75
  class Transaction #:nodoc:
76
+ attr_reader :connection, :state, :records, :savepoint_name, :isolation_level
46
77
 
47
- attr_reader :connection, :state, :records, :savepoint_name
48
- attr_writer :joinable
49
-
50
- def initialize(connection, options)
78
+ def initialize(connection, options, run_commit_callbacks: false)
51
79
  @connection = connection
52
80
  @state = TransactionState.new
53
81
  @records = []
82
+ @isolation_level = options[:isolation]
83
+ @materialized = false
54
84
  @joinable = options.fetch(:joinable, true)
85
+ @run_commit_callbacks = run_commit_callbacks
55
86
  end
56
87
 
57
88
  def add_record(record)
58
89
  records << record
59
90
  end
60
91
 
61
- def rollback
62
- @state.set_state(:rolledback)
92
+ def materialize!
93
+ @materialized = true
94
+ end
95
+
96
+ def materialized?
97
+ @materialized
63
98
  end
64
99
 
65
100
  def rollback_records
66
- ite = records.uniq
101
+ ite = records.uniq(&:object_id)
102
+ already_run_callbacks = {}
67
103
  while record = ite.shift
68
- begin
69
- record.rolledback! full_rollback?
70
- rescue => e
71
- raise if ActiveRecord::Base.raise_in_transactional_callbacks
72
- record.logger.error(e) if record.respond_to?(:logger) && record.logger
73
- end
104
+ trigger_callbacks = record.trigger_transactional_callbacks?
105
+ should_run_callbacks = !already_run_callbacks[record] && trigger_callbacks
106
+ already_run_callbacks[record] ||= trigger_callbacks
107
+ record.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: should_run_callbacks)
74
108
  end
75
109
  ensure
76
110
  ite.each do |i|
77
- i.rolledback!(full_rollback?, false)
111
+ i.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: false)
78
112
  end
79
113
  end
80
114
 
81
- def commit
82
- @state.set_state(:committed)
115
+ def before_commit_records
116
+ records.uniq.each(&:before_committed!) if @run_commit_callbacks
83
117
  end
84
118
 
85
119
  def commit_records
86
- ite = records.uniq
120
+ ite = records.uniq(&:object_id)
121
+ already_run_callbacks = {}
87
122
  while record = ite.shift
88
- begin
89
- record.committed!
90
- rescue => e
91
- raise if ActiveRecord::Base.raise_in_transactional_callbacks
92
- record.logger.error(e) if record.respond_to?(:logger) && record.logger
123
+ if @run_commit_callbacks
124
+ trigger_callbacks = record.trigger_transactional_callbacks?
125
+ should_run_callbacks = !already_run_callbacks[record] && trigger_callbacks
126
+ already_run_callbacks[record] ||= trigger_callbacks
127
+ record.committed!(should_run_callbacks: should_run_callbacks)
128
+ else
129
+ # if not running callbacks, only adds the record to the parent transaction
130
+ connection.add_transaction_record(record)
93
131
  end
94
132
  end
95
133
  ensure
96
- ite.each do |i|
97
- i.committed!(false)
98
- end
134
+ ite.each { |i| i.committed!(should_run_callbacks: false) }
99
135
  end
100
136
 
101
137
  def full_rollback?; true; end
@@ -105,52 +141,55 @@ module ActiveRecord
105
141
  end
106
142
 
107
143
  class SavepointTransaction < Transaction
144
+ def initialize(connection, savepoint_name, parent_transaction, *args)
145
+ super(connection, *args)
108
146
 
109
- def initialize(connection, savepoint_name, options)
110
- super(connection, options)
111
- if options[:isolation]
147
+ parent_transaction.state.add_child(@state)
148
+
149
+ if isolation_level
112
150
  raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
113
151
  end
114
- connection.create_savepoint(@savepoint_name = savepoint_name)
152
+
153
+ @savepoint_name = savepoint_name
115
154
  end
116
155
 
117
- def rollback
118
- connection.rollback_to_savepoint(savepoint_name)
156
+ def materialize!
157
+ connection.create_savepoint(savepoint_name)
119
158
  super
120
- rollback_records
159
+ end
160
+
161
+ def rollback
162
+ connection.rollback_to_savepoint(savepoint_name) if materialized?
163
+ @state.rollback!
121
164
  end
122
165
 
123
166
  def commit
124
- connection.release_savepoint(savepoint_name)
125
- super
126
- parent = connection.transaction_manager.current_transaction
127
- records.each { |r| parent.add_record(r) }
167
+ connection.release_savepoint(savepoint_name) if materialized?
168
+ @state.commit!
128
169
  end
129
170
 
130
171
  def full_rollback?; false; end
131
172
  end
132
173
 
133
174
  class RealTransaction < Transaction
134
-
135
- def initialize(connection, options)
136
- super
137
- if options[:isolation]
138
- connection.begin_isolated_db_transaction(options[:isolation])
175
+ def materialize!
176
+ if isolation_level
177
+ connection.begin_isolated_db_transaction(isolation_level)
139
178
  else
140
179
  connection.begin_db_transaction
141
180
  end
181
+
182
+ super
142
183
  end
143
184
 
144
185
  def rollback
145
- connection.rollback_db_transaction
146
- super
147
- rollback_records
186
+ connection.rollback_db_transaction if materialized?
187
+ @state.full_rollback!
148
188
  end
149
189
 
150
190
  def commit
151
- connection.commit_db_transaction
152
- super
153
- commit_records
191
+ connection.commit_db_transaction if materialized?
192
+ @state.full_commit!
154
193
  end
155
194
  end
156
195
 
@@ -158,43 +197,104 @@ module ActiveRecord
158
197
  def initialize(connection)
159
198
  @stack = []
160
199
  @connection = connection
200
+ @has_unmaterialized_transactions = false
201
+ @materializing_transactions = false
202
+ @lazy_transactions_enabled = true
161
203
  end
162
204
 
163
205
  def begin_transaction(options = {})
164
- transaction =
165
- if @stack.empty?
166
- RealTransaction.new(@connection, options)
206
+ @connection.lock.synchronize do
207
+ run_commit_callbacks = !current_transaction.joinable?
208
+ transaction =
209
+ if @stack.empty?
210
+ RealTransaction.new(@connection, options, run_commit_callbacks: run_commit_callbacks)
211
+ else
212
+ SavepointTransaction.new(@connection, "active_record_#{@stack.size}", @stack.last, options,
213
+ run_commit_callbacks: run_commit_callbacks)
214
+ end
215
+
216
+ if @connection.supports_lazy_transactions? && lazy_transactions_enabled? && options[:_lazy] != false
217
+ @has_unmaterialized_transactions = true
167
218
  else
168
- SavepointTransaction.new(@connection, "active_record_#{@stack.size}", options)
219
+ transaction.materialize!
220
+ end
221
+ @stack.push(transaction)
222
+ transaction
223
+ end
224
+ end
225
+
226
+ def disable_lazy_transactions!
227
+ materialize_transactions
228
+ @lazy_transactions_enabled = false
229
+ end
230
+
231
+ def enable_lazy_transactions!
232
+ @lazy_transactions_enabled = true
233
+ end
234
+
235
+ def lazy_transactions_enabled?
236
+ @lazy_transactions_enabled
237
+ end
238
+
239
+ def materialize_transactions
240
+ return if @materializing_transactions
241
+ return unless @has_unmaterialized_transactions
242
+
243
+ @connection.lock.synchronize do
244
+ begin
245
+ @materializing_transactions = true
246
+ @stack.each { |t| t.materialize! unless t.materialized? }
247
+ ensure
248
+ @materializing_transactions = false
169
249
  end
170
- @stack.push(transaction)
171
- transaction
250
+ @has_unmaterialized_transactions = false
251
+ end
172
252
  end
173
253
 
174
254
  def commit_transaction
175
- @stack.pop.commit
255
+ @connection.lock.synchronize do
256
+ transaction = @stack.last
257
+
258
+ begin
259
+ transaction.before_commit_records
260
+ ensure
261
+ @stack.pop
262
+ end
263
+
264
+ transaction.commit
265
+ transaction.commit_records
266
+ end
176
267
  end
177
268
 
178
- def rollback_transaction
179
- @stack.pop.rollback
269
+ def rollback_transaction(transaction = nil)
270
+ @connection.lock.synchronize do
271
+ transaction ||= @stack.pop
272
+ transaction.rollback
273
+ transaction.rollback_records
274
+ end
180
275
  end
181
276
 
182
277
  def within_new_transaction(options = {})
183
- transaction = begin_transaction options
184
- yield
185
- rescue Exception => error
186
- rollback_transaction if transaction
187
- raise
188
- ensure
189
- unless error
190
- if Thread.current.status == 'aborting'
191
- rollback_transaction if transaction
192
- else
193
- begin
194
- commit_transaction
195
- rescue Exception
196
- transaction.rollback unless transaction.state.completed?
197
- raise
278
+ @connection.lock.synchronize do
279
+ transaction = begin_transaction options
280
+ yield
281
+ rescue Exception => error
282
+ if transaction
283
+ rollback_transaction
284
+ after_failure_actions(transaction, error)
285
+ end
286
+ raise
287
+ ensure
288
+ if !error && transaction
289
+ if Thread.current.status == "aborting"
290
+ rollback_transaction
291
+ else
292
+ begin
293
+ commit_transaction
294
+ rescue Exception
295
+ rollback_transaction(transaction) unless transaction.state.completed?
296
+ raise
297
+ end
198
298
  end
199
299
  end
200
300
  end
@@ -209,7 +309,15 @@ module ActiveRecord
209
309
  end
210
310
 
211
311
  private
312
+
212
313
  NULL_TRANSACTION = NullTransaction.new
314
+
315
+ # Deallocate invalidated prepared statements outside of the transaction
316
+ def after_failure_actions(transaction, error)
317
+ return unless transaction.is_a?(RealTransaction)
318
+ return unless error.is_a?(ActiveRecord::PreparedStatementCacheExpired)
319
+ @connection.clear_cache!
320
+ end
213
321
  end
214
322
  end
215
323
  end
@@ -1,14 +1,17 @@
1
- require 'date'
2
- require 'bigdecimal'
3
- require 'bigdecimal/util'
4
- require 'active_record/type'
5
- require 'active_support/core_ext/benchmark'
6
- require 'active_record/connection_adapters/schema_cache'
7
- require 'active_record/connection_adapters/abstract/schema_dumper'
8
- require 'active_record/connection_adapters/abstract/schema_creation'
9
- require 'monitor'
10
- require 'arel/collectors/bind'
11
- require 'arel/collectors/sql_string'
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+ require "active_record/connection_adapters/determine_if_preparable_visitor"
5
+ require "active_record/connection_adapters/schema_cache"
6
+ require "active_record/connection_adapters/sql_type_metadata"
7
+ require "active_record/connection_adapters/abstract/schema_dumper"
8
+ require "active_record/connection_adapters/abstract/schema_creation"
9
+ require "active_support/concurrency/load_interlock_aware_monitor"
10
+ require "active_support/deprecation"
11
+ require "arel/collectors/bind"
12
+ require "arel/collectors/composite"
13
+ require "arel/collectors/sql_string"
14
+ require "arel/collectors/substitute_binds"
12
15
 
13
16
  module ActiveRecord
14
17
  module ConnectionAdapters # :nodoc:
@@ -17,22 +20,22 @@ module ActiveRecord
17
20
  autoload :Column
18
21
  autoload :ConnectionSpecification
19
22
 
20
- autoload_at 'active_record/connection_adapters/abstract/schema_definitions' do
23
+ autoload_at "active_record/connection_adapters/abstract/schema_definitions" do
21
24
  autoload :IndexDefinition
22
25
  autoload :ColumnDefinition
23
26
  autoload :ChangeColumnDefinition
27
+ autoload :ForeignKeyDefinition
24
28
  autoload :TableDefinition
25
29
  autoload :Table
26
30
  autoload :AlterTable
27
- autoload :TimestampDefaultDeprecation
31
+ autoload :ReferenceDefinition
28
32
  end
29
33
 
30
- autoload_at 'active_record/connection_adapters/abstract/connection_pool' do
34
+ autoload_at "active_record/connection_adapters/abstract/connection_pool" do
31
35
  autoload :ConnectionHandler
32
- autoload :ConnectionManagement
33
36
  end
34
37
 
35
- autoload_under 'abstract' do
38
+ autoload_under "abstract" do
36
39
  autoload :SchemaStatements
37
40
  autoload :DatabaseStatements
38
41
  autoload :DatabaseLimits
@@ -42,7 +45,7 @@ module ActiveRecord
42
45
  autoload :Savepoints
43
46
  end
44
47
 
45
- autoload_at 'active_record/connection_adapters/abstract/transaction' do
48
+ autoload_at "active_record/connection_adapters/abstract/transaction" do
46
49
  autoload :TransactionManager
47
50
  autoload :NullTransaction
48
51
  autoload :RealTransaction
@@ -54,34 +57,37 @@ module ActiveRecord
54
57
  # related classes form the abstraction layer which makes this possible.
55
58
  # An AbstractAdapter represents a connection to a database, and provides an
56
59
  # abstract interface for database-specific functionality such as establishing
57
- # a connection, escaping values, building the right SQL fragments for ':offset'
58
- # and ':limit' options, etc.
60
+ # a connection, escaping values, building the right SQL fragments for +:offset+
61
+ # and +:limit+ options, etc.
59
62
  #
60
63
  # All the concrete database adapters follow the interface laid down in this class.
61
- # ActiveRecord::Base.connection returns an AbstractAdapter object, which
64
+ # {ActiveRecord::Base.connection}[rdoc-ref:ConnectionHandling#connection] returns an AbstractAdapter object, which
62
65
  # you can use.
63
66
  #
64
67
  # Most of the methods in the adapter are useful during migrations. Most
65
- # notably, the instance methods provided by SchemaStatement are very useful.
68
+ # notably, the instance methods provided by SchemaStatements are very useful.
66
69
  class AbstractAdapter
67
- ADAPTER_NAME = 'Abstract'.freeze
70
+ ADAPTER_NAME = "Abstract"
71
+ include ActiveSupport::Callbacks
72
+ define_callbacks :checkout, :checkin
73
+
68
74
  include Quoting, DatabaseStatements, SchemaStatements
69
75
  include DatabaseLimits
70
76
  include QueryCache
71
- include ActiveSupport::Callbacks
72
- include MonitorMixin
73
- include ColumnDumper
77
+ include Savepoints
74
78
 
75
79
  SIMPLE_INT = /\A\d+\z/
76
80
 
77
- define_callbacks :checkout, :checkin
78
-
79
- attr_accessor :visitor, :pool
80
- attr_reader :schema_cache, :owner, :logger
81
+ attr_accessor :pool
82
+ attr_reader :visitor, :owner, :logger, :lock
81
83
  alias :in_use? :owner
82
84
 
85
+ set_callback :checkin, :after, :enable_lazy_transactions!
86
+
83
87
  def self.type_cast_config_to_integer(config)
84
- if config =~ SIMPLE_INT
88
+ if config.is_a?(Integer)
89
+ config
90
+ elsif SIMPLE_INT.match?(config)
85
91
  config.to_i
86
92
  else
87
93
  config
@@ -96,83 +102,176 @@ module ActiveRecord
96
102
  end
97
103
  end
98
104
 
99
- attr_reader :prepared_statements
105
+ def self.build_read_query_regexp(*parts) # :nodoc:
106
+ parts = parts.map { |part| /\A[\(\s]*#{part}/i }
107
+ Regexp.union(*parts)
108
+ end
109
+
110
+ def self.quoted_column_names # :nodoc:
111
+ @quoted_column_names ||= {}
112
+ end
113
+
114
+ def self.quoted_table_names # :nodoc:
115
+ @quoted_table_names ||= {}
116
+ end
100
117
 
101
- def initialize(connection, logger = nil, pool = nil) #:nodoc:
118
+ def initialize(connection, logger = nil, config = {}) # :nodoc:
102
119
  super()
103
120
 
104
121
  @connection = connection
105
122
  @owner = nil
106
123
  @instrumenter = ActiveSupport::Notifications.instrumenter
107
124
  @logger = logger
108
- @pool = pool
109
- @schema_cache = SchemaCache.new self
110
- @visitor = nil
111
- @prepared_statements = false
125
+ @config = config
126
+ @pool = ActiveRecord::ConnectionAdapters::NullPool.new
127
+ @idle_since = Concurrent.monotonic_time
128
+ @visitor = arel_visitor
129
+ @statements = build_statement_pool
130
+ @lock = ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
131
+
132
+ if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
133
+ @prepared_statements = true
134
+ @visitor.extend(DetermineIfPreparableVisitor)
135
+ else
136
+ @prepared_statements = false
137
+ end
138
+
139
+ @advisory_locks_enabled = self.class.type_cast_config_to_boolean(
140
+ config.fetch(:advisory_locks, true)
141
+ )
142
+ end
143
+
144
+ def replica?
145
+ @config[:replica] || false
146
+ end
147
+
148
+ # Determines whether writes are currently being prevents.
149
+ #
150
+ # Returns true if the connection is a replica, or if +prevent_writes+
151
+ # is set to true.
152
+ def preventing_writes?
153
+ replica? || ActiveRecord::Base.connection_handler.prevent_writes
154
+ end
155
+
156
+ def migrations_paths # :nodoc:
157
+ @config[:migrations_paths] || Migrator.migrations_paths
158
+ end
159
+
160
+ def migration_context # :nodoc:
161
+ MigrationContext.new(migrations_paths, schema_migration)
162
+ end
163
+
164
+ def schema_migration # :nodoc:
165
+ @schema_migration ||= begin
166
+ conn = self
167
+ spec_name = conn.pool.spec.name
168
+ name = "#{spec_name}::SchemaMigration"
169
+
170
+ Class.new(ActiveRecord::SchemaMigration) do
171
+ define_singleton_method(:name) { name }
172
+ define_singleton_method(:to_s) { name }
173
+
174
+ self.connection_specification_name = spec_name
175
+ end
176
+ end
177
+ end
178
+
179
+ def prepared_statements
180
+ @prepared_statements && !prepared_statements_disabled_cache.include?(object_id)
181
+ end
182
+
183
+ def prepared_statements_disabled_cache # :nodoc:
184
+ Thread.current[:ar_prepared_statements_disabled_cache] ||= Set.new
112
185
  end
113
186
 
114
187
  class Version
115
188
  include Comparable
116
189
 
117
- def initialize(version_string)
118
- @version = version_string.split('.').map(&:to_i)
190
+ attr_reader :full_version_string
191
+
192
+ def initialize(version_string, full_version_string = nil)
193
+ @version = version_string.split(".").map(&:to_i)
194
+ @full_version_string = full_version_string
119
195
  end
120
196
 
121
197
  def <=>(version_string)
122
- @version <=> version_string.split('.').map(&:to_i)
198
+ @version <=> version_string.split(".").map(&:to_i)
123
199
  end
124
- end
125
200
 
126
- class BindCollector < Arel::Collectors::Bind
127
- def compile(bvs, conn)
128
- super(bvs.map { |bv| conn.quote(*bv.reverse) })
201
+ def to_s
202
+ @version.join(".")
129
203
  end
130
204
  end
131
205
 
132
- class SQLString < Arel::Collectors::SQLString
133
- def compile(bvs, conn)
134
- super(bvs)
135
- end
206
+ def valid_type?(type) # :nodoc:
207
+ !native_database_types[type].nil?
136
208
  end
137
209
 
138
- def collector
139
- if prepared_statements
140
- SQLString.new
141
- else
142
- BindCollector.new
210
+ # this method must only be called while holding connection pool's mutex
211
+ def lease
212
+ if in_use?
213
+ msg = +"Cannot lease connection, "
214
+ if @owner == Thread.current
215
+ msg << "it is already leased by the current thread."
216
+ else
217
+ msg << "it is already in use by a different thread: #{@owner}. " \
218
+ "Current thread: #{Thread.current}."
219
+ end
220
+ raise ActiveRecordError, msg
143
221
  end
222
+
223
+ @owner = Thread.current
144
224
  end
145
225
 
146
- def valid_type?(type)
147
- true
226
+ def schema_cache
227
+ @pool.get_schema_cache(self)
148
228
  end
149
229
 
150
- def schema_creation
151
- SchemaCreation.new self
230
+ def schema_cache=(cache)
231
+ cache.connection = self
232
+ @pool.set_schema_cache(cache)
152
233
  end
153
234
 
154
- def lease
155
- synchronize do
156
- unless in_use?
157
- @owner = Thread.current
235
+ # this method must only be called while holding connection pool's mutex
236
+ def expire
237
+ if in_use?
238
+ if @owner != Thread.current
239
+ raise ActiveRecordError, "Cannot expire connection, " \
240
+ "it is owned by a different thread: #{@owner}. " \
241
+ "Current thread: #{Thread.current}."
158
242
  end
243
+
244
+ @idle_since = Concurrent.monotonic_time
245
+ @owner = nil
246
+ else
247
+ raise ActiveRecordError, "Cannot expire connection, it is not currently leased."
159
248
  end
160
249
  end
161
250
 
162
- def schema_cache=(cache)
163
- cache.connection = self
164
- @schema_cache = cache
251
+ # this method must only be called while holding connection pool's mutex (and a desire for segfaults)
252
+ def steal! # :nodoc:
253
+ if in_use?
254
+ if @owner != Thread.current
255
+ pool.send :remove_connection_from_thread_cache, self, @owner
256
+
257
+ @owner = Thread.current
258
+ end
259
+ else
260
+ raise ActiveRecordError, "Cannot steal connection, it is not currently leased."
261
+ end
165
262
  end
166
263
 
167
- def expire
168
- @owner = nil
264
+ # Seconds since this connection was returned to the pool
265
+ def seconds_idle # :nodoc:
266
+ return 0 if in_use?
267
+ Concurrent.monotonic_time - @idle_since
169
268
  end
170
269
 
171
270
  def unprepared_statement
172
- old_prepared_statements, @prepared_statements = @prepared_statements, false
271
+ cache = prepared_statements_disabled_cache.add(object_id) if @prepared_statements
173
272
  yield
174
273
  ensure
175
- @prepared_statements = old_prepared_statements
274
+ cache&.delete(object_id)
176
275
  end
177
276
 
178
277
  # Returns the human-readable name of the adapter. Use mixed case - one
@@ -181,15 +280,9 @@ module ActiveRecord
181
280
  self.class::ADAPTER_NAME
182
281
  end
183
282
 
184
- # Does this adapter support migrations?
185
- def supports_migrations?
186
- false
187
- end
188
-
189
- # Can this adapter determine the primary key for tables not attached
190
- # to an Active Record class, such as join tables?
191
- def supports_primary_key?
192
- false
283
+ # Does the database for this adapter exist?
284
+ def self.database_exists?(config)
285
+ raise NotImplementedError
193
286
  end
194
287
 
195
288
  # Does this adapter support DDL rollbacks in transactions? That is, would
@@ -207,6 +300,11 @@ module ActiveRecord
207
300
  false
208
301
  end
209
302
 
303
+ # Does this adapter support application-enforced advisory locking?
304
+ def supports_advisory_locks?
305
+ false
306
+ end
307
+
210
308
  # Should primary key values be selected from their corresponding
211
309
  # sequence before the insert statement? If true, next_sequence_value
212
310
  # is called before each insert to set the record's primary key.
@@ -224,6 +322,11 @@ module ActiveRecord
224
322
  false
225
323
  end
226
324
 
325
+ # Does this adapter support expression indices?
326
+ def supports_expression_index?
327
+ false
328
+ end
329
+
227
330
  # Does this adapter support explain?
228
331
  def supports_explain?
229
332
  false
@@ -250,11 +353,93 @@ module ActiveRecord
250
353
  false
251
354
  end
252
355
 
356
+ # Does this adapter support creating invalid constraints?
357
+ def supports_validate_constraints?
358
+ false
359
+ end
360
+
361
+ # Does this adapter support creating foreign key constraints
362
+ # in the same statement as creating the table?
363
+ def supports_foreign_keys_in_create?
364
+ supports_foreign_keys?
365
+ end
366
+ deprecate :supports_foreign_keys_in_create?
367
+
253
368
  # Does this adapter support views?
254
369
  def supports_views?
255
370
  false
256
371
  end
257
372
 
373
+ # Does this adapter support materialized views?
374
+ def supports_materialized_views?
375
+ false
376
+ end
377
+
378
+ # Does this adapter support datetime with precision?
379
+ def supports_datetime_with_precision?
380
+ false
381
+ end
382
+
383
+ # Does this adapter support json data type?
384
+ def supports_json?
385
+ false
386
+ end
387
+
388
+ # Does this adapter support metadata comments on database objects (tables, columns, indexes)?
389
+ def supports_comments?
390
+ false
391
+ end
392
+
393
+ # Can comments for tables, columns, and indexes be specified in create/alter table statements?
394
+ def supports_comments_in_create?
395
+ false
396
+ end
397
+
398
+ # Does this adapter support multi-value insert?
399
+ def supports_multi_insert?
400
+ true
401
+ end
402
+ deprecate :supports_multi_insert?
403
+
404
+ # Does this adapter support virtual columns?
405
+ def supports_virtual_columns?
406
+ false
407
+ end
408
+
409
+ # Does this adapter support foreign/external tables?
410
+ def supports_foreign_tables?
411
+ false
412
+ end
413
+
414
+ # Does this adapter support optimizer hints?
415
+ def supports_optimizer_hints?
416
+ false
417
+ end
418
+
419
+ def supports_common_table_expressions?
420
+ false
421
+ end
422
+
423
+ def supports_lazy_transactions?
424
+ false
425
+ end
426
+
427
+ def supports_insert_returning?
428
+ false
429
+ end
430
+
431
+ def supports_insert_on_duplicate_skip?
432
+ false
433
+ end
434
+
435
+ def supports_insert_on_duplicate_update?
436
+ false
437
+ end
438
+
439
+ def supports_insert_conflict_target?
440
+ false
441
+ end
442
+
258
443
  # This is meant to be implemented by the adapters that support extensions
259
444
  def disable_extension(name)
260
445
  end
@@ -263,6 +448,24 @@ module ActiveRecord
263
448
  def enable_extension(name)
264
449
  end
265
450
 
451
+ def advisory_locks_enabled? # :nodoc:
452
+ supports_advisory_locks? && @advisory_locks_enabled
453
+ end
454
+
455
+ # This is meant to be implemented by the adapters that support advisory
456
+ # locks
457
+ #
458
+ # Return true if we got the lock, otherwise false
459
+ def get_advisory_lock(lock_id) # :nodoc:
460
+ end
461
+
462
+ # This is meant to be implemented by the adapters that support advisory
463
+ # locks.
464
+ #
465
+ # Return true if we released the lock, otherwise false
466
+ def release_advisory_lock(lock_id) # :nodoc:
467
+ end
468
+
266
469
  # A list of extensions, to be filled in by adapters that support them.
267
470
  def extensions
268
471
  []
@@ -273,14 +476,6 @@ module ActiveRecord
273
476
  {}
274
477
  end
275
478
 
276
- # QUOTING ==================================================
277
-
278
- # Returns a bind substitution value given a bind +column+
279
- # NOTE: The column param is currently being used by the sqlserver-adapter
280
- def substitute_at(column, _unused = 0)
281
- Arel::Nodes::BindParam.new
282
- end
283
-
284
479
  # REFERENTIAL INTEGRITY ====================================
285
480
 
286
481
  # Override to turn off referential integrity while executing <tt>&block</tt>.
@@ -311,6 +506,22 @@ module ActiveRecord
311
506
  reset_transaction
312
507
  end
313
508
 
509
+ # Immediately forget this connection ever existed. Unlike disconnect!,
510
+ # this will not communicate with the server.
511
+ #
512
+ # After calling this method, the behavior of all other methods becomes
513
+ # undefined. This is called internally just before a forked process gets
514
+ # rid of a connection that belonged to its parent.
515
+ def discard!
516
+ # This should be overridden by concrete adapters.
517
+ #
518
+ # Prevent @connection's finalizer from touching the socket, or
519
+ # otherwise communicating with its server, when it is collected.
520
+ if schema_cache.connection == self
521
+ schema_cache.connection = nil
522
+ end
523
+ end
524
+
314
525
  # Reset the state of this connection, directing the DBMS to clear
315
526
  # transactions and other connection-related server-side state. Usually a
316
527
  # database-dependent operation.
@@ -321,11 +532,9 @@ module ActiveRecord
321
532
  # this should be overridden by concrete adapters
322
533
  end
323
534
 
324
- ###
325
- # Clear any caching the database adapter may be doing, for example
326
- # clearing the prepared statement cache. This is database specific.
535
+ # Clear any caching the database adapter may be doing.
327
536
  def clear_cache!
328
- # this should be overridden by concrete adapters
537
+ @lock.synchronize { @statements.clear } if @statements
329
538
  end
330
539
 
331
540
  # Returns true if its required to reload the connection between requests for development mode.
@@ -334,172 +543,230 @@ module ActiveRecord
334
543
  end
335
544
 
336
545
  # Checks whether the connection to the database is still active (i.e. not stale).
337
- # This is done under the hood by calling <tt>active?</tt>. If the connection
546
+ # This is done under the hood by calling #active?. If the connection
338
547
  # is no longer active, then this method will reconnect to the database.
339
- def verify!(*ignored)
548
+ def verify!
340
549
  reconnect! unless active?
341
550
  end
342
551
 
343
552
  # Provides access to the underlying database driver for this adapter. For
344
- # example, this method returns a Mysql object in case of MysqlAdapter,
345
- # and a PGconn object in case of PostgreSQLAdapter.
553
+ # example, this method returns a Mysql2::Client object in case of Mysql2Adapter,
554
+ # and a PG::Connection object in case of PostgreSQLAdapter.
346
555
  #
347
556
  # This is useful for when you need to call a proprietary method such as
348
557
  # PostgreSQL's lo_* methods.
349
558
  def raw_connection
559
+ disable_lazy_transactions!
350
560
  @connection
351
561
  end
352
562
 
353
- def create_savepoint(name = nil)
563
+ def default_uniqueness_comparison(attribute, value, klass) # :nodoc:
564
+ attribute.eq(value)
354
565
  end
355
566
 
356
- def release_savepoint(name = nil)
567
+ def case_sensitive_comparison(attribute, value) # :nodoc:
568
+ attribute.eq(value)
357
569
  end
358
570
 
359
- def case_sensitive_modifier(node, table_attribute)
360
- node
361
- end
362
-
363
- def case_sensitive_comparison(table, attribute, column, value)
364
- table_attr = table[attribute]
365
- value = case_sensitive_modifier(value, table_attr) unless value.nil?
366
- table_attr.eq(value)
367
- end
571
+ def case_insensitive_comparison(attribute, value) # :nodoc:
572
+ column = column_for_attribute(attribute)
368
573
 
369
- def case_insensitive_comparison(table, attribute, column, value)
370
- table[attribute].lower.eq(table.lower(value))
574
+ if can_perform_case_insensitive_comparison_for?(column)
575
+ attribute.lower.eq(attribute.relation.lower(value))
576
+ else
577
+ attribute.eq(value)
578
+ end
371
579
  end
372
580
 
373
- def current_savepoint_name
374
- current_transaction.savepoint_name
581
+ def can_perform_case_insensitive_comparison_for?(column)
582
+ true
375
583
  end
584
+ private :can_perform_case_insensitive_comparison_for?
376
585
 
377
586
  # Check the connection back in to the connection pool
378
587
  def close
379
588
  pool.checkin self
380
589
  end
381
590
 
382
- def type_map # :nodoc:
383
- @type_map ||= Type::TypeMap.new.tap do |mapping|
384
- initialize_type_map(mapping)
591
+ def column_name_for_operation(operation, node) # :nodoc:
592
+ visitor.compile(node)
593
+ end
594
+
595
+ def default_index_type?(index) # :nodoc:
596
+ index.using.nil?
597
+ end
598
+
599
+ # Called by ActiveRecord::InsertAll,
600
+ # Passed an instance of ActiveRecord::InsertAll::Builder,
601
+ # This method implements standard bulk inserts for all databases, but
602
+ # should be overridden by adapters to implement common features with
603
+ # non-standard syntax like handling duplicates or returning values.
604
+ def build_insert_sql(insert) # :nodoc:
605
+ if insert.skip_duplicates? || insert.update_duplicates?
606
+ raise NotImplementedError, "#{self.class} should define `build_insert_sql` to implement adapter-specific logic for handling duplicates during INSERT"
385
607
  end
608
+
609
+ "INSERT #{insert.into} #{insert.values_list}"
386
610
  end
387
611
 
388
- def new_column(name, default, cast_type, sql_type = nil, null = true)
389
- Column.new(name, default, cast_type, sql_type, null)
612
+ def get_database_version # :nodoc:
390
613
  end
391
614
 
392
- def lookup_cast_type(sql_type) # :nodoc:
393
- type_map.lookup(sql_type)
615
+ def database_version # :nodoc:
616
+ schema_cache.database_version
394
617
  end
395
618
 
396
- def column_name_for_operation(operation, node) # :nodoc:
397
- visitor.accept(node, collector).value
398
- end
399
-
400
- protected
401
-
402
- def initialize_type_map(m) # :nodoc:
403
- register_class_with_limit m, %r(boolean)i, Type::Boolean
404
- register_class_with_limit m, %r(char)i, Type::String
405
- register_class_with_limit m, %r(binary)i, Type::Binary
406
- register_class_with_limit m, %r(text)i, Type::Text
407
- register_class_with_limit m, %r(date)i, Type::Date
408
- register_class_with_limit m, %r(time)i, Type::Time
409
- register_class_with_limit m, %r(datetime)i, Type::DateTime
410
- register_class_with_limit m, %r(float)i, Type::Float
411
- register_class_with_limit m, %r(int)i, Type::Integer
412
-
413
- m.alias_type %r(blob)i, 'binary'
414
- m.alias_type %r(clob)i, 'text'
415
- m.alias_type %r(timestamp)i, 'datetime'
416
- m.alias_type %r(numeric)i, 'decimal'
417
- m.alias_type %r(number)i, 'decimal'
418
- m.alias_type %r(double)i, 'float'
419
-
420
- m.register_type(%r(decimal)i) do |sql_type|
421
- scale = extract_scale(sql_type)
422
- precision = extract_precision(sql_type)
423
-
424
- if scale == 0
425
- # FIXME: Remove this class as well
426
- Type::DecimalWithoutScale.new(precision: precision)
427
- else
428
- Type::Decimal.new(precision: precision, scale: scale)
619
+ def check_version # :nodoc:
620
+ end
621
+
622
+ private
623
+
624
+ def type_map
625
+ @type_map ||= Type::TypeMap.new.tap do |mapping|
626
+ initialize_type_map(mapping)
429
627
  end
430
628
  end
431
- end
432
629
 
433
- def reload_type_map # :nodoc:
434
- type_map.clear
435
- initialize_type_map(type_map)
436
- end
630
+ def initialize_type_map(m = type_map)
631
+ register_class_with_limit m, %r(boolean)i, Type::Boolean
632
+ register_class_with_limit m, %r(char)i, Type::String
633
+ register_class_with_limit m, %r(binary)i, Type::Binary
634
+ register_class_with_limit m, %r(text)i, Type::Text
635
+ register_class_with_precision m, %r(date)i, Type::Date
636
+ register_class_with_precision m, %r(time)i, Type::Time
637
+ register_class_with_precision m, %r(datetime)i, Type::DateTime
638
+ register_class_with_limit m, %r(float)i, Type::Float
639
+ register_class_with_limit m, %r(int)i, Type::Integer
640
+
641
+ m.alias_type %r(blob)i, "binary"
642
+ m.alias_type %r(clob)i, "text"
643
+ m.alias_type %r(timestamp)i, "datetime"
644
+ m.alias_type %r(numeric)i, "decimal"
645
+ m.alias_type %r(number)i, "decimal"
646
+ m.alias_type %r(double)i, "float"
647
+
648
+ m.register_type %r(^json)i, Type::Json.new
649
+
650
+ m.register_type(%r(decimal)i) do |sql_type|
651
+ scale = extract_scale(sql_type)
652
+ precision = extract_precision(sql_type)
653
+
654
+ if scale == 0
655
+ # FIXME: Remove this class as well
656
+ Type::DecimalWithoutScale.new(precision: precision)
657
+ else
658
+ Type::Decimal.new(precision: precision, scale: scale)
659
+ end
660
+ end
661
+ end
437
662
 
438
- def register_class_with_limit(mapping, key, klass) # :nodoc:
439
- mapping.register_type(key) do |*args|
440
- limit = extract_limit(args.last)
441
- klass.new(limit: limit)
663
+ def reload_type_map
664
+ type_map.clear
665
+ initialize_type_map
666
+ end
667
+
668
+ def register_class_with_limit(mapping, key, klass)
669
+ mapping.register_type(key) do |*args|
670
+ limit = extract_limit(args.last)
671
+ klass.new(limit: limit)
672
+ end
673
+ end
674
+
675
+ def register_class_with_precision(mapping, key, klass)
676
+ mapping.register_type(key) do |*args|
677
+ precision = extract_precision(args.last)
678
+ klass.new(precision: precision)
679
+ end
442
680
  end
443
- end
444
681
 
445
- def extract_scale(sql_type) # :nodoc:
446
- case sql_type
682
+ def extract_scale(sql_type)
683
+ case sql_type
447
684
  when /\((\d+)\)/ then 0
448
685
  when /\((\d+)(,(\d+))\)/ then $3.to_i
686
+ end
449
687
  end
450
- end
451
688
 
452
- def extract_precision(sql_type) # :nodoc:
453
- $1.to_i if sql_type =~ /\((\d+)(,\d+)?\)/
454
- end
689
+ def extract_precision(sql_type)
690
+ $1.to_i if sql_type =~ /\((\d+)(,\d+)?\)/
691
+ end
455
692
 
456
- def extract_limit(sql_type) # :nodoc:
457
- case sql_type
458
- when /^bigint/i
459
- 8
460
- when /\((.*)\)/
461
- $1.to_i
693
+ def extract_limit(sql_type)
694
+ $1.to_i if sql_type =~ /\((.*)\)/
462
695
  end
463
- end
464
696
 
465
- def translate_exception_class(e, sql)
466
- begin
467
- message = "#{e.class.name}: #{e.message}: #{sql}"
468
- rescue Encoding::CompatibilityError
469
- message = "#{e.class.name}: #{e.message.force_encoding sql.encoding}: #{sql}"
697
+ def translate_exception_class(e, sql, binds)
698
+ message = "#{e.class.name}: #{e.message}"
699
+
700
+ exception = translate_exception(
701
+ e, message: message, sql: sql, binds: binds
702
+ )
703
+ exception.set_backtrace e.backtrace
704
+ exception
470
705
  end
471
706
 
472
- exception = translate_exception(e, message)
473
- exception.set_backtrace e.backtrace
474
- exception
475
- end
707
+ def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil) # :doc:
708
+ @instrumenter.instrument(
709
+ "sql.active_record",
710
+ sql: sql,
711
+ name: name,
712
+ binds: binds,
713
+ type_casted_binds: type_casted_binds,
714
+ statement_name: statement_name,
715
+ connection_id: object_id,
716
+ connection: self) do
717
+ @lock.synchronize do
718
+ yield
719
+ end
720
+ rescue => e
721
+ raise translate_exception_class(e, sql, binds)
722
+ end
723
+ end
476
724
 
477
- def log(sql, name = "SQL", binds = [], statement_name = nil)
478
- @instrumenter.instrument(
479
- "sql.active_record",
480
- :sql => sql,
481
- :name => name,
482
- :connection_id => object_id,
483
- :statement_name => statement_name,
484
- :binds => binds) { yield }
485
- rescue => e
486
- raise translate_exception_class(e, sql)
487
- end
725
+ def translate_exception(exception, message:, sql:, binds:)
726
+ # override in derived class
727
+ case exception
728
+ when RuntimeError
729
+ exception
730
+ else
731
+ ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds)
732
+ end
733
+ end
488
734
 
489
- def translate_exception(exception, message)
490
- # override in derived class
491
- ActiveRecord::StatementInvalid.new(message, exception)
492
- end
735
+ def without_prepared_statement?(binds)
736
+ !prepared_statements || binds.empty?
737
+ end
493
738
 
494
- def without_prepared_statement?(binds)
495
- !prepared_statements || binds.empty?
496
- end
739
+ def column_for(table_name, column_name)
740
+ column_name = column_name.to_s
741
+ columns(table_name).detect { |c| c.name == column_name } ||
742
+ raise(ActiveRecordError, "No such column: #{table_name}.#{column_name}")
743
+ end
497
744
 
498
- def column_for(table_name, column_name) # :nodoc:
499
- column_name = column_name.to_s
500
- columns(table_name).detect { |c| c.name == column_name } ||
501
- raise(ActiveRecordError, "No such column: #{table_name}.#{column_name}")
502
- end
745
+ def column_for_attribute(attribute)
746
+ table_name = attribute.relation.name
747
+ schema_cache.columns_hash(table_name)[attribute.name.to_s]
748
+ end
749
+
750
+ def collector
751
+ if prepared_statements
752
+ Arel::Collectors::Composite.new(
753
+ Arel::Collectors::SQLString.new,
754
+ Arel::Collectors::Bind.new,
755
+ )
756
+ else
757
+ Arel::Collectors::SubstituteBinds.new(
758
+ self,
759
+ Arel::Collectors::SQLString.new,
760
+ )
761
+ end
762
+ end
763
+
764
+ def arel_visitor
765
+ Arel::Visitors::ToSql.new(self)
766
+ end
767
+
768
+ def build_statement_pool
769
+ end
503
770
  end
504
771
  end
505
772
  end