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,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/per_thread_registry"
4
+
5
+ module ActiveRecord
6
+ # This is a thread locals registry for Active Record. For example:
7
+ #
8
+ # ActiveRecord::RuntimeRegistry.connection_handler
9
+ #
10
+ # returns the connection handler local to the current thread.
11
+ #
12
+ # See the documentation of ActiveSupport::PerThreadRegistry
13
+ # for further details.
14
+ class RuntimeRegistry # :nodoc:
15
+ extend ActiveSupport::PerThreadRegistry
16
+
17
+ attr_accessor :connection_handler, :sql_runtime
18
+
19
+ [:connection_handler, :sql_runtime].each do |val|
20
+ class_eval %{ def self.#{val}; instance.#{val}; end }, __FILE__, __LINE__
21
+ class_eval %{ def self.#{val}=(x); instance.#{val}=x; end }, __FILE__, __LINE__
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,214 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Sanitization
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ # Accepts an array or string of SQL conditions and sanitizes
9
+ # them into a valid SQL fragment for a WHERE clause.
10
+ #
11
+ # sanitize_sql_for_conditions(["name=? and group_id=?", "foo'bar", 4])
12
+ # # => "name='foo''bar' and group_id=4"
13
+ #
14
+ # sanitize_sql_for_conditions(["name=:name and group_id=:group_id", name: "foo'bar", group_id: 4])
15
+ # # => "name='foo''bar' and group_id='4'"
16
+ #
17
+ # sanitize_sql_for_conditions(["name='%s' and group_id='%s'", "foo'bar", 4])
18
+ # # => "name='foo''bar' and group_id='4'"
19
+ #
20
+ # sanitize_sql_for_conditions("name='foo''bar' and group_id='4'")
21
+ # # => "name='foo''bar' and group_id='4'"
22
+ def sanitize_sql_for_conditions(condition)
23
+ return nil if condition.blank?
24
+
25
+ case condition
26
+ when Array; sanitize_sql_array(condition)
27
+ else condition
28
+ end
29
+ end
30
+ alias :sanitize_sql :sanitize_sql_for_conditions
31
+
32
+ # Accepts an array, hash, or string of SQL conditions and sanitizes
33
+ # them into a valid SQL fragment for a SET clause.
34
+ #
35
+ # sanitize_sql_for_assignment(["name=? and group_id=?", nil, 4])
36
+ # # => "name=NULL and group_id=4"
37
+ #
38
+ # sanitize_sql_for_assignment(["name=:name and group_id=:group_id", name: nil, group_id: 4])
39
+ # # => "name=NULL and group_id=4"
40
+ #
41
+ # Post.sanitize_sql_for_assignment({ name: nil, group_id: 4 })
42
+ # # => "`posts`.`name` = NULL, `posts`.`group_id` = 4"
43
+ #
44
+ # sanitize_sql_for_assignment("name=NULL and group_id='4'")
45
+ # # => "name=NULL and group_id='4'"
46
+ def sanitize_sql_for_assignment(assignments, default_table_name = table_name)
47
+ case assignments
48
+ when Array; sanitize_sql_array(assignments)
49
+ when Hash; sanitize_sql_hash_for_assignment(assignments, default_table_name)
50
+ else assignments
51
+ end
52
+ end
53
+
54
+ # Accepts an array, or string of SQL conditions and sanitizes
55
+ # them into a valid SQL fragment for an ORDER clause.
56
+ #
57
+ # sanitize_sql_for_order(["field(id, ?)", [1,3,2]])
58
+ # # => "field(id, 1,3,2)"
59
+ #
60
+ # sanitize_sql_for_order("id ASC")
61
+ # # => "id ASC"
62
+ def sanitize_sql_for_order(condition)
63
+ if condition.is_a?(Array) && condition.first.to_s.include?("?")
64
+ disallow_raw_sql!(
65
+ [condition.first],
66
+ permit: connection.column_name_with_order_matcher
67
+ )
68
+
69
+ # Ensure we aren't dealing with a subclass of String that might
70
+ # override methods we use (eg. Arel::Nodes::SqlLiteral).
71
+ if condition.first.kind_of?(String) && !condition.first.instance_of?(String)
72
+ condition = [String.new(condition.first), *condition[1..-1]]
73
+ end
74
+
75
+ Arel.sql(sanitize_sql_array(condition))
76
+ else
77
+ condition
78
+ end
79
+ end
80
+
81
+ # Sanitizes a hash of attribute/value pairs into SQL conditions for a SET clause.
82
+ #
83
+ # sanitize_sql_hash_for_assignment({ status: nil, group_id: 1 }, "posts")
84
+ # # => "`posts`.`status` = NULL, `posts`.`group_id` = 1"
85
+ def sanitize_sql_hash_for_assignment(attrs, table)
86
+ c = connection
87
+ attrs.map do |attr, value|
88
+ type = type_for_attribute(attr)
89
+ value = type.serialize(type.cast(value))
90
+ "#{c.quote_table_name_for_assignment(table, attr)} = #{c.quote(value)}"
91
+ end.join(", ")
92
+ end
93
+
94
+ # Sanitizes a +string+ so that it is safe to use within an SQL
95
+ # LIKE statement. This method uses +escape_character+ to escape all occurrences of "\", "_" and "%".
96
+ #
97
+ # sanitize_sql_like("100%")
98
+ # # => "100\\%"
99
+ #
100
+ # sanitize_sql_like("snake_cased_string")
101
+ # # => "snake\\_cased\\_string"
102
+ #
103
+ # sanitize_sql_like("100%", "!")
104
+ # # => "100!%"
105
+ #
106
+ # sanitize_sql_like("snake_cased_string", "!")
107
+ # # => "snake!_cased!_string"
108
+ def sanitize_sql_like(string, escape_character = "\\")
109
+ pattern = Regexp.union(escape_character, "%", "_")
110
+ string.gsub(pattern) { |x| [escape_character, x].join }
111
+ end
112
+
113
+ # Accepts an array of conditions. The array has each value
114
+ # sanitized and interpolated into the SQL statement.
115
+ #
116
+ # sanitize_sql_array(["name=? and group_id=?", "foo'bar", 4])
117
+ # # => "name='foo''bar' and group_id=4"
118
+ #
119
+ # sanitize_sql_array(["name=:name and group_id=:group_id", name: "foo'bar", group_id: 4])
120
+ # # => "name='foo''bar' and group_id=4"
121
+ #
122
+ # sanitize_sql_array(["name='%s' and group_id='%s'", "foo'bar", 4])
123
+ # # => "name='foo''bar' and group_id='4'"
124
+ def sanitize_sql_array(ary)
125
+ statement, *values = ary
126
+ if values.first.is_a?(Hash) && /:\w+/.match?(statement)
127
+ replace_named_bind_variables(statement, values.first)
128
+ elsif statement.include?("?")
129
+ replace_bind_variables(statement, values)
130
+ elsif statement.blank?
131
+ statement
132
+ else
133
+ statement % values.collect { |value| connection.quote_string(value.to_s) }
134
+ end
135
+ end
136
+
137
+ def disallow_raw_sql!(args, permit: connection.column_name_matcher) # :nodoc:
138
+ unexpected = nil
139
+ args.each do |arg|
140
+ next if arg.is_a?(Symbol) || Arel.arel_node?(arg) || permit.match?(arg.to_s)
141
+ (unexpected ||= []) << arg
142
+ end
143
+
144
+ return unless unexpected
145
+
146
+ if allow_unsafe_raw_sql == :deprecated
147
+ ActiveSupport::Deprecation.warn(
148
+ "Dangerous query method (method whose arguments are used as raw " \
149
+ "SQL) called with non-attribute argument(s): " \
150
+ "#{unexpected.map(&:inspect).join(", ")}. Non-attribute " \
151
+ "arguments will be disallowed in Rails 6.1. This method should " \
152
+ "not be called with user-provided values, such as request " \
153
+ "parameters or model attributes. Known-safe values can be passed " \
154
+ "by wrapping them in Arel.sql()."
155
+ )
156
+ else
157
+ raise(ActiveRecord::UnknownAttributeReference,
158
+ "Query method called with non-attribute argument(s): " +
159
+ unexpected.map(&:inspect).join(", ")
160
+ )
161
+ end
162
+ end
163
+
164
+ private
165
+ def replace_bind_variables(statement, values)
166
+ raise_if_bind_arity_mismatch(statement, statement.count("?"), values.size)
167
+ bound = values.dup
168
+ c = connection
169
+ statement.gsub(/\?/) do
170
+ replace_bind_variable(bound.shift, c)
171
+ end
172
+ end
173
+
174
+ def replace_bind_variable(value, c = connection)
175
+ if ActiveRecord::Relation === value
176
+ value.to_sql
177
+ else
178
+ quote_bound_value(value, c)
179
+ end
180
+ end
181
+
182
+ def replace_named_bind_variables(statement, bind_vars)
183
+ statement.gsub(/(:?):([a-zA-Z]\w*)/) do |match|
184
+ if $1 == ":" # skip postgresql casts
185
+ match # return the whole match
186
+ elsif bind_vars.include?(match = $2.to_sym)
187
+ replace_bind_variable(bind_vars[match])
188
+ else
189
+ raise PreparedStatementInvalid, "missing value for :#{match} in #{statement}"
190
+ end
191
+ end
192
+ end
193
+
194
+ def quote_bound_value(value, c = connection)
195
+ if value.respond_to?(:map) && !value.acts_like?(:string)
196
+ quoted = value.map { |v| c.quote(v) }
197
+ if quoted.empty?
198
+ c.quote(nil)
199
+ else
200
+ quoted.join(",")
201
+ end
202
+ else
203
+ c.quote(value)
204
+ end
205
+ end
206
+
207
+ def raise_if_bind_arity_mismatch(statement, expected, provided)
208
+ unless expected == provided
209
+ raise PreparedStatementInvalid, "wrong number of bind variables (#{provided} for #{expected}) in: #{statement}"
210
+ end
211
+ end
212
+ end
213
+ end
214
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ # = Active Record \Schema
5
+ #
6
+ # Allows programmers to programmatically define a schema in a portable
7
+ # DSL. This means you can define tables, indexes, etc. without using SQL
8
+ # directly, so your applications can more easily support multiple
9
+ # databases.
10
+ #
11
+ # Usage:
12
+ #
13
+ # ActiveRecord::Schema.define do
14
+ # create_table :authors do |t|
15
+ # t.string :name, null: false
16
+ # end
17
+ #
18
+ # add_index :authors, :name, :unique
19
+ #
20
+ # create_table :posts do |t|
21
+ # t.integer :author_id, null: false
22
+ # t.string :subject
23
+ # t.text :body
24
+ # t.boolean :private, default: false
25
+ # end
26
+ #
27
+ # add_index :posts, :author_id
28
+ # end
29
+ #
30
+ # ActiveRecord::Schema is only supported by database adapters that also
31
+ # support migrations, the two features being very similar.
32
+ class Schema < Migration::Current
33
+ # Eval the given block. All methods available to the current connection
34
+ # adapter are available within the block, so you can easily use the
35
+ # database definition DSL to build up your schema (
36
+ # {create_table}[rdoc-ref:ConnectionAdapters::SchemaStatements#create_table],
37
+ # {add_index}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_index], etc.).
38
+ #
39
+ # The +info+ hash is optional, and if given is used to define metadata
40
+ # about the current schema (currently, only the schema's version):
41
+ #
42
+ # ActiveRecord::Schema.define(version: 2038_01_19_000001) do
43
+ # ...
44
+ # end
45
+ def self.define(info = {}, &block)
46
+ new.define(info, &block)
47
+ end
48
+
49
+ def define(info, &block) # :nodoc:
50
+ instance_eval(&block)
51
+
52
+ if info[:version].present?
53
+ connection.schema_migration.create_table
54
+ connection.assume_migrated_upto_version(info[:version])
55
+ end
56
+
57
+ ActiveRecord::InternalMetadata.create_table
58
+ ActiveRecord::InternalMetadata[:environment] = connection.migration_context.current_environment
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,270 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "stringio"
4
+
5
+ module ActiveRecord
6
+ # = Active Record Schema Dumper
7
+ #
8
+ # This class is used to dump the database schema for some connection to some
9
+ # output format (i.e., ActiveRecord::Schema).
10
+ class SchemaDumper #:nodoc:
11
+ private_class_method :new
12
+
13
+ ##
14
+ # :singleton-method:
15
+ # A list of tables which should not be dumped to the schema.
16
+ # Acceptable values are strings as well as regexp if ActiveRecord::Base.schema_format == :ruby.
17
+ # Only strings are accepted if ActiveRecord::Base.schema_format == :sql.
18
+ cattr_accessor :ignore_tables, default: []
19
+
20
+ ##
21
+ # :singleton-method:
22
+ # Specify a custom regular expression matching foreign keys which name
23
+ # should not be dumped to db/schema.rb.
24
+ cattr_accessor :fk_ignore_pattern, default: /^fk_rails_[0-9a-f]{10}$/
25
+
26
+ class << self
27
+ def dump(connection = ActiveRecord::Base.connection, stream = STDOUT, config = ActiveRecord::Base)
28
+ connection.create_schema_dumper(generate_options(config)).dump(stream)
29
+ stream
30
+ end
31
+
32
+ private
33
+ def generate_options(config)
34
+ {
35
+ table_name_prefix: config.table_name_prefix,
36
+ table_name_suffix: config.table_name_suffix
37
+ }
38
+ end
39
+ end
40
+
41
+ def dump(stream)
42
+ header(stream)
43
+ extensions(stream)
44
+ tables(stream)
45
+ trailer(stream)
46
+ stream
47
+ end
48
+
49
+ private
50
+ attr_accessor :table_name
51
+
52
+ def initialize(connection, options = {})
53
+ @connection = connection
54
+ @version = connection.migration_context.current_version rescue nil
55
+ @options = options
56
+ end
57
+
58
+ # turns 20170404131909 into "2017_04_04_131909"
59
+ def formatted_version
60
+ stringified = @version.to_s
61
+ return stringified unless stringified.length == 14
62
+ stringified.insert(4, "_").insert(7, "_").insert(10, "_")
63
+ end
64
+
65
+ def define_params
66
+ @version ? "version: #{formatted_version}" : ""
67
+ end
68
+
69
+ def header(stream)
70
+ stream.puts <<HEADER
71
+ # This file is auto-generated from the current state of the database. Instead
72
+ # of editing this file, please use the migrations feature of Active Record to
73
+ # incrementally modify your database, and then regenerate this schema definition.
74
+ #
75
+ # This file is the source Rails uses to define your schema when running `rails
76
+ # db:schema:load`. When creating a new database, `rails db:schema:load` tends to
77
+ # be faster and is potentially less error prone than running all of your
78
+ # migrations from scratch. Old migrations may fail to apply correctly if those
79
+ # migrations use external dependencies or application code.
80
+ #
81
+ # It's strongly recommended that you check this file into your version control system.
82
+
83
+ ActiveRecord::Schema.define(#{define_params}) do
84
+
85
+ HEADER
86
+ end
87
+
88
+ def trailer(stream)
89
+ stream.puts "end"
90
+ end
91
+
92
+ # extensions are only supported by PostgreSQL
93
+ def extensions(stream)
94
+ end
95
+
96
+ def tables(stream)
97
+ sorted_tables = @connection.tables.sort
98
+
99
+ sorted_tables.each do |table_name|
100
+ table(table_name, stream) unless ignored?(table_name)
101
+ end
102
+
103
+ # dump foreign keys at the end to make sure all dependent tables exist.
104
+ if @connection.supports_foreign_keys?
105
+ sorted_tables.each do |tbl|
106
+ foreign_keys(tbl, stream) unless ignored?(tbl)
107
+ end
108
+ end
109
+ end
110
+
111
+ def table(table, stream)
112
+ columns = @connection.columns(table)
113
+ begin
114
+ self.table_name = table
115
+
116
+ tbl = StringIO.new
117
+
118
+ # first dump primary key column
119
+ pk = @connection.primary_key(table)
120
+
121
+ tbl.print " create_table #{remove_prefix_and_suffix(table).inspect}"
122
+
123
+ case pk
124
+ when String
125
+ tbl.print ", primary_key: #{pk.inspect}" unless pk == "id"
126
+ pkcol = columns.detect { |c| c.name == pk }
127
+ pkcolspec = column_spec_for_primary_key(pkcol)
128
+ if pkcolspec.present?
129
+ tbl.print ", #{format_colspec(pkcolspec)}"
130
+ end
131
+ when Array
132
+ tbl.print ", primary_key: #{pk.inspect}"
133
+ else
134
+ tbl.print ", id: false"
135
+ end
136
+
137
+ table_options = @connection.table_options(table)
138
+ if table_options.present?
139
+ tbl.print ", #{format_options(table_options)}"
140
+ end
141
+
142
+ tbl.puts ", force: :cascade do |t|"
143
+
144
+ # then dump all non-primary key columns
145
+ columns.each do |column|
146
+ raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
147
+ next if column.name == pk
148
+ type, colspec = column_spec(column)
149
+ if type.is_a?(Symbol)
150
+ tbl.print " t.#{type} #{column.name.inspect}"
151
+ else
152
+ tbl.print " t.column #{column.name.inspect}, #{type.inspect}"
153
+ end
154
+ tbl.print ", #{format_colspec(colspec)}" if colspec.present?
155
+ tbl.puts
156
+ end
157
+
158
+ indexes_in_create(table, tbl)
159
+
160
+ tbl.puts " end"
161
+ tbl.puts
162
+
163
+ tbl.rewind
164
+ stream.print tbl.read
165
+ rescue => e
166
+ stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}"
167
+ stream.puts "# #{e.message}"
168
+ stream.puts
169
+ ensure
170
+ self.table_name = nil
171
+ end
172
+ end
173
+
174
+ # Keep it for indexing materialized views
175
+ def indexes(table, stream)
176
+ if (indexes = @connection.indexes(table)).any?
177
+ add_index_statements = indexes.map do |index|
178
+ table_name = remove_prefix_and_suffix(index.table).inspect
179
+ " add_index #{([table_name] + index_parts(index)).join(', ')}"
180
+ end
181
+
182
+ stream.puts add_index_statements.sort.join("\n")
183
+ stream.puts
184
+ end
185
+ end
186
+
187
+ def indexes_in_create(table, stream)
188
+ if (indexes = @connection.indexes(table)).any?
189
+ index_statements = indexes.map do |index|
190
+ " t.index #{index_parts(index).join(', ')}"
191
+ end
192
+ stream.puts index_statements.sort.join("\n")
193
+ end
194
+ end
195
+
196
+ def index_parts(index)
197
+ index_parts = [
198
+ index.columns.inspect,
199
+ "name: #{index.name.inspect}",
200
+ ]
201
+ index_parts << "unique: true" if index.unique
202
+ index_parts << "length: #{format_index_parts(index.lengths)}" if index.lengths.present?
203
+ index_parts << "order: #{format_index_parts(index.orders)}" if index.orders.present?
204
+ index_parts << "opclass: #{format_index_parts(index.opclasses)}" if index.opclasses.present?
205
+ index_parts << "where: #{index.where.inspect}" if index.where
206
+ index_parts << "using: #{index.using.inspect}" if !@connection.default_index_type?(index)
207
+ index_parts << "type: #{index.type.inspect}" if index.type
208
+ index_parts << "comment: #{index.comment.inspect}" if index.comment
209
+ index_parts
210
+ end
211
+
212
+ def foreign_keys(table, stream)
213
+ if (foreign_keys = @connection.foreign_keys(table)).any?
214
+ add_foreign_key_statements = foreign_keys.map do |foreign_key|
215
+ parts = [
216
+ "add_foreign_key #{remove_prefix_and_suffix(foreign_key.from_table).inspect}",
217
+ remove_prefix_and_suffix(foreign_key.to_table).inspect,
218
+ ]
219
+
220
+ if foreign_key.column != @connection.foreign_key_column_for(foreign_key.to_table)
221
+ parts << "column: #{foreign_key.column.inspect}"
222
+ end
223
+
224
+ if foreign_key.custom_primary_key?
225
+ parts << "primary_key: #{foreign_key.primary_key.inspect}"
226
+ end
227
+
228
+ if foreign_key.export_name_on_schema_dump?
229
+ parts << "name: #{foreign_key.name.inspect}"
230
+ end
231
+
232
+ parts << "on_update: #{foreign_key.on_update.inspect}" if foreign_key.on_update
233
+ parts << "on_delete: #{foreign_key.on_delete.inspect}" if foreign_key.on_delete
234
+
235
+ " #{parts.join(', ')}"
236
+ end
237
+
238
+ stream.puts add_foreign_key_statements.sort.join("\n")
239
+ end
240
+ end
241
+
242
+ def format_colspec(colspec)
243
+ colspec.map { |key, value| "#{key}: #{value}" }.join(", ")
244
+ end
245
+
246
+ def format_options(options)
247
+ options.map { |key, value| "#{key}: #{value.inspect}" }.join(", ")
248
+ end
249
+
250
+ def format_index_parts(options)
251
+ if options.is_a?(Hash)
252
+ "{ #{format_options(options)} }"
253
+ else
254
+ options.inspect
255
+ end
256
+ end
257
+
258
+ def remove_prefix_and_suffix(table)
259
+ prefix = Regexp.escape(@options[:table_name_prefix].to_s)
260
+ suffix = Regexp.escape(@options[:table_name_suffix].to_s)
261
+ table.sub(/\A#{prefix}(.+)#{suffix}\z/, "\\1")
262
+ end
263
+
264
+ def ignored?(table_name)
265
+ [ActiveRecord::Base.schema_migrations_table_name, ActiveRecord::Base.internal_metadata_table_name, ignore_tables].flatten.any? do |ignored|
266
+ ignored === remove_prefix_and_suffix(table_name)
267
+ end
268
+ end
269
+ end
270
+ end