activerecord 6.1.7 → 7.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (311) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +2030 -1020
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +18 -18
  5. data/lib/active_record/aggregations.rb +17 -14
  6. data/lib/active_record/association_relation.rb +1 -11
  7. data/lib/active_record/associations/association.rb +51 -19
  8. data/lib/active_record/associations/association_scope.rb +17 -12
  9. data/lib/active_record/associations/belongs_to_association.rb +28 -9
  10. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
  11. data/lib/active_record/associations/builder/association.rb +11 -5
  12. data/lib/active_record/associations/builder/belongs_to.rb +40 -14
  13. data/lib/active_record/associations/builder/collection_association.rb +10 -3
  14. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
  15. data/lib/active_record/associations/builder/has_many.rb +3 -2
  16. data/lib/active_record/associations/builder/has_one.rb +2 -1
  17. data/lib/active_record/associations/builder/singular_association.rb +6 -2
  18. data/lib/active_record/associations/collection_association.rb +39 -35
  19. data/lib/active_record/associations/collection_proxy.rb +30 -15
  20. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  21. data/lib/active_record/associations/foreign_association.rb +10 -3
  22. data/lib/active_record/associations/has_many_association.rb +28 -18
  23. data/lib/active_record/associations/has_many_through_association.rb +12 -7
  24. data/lib/active_record/associations/has_one_association.rb +20 -10
  25. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  26. data/lib/active_record/associations/join_dependency/join_association.rb +3 -2
  27. data/lib/active_record/associations/join_dependency.rb +28 -20
  28. data/lib/active_record/associations/preloader/association.rb +210 -52
  29. data/lib/active_record/associations/preloader/batch.rb +48 -0
  30. data/lib/active_record/associations/preloader/branch.rb +147 -0
  31. data/lib/active_record/associations/preloader/through_association.rb +50 -14
  32. data/lib/active_record/associations/preloader.rb +50 -121
  33. data/lib/active_record/associations/singular_association.rb +9 -3
  34. data/lib/active_record/associations/through_association.rb +25 -14
  35. data/lib/active_record/associations.rb +446 -306
  36. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  37. data/lib/active_record/attribute_assignment.rb +1 -3
  38. data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
  39. data/lib/active_record/attribute_methods/dirty.rb +73 -22
  40. data/lib/active_record/attribute_methods/primary_key.rb +78 -26
  41. data/lib/active_record/attribute_methods/query.rb +31 -19
  42. data/lib/active_record/attribute_methods/read.rb +27 -12
  43. data/lib/active_record/attribute_methods/serialization.rb +194 -37
  44. data/lib/active_record/attribute_methods/time_zone_conversion.rb +8 -3
  45. data/lib/active_record/attribute_methods/write.rb +12 -15
  46. data/lib/active_record/attribute_methods.rb +161 -40
  47. data/lib/active_record/attributes.rb +27 -38
  48. data/lib/active_record/autosave_association.rb +65 -31
  49. data/lib/active_record/base.rb +25 -2
  50. data/lib/active_record/callbacks.rb +18 -34
  51. data/lib/active_record/coders/column_serializer.rb +61 -0
  52. data/lib/active_record/coders/json.rb +1 -1
  53. data/lib/active_record/coders/yaml_column.rb +70 -46
  54. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +367 -0
  55. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +78 -0
  57. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +113 -597
  58. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
  59. data/lib/active_record/connection_adapters/abstract/database_statements.rb +172 -50
  60. data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -27
  61. data/lib/active_record/connection_adapters/abstract/quoting.rb +87 -73
  62. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +367 -141
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +281 -59
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +631 -150
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +317 -164
  70. data/lib/active_record/connection_adapters/column.rb +13 -0
  71. data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
  72. data/lib/active_record/connection_adapters/mysql/database_statements.rb +25 -134
  73. data/lib/active_record/connection_adapters/mysql/quoting.rb +56 -25
  74. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
  76. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
  77. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +39 -14
  78. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +151 -0
  79. data/lib/active_record/connection_adapters/mysql2_adapter.rb +112 -55
  80. data/lib/active_record/connection_adapters/pool_config.rb +20 -11
  81. data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +89 -52
  84. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  85. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
  89. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
  90. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +12 -3
  91. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  94. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -56
  96. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
  97. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
  98. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +153 -3
  99. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
  100. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +397 -75
  101. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
  102. data/lib/active_record/connection_adapters/postgresql_adapter.rb +508 -246
  103. data/lib/active_record/connection_adapters/schema_cache.rb +319 -90
  104. data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
  105. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +72 -53
  106. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +37 -21
  107. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
  108. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -22
  109. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +296 -104
  110. data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
  111. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
  112. data/lib/active_record/connection_adapters/trilogy_adapter.rb +258 -0
  113. data/lib/active_record/connection_adapters.rb +9 -6
  114. data/lib/active_record/connection_handling.rb +108 -137
  115. data/lib/active_record/core.rb +242 -233
  116. data/lib/active_record/counter_cache.rb +52 -27
  117. data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -2
  118. data/lib/active_record/database_configurations/database_config.rb +21 -12
  119. data/lib/active_record/database_configurations/hash_config.rb +88 -16
  120. data/lib/active_record/database_configurations/url_config.rb +18 -12
  121. data/lib/active_record/database_configurations.rb +95 -59
  122. data/lib/active_record/delegated_type.rb +66 -20
  123. data/lib/active_record/deprecator.rb +7 -0
  124. data/lib/active_record/destroy_association_async_job.rb +4 -2
  125. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  126. data/lib/active_record/dynamic_matchers.rb +1 -1
  127. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  128. data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
  129. data/lib/active_record/encryption/cipher.rb +53 -0
  130. data/lib/active_record/encryption/config.rb +68 -0
  131. data/lib/active_record/encryption/configurable.rb +60 -0
  132. data/lib/active_record/encryption/context.rb +42 -0
  133. data/lib/active_record/encryption/contexts.rb +76 -0
  134. data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
  135. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  136. data/lib/active_record/encryption/encryptable_record.rb +230 -0
  137. data/lib/active_record/encryption/encrypted_attribute_type.rb +155 -0
  138. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  139. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  140. data/lib/active_record/encryption/encryptor.rb +155 -0
  141. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  142. data/lib/active_record/encryption/errors.rb +15 -0
  143. data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
  144. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  145. data/lib/active_record/encryption/key.rb +28 -0
  146. data/lib/active_record/encryption/key_generator.rb +53 -0
  147. data/lib/active_record/encryption/key_provider.rb +46 -0
  148. data/lib/active_record/encryption/message.rb +33 -0
  149. data/lib/active_record/encryption/message_serializer.rb +92 -0
  150. data/lib/active_record/encryption/null_encryptor.rb +21 -0
  151. data/lib/active_record/encryption/properties.rb +76 -0
  152. data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
  153. data/lib/active_record/encryption/scheme.rb +100 -0
  154. data/lib/active_record/encryption.rb +58 -0
  155. data/lib/active_record/enum.rb +154 -63
  156. data/lib/active_record/errors.rb +172 -15
  157. data/lib/active_record/explain.rb +23 -3
  158. data/lib/active_record/explain_registry.rb +11 -6
  159. data/lib/active_record/explain_subscriber.rb +1 -1
  160. data/lib/active_record/fixture_set/file.rb +15 -1
  161. data/lib/active_record/fixture_set/model_metadata.rb +14 -4
  162. data/lib/active_record/fixture_set/render_context.rb +2 -0
  163. data/lib/active_record/fixture_set/table_row.rb +70 -14
  164. data/lib/active_record/fixture_set/table_rows.rb +4 -4
  165. data/lib/active_record/fixtures.rb +147 -86
  166. data/lib/active_record/future_result.rb +174 -0
  167. data/lib/active_record/gem_version.rb +3 -3
  168. data/lib/active_record/inheritance.rb +81 -29
  169. data/lib/active_record/insert_all.rb +135 -22
  170. data/lib/active_record/integration.rb +11 -10
  171. data/lib/active_record/internal_metadata.rb +119 -33
  172. data/lib/active_record/legacy_yaml_adapter.rb +2 -39
  173. data/lib/active_record/locking/optimistic.rb +37 -22
  174. data/lib/active_record/locking/pessimistic.rb +15 -6
  175. data/lib/active_record/log_subscriber.rb +52 -19
  176. data/lib/active_record/marshalling.rb +59 -0
  177. data/lib/active_record/message_pack.rb +124 -0
  178. data/lib/active_record/middleware/database_selector/resolver.rb +10 -10
  179. data/lib/active_record/middleware/database_selector.rb +23 -13
  180. data/lib/active_record/middleware/shard_selector.rb +62 -0
  181. data/lib/active_record/migration/command_recorder.rb +112 -14
  182. data/lib/active_record/migration/compatibility.rb +233 -46
  183. data/lib/active_record/migration/default_strategy.rb +23 -0
  184. data/lib/active_record/migration/execution_strategy.rb +19 -0
  185. data/lib/active_record/migration/join_table.rb +1 -1
  186. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  187. data/lib/active_record/migration.rb +361 -173
  188. data/lib/active_record/model_schema.rb +125 -101
  189. data/lib/active_record/nested_attributes.rb +50 -20
  190. data/lib/active_record/no_touching.rb +3 -3
  191. data/lib/active_record/normalization.rb +167 -0
  192. data/lib/active_record/persistence.rb +409 -88
  193. data/lib/active_record/promise.rb +84 -0
  194. data/lib/active_record/query_cache.rb +4 -22
  195. data/lib/active_record/query_logs.rb +174 -0
  196. data/lib/active_record/query_logs_formatter.rb +41 -0
  197. data/lib/active_record/querying.rb +29 -6
  198. data/lib/active_record/railtie.rb +220 -44
  199. data/lib/active_record/railties/controller_runtime.rb +15 -10
  200. data/lib/active_record/railties/databases.rake +188 -252
  201. data/lib/active_record/railties/job_runtime.rb +23 -0
  202. data/lib/active_record/readonly_attributes.rb +41 -3
  203. data/lib/active_record/reflection.rb +248 -81
  204. data/lib/active_record/relation/batches/batch_enumerator.rb +23 -7
  205. data/lib/active_record/relation/batches.rb +192 -63
  206. data/lib/active_record/relation/calculations.rb +246 -90
  207. data/lib/active_record/relation/delegation.rb +28 -14
  208. data/lib/active_record/relation/finder_methods.rb +108 -51
  209. data/lib/active_record/relation/merger.rb +22 -13
  210. data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -3
  211. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
  212. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  213. data/lib/active_record/relation/predicate_builder.rb +27 -20
  214. data/lib/active_record/relation/query_attribute.rb +30 -12
  215. data/lib/active_record/relation/query_methods.rb +670 -129
  216. data/lib/active_record/relation/record_fetch_warning.rb +7 -9
  217. data/lib/active_record/relation/spawn_methods.rb +20 -3
  218. data/lib/active_record/relation/where_clause.rb +10 -19
  219. data/lib/active_record/relation.rb +287 -120
  220. data/lib/active_record/result.rb +37 -11
  221. data/lib/active_record/runtime_registry.rb +32 -13
  222. data/lib/active_record/sanitization.rb +65 -20
  223. data/lib/active_record/schema.rb +36 -22
  224. data/lib/active_record/schema_dumper.rb +73 -24
  225. data/lib/active_record/schema_migration.rb +68 -33
  226. data/lib/active_record/scoping/default.rb +72 -15
  227. data/lib/active_record/scoping/named.rb +5 -13
  228. data/lib/active_record/scoping.rb +65 -34
  229. data/lib/active_record/secure_password.rb +60 -0
  230. data/lib/active_record/secure_token.rb +21 -3
  231. data/lib/active_record/serialization.rb +6 -1
  232. data/lib/active_record/signed_id.rb +10 -8
  233. data/lib/active_record/store.rb +10 -10
  234. data/lib/active_record/suppressor.rb +13 -15
  235. data/lib/active_record/table_metadata.rb +16 -3
  236. data/lib/active_record/tasks/database_tasks.rb +251 -140
  237. data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
  238. data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
  239. data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
  240. data/lib/active_record/test_databases.rb +1 -1
  241. data/lib/active_record/test_fixtures.rb +117 -96
  242. data/lib/active_record/timestamp.rb +32 -19
  243. data/lib/active_record/token_for.rb +113 -0
  244. data/lib/active_record/touch_later.rb +11 -6
  245. data/lib/active_record/transactions.rb +48 -27
  246. data/lib/active_record/translation.rb +3 -3
  247. data/lib/active_record/type/adapter_specific_registry.rb +32 -14
  248. data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
  249. data/lib/active_record/type/internal/timezone.rb +7 -2
  250. data/lib/active_record/type/serialized.rb +9 -5
  251. data/lib/active_record/type/time.rb +4 -0
  252. data/lib/active_record/type/type_map.rb +17 -20
  253. data/lib/active_record/type.rb +1 -2
  254. data/lib/active_record/validations/absence.rb +1 -1
  255. data/lib/active_record/validations/associated.rb +4 -4
  256. data/lib/active_record/validations/numericality.rb +5 -4
  257. data/lib/active_record/validations/presence.rb +5 -28
  258. data/lib/active_record/validations/uniqueness.rb +51 -6
  259. data/lib/active_record/validations.rb +8 -4
  260. data/lib/active_record/version.rb +1 -1
  261. data/lib/active_record.rb +335 -32
  262. data/lib/arel/attributes/attribute.rb +0 -8
  263. data/lib/arel/crud.rb +28 -22
  264. data/lib/arel/delete_manager.rb +18 -4
  265. data/lib/arel/errors.rb +10 -0
  266. data/lib/arel/factory_methods.rb +4 -0
  267. data/lib/arel/filter_predications.rb +9 -0
  268. data/lib/arel/insert_manager.rb +2 -3
  269. data/lib/arel/nodes/and.rb +4 -0
  270. data/lib/arel/nodes/binary.rb +6 -1
  271. data/lib/arel/nodes/bound_sql_literal.rb +61 -0
  272. data/lib/arel/nodes/casted.rb +1 -1
  273. data/lib/arel/nodes/cte.rb +36 -0
  274. data/lib/arel/nodes/delete_statement.rb +12 -13
  275. data/lib/arel/nodes/filter.rb +10 -0
  276. data/lib/arel/nodes/fragments.rb +35 -0
  277. data/lib/arel/nodes/function.rb +1 -0
  278. data/lib/arel/nodes/homogeneous_in.rb +1 -9
  279. data/lib/arel/nodes/insert_statement.rb +2 -2
  280. data/lib/arel/nodes/leading_join.rb +8 -0
  281. data/lib/arel/nodes/node.rb +111 -2
  282. data/lib/arel/nodes/select_core.rb +2 -2
  283. data/lib/arel/nodes/select_statement.rb +2 -2
  284. data/lib/arel/nodes/sql_literal.rb +6 -0
  285. data/lib/arel/nodes/table_alias.rb +4 -0
  286. data/lib/arel/nodes/update_statement.rb +8 -3
  287. data/lib/arel/nodes.rb +5 -0
  288. data/lib/arel/predications.rb +13 -3
  289. data/lib/arel/select_manager.rb +10 -4
  290. data/lib/arel/table.rb +9 -6
  291. data/lib/arel/tree_manager.rb +5 -13
  292. data/lib/arel/update_manager.rb +18 -4
  293. data/lib/arel/visitors/dot.rb +80 -90
  294. data/lib/arel/visitors/mysql.rb +16 -3
  295. data/lib/arel/visitors/postgresql.rb +0 -10
  296. data/lib/arel/visitors/to_sql.rb +141 -20
  297. data/lib/arel/visitors/visitor.rb +2 -2
  298. data/lib/arel.rb +18 -3
  299. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  300. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  301. data/lib/rails/generators/active_record/migration.rb +3 -1
  302. data/lib/rails/generators/active_record/model/USAGE +113 -0
  303. data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
  304. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
  305. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  306. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  307. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  308. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  309. metadata +96 -16
  310. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  311. data/lib/active_record/null_relation.rb +0 -67
