omg-activerecord 8.0.0.alpha1

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 (412) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +355 -0
  3. data/MIT-LICENSE +22 -0
  4. data/README.rdoc +219 -0
  5. data/examples/performance.rb +185 -0
  6. data/examples/simple.rb +15 -0
  7. data/lib/active_record/aggregations.rb +287 -0
  8. data/lib/active_record/association_relation.rb +50 -0
  9. data/lib/active_record/associations/alias_tracker.rb +90 -0
  10. data/lib/active_record/associations/association.rb +417 -0
  11. data/lib/active_record/associations/association_scope.rb +175 -0
  12. data/lib/active_record/associations/belongs_to_association.rb +163 -0
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +50 -0
  14. data/lib/active_record/associations/builder/association.rb +170 -0
  15. data/lib/active_record/associations/builder/belongs_to.rb +160 -0
  16. data/lib/active_record/associations/builder/collection_association.rb +80 -0
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +107 -0
  18. data/lib/active_record/associations/builder/has_many.rb +23 -0
  19. data/lib/active_record/associations/builder/has_one.rb +61 -0
  20. data/lib/active_record/associations/builder/singular_association.rb +48 -0
  21. data/lib/active_record/associations/collection_association.rb +535 -0
  22. data/lib/active_record/associations/collection_proxy.rb +1163 -0
  23. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  24. data/lib/active_record/associations/errors.rb +265 -0
  25. data/lib/active_record/associations/foreign_association.rb +40 -0
  26. data/lib/active_record/associations/has_many_association.rb +167 -0
  27. data/lib/active_record/associations/has_many_through_association.rb +232 -0
  28. data/lib/active_record/associations/has_one_association.rb +142 -0
  29. data/lib/active_record/associations/has_one_through_association.rb +45 -0
  30. data/lib/active_record/associations/join_dependency/join_association.rb +106 -0
  31. data/lib/active_record/associations/join_dependency/join_base.rb +23 -0
  32. data/lib/active_record/associations/join_dependency/join_part.rb +71 -0
  33. data/lib/active_record/associations/join_dependency.rb +301 -0
  34. data/lib/active_record/associations/nested_error.rb +47 -0
  35. data/lib/active_record/associations/preloader/association.rb +316 -0
  36. data/lib/active_record/associations/preloader/batch.rb +48 -0
  37. data/lib/active_record/associations/preloader/branch.rb +153 -0
  38. data/lib/active_record/associations/preloader/through_association.rb +150 -0
  39. data/lib/active_record/associations/preloader.rb +135 -0
  40. data/lib/active_record/associations/singular_association.rb +76 -0
  41. data/lib/active_record/associations/through_association.rb +132 -0
  42. data/lib/active_record/associations.rb +1897 -0
  43. data/lib/active_record/asynchronous_queries_tracker.rb +64 -0
  44. data/lib/active_record/attribute_assignment.rb +82 -0
  45. data/lib/active_record/attribute_methods/before_type_cast.rb +106 -0
  46. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  47. data/lib/active_record/attribute_methods/dirty.rb +262 -0
  48. data/lib/active_record/attribute_methods/primary_key.rb +158 -0
  49. data/lib/active_record/attribute_methods/query.rb +50 -0
  50. data/lib/active_record/attribute_methods/read.rb +46 -0
  51. data/lib/active_record/attribute_methods/serialization.rb +232 -0
  52. data/lib/active_record/attribute_methods/time_zone_conversion.rb +94 -0
  53. data/lib/active_record/attribute_methods/write.rb +49 -0
  54. data/lib/active_record/attribute_methods.rb +542 -0
  55. data/lib/active_record/attributes.rb +307 -0
  56. data/lib/active_record/autosave_association.rb +586 -0
  57. data/lib/active_record/base.rb +338 -0
  58. data/lib/active_record/callbacks.rb +452 -0
  59. data/lib/active_record/coders/column_serializer.rb +61 -0
  60. data/lib/active_record/coders/json.rb +15 -0
  61. data/lib/active_record/coders/yaml_column.rb +95 -0
  62. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +290 -0
  63. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +210 -0
  64. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +78 -0
  65. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +923 -0
  66. data/lib/active_record/connection_adapters/abstract/database_limits.rb +31 -0
  67. data/lib/active_record/connection_adapters/abstract/database_statements.rb +747 -0
  68. data/lib/active_record/connection_adapters/abstract/query_cache.rb +319 -0
  69. data/lib/active_record/connection_adapters/abstract/quoting.rb +239 -0
  70. data/lib/active_record/connection_adapters/abstract/savepoints.rb +24 -0
  71. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +190 -0
  72. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +961 -0
  73. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +106 -0
  74. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1883 -0
  75. data/lib/active_record/connection_adapters/abstract/transaction.rb +676 -0
  76. data/lib/active_record/connection_adapters/abstract_adapter.rb +1218 -0
  77. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +1016 -0
  78. data/lib/active_record/connection_adapters/column.rb +122 -0
  79. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  80. data/lib/active_record/connection_adapters/mysql/column.rb +28 -0
  81. data/lib/active_record/connection_adapters/mysql/database_statements.rb +95 -0
  82. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
  83. data/lib/active_record/connection_adapters/mysql/quoting.rb +114 -0
  84. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +106 -0
  85. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +106 -0
  86. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +97 -0
  87. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +300 -0
  88. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
  89. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +96 -0
  90. data/lib/active_record/connection_adapters/mysql2_adapter.rb +196 -0
  91. data/lib/active_record/connection_adapters/pool_config.rb +83 -0
  92. data/lib/active_record/connection_adapters/pool_manager.rb +57 -0
  93. data/lib/active_record/connection_adapters/postgresql/column.rb +82 -0
  94. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +231 -0
  95. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +91 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +53 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +54 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +31 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +36 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +20 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +109 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
  109. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  110. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  111. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +42 -0
  112. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
  113. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +74 -0
  114. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +124 -0
  115. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
  116. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  117. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  118. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +125 -0
  119. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +45 -0
  120. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
  121. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
  122. data/lib/active_record/connection_adapters/postgresql/oid.rb +38 -0
  123. data/lib/active_record/connection_adapters/postgresql/quoting.rb +238 -0
  124. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +71 -0
  125. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +169 -0
  126. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +392 -0
  127. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +127 -0
  128. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +1162 -0
  129. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
  130. data/lib/active_record/connection_adapters/postgresql/utils.rb +79 -0
  131. data/lib/active_record/connection_adapters/postgresql_adapter.rb +1182 -0
  132. data/lib/active_record/connection_adapters/schema_cache.rb +478 -0
  133. data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
  134. data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
  135. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +145 -0
  136. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  137. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +116 -0
  138. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +37 -0
  139. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +39 -0
  140. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +47 -0
  141. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +221 -0
  142. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +843 -0
  143. data/lib/active_record/connection_adapters/statement_pool.rb +67 -0
  144. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +69 -0
  145. data/lib/active_record/connection_adapters/trilogy_adapter.rb +212 -0
  146. data/lib/active_record/connection_adapters.rb +176 -0
  147. data/lib/active_record/connection_handling.rb +413 -0
  148. data/lib/active_record/core.rb +836 -0
  149. data/lib/active_record/counter_cache.rb +230 -0
  150. data/lib/active_record/database_configurations/connection_url_resolver.rb +105 -0
  151. data/lib/active_record/database_configurations/database_config.rb +104 -0
  152. data/lib/active_record/database_configurations/hash_config.rb +172 -0
  153. data/lib/active_record/database_configurations/url_config.rb +78 -0
  154. data/lib/active_record/database_configurations.rb +309 -0
  155. data/lib/active_record/delegated_type.rb +289 -0
  156. data/lib/active_record/deprecator.rb +7 -0
  157. data/lib/active_record/destroy_association_async_job.rb +38 -0
  158. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  159. data/lib/active_record/dynamic_matchers.rb +121 -0
  160. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  161. data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
  162. data/lib/active_record/encryption/cipher.rb +53 -0
  163. data/lib/active_record/encryption/config.rb +70 -0
  164. data/lib/active_record/encryption/configurable.rb +60 -0
  165. data/lib/active_record/encryption/context.rb +42 -0
  166. data/lib/active_record/encryption/contexts.rb +76 -0
  167. data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
  168. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  169. data/lib/active_record/encryption/encryptable_record.rb +230 -0
  170. data/lib/active_record/encryption/encrypted_attribute_type.rb +184 -0
  171. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  172. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  173. data/lib/active_record/encryption/encryptor.rb +177 -0
  174. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  175. data/lib/active_record/encryption/errors.rb +15 -0
  176. data/lib/active_record/encryption/extended_deterministic_queries.rb +159 -0
  177. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  178. data/lib/active_record/encryption/key.rb +28 -0
  179. data/lib/active_record/encryption/key_generator.rb +53 -0
  180. data/lib/active_record/encryption/key_provider.rb +46 -0
  181. data/lib/active_record/encryption/message.rb +33 -0
  182. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  183. data/lib/active_record/encryption/message_serializer.rb +96 -0
  184. data/lib/active_record/encryption/null_encryptor.rb +25 -0
  185. data/lib/active_record/encryption/properties.rb +76 -0
  186. data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
  187. data/lib/active_record/encryption/scheme.rb +107 -0
  188. data/lib/active_record/encryption.rb +58 -0
  189. data/lib/active_record/enum.rb +424 -0
  190. data/lib/active_record/errors.rb +614 -0
  191. data/lib/active_record/explain.rb +63 -0
  192. data/lib/active_record/explain_registry.rb +37 -0
  193. data/lib/active_record/explain_subscriber.rb +34 -0
  194. data/lib/active_record/fixture_set/file.rb +89 -0
  195. data/lib/active_record/fixture_set/model_metadata.rb +42 -0
  196. data/lib/active_record/fixture_set/render_context.rb +19 -0
  197. data/lib/active_record/fixture_set/table_row.rb +208 -0
  198. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  199. data/lib/active_record/fixtures.rb +850 -0
  200. data/lib/active_record/future_result.rb +182 -0
  201. data/lib/active_record/gem_version.rb +17 -0
  202. data/lib/active_record/inheritance.rb +366 -0
  203. data/lib/active_record/insert_all.rb +328 -0
  204. data/lib/active_record/integration.rb +209 -0
  205. data/lib/active_record/internal_metadata.rb +164 -0
  206. data/lib/active_record/legacy_yaml_adapter.rb +15 -0
  207. data/lib/active_record/locale/en.yml +48 -0
  208. data/lib/active_record/locking/optimistic.rb +228 -0
  209. data/lib/active_record/locking/pessimistic.rb +102 -0
  210. data/lib/active_record/log_subscriber.rb +149 -0
  211. data/lib/active_record/marshalling.rb +56 -0
  212. data/lib/active_record/message_pack.rb +124 -0
  213. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  214. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  215. data/lib/active_record/middleware/database_selector.rb +87 -0
  216. data/lib/active_record/middleware/shard_selector.rb +62 -0
  217. data/lib/active_record/migration/command_recorder.rb +406 -0
  218. data/lib/active_record/migration/compatibility.rb +490 -0
  219. data/lib/active_record/migration/default_strategy.rb +22 -0
  220. data/lib/active_record/migration/execution_strategy.rb +19 -0
  221. data/lib/active_record/migration/join_table.rb +16 -0
  222. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  223. data/lib/active_record/migration.rb +1626 -0
  224. data/lib/active_record/model_schema.rb +635 -0
  225. data/lib/active_record/nested_attributes.rb +633 -0
  226. data/lib/active_record/no_touching.rb +65 -0
  227. data/lib/active_record/normalization.rb +163 -0
  228. data/lib/active_record/persistence.rb +968 -0
  229. data/lib/active_record/promise.rb +84 -0
  230. data/lib/active_record/query_cache.rb +56 -0
  231. data/lib/active_record/query_logs.rb +247 -0
  232. data/lib/active_record/query_logs_formatter.rb +30 -0
  233. data/lib/active_record/querying.rb +122 -0
  234. data/lib/active_record/railtie.rb +440 -0
  235. data/lib/active_record/railties/console_sandbox.rb +5 -0
  236. data/lib/active_record/railties/controller_runtime.rb +65 -0
  237. data/lib/active_record/railties/databases.rake +641 -0
  238. data/lib/active_record/railties/job_runtime.rb +23 -0
  239. data/lib/active_record/readonly_attributes.rb +66 -0
  240. data/lib/active_record/reflection.rb +1287 -0
  241. data/lib/active_record/relation/batches/batch_enumerator.rb +115 -0
  242. data/lib/active_record/relation/batches.rb +491 -0
  243. data/lib/active_record/relation/calculations.rb +679 -0
  244. data/lib/active_record/relation/delegation.rb +154 -0
  245. data/lib/active_record/relation/finder_methods.rb +661 -0
  246. data/lib/active_record/relation/from_clause.rb +30 -0
  247. data/lib/active_record/relation/merger.rb +192 -0
  248. data/lib/active_record/relation/predicate_builder/array_handler.rb +48 -0
  249. data/lib/active_record/relation/predicate_builder/association_query_value.rb +76 -0
  250. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  251. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +60 -0
  252. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  253. data/lib/active_record/relation/predicate_builder/relation_handler.rb +24 -0
  254. data/lib/active_record/relation/predicate_builder.rb +181 -0
  255. data/lib/active_record/relation/query_attribute.rb +68 -0
  256. data/lib/active_record/relation/query_methods.rb +2235 -0
  257. data/lib/active_record/relation/record_fetch_warning.rb +52 -0
  258. data/lib/active_record/relation/spawn_methods.rb +78 -0
  259. data/lib/active_record/relation/where_clause.rb +218 -0
  260. data/lib/active_record/relation.rb +1495 -0
  261. data/lib/active_record/result.rb +249 -0
  262. data/lib/active_record/runtime_registry.rb +82 -0
  263. data/lib/active_record/sanitization.rb +254 -0
  264. data/lib/active_record/schema.rb +77 -0
  265. data/lib/active_record/schema_dumper.rb +364 -0
  266. data/lib/active_record/schema_migration.rb +106 -0
  267. data/lib/active_record/scoping/default.rb +205 -0
  268. data/lib/active_record/scoping/named.rb +202 -0
  269. data/lib/active_record/scoping.rb +136 -0
  270. data/lib/active_record/secure_password.rb +60 -0
  271. data/lib/active_record/secure_token.rb +66 -0
  272. data/lib/active_record/serialization.rb +29 -0
  273. data/lib/active_record/signed_id.rb +137 -0
  274. data/lib/active_record/statement_cache.rb +164 -0
  275. data/lib/active_record/store.rb +299 -0
  276. data/lib/active_record/suppressor.rb +59 -0
  277. data/lib/active_record/table_metadata.rb +85 -0
  278. data/lib/active_record/tasks/database_tasks.rb +681 -0
  279. data/lib/active_record/tasks/mysql_database_tasks.rb +120 -0
  280. data/lib/active_record/tasks/postgresql_database_tasks.rb +147 -0
  281. data/lib/active_record/tasks/sqlite_database_tasks.rb +89 -0
  282. data/lib/active_record/test_databases.rb +24 -0
  283. data/lib/active_record/test_fixtures.rb +321 -0
  284. data/lib/active_record/testing/query_assertions.rb +121 -0
  285. data/lib/active_record/timestamp.rb +177 -0
  286. data/lib/active_record/token_for.rb +123 -0
  287. data/lib/active_record/touch_later.rb +70 -0
  288. data/lib/active_record/transaction.rb +132 -0
  289. data/lib/active_record/transactions.rb +523 -0
  290. data/lib/active_record/translation.rb +22 -0
  291. data/lib/active_record/type/adapter_specific_registry.rb +144 -0
  292. data/lib/active_record/type/date.rb +9 -0
  293. data/lib/active_record/type/date_time.rb +9 -0
  294. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  295. data/lib/active_record/type/hash_lookup_type_map.rb +57 -0
  296. data/lib/active_record/type/internal/timezone.rb +22 -0
  297. data/lib/active_record/type/json.rb +30 -0
  298. data/lib/active_record/type/serialized.rb +76 -0
  299. data/lib/active_record/type/text.rb +11 -0
  300. data/lib/active_record/type/time.rb +35 -0
  301. data/lib/active_record/type/type_map.rb +58 -0
  302. data/lib/active_record/type/unsigned_integer.rb +16 -0
  303. data/lib/active_record/type.rb +83 -0
  304. data/lib/active_record/type_caster/connection.rb +33 -0
  305. data/lib/active_record/type_caster/map.rb +23 -0
  306. data/lib/active_record/type_caster.rb +9 -0
  307. data/lib/active_record/validations/absence.rb +25 -0
  308. data/lib/active_record/validations/associated.rb +65 -0
  309. data/lib/active_record/validations/length.rb +26 -0
  310. data/lib/active_record/validations/numericality.rb +36 -0
  311. data/lib/active_record/validations/presence.rb +45 -0
  312. data/lib/active_record/validations/uniqueness.rb +295 -0
  313. data/lib/active_record/validations.rb +101 -0
  314. data/lib/active_record/version.rb +10 -0
  315. data/lib/active_record.rb +616 -0
  316. data/lib/arel/alias_predication.rb +9 -0
  317. data/lib/arel/attributes/attribute.rb +33 -0
  318. data/lib/arel/collectors/bind.rb +31 -0
  319. data/lib/arel/collectors/composite.rb +46 -0
  320. data/lib/arel/collectors/plain_string.rb +20 -0
  321. data/lib/arel/collectors/sql_string.rb +27 -0
  322. data/lib/arel/collectors/substitute_binds.rb +35 -0
  323. data/lib/arel/crud.rb +48 -0
  324. data/lib/arel/delete_manager.rb +32 -0
  325. data/lib/arel/errors.rb +19 -0
  326. data/lib/arel/expressions.rb +29 -0
  327. data/lib/arel/factory_methods.rb +53 -0
  328. data/lib/arel/filter_predications.rb +9 -0
  329. data/lib/arel/insert_manager.rb +48 -0
  330. data/lib/arel/math.rb +45 -0
  331. data/lib/arel/nodes/ascending.rb +23 -0
  332. data/lib/arel/nodes/binary.rb +125 -0
  333. data/lib/arel/nodes/bind_param.rb +44 -0
  334. data/lib/arel/nodes/bound_sql_literal.rb +65 -0
  335. data/lib/arel/nodes/case.rb +55 -0
  336. data/lib/arel/nodes/casted.rb +62 -0
  337. data/lib/arel/nodes/comment.rb +29 -0
  338. data/lib/arel/nodes/count.rb +12 -0
  339. data/lib/arel/nodes/cte.rb +36 -0
  340. data/lib/arel/nodes/delete_statement.rb +44 -0
  341. data/lib/arel/nodes/descending.rb +23 -0
  342. data/lib/arel/nodes/equality.rb +15 -0
  343. data/lib/arel/nodes/extract.rb +24 -0
  344. data/lib/arel/nodes/false.rb +16 -0
  345. data/lib/arel/nodes/filter.rb +10 -0
  346. data/lib/arel/nodes/fragments.rb +35 -0
  347. data/lib/arel/nodes/full_outer_join.rb +8 -0
  348. data/lib/arel/nodes/function.rb +45 -0
  349. data/lib/arel/nodes/grouping.rb +11 -0
  350. data/lib/arel/nodes/homogeneous_in.rb +68 -0
  351. data/lib/arel/nodes/in.rb +15 -0
  352. data/lib/arel/nodes/infix_operation.rb +92 -0
  353. data/lib/arel/nodes/inner_join.rb +8 -0
  354. data/lib/arel/nodes/insert_statement.rb +37 -0
  355. data/lib/arel/nodes/join_source.rb +20 -0
  356. data/lib/arel/nodes/leading_join.rb +8 -0
  357. data/lib/arel/nodes/matches.rb +18 -0
  358. data/lib/arel/nodes/named_function.rb +23 -0
  359. data/lib/arel/nodes/nary.rb +39 -0
  360. data/lib/arel/nodes/node.rb +161 -0
  361. data/lib/arel/nodes/node_expression.rb +13 -0
  362. data/lib/arel/nodes/ordering.rb +27 -0
  363. data/lib/arel/nodes/outer_join.rb +8 -0
  364. data/lib/arel/nodes/over.rb +15 -0
  365. data/lib/arel/nodes/regexp.rb +16 -0
  366. data/lib/arel/nodes/right_outer_join.rb +8 -0
  367. data/lib/arel/nodes/select_core.rb +67 -0
  368. data/lib/arel/nodes/select_statement.rb +41 -0
  369. data/lib/arel/nodes/sql_literal.rb +32 -0
  370. data/lib/arel/nodes/string_join.rb +11 -0
  371. data/lib/arel/nodes/table_alias.rb +35 -0
  372. data/lib/arel/nodes/terminal.rb +16 -0
  373. data/lib/arel/nodes/true.rb +16 -0
  374. data/lib/arel/nodes/unary.rb +44 -0
  375. data/lib/arel/nodes/unary_operation.rb +20 -0
  376. data/lib/arel/nodes/unqualified_column.rb +22 -0
  377. data/lib/arel/nodes/update_statement.rb +46 -0
  378. data/lib/arel/nodes/values_list.rb +9 -0
  379. data/lib/arel/nodes/window.rb +126 -0
  380. data/lib/arel/nodes/with.rb +11 -0
  381. data/lib/arel/nodes.rb +75 -0
  382. data/lib/arel/order_predications.rb +13 -0
  383. data/lib/arel/predications.rb +260 -0
  384. data/lib/arel/select_manager.rb +276 -0
  385. data/lib/arel/table.rb +121 -0
  386. data/lib/arel/tree_manager.rb +65 -0
  387. data/lib/arel/update_manager.rb +49 -0
  388. data/lib/arel/visitors/dot.rb +299 -0
  389. data/lib/arel/visitors/mysql.rb +111 -0
  390. data/lib/arel/visitors/postgresql.rb +99 -0
  391. data/lib/arel/visitors/sqlite.rb +38 -0
  392. data/lib/arel/visitors/to_sql.rb +1033 -0
  393. data/lib/arel/visitors/visitor.rb +45 -0
  394. data/lib/arel/visitors.rb +13 -0
  395. data/lib/arel/window_predications.rb +9 -0
  396. data/lib/arel.rb +73 -0
  397. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  398. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  399. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  400. data/lib/rails/generators/active_record/migration/migration_generator.rb +76 -0
  401. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +29 -0
  402. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +48 -0
  403. data/lib/rails/generators/active_record/migration.rb +54 -0
  404. data/lib/rails/generators/active_record/model/USAGE +113 -0
  405. data/lib/rails/generators/active_record/model/model_generator.rb +94 -0
  406. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  407. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  408. data/lib/rails/generators/active_record/model/templates/module.rb.tt +7 -0
  409. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  410. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  411. data/lib/rails/generators/active_record.rb +19 -0
  412. metadata +505 -0
