activerecord 5.2.8 → 7.0.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 (364) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1393 -587
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +7 -5
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record/aggregations.rb +10 -9
  7. data/lib/active_record/association_relation.rb +22 -12
  8. data/lib/active_record/associations/alias_tracker.rb +19 -16
  9. data/lib/active_record/associations/association.rb +122 -47
  10. data/lib/active_record/associations/association_scope.rb +24 -24
  11. data/lib/active_record/associations/belongs_to_association.rb +67 -49
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +16 -7
  13. data/lib/active_record/associations/builder/association.rb +52 -23
  14. data/lib/active_record/associations/builder/belongs_to.rb +44 -61
  15. data/lib/active_record/associations/builder/collection_association.rb +17 -19
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
  17. data/lib/active_record/associations/builder/has_many.rb +10 -3
  18. data/lib/active_record/associations/builder/has_one.rb +35 -3
  19. data/lib/active_record/associations/builder/singular_association.rb +5 -3
  20. data/lib/active_record/associations/collection_association.rb +59 -50
  21. data/lib/active_record/associations/collection_proxy.rb +32 -23
  22. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  23. data/lib/active_record/associations/foreign_association.rb +20 -0
  24. data/lib/active_record/associations/has_many_association.rb +27 -14
  25. data/lib/active_record/associations/has_many_through_association.rb +26 -19
  26. data/lib/active_record/associations/has_one_association.rb +52 -37
  27. data/lib/active_record/associations/has_one_through_association.rb +6 -6
  28. data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
  29. data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
  30. data/lib/active_record/associations/join_dependency.rb +97 -62
  31. data/lib/active_record/associations/preloader/association.rb +220 -60
  32. data/lib/active_record/associations/preloader/batch.rb +48 -0
  33. data/lib/active_record/associations/preloader/branch.rb +147 -0
  34. data/lib/active_record/associations/preloader/through_association.rb +85 -40
  35. data/lib/active_record/associations/preloader.rb +44 -105
  36. data/lib/active_record/associations/singular_association.rb +9 -17
  37. data/lib/active_record/associations/through_association.rb +4 -4
  38. data/lib/active_record/associations.rb +207 -66
  39. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  40. data/lib/active_record/attribute_assignment.rb +17 -19
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +19 -8
  42. data/lib/active_record/attribute_methods/dirty.rb +141 -47
  43. data/lib/active_record/attribute_methods/primary_key.rb +22 -27
  44. data/lib/active_record/attribute_methods/query.rb +6 -10
  45. data/lib/active_record/attribute_methods/read.rb +15 -55
  46. data/lib/active_record/attribute_methods/serialization.rb +77 -18
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +16 -18
  48. data/lib/active_record/attribute_methods/write.rb +18 -37
  49. data/lib/active_record/attribute_methods.rb +90 -153
  50. data/lib/active_record/attributes.rb +38 -12
  51. data/lib/active_record/autosave_association.rb +50 -50
  52. data/lib/active_record/base.rb +23 -18
  53. data/lib/active_record/callbacks.rb +159 -44
  54. data/lib/active_record/coders/yaml_column.rb +12 -3
  55. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +292 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
  57. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
  58. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +92 -464
  59. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -51
  60. data/lib/active_record/connection_adapters/abstract/database_statements.rb +209 -164
  61. data/lib/active_record/connection_adapters/abstract/query_cache.rb +38 -22
  62. data/lib/active_record/connection_adapters/abstract/quoting.rb +103 -82
  63. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  64. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +140 -110
  65. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -94
  66. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +16 -5
  67. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +456 -159
  68. data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -78
  69. data/lib/active_record/connection_adapters/abstract_adapter.rb +367 -162
  70. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +311 -327
  71. data/lib/active_record/connection_adapters/column.rb +33 -11
  72. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  73. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  74. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  75. data/lib/active_record/connection_adapters/mysql/database_statements.rb +113 -45
  76. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  77. data/lib/active_record/connection_adapters/mysql/quoting.rb +71 -5
  78. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
  79. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
  80. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +25 -8
  81. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +143 -19
  82. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
  83. data/lib/active_record/connection_adapters/mysql2_adapter.rb +63 -22
  84. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  85. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  86. data/lib/active_record/connection_adapters/postgresql/column.rb +53 -28
  87. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +56 -63
  88. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  91. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +10 -2
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +15 -2
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +54 -16
  95. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
  97. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
  100. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
  101. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  102. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +26 -12
  105. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
  106. data/lib/active_record/connection_adapters/postgresql/oid.rb +4 -0
  107. data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -52
  108. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +34 -2
  109. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +39 -4
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +128 -91
  111. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -1
  112. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +149 -113
  113. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
  114. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  115. data/lib/active_record/connection_adapters/postgresql_adapter.rb +386 -182
  116. data/lib/active_record/connection_adapters/schema_cache.rb +161 -22
  117. data/lib/active_record/connection_adapters/sql_type_metadata.rb +17 -6
  118. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +152 -0
  119. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +65 -18
  120. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  121. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +92 -26
  122. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +251 -204
  123. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  124. data/lib/active_record/connection_adapters.rb +53 -0
  125. data/lib/active_record/connection_handling.rb +292 -38
  126. data/lib/active_record/core.rb +385 -158
  127. data/lib/active_record/counter_cache.rb +8 -30
  128. data/lib/active_record/database_configurations/connection_url_resolver.rb +100 -0
  129. data/lib/active_record/database_configurations/database_config.rb +83 -0
  130. data/lib/active_record/database_configurations/hash_config.rb +154 -0
  131. data/lib/active_record/database_configurations/url_config.rb +53 -0
  132. data/lib/active_record/database_configurations.rb +256 -0
  133. data/lib/active_record/delegated_type.rb +250 -0
  134. data/lib/active_record/destroy_association_async_job.rb +36 -0
  135. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  136. data/lib/active_record/dynamic_matchers.rb +4 -5
  137. data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
  138. data/lib/active_record/encryption/cipher.rb +53 -0
  139. data/lib/active_record/encryption/config.rb +44 -0
  140. data/lib/active_record/encryption/configurable.rb +61 -0
  141. data/lib/active_record/encryption/context.rb +35 -0
  142. data/lib/active_record/encryption/contexts.rb +72 -0
  143. data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
  144. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  145. data/lib/active_record/encryption/encryptable_record.rb +208 -0
  146. data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
  147. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  148. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  149. data/lib/active_record/encryption/encryptor.rb +155 -0
  150. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  151. data/lib/active_record/encryption/errors.rb +15 -0
  152. data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
  153. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  154. data/lib/active_record/encryption/key.rb +28 -0
  155. data/lib/active_record/encryption/key_generator.rb +42 -0
  156. data/lib/active_record/encryption/key_provider.rb +46 -0
  157. data/lib/active_record/encryption/message.rb +33 -0
  158. data/lib/active_record/encryption/message_serializer.rb +90 -0
  159. data/lib/active_record/encryption/null_encryptor.rb +21 -0
  160. data/lib/active_record/encryption/properties.rb +76 -0
  161. data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
  162. data/lib/active_record/encryption/scheme.rb +99 -0
  163. data/lib/active_record/encryption.rb +55 -0
  164. data/lib/active_record/enum.rb +130 -51
  165. data/lib/active_record/errors.rb +129 -23
  166. data/lib/active_record/explain.rb +10 -6
  167. data/lib/active_record/explain_registry.rb +11 -6
  168. data/lib/active_record/explain_subscriber.rb +1 -1
  169. data/lib/active_record/fixture_set/file.rb +22 -15
  170. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  171. data/lib/active_record/fixture_set/render_context.rb +17 -0
  172. data/lib/active_record/fixture_set/table_row.rb +187 -0
  173. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  174. data/lib/active_record/fixtures.rb +206 -490
  175. data/lib/active_record/future_result.rb +139 -0
  176. data/lib/active_record/gem_version.rb +3 -3
  177. data/lib/active_record/inheritance.rb +104 -37
  178. data/lib/active_record/insert_all.rb +278 -0
  179. data/lib/active_record/integration.rb +69 -18
  180. data/lib/active_record/internal_metadata.rb +24 -9
  181. data/lib/active_record/legacy_yaml_adapter.rb +3 -36
  182. data/lib/active_record/locking/optimistic.rb +41 -26
  183. data/lib/active_record/locking/pessimistic.rb +18 -8
  184. data/lib/active_record/log_subscriber.rb +46 -35
  185. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  186. data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
  187. data/lib/active_record/middleware/database_selector.rb +82 -0
  188. data/lib/active_record/middleware/shard_selector.rb +60 -0
  189. data/lib/active_record/migration/command_recorder.rb +96 -44
  190. data/lib/active_record/migration/compatibility.rb +246 -64
  191. data/lib/active_record/migration/join_table.rb +1 -2
  192. data/lib/active_record/migration.rb +266 -187
  193. data/lib/active_record/model_schema.rb +165 -52
  194. data/lib/active_record/nested_attributes.rb +17 -19
  195. data/lib/active_record/no_touching.rb +11 -4
  196. data/lib/active_record/null_relation.rb +2 -7
  197. data/lib/active_record/persistence.rb +467 -92
  198. data/lib/active_record/query_cache.rb +21 -4
  199. data/lib/active_record/query_logs.rb +138 -0
  200. data/lib/active_record/querying.rb +51 -24
  201. data/lib/active_record/railtie.rb +224 -57
  202. data/lib/active_record/railties/console_sandbox.rb +2 -4
  203. data/lib/active_record/railties/controller_runtime.rb +31 -36
  204. data/lib/active_record/railties/databases.rake +369 -101
  205. data/lib/active_record/readonly_attributes.rb +15 -0
  206. data/lib/active_record/reflection.rb +170 -137
  207. data/lib/active_record/relation/batches/batch_enumerator.rb +44 -14
  208. data/lib/active_record/relation/batches.rb +46 -37
  209. data/lib/active_record/relation/calculations.rb +168 -96
  210. data/lib/active_record/relation/delegation.rb +37 -52
  211. data/lib/active_record/relation/finder_methods.rb +79 -58
  212. data/lib/active_record/relation/from_clause.rb +5 -1
  213. data/lib/active_record/relation/merger.rb +50 -51
  214. data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
  215. data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
  216. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  217. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
  218. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  219. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  220. data/lib/active_record/relation/predicate_builder.rb +58 -46
  221. data/lib/active_record/relation/query_attribute.rb +9 -10
  222. data/lib/active_record/relation/query_methods.rb +685 -208
  223. data/lib/active_record/relation/record_fetch_warning.rb +9 -11
  224. data/lib/active_record/relation/spawn_methods.rb +10 -10
  225. data/lib/active_record/relation/where_clause.rb +108 -64
  226. data/lib/active_record/relation.rb +515 -151
  227. data/lib/active_record/result.rb +78 -42
  228. data/lib/active_record/runtime_registry.rb +9 -13
  229. data/lib/active_record/sanitization.rb +29 -44
  230. data/lib/active_record/schema.rb +37 -31
  231. data/lib/active_record/schema_dumper.rb +74 -23
  232. data/lib/active_record/schema_migration.rb +7 -9
  233. data/lib/active_record/scoping/default.rb +62 -17
  234. data/lib/active_record/scoping/named.rb +17 -32
  235. data/lib/active_record/scoping.rb +70 -41
  236. data/lib/active_record/secure_token.rb +16 -8
  237. data/lib/active_record/serialization.rb +6 -4
  238. data/lib/active_record/signed_id.rb +116 -0
  239. data/lib/active_record/statement_cache.rb +49 -6
  240. data/lib/active_record/store.rb +88 -9
  241. data/lib/active_record/suppressor.rb +13 -17
  242. data/lib/active_record/table_metadata.rb +42 -43
  243. data/lib/active_record/tasks/database_tasks.rb +352 -94
  244. data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
  245. data/lib/active_record/tasks/postgresql_database_tasks.rb +41 -39
  246. data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
  247. data/lib/active_record/test_databases.rb +24 -0
  248. data/lib/active_record/test_fixtures.rb +287 -0
  249. data/lib/active_record/timestamp.rb +44 -34
  250. data/lib/active_record/touch_later.rb +23 -22
  251. data/lib/active_record/transactions.rb +67 -128
  252. data/lib/active_record/translation.rb +3 -3
  253. data/lib/active_record/type/adapter_specific_registry.rb +34 -19
  254. data/lib/active_record/type/hash_lookup_type_map.rb +34 -2
  255. data/lib/active_record/type/internal/timezone.rb +2 -2
  256. data/lib/active_record/type/serialized.rb +7 -4
  257. data/lib/active_record/type/time.rb +10 -0
  258. data/lib/active_record/type/type_map.rb +17 -21
  259. data/lib/active_record/type/unsigned_integer.rb +0 -1
  260. data/lib/active_record/type.rb +9 -5
  261. data/lib/active_record/type_caster/connection.rb +15 -15
  262. data/lib/active_record/type_caster/map.rb +8 -8
  263. data/lib/active_record/validations/associated.rb +2 -3
  264. data/lib/active_record/validations/numericality.rb +35 -0
  265. data/lib/active_record/validations/uniqueness.rb +39 -31
  266. data/lib/active_record/validations.rb +4 -3
  267. data/lib/active_record.rb +209 -32
  268. data/lib/arel/alias_predication.rb +9 -0
  269. data/lib/arel/attributes/attribute.rb +33 -0
  270. data/lib/arel/collectors/bind.rb +29 -0
  271. data/lib/arel/collectors/composite.rb +39 -0
  272. data/lib/arel/collectors/plain_string.rb +20 -0
  273. data/lib/arel/collectors/sql_string.rb +27 -0
  274. data/lib/arel/collectors/substitute_binds.rb +35 -0
  275. data/lib/arel/crud.rb +48 -0
  276. data/lib/arel/delete_manager.rb +32 -0
  277. data/lib/arel/errors.rb +9 -0
  278. data/lib/arel/expressions.rb +29 -0
  279. data/lib/arel/factory_methods.rb +49 -0
  280. data/lib/arel/filter_predications.rb +9 -0
  281. data/lib/arel/insert_manager.rb +48 -0
  282. data/lib/arel/math.rb +45 -0
  283. data/lib/arel/nodes/and.rb +32 -0
  284. data/lib/arel/nodes/ascending.rb +23 -0
  285. data/lib/arel/nodes/binary.rb +126 -0
  286. data/lib/arel/nodes/bind_param.rb +44 -0
  287. data/lib/arel/nodes/case.rb +55 -0
  288. data/lib/arel/nodes/casted.rb +62 -0
  289. data/lib/arel/nodes/comment.rb +29 -0
  290. data/lib/arel/nodes/count.rb +12 -0
  291. data/lib/arel/nodes/delete_statement.rb +44 -0
  292. data/lib/arel/nodes/descending.rb +23 -0
  293. data/lib/arel/nodes/equality.rb +15 -0
  294. data/lib/arel/nodes/extract.rb +24 -0
  295. data/lib/arel/nodes/false.rb +16 -0
  296. data/lib/arel/nodes/filter.rb +10 -0
  297. data/lib/arel/nodes/full_outer_join.rb +8 -0
  298. data/lib/arel/nodes/function.rb +45 -0
  299. data/lib/arel/nodes/grouping.rb +11 -0
  300. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  301. data/lib/arel/nodes/in.rb +15 -0
  302. data/lib/arel/nodes/infix_operation.rb +92 -0
  303. data/lib/arel/nodes/inner_join.rb +8 -0
  304. data/lib/arel/nodes/insert_statement.rb +37 -0
  305. data/lib/arel/nodes/join_source.rb +20 -0
  306. data/lib/arel/nodes/matches.rb +18 -0
  307. data/lib/arel/nodes/named_function.rb +23 -0
  308. data/lib/arel/nodes/node.rb +51 -0
  309. data/lib/arel/nodes/node_expression.rb +13 -0
  310. data/lib/arel/nodes/ordering.rb +27 -0
  311. data/lib/arel/nodes/outer_join.rb +8 -0
  312. data/lib/arel/nodes/over.rb +15 -0
  313. data/lib/arel/nodes/regexp.rb +16 -0
  314. data/lib/arel/nodes/right_outer_join.rb +8 -0
  315. data/lib/arel/nodes/select_core.rb +67 -0
  316. data/lib/arel/nodes/select_statement.rb +41 -0
  317. data/lib/arel/nodes/sql_literal.rb +19 -0
  318. data/lib/arel/nodes/string_join.rb +11 -0
  319. data/lib/arel/nodes/table_alias.rb +31 -0
  320. data/lib/arel/nodes/terminal.rb +16 -0
  321. data/lib/arel/nodes/true.rb +16 -0
  322. data/lib/arel/nodes/unary.rb +44 -0
  323. data/lib/arel/nodes/unary_operation.rb +20 -0
  324. data/lib/arel/nodes/unqualified_column.rb +22 -0
  325. data/lib/arel/nodes/update_statement.rb +46 -0
  326. data/lib/arel/nodes/values_list.rb +9 -0
  327. data/lib/arel/nodes/window.rb +126 -0
  328. data/lib/arel/nodes/with.rb +11 -0
  329. data/lib/arel/nodes.rb +71 -0
  330. data/lib/arel/order_predications.rb +13 -0
  331. data/lib/arel/predications.rb +258 -0
  332. data/lib/arel/select_manager.rb +276 -0
  333. data/lib/arel/table.rb +117 -0
  334. data/lib/arel/tree_manager.rb +60 -0
  335. data/lib/arel/update_manager.rb +48 -0
  336. data/lib/arel/visitors/dot.rb +298 -0
  337. data/lib/arel/visitors/mysql.rb +99 -0
  338. data/lib/arel/visitors/postgresql.rb +110 -0
  339. data/lib/arel/visitors/sqlite.rb +38 -0
  340. data/lib/arel/visitors/to_sql.rb +955 -0
  341. data/lib/arel/visitors/visitor.rb +45 -0
  342. data/lib/arel/visitors.rb +13 -0
  343. data/lib/arel/window_predications.rb +9 -0
  344. data/lib/arel.rb +55 -0
  345. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  346. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  347. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
  348. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
  349. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
  350. data/lib/rails/generators/active_record/migration.rb +19 -2
  351. data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
  352. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  353. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  354. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  355. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  356. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  357. metadata +162 -32
  358. data/lib/active_record/attribute_decorators.rb +0 -90
  359. data/lib/active_record/collection_cache_key.rb +0 -53
  360. data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
  361. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
  362. data/lib/active_record/define_callbacks.rb +0 -22
  363. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
  364. data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_record/connection_adapters/determine_if_preparable_visitor"