@@ -5,42 +5,69 @@ require "active_support/multibyte/chars"
5
5
 
6
6
  module ActiveRecord
7
7
  module ConnectionAdapters # :nodoc:
8
+ # = Active Record Connection Adapters \Quoting
8
9
  module Quoting
9
10
  # Quotes the column value to help prevent
10
11
  # {SQL injection attacks}[https://en.wikipedia.org/wiki/SQL_injection].
11
12
  def quote(value)
12
- if value.is_a?(Base)
13
- ActiveSupport::Deprecation.warn(<<~MSG)
14
- Passing an Active Record object to `quote` directly is deprecated
15
- and will be no longer quoted as id value in Rails 7.0.
16
- MSG
17
- value = value.id_for_database
13
+ case value
14
+ when String, Symbol, ActiveSupport::Multibyte::Chars
15
+ "'#{quote_string(value.to_s)}'"
16
+ when true then quoted_true
17
+ when false then quoted_false
18
+ when nil then "NULL"
19
+ # BigDecimals need to be put in a non-normalized form and quoted.
20
+ when BigDecimal then value.to_s("F")
21
+ when Numeric then value.to_s
22
+ when Type::Binary::Data then quoted_binary(value)
23
+ when Type::Time::Value then "'#{quoted_time(value)}'"
24
+ when Date, Time then "'#{quoted_date(value)}'"
25
+ when Class then "'#{value}'"
26
+ when ActiveSupport::Duration
27
+ warn_quote_duration_deprecated
28
+ value.to_s
29
+ else raise TypeError, "can't quote #{value.class.name}"
18
30
  end
