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
@@ -3,64 +3,18 @@
3
3
  module ActiveRecord
4
4
  module ConnectionAdapters # :nodoc:
5
5
  module DatabaseLimits
6
- # Returns the maximum length of a table alias.
7
- def table_alias_length
8
- 255
9
- end
10
-
11
- # Returns the maximum length of a column name.
12
- def column_name_length
6
+ def max_identifier_length # :nodoc:
13
7
  64
14
8
  end
15
9
 
16
- # Returns the maximum length of a table name.
17
- def table_name_length
18
- 64
19
- end
20
-
21
- # Returns the maximum allowed length for an index name. This
22
- # limit is enforced by \Rails and is less than or equal to
23
- # #index_name_length. The gap between
24
- # #index_name_length is to allow internal \Rails
25
- # operations to use prefixes in temporary operations.
26
- def allowed_index_name_length
27
- index_name_length
10
+ # Returns the maximum length of a table alias.
11
+ def table_alias_length
12
+ max_identifier_length
28
13
  end
29
14
 
30
15
  # Returns the maximum length of an index name.
31
16
  def index_name_length
32
- 64
33
- end
34
-
35
- # Returns the maximum number of columns per table.
36
- def columns_per_table
37
- 1024
38
- end
39
-
40
- # Returns the maximum number of indexes per table.
41
- def indexes_per_table
42
- 16
43
- end
44
-
45
- # Returns the maximum number of columns in a multicolumn index.
46
- def columns_per_multicolumn_index
47
- 16
48
- end
49
-
50
- # Returns the maximum number of elements in an IN (x,y,z) clause.
51
- # +nil+ means no limit.
52
- def in_clause_length
53
- nil
54
- end
55
-
56
- # Returns the maximum length of an SQL query.
57
- def sql_query_length
58
- 1048575
59
- end
60
-
61
- # Returns maximum number of joins in a single query.
62
- def joins_per_query
63
- 256
17
+ max_identifier_length
64
18
  end
65
19
 
66
20
  private
@@ -14,29 +14,32 @@ module ActiveRecord
14
14
  sql
15
15
  end
16
16
 
17
- def to_sql_and_binds(arel_or_sql_string, binds = []) # :nodoc:
17
+ def to_sql_and_binds(arel_or_sql_string, binds = [], preparable = nil) # :nodoc:
18
18
  if arel_or_sql_string.respond_to?(:ast)
19
19
  unless binds.empty?
20
20
  raise "Passing bind parameters with an arel AST is forbidden. " \
21
21
  "The values must be stored on the AST directly"
22
22
  end
23
23
 
24
+ collector = collector()
25
+
24
26
  if prepared_statements
25
- sql, binds = visitor.accept(arel_or_sql_string.ast, collector).value
27
+ collector.preparable = true
28
+ sql, binds = visitor.compile(arel_or_sql_string.ast, collector)
26
29
 
27
30
  if binds.length > bind_params_length
28
31
  unprepared_statement do
29
- sql, binds = to_sql_and_binds(arel_or_sql_string)
30
- visitor.preparable = false
32
+ return to_sql_and_binds(arel_or_sql_string)
31
33
  end
32
34
  end
35
+ preparable = collector.preparable
33
36
  else
34
- sql = visitor.accept(arel_or_sql_string.ast, collector).value
37
+ sql = visitor.compile(arel_or_sql_string.ast, collector)
35
38
  end
36
- [sql.freeze, binds]
39
+ [sql.freeze, binds, preparable]
37
40
  else
38
- visitor.preparable = false if prepared_statements
39
- [arel_or_sql_string.dup.freeze, binds]
41
+ arel_or_sql_string = arel_or_sql_string.dup.freeze unless arel_or_sql_string.frozen?
42
+ [arel_or_sql_string, binds, preparable]
40
43
  end
41
44
  end
42
45
  private :to_sql_and_binds
@@ -45,30 +48,24 @@ module ActiveRecord
45
48
  # can be used to query the database repeatedly.
46
49
  def cacheable_query(klass, arel) # :nodoc:
47
50
  if prepared_statements
48
- sql, binds = visitor.accept(arel.ast, collector).value
51
+ sql, binds = visitor.compile(arel.ast, collector)
49
52
  query = klass.query(sql)
50
53
  else