4
- require "active_record/connection_adapters/schema_cache"
3
+ require "set"
5
4
  require "active_record/connection_adapters/sql_type_metadata"
6
5
  require "active_record/connection_adapters/abstract/schema_dumper"
7
6
  require "active_record/connection_adapters/abstract/schema_creation"
@@ -13,44 +12,6 @@ require "arel/collectors/substitute_binds"
13
12
 
14
13
  module ActiveRecord
15
14
  module ConnectionAdapters # :nodoc:
16
- extend ActiveSupport::Autoload
17
-
18
- autoload :Column
19
- autoload :ConnectionSpecification
20
-
21
- autoload_at "active_record/connection_adapters/abstract/schema_definitions" do
22
- autoload :IndexDefinition
23
- autoload :ColumnDefinition
24
- autoload :ChangeColumnDefinition
25
- autoload :ForeignKeyDefinition
26
- autoload :TableDefinition
27
- autoload :Table
28
- autoload :AlterTable
29
- autoload :ReferenceDefinition
30
- end
31
-
32
- autoload_at "active_record/connection_adapters/abstract/connection_pool" do
33
- autoload :ConnectionHandler
34
- end
35
-
36
- autoload_under "abstract" do
37
- autoload :SchemaStatements
38
- autoload :DatabaseStatements
39
- autoload :DatabaseLimits
40
- autoload :Quoting
41
- autoload :ConnectionPool
42
- autoload :QueryCache
43
- autoload :Savepoints
44
- end
45
-
46
- autoload_at "active_record/connection_adapters/abstract/transaction" do
47
- autoload :TransactionManager
48
- autoload :NullTransaction
49
- autoload :RealTransaction
50
- autoload :SavepointTransaction
51
- autoload :TransactionState
52
- end
53
-
54
15
  # Active Record supports multiple database systems. AbstractAdapter and