19
-
20
- _quote(value)
21
31
  end
22
32
 
23
33
  # Cast a +value+ to a type that the database understands. For example,
24
34
  # SQLite does not understand dates, so this method will convert a Date
25
35
  # to a String.
26
- def type_cast(value, column = nil)
27
- if value.is_a?(Base)
28
- ActiveSupport::Deprecation.warn(<<~MSG)
29
- Passing an Active Record object to `type_cast` directly is deprecated
30
- and will be no longer type casted as id value in Rails 7.0.
31
- MSG
32
- value = value.id_for_database
36
+ def type_cast(value)
37
+ case value
38
+ when Symbol, ActiveSupport::Multibyte::Chars, Type::Binary::Data
39
+ value.to_s
40
+ when true then unquoted_true
41
+ when false then unquoted_false
42
+ # BigDecimals need to be put in a non-normalized form and quoted.
43
+ when BigDecimal then value.to_s("F")
44
+ when nil, Numeric, String then value
45
+ when Type::Time::Value then quoted_time(value)
46
+ when Date, Time then quoted_date(value)
47
+ else raise TypeError, "can't cast #{value.class.name}"
33
48
  end
49
+ end
34
50
 
35
- if column
36
- ActiveSupport::Deprecation.warn(<<~MSG)
37
- Passing a column to `type_cast` is deprecated and will be removed in Rails 7.0.
38
- MSG
39
- type = lookup_cast_type_from_column(column)
40
- value = type.serialize(value)
41
- end
51
+ # Quote a value to be used as a bound parameter of unknown type. For example,
52
+ # MySQL might perform dangerous castings when comparing a string to a number,
53
+ # so this method will cast numbers to string.
54
+ #
55
+ # Deprecated: Consider `Arel.sql("... ? ...", value)` or
56
+ # +sanitize_sql+ instead.
57
+ def quote_bound_value(value)
58
+ ActiveRecord.deprecator.warn(<<~MSG.squish)
59
+ #quote_bound_value is deprecated and will be removed in Rails 7.2.
60
+ Consider Arel.sql(".. ? ..", value) or #sanitize_sql instead.
61
+ MSG
42
62
 
