activerecord 6.1.7 → 7.1.0

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 (307) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1516 -1019
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +17 -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 +50 -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 +35 -31
  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.rb +26 -16
  27. data/lib/active_record/associations/preloader/association.rb +207 -52
  28. data/lib/active_record/associations/preloader/batch.rb +48 -0
  29. data/lib/active_record/associations/preloader/branch.rb +147 -0
  30. data/lib/active_record/associations/preloader/through_association.rb +50 -14
  31. data/lib/active_record/associations/preloader.rb +50 -121
  32. data/lib/active_record/associations/singular_association.rb +9 -3
  33. data/lib/active_record/associations/through_association.rb +25 -14
  34. data/lib/active_record/associations.rb +423 -289
  35. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  36. data/lib/active_record/attribute_assignment.rb +1 -3
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
  38. data/lib/active_record/attribute_methods/dirty.rb +61 -14
  39. data/lib/active_record/attribute_methods/primary_key.rb +78 -26
  40. data/lib/active_record/attribute_methods/query.rb +31 -19
  41. data/lib/active_record/attribute_methods/read.rb +25 -10
  42. data/lib/active_record/attribute_methods/serialization.rb +194 -37
  43. data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -3
  44. data/lib/active_record/attribute_methods/write.rb +10 -13
  45. data/lib/active_record/attribute_methods.rb +121 -40
  46. data/lib/active_record/attributes.rb +27 -38
  47. data/lib/active_record/autosave_association.rb +61 -30
  48. data/lib/active_record/base.rb +25 -2
  49. data/lib/active_record/callbacks.rb +18 -34
  50. data/lib/active_record/coders/column_serializer.rb +61 -0
  51. data/lib/active_record/coders/json.rb +1 -1
  52. data/lib/active_record/coders/yaml_column.rb +70 -46
  53. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +367 -0
  54. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
  55. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +78 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +96 -590
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +171 -51
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +77 -27
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +87 -73
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +360 -136
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +281 -59
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +622 -149
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +285 -156
  69. data/lib/active_record/connection_adapters/column.rb +13 -0
  70. data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
  71. data/lib/active_record/connection_adapters/mysql/database_statements.rb +25 -134
  72. data/lib/active_record/connection_adapters/mysql/quoting.rb +56 -25
  73. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
  74. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
  75. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
  76. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +38 -14
  77. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +148 -0
  78. data/lib/active_record/connection_adapters/mysql2_adapter.rb +104 -53
  79. data/lib/active_record/connection_adapters/pool_config.rb +20 -11
  80. data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
  81. data/lib/active_record/connection_adapters/postgresql/column.rb +18 -1
  82. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +86 -52
  83. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  84. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
  87. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +12 -3
  88. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  91. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  92. data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -56
  93. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
  94. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
  95. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +153 -3
  96. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
  97. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +381 -69
  98. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
  99. data/lib/active_record/connection_adapters/postgresql_adapter.rb +492 -230
  100. data/lib/active_record/connection_adapters/schema_cache.rb +319 -90
  101. data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
  102. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +65 -53
  103. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +37 -21
  104. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
  105. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -22
  106. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +294 -102
  107. data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
  108. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +98 -0
  109. data/lib/active_record/connection_adapters/trilogy_adapter.rb +254 -0
  110. data/lib/active_record/connection_adapters.rb +9 -6
  111. data/lib/active_record/connection_handling.rb +107 -136
  112. data/lib/active_record/core.rb +194 -224
  113. data/lib/active_record/counter_cache.rb +46 -25
  114. data/lib/active_record/database_configurations/connection_url_resolver.rb +2 -1
  115. data/lib/active_record/database_configurations/database_config.rb +21 -12
  116. data/lib/active_record/database_configurations/hash_config.rb +84 -16
  117. data/lib/active_record/database_configurations/url_config.rb +18 -12
  118. data/lib/active_record/database_configurations.rb +95 -59
  119. data/lib/active_record/delegated_type.rb +61 -15
  120. data/lib/active_record/deprecator.rb +7 -0
  121. data/lib/active_record/destroy_association_async_job.rb +3 -1
  122. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  123. data/lib/active_record/dynamic_matchers.rb +1 -1
  124. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  125. data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
  126. data/lib/active_record/encryption/cipher.rb +53 -0
  127. data/lib/active_record/encryption/config.rb +68 -0
  128. data/lib/active_record/encryption/configurable.rb +60 -0
  129. data/lib/active_record/encryption/context.rb +42 -0
  130. data/lib/active_record/encryption/contexts.rb +76 -0
  131. data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
  132. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  133. data/lib/active_record/encryption/encryptable_record.rb +224 -0
  134. data/lib/active_record/encryption/encrypted_attribute_type.rb +151 -0
  135. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  136. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  137. data/lib/active_record/encryption/encryptor.rb +155 -0
  138. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  139. data/lib/active_record/encryption/errors.rb +15 -0
  140. data/lib/active_record/encryption/extended_deterministic_queries.rb +172 -0
  141. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  142. data/lib/active_record/encryption/key.rb +28 -0
  143. data/lib/active_record/encryption/key_generator.rb +53 -0
  144. data/lib/active_record/encryption/key_provider.rb +46 -0
  145. data/lib/active_record/encryption/message.rb +33 -0
  146. data/lib/active_record/encryption/message_serializer.rb +92 -0
  147. data/lib/active_record/encryption/null_encryptor.rb +21 -0
  148. data/lib/active_record/encryption/properties.rb +76 -0
  149. data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
  150. data/lib/active_record/encryption/scheme.rb +96 -0
  151. data/lib/active_record/encryption.rb +56 -0
  152. data/lib/active_record/enum.rb +156 -62
  153. data/lib/active_record/errors.rb +171 -15
  154. data/lib/active_record/explain.rb +23 -3
  155. data/lib/active_record/explain_registry.rb +11 -6
  156. data/lib/active_record/explain_subscriber.rb +1 -1
  157. data/lib/active_record/fixture_set/file.rb +15 -1
  158. data/lib/active_record/fixture_set/model_metadata.rb +14 -4
  159. data/lib/active_record/fixture_set/render_context.rb +2 -0
  160. data/lib/active_record/fixture_set/table_row.rb +70 -14
  161. data/lib/active_record/fixture_set/table_rows.rb +4 -4
  162. data/lib/active_record/fixtures.rb +131 -86
  163. data/lib/active_record/future_result.rb +164 -0
  164. data/lib/active_record/gem_version.rb +3 -3
  165. data/lib/active_record/inheritance.rb +81 -29
  166. data/lib/active_record/insert_all.rb +133 -20
  167. data/lib/active_record/integration.rb +11 -10
  168. data/lib/active_record/internal_metadata.rb +117 -33
  169. data/lib/active_record/legacy_yaml_adapter.rb +2 -39
  170. data/lib/active_record/locking/optimistic.rb +36 -21
  171. data/lib/active_record/locking/pessimistic.rb +15 -6
  172. data/lib/active_record/log_subscriber.rb +52 -19
  173. data/lib/active_record/marshalling.rb +56 -0
  174. data/lib/active_record/message_pack.rb +124 -0
  175. data/lib/active_record/middleware/database_selector/resolver.rb +10 -10
  176. data/lib/active_record/middleware/database_selector.rb +23 -13
  177. data/lib/active_record/middleware/shard_selector.rb +62 -0
  178. data/lib/active_record/migration/command_recorder.rb +108 -13
  179. data/lib/active_record/migration/compatibility.rb +221 -48
  180. data/lib/active_record/migration/default_strategy.rb +23 -0
  181. data/lib/active_record/migration/execution_strategy.rb +19 -0
  182. data/lib/active_record/migration/join_table.rb +1 -1
  183. data/lib/active_record/migration.rb +355 -171
  184. data/lib/active_record/model_schema.rb +116 -97
  185. data/lib/active_record/nested_attributes.rb +36 -15
  186. data/lib/active_record/no_touching.rb +3 -3
  187. data/lib/active_record/normalization.rb +159 -0
  188. data/lib/active_record/persistence.rb +405 -85
  189. data/lib/active_record/promise.rb +84 -0
  190. data/lib/active_record/query_cache.rb +3 -21
  191. data/lib/active_record/query_logs.rb +174 -0
  192. data/lib/active_record/query_logs_formatter.rb +41 -0
  193. data/lib/active_record/querying.rb +29 -6
  194. data/lib/active_record/railtie.rb +219 -43
  195. data/lib/active_record/railties/controller_runtime.rb +13 -9
  196. data/lib/active_record/railties/databases.rake +185 -249
  197. data/lib/active_record/railties/job_runtime.rb +23 -0
  198. data/lib/active_record/readonly_attributes.rb +41 -3
  199. data/lib/active_record/reflection.rb +229 -80
  200. data/lib/active_record/relation/batches/batch_enumerator.rb +23 -7
  201. data/lib/active_record/relation/batches.rb +192 -63
  202. data/lib/active_record/relation/calculations.rb +211 -90
  203. data/lib/active_record/relation/delegation.rb +27 -13
  204. data/lib/active_record/relation/finder_methods.rb +108 -51
  205. data/lib/active_record/relation/merger.rb +22 -13
  206. data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -3
  207. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -6
  208. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  209. data/lib/active_record/relation/predicate_builder.rb +27 -20
  210. data/lib/active_record/relation/query_attribute.rb +30 -12
  211. data/lib/active_record/relation/query_methods.rb +654 -127
  212. data/lib/active_record/relation/record_fetch_warning.rb +7 -9
  213. data/lib/active_record/relation/spawn_methods.rb +20 -3
  214. data/lib/active_record/relation/where_clause.rb +10 -19
  215. data/lib/active_record/relation.rb +262 -120
  216. data/lib/active_record/result.rb +37 -11
  217. data/lib/active_record/runtime_registry.rb +18 -13
  218. data/lib/active_record/sanitization.rb +65 -20
  219. data/lib/active_record/schema.rb +36 -22
  220. data/lib/active_record/schema_dumper.rb +73 -24
  221. data/lib/active_record/schema_migration.rb +68 -33
  222. data/lib/active_record/scoping/default.rb +72 -15
  223. data/lib/active_record/scoping/named.rb +5 -13
  224. data/lib/active_record/scoping.rb +65 -34
  225. data/lib/active_record/secure_password.rb +60 -0
  226. data/lib/active_record/secure_token.rb +21 -3
  227. data/lib/active_record/serialization.rb +6 -1
  228. data/lib/active_record/signed_id.rb +10 -8
  229. data/lib/active_record/store.rb +10 -10
  230. data/lib/active_record/suppressor.rb +13 -15
  231. data/lib/active_record/table_metadata.rb +16 -3
  232. data/lib/active_record/tasks/database_tasks.rb +225 -136
  233. data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
  234. data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
  235. data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
  236. data/lib/active_record/test_databases.rb +1 -1
  237. data/lib/active_record/test_fixtures.rb +116 -96
  238. data/lib/active_record/timestamp.rb +28 -17
  239. data/lib/active_record/token_for.rb +113 -0
  240. data/lib/active_record/touch_later.rb +11 -6
  241. data/lib/active_record/transactions.rb +48 -27
  242. data/lib/active_record/translation.rb +3 -3
  243. data/lib/active_record/type/adapter_specific_registry.rb +32 -14
  244. data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
  245. data/lib/active_record/type/internal/timezone.rb +7 -2
  246. data/lib/active_record/type/serialized.rb +9 -5
  247. data/lib/active_record/type/time.rb +4 -0
  248. data/lib/active_record/type/type_map.rb +17 -20
  249. data/lib/active_record/type.rb +1 -2
  250. data/lib/active_record/validations/absence.rb +1 -1
  251. data/lib/active_record/validations/associated.rb +4 -4
  252. data/lib/active_record/validations/numericality.rb +5 -4
  253. data/lib/active_record/validations/presence.rb +5 -28
  254. data/lib/active_record/validations/uniqueness.rb +51 -6
  255. data/lib/active_record/validations.rb +8 -4
  256. data/lib/active_record/version.rb +1 -1
  257. data/lib/active_record.rb +335 -32
  258. data/lib/arel/attributes/attribute.rb +0 -8
  259. data/lib/arel/crud.rb +28 -22
  260. data/lib/arel/delete_manager.rb +18 -4
  261. data/lib/arel/errors.rb +10 -0
  262. data/lib/arel/factory_methods.rb +4 -0
  263. data/lib/arel/filter_predications.rb +9 -0
  264. data/lib/arel/insert_manager.rb +2 -3
  265. data/lib/arel/nodes/and.rb +4 -0
  266. data/lib/arel/nodes/binary.rb +6 -1
  267. data/lib/arel/nodes/bound_sql_literal.rb +61 -0
  268. data/lib/arel/nodes/casted.rb +1 -1
  269. data/lib/arel/nodes/cte.rb +36 -0
  270. data/lib/arel/nodes/delete_statement.rb +12 -13
  271. data/lib/arel/nodes/filter.rb +10 -0
  272. data/lib/arel/nodes/fragments.rb +35 -0
  273. data/lib/arel/nodes/function.rb +1 -0
  274. data/lib/arel/nodes/homogeneous_in.rb +0 -8
  275. data/lib/arel/nodes/insert_statement.rb +2 -2
  276. data/lib/arel/nodes/leading_join.rb +8 -0
  277. data/lib/arel/nodes/node.rb +111 -2
  278. data/lib/arel/nodes/select_core.rb +2 -2
  279. data/lib/arel/nodes/select_statement.rb +2 -2
  280. data/lib/arel/nodes/sql_literal.rb +6 -0
  281. data/lib/arel/nodes/table_alias.rb +4 -0
  282. data/lib/arel/nodes/update_statement.rb +8 -3
  283. data/lib/arel/nodes.rb +5 -0
  284. data/lib/arel/predications.rb +13 -3
  285. data/lib/arel/select_manager.rb +10 -4
  286. data/lib/arel/table.rb +9 -6
  287. data/lib/arel/tree_manager.rb +0 -12
  288. data/lib/arel/update_manager.rb +18 -4
  289. data/lib/arel/visitors/dot.rb +80 -90
  290. data/lib/arel/visitors/mysql.rb +16 -3
  291. data/lib/arel/visitors/postgresql.rb +0 -10
  292. data/lib/arel/visitors/to_sql.rb +139 -19
  293. data/lib/arel/visitors/visitor.rb +2 -2
  294. data/lib/arel.rb +18 -3
  295. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  296. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  297. data/lib/rails/generators/active_record/migration.rb +3 -1
  298. data/lib/rails/generators/active_record/model/USAGE +113 -0
  299. data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
  300. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
  301. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  302. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  303. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  304. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  305. metadata +92 -13
  306. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  307. data/lib/active_record/null_relation.rb +0 -67
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ module Trilogy
6
+ module DatabaseStatements
7
+ def select_all(*, **) # :nodoc:
8
+ result = super
9
+ with_raw_connection do |conn|
10
+ conn.next_result while conn.more_results_exist?
11
+ end
12
+ result
13
+ end
14
+
15
+ def internal_exec_query(sql, name = "SQL", binds = [], prepare: false, async: false) # :nodoc:
16
+ sql = transform_query(sql)
17
+ check_if_write_query(sql)
18
+ mark_transaction_written_if_write(sql)
19
+
20
+ result = raw_execute(sql, name, async: async)
21
+ ActiveRecord::Result.new(result.fields, result.to_a)
22
+ end
23
+
24
+ def exec_insert(sql, name, binds, pk = nil, sequence_name = nil, returning: nil) # :nodoc:
25
+ sql = transform_query(sql)
26
+ check_if_write_query(sql)
27
+ mark_transaction_written_if_write(sql)
28
+
29
+ raw_execute(to_sql(sql, binds), name)
30
+ end
31
+
32
+ def exec_delete(sql, name = nil, binds = []) # :nodoc:
33
+ sql = transform_query(sql)
34
+ check_if_write_query(sql)
35
+ mark_transaction_written_if_write(sql)
36
+
37
+ result = raw_execute(to_sql(sql, binds), name)
38
+ result.affected_rows
39
+ end
40
+
41
+ alias :exec_update :exec_delete # :nodoc:
42
+
43
+ private
44
+ def raw_execute(sql, name, async: false, allow_retry: false, materialize_transactions: true)
45
+ log(sql, name, async: async) do
46
+ with_raw_connection(allow_retry: allow_retry, materialize_transactions: materialize_transactions) do |conn|
47
+ sync_timezone_changes(conn)
48
+ result = conn.query(sql)
49
+ handle_warnings(sql)
50
+ result
51
+ end
52
+ end
53
+ end
54
+
55
+ def last_inserted_id(result)
56
+ result.last_insert_id
57
+ end
58
+
59
+ def sync_timezone_changes(conn)
60
+ # Sync any changes since connection last established.
61
+ if default_timezone == :local
62
+ conn.query_flags |= ::Trilogy::QUERY_FLAGS_LOCAL_TIMEZONE
63
+ else
64
+ conn.query_flags &= ~::Trilogy::QUERY_FLAGS_LOCAL_TIMEZONE
65
+ end
66
+ end
67
+
68
+ def execute_batch(statements, name = nil)
69
+ statements = statements.map { |sql| transform_query(sql) }
70
+ combine_multi_statements(statements).each do |statement|
71
+ with_raw_connection do |conn|
72
+ raw_execute(statement, name)
73
+ conn.next_result while conn.more_results_exist?
74
+ end
75
+ end
76
+ end
77
+
78
+ def multi_statements_enabled?
79
+ !!@config[:multi_statement]
80
+ end
81
+
82
+ def with_multi_statements
83
+ if multi_statements_enabled?
84
+ return yield
85
+ end
86
+
87
+ with_raw_connection do |conn|
88
+ conn.set_server_option(::Trilogy::SET_SERVER_MULTI_STATEMENTS_ON)
89
+
90
+ yield
91
+ ensure
92
+ conn.set_server_option(::Trilogy::SET_SERVER_MULTI_STATEMENTS_OFF)
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,254 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record/connection_adapters/abstract_mysql_adapter"
4
+
5
+ gem "trilogy", "~> 2.4"
6
+ require "trilogy"
7
+
8
+ require "active_record/connection_adapters/trilogy/database_statements"
9
+
10
+ module ActiveRecord
11
+ module ConnectionHandling # :nodoc:
12
+ def trilogy_adapter_class
13
+ ConnectionAdapters::TrilogyAdapter
14
+ end
15
+
16
+ # Establishes a connection to the database that's used by all Active Record objects.
17
+ def trilogy_connection(config)
18
+ configuration = config.dup
19
+
20
+ # Set FOUND_ROWS capability on the connection so UPDATE queries returns number of rows
21
+ # matched rather than number of rows updated.
22
+ configuration[:found_rows] = true
23
+
24
+ options = [
25
+ configuration[:host],
26
+ configuration[:port],
27
+ configuration[:database],
28
+ configuration[:username],
29
+ configuration[:password],
30
+ configuration[:socket],
31
+ 0
32
+ ]
33
+
34
+ trilogy_adapter_class.new nil, logger, options, configuration
35
+ end
36
+ end
37
+ module ConnectionAdapters
38
+ class TrilogyAdapter < AbstractMysqlAdapter
39
+ ER_BAD_DB_ERROR = 1049
40
+ ER_DBACCESS_DENIED_ERROR = 1044
41
+ ER_ACCESS_DENIED_ERROR = 1045
42
+ ER_SERVER_SHUTDOWN = 1053
43
+
44
+ ADAPTER_NAME = "Trilogy"
45
+
46
+ include Trilogy::DatabaseStatements
47
+
48
+ SSL_MODES = {
49
+ SSL_MODE_DISABLED: ::Trilogy::SSL_DISABLED,
50
+ SSL_MODE_PREFERRED: ::Trilogy::SSL_PREFERRED_NOVERIFY,
51
+ SSL_MODE_REQUIRED: ::Trilogy::SSL_REQUIRED_NOVERIFY,
52
+ SSL_MODE_VERIFY_CA: ::Trilogy::SSL_VERIFY_CA,
53
+ SSL_MODE_VERIFY_IDENTITY: ::Trilogy::SSL_VERIFY_IDENTITY
54
+ }.freeze
55
+
56
+ class << self
57
+ def new_client(config)
58
+ config[:ssl_mode] = parse_ssl_mode(config[:ssl_mode]) if config[:ssl_mode]
59
+ ::Trilogy.new(config)
60
+ rescue ::Trilogy::ConnectionError, ::Trilogy::ProtocolError => error
61
+ raise translate_connect_error(config, error)
62
+ end
63
+
64
+ def parse_ssl_mode(mode)
65
+ return mode if mode.is_a? Integer
66
+
67
+ m = mode.to_s.upcase
68
+ m = "SSL_MODE_#{m}" unless m.start_with? "SSL_MODE_"
69
+
70
+ SSL_MODES.fetch(m.to_sym, mode)
71
+ end
72
+
73
+ def translate_connect_error(config, error)
74
+ case error.error_code
75
+ when ER_DBACCESS_DENIED_ERROR, ER_BAD_DB_ERROR
76
+ ActiveRecord::NoDatabaseError.db_error(config[:database])
77
+ when ER_ACCESS_DENIED_ERROR
78
+ ActiveRecord::DatabaseConnectionError.username_error(config[:username])
79
+ else
80
+ if error.message.include?("TRILOGY_DNS_ERROR")
81
+ ActiveRecord::DatabaseConnectionError.hostname_error(config[:host])
82
+ else
83
+ ActiveRecord::ConnectionNotEstablished.new(error.message)
84
+ end
85
+ end
86
+ end
87
+
88
+ private
89
+ def initialize_type_map(m)
90
+ super
91
+
92
+ m.register_type(%r(char)i) do |sql_type|
93
+ limit = extract_limit(sql_type)
94
+ Type.lookup(:string, adapter: :trilogy, limit: limit)
95
+ end
96
+
97
+ m.register_type %r(^enum)i, Type.lookup(:string, adapter: :trilogy)
98
+ m.register_type %r(^set)i, Type.lookup(:string, adapter: :trilogy)
99
+ end
100
+ end
101
+
102
+ TYPE_MAP = Type::TypeMap.new.tap { |m| initialize_type_map(m) }
103
+
104
+ def supports_json?
105
+ !mariadb? && database_version >= "5.7.8"
106
+ end
107
+
108
+ def supports_comments?
109
+ true
110
+ end
111
+
112
+ def supports_comments_in_create?
113
+ true
114
+ end
115
+
116
+ def supports_savepoints?
117
+ true
118
+ end
119
+
120
+ def savepoint_errors_invalidate_transactions?
121
+ true
122
+ end
123
+
124
+ def supports_lazy_transactions?
125
+ true
126
+ end
127
+
128
+ def quote_string(string)
129
+ with_raw_connection(allow_retry: true, materialize_transactions: false) do |conn|
130
+ conn.escape(string)
131
+ end
132
+ end
133
+
134
+ def active?
135
+ connection&.ping || false
136
+ rescue ::Trilogy::Error
137
+ false
138
+ end
139
+
140
+ alias reset! reconnect!
141
+
142
+ def disconnect!
143
+ super
144
+ unless connection.nil?
145
+ connection.close
146
+ self.connection = nil
147
+ end
148
+ end
149
+
150
+ def discard!
151
+ super
152
+ unless connection.nil?
153
+ connection.discard!
154
+ self.connection = nil
155
+ end
156
+ end
157
+
158
+ private
159
+ def text_type?(type)
160
+ TYPE_MAP.lookup(type).is_a?(Type::String) || TYPE_MAP.lookup(type).is_a?(Type::Text)
161
+ end
162
+
163
+ def each_hash(result)
164
+ return to_enum(:each_hash, result) unless block_given?
165
+
166
+ keys = result.fields.map(&:to_sym)
167
+ result.rows.each do |row|
168
+ hash = {}
169
+ idx = 0
170
+ row.each do |value|
171
+ hash[keys[idx]] = value
172
+ idx += 1
173
+ end
174
+ yield hash
175
+ end
176
+
177
+ nil
178
+ end
179
+
180
+ def error_number(exception)
181
+ exception.error_code if exception.respond_to?(:error_code)
182
+ end
183
+
184
+ def connection
185
+ @raw_connection
186
+ end
187
+
188
+ def connection=(conn)
189
+ @raw_connection = conn
190
+ end
191
+
192
+ def connect
193
+ self.connection = self.class.new_client(@config)
194
+ rescue ConnectionNotEstablished => ex
195
+ raise ex.set_pool(@pool)
196
+ end
197
+
198
+ def reconnect
199
+ connection&.close
200
+ self.connection = nil
201
+ connect
202
+ end
203
+
204
+ def full_version
205
+ schema_cache.database_version.full_version_string
206
+ end
207
+
208
+ def get_full_version
209
+ with_raw_connection(allow_retry: true, materialize_transactions: false) do |conn|
210
+ conn.server_info[:version]
211
+ end
212
+ end
213
+
214
+ def translate_exception(exception, message:, sql:, binds:)
215
+ if exception.is_a?(::Trilogy::TimeoutError) && !exception.error_code
216
+ return ActiveRecord::AdapterTimeout.new(message, sql: sql, binds: binds, connection_pool: @pool)
217
+ end
218
+ error_code = exception.error_code if exception.respond_to?(:error_code)
219
+
220
+ case error_code
221
+ when ER_SERVER_SHUTDOWN
222
+ return ConnectionFailed.new(message, connection_pool: @pool)
223
+ end
224
+
225
+ case exception
226
+ when Errno::EPIPE, SocketError, IOError
227
+ return ConnectionFailed.new(message, connection_pool: @pool)
228
+ when ::Trilogy::Error
229
+ if /Connection reset by peer|TRILOGY_CLOSED_CONNECTION|TRILOGY_INVALID_SEQUENCE_ID|TRILOGY_UNEXPECTED_PACKET/.match?(exception.message)
230
+ return ConnectionFailed.new(message, connection_pool: @pool)
231
+ end
232
+ end
233
+
234
+ super
235
+ end
236
+
237
+ def default_prepared_statements
238
+ false
239
+ end
240
+
241
+ ActiveRecord::Type.register(:immutable_string, adapter: :trilogy) do |_, **args|
242
+ Type::ImmutableString.new(true: "1", false: "0", **args)
243
+ end
244
+
245
+ ActiveRecord::Type.register(:string, adapter: :trilogy) do |_, **args|
246
+ Type::String.new(true: "1", false: "0", **args)
247
+ end
248
+
249
+ ActiveRecord::Type.register(:unsigned_integer, Type::UnsignedInteger, adapter: :trilogy)
250
+ end
251
+
252
+ ActiveSupport.run_load_hooks(:active_record_trilogyadapter, TrilogyAdapter)
253
+ end
254
+ end
@@ -11,14 +11,16 @@ module ActiveRecord
11
11
  autoload :Column