55
16
  # related classes form the abstraction layer which makes this possible.
56
17
  # An AbstractAdapter represents a connection to a database, and provides an
@@ -65,7 +26,7 @@ module ActiveRecord
65
26
  # Most of the methods in the adapter are useful during migrations. Most
66
27
  # notably, the instance methods provided by SchemaStatements are very useful.
67
28
  class AbstractAdapter
68
- ADAPTER_NAME = "Abstract".freeze
29
+ ADAPTER_NAME = "Abstract"
69
30
  include ActiveSupport::Callbacks
70
31
  define_callbacks :checkout, :checkin
71
32
 
@@ -75,15 +36,18 @@ module ActiveRecord
75
36
  include Savepoints
76
37
 
77
38
  SIMPLE_INT = /\A\d+\z/
39
+ COMMENT_REGEX = %r{(?:--.*\n)*|/\*(?:[^*]|\*[^/])*\*/}m
78
40
 
79
- attr_accessor :visitor, :pool
80
- attr_reader :schema_cache, :owner, :logger, :prepared_statements, :lock
41
+ attr_accessor :pool
42
+ attr_reader :visitor, :owner, :logger, :lock
81
43
  alias :in_use? :owner
82
44
 
45
+ set_callback :checkin, :after, :enable_lazy_transactions!
46
+
83
47
  def self.type_cast_config_to_integer(config)