43
- _type_cast(value)
63
+ quote(cast_bound_value(value))
64
+ end
65
+
66
+ # Cast a value to be used as a bound parameter of unknown type. For example,
67
+ # MySQL might perform dangerous castings when comparing a string to a number,
68
+ # so this method will cast numbers to string.
69
+ def cast_bound_value(value) # :nodoc:
70
+ value
44
71
  end
45
72
 
46
73
  # If you are having to call this function, you are likely doing something
@@ -59,7 +86,7 @@ module ActiveRecord
59
86
  # Quotes a string, escaping any ' (single quote) and \ (backslash)
60
87
  # characters.
61
88
  def quote_string(s)
62
- s.gsub('\\', '\&\&').gsub("'", "''") # ' (for ruby-mode)
89
+ s.gsub("\\", '\&\&').gsub("'", "''") # ' (for ruby-mode)
63
90
  end
64
91
 
65
92
  # Quotes the column name. Defaults to no quoting.
@@ -75,7 +102,7 @@ module ActiveRecord
75
102
  # Override to return the quoted table name for assignment. Defaults to
76
103
  # table quoting.
77
104
  #
78
- # This works for mysql2 where table.column can be used to
105
+ # This works for MySQL where table.column can be used to
79
106
  # resolve ambiguity.
