activerecord 6.0.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (340) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1086 -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.rb +195 -0
  8. data/lib/active_record/aggregations.rb +285 -0
  9. data/lib/active_record/association_relation.rb +49 -0
  10. data/lib/active_record/associations.rb +1865 -0
  11. data/lib/active_record/associations/alias_tracker.rb +81 -0
  12. data/lib/active_record/associations/association.rb +340 -0
  13. data/lib/active_record/associations/association_scope.rb +166 -0
  14. data/lib/active_record/associations/belongs_to_association.rb +124 -0
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +36 -0
  16. data/lib/active_record/associations/builder/association.rb +136 -0
  17. data/lib/active_record/associations/builder/belongs_to.rb +130 -0
  18. data/lib/active_record/associations/builder/collection_association.rb +72 -0
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +114 -0
  20. data/lib/active_record/associations/builder/has_many.rb +19 -0
  21. data/lib/active_record/associations/builder/has_one.rb +64 -0
  22. data/lib/active_record/associations/builder/singular_association.rb +44 -0
  23. data/lib/active_record/associations/collection_association.rb +498 -0
  24. data/lib/active_record/associations/collection_proxy.rb +1128 -0
  25. data/lib/active_record/associations/foreign_association.rb +20 -0
  26. data/lib/active_record/associations/has_many_association.rb +136 -0
  27. data/lib/active_record/associations/has_many_through_association.rb +220 -0
  28. data/lib/active_record/associations/has_one_association.rb +118 -0
  29. data/lib/active_record/associations/has_one_through_association.rb +45 -0
  30. data/lib/active_record/associations/join_dependency.rb +262 -0
  31. data/lib/active_record/associations/join_dependency/join_association.rb +80 -0
  32. data/lib/active_record/associations/join_dependency/join_base.rb +23 -0
  33. data/lib/active_record/associations/join_dependency/join_part.rb +71 -0
  34. data/lib/active_record/associations/preloader.rb +201 -0
  35. data/lib/active_record/associations/preloader/association.rb +133 -0
  36. data/lib/active_record/associations/preloader/through_association.rb +116 -0
  37. data/lib/active_record/associations/singular_association.rb +59 -0
  38. data/lib/active_record/associations/through_association.rb +121 -0
  39. data/lib/active_record/attribute_assignment.rb +85 -0
  40. data/lib/active_record/attribute_decorators.rb +90 -0
  41. data/lib/active_record/attribute_methods.rb +420 -0
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +81 -0
  43. data/lib/active_record/attribute_methods/dirty.rb +221 -0
  44. data/lib/active_record/attribute_methods/primary_key.rb +136 -0
  45. data/lib/active_record/attribute_methods/query.rb +41 -0
  46. data/lib/active_record/attribute_methods/read.rb +47 -0
  47. data/lib/active_record/attribute_methods/serialization.rb +90 -0
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +91 -0
  49. data/lib/active_record/attribute_methods/write.rb +61 -0
  50. data/lib/active_record/attributes.rb +279 -0
  51. data/lib/active_record/autosave_association.rb +512 -0
  52. data/lib/active_record/base.rb +328 -0
  53. data/lib/active_record/callbacks.rb +339 -0
  54. data/lib/active_record/coders/json.rb +15 -0
  55. data/lib/active_record/coders/yaml_column.rb +50 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +1175 -0
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +85 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +516 -0
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +155 -0
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +251 -0
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +713 -0
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +93 -0
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1475 -0
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +323 -0
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +772 -0
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +830 -0
  69. data/lib/active_record/connection_adapters/column.rb +95 -0
  70. data/lib/active_record/connection_adapters/connection_specification.rb +297 -0
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +202 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +146 -0
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -0
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +184 -0
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +92 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +53 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +23 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +41 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +113 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +26 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +205 -0
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +222 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +776 -0
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +953 -0
  117. data/lib/active_record/connection_adapters/schema_cache.rb +141 -0
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
  119. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +120 -0
  120. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  121. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  126. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +561 -0
  127. data/lib/active_record/connection_adapters/statement_pool.rb +61 -0
  128. data/lib/active_record/connection_handling.rb +274 -0
  129. data/lib/active_record/core.rb +603 -0
  130. data/lib/active_record/counter_cache.rb +193 -0
  131. data/lib/active_record/database_configurations.rb +233 -0
  132. data/lib/active_record/database_configurations/database_config.rb +37 -0
  133. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  134. data/lib/active_record/database_configurations/url_config.rb +79 -0
  135. data/lib/active_record/define_callbacks.rb +22 -0
  136. data/lib/active_record/dynamic_matchers.rb +122 -0
  137. data/lib/active_record/enum.rb +274 -0
  138. data/lib/active_record/errors.rb +388 -0
  139. data/lib/active_record/explain.rb +50 -0
  140. data/lib/active_record/explain_registry.rb +32 -0
  141. data/lib/active_record/explain_subscriber.rb +34 -0
  142. data/lib/active_record/fixture_set/file.rb +82 -0
  143. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  144. data/lib/active_record/fixture_set/render_context.rb +17 -0
  145. data/lib/active_record/fixture_set/table_row.rb +153 -0
  146. data/lib/active_record/fixture_set/table_rows.rb +47 -0
  147. data/lib/active_record/fixtures.rb +738 -0
  148. data/lib/active_record/gem_version.rb +17 -0
  149. data/lib/active_record/inheritance.rb +293 -0
  150. data/lib/active_record/insert_all.rb +179 -0
  151. data/lib/active_record/integration.rb +207 -0
  152. data/lib/active_record/internal_metadata.rb +53 -0
  153. data/lib/active_record/legacy_yaml_adapter.rb +48 -0
  154. data/lib/active_record/locale/en.yml +48 -0
  155. data/lib/active_record/locking/optimistic.rb +197 -0
  156. data/lib/active_record/locking/pessimistic.rb +89 -0
  157. data/lib/active_record/log_subscriber.rb +118 -0
  158. data/lib/active_record/middleware/database_selector.rb +75 -0
  159. data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
  160. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  161. data/lib/active_record/migration.rb +1397 -0
  162. data/lib/active_record/migration/command_recorder.rb +284 -0
  163. data/lib/active_record/migration/compatibility.rb +244 -0
  164. data/lib/active_record/migration/join_table.rb +17 -0
  165. data/lib/active_record/model_schema.rb +545 -0
  166. data/lib/active_record/nested_attributes.rb +600 -0
  167. data/lib/active_record/no_touching.rb +65 -0
  168. data/lib/active_record/null_relation.rb +68 -0
  169. data/lib/active_record/persistence.rb +967 -0
  170. data/lib/active_record/query_cache.rb +52 -0
  171. data/lib/active_record/querying.rb +82 -0
  172. data/lib/active_record/railtie.rb +263 -0
  173. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  174. data/lib/active_record/railties/console_sandbox.rb +7 -0
  175. data/lib/active_record/railties/controller_runtime.rb +51 -0
  176. data/lib/active_record/railties/databases.rake +527 -0
  177. data/lib/active_record/readonly_attributes.rb +24 -0
  178. data/lib/active_record/reflection.rb +1042 -0
  179. data/lib/active_record/relation.rb +860 -0
  180. data/lib/active_record/relation/batches.rb +290 -0
  181. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  182. data/lib/active_record/relation/calculations.rb +424 -0
  183. data/lib/active_record/relation/delegation.rb +130 -0
  184. data/lib/active_record/relation/finder_methods.rb +561 -0
  185. data/lib/active_record/relation/from_clause.rb +26 -0
  186. data/lib/active_record/relation/merger.rb +184 -0
  187. data/lib/active_record/relation/predicate_builder.rb +150 -0
  188. data/lib/active_record/relation/predicate_builder/array_handler.rb +49 -0
  189. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  190. data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
  191. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  192. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  193. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  194. data/lib/active_record/relation/predicate_builder/relation_handler.rb +19 -0
  195. data/lib/active_record/relation/query_attribute.rb +50 -0
  196. data/lib/active_record/relation/query_methods.rb +1371 -0
  197. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  198. data/lib/active_record/relation/spawn_methods.rb +77 -0
  199. data/lib/active_record/relation/where_clause.rb +190 -0
  200. data/lib/active_record/relation/where_clause_factory.rb +33 -0
  201. data/lib/active_record/result.rb +168 -0
  202. data/lib/active_record/runtime_registry.rb +24 -0
  203. data/lib/active_record/sanitization.rb +214 -0
  204. data/lib/active_record/schema.rb +61 -0
  205. data/lib/active_record/schema_dumper.rb +270 -0
  206. data/lib/active_record/schema_migration.rb +60 -0
  207. data/lib/active_record/scoping.rb +106 -0
  208. data/lib/active_record/scoping/default.rb +151 -0
  209. data/lib/active_record/scoping/named.rb +217 -0
  210. data/lib/active_record/secure_token.rb +40 -0
  211. data/lib/active_record/serialization.rb +22 -0
  212. data/lib/active_record/statement_cache.rb +148 -0
  213. data/lib/active_record/store.rb +290 -0
  214. data/lib/active_record/suppressor.rb +61 -0
  215. data/lib/active_record/table_metadata.rb +75 -0
  216. data/lib/active_record/tasks/database_tasks.rb +506 -0
  217. data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
  218. data/lib/active_record/tasks/postgresql_database_tasks.rb +141 -0
  219. data/lib/active_record/tasks/sqlite_database_tasks.rb +77 -0
  220. data/lib/active_record/test_databases.rb +23 -0
  221. data/lib/active_record/test_fixtures.rb +224 -0
  222. data/lib/active_record/timestamp.rb +167 -0
  223. data/lib/active_record/touch_later.rb +66 -0
  224. data/lib/active_record/transactions.rb +493 -0
  225. data/lib/active_record/translation.rb +24 -0
  226. data/lib/active_record/type.rb +78 -0
  227. data/lib/active_record/type/adapter_specific_registry.rb +129 -0
  228. data/lib/active_record/type/date.rb +9 -0
  229. data/lib/active_record/type/date_time.rb +9 -0
  230. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  231. data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
  232. data/lib/active_record/type/internal/timezone.rb +17 -0
  233. data/lib/active_record/type/json.rb +30 -0
  234. data/lib/active_record/type/serialized.rb +71 -0
  235. data/lib/active_record/type/text.rb +11 -0
  236. data/lib/active_record/type/time.rb +21 -0
  237. data/lib/active_record/type/type_map.rb +62 -0
  238. data/lib/active_record/type/unsigned_integer.rb +17 -0
  239. data/lib/active_record/type_caster.rb +9 -0
  240. data/lib/active_record/type_caster/connection.rb +34 -0
  241. data/lib/active_record/type_caster/map.rb +20 -0
  242. data/lib/active_record/validations.rb +94 -0
  243. data/lib/active_record/validations/absence.rb +25 -0
  244. data/lib/active_record/validations/associated.rb +60 -0
  245. data/lib/active_record/validations/length.rb +26 -0
  246. data/lib/active_record/validations/presence.rb +68 -0
  247. data/lib/active_record/validations/uniqueness.rb +226 -0
  248. data/lib/active_record/version.rb +10 -0
  249. data/lib/arel.rb +58 -0
  250. data/lib/arel/alias_predication.rb +9 -0
  251. data/lib/arel/attributes.rb +22 -0
  252. data/lib/arel/attributes/attribute.rb +37 -0
  253. data/lib/arel/collectors/bind.rb +24 -0
  254. data/lib/arel/collectors/composite.rb +31 -0
  255. data/lib/arel/collectors/plain_string.rb +20 -0
  256. data/lib/arel/collectors/sql_string.rb +20 -0
  257. data/lib/arel/collectors/substitute_binds.rb +28 -0
  258. data/lib/arel/crud.rb +42 -0
  259. data/lib/arel/delete_manager.rb +18 -0
  260. data/lib/arel/errors.rb +9 -0
  261. data/lib/arel/expressions.rb +29 -0
  262. data/lib/arel/factory_methods.rb +49 -0
  263. data/lib/arel/insert_manager.rb +49 -0
  264. data/lib/arel/math.rb +45 -0
  265. data/lib/arel/nodes.rb +68 -0
  266. data/lib/arel/nodes/and.rb +32 -0
  267. data/lib/arel/nodes/ascending.rb +23 -0
  268. data/lib/arel/nodes/binary.rb +52 -0
  269. data/lib/arel/nodes/bind_param.rb +36 -0
  270. data/lib/arel/nodes/case.rb +55 -0
  271. data/lib/arel/nodes/casted.rb +50 -0
  272. data/lib/arel/nodes/comment.rb +29 -0
  273. data/lib/arel/nodes/count.rb +12 -0
  274. data/lib/arel/nodes/delete_statement.rb +45 -0
  275. data/lib/arel/nodes/descending.rb +23 -0
  276. data/lib/arel/nodes/equality.rb +18 -0
  277. data/lib/arel/nodes/extract.rb +24 -0
  278. data/lib/arel/nodes/false.rb +16 -0
  279. data/lib/arel/nodes/full_outer_join.rb +8 -0
  280. data/lib/arel/nodes/function.rb +44 -0
  281. data/lib/arel/nodes/grouping.rb +8 -0
  282. data/lib/arel/nodes/in.rb +8 -0
  283. data/lib/arel/nodes/infix_operation.rb +80 -0
  284. data/lib/arel/nodes/inner_join.rb +8 -0
  285. data/lib/arel/nodes/insert_statement.rb +37 -0
  286. data/lib/arel/nodes/join_source.rb +20 -0
  287. data/lib/arel/nodes/matches.rb +18 -0
  288. data/lib/arel/nodes/named_function.rb +23 -0
  289. data/lib/arel/nodes/node.rb +50 -0
  290. data/lib/arel/nodes/node_expression.rb +13 -0
  291. data/lib/arel/nodes/outer_join.rb +8 -0
  292. data/lib/arel/nodes/over.rb +15 -0
  293. data/lib/arel/nodes/regexp.rb +16 -0
  294. data/lib/arel/nodes/right_outer_join.rb +8 -0
  295. data/lib/arel/nodes/select_core.rb +67 -0
  296. data/lib/arel/nodes/select_statement.rb +41 -0
  297. data/lib/arel/nodes/sql_literal.rb +16 -0
  298. data/lib/arel/nodes/string_join.rb +11 -0
  299. data/lib/arel/nodes/table_alias.rb +27 -0
  300. data/lib/arel/nodes/terminal.rb +16 -0
  301. data/lib/arel/nodes/true.rb +16 -0
  302. data/lib/arel/nodes/unary.rb +45 -0
  303. data/lib/arel/nodes/unary_operation.rb +20 -0
  304. data/lib/arel/nodes/unqualified_column.rb +22 -0
  305. data/lib/arel/nodes/update_statement.rb +41 -0
  306. data/lib/arel/nodes/values_list.rb +9 -0
  307. data/lib/arel/nodes/window.rb +126 -0
  308. data/lib/arel/nodes/with.rb +11 -0
  309. data/lib/arel/order_predications.rb +13 -0
  310. data/lib/arel/predications.rb +257 -0
  311. data/lib/arel/select_manager.rb +271 -0
  312. data/lib/arel/table.rb +110 -0
  313. data/lib/arel/tree_manager.rb +72 -0
  314. data/lib/arel/update_manager.rb +34 -0
  315. data/lib/arel/visitors.rb +20 -0
  316. data/lib/arel/visitors/depth_first.rb +204 -0
  317. data/lib/arel/visitors/dot.rb +297 -0
  318. data/lib/arel/visitors/ibm_db.rb +34 -0
  319. data/lib/arel/visitors/informix.rb +62 -0
  320. data/lib/arel/visitors/mssql.rb +157 -0
  321. data/lib/arel/visitors/mysql.rb +83 -0
  322. data/lib/arel/visitors/oracle.rb +159 -0
  323. data/lib/arel/visitors/oracle12.rb +66 -0
  324. data/lib/arel/visitors/postgresql.rb +110 -0
  325. data/lib/arel/visitors/sqlite.rb +39 -0
  326. data/lib/arel/visitors/to_sql.rb +889 -0
  327. data/lib/arel/visitors/visitor.rb +46 -0
  328. data/lib/arel/visitors/where_sql.rb +23 -0
  329. data/lib/arel/window_predications.rb +9 -0
  330. data/lib/rails/generators/active_record.rb +19 -0
  331. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  332. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  333. data/lib/rails/generators/active_record/migration.rb +48 -0
  334. data/lib/rails/generators/active_record/migration/migration_generator.rb +75 -0
  335. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  336. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +48 -0
  337. data/lib/rails/generators/active_record/model/model_generator.rb +49 -0
  338. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  339. data/lib/rails/generators/active_record/model/templates/module.rb.tt +7 -0
  340. metadata +418 -0