84
48
  if config.is_a?(Integer)
85
49
  config
86
- elsif config =~ SIMPLE_INT
50
+ elsif SIMPLE_INT.match?(config)
87
51
  config.to_i
88
52
  else
89
53
  config
@@ -98,6 +62,23 @@ module ActiveRecord
98
62
  end
99
63
  end
100
64
 
65
+ DEFAULT_READ_QUERY = [:begin, :commit, :explain, :release, :rollback, :savepoint, :select, :with] # :nodoc:
66
+ private_constant :DEFAULT_READ_QUERY
67
+
68
+ def self.build_read_query_regexp(*parts) # :nodoc:
69
+ parts += DEFAULT_READ_QUERY
70
+ parts = parts.map { |part| /#{part}/i }
71
+ /\A(?:[(\s]|#{COMMENT_REGEX})*#{Regexp.union(*parts)}/
72
+ end
73
+
74
+ def self.quoted_column_names # :nodoc:
75
+ @quoted_column_names ||= {}
76
+ end
77
+
78
+ def self.quoted_table_names # :nodoc:
79
+ @quoted_table_names ||= {}
80
+ end
81
+
101
82
  def initialize(connection, logger = nil, config = {}) # :nodoc:
102
83
  super()
103
84
 
@@ -106,39 +87,117 @@ module ActiveRecord
106
87
  @instrumenter = ActiveSupport::Notifications.instrumenter
107
88
  @logger = logger
108
89
  @config = config
109
- @pool = nil
110
- @idle_since = Concurrent.monotonic_time
111
- @schema_cache = SchemaCache.new self
112
- @quoted_column_names, @quoted_table_names = {}, {}
90
+ @pool = ActiveRecord::ConnectionAdapters::NullPool.new
91
+ @idle_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
113
92
  @visitor = arel_visitor
93
+ @statements = build_statement_pool
114
94
  @lock = ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
115
95
 
116
- if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
117
- @prepared_statements = true
118
- @visitor.extend(DetermineIfPreparableVisitor)
119
- else
120
- @prepared_statements = false
96
+ @prepared_statements = self.class.type_cast_config_to_boolean(
97
+ config.fetch(:prepared_statements, true)
98
+ )
99
+
100
+ @advisory_locks_enabled = self.class.type_cast_config_to_boolean(
101
+ config.fetch(:advisory_locks, true)
102
+ )
103
+ end
104
+
105
+ EXCEPTION_NEVER = { Exception => :never }.freeze # :nodoc:
106
+ EXCEPTION_IMMEDIATE = { Exception => :immediate }.freeze # :nodoc:
107
+ private_constant :EXCEPTION_NEVER, :EXCEPTION_IMMEDIATE
108
+ def with_instrumenter(instrumenter, &block) # :nodoc:
109
+ Thread.handle_interrupt(EXCEPTION_NEVER) do
110
+ previous_instrumenter = @instrumenter
111
+ @instrumenter = instrumenter
112
+ Thread.handle_interrupt(EXCEPTION_IMMEDIATE, &block)
113
+ ensure
114
+ @instrumenter = previous_instrumenter
115
+ end
116
+ end
117
+
118
+ def check_if_write_query(sql) # :nodoc:
119
+ if preventing_writes? && write_query?(sql)
120
+ raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
121
121
  end
122
122
  end
123
123
 
124
+ def replica?
125
+ @config[:replica] || false
126
+ end
127
+
128
+ def use_metadata_table?
129
+ @config.fetch(:use_metadata_table, true)
130
+ end
131
+
132
+ # Determines whether writes are currently being prevented.
133
+ #
134
+ # Returns true if the connection is a replica.
135
+ #
136
+ # If the application is using legacy handling, returns
137
+ # true if +connection_handler.prevent_writes+ is set.
138
+ #
139
+ # If the application is using the new connection handling
140
+ # will return true based on +current_preventing_writes+.
141
+ def preventing_writes?
142
+ return true if replica?
143
+ return ActiveRecord::Base.connection_handler.prevent_writes if ActiveRecord.legacy_connection_handling
144
+ return false if connection_class.nil?
145
+
146
+ connection_class.current_preventing_writes
147
+ end
148
+
124
149
  def migrations_paths # :nodoc:
125
150
  @config[:migrations_paths] || Migrator.migrations_paths
126
151
  end
127
152
 
128
153
  def migration_context # :nodoc:
129
- MigrationContext.new(migrations_paths)
154
+ MigrationContext.new(migrations_paths, schema_migration)
155
+ end
156
+
157
+ def schema_migration # :nodoc:
158
+ @schema_migration ||= begin
159
+ conn = self
160
+ spec_name = conn.pool.pool_config.connection_specification_name
161
+
162
+ return ActiveRecord::SchemaMigration if spec_name == "ActiveRecord::Base"
163
+
164
+ schema_migration_name = "#{spec_name}::SchemaMigration"
165
+
166
+ Class.new(ActiveRecord::SchemaMigration) do
167
+ define_singleton_method(:name) { schema_migration_name }
168
+ define_singleton_method(:to_s) { schema_migration_name }
169
+
170
+ self.connection_specification_name = spec_name
171
+ end
172
+ end
173
+ end
174
+
175
+ def prepared_statements?
176
+ @prepared_statements && !prepared_statements_disabled_cache.include?(object_id)
177
+ end
178
+ alias :prepared_statements :prepared_statements?
179
+
180
+ def prepared_statements_disabled_cache # :nodoc:
181
+ ActiveSupport::IsolatedExecutionState[:active_record_prepared_statements_disabled_cache] ||= Set.new
130
182
  end
131
183
 
132
184
  class Version
133
185
  include Comparable
134
186
 
135
- def initialize(version_string)
187
+ attr_reader :full_version_string
188
+
189
+ def initialize(version_string, full_version_string = nil)
136
190
  @version = version_string.split(".").map(&:to_i)
191
+ @full_version_string = full_version_string
137
192
  end
138
193
 
139
194
  def <=>(version_string)
140
195
  @version <=> version_string.split(".").map(&:to_i)
141
196
  end
197
+
198
+ def to_s
199
+ @version.join(".")
200
+ end
142
201
  end
143
202
 
144
203
  def valid_type?(type) # :nodoc:
@@ -148,7 +207,7 @@ module ActiveRecord
148
207
  # this method must only be called while holding connection pool's mutex
149
208
  def lease
150
209
  if in_use?
151
- msg = "Cannot lease connection, ".dup
210
+ msg = +"Cannot lease connection, "
152
211
  if @owner == Thread.current
153
212
  msg << "it is already leased by the current thread."
154
213
  else
@@ -161,9 +220,29 @@ module ActiveRecord
161
220
  @owner = Thread.current
162
221
  end
163
222
 
223
+ def connection_class # :nodoc:
224
+ @pool.connection_class
225
+ end
226
+
227
+ # The role (ie :writing) for the current connection. In a
228
+ # non-multi role application, `:writing` is returned.
229
+ def role
230
+ @pool.role
231
+ end
232
+
233
+ # The shard (ie :default) for the current connection. In
234
+ # a non-sharded application, `:default` is returned.
235
+ def shard
236
+ @pool.shard
237
+ end
238
+
239
+ def schema_cache
240
+ @pool.get_schema_cache(self)
241
+ end
242
+
164
243
  def schema_cache=(cache)
165
244
  cache.connection = self
166
- @schema_cache = cache
245
+ @pool.set_schema_cache(cache)
167
246
  end
168
247
 
169
248
  # this method must only be called while holding connection pool's mutex
@@ -175,7 +254,7 @@ module ActiveRecord
175
254
  "Current thread: #{Thread.current}."
176
255
  end
177
256
 
178
- @idle_since = Concurrent.monotonic_time
257
+ @idle_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
179
258
  @owner = nil
180
259
  else
181
260
  raise ActiveRecordError, "Cannot expire connection, it is not currently leased."
@@ -198,14 +277,14 @@ module ActiveRecord
198
277
  # Seconds since this connection was returned to the pool
199
278
  def seconds_idle # :nodoc:
200
279
  return 0 if in_use?
201
- Concurrent.monotonic_time - @idle_since
280
+ Process.clock_gettime(Process::CLOCK_MONOTONIC) - @idle_since
202
281
  end
203
282
 
204
283
  def unprepared_statement
205
- old_prepared_statements, @prepared_statements = @prepared_statements, false
284
+ cache = prepared_statements_disabled_cache.add?(object_id) if @prepared_statements
206
285
  yield
207
286
  ensure
208
- @prepared_statements = old_prepared_statements
287
+ cache&.delete(object_id)
209
288
  end
210
289
 
211
290
  # Returns the human-readable name of the adapter. Use mixed case - one
@@ -214,6 +293,11 @@ module ActiveRecord
214
293
  self.class::ADAPTER_NAME
215
294
  end
216
295
 
296
+ # Does the database for this adapter exist?
297
+ def self.database_exists?(config)
298
+ raise NotImplementedError
299
+ end
300
+
217
301
  # Does this adapter support DDL rollbacks in transactions? That is, would
218
302
  # CREATE TABLE or ALTER TABLE get rolled back by a transaction?
219
303
  def supports_ddl_transactions?
@@ -241,6 +325,10 @@ module ActiveRecord
241
325
  false
242
326
  end
243
327
 
328
+ def supports_partitioned_indexes?
329
+ false
330
+ end
331
+
244
332
  # Does this adapter support index sort order?
245
333
  def supports_index_sort_order?
246
334
  false
@@ -287,10 +375,14 @@ module ActiveRecord
287
375
  false
288
376
  end
289
377
 
290
- # Does this adapter support creating foreign key constraints
291
- # in the same statement as creating the table?
292
- def supports_foreign_keys_in_create?
293
- supports_foreign_keys?
378
+ # Does this adapter support creating deferrable constraints?
379
+ def supports_deferrable_constraints?
380
+ false
381
+ end
382
+
383
+ # Does this adapter support creating check constraints?
384
+ def supports_check_constraints?
385
+ false
294
386
  end
295
387
 
296
388
  # Does this adapter support views?
@@ -298,6 +390,11 @@ module ActiveRecord
298
390
  false
299
391
  end
300
392
 
393
+ # Does this adapter support materialized views?
394
+ def supports_materialized_views?
395
+ false
396
+ end
397
+
301
398
  # Does this adapter support datetime with precision?
302
399
  def supports_datetime_with_precision?
303
400
  false
@@ -318,11 +415,6 @@ module ActiveRecord
318
415
  false
319
416
  end
320
417
 
321
- # Does this adapter support multi-value insert?
322
- def supports_multi_insert?
323
- true
324
- end
325
-
326
418
  # Does this adapter support virtual columns?
327
419
  def supports_virtual_columns?
328
420
  false
@@ -333,6 +425,44 @@ module ActiveRecord
333
425
  false
334
426
  end
335
427
 
428
+ # Does this adapter support optimizer hints?
429
+ def supports_optimizer_hints?
430
+ false
431
+ end
432
+
433
+ def supports_common_table_expressions?
434
+ false
435
+ end
436
+
437
+ def supports_lazy_transactions?
438
+ false
439
+ end
440
+
441
+ def supports_insert_returning?
442
+ false
443
+ end
444
+
445
+ def supports_insert_on_duplicate_skip?
446
+ false
447
+ end
448
+
449
+ def supports_insert_on_duplicate_update?
450
+ false
451
+ end
452
+
453
+ def supports_insert_conflict_target?
454
+ false
455
+ end
456
+
457
+ def supports_concurrent_connections?
458
+ true
459
+ end
460
+
461
+ def async_enabled? # :nodoc:
462
+ supports_concurrent_connections? &&
463
+ !ActiveRecord.async_query_executor.nil? && !pool.async_executor.nil?
464
+ end
465
+
336
466
  # This is meant to be implemented by the adapters that support extensions
337
467
  def disable_extension(name)
338
468
  end
@@ -341,6 +471,14 @@ module ActiveRecord
341
471
  def enable_extension(name)
342
472
  end
343
473
 
474
+ # This is meant to be implemented by the adapters that support custom enum types
475
+ def create_enum(*) # :nodoc:
476
+ end
477
+
478
+ def advisory_locks_enabled? # :nodoc:
479
+ supports_advisory_locks? && @advisory_locks_enabled
480
+ end
481
+
344
482
  # This is meant to be implemented by the adapters that support advisory
345
483
  # locks
346
484
  #
@@ -372,6 +510,11 @@ module ActiveRecord
372
510
  yield
373
511
  end
374
512
 
513
+ # Override to check all foreign key constraints in a database.
514
+ def all_foreign_keys_valid?
515
+ true
516
+ end
517
+
375
518
  # CONNECTION MANAGEMENT ====================================
376
519
 
377
520
  # Checks whether the connection to the database is still active. This includes
@@ -406,6 +549,9 @@ module ActiveRecord
406
549
  #
407
550
  # Prevent @connection's finalizer from touching the socket, or
408
551
  # otherwise communicating with its server, when it is collected.
552
+ if schema_cache.connection == self
553
+ schema_cache.connection = nil
554
+ end
409
555
  end
410
556
 
411
557
  # Reset the state of this connection, directing the DBMS to clear
@@ -418,11 +564,15 @@ module ActiveRecord
418
564
  # this should be overridden by concrete adapters
419
565
  end
420
566
 
421
- ###
422
- # Clear any caching the database adapter may be doing, for example
423
- # clearing the prepared statement cache. This is database specific.
567
+ # Removes the connection from the pool and disconnect it.
568
+ def throw_away!
569
+ pool.remove self
570
+ disconnect!
571
+ end
572
+
573
+ # Clear any caching the database adapter may be doing.
424
574
  def clear_cache!
425
- # this should be overridden by concrete adapters
575
+ @lock.synchronize { @statements.clear } if @statements
426
576
  end
427
577
 
428
578
  # Returns true if its required to reload the connection between requests for development mode.
@@ -444,18 +594,25 @@ module ActiveRecord
444
594
  # This is useful for when you need to call a proprietary method such as
445
595
  # PostgreSQL's lo_* methods.
446
596
  def raw_connection
597
+ disable_lazy_transactions!
447
598
  @connection
448
599
  end
449
600
 
450
- def case_sensitive_comparison(table, attribute, column, value) # :nodoc:
451
- table[attribute].eq(value)
601
+ def default_uniqueness_comparison(attribute, value) # :nodoc:
602
+ attribute.eq(value)
452
603
  end
453
604
 
454
- def case_insensitive_comparison(table, attribute, column, value) # :nodoc:
605
+ def case_sensitive_comparison(attribute, value) # :nodoc:
606
+ attribute.eq(value)
607
+ end
608
+
609
+ def case_insensitive_comparison(attribute, value) # :nodoc:
610
+ column = column_for_attribute(attribute)
611
+
455
612
  if can_perform_case_insensitive_comparison_for?(column)
456
- table[attribute].lower.eq(table.lower(value))
613
+ attribute.lower.eq(attribute.relation.lower(value))
457
614
  else
458
- table[attribute].eq(value)
615
+ attribute.eq(value)
459
616
  end
460
617
  end
461
618
 
@@ -469,105 +626,133 @@ module ActiveRecord
469
626
  pool.checkin self
470
627
  end
471
628
 
472
- def column_name_for_operation(operation, node) # :nodoc:
473
- column_name_from_arel_node(node)
629
+ def default_index_type?(index) # :nodoc:
630
+ index.using.nil?
474
631
  end
475
632
 
476
- def column_name_from_arel_node(node) # :nodoc:
477
- visitor.accept(node, Arel::Collectors::SQLString.new).value
633
+ # Called by ActiveRecord::InsertAll,
634
+ # Passed an instance of ActiveRecord::InsertAll::Builder,
635
+ # This method implements standard bulk inserts for all databases, but
636
+ # should be overridden by adapters to implement common features with
637
+ # non-standard syntax like handling duplicates or returning values.
638
+ def build_insert_sql(insert) # :nodoc:
639
+ if insert.skip_duplicates? || insert.update_duplicates?
640
+ raise NotImplementedError, "#{self.class} should define `build_insert_sql` to implement adapter-specific logic for handling duplicates during INSERT"
641
+ end
642
+
643
+ "INSERT #{insert.into} #{insert.values_list}"
478
644
  end
479
645
 
480
- def default_index_type?(index) # :nodoc:
481
- index.using.nil?
646
+ def get_database_version # :nodoc:
482
647
  end
483
648
 
484
- private
485
- def type_map
486
- @type_map ||= Type::TypeMap.new.tap do |mapping|
487
- initialize_type_map(mapping)
488
- end
649
+ def database_version # :nodoc:
650
+ schema_cache.database_version
651
+ end
652
+
653
+ def check_version # :nodoc:
654
+ end
655
+
656
+ # Returns the version identifier of the schema currently available in
657
+ # the database. This is generally equal to the number of the highest-
658
+ # numbered migration that has been executed, or 0 if no schema
659
+ # information is present / the database is empty.
660
+ def schema_version
661
+ migration_context.current_version
662
+ end
663
+
664
+ def field_ordered_value(column, values) # :nodoc:
665
+ node = Arel::Nodes::Case.new(column)
666
+ values.each.with_index(1) do |value, order|
667
+ node.when(value).then(order)
489
668
  end
490
669
 
491
- def initialize_type_map(m = type_map)
492
- register_class_with_limit m, %r(boolean)i, Type::Boolean
493
- register_class_with_limit m, %r(char)i, Type::String
494
- register_class_with_limit m, %r(binary)i, Type::Binary
495
- register_class_with_limit m, %r(text)i, Type::Text
496
- register_class_with_precision m, %r(date)i, Type::Date
497
- register_class_with_precision m, %r(time)i, Type::Time
498
- register_class_with_precision m, %r(datetime)i, Type::DateTime
499
- register_class_with_limit m, %r(float)i, Type::Float
500
- register_class_with_limit m, %r(int)i, Type::Integer
501
-
502
- m.alias_type %r(blob)i, "binary"
503
- m.alias_type %r(clob)i, "text"
504
- m.alias_type %r(timestamp)i, "datetime"
505
- m.alias_type %r(numeric)i, "decimal"
506
- m.alias_type %r(number)i, "decimal"
507
- m.alias_type %r(double)i, "float"
508
-
509
- m.register_type %r(^json)i, Type::Json.new
510
-
511
- m.register_type(%r(decimal)i) do |sql_type|
512
- scale = extract_scale(sql_type)
513
- precision = extract_precision(sql_type)
514
-
515
- if scale == 0
516
- # FIXME: Remove this class as well
517
- Type::DecimalWithoutScale.new(precision: precision)
518
- else
519
- Type::Decimal.new(precision: precision, scale: scale)
670
+ Arel::Nodes::Ascending.new(node.else(values.length + 1))
671
+ end
672
+
673
+ class << self
674
+ private
675
+ def initialize_type_map(m)
676
+ register_class_with_limit m, %r(boolean)i, Type::Boolean
677
+ register_class_with_limit m, %r(char)i, Type::String
678
+ register_class_with_limit m, %r(binary)i, Type::Binary
679
+ register_class_with_limit m, %r(text)i, Type::Text
680
+ register_class_with_precision m, %r(date)i, Type::Date
681
+ register_class_with_precision m, %r(time)i, Type::Time
682
+ register_class_with_precision m, %r(datetime)i, Type::DateTime
683
+ register_class_with_limit m, %r(float)i, Type::Float
684
+ register_class_with_limit m, %r(int)i, Type::Integer
685
+
686
+ m.alias_type %r(blob)i, "binary"
687
+ m.alias_type %r(clob)i, "text"
688
+ m.alias_type %r(timestamp)i, "datetime"
689
+ m.alias_type %r(numeric)i, "decimal"
690
+ m.alias_type %r(number)i, "decimal"
691
+ m.alias_type %r(double)i, "float"
692
+
693
+ m.register_type %r(^json)i, Type::Json.new
694
+
695
+ m.register_type(%r(decimal)i) do |sql_type|
696
+ scale = extract_scale(sql_type)
697
+ precision = extract_precision(sql_type)
698
+
699
+ if scale == 0
700
+ # FIXME: Remove this class as well
701
+ Type::DecimalWithoutScale.new(precision: precision)
702
+ else
703
+ Type::Decimal.new(precision: precision, scale: scale)
704
+ end
520
705
  end
521
706
  end
522
- end
523
707
 
524
- def reload_type_map
525
- type_map.clear
526
- initialize_type_map
527
- end
708
+ def register_class_with_limit(mapping, key, klass)
709
+ mapping.register_type(key) do |*args|
710
+ limit = extract_limit(args.last)
711
+ klass.new(limit: limit)
712
+ end
713
+ end
528
714
 
529
- def register_class_with_limit(mapping, key, klass)
530
- mapping.register_type(key) do |*args|
531
- limit = extract_limit(args.last)
532
- klass.new(limit: limit)
715
+ def register_class_with_precision(mapping, key, klass)
716
+ mapping.register_type(key) do |*args|
717
+ precision = extract_precision(args.last)
718
+ klass.new(precision: precision)
719
+ end
533
720
  end
534
- end
535
721
 
536
- def register_class_with_precision(mapping, key, klass)
537
- mapping.register_type(key) do |*args|
538
- precision = extract_precision(args.last)
539
- klass.new(precision: precision)
722
+ def extract_scale(sql_type)
723
+ case sql_type
724
+ when /\((\d+)\)/ then 0
725
+ when /\((\d+)(,(\d+))\)/ then $3.to_i
726
+ end
540
727
  end
541
- end
542
728
 
543
- def extract_scale(sql_type)
544
- case sql_type
545
- when /\((\d+)\)/ then 0
546
- when /\((\d+)(,(\d+))\)/ then $3.to_i
729
+ def extract_precision(sql_type)
730
+ $1.to_i if sql_type =~ /\((\d+)(,\d+)?\)/
547
731
  end
548
- end
549
732
 
550
- def extract_precision(sql_type)
551
- $1.to_i if sql_type =~ /\((\d+)(,\d+)?\)/
552
- end
733
+ def extract_limit(sql_type)
734
+ $1.to_i if sql_type =~ /\((.*)\)/
735
+ end
736
+ end
737
+
738
+ TYPE_MAP = Type::TypeMap.new.tap { |m| initialize_type_map(m) }
553
739
 
554
- def extract_limit(sql_type)
555
- $1.to_i if sql_type =~ /\((.*)\)/
740
+ private
741
+ def type_map
742
+ TYPE_MAP
556
743
  end
557
744
 
558
- def translate_exception_class(e, sql)
559
- begin
560
- message = "#{e.class.name}: #{e.message}: #{sql}"
561
- rescue Encoding::CompatibilityError
562
- message = "#{e.class.name}: #{e.message.force_encoding sql.encoding}: #{sql}"
563
- end
745
+ def translate_exception_class(e, sql, binds)
746
+ message = "#{e.class.name}: #{e.message}"
564
747
 
565
- exception = translate_exception(e, message)
748
+ exception = translate_exception(
749
+ e, message: message, sql: sql, binds: binds
750
+ )
566
751
  exception.set_backtrace e.backtrace
567
752
  exception
568
753
  end
569
754
 
570
- def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil) # :doc:
755
+ def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil, async: false, &block) # :doc:
571
756
  @instrumenter.instrument(
572
757
  "sql.active_record",
573
758
  sql: sql,
@@ -575,24 +760,28 @@ module ActiveRecord
575
760
  binds: binds,
576
761
  type_casted_binds: type_casted_binds,
577
762
  statement_name: statement_name,
578
- connection_id: object_id) do
579
- begin
580
- @lock.synchronize do
581
- yield
582
- end
583
- rescue => e
584
- raise translate_exception_class(e, sql)
585
- end
763
+ async: async,
764
+ connection: self) do
765
+ @lock.synchronize(&block)
766
+ rescue => e
767
+ raise translate_exception_class(e, sql, binds)
768
+ end
769
+ end
770
+
771
+ def transform_query(sql)
772
+ ActiveRecord.query_transformers.each do |transformer|
773
+ sql = transformer.call(sql)
586
774
  end