51
- collector = PartialQueryCollector.new
52
- parts, binds = visitor.accept(arel.ast, collector).value
54
+ collector = klass.partial_query_collector
55
+ parts, binds = visitor.compile(arel.ast, collector)
53
56
  query = klass.partial_query(parts)
54
57
  end
55
58
  [query, binds]
56
59
  end
57
60
 
58
61
  # Returns an ActiveRecord::Result instance.
59
- def select_all(arel, name = nil, binds = [], preparable: nil)
62
+ def select_all(arel, name = nil, binds = [], preparable: nil, async: false)
60
63
  arel = arel_from_relation(arel)
61
- sql, binds = to_sql_and_binds(arel, binds)
62
-
63
- if preparable.nil?
64
- preparable = prepared_statements ? visitor.preparable : false
65
- end
64
+ sql, binds, preparable = to_sql_and_binds(arel, binds, preparable)
66
65
 
67
- if prepared_statements && preparable
68
- select_prepared(sql, name, binds)
69
- else
70
- select(sql, name, binds)
71
- end
66
+ select(sql, name, binds, prepare: prepared_statements && preparable, async: async && FutureResult::SelectAll)
67
+ rescue ::RangeError
68
+ ActiveRecord::Result.empty
72
69
  end
73
70
 
74
71
  # Returns a record hash with the column names as keys and column values
@@ -106,6 +103,11 @@ module ActiveRecord
106
103
  exec_query(sql, name).rows
107
104
  end
108
105
 
106
+ # Determines whether the SQL statement is a write query.
107
+ def write_query?(sql)
108
+ raise NotImplementedError
109
+ end
110
+
109
111
  # Executes the SQL statement in the context of this connection and returns
110
112
  # the raw result from the connection adapter.
111
113
  # Note: depending on your database connector, the result returned by this
@@ -126,7 +128,7 @@ module ActiveRecord
126
128
  # +binds+ as the bind substitutes. +name+ is logged along with
127
129
  # the executed +sql+ statement.
128
130
  def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
129
- sql, binds = sql_for_insert(sql, pk, nil, sequence_name, binds)
131
+ sql, binds = sql_for_insert(sql, pk, binds)
130
132
  exec_query(sql, name, binds)
131
133
  end
132
134
 
@@ -137,11 +139,6 @@ module ActiveRecord
137
139
  exec_query(sql, name, binds)
138
140
  end
139
141
 
140
- # Executes the truncate statement.
141
- def truncate(table_name, name = nil)
142
- raise NotImplementedError
143
- end
144
-
145
142
  # Executes update +sql+ statement in the context of this connection using
146
143
  # +binds+ as the bind substitutes. +name+ is logged along with
147
144
  # the executed +sql+ statement.
@@ -149,6 +146,14 @@ module ActiveRecord
149
146
  exec_query(sql, name, binds)
150
147
  end
151
148
 
149
+ def exec_insert_all(sql, name) # :nodoc:
150
+ exec_query(sql, name)
151
+ end
152
+
153
+ def explain(arel, binds = []) # :nodoc:
154
+ raise NotImplementedError
155
+ end
156
+
152
157
  # Executes an INSERT query and returns the new record's ID
153
158
  #
154
159
  # +id_value+ will be returned unless the value is +nil+, in
@@ -176,27 +181,53 @@ module ActiveRecord
176
181
  exec_delete(sql, name, binds)
177
182
  end
178
183
 
179
- # Returns +true+ when the connection adapter supports prepared statement
180
- # caching, otherwise returns +false+
181
- def supports_statement_cache? # :nodoc:
182
- true
184
+ # Executes the truncate statement.
185
+ def truncate(table_name, name = nil)
186
+ execute(build_truncate_statement(table_name), name)
187
+ end
188
+
189
+ def truncate_tables(*table_names) # :nodoc:
190
+ table_names -= [schema_migration.table_name, InternalMetadata.table_name]
191
+
192
+ return if table_names.empty?
193
+
194
+ with_multi_statements do
195
+ disable_referential_integrity do
196
+ statements = build_truncate_statements(table_names)
197
+ execute_batch(statements, "Truncate Tables")
198
+ end
199
+ end
183
200
  end
184
- deprecate :supports_statement_cache?
185
201
 