@@ -0,0 +1,323 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ class TransactionState
6
+ def initialize(state = nil)
7
+ @state = state
8
+ @children = []
9
+ end
10
+
11
+ def add_child(state)
12
+ @children << state
13
+ end
14
+
15
+ def finalized?
16
+ @state
17
+ end
18
+
19
+ def committed?
20
+ @state == :committed || @state == :fully_committed
21
+ end
22
+
23
+ def fully_committed?
24
+ @state == :fully_committed
25
+ end
26
+
27
+ def rolledback?
28
+ @state == :rolledback || @state == :fully_rolledback
29
+ end
30
+
31
+ def fully_rolledback?
32
+ @state == :fully_rolledback
33
+ end
34
+
35
+ def fully_completed?
36
+ completed?
37
+ end
38
+
39
+ def completed?
40
+ committed? || rolledback?
41
+ end
42
+
43
+ def rollback!
44
+ @children.each { |c| c.rollback! }
45
+ @state = :rolledback
46
+ end
47
+
48
+ def full_rollback!
49
+ @children.each { |c| c.rollback! }
50
+ @state = :fully_rolledback
51
+ end
52
+
53
+ def commit!
54
+ @state = :committed
55
+ end
56
+
57
+ def full_commit!
58
+ @state = :fully_committed
59
+ end
60
+
61
+ def nullify!
62
+ @state = nil
63
+ end
64
+ end
65
+
66
+ class NullTransaction #:nodoc:
67
+ def initialize; end
68
+ def state; end
69
+ def closed?; true; end
70
+ def open?; false; end
71
+ def joinable?; false; end
72
+ def add_record(record); end
73
+ end
74
+
75
+ class Transaction #:nodoc:
76
+ attr_reader :connection, :state, :records, :savepoint_name, :isolation_level
77
+
78
+ def initialize(connection, options, run_commit_callbacks: false)
79
+ @connection = connection
80
+ @state = TransactionState.new
81
+ @records = []
82
+ @isolation_level = options[:isolation]
83
+ @materialized = false
84
+ @joinable = options.fetch(:joinable, true)
85
+ @run_commit_callbacks = run_commit_callbacks
86
+ end
87
+
88
+ def add_record(record)
89
+ records << record
90
+ end
91
+
92
+ def materialize!
93
+ @materialized = true
94
+ end
95
+
96
+ def materialized?
97
+ @materialized
98
+ end
99
+
100
+ def rollback_records
101
+ ite = records.uniq(&:object_id)
102
+ already_run_callbacks = {}
103
+ while record = ite.shift
104
+ trigger_callbacks = record.trigger_transactional_callbacks?
105
+ should_run_callbacks = !already_run_callbacks[record] && trigger_callbacks
106
+ already_run_callbacks[record] ||= trigger_callbacks
107
+ record.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: should_run_callbacks)
108
+ end
109
+ ensure
110
+ ite.each do |i|
111
+ i.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: false)
112
+ end
113
+ end
114
+
115
+ def before_commit_records
116
+ records.uniq.each(&:before_committed!) if @run_commit_callbacks
117
+ end
118
+
119
+ def commit_records
120
+ ite = records.uniq(&:object_id)
121
+ already_run_callbacks = {}
122
+ while record = ite.shift
123
+ if @run_commit_callbacks
124
+ trigger_callbacks = record.trigger_transactional_callbacks?
125
+ should_run_callbacks = !already_run_callbacks[record] && trigger_callbacks
126
+ already_run_callbacks[record] ||= trigger_callbacks
127
+ record.committed!(should_run_callbacks: should_run_callbacks)
128
+ else
129
+ # if not running callbacks, only adds the record to the parent transaction
130
+ connection.add_transaction_record(record)
131
+ end
132
+ end
133
+ ensure
134
+ ite.each { |i| i.committed!(should_run_callbacks: false) }
135
+ end
136
+
137
+ def full_rollback?; true; end
138
+ def joinable?; @joinable; end
139
+ def closed?; false; end
140
+ def open?; !closed?; end
141
+ end
142
+
143
+ class SavepointTransaction < Transaction
144
+ def initialize(connection, savepoint_name, parent_transaction, *args)
145
+ super(connection, *args)
146
+
147
+ parent_transaction.state.add_child(@state)
148
+
149
+ if isolation_level
150
+ raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
151
+ end
152
+
153
+ @savepoint_name = savepoint_name
154
+ end
155
+
156
+ def materialize!
157
+ connection.create_savepoint(savepoint_name)
158
+ super
159
+ end
160
+
161
+ def rollback
162
+ connection.rollback_to_savepoint(savepoint_name) if materialized?
163
+ @state.rollback!
164
+ end
165
+
166
+ def commit
167
+ connection.release_savepoint(savepoint_name) if materialized?
168
+ @state.commit!
169
+ end
170
+
171
+ def full_rollback?; false; end
172
+ end
173
+
174
+ class RealTransaction < Transaction
175
+ def materialize!
176
+ if isolation_level
177
+ connection.begin_isolated_db_transaction(isolation_level)
178
+ else
179
+ connection.begin_db_transaction
180
+ end
181
+
182
+ super
183
+ end
184
+
185
+ def rollback
186
+ connection.rollback_db_transaction if materialized?
187
+ @state.full_rollback!
188
+ end
189
+
190
+ def commit
191
+ connection.commit_db_transaction if materialized?
192
+ @state.full_commit!
193
+ end
194
+ end
195
+
196
+ class TransactionManager #:nodoc:
197
+ def initialize(connection)
198
+ @stack = []
199
+ @connection = connection
200
+ @has_unmaterialized_transactions = false
201
+ @materializing_transactions = false
202
+ @lazy_transactions_enabled = true
203
+ end
204
+
205
+ def begin_transaction(options = {})
206
+ @connection.lock.synchronize do
207
+ run_commit_callbacks = !current_transaction.joinable?
208
+ transaction =
209
+ if @stack.empty?
210
+ RealTransaction.new(@connection, options, run_commit_callbacks: run_commit_callbacks)
211
+ else
212
+ SavepointTransaction.new(@connection, "active_record_#{@stack.size}", @stack.last, options,
213
+ run_commit_callbacks: run_commit_callbacks)
214
+ end
215
+
216
+ if @connection.supports_lazy_transactions? && lazy_transactions_enabled? && options[:_lazy] != false
217
+ @has_unmaterialized_transactions = true
218
+ else
219
+ transaction.materialize!
220
+ end
221
+ @stack.push(transaction)
222
+ transaction
223
+ end
224
+ end
225
+
226
+ def disable_lazy_transactions!
227
+ materialize_transactions
228
+ @lazy_transactions_enabled = false
229
+ end
230
+
231
+ def enable_lazy_transactions!
232
+ @lazy_transactions_enabled = true
233
+ end
234
+
235
+ def lazy_transactions_enabled?
236
+ @lazy_transactions_enabled
237
+ end
238
+
239
+ def materialize_transactions
240
+ return if @materializing_transactions
241
+ return unless @has_unmaterialized_transactions
242
+
243
+ @connection.lock.synchronize do
244
+ begin
245
+ @materializing_transactions = true
246
+ @stack.each { |t| t.materialize! unless t.materialized? }
247
+ ensure
248
+ @materializing_transactions = false
249
+ end
250
+ @has_unmaterialized_transactions = false
251
+ end
252
+ end
253
+
254
+ def commit_transaction
255
+ @connection.lock.synchronize do
256
+ transaction = @stack.last
257
+
258
+ begin
259
+ transaction.before_commit_records
260
+ ensure
261
+ @stack.pop
262
+ end
263
+
264
+ transaction.commit
265
+ transaction.commit_records
266
+ end
267
+ end
268
+
269
+ def rollback_transaction(transaction = nil)
270
+ @connection.lock.synchronize do
271
+ transaction ||= @stack.pop
272
+ transaction.rollback
273
+ transaction.rollback_records
274
+ end
275
+ end
276
+
277
+ def within_new_transaction(options = {})
278
+ @connection.lock.synchronize do
279
+ transaction = begin_transaction options
280
+ yield
281
+ rescue Exception => error
282
+ if transaction
283
+ rollback_transaction
284
+ after_failure_actions(transaction, error)
285
+ end
286
+ raise
287
+ ensure
288
+ if !error && transaction
289
+ if Thread.current.status == "aborting"
290
+ rollback_transaction
291
+ else
292
+ begin
293
+ commit_transaction
294
+ rescue Exception
295
+ rollback_transaction(transaction) unless transaction.state.completed?
296
+ raise
297
+ end
298
+ end
299
+ end
300
+ end
301
+ end
302
+
303
+ def open_transactions
304
+ @stack.size
305
+ end
306
+
307
+ def current_transaction
308
+ @stack.last || NULL_TRANSACTION
309
+ end
310
+
311
+ private
312
+
313
+ NULL_TRANSACTION = NullTransaction.new
314
+
315
+ # Deallocate invalidated prepared statements outside of the transaction
316
+ def after_failure_actions(transaction, error)
317
+ return unless transaction.is_a?(RealTransaction)
318
+ return unless error.is_a?(ActiveRecord::PreparedStatementCacheExpired)
319
+ @connection.clear_cache!
320
+ end
321
+ end
322
+ end
323
+ end
@@ -0,0 +1,772 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+ require "active_record/connection_adapters/determine_if_preparable_visitor"
5
+ require "active_record/connection_adapters/schema_cache"
6
+ require "active_record/connection_adapters/sql_type_metadata"
7
+ require "active_record/connection_adapters/abstract/schema_dumper"
8
+ require "active_record/connection_adapters/abstract/schema_creation"
9
+ require "active_support/concurrency/load_interlock_aware_monitor"
10
+ require "active_support/deprecation"
11
+ require "arel/collectors/bind"
12
+ require "arel/collectors/composite"
13
+ require "arel/collectors/sql_string"
14
+ require "arel/collectors/substitute_binds"
15
+
16
+ module ActiveRecord
17
+ module ConnectionAdapters # :nodoc:
18
+ extend ActiveSupport::Autoload
19
+
20
+ autoload :Column
21
+ autoload :ConnectionSpecification
22
+
23
+ autoload_at "active_record/connection_adapters/abstract/schema_definitions" do
24
+ autoload :IndexDefinition
25
+ autoload :ColumnDefinition
26
+ autoload :ChangeColumnDefinition
27
+ autoload :ForeignKeyDefinition
28
+ autoload :TableDefinition
29
+ autoload :Table
30
+ autoload :AlterTable
31
+ autoload :ReferenceDefinition
32
+ end
33
+
34
+ autoload_at "active_record/connection_adapters/abstract/connection_pool" do
35
+ autoload :ConnectionHandler
36
+ end
37
+
38
+ autoload_under "abstract" do
39
+ autoload :SchemaStatements
40
+ autoload :DatabaseStatements
41
+ autoload :DatabaseLimits
42
+ autoload :Quoting
43
+ autoload :ConnectionPool
44
+ autoload :QueryCache
45
+ autoload :Savepoints
46
+ end
47
+
48
+ autoload_at "active_record/connection_adapters/abstract/transaction" do
49
+ autoload :TransactionManager
50
+ autoload :NullTransaction
51
+ autoload :RealTransaction
52
+ autoload :SavepointTransaction
53
+ autoload :TransactionState
54
+ end
55
+
56
+ # Active Record supports multiple database systems. AbstractAdapter and
57
+ # related classes form the abstraction layer which makes this possible.
58
+ # An AbstractAdapter represents a connection to a database, and provides an
59
+ # abstract interface for database-specific functionality such as establishing
60
+ # a connection, escaping values, building the right SQL fragments for +:offset+
61
+ # and +:limit+ options, etc.
62
+ #
63
+ # All the concrete database adapters follow the interface laid down in this class.
64
+ # {ActiveRecord::Base.connection}[rdoc-ref:ConnectionHandling#connection] returns an AbstractAdapter object, which
65
+ # you can use.
66
+ #
67
+ # Most of the methods in the adapter are useful during migrations. Most
68
+ # notably, the instance methods provided by SchemaStatements are very useful.
69
+ class AbstractAdapter
70
+ ADAPTER_NAME = "Abstract"
71
+ include ActiveSupport::Callbacks
72
+ define_callbacks :checkout, :checkin
73
+
74
+ include Quoting, DatabaseStatements, SchemaStatements
75
+ include DatabaseLimits
76
+ include QueryCache
77
+ include Savepoints
78
+
79
+ SIMPLE_INT = /\A\d+\z/
80
+
81
+ attr_accessor :pool
82
+ attr_reader :visitor, :owner, :logger, :lock
83
+ alias :in_use? :owner
84
+
85
+ set_callback :checkin, :after, :enable_lazy_transactions!
86
+
87
+ def self.type_cast_config_to_integer(config)
88
+ if config.is_a?(Integer)
89
+ config
90
+ elsif SIMPLE_INT.match?(config)
91
+ config.to_i
92
+ else
93
+ config
94
+ end
95
+ end
96
+
97
+ def self.type_cast_config_to_boolean(config)
98
+ if config == "false"
99
+ false
100
+ else
101
+ config
102
+ end
103
+ end
104
+
105
+ def self.build_read_query_regexp(*parts) # :nodoc:
106
+ parts = parts.map { |part| /\A[\(\s]*#{part}/i }
107
+ Regexp.union(*parts)
108
+ end
109
+
110
+ def self.quoted_column_names # :nodoc:
111
+ @quoted_column_names ||= {}
112
+ end
113
+
114
+ def self.quoted_table_names # :nodoc:
115
+ @quoted_table_names ||= {}
116
+ end
117
+
118
+ def initialize(connection, logger = nil, config = {}) # :nodoc:
119
+ super()
120
+
121
+ @connection = connection
122
+ @owner = nil
123
+ @instrumenter = ActiveSupport::Notifications.instrumenter
124
+ @logger = logger
125
+ @config = config
126
+ @pool = ActiveRecord::ConnectionAdapters::NullPool.new
127
+ @idle_since = Concurrent.monotonic_time
128
+ @visitor = arel_visitor
129
+ @statements = build_statement_pool
130
+ @lock = ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
131
+
132
+ if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
133
+ @prepared_statements = true
134
+ @visitor.extend(DetermineIfPreparableVisitor)
135
+ else
136
+ @prepared_statements = false
137
+ end
138
+
139
+ @advisory_locks_enabled = self.class.type_cast_config_to_boolean(
140
+ config.fetch(:advisory_locks, true)
141
+ )
142
+ end
143
+
144
+ def replica?
145
+ @config[:replica] || false
146
+ end
147
+
148
+ # Determines whether writes are currently being prevents.
149
+ #
150
+ # Returns true if the connection is a replica, or if +prevent_writes+
151
+ # is set to true.
152
+ def preventing_writes?
153
+ replica? || ActiveRecord::Base.connection_handler.prevent_writes
154
+ end
155
+
156
+ def migrations_paths # :nodoc:
157
+ @config[:migrations_paths] || Migrator.migrations_paths
158
+ end
159
+
160
+ def migration_context # :nodoc:
161
+ MigrationContext.new(migrations_paths, schema_migration)
162
+ end
163
+
164
+ def schema_migration # :nodoc:
165
+ @schema_migration ||= begin
166
+ conn = self
167
+ spec_name = conn.pool.spec.name
168
+ name = "#{spec_name}::SchemaMigration"
169
+
170
+ Class.new(ActiveRecord::SchemaMigration) do
171
+ define_singleton_method(:name) { name }
172
+ define_singleton_method(:to_s) { name }
173
+
174
+ self.connection_specification_name = spec_name
175
+ end
176
+ end
177
+ end
178
+
179
+ def prepared_statements
180
+ @prepared_statements && !prepared_statements_disabled_cache.include?(object_id)
181
+ end
182
+
183
+ def prepared_statements_disabled_cache # :nodoc:
184
+ Thread.current[:ar_prepared_statements_disabled_cache] ||= Set.new
185
+ end
186
+
187
+ class Version
188
+ include Comparable
189
+
190
+ attr_reader :full_version_string
191
+
192
+ def initialize(version_string, full_version_string = nil)
193
+ @version = version_string.split(".").map(&:to_i)
194
+ @full_version_string = full_version_string
195
+ end
196
+
197
+ def <=>(version_string)
198
+ @version <=> version_string.split(".").map(&:to_i)
199
+ end
200
+
201
+ def to_s
202
+ @version.join(".")
203
+ end
204
+ end
205
+
206
+ def valid_type?(type) # :nodoc:
207
+ !native_database_types[type].nil?
208
+ end
209
+
210
+ # this method must only be called while holding connection pool's mutex
211
+ def lease
212
+ if in_use?
213
+ msg = +"Cannot lease connection, "
214
+ if @owner == Thread.current
215
+ msg << "it is already leased by the current thread."
216
+ else
217
+ msg << "it is already in use by a different thread: #{@owner}. " \
218
+ "Current thread: #{Thread.current}."
219
+ end
220
+ raise ActiveRecordError, msg
221
+ end
222
+
223
+ @owner = Thread.current
224
+ end
225
+
226
+ def schema_cache
227
+ @pool.get_schema_cache(self)
228
+ end
229
+
230
+ def schema_cache=(cache)
231
+ cache.connection = self
232
+ @pool.set_schema_cache(cache)
233
+ end
234
+
235
+ # this method must only be called while holding connection pool's mutex
236
+ def expire
237
+ if in_use?
238
+ if @owner != Thread.current
239
+ raise ActiveRecordError, "Cannot expire connection, " \
240
+ "it is owned by a different thread: #{@owner}. " \
241
+ "Current thread: #{Thread.current}."
242
+ end
243
+
244
+ @idle_since = Concurrent.monotonic_time
245
+ @owner = nil
246
+ else
247
+ raise ActiveRecordError, "Cannot expire connection, it is not currently leased."
248
+ end
249
+ end
250
+
251
+ # this method must only be called while holding connection pool's mutex (and a desire for segfaults)
252
+ def steal! # :nodoc:
253
+ if in_use?
254
+ if @owner != Thread.current
255
+ pool.send :remove_connection_from_thread_cache, self, @owner
256
+
257
+ @owner = Thread.current
258
+ end
259
+ else
260
+ raise ActiveRecordError, "Cannot steal connection, it is not currently leased."
261
+ end
262
+ end
263
+
264
+ # Seconds since this connection was returned to the pool
265
+ def seconds_idle # :nodoc:
266
+ return 0 if in_use?
267
+ Concurrent.monotonic_time - @idle_since
268
+ end
269
+
270
+ def unprepared_statement
271
+ cache = prepared_statements_disabled_cache.add(object_id) if @prepared_statements
272
+ yield
273
+ ensure
274
+ cache&.delete(object_id)
275
+ end
276
+
277
+ # Returns the human-readable name of the adapter. Use mixed case - one
278
+ # can always use downcase if needed.
279
+ def adapter_name
280
+ self.class::ADAPTER_NAME
281
+ end
282
+
283
+ # Does the database for this adapter exist?
284
+ def self.database_exists?(config)
285
+ raise NotImplementedError
286
+ end
287
+
288
+ # Does this adapter support DDL rollbacks in transactions? That is, would
289
+ # CREATE TABLE or ALTER TABLE get rolled back by a transaction?
290
+ def supports_ddl_transactions?
291
+ false
292
+ end
293
+
294
+ def supports_bulk_alter?
295
+ false
296
+ end
297
+
298
+ # Does this adapter support savepoints?
299
+ def supports_savepoints?
300
+ false
301
+ end
302
+
303
+ # Does this adapter support application-enforced advisory locking?
304
+ def supports_advisory_locks?
305
+ false
306
+ end
307
+
308
+ # Should primary key values be selected from their corresponding
309
+ # sequence before the insert statement? If true, next_sequence_value
310
+ # is called before each insert to set the record's primary key.
311
+ def prefetch_primary_key?(table_name = nil)
312
+ false
313
+ end
314
+
315
+ # Does this adapter support index sort order?
316
+ def supports_index_sort_order?
317
+ false
318
+ end
319
+
320
+ # Does this adapter support partial indices?
321
+ def supports_partial_index?
322
+ false
323
+ end
324
+
325
+ # Does this adapter support expression indices?
326
+ def supports_expression_index?
327
+ false
328
+ end
329
+
330
+ # Does this adapter support explain?
331
+ def supports_explain?
332
+ false
333
+ end
334
+
335
+ # Does this adapter support setting the isolation level for a transaction?
336
+ def supports_transaction_isolation?
337
+ false
338
+ end
339
+
340
+ # Does this adapter support database extensions?
341
+ def supports_extensions?
342
+ false
343
+ end
344
+
345
+ # Does this adapter support creating indexes in the same statement as
346
+ # creating the table?
347
+ def supports_indexes_in_create?
348
+ false
349
+ end
350
+
351
+ # Does this adapter support creating foreign key constraints?
352
+ def supports_foreign_keys?
353
+ false
354
+ end
355
+
356
+ # Does this adapter support creating invalid constraints?
357
+ def supports_validate_constraints?
358
+ false
359
+ end
360
+
361
+ # Does this adapter support creating foreign key constraints
362
+ # in the same statement as creating the table?
363
+ def supports_foreign_keys_in_create?
364
+ supports_foreign_keys?
365
+ end
366
+ deprecate :supports_foreign_keys_in_create?
367
+
368
+ # Does this adapter support views?
369
+ def supports_views?
370
+ false
371
+ end
372
+
373
+ # Does this adapter support materialized views?
374
+ def supports_materialized_views?
375
+ false
376
+ end
377
+
378
+ # Does this adapter support datetime with precision?
379
+ def supports_datetime_with_precision?
380
+ false
381
+ end
382
+
383
+ # Does this adapter support json data type?
384
+ def supports_json?
385
+ false
386
+ end
387
+
388
+ # Does this adapter support metadata comments on database objects (tables, columns, indexes)?
389
+ def supports_comments?
390
+ false
391
+ end
392
+
393
+ # Can comments for tables, columns, and indexes be specified in create/alter table statements?
394
+ def supports_comments_in_create?
395
+ false
396
+ end
397
+
398
+ # Does this adapter support multi-value insert?
399
+ def supports_multi_insert?
400
+ true
401
+ end
402
+ deprecate :supports_multi_insert?
403
+
404
+ # Does this adapter support virtual columns?
405
+ def supports_virtual_columns?
406
+ false
407
+ end
408
+
409
+ # Does this adapter support foreign/external tables?
410
+ def supports_foreign_tables?
411
+ false
412
+ end
413
+
414
+ # Does this adapter support optimizer hints?
415
+ def supports_optimizer_hints?
416
+ false
417
+ end
418
+
419
+ def supports_common_table_expressions?
420
+ false
421
+ end
422
+
423
+ def supports_lazy_transactions?
424
+ false
425
+ end
426
+
427
+ def supports_insert_returning?
428
+ false
429
+ end
430
+
431
+ def supports_insert_on_duplicate_skip?
432
+ false
433
+ end
434
+
435
+ def supports_insert_on_duplicate_update?
436
+ false
437
+ end
438
+
439
+ def supports_insert_conflict_target?
440
+ false
441
+ end
442
+
443
+ # This is meant to be implemented by the adapters that support extensions
444
+ def disable_extension(name)
445
+ end
446
+
447
+ # This is meant to be implemented by the adapters that support extensions
448
+ def enable_extension(name)
449
+ end
450
+
451
+ def advisory_locks_enabled? # :nodoc:
452
+ supports_advisory_locks? && @advisory_locks_enabled
453
+ end
454
+
455
+ # This is meant to be implemented by the adapters that support advisory
456
+ # locks
457
+ #
458
+ # Return true if we got the lock, otherwise false
459
+ def get_advisory_lock(lock_id) # :nodoc:
460
+ end
461
+
462
+ # This is meant to be implemented by the adapters that support advisory
463
+ # locks.
464
+ #
465
+ # Return true if we released the lock, otherwise false
466
+ def release_advisory_lock(lock_id) # :nodoc:
467
+ end
468
+
469
+ # A list of extensions, to be filled in by adapters that support them.
470
+ def extensions
471
+ []
472
+ end
473
+
474
+ # A list of index algorithms, to be filled by adapters that support them.
475
+ def index_algorithms
476
+ {}
477
+ end
478
+
479
+ # REFERENTIAL INTEGRITY ====================================
480
+
481
+ # Override to turn off referential integrity while executing <tt>&block</tt>.
482
+ def disable_referential_integrity
483
+ yield
484
+ end
485
+
486
+ # CONNECTION MANAGEMENT ====================================
487
+
488
+ # Checks whether the connection to the database is still active. This includes
489
+ # checking whether the database is actually capable of responding, i.e. whether
490
+ # the connection isn't stale.
491
+ def active?
492
+ end
493
+
494
+ # Disconnects from the database if already connected, and establishes a
495
+ # new connection with the database. Implementors should call super if they
496
+ # override the default implementation.
497
+ def reconnect!
498
+ clear_cache!
499
+ reset_transaction
500
+ end
501
+
502
+ # Disconnects from the database if already connected. Otherwise, this
503
+ # method does nothing.
504
+ def disconnect!
505
+ clear_cache!
506
+ reset_transaction
507
+ end
508
+
509
+ # Immediately forget this connection ever existed. Unlike disconnect!,
510
+ # this will not communicate with the server.
511
+ #
512
+ # After calling this method, the behavior of all other methods becomes
513
+ # undefined. This is called internally just before a forked process gets
514
+ # rid of a connection that belonged to its parent.
515
+ def discard!
516
+ # This should be overridden by concrete adapters.
517
+ #
518
+ # Prevent @connection's finalizer from touching the socket, or
519
+ # otherwise communicating with its server, when it is collected.
520
+ if schema_cache.connection == self
521
+ schema_cache.connection = nil
522
+ end
523
+ end
524
+
525
+ # Reset the state of this connection, directing the DBMS to clear
526
+ # transactions and other connection-related server-side state. Usually a
527
+ # database-dependent operation.
528
+ #
529
+ # The default implementation does nothing; the implementation should be
530
+ # overridden by concrete adapters.
531
+ def reset!
532
+ # this should be overridden by concrete adapters
533
+ end
534
+
535
+ # Clear any caching the database adapter may be doing.
536
+ def clear_cache!
537
+ @lock.synchronize { @statements.clear } if @statements
538
+ end
539
+
540
+ # Returns true if its required to reload the connection between requests for development mode.
541
+ def requires_reloading?
542
+ false
543
+ end
544
+
545
+ # Checks whether the connection to the database is still active (i.e. not stale).
546
+ # This is done under the hood by calling #active?. If the connection
547
+ # is no longer active, then this method will reconnect to the database.
548
+ def verify!
549
+ reconnect! unless active?
550
+ end
551
+
552
+ # Provides access to the underlying database driver for this adapter. For
553
+ # example, this method returns a Mysql2::Client object in case of Mysql2Adapter,
554
+ # and a PG::Connection object in case of PostgreSQLAdapter.
555
+ #
556
+ # This is useful for when you need to call a proprietary method such as
557
+ # PostgreSQL's lo_* methods.
558
+ def raw_connection
559
+ disable_lazy_transactions!
560
+ @connection
561
+ end
562
+
563
+ def default_uniqueness_comparison(attribute, value, klass) # :nodoc:
564
+ attribute.eq(value)
565
+ end
566
+
567
+ def case_sensitive_comparison(attribute, value) # :nodoc:
568
+ attribute.eq(value)
569
+ end
570
+
571
+ def case_insensitive_comparison(attribute, value) # :nodoc:
572
+ column = column_for_attribute(attribute)
573
+
574
+ if can_perform_case_insensitive_comparison_for?(column)
575
+ attribute.lower.eq(attribute.relation.lower(value))
576
+ else
577
+ attribute.eq(value)
578
+ end
579
+ end
580
+
581
+ def can_perform_case_insensitive_comparison_for?(column)
582
+ true
583
+ end
584
+ private :can_perform_case_insensitive_comparison_for?
585
+
586
+ # Check the connection back in to the connection pool
587
+ def close
588
+ pool.checkin self
589
+ end
590
+
591
+ def column_name_for_operation(operation, node) # :nodoc:
592
+ visitor.compile(node)
593
+ end
594
+
595
+ def default_index_type?(index) # :nodoc:
596
+ index.using.nil?
597
+ end
598
+
599
+ # Called by ActiveRecord::InsertAll,
600
+ # Passed an instance of ActiveRecord::InsertAll::Builder,
601
+ # This method implements standard bulk inserts for all databases, but
602
+ # should be overridden by adapters to implement common features with
603
+ # non-standard syntax like handling duplicates or returning values.
604
+ def build_insert_sql(insert) # :nodoc:
605
+ if insert.skip_duplicates? || insert.update_duplicates?
606
+ raise NotImplementedError, "#{self.class} should define `build_insert_sql` to implement adapter-specific logic for handling duplicates during INSERT"
607
+ end
608
+
609
+ "INSERT #{insert.into} #{insert.values_list}"
610
+ end
611
+
612
+ def get_database_version # :nodoc:
613
+ end
614
+
615
+ def database_version # :nodoc:
616
+ schema_cache.database_version
617
+ end
618
+
619
+ def check_version # :nodoc:
620
+ end
621
+
622
+ private
623
+
624
+ def type_map
625
+ @type_map ||= Type::TypeMap.new.tap do |mapping|
626
+ initialize_type_map(mapping)
627
+ end
628
+ end
629
+
630
+ def initialize_type_map(m = type_map)
631
+ register_class_with_limit m, %r(boolean)i, Type::Boolean
632
+ register_class_with_limit m, %r(char)i, Type::String
633
+ register_class_with_limit m, %r(binary)i, Type::Binary
634
+ register_class_with_limit m, %r(text)i, Type::Text
635
+ register_class_with_precision m, %r(date)i, Type::Date
636
+ register_class_with_precision m, %r(time)i, Type::Time
637
+ register_class_with_precision m, %r(datetime)i, Type::DateTime
638
+ register_class_with_limit m, %r(float)i, Type::Float
639
+ register_class_with_limit m, %r(int)i, Type::Integer
640
+
641
+ m.alias_type %r(blob)i, "binary"
642
+ m.alias_type %r(clob)i, "text"
643
+ m.alias_type %r(timestamp)i, "datetime"
644
+ m.alias_type %r(numeric)i, "decimal"
645
+ m.alias_type %r(number)i, "decimal"
646
+ m.alias_type %r(double)i, "float"
647
+
648
+ m.register_type %r(^json)i, Type::Json.new
649
+
650
+ m.register_type(%r(decimal)i) do |sql_type|
651
+ scale = extract_scale(sql_type)
652
+ precision = extract_precision(sql_type)
653
+
654
+ if scale == 0
655
+ # FIXME: Remove this class as well
656
+ Type::DecimalWithoutScale.new(precision: precision)
657
+ else
658
+ Type::Decimal.new(precision: precision, scale: scale)
659
+ end
660
+ end
661
+ end
662
+
663
+ def reload_type_map
664
+ type_map.clear
665
+ initialize_type_map
666
+ end
667
+
668
+ def register_class_with_limit(mapping, key, klass)
669
+ mapping.register_type(key) do |*args|
670
+ limit = extract_limit(args.last)
671
+ klass.new(limit: limit)
672
+ end
673
+ end
674
+
675
+ def register_class_with_precision(mapping, key, klass)
676
+ mapping.register_type(key) do |*args|
677
+ precision = extract_precision(args.last)
678
+ klass.new(precision: precision)
679
+ end
680
+ end
681
+
682
+ def extract_scale(sql_type)
683
+ case sql_type
684
+ when /\((\d+)\)/ then 0
685
+ when /\((\d+)(,(\d+))\)/ then $3.to_i
686
+ end
687
+ end
688
+
689
+ def extract_precision(sql_type)
690
+ $1.to_i if sql_type =~ /\((\d+)(,\d+)?\)/
691
+ end
692
+
693
+ def extract_limit(sql_type)
694
+ $1.to_i if sql_type =~ /\((.*)\)/
695
+ end
696
+
697
+ def translate_exception_class(e, sql, binds)
698
+ message = "#{e.class.name}: #{e.message}"
699
+
700
+ exception = translate_exception(
701
+ e, message: message, sql: sql, binds: binds
702
+ )
703
+ exception.set_backtrace e.backtrace
704
+ exception
705
+ end
706
+
707
+ def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil) # :doc:
708
+ @instrumenter.instrument(
709
+ "sql.active_record",
710
+ sql: sql,
711
+ name: name,
712
+ binds: binds,
713
+ type_casted_binds: type_casted_binds,
714
+ statement_name: statement_name,
715
+ connection_id: object_id,
716
+ connection: self) do
717
+ @lock.synchronize do
718
+ yield
719
+ end
720
+ rescue => e
721
+ raise translate_exception_class(e, sql, binds)
722
+ end
723
+ end
724
+
725
+ def translate_exception(exception, message:, sql:, binds:)
726
+ # override in derived class
727
+ case exception
728
+ when RuntimeError
729
+ exception
730
+ else
731
+ ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds)
732
+ end
733
+ end
734
+
735
+ def without_prepared_statement?(binds)
736
+ !prepared_statements || binds.empty?
737
+ end
738
+
739
+ def column_for(table_name, column_name)
740
+ column_name = column_name.to_s
741
+ columns(table_name).detect { |c| c.name == column_name } ||
742
+ raise(ActiveRecordError, "No such column: #{table_name}.#{column_name}")
743
+ end
744
+
745
+ def column_for_attribute(attribute)
746
+ table_name = attribute.relation.name
747
+ schema_cache.columns_hash(table_name)[attribute.name.to_s]
748
+ end
749
+
750
+ def collector
751
+ if prepared_statements
752
+ Arel::Collectors::Composite.new(
753
+ Arel::Collectors::SQLString.new,
754
+ Arel::Collectors::Bind.new,
755
+ )
756
+ else
757
+ Arel::Collectors::SubstituteBinds.new(
758
+ self,
759
+ Arel::Collectors::SQLString.new,
760
+ )
761
+ end
762
+ end
763
+
764
+ def arel_visitor
765
+ Arel::Visitors::ToSql.new(self)
766
+ end
767
+
768
+ def build_statement_pool
769
+ end
770
+ end
771
+ end
772
+ end