@@ -0,0 +1,1218 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+ require "active_record/connection_adapters/sql_type_metadata"
5
+ require "active_record/connection_adapters/abstract/schema_dumper"
6
+ require "active_record/connection_adapters/abstract/schema_creation"
7
+ require "active_support/concurrency/null_lock"
8
+ require "active_support/concurrency/load_interlock_aware_monitor"
9
+ require "arel/collectors/bind"
10
+ require "arel/collectors/composite"
11
+ require "arel/collectors/sql_string"
12
+ require "arel/collectors/substitute_binds"
13
+
14
+ module ActiveRecord
15
+ module ConnectionAdapters # :nodoc:
16
+ # = Active Record Abstract Adapter
17
+ #
18
+ # Active Record supports multiple database systems. AbstractAdapter and
19
+ # related classes form the abstraction layer which makes this possible.
20
+ # An AbstractAdapter represents a connection to a database, and provides an
21
+ # abstract interface for database-specific functionality such as establishing
22
+ # a connection, escaping values, building the right SQL fragments for +:offset+
23
+ # and +:limit+ options, etc.
24
+ #
25
+ # All the concrete database adapters follow the interface laid down in this class.
26
+ # {ActiveRecord::Base.lease_connection}[rdoc-ref:ConnectionHandling#lease_connection] returns an AbstractAdapter object, which
27
+ # you can use.
28
+ #
29
+ # Most of the methods in the adapter are useful during migrations. Most
30
+ # notably, the instance methods provided by SchemaStatements are very useful.
31
+ class AbstractAdapter
32
+ ADAPTER_NAME = "Abstract"
33
+ include ActiveSupport::Callbacks
34
+ define_callbacks :checkout, :checkin
35
+
36
+ include Quoting, DatabaseStatements, SchemaStatements
37
+ include DatabaseLimits
38
+ include QueryCache
39
+ include Savepoints
40
+
41
+ SIMPLE_INT = /\A\d+\z/
42
+ COMMENT_REGEX = %r{(?:--.*\n)|/\*(?:[^*]|\*[^/])*\*/}
43
+
44
+ attr_reader :pool
45
+ attr_reader :visitor, :owner, :logger, :lock
46
+ alias :in_use? :owner
47
+
48
+ def pool=(value)
49
+ return if value.eql?(@pool)
50
+ @schema_cache = nil
51
+ @pool = value
52
+ end
53
+
54
+ set_callback :checkin, :after, :enable_lazy_transactions!
55
+
56
+ def self.type_cast_config_to_integer(config)
57
+ if config.is_a?(Integer)
58
+ config
59
+ elsif SIMPLE_INT.match?(config)
60
+ config.to_i
61
+ else
62
+ config
63
+ end
64
+ end
65
+
66
+ def self.type_cast_config_to_boolean(config)
67
+ if config == "false"
68
+ false
69
+ else
70
+ config
71
+ end
72
+ end
73
+
74
+ def self.validate_default_timezone(config)
75
+ case config
76
+ when nil
77
+ when "utc", "local"
78
+ config.to_sym
79
+ else
80
+ raise ArgumentError, "default_timezone must be either 'utc' or 'local'"
81
+ end
82
+ end
83
+
84
+ DEFAULT_READ_QUERY = [:begin, :commit, :explain, :release, :rollback, :savepoint, :select, :with] # :nodoc:
85
+ private_constant :DEFAULT_READ_QUERY
86
+
87
+ def self.build_read_query_regexp(*parts) # :nodoc:
88
+ parts += DEFAULT_READ_QUERY
89
+ parts = parts.map { |part| /#{part}/i }
90
+ /\A(?:[(\s]|#{COMMENT_REGEX})*#{Regexp.union(*parts)}/
91
+ end
92
+
93
+ def self.find_cmd_and_exec(commands, *args) # :doc:
94
+ commands = Array(commands)
95
+
96
+ dirs_on_path = ENV["PATH"].to_s.split(File::PATH_SEPARATOR)
97
+ unless (ext = RbConfig::CONFIG["EXEEXT"]).empty?
98
+ commands = commands.map { |cmd| "#{cmd}#{ext}" }
99
+ end
100
+
101
+ full_path_command = nil
102
+ found = commands.detect do |cmd|
103
+ dirs_on_path.detect do |path|
104
+ full_path_command = File.join(path, cmd)
105
+ begin
106
+ stat = File.stat(full_path_command)
107
+ rescue SystemCallError
108
+ else
109
+ stat.file? && stat.executable?
110
+ end
111
+ end
112
+ end
113
+
114
+ if found
115
+ exec full_path_command, *args
116
+ else
117
+ abort("Couldn't find database client: #{commands.join(', ')}. Check your $PATH and try again.")
118
+ end
119
+ end
120
+
121
+ # Opens a database console session.
122
+ def self.dbconsole(config, options = {})
123
+ raise NotImplementedError
124
+ end
125
+
126
+ def initialize(config_or_deprecated_connection, deprecated_logger = nil, deprecated_connection_options = nil, deprecated_config = nil) # :nodoc:
127
+ super()
128
+
129
+ @raw_connection = nil
130
+ @unconfigured_connection = nil
131
+
132
+ if config_or_deprecated_connection.is_a?(Hash)
133
+ @config = config_or_deprecated_connection.symbolize_keys
134
+ @logger = ActiveRecord::Base.logger
135
+
136
+ if deprecated_logger || deprecated_connection_options || deprecated_config
137
+ raise ArgumentError, "when initializing an Active Record adapter with a config hash, that should be the only argument"
138
+ end
139
+ else
140
+ # Soft-deprecated for now; we'll probably warn in future.
141
+
142
+ @unconfigured_connection = config_or_deprecated_connection
143
+ @logger = deprecated_logger || ActiveRecord::Base.logger
144
+ if deprecated_config
145
+ @config = (deprecated_config || {}).symbolize_keys
146
+ @connection_parameters = deprecated_connection_options
147
+ else
148
+ @config = (deprecated_connection_options || {}).symbolize_keys
149
+ @connection_parameters = nil
150
+ end
151
+ end
152
+
153
+ @owner = nil
154
+ @instrumenter = ActiveSupport::Notifications.instrumenter
155
+ @pool = ActiveRecord::ConnectionAdapters::NullPool.new
156
+ @idle_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
157
+ @visitor = arel_visitor
158
+ @statements = build_statement_pool
159
+ self.lock_thread = nil
160
+
161
+ @prepared_statements = !ActiveRecord.disable_prepared_statements && self.class.type_cast_config_to_boolean(
162
+ @config.fetch(:prepared_statements) { default_prepared_statements }
163
+ )
164
+
165
+ @advisory_locks_enabled = self.class.type_cast_config_to_boolean(
166
+ @config.fetch(:advisory_locks, true)
167
+ )
168
+
169
+ @default_timezone = self.class.validate_default_timezone(@config[:default_timezone])
170
+
171
+ @raw_connection_dirty = false
172
+ @verified = false
173
+ end
174
+
175
+ def inspect # :nodoc:
176
+ name_field = " name=#{pool.db_config.name.inspect}" unless pool.db_config.name == "primary"
177
+ shard_field = " shard=#{shard.inspect}" unless shard == :default
178
+
179
+ "#<#{self.class.name}:#{'%#016x' % (object_id << 1)} env_name=#{pool.db_config.env_name.inspect}#{name_field} role=#{role.inspect}#{shard_field}>"
180
+ end
181
+
182
+ def lock_thread=(lock_thread) # :nodoc:
183
+ @lock =
184
+ case lock_thread
185
+ when Thread
186
+ ActiveSupport::Concurrency::ThreadLoadInterlockAwareMonitor.new
187
+ when Fiber
188
+ ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
189
+ else
190
+ ActiveSupport::Concurrency::NullLock
191
+ end
192
+ end
193
+
194
+ EXCEPTION_NEVER = { Exception => :never }.freeze # :nodoc:
195
+ EXCEPTION_IMMEDIATE = { Exception => :immediate }.freeze # :nodoc:
196
+ private_constant :EXCEPTION_NEVER, :EXCEPTION_IMMEDIATE
197
+ def with_instrumenter(instrumenter, &block) # :nodoc:
198
+ Thread.handle_interrupt(EXCEPTION_NEVER) do
199
+ previous_instrumenter = @instrumenter
200
+ @instrumenter = instrumenter
201
+ Thread.handle_interrupt(EXCEPTION_IMMEDIATE, &block)
202
+ ensure
203
+ @instrumenter = previous_instrumenter
204
+ end
205
+ end
206
+
207
+ def check_if_write_query(sql) # :nodoc:
208
+ if preventing_writes? && write_query?(sql)
209
+ raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
210
+ end
211
+ end
212
+
213
+ def replica?
214
+ @config[:replica] || false
215
+ end
216
+
217
+ def connection_retries
218
+ (@config[:connection_retries] || 1).to_i
219
+ end
220
+
221
+ def retry_deadline
222
+ if @config[:retry_deadline]
223
+ @config[:retry_deadline].to_f
224
+ else
225
+ nil
226
+ end
227
+ end
228
+
229
+ def default_timezone
230
+ @default_timezone || ActiveRecord.default_timezone
231
+ end
232
+
233
+ # Determines whether writes are currently being prevented.
234
+ #
235
+ # Returns true if the connection is a replica or returns
236
+ # the value of +current_preventing_writes+.
237
+ def preventing_writes?
238
+ return true if replica?
239
+ return false if connection_class.nil?
240
+
241
+ connection_class.current_preventing_writes
242
+ end
243
+
244
+ def prepared_statements?
245
+ @prepared_statements && !prepared_statements_disabled_cache.include?(object_id)
246
+ end
247
+ alias :prepared_statements :prepared_statements?
248
+
249
+ def prepared_statements_disabled_cache # :nodoc:
250
+ ActiveSupport::IsolatedExecutionState[:active_record_prepared_statements_disabled_cache] ||= Set.new
251
+ end
252
+
253
+ class Version
254
+ include Comparable
255
+
256
+ attr_reader :full_version_string
257
+
258
+ def initialize(version_string, full_version_string = nil)
259
+ @version = version_string.split(".").map(&:to_i)
260
+ @full_version_string = full_version_string
261
+ end
262
+
263
+ def <=>(version_string)
264
+ @version <=> version_string.split(".").map(&:to_i)
265
+ end
266
+
267
+ def to_s
268
+ @version.join(".")
269
+ end
270
+ end
271
+
272
+ def valid_type?(type) # :nodoc:
273
+ !native_database_types[type].nil?
274
+ end
275
+
276
+ # this method must only be called while holding connection pool's mutex
277
+ def lease
278
+ if in_use?
279
+ msg = +"Cannot lease connection, "
280
+ if @owner == ActiveSupport::IsolatedExecutionState.context
281
+ msg << "it is already leased by the current thread."
282
+ else
283
+ msg << "it is already in use by a different thread: #{@owner}. " \
284
+ "Current thread: #{ActiveSupport::IsolatedExecutionState.context}."
285
+ end
286
+ raise ActiveRecordError, msg
287
+ end
288
+
289
+ @owner = ActiveSupport::IsolatedExecutionState.context
290
+ end
291
+
292
+ def connection_class # :nodoc:
293
+ @pool.connection_class
294
+ end
295
+
296
+ # The role (e.g. +:writing+) for the current connection. In a
297
+ # non-multi role application, +:writing+ is returned.
298
+ def role
299
+ @pool.role
300
+ end
301
+
302
+ # The shard (e.g. +:default+) for the current connection. In
303
+ # a non-sharded application, +:default+ is returned.
304
+ def shard
305
+ @pool.shard
306
+ end
307
+
308
+ def schema_cache
309
+ @pool.schema_cache || (@schema_cache ||= BoundSchemaReflection.for_lone_connection(@pool.schema_reflection, self))
310
+ end
311
+
312
+ # this method must only be called while holding connection pool's mutex
313
+ def expire
314
+ if in_use?
315
+ if @owner != ActiveSupport::IsolatedExecutionState.context
316
+ raise ActiveRecordError, "Cannot expire connection, " \
317
+ "it is owned by a different thread: #{@owner}. " \
318
+ "Current thread: #{ActiveSupport::IsolatedExecutionState.context}."
319
+ end
320
+
321
+ @idle_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
322
+ @owner = nil
323
+ else
324
+ raise ActiveRecordError, "Cannot expire connection, it is not currently leased."
325
+ end
326
+ end
327
+
328
+ # this method must only be called while holding connection pool's mutex (and a desire for segfaults)
329
+ def steal! # :nodoc:
330
+ if in_use?
331
+ if @owner != ActiveSupport::IsolatedExecutionState.context
332
+ pool.send :remove_connection_from_thread_cache, self, @owner
333
+
334
+ @owner = ActiveSupport::IsolatedExecutionState.context
335
+ end
336
+ else
337
+ raise ActiveRecordError, "Cannot steal connection, it is not currently leased."
338
+ end
339
+ end
340
+
341
+ # Seconds since this connection was returned to the pool
342
+ def seconds_idle # :nodoc:
343
+ return 0 if in_use?
344
+ Process.clock_gettime(Process::CLOCK_MONOTONIC) - @idle_since
345
+ end
346
+
347
+ def unprepared_statement
348
+ cache = prepared_statements_disabled_cache.add?(object_id) if @prepared_statements
349
+ yield
350
+ ensure
351
+ cache&.delete(object_id)
352
+ end
353
+
354
+ # Returns the human-readable name of the adapter. Use mixed case - one
355
+ # can always use downcase if needed.
356
+ def adapter_name
357
+ self.class::ADAPTER_NAME
358
+ end
359
+
360
+ # Does the database for this adapter exist?
361
+ def self.database_exists?(config)
362
+ new(config).database_exists?
363
+ end
364
+
365
+ def database_exists?
366
+ connect!
367
+ true
368
+ rescue ActiveRecord::NoDatabaseError
369
+ false
370
+ end
371
+
372
+ # Does this adapter support DDL rollbacks in transactions? That is, would
373
+ # CREATE TABLE or ALTER TABLE get rolled back by a transaction?
374
+ def supports_ddl_transactions?
375
+ false
376
+ end
377
+
378
+ def supports_bulk_alter?
379
+ false
380
+ end
381
+
382
+ # Does this adapter support savepoints?
383
+ def supports_savepoints?
384
+ false
385
+ end
386
+
387
+ # Do TransactionRollbackErrors on savepoints affect the parent
388
+ # transaction?
389
+ def savepoint_errors_invalidate_transactions?
390
+ false
391
+ end
392
+
393
+ def supports_restart_db_transaction?
394
+ false
395
+ end
396
+
397
+ # Does this adapter support application-enforced advisory locking?
398
+ def supports_advisory_locks?
399
+ false
400
+ end
401
+
402
+ # Should primary key values be selected from their corresponding
403
+ # sequence before the insert statement? If true, next_sequence_value
404
+ # is called before each insert to set the record's primary key.
405
+ def prefetch_primary_key?(table_name = nil)
406
+ false
407
+ end
408
+
409
+ def supports_partitioned_indexes?
410
+ false
411
+ end
412
+
413
+ # Does this adapter support index sort order?
414
+ def supports_index_sort_order?
415
+ false
416
+ end
417
+
418
+ # Does this adapter support partial indices?
419
+ def supports_partial_index?
420
+ false
421
+ end
422
+
423
+ # Does this adapter support including non-key columns?
424
+ def supports_index_include?
425
+ false
426
+ end
427
+
428
+ # Does this adapter support expression indices?
429
+ def supports_expression_index?
430
+ false
431
+ end
432
+
433
+ # Does this adapter support explain?
434
+ def supports_explain?
435
+ false
436
+ end
437
+
438
+ # Does this adapter support setting the isolation level for a transaction?
439
+ def supports_transaction_isolation?
440
+ false
441
+ end
442
+
443
+ # Does this adapter support database extensions?
444
+ def supports_extensions?
445
+ false
446
+ end
447
+
448
+ # Does this adapter support creating indexes in the same statement as
449
+ # creating the table?
450
+ def supports_indexes_in_create?
451
+ false
452
+ end
453
+
454
+ # Does this adapter support creating foreign key constraints?
455
+ def supports_foreign_keys?
456
+ false
457
+ end
458
+
459
+ # Does this adapter support creating invalid constraints?
460
+ def supports_validate_constraints?
461
+ false
462
+ end
463
+
464
+ # Does this adapter support creating deferrable constraints?
465
+ def supports_deferrable_constraints?
466
+ false
467
+ end
468
+
469
+ # Does this adapter support creating check constraints?
470
+ def supports_check_constraints?
471
+ false
472
+ end
473
+
474
+ # Does this adapter support creating exclusion constraints?
475
+ def supports_exclusion_constraints?
476
+ false
477
+ end
478
+
479
+ # Does this adapter support creating unique constraints?
480
+ def supports_unique_constraints?
481
+ false
482
+ end
483
+
484
+ # Does this adapter support views?
485
+ def supports_views?
486
+ false
487
+ end
488
+
489
+ # Does this adapter support materialized views?
490
+ def supports_materialized_views?
491
+ false
492
+ end
493
+
494
+ # Does this adapter support datetime with precision?
495
+ def supports_datetime_with_precision?
496
+ false
497
+ end
498
+
499
+ # Does this adapter support JSON data type?
500
+ def supports_json?
501
+ false
502
+ end
503
+
504
+ # Does this adapter support metadata comments on database objects (tables, columns, indexes)?
505
+ def supports_comments?
506
+ false
507
+ end
508
+
509
+ # Can comments for tables, columns, and indexes be specified in create/alter table statements?
510
+ def supports_comments_in_create?
511
+ false
512
+ end
513
+
514
+ # Does this adapter support virtual columns?
515
+ def supports_virtual_columns?
516
+ false
517
+ end
518
+
519
+ # Does this adapter support foreign/external tables?
520
+ def supports_foreign_tables?
521
+ false
522
+ end
523
+
524
+ # Does this adapter support optimizer hints?
525
+ def supports_optimizer_hints?
526
+ false
527
+ end
528
+
529
+ def supports_common_table_expressions?
530
+ false
531
+ end
532
+
533
+ def supports_lazy_transactions?
534
+ false
535
+ end
536
+
537
+ def supports_insert_returning?
538
+ false
539
+ end
540
+
541
+ def supports_insert_on_duplicate_skip?
542
+ false
543
+ end
544
+
545
+ def supports_insert_on_duplicate_update?
546
+ false
547
+ end
548
+
549
+ def supports_insert_conflict_target?
550
+ false
551
+ end
552
+
553
+ def supports_concurrent_connections?
554
+ true
555
+ end
556
+
557
+ def supports_nulls_not_distinct?
558
+ false
559
+ end
560
+
561
+ def return_value_after_insert?(column) # :nodoc:
562
+ column.auto_populated?
563
+ end
564
+
565
+ def async_enabled? # :nodoc:
566
+ supports_concurrent_connections? &&
567
+ !ActiveRecord.async_query_executor.nil? && !pool.async_executor.nil?
568
+ end
569
+
570
+ # This is meant to be implemented by the adapters that support extensions
571
+ def disable_extension(name, **)
572
+ end
573
+
574
+ # This is meant to be implemented by the adapters that support extensions
575
+ def enable_extension(name, **)
576
+ end
577
+
578
+ # This is meant to be implemented by the adapters that support custom enum types
579
+ def create_enum(...) # :nodoc:
580
+ end
581
+
582
+ # This is meant to be implemented by the adapters that support custom enum types
583
+ def drop_enum(...) # :nodoc:
584
+ end
585
+
586
+ # This is meant to be implemented by the adapters that support custom enum types
587
+ def rename_enum(...) # :nodoc:
588
+ end
589
+
590
+ # This is meant to be implemented by the adapters that support custom enum types
591
+ def add_enum_value(...) # :nodoc:
592
+ end
593
+
594
+ # This is meant to be implemented by the adapters that support custom enum types
595
+ def rename_enum_value(...) # :nodoc:
596
+ end
597
+
598
+ # This is meant to be implemented by the adapters that support virtual tables
599
+ def create_virtual_table(*) # :nodoc:
600
+ end
601
+
602
+ # This is meant to be implemented by the adapters that support virtual tables
603
+ def drop_virtual_table(*) # :nodoc:
604
+ end
605
+
606
+ def advisory_locks_enabled? # :nodoc:
607
+ supports_advisory_locks? && @advisory_locks_enabled
608
+ end
609
+
610
+ # This is meant to be implemented by the adapters that support advisory
611
+ # locks
612
+ #
613
+ # Return true if we got the lock, otherwise false
614
+ def get_advisory_lock(lock_id) # :nodoc:
615
+ end
616
+
617
+ # This is meant to be implemented by the adapters that support advisory
618
+ # locks.
619
+ #
620
+ # Return true if we released the lock, otherwise false
621
+ def release_advisory_lock(lock_id) # :nodoc:
622
+ end
623
+
624
+ # A list of extensions, to be filled in by adapters that support them.
625
+ def extensions
626
+ []
627
+ end
628
+
629
+ # A list of index algorithms, to be filled by adapters that support them.
630
+ def index_algorithms
631
+ {}
632
+ end
633
+
634
+ # REFERENTIAL INTEGRITY ====================================
635
+
636
+ # Override to turn off referential integrity while executing <tt>&block</tt>.
637
+ def disable_referential_integrity
638
+ yield
639
+ end
640
+
641
+ # Override to check all foreign key constraints in a database.
642
+ # The adapter should raise a +ActiveRecord::StatementInvalid+ if foreign key
643
+ # constraints are not met.
644
+ def check_all_foreign_keys_valid!
645
+ end
646
+
647
+ # CONNECTION MANAGEMENT ====================================
648
+
649
+ # Checks whether the connection to the database was established. This doesn't
650
+ # include checking whether the database is actually capable of responding, i.e.
651
+ # whether the connection is stale.
652
+ def connected?
653
+ !@raw_connection.nil?
654
+ end
655
+
656
+ # Checks whether the connection to the database is still active. This includes
657
+ # checking whether the database is actually capable of responding, i.e. whether
658
+ # the connection isn't stale.
659
+ def active?
660
+ end
661
+
662
+ # Disconnects from the database if already connected, and establishes a new
663
+ # connection with the database. Implementors should define private #reconnect
664
+ # instead.
665
+ def reconnect!(restore_transactions: false)
666
+ retries_available = connection_retries
667
+ deadline = retry_deadline && Process.clock_gettime(Process::CLOCK_MONOTONIC) + retry_deadline
668
+
669
+ @lock.synchronize do
670
+ reconnect
671
+
672
+ enable_lazy_transactions!
673
+ @raw_connection_dirty = false
674
+ @verified = true
675
+
676
+ reset_transaction(restore: restore_transactions) do
677
+ clear_cache!(new_connection: true)
678
+ configure_connection
679
+ end
680
+ rescue => original_exception
681
+ translated_exception = translate_exception_class(original_exception, nil, nil)
682
+ retry_deadline_exceeded = deadline && deadline < Process.clock_gettime(Process::CLOCK_MONOTONIC)
683
+
684
+ if !retry_deadline_exceeded && retries_available > 0
685
+ retries_available -= 1
686
+
687
+ if retryable_connection_error?(translated_exception)
688
+ backoff(connection_retries - retries_available)
689
+ retry
690
+ end
691
+ end
692
+
693
+ @verified = false
694
+
695
+ raise translated_exception
696
+ end
697
+ end
698
+
699
+ # Disconnects from the database if already connected. Otherwise, this
700
+ # method does nothing.
701
+ def disconnect!
702
+ @lock.synchronize do
703
+ clear_cache!(new_connection: true)
704
+ reset_transaction
705
+ @raw_connection_dirty = false
706
+ end
707
+ end
708
+
709
+ # Immediately forget this connection ever existed. Unlike disconnect!,
710
+ # this will not communicate with the server.
711
+ #
712
+ # After calling this method, the behavior of all other methods becomes
713
+ # undefined. This is called internally just before a forked process gets
714
+ # rid of a connection that belonged to its parent.
715
+ def discard!
716
+ # This should be overridden by concrete adapters.
717
+ end
718
+
719
+ # Reset the state of this connection, directing the DBMS to clear
720
+ # transactions and other connection-related server-side state. Usually a
721
+ # database-dependent operation.
722
+ #
723
+ # If a database driver or protocol does not support such a feature,
724
+ # implementors may alias this to #reconnect!. Otherwise, implementors
725
+ # should call super immediately after resetting the connection (and while
726
+ # still holding @lock).
727
+ def reset!
728
+ clear_cache!(new_connection: true)
729
+ reset_transaction
730
+ configure_connection
731
+ end
732
+
733
+ # Removes the connection from the pool and disconnect it.
734
+ def throw_away!
735
+ pool.remove self
736
+ disconnect!
737
+ end
738
+
739
+ # Clear any caching the database adapter may be doing.
740
+ def clear_cache!(new_connection: false)
741
+ if @statements
742
+ @lock.synchronize do
743
+ if new_connection
744
+ @statements.reset
745
+ else
746
+ @statements.clear
747
+ end
748
+ end
749
+ end
750
+ end
751
+
752
+ # Returns true if its required to reload the connection between requests for development mode.
753
+ def requires_reloading?
754
+ false
755
+ end
756
+
757
+ # Checks whether the connection to the database is still active (i.e. not stale).
758
+ # This is done under the hood by calling #active?. If the connection
759
+ # is no longer active, then this method will reconnect to the database.
760
+ def verify!
761
+ unless active?
762
+ @lock.synchronize do
763
+ if @unconfigured_connection
764
+ @raw_connection = @unconfigured_connection
765
+ @unconfigured_connection = nil
766
+ configure_connection
767
+ @verified = true
768
+ return
769
+ end
770
+
771
+ reconnect!(restore_transactions: true)
772
+ end
773
+ end
774
+
775
+ @verified = true
776
+ end
777
+
778
+ def connect!
779
+ verify!
780
+ self
781
+ end
782
+
783
+ def clean! # :nodoc:
784
+ @raw_connection_dirty = false
785
+ @verified = nil
786
+ end
787
+
788
+ # Provides access to the underlying database driver for this adapter. For
789
+ # example, this method returns a Mysql2::Client object in case of Mysql2Adapter,
790
+ # and a PG::Connection object in case of PostgreSQLAdapter.
791
+ #
792
+ # This is useful for when you need to call a proprietary method such as
793
+ # PostgreSQL's lo_* methods.
794
+ #
795
+ # Active Record cannot track if the database is getting modified using
796
+ # this client. If that is the case, generally you'll want to invalidate
797
+ # the query cache using +ActiveRecord::Base.clear_query_cache+.
798
+ def raw_connection
799
+ with_raw_connection do |conn|
800
+ disable_lazy_transactions!
801
+ @raw_connection_dirty = true
802
+ conn
803
+ end
804
+ end
805
+
806
+ def default_uniqueness_comparison(attribute, value) # :nodoc:
807
+ attribute.eq(value)
808
+ end
809
+
810
+ def case_sensitive_comparison(attribute, value) # :nodoc:
811
+ attribute.eq(value)
812
+ end
813
+
814
+ def case_insensitive_comparison(attribute, value) # :nodoc:
815
+ column = column_for_attribute(attribute)
816
+
817
+ if can_perform_case_insensitive_comparison_for?(column)
818
+ attribute.lower.eq(attribute.relation.lower(value))
819
+ else
820
+ attribute.eq(value)
821
+ end
822
+ end
823
+
824
+ def can_perform_case_insensitive_comparison_for?(column)
825
+ true
826
+ end
827
+ private :can_perform_case_insensitive_comparison_for?
828
+
829
+ # Check the connection back in to the connection pool
830
+ def close
831
+ pool.checkin self
832
+ end
833
+
834
+ def default_index_type?(index) # :nodoc:
835
+ index.using.nil?
836
+ end
837
+
838
+ # Called by ActiveRecord::InsertAll,
839
+ # Passed an instance of ActiveRecord::InsertAll::Builder,
840
+ # This method implements standard bulk inserts for all databases, but
841
+ # should be overridden by adapters to implement common features with
842
+ # non-standard syntax like handling duplicates or returning values.
843
+ def build_insert_sql(insert) # :nodoc:
844
+ if insert.skip_duplicates? || insert.update_duplicates?
845
+ raise NotImplementedError, "#{self.class} should define `build_insert_sql` to implement adapter-specific logic for handling duplicates during INSERT"
846
+ end
847
+
848
+ "INSERT #{insert.into} #{insert.values_list}"
849
+ end
850
+
851
+ def get_database_version # :nodoc:
852
+ end
853
+
854
+ def database_version # :nodoc:
855
+ pool.server_version(self)
856
+ end
857
+
858
+ def check_version # :nodoc:
859
+ end
860
+
861
+ # Returns the version identifier of the schema currently available in
862
+ # the database. This is generally equal to the number of the highest-
863
+ # numbered migration that has been executed, or 0 if no schema
864
+ # information is present / the database is empty.
865
+ def schema_version
866
+ pool.migration_context.current_version
867
+ end
868
+
869
+ class << self
870
+ def register_class_with_precision(mapping, key, klass, **kwargs) # :nodoc:
871
+ mapping.register_type(key) do |*args|
872
+ precision = extract_precision(args.last)
873
+ klass.new(precision: precision, **kwargs)
874
+ end
875
+ end
876
+
877
+ def extended_type_map(default_timezone:) # :nodoc:
878
+ Type::TypeMap.new(self::TYPE_MAP).tap do |m|
879
+ register_class_with_precision m, %r(\A[^\(]*time)i, Type::Time, timezone: default_timezone
880
+ register_class_with_precision m, %r(\A[^\(]*datetime)i, Type::DateTime, timezone: default_timezone
881
+ m.alias_type %r(\A[^\(]*timestamp)i, "datetime"
882
+ end
883
+ end
884
+
885
+ private
886
+ def initialize_type_map(m)
887
+ register_class_with_limit m, %r(boolean)i, Type::Boolean
888
+ register_class_with_limit m, %r(char)i, Type::String
889
+ register_class_with_limit m, %r(binary)i, Type::Binary
890
+ register_class_with_limit m, %r(text)i, Type::Text
891
+ register_class_with_precision m, %r(date)i, Type::Date
892
+ register_class_with_precision m, %r(time)i, Type::Time
893
+ register_class_with_precision m, %r(datetime)i, Type::DateTime
894
+ register_class_with_limit m, %r(float)i, Type::Float
895
+ register_class_with_limit m, %r(int)i, Type::Integer
896
+
897
+ m.alias_type %r(blob)i, "binary"
898
+ m.alias_type %r(clob)i, "text"
899
+ m.alias_type %r(timestamp)i, "datetime"
900
+ m.alias_type %r(numeric)i, "decimal"
901
+ m.alias_type %r(number)i, "decimal"
902
+ m.alias_type %r(double)i, "float"
903
+
904
+ m.register_type %r(^json)i, Type::Json.new
905
+
906
+ m.register_type(%r(decimal)i) do |sql_type|
907
+ scale = extract_scale(sql_type)
908
+ precision = extract_precision(sql_type)
909
+
910
+ if scale == 0
911
+ # FIXME: Remove this class as well
912
+ Type::DecimalWithoutScale.new(precision: precision)
913
+ else
914
+ Type::Decimal.new(precision: precision, scale: scale)
915
+ end
916
+ end
917
+ end
918
+
919
+ def register_class_with_limit(mapping, key, klass)
920
+ mapping.register_type(key) do |*args|
921
+ limit = extract_limit(args.last)
922
+ klass.new(limit: limit)
923
+ end
924
+ end
925
+
926
+ def extract_scale(sql_type)
927
+ case sql_type
928
+ when /\((\d+)\)/ then 0
929
+ when /\((\d+)(,(\d+))\)/ then $3.to_i
930
+ end
931
+ end
932
+
933
+ def extract_precision(sql_type)
934
+ $1.to_i if sql_type =~ /\((\d+)(,\d+)?\)/
935
+ end
936
+
937
+ def extract_limit(sql_type)
938
+ $1.to_i if sql_type =~ /\((.*)\)/
939
+ end
940
+ end
941
+
942
+ TYPE_MAP = Type::TypeMap.new.tap { |m| initialize_type_map(m) }
943
+ EXTENDED_TYPE_MAPS = Concurrent::Map.new
944
+
945
+ private
946
+ def reconnect_can_restore_state?
947
+ transaction_manager.restorable? && !@raw_connection_dirty
948
+ end
949
+
950
+ # Lock the monitor, ensure we're properly connected and
951
+ # transactions are materialized, and then yield the underlying
952
+ # raw connection object.
953
+ #
954
+ # If +allow_retry+ is true, a connection-related exception will
955
+ # cause an automatic reconnect and re-run of the block, up to
956
+ # the connection's configured +connection_retries+ setting
957
+ # and the configured +retry_deadline+ limit. (Note that when
958
+ # +allow_retry+ is true, it's possible to return without having marked
959
+ # the connection as verified. If the block is guaranteed to exercise the
960
+ # connection, consider calling `verified!` to avoid needless
961
+ # verification queries in subsequent calls.)
962
+ #
963
+ # If +materialize_transactions+ is false, the block will be run without
964
+ # ensuring virtual transactions have been materialized in the DB
965
+ # server's state. The active transaction will also remain clean
966
+ # (if it is not already dirty), meaning it's able to be restored
967
+ # by reconnecting and opening an equivalent-depth set of new
968
+ # transactions. This should only be used by transaction control
969
+ # methods, and internal transaction-agnostic queries.
970
+ #
971
+ ###
972
+ #
973
+ # It's not the primary use case, so not something to optimize
974
+ # for, but note that this method does need to be re-entrant:
975
+ # +materialize_transactions+ will re-enter if it has work to do,
976
+ # and the yield block can also do so under some circumstances.
977
+ #
978
+ # In the latter case, we really ought to guarantee the inner
979
+ # call will not reconnect (which would interfere with the
980
+ # still-yielded connection in the outer block), but we currently
981
+ # provide no special enforcement there.
982
+ #
983
+ def with_raw_connection(allow_retry: false, materialize_transactions: true)
984
+ @lock.synchronize do
985
+ connect! if @raw_connection.nil? && reconnect_can_restore_state?
986
+
987
+ self.materialize_transactions if materialize_transactions
988
+
989
+ retries_available = allow_retry ? connection_retries : 0
990
+ deadline = retry_deadline && Process.clock_gettime(Process::CLOCK_MONOTONIC) + retry_deadline
991
+ reconnectable = reconnect_can_restore_state?
992
+
993
+ if @verified
994
+ # Cool, we're confident the connection's ready to use. (Note this might have
995
+ # become true during the above #materialize_transactions.)
996
+ elsif reconnectable
997
+ if allow_retry
998
+ # Not sure about the connection yet, but if anything goes wrong we can
999
+ # just reconnect and re-run our query
1000
+ else
1001
+ # We can reconnect if needed, but we don't trust the upcoming query to be
1002
+ # safely re-runnable: let's verify the connection to be sure
1003
+ verify!
1004
+ end
1005
+ else
1006
+ # We don't know whether the connection is okay, but it also doesn't matter:
1007
+ # we wouldn't be able to reconnect anyway. We're just going to run our query
1008
+ # and hope for the best.
1009
+ end
1010
+
1011
+ begin
1012
+ yield @raw_connection
1013
+ rescue => original_exception
1014
+ translated_exception = translate_exception_class(original_exception, nil, nil)
1015
+ invalidate_transaction(translated_exception)
1016
+ retry_deadline_exceeded = deadline && deadline < Process.clock_gettime(Process::CLOCK_MONOTONIC)
1017
+
1018
+ if !retry_deadline_exceeded && retries_available > 0
1019
+ retries_available -= 1
1020
+
1021
+ if retryable_query_error?(translated_exception)
1022
+ backoff(connection_retries - retries_available)
1023
+ retry
1024
+ elsif reconnectable && retryable_connection_error?(translated_exception)
1025
+ reconnect!(restore_transactions: true)
1026
+ # Only allowed to reconnect once, because reconnect! has its own retry
1027
+ # loop
1028
+ reconnectable = false
1029
+ retry
1030
+ end
1031
+ end
1032
+
1033
+ unless retryable_query_error?(translated_exception)
1034
+ # Barring a known-retryable error inside the query (regardless of
1035
+ # whether we were in a _position_ to retry it), we should infer that
1036
+ # there's likely a real problem with the connection.
1037
+ @verified = false
1038
+ end
1039
+
1040
+ raise translated_exception
1041
+ ensure
1042
+ dirty_current_transaction if materialize_transactions
1043
+ end
1044
+ end
1045
+ end
1046
+
1047
+ # Mark the connection as verified. Call this inside a
1048
+ # `with_raw_connection` block only when the block is guaranteed to
1049
+ # exercise the raw connection.
1050
+ def verified!
1051
+ @verified = true
1052
+ end
1053
+
1054
+ def retryable_connection_error?(exception)
1055
+ (exception.is_a?(ConnectionNotEstablished) && !exception.is_a?(ConnectionNotDefined)) ||
1056
+ exception.is_a?(ConnectionFailed)
1057
+ end
1058
+
1059
+ def invalidate_transaction(exception)
1060
+ return unless exception.is_a?(TransactionRollbackError)
1061
+ return unless savepoint_errors_invalidate_transactions?
1062
+
1063
+ current_transaction.invalidate!
1064
+ end
1065
+
1066
+ def retryable_query_error?(exception)
1067
+ # We definitely can't retry if we were inside an invalidated transaction.
1068
+ return false if current_transaction.invalidated?
1069
+
1070
+ exception.is_a?(Deadlocked) || exception.is_a?(LockWaitTimeout)
1071
+ end
1072
+
1073
+ def backoff(counter)
1074
+ sleep 0.1 * counter
1075
+ end
1076
+
1077
+ def reconnect
1078
+ raise NotImplementedError
1079
+ end
1080
+
1081
+ # Returns a raw connection for internal use with methods that are known
1082
+ # to both be thread-safe and not rely upon actual server communication.
1083
+ # This is useful for e.g. string escaping methods.
1084
+ def any_raw_connection
1085
+ @raw_connection || valid_raw_connection
1086
+ end
1087
+
1088
+ # Similar to any_raw_connection, but ensures it is validated and
1089
+ # connected. Any method called on this result still needs to be
1090
+ # independently thread-safe, so it probably shouldn't talk to the
1091
+ # server... but some drivers fail if they know the connection has gone
1092
+ # away.
1093
+ def valid_raw_connection
1094
+ (@verified && @raw_connection) ||
1095
+ # `allow_retry: false`, to force verification: the block won't
1096
+ # raise, so a retry wouldn't help us get the valid connection we
1097
+ # need.
1098
+ with_raw_connection(allow_retry: false, materialize_transactions: false) { |conn| conn }
1099
+ end
1100
+
1101
+ def extended_type_map_key
1102
+ if @default_timezone
1103
+ { default_timezone: @default_timezone }
1104
+ end
1105
+ end
1106
+
1107
+ def type_map
1108
+ if key = extended_type_map_key
1109
+ self.class::EXTENDED_TYPE_MAPS.compute_if_absent(key) do
1110
+ self.class.extended_type_map(**key)
1111
+ end
1112
+ else
1113
+ self.class::TYPE_MAP
1114
+ end
1115
+ end
1116
+
1117
+ def translate_exception_class(native_error, sql, binds)
1118
+ return native_error if native_error.is_a?(ActiveRecordError)
1119
+
1120
+ message = "#{native_error.class.name}: #{native_error.message}"
1121
+
1122
+ active_record_error = translate_exception(
1123
+ native_error, message: message, sql: sql, binds: binds
1124
+ )
1125
+ active_record_error.set_backtrace(native_error.backtrace)
1126
+ active_record_error
1127
+ end
1128
+
1129
+ def log(sql, name = "SQL", binds = [], type_casted_binds = [], async: false, &block) # :doc:
1130
+ @instrumenter.instrument(
1131
+ "sql.active_record",
1132
+ sql: sql,
1133
+ name: name,
1134
+ binds: binds,
1135
+ type_casted_binds: type_casted_binds,
1136
+ async: async,
1137
+ connection: self,
1138
+ transaction: current_transaction.user_transaction.presence,
1139
+ row_count: 0,
1140
+ &block
1141
+ )
1142
+ rescue ActiveRecord::StatementInvalid => ex
1143
+ raise ex.set_query(sql, binds)
1144
+ end
1145
+
1146
+ def translate_exception(exception, message:, sql:, binds:)
1147
+ # override in derived class
1148
+ case exception
1149
+ when RuntimeError, ActiveRecord::ActiveRecordError
1150
+ exception
1151
+ else
1152
+ ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds, connection_pool: @pool)
1153
+ end
1154
+ end
1155
+
1156
+ def column_for(table_name, column_name)
1157
+ column_name = column_name.to_s
1158
+ columns(table_name).detect { |c| c.name == column_name } ||
1159
+ raise(ActiveRecordError, "No such column: #{table_name}.#{column_name}")
1160
+ end
1161
+
1162
+ def column_for_attribute(attribute)
1163
+ table_name = attribute.relation.name
1164
+ schema_cache.columns_hash(table_name)[attribute.name.to_s]
1165
+ end
1166
+
1167
+ def collector
1168
+ if prepared_statements
1169
+ Arel::Collectors::Composite.new(
1170
+ Arel::Collectors::SQLString.new,
1171
+ Arel::Collectors::Bind.new,
1172
+ )
1173
+ else
1174
+ Arel::Collectors::SubstituteBinds.new(
1175
+ self,
1176
+ Arel::Collectors::SQLString.new,
1177
+ )
1178
+ end
1179
+ end
1180
+
1181
+ def arel_visitor
1182
+ Arel::Visitors::ToSql.new(self)
1183
+ end
1184
+
1185
+ def build_statement_pool
1186
+ end
1187
+
1188
+ # Builds the result object.
1189
+ #
1190
+ # This is an internal hook to make possible connection adapters to build
1191
+ # custom result objects with connection-specific data.
1192
+ def build_result(columns:, rows:, column_types: nil)
1193
+ ActiveRecord::Result.new(columns, rows, column_types)
1194
+ end
1195
+
1196
+ # Perform any necessary initialization upon the newly-established
1197
+ # @raw_connection -- this is the place to modify the adapter's
1198
+ # connection settings, run queries to configure any application-global
1199
+ # "session" variables, etc.
1200
+ #
1201
+ # Implementations may assume this method will only be called while
1202
+ # holding @lock (or from #initialize).
1203
+ def configure_connection
1204
+ check_version
1205
+ end
1206
+
1207
+ def default_prepared_statements
1208
+ true
1209
+ end
1210
+
1211
+ def warning_ignored?(warning)
1212
+ ActiveRecord.db_warnings_ignore.any? do |warning_matcher|
1213
+ warning.message.match?(warning_matcher) || warning.code.to_s.match?(warning_matcher)
1214
+ end
1215
+ end
1216
+ end
1217
+ end
1218
+ end