775
+ sql
587
776
  end
588
777
 
589
- def translate_exception(exception, message)
778
+ def translate_exception(exception, message:, sql:, binds:)
590
779
  # override in derived class
591
780
  case exception
592
781
  when RuntimeError
593
782
  exception
594
783
  else
595
- ActiveRecord::StatementInvalid.new(message)
784
+ ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds)
596
785
  end
597
786
  end
598
787
 
@@ -606,6 +795,11 @@ module ActiveRecord
606
795
  raise(ActiveRecordError, "No such column: #{table_name}.#{column_name}")
607
796
  end
608
797
 
798
+ def column_for_attribute(attribute)
799
+ table_name = attribute.relation.name
800
+ schema_cache.columns_hash(table_name)[attribute.name.to_s]
801
+ end
802
+
609
803
  def collector
610
804
  if prepared_statements
611
805
  Arel::Collectors::Composite.new(
@@ -623,6 +817,17 @@ module ActiveRecord
623
817
  def arel_visitor
624
818
  Arel::Visitors::ToSql.new(self)
625
819
  end
820
+
821
+ def build_statement_pool
822
+ end
823
+
824
+ # Builds the result object.
825
+ #
826
+ # This is an internal hook to make possible connection adapters to build
827
+ # custom result objects with connection-specific data.
828
+ def build_result(columns:, rows:, column_types: {})
829
+ ActiveRecord::Result.new(columns, rows, column_types)
830
+ end
626
831
  end
627
832
  end
628
833
  end