186
202
  # Runs the given block in a database transaction, and returns the result
187
203
  # of the block.
188
204
  #
189
205
  # == Nested transactions support
190
206
  #
207
+ # #transaction calls can be nested. By default, this makes all database
208
+ # statements in the nested transaction block become part of the parent
209
+ # transaction. For example, the following behavior may be surprising:
210
+ #
211
+ # ActiveRecord::Base.transaction do
212
+ # Post.create(title: 'first')
213
+ # ActiveRecord::Base.transaction do
214
+ # Post.create(title: 'second')
215
+ # raise ActiveRecord::Rollback
216
+ # end
217
+ # end
218
+ #
219
+ # This creates both "first" and "second" posts. Reason is the
220
+ # ActiveRecord::Rollback exception in the nested block does not issue a
221
+ # ROLLBACK. Since these exceptions are captured in transaction blocks,
222
+ # the parent block does not see it and the real transaction is committed.
223
+ #
191
224
  # Most databases don't support true nested transactions. At the time of
192
225
  # writing, the only database that supports true nested transactions that
193
226
  # we're aware of, is MS-SQL.
194
227
  #
195
228
  # In order to get around this problem, #transaction will emulate the effect
196
229
  # of nested transactions, by using savepoints:
197
- # https://dev.mysql.com/doc/refman/5.7/en/savepoint.html
198
- # Savepoints are supported by MySQL and PostgreSQL. SQLite3 version >= '3.6.8'
199
- # supports savepoints.
230
+ # https://dev.mysql.com/doc/refman/en/savepoint.html.
200
231
  #
201
232
  # It is safe to call this method if a database transaction is already open,
202
233
  # i.e. if #transaction is called within another #transaction block. In case
@@ -208,6 +239,24 @@ module ActiveRecord
208
239
  # - However, if +:requires_new+ is set, the block will be wrapped in a
209
240
  # database savepoint acting as a sub-transaction.
210
241
  #
242
+ # In order to get a ROLLBACK for the nested transaction you may ask for a
243
+ # real sub-transaction by passing <tt>requires_new: true</tt>.
244
+ # If anything goes wrong, the database rolls back to the beginning of
245
+ # the sub-transaction without rolling back the parent transaction.
246
+ # If we add it to the previous example:
247
+ #
248
+ # ActiveRecord::Base.transaction do
249
+ # Post.create(title: 'first')
250
+ # ActiveRecord::Base.transaction(requires_new: true) do
251
+ # Post.create(title: 'second')
252
+ # raise ActiveRecord::Rollback
253
+ # end
254
+ # end
255
+ #
256
+ # only post with title "first" is created.
257
+ #
258
+ # See ActiveRecord::Transactions to learn more.
259
+ #
211
260
  # === Caveats
212
261
  #
213
262
  # MySQL doesn't support DDL transactions. If you perform a DDL operation,
@@ -247,7 +296,7 @@ module ActiveRecord
247
296
  # semantics of these different levels:
248
297
  #
249
298
  # * https://www.postgresql.org/docs/current/static/transaction-iso.html
250
- # * https://dev.mysql.com/doc/refman/5.7/en/set-transaction.html
299
+ # * https://dev.mysql.com/doc/refman/en/set-transaction.html
251
300
  #
252
301
  # An ActiveRecord::TransactionIsolationError will be raised if:
253
302
  #
@@ -257,39 +306,44 @@ module ActiveRecord
257
306
  #
258
307
  # The mysql2 and postgresql adapters support setting the transaction
259
308
  # isolation level.
260
- def transaction(requires_new: nil, isolation: nil, joinable: true)
309
+ def transaction(requires_new: nil, isolation: nil, joinable: true, &block)
261
310
  if !requires_new && current_transaction.joinable?
262
311
  if isolation
263
312
  raise ActiveRecord::TransactionIsolationError, "cannot set isolation when joining a transaction"
264
313
  end
265
314
  yield
266
315
  else
267
- transaction_manager.within_new_transaction(isolation: isolation, joinable: joinable) { yield }
316
+ transaction_manager.within_new_transaction(isolation: isolation, joinable: joinable, &block)
268
317
  end
269
318
  rescue ActiveRecord::Rollback
270
319
  # rollbacks are silently swallowed
271
320
  end
272
321
 
