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,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "concurrent/map"
4
+
5
+ module ActiveRecord
6
+ module ConnectionAdapters # :nodoc:
7
+ module QueryCache
8
+ class << self
9
+ def included(base) #:nodoc:
10
+ dirties_query_cache base, :insert, :update, :delete, :truncate, :truncate_tables,
11
+ :rollback_to_savepoint, :rollback_db_transaction, :exec_insert_all
12
+
13
+ base.set_callback :checkout, :after, :configure_query_cache!
14
+ base.set_callback :checkin, :after, :disable_query_cache!
15
+ end
16
+
17
+ def dirties_query_cache(base, *method_names)
18
+ method_names.each do |method_name|
19
+ base.class_eval <<-end_code, __FILE__, __LINE__ + 1
20
+ def #{method_name}(*)
21
+ ActiveRecord::Base.clear_query_caches_for_current_thread if @query_cache_enabled
22
+ super
23
+ end
24
+ end_code
25
+ end
26
+ end
27
+ end
28
+
29
+ module ConnectionPoolConfiguration
30
+ def initialize(*)
31
+ super
32
+ @query_cache_enabled = Concurrent::Map.new { false }
33
+ end
34
+
35
+ def enable_query_cache!
36
+ @query_cache_enabled[connection_cache_key(current_thread)] = true
37
+ connection.enable_query_cache! if active_connection?
38
+ end
39
+
40
+ def disable_query_cache!
41
+ @query_cache_enabled.delete connection_cache_key(current_thread)
42
+ connection.disable_query_cache! if active_connection?
43
+ end
44
+
45
+ def query_cache_enabled
46
+ @query_cache_enabled[connection_cache_key(current_thread)]
47
+ end
48
+ end
49
+
50
+ attr_reader :query_cache, :query_cache_enabled
51
+
52
+ def initialize(*)
53
+ super
54
+ @query_cache = Hash.new { |h, sql| h[sql] = {} }
55
+ @query_cache_enabled = false
56
+ end
57
+
58
+ # Enable the query cache within the block.
59
+ def cache
60
+ old, @query_cache_enabled = @query_cache_enabled, true
61
+ yield
62
+ ensure
63
+ @query_cache_enabled = old
64
+ clear_query_cache unless @query_cache_enabled
65
+ end
66
+
67
+ def enable_query_cache!
68
+ @query_cache_enabled = true
69
+ end
70
+
71
+ def disable_query_cache!
72
+ @query_cache_enabled = false
73
+ clear_query_cache
74
+ end
75
+
76
+ # Disable the query cache within the block.
77
+ def uncached
78
+ old, @query_cache_enabled = @query_cache_enabled, false
79
+ yield
80
+ ensure
81
+ @query_cache_enabled = old
82
+ end
83
+
84
+ # Clears the query cache.
85
+ #
86
+ # One reason you may wish to call this method explicitly is between queries
87
+ # that ask the database to randomize results. Otherwise the cache would see
88
+ # the same SQL query and repeatedly return the same result each time, silently
89
+ # undermining the randomness you were expecting.
90
+ def clear_query_cache
91
+ @lock.synchronize do
92
+ @query_cache.clear
93
+ end
94
+ end
95
+
96
+ def select_all(arel, name = nil, binds = [], preparable: nil)
97
+ if @query_cache_enabled && !locked?(arel)
98
+ arel = arel_from_relation(arel)
99
+ sql, binds = to_sql_and_binds(arel, binds)
100
+
101
+ if preparable.nil?
102
+ preparable = prepared_statements ? visitor.preparable : false
103
+ end
104
+
105
+ cache_sql(sql, name, binds) { super(sql, name, binds, preparable: preparable) }
106
+ else
107
+ super
108
+ end
109
+ end
110
+
111
+ private
112
+
113
+ def cache_sql(sql, name, binds)
114
+ @lock.synchronize do
115
+ result =
116
+ if @query_cache[sql].key?(binds)
117
+ ActiveSupport::Notifications.instrument(
118
+ "sql.active_record",
119
+ cache_notification_info(sql, name, binds)
120
+ )
121
+ @query_cache[sql][binds]
122
+ else
123
+ @query_cache[sql][binds] = yield
124
+ end
125
+ result.dup
126
+ end
127
+ end
128
+
129
+ # Database adapters can override this method to
130
+ # provide custom cache information.
131
+ def cache_notification_info(sql, name, binds)
132
+ {
133
+ sql: sql,
134
+ binds: binds,
135
+ type_casted_binds: -> { type_casted_binds(binds) },
136
+ name: name,
137
+ connection_id: object_id,
138
+ connection: self,
139
+ cached: true
140
+ }
141
+ end
142
+
143
+ # If arel is locked this is a SELECT ... FOR UPDATE or somesuch. Such
144
+ # queries should not be cached.
145
+ def locked?(arel)
146
+ arel = arel.arel if arel.is_a?(Relation)
147
+ arel.respond_to?(:locked) && arel.locked
148
+ end
149
+
150
+ def configure_query_cache!
151
+ enable_query_cache! if pool.query_cache_enabled
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,251 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/big_decimal/conversions"
4
+ require "active_support/multibyte/chars"
5
+
6
+ module ActiveRecord
7
+ module ConnectionAdapters # :nodoc:
8
+ module Quoting
9
+ # Quotes the column value to help prevent
10
+ # {SQL injection attacks}[https://en.wikipedia.org/wiki/SQL_injection].
11
+ def quote(value)
12
+ value = id_value_for_database(value) if value.is_a?(Base)
13
+
14
+ if value.respond_to?(:value_for_database)
15
+ value = value.value_for_database
16
+ end
17
+
18
+ _quote(value)
19
+ end
20
+
21
+ # Cast a +value+ to a type that the database understands. For example,
22
+ # SQLite does not understand dates, so this method will convert a Date
23
+ # to a String.
24
+ def type_cast(value, column = nil)
25
+ value = id_value_for_database(value) if value.is_a?(Base)
26
+
27
+ if column
28
+ value = type_cast_from_column(column, value)
29
+ end
30
+
31
+ _type_cast(value)
32
+ rescue TypeError
33
+ to_type = column ? " to #{column.type}" : ""
34
+ raise TypeError, "can't cast #{value.class}#{to_type}"
35
+ end
36
+
37
+ # If you are having to call this function, you are likely doing something
38
+ # wrong. The column does not have sufficient type information if the user
39
+ # provided a custom type on the class level either explicitly (via
40
+ # Attributes::ClassMethods#attribute) or implicitly (via
41
+ # AttributeMethods::Serialization::ClassMethods#serialize, +time_zone_aware_attributes+).
42
+ # In almost all cases, the sql type should only be used to change quoting behavior, when the primitive to
43
+ # represent the type doesn't sufficiently reflect the differences
44
+ # (varchar vs binary) for example. The type used to get this primitive
45
+ # should have been provided before reaching the connection adapter.
46
+ def type_cast_from_column(column, value) # :nodoc:
47
+ if column
48
+ type = lookup_cast_type_from_column(column)
49
+ type.serialize(value)
50
+ else
51
+ value
52
+ end
53
+ end
54
+
55
+ # See docs for #type_cast_from_column
56
+ def lookup_cast_type_from_column(column) # :nodoc:
57
+ lookup_cast_type(column.sql_type)
58
+ end
59
+
60
+ # Quotes a string, escaping any ' (single quote) and \ (backslash)
61
+ # characters.
62
+ def quote_string(s)
63
+ s.gsub('\\', '\&\&').gsub("'", "''") # ' (for ruby-mode)
64
+ end
65
+
66
+ # Quotes the column name. Defaults to no quoting.
67
+ def quote_column_name(column_name)
68
+ column_name.to_s
69
+ end
70
+
71
+ # Quotes the table name. Defaults to column name quoting.
72
+ def quote_table_name(table_name)
73
+ quote_column_name(table_name)
74
+ end
75
+
76
+ # Override to return the quoted table name for assignment. Defaults to
77
+ # table quoting.
78
+ #
79
+ # This works for mysql2 where table.column can be used to
80
+ # resolve ambiguity.
81
+ #
82
+ # We override this in the sqlite3 and postgresql adapters to use only
83
+ # the column name (as per syntax requirements).
84
+ def quote_table_name_for_assignment(table, attr)
85
+ quote_table_name("#{table}.#{attr}")
86
+ end
87
+
88
+ def quote_default_expression(value, column) # :nodoc:
89
+ if value.is_a?(Proc)
90
+ value.call
91
+ else
92
+ value = lookup_cast_type(column.sql_type).serialize(value)
93
+ quote(value)
94
+ end
95
+ end
96
+
97
+ def quoted_true
98
+ "TRUE"
99
+ end
100
+
101
+ def unquoted_true
102
+ true
103
+ end
104
+
105
+ def quoted_false
106
+ "FALSE"
107
+ end
108
+
109
+ def unquoted_false
110
+ false
111
+ end
112
+
113
+ # Quote date/time values for use in SQL input. Includes microseconds
114
+ # if the value is a Time responding to usec.
115
+ def quoted_date(value)
116
+ if value.acts_like?(:time)
117
+ zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
118
+
119
+ if value.respond_to?(zone_conversion_method)
120
+ value = value.send(zone_conversion_method)
121
+ end
122
+ end
123
+
124
+ result = value.to_s(:db)
125
+ if value.respond_to?(:usec) && value.usec > 0
126
+ "#{result}.#{sprintf("%06d", value.usec)}"
127
+ else
128
+ result
129
+ end
130
+ end
131
+
132
+ def quoted_time(value) # :nodoc:
133
+ value = value.change(year: 2000, month: 1, day: 1)
134
+ quoted_date(value).sub(/\A\d\d\d\d-\d\d-\d\d /, "")
135
+ end
136
+
137
+ def quoted_binary(value) # :nodoc:
138
+ "'#{quote_string(value.to_s)}'"
139
+ end
140
+
141
+ def sanitize_as_sql_comment(value) # :nodoc:
142
+ value.to_s.gsub(%r{ (/ (?: | \g<1>) \*) \+? \s* | \s* (\* (?: | \g<2>) /) }x, "")
143
+ end
144
+
145
+ def column_name_matcher # :nodoc:
146
+ COLUMN_NAME
147
+ end
148
+
149
+ def column_name_with_order_matcher # :nodoc:
150
+ COLUMN_NAME_WITH_ORDER
151
+ end
152
+
153
+ # Regexp for column names (with or without a table name prefix).
154
+ # Matches the following:
155
+ #
156
+ # "#{table_name}.#{column_name}"
157
+ # "#{column_name}"
158
+ COLUMN_NAME = /
159
+ \A
160
+ (
161
+ (?:
162
+ # table_name.column_name | function(one or no argument)
163
+ ((?:\w+\.)?\w+) | \w+\((?:|\g<2>)\)
164
+ )
165
+ (?:\s+AS\s+\w+)?
166
+ )
167
+ (?:\s*,\s*\g<1>)*
168
+ \z
169
+ /ix
170
+
171
+ # Regexp for column names with order (with or without a table name prefix,
172
+ # with or without various order modifiers). Matches the following:
173
+ #
174
+ # "#{table_name}.#{column_name}"
175
+ # "#{table_name}.#{column_name} #{direction}"
176
+ # "#{table_name}.#{column_name} #{direction} NULLS FIRST"
177
+ # "#{table_name}.#{column_name} NULLS LAST"
178
+ # "#{column_name}"
179
+ # "#{column_name} #{direction}"
180
+ # "#{column_name} #{direction} NULLS FIRST"
181
+ # "#{column_name} NULLS LAST"
182
+ COLUMN_NAME_WITH_ORDER = /
183
+ \A
184
+ (
185
+ (?:
186
+ # table_name.column_name | function(one or no argument)
187
+ ((?:\w+\.)?\w+) | \w+\((?:|\g<2>)\)
188
+ )
189
+ (?:\s+ASC|\s+DESC)?
190
+ (?:\s+NULLS\s+(?:FIRST|LAST))?
191
+ )
192
+ (?:\s*,\s*\g<1>)*
193
+ \z
194
+ /ix
195
+
196
+ private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
197
+
198
+ private
199
+ def type_casted_binds(binds)
200
+ if binds.first.is_a?(Array)
201
+ binds.map { |column, value| type_cast(value, column) }
202
+ else
203
+ binds.map { |attr| type_cast(attr.value_for_database) }
204
+ end
205
+ end
206
+
207
+ def lookup_cast_type(sql_type)
208
+ type_map.lookup(sql_type)
209
+ end
210
+
211
+ def id_value_for_database(value)
212
+ if primary_key = value.class.primary_key
213
+ value.instance_variable_get(:@attributes)[primary_key].value_for_database
214
+ end
215
+ end
216
+
217
+ def _quote(value)
218
+ case value
219
+ when String, Symbol, ActiveSupport::Multibyte::Chars
220
+ "'#{quote_string(value.to_s)}'"
221
+ when true then quoted_true
222
+ when false then quoted_false
223
+ when nil then "NULL"
224
+ # BigDecimals need to be put in a non-normalized form and quoted.
225
+ when BigDecimal then value.to_s("F")
226
+ when Numeric, ActiveSupport::Duration then value.to_s
227
+ when Type::Binary::Data then quoted_binary(value)
228
+ when Type::Time::Value then "'#{quoted_time(value)}'"
229
+ when Date, Time then "'#{quoted_date(value)}'"
230
+ when Class then "'#{value}'"
231
+ else raise TypeError, "can't quote #{value.class.name}"
232
+ end
233
+ end
234
+
235
+ def _type_cast(value)
236
+ case value
237
+ when Symbol, ActiveSupport::Multibyte::Chars, Type::Binary::Data
238
+ value.to_s
239
+ when true then unquoted_true
240
+ when false then unquoted_false
241
+ # BigDecimals need to be put in a non-normalized form and quoted.
242
+ when BigDecimal then value.to_s("F")
243
+ when nil, Numeric, String then value
244
+ when Type::Time::Value then quoted_time(value)
245
+ when Date, Time then quoted_date(value)
246
+ else raise TypeError
247
+ end
248
+ end
249
+ end
250
+ end
251
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ module Savepoints
6
+ def current_savepoint_name
7
+ current_transaction.savepoint_name
8
+ end
9
+
10
+ def create_savepoint(name = current_savepoint_name)
11
+ execute("SAVEPOINT #{name}")
12
+ end
13
+
14
+ def exec_rollback_to_savepoint(name = current_savepoint_name)
15
+ execute("ROLLBACK TO SAVEPOINT #{name}")
16
+ end
17
+
18
+ def release_savepoint(name = current_savepoint_name)
19
+ execute("RELEASE SAVEPOINT #{name}")
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,153 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ class AbstractAdapter
6
+ class SchemaCreation # :nodoc:
7
+ def initialize(conn)
8
+ @conn = conn
9
+ @cache = {}
10
+ end
11
+
12
+ def accept(o)
13
+ m = @cache[o.class] ||= "visit_#{o.class.name.split('::').last}"
14
+ send m, o
15
+ end
16
+
17
+ delegate :quote_column_name, :quote_table_name, :quote_default_expression, :type_to_sql,
18
+ :options_include_default?, :supports_indexes_in_create?, :supports_foreign_keys?, :foreign_key_options,
19
+ to: :@conn, private: true
20
+
21
+ private
22
+
23
+ def visit_AlterTable(o)
24
+ sql = +"ALTER TABLE #{quote_table_name(o.name)} "
25
+ sql << o.adds.map { |col| accept col }.join(" ")
26
+ sql << o.foreign_key_adds.map { |fk| visit_AddForeignKey fk }.join(" ")
27
+ sql << o.foreign_key_drops.map { |fk| visit_DropForeignKey fk }.join(" ")
28
+ end
29
+
30
+ def visit_ColumnDefinition(o)
31
+ o.sql_type = type_to_sql(o.type, o.options)
32
+ column_sql = +"#{quote_column_name(o.name)} #{o.sql_type}"
33
+ add_column_options!(column_sql, column_options(o)) unless o.type == :primary_key
34
+ column_sql
35
+ end
36
+
37
+ def visit_AddColumnDefinition(o)
38
+ +"ADD #{accept(o.column)}"
39
+ end
40
+
41
+ def visit_TableDefinition(o)
42
+ create_sql = +"CREATE#{table_modifier_in_create(o)} TABLE "
43
+ create_sql << "IF NOT EXISTS " if o.if_not_exists
44
+ create_sql << "#{quote_table_name(o.name)} "
45
+
46
+ statements = o.columns.map { |c| accept c }
47
+ statements << accept(o.primary_keys) if o.primary_keys
48
+
49
+ if supports_indexes_in_create?
50
+ statements.concat(o.indexes.map { |column_name, options| index_in_create(o.name, column_name, options) })
51
+ end
52
+
53
+ if supports_foreign_keys?
54
+ statements.concat(o.foreign_keys.map { |to_table, options| foreign_key_in_create(o.name, to_table, options) })
55
+ end
56
+
57
+ create_sql << "(#{statements.join(', ')})" if statements.present?
58
+ add_table_options!(create_sql, table_options(o))
59
+ create_sql << " AS #{to_sql(o.as)}" if o.as
60
+ create_sql
61
+ end
62
+
63
+ def visit_PrimaryKeyDefinition(o)
64
+ "PRIMARY KEY (#{o.name.map { |name| quote_column_name(name) }.join(', ')})"
65
+ end
66
+
67
+ def visit_ForeignKeyDefinition(o)
68
+ sql = +<<~SQL
69
+ CONSTRAINT #{quote_column_name(o.name)}
70
+ FOREIGN KEY (#{quote_column_name(o.column)})
71
+ REFERENCES #{quote_table_name(o.to_table)} (#{quote_column_name(o.primary_key)})
72
+ SQL
73
+ sql << " #{action_sql('DELETE', o.on_delete)}" if o.on_delete
74
+ sql << " #{action_sql('UPDATE', o.on_update)}" if o.on_update
75
+ sql
76
+ end
77
+
78
+ def visit_AddForeignKey(o)
79
+ "ADD #{accept(o)}"
80
+ end
81
+
82
+ def visit_DropForeignKey(name)
83
+ "DROP CONSTRAINT #{quote_column_name(name)}"
84
+ end
85
+
86
+ def table_options(o)
87
+ table_options = {}
88
+ table_options[:comment] = o.comment
89
+ table_options[:options] = o.options
90
+ table_options
91
+ end
92
+
93
+ def add_table_options!(create_sql, options)
94
+ if options_sql = options[:options]
95
+ create_sql << " #{options_sql}"
96
+ end
97
+ create_sql
98
+ end
99
+
100
+ def column_options(o)
101
+ o.options.merge(column: o)
102
+ end
103
+
104
+ def add_column_options!(sql, options)
105
+ sql << " DEFAULT #{quote_default_expression(options[:default], options[:column])}" if options_include_default?(options)
106
+ # must explicitly check for :null to allow change_column to work on migrations
107
+ if options[:null] == false
108
+ sql << " NOT NULL"
109
+ end
110
+ if options[:auto_increment] == true
111
+ sql << " AUTO_INCREMENT"
112
+ end
113
+ if options[:primary_key] == true
114
+ sql << " PRIMARY KEY"
115
+ end
116
+ sql
117
+ end
118
+
119
+ def to_sql(sql)
120
+ sql = sql.to_sql if sql.respond_to?(:to_sql)
121
+ sql
122
+ end
123
+
124
+ # Returns any SQL string to go between CREATE and TABLE. May be nil.
125
+ def table_modifier_in_create(o)
126
+ " TEMPORARY" if o.temporary
127
+ end
128
+
129
+ def foreign_key_in_create(from_table, to_table, options)
130
+ prefix = ActiveRecord::Base.table_name_prefix
131
+ suffix = ActiveRecord::Base.table_name_suffix
132
+ to_table = "#{prefix}#{to_table}#{suffix}"
133
+ options = foreign_key_options(from_table, to_table, options)
134
+ accept ForeignKeyDefinition.new(from_table, to_table, options)
135
+ end
136
+
137
+ def action_sql(action, dependency)
138
+ case dependency
139
+ when :nullify then "ON #{action} SET NULL"
140
+ when :cascade then "ON #{action} CASCADE"
141
+ when :restrict then "ON #{action} RESTRICT"
142
+ else
143
+ raise ArgumentError, <<~MSG
144
+ '#{dependency}' is not supported for :on_update or :on_delete.
145
+ Supported values are: :nullify, :cascade, :restrict
146
+ MSG
147
+ end
148
+ end
149
+ end
150
+ end
151
+ SchemaCreation = AbstractAdapter::SchemaCreation # :nodoc:
152
+ end
153
+ end