80
107
  #
81
108
  # We override this in the sqlite3 and postgresql adapters to use only
@@ -113,14 +140,14 @@ module ActiveRecord
113
140
  # if the value is a Time responding to usec.
114
141
  def quoted_date(value)
115
142
  if value.acts_like?(:time)
116
- if ActiveRecord::Base.default_timezone == :utc
117
- value = value.getutc if value.respond_to?(:getutc) && !value.utc?
143
+ if default_timezone == :utc
144
+ value = value.getutc if !value.utc?
118
145
  else
119
- value = value.getlocal if value.respond_to?(:getlocal)
146
+ value = value.getlocal
120
147
  end
121
148
  end
122
149
 
123
- result = value.to_s(:db)
150
+ result = value.to_fs(:db)
124
151
  if value.respond_to?(:usec) && value.usec > 0
125
152
  result << "." << sprintf("%06d", value.usec)
126
153
  else
@@ -138,7 +165,16 @@ module ActiveRecord
138
165
  end
139
166
 
140
167
  def sanitize_as_sql_comment(value) # :nodoc:
141
- value.to_s.gsub(%r{ (/ (?: | \g<1>) \*) \+? \s* | \s* (\* (?: | \g<2>) /) }x, "")
168
+ # Sanitize a string to appear within a SQL comment
169
+ # For compatibility, this also surrounding "/*+", "/*", and "*/"
170
+ # charcacters, possibly with single surrounding space.
171
+ # Then follows that by replacing any internal "*/" or "/ *" with
172
+ # "* /" or "/ *"
173
+ comment = value.to_s.dup
174
+ comment.gsub!(%r{\A\s*/\*\+?\s?|\s?\*/\s*\Z}, "")
175
+ comment.gsub!("*/", "* /")
176
+ comment.gsub!("/*", "/ *")
177
+ comment
142
178
  end