273
- attr_reader :transaction_manager #:nodoc:
322
+ attr_reader :transaction_manager # :nodoc:
323
+
324
+ delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction,
325
+ :commit_transaction, :rollback_transaction, :materialize_transactions,
326
+ :disable_lazy_transactions!, :enable_lazy_transactions!, to: :transaction_manager
274
327
 
275
- delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction, :commit_transaction, :rollback_transaction, to: :transaction_manager
328
+ def mark_transaction_written_if_write(sql) # :nodoc:
329
+ transaction = current_transaction
330
+ if transaction.open?
331
+ transaction.written ||= write_query?(sql)
332
+ end
333
+ end
276
334
 
277
335
  def transaction_open?
278
336
  current_transaction.open?
279
337
  end
280
338
 
281
- def reset_transaction #:nodoc:
339
+ def reset_transaction # :nodoc:
282
340
  @transaction_manager = ConnectionAdapters::TransactionManager.new(self)
283
341
  end
284
342
 
285
343
  # Register a record with the current transaction so that its after_commit and after_rollback callbacks
286
344
  # can be called.
287
- def add_transaction_record(record)
288
- current_transaction.add_record(record)
289
- end
290
-
291
- def transaction_state
292
- current_transaction.state
345
+ def add_transaction_record(record, ensure_finalize = true)
346
+ current_transaction.add_record(record, ensure_finalize)
293
347
  end
294
348
 
295
349
  # Begins the transaction (and turns off auto-committing).
@@ -320,7 +374,7 @@ module ActiveRecord
320
374
  exec_rollback_db_transaction
321
375
  end
322
376
 
323
- def exec_rollback_db_transaction() end #:nodoc:
377
+ def exec_rollback_db_transaction() end # :nodoc:
324
378
 
325
379
  def rollback_to_savepoint(name = nil)
326
380
  exec_rollback_to_savepoint(name)
@@ -336,69 +390,29 @@ module ActiveRecord
336
390
  end
337
391
 
338
392
  # Inserts the given fixture into the table. Overridden in adapters that require
339
- # something beyond a simple insert (eg. Oracle).
340
- # Most of adapters should implement `insert_fixtures` that leverages bulk SQL insert.
393
+ # something beyond a simple insert (e.g. Oracle).
394
+ # Most of adapters should implement +insert_fixtures_set+ that leverages bulk SQL insert.
341
395
  # We keep this method to provide fallback
342
396
  # for databases like sqlite that do not support bulk inserts.
343
397
  def insert_fixture(fixture, table_name)
344
- fixture = fixture.stringify_keys
345
-
346
- columns = schema_cache.columns_hash(table_name)
347
- binds = fixture.map do |name, value|
348
- if column = columns[name]
349
- type = lookup_cast_type_from_column(column)
350
- Relation::QueryAttribute.new(name, value, type)
351
- else
352
- raise Fixture::FixtureError, %(table "#{table_name}" has no column named #{name.inspect}.)
353
- end
354
- end
355
-
356
- table = Arel::Table.new(table_name)
357
-
358
- values = binds.map do |bind|
359
- value = with_yaml_fallback(bind.value_for_database)
360
- [table[bind.name], value]
361
- end
362
-
363
- manager = Arel::InsertManager.new
364
- manager.into(table)
365
- manager.insert(values)
366
- execute manager.to_sql, "Fixture Insert"
367
- end
368
-
369
- # Inserts a set of fixtures into the table. Overridden in adapters that require
370
- # something beyond a simple insert (eg. Oracle).
371
- def insert_fixtures(fixtures, table_name)
372
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
373
- `insert_fixtures` is deprecated and will be removed in the next version of Rails.
374
- Consider using `insert_fixtures_set` for performance improvement.
375
- MSG
376
- return if fixtures.empty?
377
-
378
- execute(build_fixture_sql(fixtures, table_name), "Fixtures Insert")
398
+ execute(build_fixture_sql(Array.wrap(fixture), table_name), "Fixture Insert")
379
399
  end
380
400
 
381
401
  def insert_fixtures_set(fixture_set, tables_to_delete = [])
382
- fixture_inserts = fixture_set.map do |table_name, fixtures|
383
- next if fixtures.empty?
384
-
385
- build_fixture_sql(fixtures, table_name)
386
- end.compact
387
-
388
- table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name table}".dup }
389
- total_sql = Array.wrap(combine_multi_statements(table_deletes + fixture_inserts))
390
-
391
- disable_referential_integrity do
392
- transaction(requires_new: true) do
393
- total_sql.each do |sql|
394
- execute sql, "Fixtures Load"
395
- yield if block_given?
402
+ fixture_inserts = build_fixture_statements(fixture_set)
403
+ table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name(table)}" }
404
+ statements = table_deletes + fixture_inserts
405
+
406
+ with_multi_statements do
407
+ disable_referential_integrity do
408
+ transaction(requires_new: true) do
409
+ execute_batch(statements, "Fixtures Load")
396
410
  end
