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,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class Relation
5
+ module RecordFetchWarning
6
+ # When this module is prepended to ActiveRecord::Relation and
7
+ # +config.active_record.warn_on_records_fetched_greater_than+ is
8
+ # set to an integer, if the number of records a query returns is
9
+ # greater than the value of +warn_on_records_fetched_greater_than+,
10
+ # a warning is logged. This allows for the detection of queries that
11
+ # return a large number of records, which could cause memory bloat.
12
+ #
13
+ # In most cases, fetching large number of records can be performed
14
+ # efficiently using the ActiveRecord::Batches methods.
15
+ # See ActiveRecord::Batches for more information.
16
+ def exec_queries
17
+ QueryRegistry.reset
18
+
19
+ super.tap do
20
+ if logger && warn_on_records_fetched_greater_than
21
+ if @records.length > warn_on_records_fetched_greater_than
22
+ logger.warn "Query fetched #{@records.size} #{@klass} records: #{QueryRegistry.queries.join(";")}"
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ # :stopdoc:
29
+ ActiveSupport::Notifications.subscribe("sql.active_record") do |*, payload|
30
+ QueryRegistry.queries << payload[:sql]
31
+ end
32
+ # :startdoc:
33
+
34
+ class QueryRegistry # :nodoc:
35
+ extend ActiveSupport::PerThreadRegistry
36
+
37
+ attr_reader :queries
38
+
39
+ def initialize
40
+ @queries = []
41
+ end
42
+
43
+ def reset
44
+ @queries.clear
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ ActiveRecord::Relation.prepend ActiveRecord::Relation::RecordFetchWarning
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash/except"
4
+ require "active_support/core_ext/hash/slice"
5
+ require "active_record/relation/merger"
6
+
7
+ module ActiveRecord
8
+ module SpawnMethods
9
+ # This is overridden by Associations::CollectionProxy
10
+ def spawn #:nodoc:
11
+ already_in_scope? ? klass.all : clone
12
+ end
13
+
14
+ # Merges in the conditions from <tt>other</tt>, if <tt>other</tt> is an ActiveRecord::Relation.
15
+ # Returns an array representing the intersection of the resulting records with <tt>other</tt>, if <tt>other</tt> is an array.
16
+ #
17
+ # Post.where(published: true).joins(:comments).merge( Comment.where(spam: false) )
18
+ # # Performs a single join query with both where conditions.
19
+ #
20
+ # recent_posts = Post.order('created_at DESC').first(5)
21
+ # Post.where(published: true).merge(recent_posts)
22
+ # # Returns the intersection of all published posts with the 5 most recently created posts.
23
+ # # (This is just an example. You'd probably want to do this with a single query!)
24
+ #
25
+ # Procs will be evaluated by merge:
26
+ #
27
+ # Post.where(published: true).merge(-> { joins(:comments) })
28
+ # # => Post.where(published: true).joins(:comments)
29
+ #
30
+ # This is mainly intended for sharing common conditions between multiple associations.
31
+ def merge(other)
32
+ if other.is_a?(Array)
33
+ records & other
34
+ elsif other
35
+ spawn.merge!(other)
36
+ else
37
+ raise ArgumentError, "invalid argument: #{other.inspect}."
38
+ end
39
+ end
40
+
41
+ def merge!(other) # :nodoc:
42
+ if other.is_a?(Hash)
43
+ Relation::HashMerger.new(self, other).merge
44
+ elsif other.is_a?(Relation)
45
+ Relation::Merger.new(self, other).merge
46
+ elsif other.respond_to?(:to_proc)
47
+ instance_exec(&other)
48
+ else
49
+ raise ArgumentError, "#{other.inspect} is not an ActiveRecord::Relation"
50
+ end
51
+ end
52
+
53
+ # Removes from the query the condition(s) specified in +skips+.
54
+ #
55
+ # Post.order('id asc').except(:order) # discards the order condition
56
+ # Post.where('id > 10').order('id asc').except(:where) # discards the where condition but keeps the order
57
+ def except(*skips)
58
+ relation_with values.except(*skips)
59
+ end
60
+
61
+ # Removes any condition from the query other than the one(s) specified in +onlies+.
62
+ #
63
+ # Post.order('id asc').only(:where) # discards the order condition
64
+ # Post.order('id asc').only(:where, :order) # uses the specified order
65
+ def only(*onlies)
66
+ relation_with values.slice(*onlies)
67
+ end
68
+
69
+ private
70
+
71
+ def relation_with(values)
72
+ result = Relation.create(klass, values: values)
73
+ result.extend(*extending_values) if extending_values.any?
74
+ result
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,190 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class Relation
5
+ class WhereClause # :nodoc:
6
+ delegate :any?, :empty?, to: :predicates
7
+
8
+ def initialize(predicates)
9
+ @predicates = predicates
10
+ end
11
+
12
+ def +(other)
13
+ WhereClause.new(
14
+ predicates + other.predicates,
15
+ )
16
+ end
17
+
18
+ def -(other)
19
+ WhereClause.new(
20
+ predicates - other.predicates,
21
+ )
22
+ end
23
+
24
+ def merge(other)
25
+ WhereClause.new(
26
+ predicates_unreferenced_by(other) + other.predicates,
27
+ )
28
+ end
29
+
30
+ def except(*columns)
31
+ WhereClause.new(except_predicates(columns))
32
+ end
33
+
34
+ def or(other)
35
+ left = self - other
36
+ common = self - left
37
+ right = other - common
38
+
39
+ if left.empty? || right.empty?
40
+ common
41
+ else
42
+ or_clause = WhereClause.new(
43
+ [left.ast.or(right.ast)],
44
+ )
45
+ common + or_clause
46
+ end
47
+ end
48
+
49
+ def to_h(table_name = nil)
50
+ equalities = equalities(predicates)
51
+ if table_name
52
+ equalities = equalities.select do |node|
53
+ node.left.relation.name == table_name
54
+ end
55
+ end
56
+
57
+ equalities.map { |node|
58
+ name = node.left.name.to_s
59
+ value = extract_node_value(node.right)
60
+ [name, value]
61
+ }.to_h
62
+ end
63
+
64
+ def ast
65
+ Arel::Nodes::And.new(predicates_with_wrapped_sql_literals)
66
+ end
67
+
68
+ def ==(other)
69
+ other.is_a?(WhereClause) &&
70
+ predicates == other.predicates
71
+ end
72
+
73
+ def invert(as = :nand)
74
+ if predicates.size == 1
75
+ inverted_predicates = [ invert_predicate(predicates.first) ]
76
+ elsif as == :nor
77
+ inverted_predicates = predicates.map { |node| invert_predicate(node) }
78
+ else
79
+ inverted_predicates = [ Arel::Nodes::Not.new(ast) ]
80
+ end
81
+
82
+ WhereClause.new(inverted_predicates)
83
+ end
84
+
85
+ def self.empty
86
+ @empty ||= new([])
87
+ end
88
+
89
+ protected
90
+
91
+ attr_reader :predicates
92
+
93
+ def referenced_columns
94
+ @referenced_columns ||= begin
95
+ equality_nodes = predicates.select { |n| equality_node?(n) }
96
+ Set.new(equality_nodes, &:left)
97
+ end
98
+ end
99
+
100
+ private
101
+ def equalities(predicates)
102
+ equalities = []
103
+
104
+ predicates.each do |node|
105
+ case node
106
+ when Arel::Nodes::Equality
107
+ equalities << node
108
+ when Arel::Nodes::And
109
+ equalities.concat equalities(node.children)
110
+ end
111
+ end
112
+
113
+ equalities
114
+ end
115
+
116
+ def predicates_unreferenced_by(other)
117
+ predicates.reject do |n|
118
+ equality_node?(n) && other.referenced_columns.include?(n.left)
119
+ end
120
+ end
121
+
122
+ def equality_node?(node)
123
+ node.respond_to?(:operator) && node.operator == :==
124
+ end
125
+
126
+ def invert_predicate(node)
127
+ case node
128
+ when NilClass
129
+ raise ArgumentError, "Invalid argument for .where.not(), got nil."
130
+ when Arel::Nodes::In
131
+ Arel::Nodes::NotIn.new(node.left, node.right)
132
+ when Arel::Nodes::IsNotDistinctFrom
133
+ Arel::Nodes::IsDistinctFrom.new(node.left, node.right)
134
+ when Arel::Nodes::IsDistinctFrom
135
+ Arel::Nodes::IsNotDistinctFrom.new(node.left, node.right)
136
+ when Arel::Nodes::Equality
137
+ Arel::Nodes::NotEqual.new(node.left, node.right)
138
+ when String
139
+ Arel::Nodes::Not.new(Arel::Nodes::SqlLiteral.new(node))
140
+ else
141
+ Arel::Nodes::Not.new(node)
142
+ end
143
+ end
144
+
145
+ def except_predicates(columns)
146
+ predicates.reject do |node|
147
+ Arel.fetch_attribute(node) { |attr| columns.include?(attr.name.to_s) }
148
+ end
149
+ end
150
+
151
+ def predicates_with_wrapped_sql_literals
152
+ non_empty_predicates.map do |node|
153
+ case node
154
+ when Arel::Nodes::SqlLiteral, ::String
155
+ wrap_sql_literal(node)
156
+ else node
157
+ end
158
+ end
159
+ end
160
+
161
+ ARRAY_WITH_EMPTY_STRING = [""]
162
+ def non_empty_predicates
163
+ predicates - ARRAY_WITH_EMPTY_STRING
164
+ end
165
+
166
+ def wrap_sql_literal(node)
167
+ if ::String === node
168
+ node = Arel.sql(node)
169
+ end
170
+ Arel::Nodes::Grouping.new(node)
171
+ end
172
+
173
+ def extract_node_value(node)
174
+ case node
175
+ when Array
176
+ node.map { |v| extract_node_value(v) }
177
+ when Arel::Nodes::Casted, Arel::Nodes::Quoted
178
+ node.val
179
+ when Arel::Nodes::BindParam
180
+ value = node.value
181
+ if value.respond_to?(:value_before_type_cast)
182
+ value.value_before_type_cast
183
+ else
184
+ value
185
+ end
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class Relation
5
+ class WhereClauseFactory # :nodoc:
6
+ def initialize(klass, predicate_builder)
7
+ @klass = klass
8
+ @predicate_builder = predicate_builder
9
+ end
10
+
11
+ def build(opts, other)
12
+ case opts
13
+ when String, Array
14
+ parts = [klass.sanitize_sql(other.empty? ? opts : ([opts] + other))]
15
+ when Hash
16
+ attributes = predicate_builder.resolve_column_aliases(opts)
17
+ attributes.stringify_keys!
18
+
19
+ parts = predicate_builder.build_from_hash(attributes)
20
+ when Arel::Nodes::Node
21
+ parts = [opts]
22
+ else
23
+ raise ArgumentError, "Unsupported argument type: #{opts} (#{opts.class})"
24
+ end
25
+
26
+ WhereClause.new(parts)
27
+ end
28
+
29
+ private
30
+ attr_reader :klass, :predicate_builder
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,168 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ ###
5
+ # This class encapsulates a result returned from calling
6
+ # {#exec_query}[rdoc-ref:ConnectionAdapters::DatabaseStatements#exec_query]
7
+ # on any database connection adapter. For example:
8
+ #
9
+ # result = ActiveRecord::Base.connection.exec_query('SELECT id, title, body FROM posts')
10
+ # result # => #<ActiveRecord::Result:0xdeadbeef>
11
+ #
12
+ # # Get the column names of the result:
13
+ # result.columns
14
+ # # => ["id", "title", "body"]
15
+ #
16
+ # # Get the record values of the result:
17
+ # result.rows
18
+ # # => [[1, "title_1", "body_1"],
19
+ # [2, "title_2", "body_2"],
20
+ # ...
21
+ # ]
22
+ #
23
+ # # Get an array of hashes representing the result (column => value):
24
+ # result.to_a
25
+ # # => [{"id" => 1, "title" => "title_1", "body" => "body_1"},
26
+ # {"id" => 2, "title" => "title_2", "body" => "body_2"},
27
+ # ...
28
+ # ]
29
+ #
30
+ # # ActiveRecord::Result also includes Enumerable.
31
+ # result.each do |row|
32
+ # puts row['title'] + " " + row['body']
33
+ # end
34
+ class Result
35
+ include Enumerable
36
+
37
+ attr_reader :columns, :rows, :column_types
38
+
39
+ def initialize(columns, rows, column_types = {})
40
+ @columns = columns
41
+ @rows = rows
42
+ @hash_rows = nil
43
+ @column_types = column_types
44
+ end
45
+
46
+ # Returns true if this result set includes the column named +name+
47
+ def includes_column?(name)
48
+ @columns.include? name
49
+ end
50
+
51
+ # Returns the number of elements in the rows array.
52
+ def length
53
+ @rows.length
54
+ end
55
+
56
+ # Calls the given block once for each element in row collection, passing
57
+ # row as parameter.
58
+ #
59
+ # Returns an +Enumerator+ if no block is given.
60
+ def each
61
+ if block_given?
62
+ hash_rows.each { |row| yield row }
63
+ else
64
+ hash_rows.to_enum { @rows.size }
65
+ end
66
+ end
67
+
68
+ def to_hash
69
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
70
+ `ActiveRecord::Result#to_hash` has been renamed to `to_a`.
71
+ `to_hash` is deprecated and will be removed in Rails 6.1.
72
+ MSG
73
+ to_a
74
+ end
75
+
76
+ alias :map! :map
77
+ alias :collect! :map
78
+
79
+ # Returns true if there are no records, otherwise false.
80
+ def empty?
81
+ rows.empty?
82
+ end
83
+
84
+ # Returns an array of hashes representing each row record.
85
+ def to_ary
86
+ hash_rows
87
+ end
88
+
89
+ alias :to_a :to_ary
90
+
91
+ def [](idx)
92
+ hash_rows[idx]
93
+ end
94
+
95
+ # Returns the first record from the rows collection.
96
+ # If the rows collection is empty, returns +nil+.
97
+ def first
98
+ return nil if @rows.empty?
99
+ Hash[@columns.zip(@rows.first)]
100
+ end
101
+
102
+ # Returns the last record from the rows collection.
103
+ # If the rows collection is empty, returns +nil+.
104
+ def last
105
+ return nil if @rows.empty?
106
+ Hash[@columns.zip(@rows.last)]
107
+ end
108
+
109
+ def cast_values(type_overrides = {}) # :nodoc:
110
+ if columns.one?
111
+ # Separated to avoid allocating an array per row
112
+
113
+ type = column_type(columns.first, type_overrides)
114
+
115
+ rows.map do |(value)|
116
+ type.deserialize(value)
117
+ end
118
+ else
119
+ types = columns.map { |name| column_type(name, type_overrides) }
120
+
121
+ rows.map do |values|
122
+ Array.new(values.size) { |i| types[i].deserialize(values[i]) }
123
+ end
124
+ end
125
+ end
126
+
127
+ def initialize_copy(other)
128
+ @columns = columns.dup
129
+ @rows = rows.dup
130
+ @column_types = column_types.dup
131
+ @hash_rows = nil
132
+ end
133
+
134
+ private
135
+
136
+ def column_type(name, type_overrides = {})
137
+ type_overrides.fetch(name) do
138
+ column_types.fetch(name, Type.default_value)
139
+ end
140
+ end
141
+
142
+ def hash_rows
143
+ @hash_rows ||=
144
+ begin
145
+ # We freeze the strings to prevent them getting duped when
146
+ # used as keys in ActiveRecord::Base's @attributes hash
147
+ columns = @columns.map(&:-@)
148
+ length = columns.length
149
+
150
+ @rows.map { |row|
151
+ # In the past we used Hash[columns.zip(row)]
152
+ # though elegant, the verbose way is much more efficient
153
+ # both time and memory wise cause it avoids a big array allocation
154
+ # this method is called a lot and needs to be micro optimised
155
+ hash = {}
156
+
157
+ index = 0
158
+ while index < length
159
+ hash[columns[index]] = row[index]
160
+ index += 1
161
+ end
162
+
163
+ hash
164
+ }
165
+ end
166
+ end
167
+ end
168
+ end