12
12
  autoload :PoolConfig
13
13
  autoload :PoolManager
14
- autoload :LegacyPoolManager
15
14
  autoload :SchemaCache
15
+ autoload :BoundSchemaReflection, "active_record/connection_adapters/schema_cache"
16
+ autoload :SchemaReflection, "active_record/connection_adapters/schema_cache"
16
17
  autoload :Deduplicable
17
18
 
18
19
  autoload_at "active_record/connection_adapters/abstract/schema_definitions" do
19
20
  autoload :IndexDefinition
20
21
  autoload :ColumnDefinition
21
22
  autoload :ChangeColumnDefinition
23
+ autoload :ChangeColumnDefaultDefinition
22
24
  autoload :ForeignKeyDefinition
23
25
  autoload :CheckConstraintDefinition
24
26
  autoload :TableDefinition
@@ -27,20 +29,21 @@ module ActiveRecord
27
29
  autoload :ReferenceDefinition
28
30
  end
29
31
 
30
- autoload_at "active_record/connection_adapters/abstract/connection_pool" do
31
- autoload :ConnectionHandler
32
- end
33
-
34
32
  autoload_under "abstract" do
35
33
  autoload :SchemaStatements
36
34
  autoload :DatabaseStatements
37
35
  autoload :DatabaseLimits
38
36
  autoload :Quoting
39
- autoload :ConnectionPool
37
+ autoload :ConnectionHandler
40
38
  autoload :QueryCache
41
39
  autoload :Savepoints
42
40
  end
43
41
 
42
+ autoload_at "active_record/connection_adapters/abstract/connection_pool" do
43
+ autoload :ConnectionPool
44
+ autoload :NullPool
45
+ end
46
+
44
47
  autoload_at "active_record/connection_adapters/abstract/transaction" do
45
48
  autoload :TransactionManager
46
49
  autoload :NullTransaction