397
411
  end
398
412
  end
399
413
  end
400
414
 
401
- def empty_insert_statement_value
415
+ def empty_insert_statement_value(primary_key = nil)
402
416
  "DEFAULT VALUES"
403
417
  end
404
418
 
@@ -416,25 +430,48 @@ module ActiveRecord
416
430
  end
417
431
  end
418
432
 
419
- # The default strategy for an UPDATE with joins is to use a subquery. This doesn't work
420
- # on MySQL (even when aliasing the tables), but MySQL allows using JOIN directly in
421
- # an UPDATE statement, so in the MySQL adapters we redefine this to do that.
422
- def join_to_update(update, select, key) # :nodoc:
423
- subselect = subquery_for(key, select)
433
+ # Fixture value is quoted by Arel, however scalar values
434
+ # are not quotable. In this case we want to convert
435
+ # the column value to YAML.
436
+ def with_yaml_fallback(value) # :nodoc:
437
+ if value.is_a?(Hash) || value.is_a?(Array)
438
+ YAML.dump(value)
439
+ else
440
+ value
441
+ end
442
+ end
443
+
444
+ # This is a safe default, even if not high precision on all databases
445
+ HIGH_PRECISION_CURRENT_TIMESTAMP = Arel.sql("CURRENT_TIMESTAMP").freeze # :nodoc:
446
+ private_constant :HIGH_PRECISION_CURRENT_TIMESTAMP
424
447
 
425
- update.where key.in(subselect)
448
+ # Returns an Arel SQL literal for the CURRENT_TIMESTAMP for usage with
449
+ # arbitrary precision date/time columns.
450
+ #
451
+ # Adapters supporting datetime with precision should override this to
452
+ # provide as much precision as is available.
453
+ def high_precision_current_timestamp
454
+ HIGH_PRECISION_CURRENT_TIMESTAMP
426
455
  end
427
- alias join_to_delete join_to_update
428
456
 
429
457
  private
458
+ def execute_batch(statements, name = nil)
459
+ statements.each do |statement|
460
+ execute(statement, name)
461
+ end
462
+ end
463
+
464
+ DEFAULT_INSERT_VALUE = Arel.sql("DEFAULT").freeze
465
+ private_constant :DEFAULT_INSERT_VALUE
466
+
430
467
  def default_insert_value(column)
431
- Arel.sql("DEFAULT")
468
+ DEFAULT_INSERT_VALUE
432
469
  end
433
470
 
434
471
  def build_fixture_sql(fixtures, table_name)
435
- columns = schema_cache.columns_hash(table_name)
472
+ columns = schema_cache.columns_hash(table_name).reject { |_, column| supports_virtual_columns? && column.virtual? }
436
473
 
437
- values = fixtures.map do |fixture|
474
+ values_list = fixtures.map do |fixture|
438
475
  fixture = fixture.stringify_keys
439
476
 
440
477
  unknown_columns = fixture.keys - columns.keys
@@ -445,8 +482,7 @@ module ActiveRecord
445
482
  columns.map do |name, column|
446
483
  if fixture.key?(name)
447
484
  type = lookup_cast_type_from_column(column)
448
- bind = Relation::QueryAttribute.new(name, fixture[name], type)
449
- with_yaml_fallback(bind.value_for_database)
485
+ with_yaml_fallback(type.serialize(fixture[name]))
450
486
  else
451
487
  default_insert_value(column)
452
488
  end
@@ -454,35 +490,77 @@ module ActiveRecord
454
490
  end
455
491
 
456
492
  table = Arel::Table.new(table_name)