143
179
 
144
180
  def column_name_matcher # :nodoc:
@@ -159,7 +195,7 @@ module ActiveRecord
159
195
  (
160
196
  (?:
161
197
  # table_name.column_name | function(one or no argument)
162
- ((?:\w+\.)?\w+) | \w+\((?:|\g<2>)\)
198
+ ((?:\w+\.)?\w+ | \w+\((?:|\g<2>)\))
163
199
  )
164
200
  (?:(?:\s+AS)?\s+\w+)?
165
201
  )
@@ -183,7 +219,7 @@ module ActiveRecord
183
219
  (
184
220
  (?:
185
221
  # table_name.column_name | function(one or no argument)
186
- ((?:\w+\.)?\w+) | \w+\((?:|\g<2>)\)
222
+ ((?:\w+\.)?\w+ | \w+\((?:|\g<2>)\))
187
223
  )
188
224
  (?:\s+ASC|\s+DESC)?
189
225
  (?:\s+NULLS\s+(?:FIRST|LAST))?
@@ -196,16 +232,11 @@ module ActiveRecord
196
232
 
197
233
  private
198
234
  def type_casted_binds(binds)
199
- case binds.first
200
- when Array
201
- binds.map { |column, value| type_cast(value, column) }
202
- else
203
- binds.map do |value|
204
- if ActiveModel::Attribute === value
205
- type_cast(value.value_for_database)
206
- else
207
- type_cast(value)
208
- end
235
+ binds.map do |value|
236
+ if ActiveModel::Attribute === value
237
+ type_cast(value.value_for_database)
238
+ else
239
+ type_cast(value)
209
240
  end
210
241
  end
211
242
  end
@@ -214,37 +245,20 @@ module ActiveRecord
214
245
  type_map.lookup(sql_type)
215
246
  end
216
247
 
217
- def _quote(value)
218
- case value
219
- when String, Symbol, ActiveSupport::Multibyte::Chars
220
- "'#{quote_string(value.to_s)}'"
221
- when true then quoted_true
222
- when false then quoted_false
223
- when nil then "NULL"
224
- # BigDecimals need to be put in a non-normalized form and quoted.
225
- when BigDecimal then value.to_s("F")
226
- when Numeric, ActiveSupport::Duration then value.to_s
227
- when Type::Binary::Data then quoted_binary(value)
228
- when Type::Time::Value then "'#{quoted_time(value)}'"
229
- when Date, Time then "'#{quoted_date(value)}'"
230
- when Class then "'#{value}'"
231
- else raise TypeError, "can't quote #{value.class.name}"
232
- end
233
- end
234
-
235
- def _type_cast(value)
236
- case value
237
- when Symbol, ActiveSupport::Multibyte::Chars, Type::Binary::Data
238
- value.to_s
239
- when true then unquoted_true
240
- when false then unquoted_false
241
- # BigDecimals need to be put in a non-normalized form and quoted.
242
- when BigDecimal then value.to_s("F")
243
- when nil, Numeric, String then value
244
- when Type::Time::Value then quoted_time(value)
245
- when Date, Time then quoted_date(value)
246
- else raise TypeError, "can't cast #{value.class.name}"
247
- end
248
+ def warn_quote_duration_deprecated
249
+ ActiveRecord.deprecator.warn(<<~MSG)
250
+ Using ActiveSupport::Duration as an interpolated bind parameter in a SQL
251
+ string template is deprecated. To avoid this warning, you should explicitly
252
+ convert the duration to a more specific database type. For example, if you
253
+ want to use a duration as an integer number of seconds:
254
+ ```
255
+ Record.where("duration = ?", 1.hour.to_i)
256
+ ```
257
+ If you want to use a duration as an ISO 8601 string:
258
+ ```
259
+ Record.where("duration = ?", 1.hour.iso8601)
260
+ ```
261
+ MSG
248
262
  end
249
263
  end
250
264
  end
@@ -2,21 +2,22 @@
2
2
 
3
3
  module ActiveRecord
4
4
  module ConnectionAdapters
5
+ # = Active Record Connection Adapters \Savepoints
5
6
  module Savepoints
6
7
  def current_savepoint_name
7
8
  current_transaction.savepoint_name
8
9
  end
9
10
 
10
11
  def create_savepoint(name = current_savepoint_name)
11
- execute("SAVEPOINT #{name}", "TRANSACTION")
12
+ internal_execute("SAVEPOINT #{name}", "TRANSACTION")
12
13
  end
13
14
 
14
15
  def exec_rollback_to_savepoint(name = current_savepoint_name)
15
- execute("ROLLBACK TO SAVEPOINT #{name}", "TRANSACTION")
16
+ internal_execute("ROLLBACK TO SAVEPOINT #{name}", "TRANSACTION")
16
17
  end
17
18
 
18
19
  def release_savepoint(name = current_savepoint_name)
19
- execute("RELEASE SAVEPOINT #{name}", "TRANSACTION")
20
+ internal_execute("RELEASE SAVEPOINT #{name}", "TRANSACTION")
20
21
  end
21
22
  end
22
23
  end
@@ -14,8 +14,10 @@ module ActiveRecord
14
14
  end
15
15
 
16
16
  delegate :quote_column_name, :quote_table_name, :quote_default_expression, :type_to_sql,
17
- :options_include_default?, :supports_indexes_in_create?, :supports_foreign_keys?, :foreign_key_options,
18
- :quoted_columns_for_index, :supports_partial_index?, :supports_check_constraints?, :check_constraint_options,
17
+ :options_include_default?, :supports_indexes_in_create?, :use_foreign_keys?,
18
+ :quoted_columns_for_index, :supports_partial_index?, :supports_check_constraints?,
19
+ :supports_index_include?, :supports_exclusion_constraints?, :supports_unique_constraints?,
20
+ :supports_nulls_not_distinct?,
19
21
  to: :@conn, private: true
20
22
 
21
23
  private
@@ -51,12 +53,20 @@ module ActiveRecord
51
53
  statements.concat(o.indexes.map { |column_name, options| index_in_create(o.name, column_name, options) })
52
54
  end
53
55
 
54
- if supports_foreign_keys?
55
- statements.concat(o.foreign_keys.map { |to_table, options| foreign_key_in_create(o.name, to_table, options) })
56
+ if use_foreign_keys?
57
+ statements.concat(o.foreign_keys.map { |fk| accept fk })
56
58
  end
57
59
 
58
60
  if supports_check_constraints?
59
- statements.concat(o.check_constraints.map { |expression, options| check_constraint_in_create(o.name, expression, options) })
61
+ statements.concat(o.check_constraints.map { |chk| accept chk })
62
+ end
63
+
64
+ if supports_exclusion_constraints?
65
+ statements.concat(o.exclusion_constraints.map { |exc| accept exc })
66
+ end
67
+
68
+ if supports_unique_constraints?
69
+ statements.concat(o.unique_constraints.map { |exc| accept exc })
60
70
  end
61
71
 
62
72
  create_sql << "(#{statements.join(', ')})" if statements.present?
@@ -70,10 +80,12 @@ module ActiveRecord
70
80
  end
71
81
 
72
82
  def visit_ForeignKeyDefinition(o)
83
+ quoted_columns = Array(o.column).map { |c| quote_column_name(c) }
84
+ quoted_primary_keys = Array(o.primary_key).map { |c| quote_column_name(c) }
73
85
  sql = +<<~SQL
74
86
  CONSTRAINT #{quote_column_name(o.name)}
75
- FOREIGN KEY (#{quote_column_name(o.column)})
76
- REFERENCES #{quote_table_name(o.to_table)} (#{quote_column_name(o.primary_key)})
87
+ FOREIGN KEY (#{quoted_columns.join(", ")})
88
+ REFERENCES #{quote_table_name(o.to_table)} (#{quoted_primary_keys.join(", ")})
77
89
  SQL
78
90
  sql << " #{action_sql('DELETE', o.on_delete)}" if o.on_delete
79
91
  sql << " #{action_sql('UPDATE', o.on_update)}" if o.on_update
@@ -100,6 +112,8 @@ module ActiveRecord
100
112
  sql << "#{quote_column_name(index.name)} ON #{quote_table_name(index.table)}"
101
113
  sql << "USING #{index.using}" if supports_index_using? && index.using
102
114
  sql << "(#{quoted_columns(index)})"
115
+ sql << "INCLUDE (#{quoted_include_columns(index.include)})" if supports_index_include? && index.include
116
+ sql << "NULLS NOT DISTINCT" if supports_nulls_not_distinct? && index.nulls_not_distinct
103
117
  sql << "WHERE #{index.where}" if supports_partial_index? && index.where
104
118
 
105
119
  sql.join(" ")
@@ -159,19 +173,6 @@ module ActiveRecord
159
173
  " TEMPORARY" if o.temporary
160
174
  end
161
175
 
162
- def foreign_key_in_create(from_table, to_table, options)
163
- prefix = ActiveRecord::Base.table_name_prefix
164
- suffix = ActiveRecord::Base.table_name_suffix
165
- to_table = "#{prefix}#{to_table}#{suffix}"
166
- options = foreign_key_options(from_table, to_table, options)
167
- accept ForeignKeyDefinition.new(from_table, to_table, options)
168
- end
169
-
170
- def check_constraint_in_create(table_name, expression, options)
171
- options = check_constraint_options(table_name, expression, options)
172
- accept CheckConstraintDefinition.new(table_name, expression, options)
173
- end
174
-
175
176
  def action_sql(action, dependency)
176
177
  case dependency
177
178
  when :nullify then "ON #{action} SET NULL"