activerecord 5.0.7.2 → 6.0.3.4

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