457
- manager = Arel::InsertManager.new
458
- manager.into(table)
459
- columns.each_key { |column| manager.columns << table[column] }
460
- manager.values = manager.create_values_list(values)
493
+ manager = Arel::InsertManager.new(table)
494
+
495
+ if values_list.size == 1
496
+ values = values_list.shift
497
+ new_values = []
498
+ columns.each_key.with_index { |column, i|
499
+ unless values[i].equal?(DEFAULT_INSERT_VALUE)
500
+ new_values << values[i]
501
+ manager.columns << table[column]
502
+ end
503
+ }
504
+ values_list << new_values
505
+ else
506
+ columns.each_key { |column| manager.columns << table[column] }
507
+ end
461
508
 
462
- manager.to_sql
509
+ manager.values = manager.create_values_list(values_list)
510
+ visitor.compile(manager.ast)
463
511
  end
464
512
 
465
- def combine_multi_statements(total_sql)
466
- total_sql.join(";\n")
513
+ def build_fixture_statements(fixture_set)
514
+ fixture_set.filter_map do |table_name, fixtures|
515
+ next if fixtures.empty?
516
+ build_fixture_sql(fixtures, table_name)
517
+ end
467
518
  end
468
519
 
469
- # Returns a subquery for the given key using the join information.
470
- def subquery_for(key, select)
471
- subselect = select.clone
472
- subselect.projections = [key]
473
- subselect
520
+ def build_truncate_statement(table_name)
521
+ "TRUNCATE TABLE #{quote_table_name(table_name)}"
474
522
  end
475
523
 
476
- # Returns an ActiveRecord::Result instance.
477
- def select(sql, name = nil, binds = [])
478
- exec_query(sql, name, binds, prepare: false)
524
+ def build_truncate_statements(table_names)
525
+ table_names.map do |table_name|
526
+ build_truncate_statement(table_name)
527
+ end
479
528
  end
480
529
 
481
- def select_prepared(sql, name = nil, binds = [])
482
- exec_query(sql, name, binds, prepare: true)
530
+ def with_multi_statements
531
+ yield
483
532
  end
484
533
 
485
- def sql_for_insert(sql, pk, id_value, sequence_name, binds)
534
+ def combine_multi_statements(total_sql)
535
+ total_sql.join(";\n")
536
+ end
537
+
538
+ # Returns an ActiveRecord::Result instance.
539
+ def select(sql, name = nil, binds = [], prepare: false, async: false)
540
+ if async && async_enabled?
541
+ if current_transaction.joinable?
542
+ raise AsynchronousQueryInsideTransactionError, "Asynchronous queries are not allowed inside transactions"
543
+ end
544
+
545
+ future_result = async.new(
546
+ pool,
547
+ sql,
548
+ name,
549
+ binds,
550
+ prepare: prepare,
551
+ )
552
+ if supports_concurrent_connections? && current_transaction.closed?
553
+ future_result.schedule!(ActiveRecord::Base.asynchronous_queries_session)
554
+ else
555
+ future_result.execute!(self)
556
+ end
557
+ return future_result
558
+ end
559
+
560
+ exec_query(sql, name, binds, prepare: prepare)
561
+ end
562
+
563
+ def sql_for_insert(sql, pk, binds)
486
564
  [sql, binds]
487
565
  end
488
566
 
@@ -502,39 +580,6 @@ module ActiveRecord
502
580
  relation
503
581
  end
504
582
  end
505
-
506
- # Fixture value is quoted by Arel, however scalar values
507
- # are not quotable. In this case we want to convert
508
- # the column value to YAML.
509
- def with_yaml_fallback(value)
510
- if value.is_a?(Hash) || value.is_a?(Array)
511
- YAML.dump(value)
512
- else
513
- value
514
- end
515
- end
516
-
517
- class PartialQueryCollector
518
- def initialize
519
- @parts = []
520
- @binds = []
521
- end
522
-
523
- def <<(str)
524
- @parts << str
525
- self
526
- end
527
-
528
- def add_bind(obj)
529
- @binds << obj
530
- @parts << Arel::Nodes::BindParam.new(1)
531
- self
532
- end
533
-
534
- def value
535
- [@parts, @binds]
536
- end
537
- end
538
583
  end
539
584
  end
540
585
  end