activerecord 4.2.0 → 6.1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (374) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1221 -796
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +15 -14
  5. data/examples/performance.rb +33 -32
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/aggregations.rb +267 -249
  8. data/lib/active_record/association_relation.rb +45 -7
  9. data/lib/active_record/associations/alias_tracker.rb +40 -43
  10. data/lib/active_record/associations/association.rb +172 -67
  11. data/lib/active_record/associations/association_scope.rb +105 -129
  12. data/lib/active_record/associations/belongs_to_association.rb +85 -59
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
  14. data/lib/active_record/associations/builder/association.rb +57 -43
  15. data/lib/active_record/associations/builder/belongs_to.rb +74 -57
  16. data/lib/active_record/associations/builder/collection_association.rb +15 -33
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +57 -70
  18. data/lib/active_record/associations/builder/has_many.rb +13 -5
  19. data/lib/active_record/associations/builder/has_one.rb +44 -6
  20. data/lib/active_record/associations/builder/singular_association.rb +16 -10
  21. data/lib/active_record/associations/collection_association.rb +168 -279
  22. data/lib/active_record/associations/collection_proxy.rb +263 -155
  23. data/lib/active_record/associations/foreign_association.rb +33 -0
  24. data/lib/active_record/associations/has_many_association.rb +57 -84
  25. data/lib/active_record/associations/has_many_through_association.rb +70 -82
  26. data/lib/active_record/associations/has_one_association.rb +74 -47
  27. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  28. data/lib/active_record/associations/join_dependency/join_association.rb +54 -73
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  31. data/lib/active_record/associations/join_dependency.rb +175 -164
  32. data/lib/active_record/associations/preloader/association.rb +107 -112
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  34. data/lib/active_record/associations/preloader.rb +99 -96
  35. data/lib/active_record/associations/singular_association.rb +18 -45
  36. data/lib/active_record/associations/through_association.rb +49 -24
  37. data/lib/active_record/associations.rb +1845 -1597
  38. data/lib/active_record/attribute_assignment.rb +59 -185
  39. data/lib/active_record/attribute_methods/before_type_cast.rb +20 -7
  40. data/lib/active_record/attribute_methods/dirty.rb +168 -138
  41. data/lib/active_record/attribute_methods/primary_key.rb +93 -83
  42. data/lib/active_record/attribute_methods/query.rb +8 -10
  43. data/lib/active_record/attribute_methods/read.rb +19 -79
  44. data/lib/active_record/attribute_methods/serialization.rb +49 -24
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +59 -36
  46. data/lib/active_record/attribute_methods/write.rb +25 -56
  47. data/lib/active_record/attribute_methods.rb +153 -162
  48. data/lib/active_record/attributes.rb +234 -70
  49. data/lib/active_record/autosave_association.rb +157 -69
  50. data/lib/active_record/base.rb +49 -50
  51. data/lib/active_record/callbacks.rb +234 -79
  52. data/lib/active_record/coders/json.rb +3 -1
  53. data/lib/active_record/coders/yaml_column.rb +46 -13
  54. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -317
  55. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
  56. data/lib/active_record/connection_adapters/abstract/database_statements.rb +301 -113
  57. data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
  58. data/lib/active_record/connection_adapters/abstract/quoting.rb +187 -60
  59. data/lib/active_record/connection_adapters/abstract/savepoints.rb +9 -7
  60. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
  61. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +485 -253
  62. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  63. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +909 -263
  64. data/lib/active_record/connection_adapters/abstract/transaction.rb +254 -92
  65. data/lib/active_record/connection_adapters/abstract_adapter.rb +492 -221
  66. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +580 -608
  67. data/lib/active_record/connection_adapters/column.rb +67 -40
  68. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  69. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  70. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  71. data/lib/active_record/connection_adapters/mysql/database_statements.rb +196 -0
  72. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
  73. data/lib/active_record/connection_adapters/mysql/quoting.rb +96 -0
  74. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +97 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +103 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +91 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +271 -0
  78. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
  79. data/lib/active_record/connection_adapters/mysql2_adapter.rb +81 -199
  80. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  81. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +44 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +78 -161
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -57
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +5 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +8 -6
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +17 -13
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +6 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -20
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  98. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  101. data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +67 -51
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  109. data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -25
  110. data/lib/active_record/connection_adapters/postgresql/quoting.rb +171 -48
  111. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  112. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
  114. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
  115. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +499 -293
  116. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
  117. data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
  118. data/lib/active_record/connection_adapters/postgresql_adapter.rb +595 -382
  119. data/lib/active_record/connection_adapters/schema_cache.rb +191 -29
  120. data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
  121. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
  122. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  123. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +21 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  126. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  127. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
  128. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +322 -389
  129. data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
  130. data/lib/active_record/connection_adapters.rb +52 -0
  131. data/lib/active_record/connection_handling.rb +314 -41
  132. data/lib/active_record/core.rb +488 -243
  133. data/lib/active_record/counter_cache.rb +71 -50
  134. data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
  135. data/lib/active_record/database_configurations/database_config.rb +80 -0
  136. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  137. data/lib/active_record/database_configurations/url_config.rb +53 -0
  138. data/lib/active_record/database_configurations.rb +273 -0
  139. data/lib/active_record/delegated_type.rb +209 -0
  140. data/lib/active_record/destroy_association_async_job.rb +36 -0
  141. data/lib/active_record/dynamic_matchers.rb +87 -106
  142. data/lib/active_record/enum.rb +212 -94
  143. data/lib/active_record/errors.rb +225 -54
  144. data/lib/active_record/explain.rb +27 -11
  145. data/lib/active_record/explain_registry.rb +4 -2
  146. data/lib/active_record/explain_subscriber.rb +11 -6
  147. data/lib/active_record/fixture_set/file.rb +33 -14
  148. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  149. data/lib/active_record/fixture_set/render_context.rb +17 -0
  150. data/lib/active_record/fixture_set/table_row.rb +152 -0
  151. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  152. data/lib/active_record/fixtures.rb +273 -496
  153. data/lib/active_record/gem_version.rb +6 -4
  154. data/lib/active_record/inheritance.rb +175 -110
  155. data/lib/active_record/insert_all.rb +212 -0
  156. data/lib/active_record/integration.rb +121 -29
  157. data/lib/active_record/internal_metadata.rb +64 -0
  158. data/lib/active_record/legacy_yaml_adapter.rb +52 -0
  159. data/lib/active_record/locale/en.yml +3 -2
  160. data/lib/active_record/locking/optimistic.rb +103 -95
  161. data/lib/active_record/locking/pessimistic.rb +22 -6
  162. data/lib/active_record/log_subscriber.rb +93 -31
  163. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  164. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  165. data/lib/active_record/middleware/database_selector.rb +77 -0
  166. data/lib/active_record/migration/command_recorder.rb +185 -90
  167. data/lib/active_record/migration/compatibility.rb +298 -0
  168. data/lib/active_record/migration/join_table.rb +8 -7
  169. data/lib/active_record/migration.rb +685 -309
  170. data/lib/active_record/model_schema.rb +420 -113
  171. data/lib/active_record/nested_attributes.rb +265 -216
  172. data/lib/active_record/no_touching.rb +15 -2
  173. data/lib/active_record/null_relation.rb +24 -38
  174. data/lib/active_record/persistence.rb +574 -135
  175. data/lib/active_record/query_cache.rb +29 -23
  176. data/lib/active_record/querying.rb +50 -31
  177. data/lib/active_record/railtie.rb +175 -54
  178. data/lib/active_record/railties/console_sandbox.rb +3 -3
  179. data/lib/active_record/railties/controller_runtime.rb +34 -33
  180. data/lib/active_record/railties/databases.rake +533 -216
  181. data/lib/active_record/readonly_attributes.rb +9 -4
  182. data/lib/active_record/reflection.rb +485 -310
  183. data/lib/active_record/relation/batches/batch_enumerator.rb +85 -0
  184. data/lib/active_record/relation/batches.rb +217 -59
  185. data/lib/active_record/relation/calculations.rb +326 -244
  186. data/lib/active_record/relation/delegation.rb +76 -84
  187. data/lib/active_record/relation/finder_methods.rb +318 -256
  188. data/lib/active_record/relation/from_clause.rb +30 -0
  189. data/lib/active_record/relation/merger.rb +99 -84
  190. data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -25
  191. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
  192. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  193. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +57 -0
  194. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  195. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  196. data/lib/active_record/relation/predicate_builder.rb +139 -96
  197. data/lib/active_record/relation/query_attribute.rb +50 -0
  198. data/lib/active_record/relation/query_methods.rb +757 -409
  199. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  200. data/lib/active_record/relation/spawn_methods.rb +23 -21
  201. data/lib/active_record/relation/where_clause.rb +239 -0
  202. data/lib/active_record/relation.rb +554 -342
  203. data/lib/active_record/result.rb +91 -47
  204. data/lib/active_record/runtime_registry.rb +6 -4
  205. data/lib/active_record/sanitization.rb +134 -122
  206. data/lib/active_record/schema.rb +21 -24
  207. data/lib/active_record/schema_dumper.rb +141 -92
  208. data/lib/active_record/schema_migration.rb +24 -26
  209. data/lib/active_record/scoping/default.rb +96 -82
  210. data/lib/active_record/scoping/named.rb +78 -36
  211. data/lib/active_record/scoping.rb +45 -27
  212. data/lib/active_record/secure_token.rb +48 -0
  213. data/lib/active_record/serialization.rb +8 -6
  214. data/lib/active_record/signed_id.rb +116 -0
  215. data/lib/active_record/statement_cache.rb +89 -36
  216. data/lib/active_record/store.rb +133 -43
  217. data/lib/active_record/suppressor.rb +61 -0
  218. data/lib/active_record/table_metadata.rb +81 -0
  219. data/lib/active_record/tasks/database_tasks.rb +366 -129
  220. data/lib/active_record/tasks/mysql_database_tasks.rb +68 -100
  221. data/lib/active_record/tasks/postgresql_database_tasks.rb +87 -39
  222. data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -19
  223. data/lib/active_record/test_databases.rb +24 -0
  224. data/lib/active_record/test_fixtures.rb +291 -0
  225. data/lib/active_record/timestamp.rb +86 -43
  226. data/lib/active_record/touch_later.rb +65 -0
  227. data/lib/active_record/transactions.rb +181 -152
  228. data/lib/active_record/translation.rb +3 -1
  229. data/lib/active_record/type/adapter_specific_registry.rb +126 -0
  230. data/lib/active_record/type/date.rb +4 -41
  231. data/lib/active_record/type/date_time.rb +4 -38
  232. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  233. data/lib/active_record/type/hash_lookup_type_map.rb +12 -5
  234. data/lib/active_record/type/internal/timezone.rb +17 -0
  235. data/lib/active_record/type/json.rb +30 -0
  236. data/lib/active_record/type/serialized.rb +33 -15
  237. data/lib/active_record/type/text.rb +2 -2
  238. data/lib/active_record/type/time.rb +21 -16
  239. data/lib/active_record/type/type_map.rb +16 -19
  240. data/lib/active_record/type/unsigned_integer.rb +9 -8
  241. data/lib/active_record/type.rb +84 -23
  242. data/lib/active_record/type_caster/connection.rb +33 -0
  243. data/lib/active_record/type_caster/map.rb +23 -0
  244. data/lib/active_record/type_caster.rb +9 -0
  245. data/lib/active_record/validations/absence.rb +25 -0
  246. data/lib/active_record/validations/associated.rb +12 -4
  247. data/lib/active_record/validations/length.rb +26 -0
  248. data/lib/active_record/validations/numericality.rb +35 -0
  249. data/lib/active_record/validations/presence.rb +14 -13
  250. data/lib/active_record/validations/uniqueness.rb +65 -48
  251. data/lib/active_record/validations.rb +39 -35
  252. data/lib/active_record/version.rb +3 -1
  253. data/lib/active_record.rb +44 -28
  254. data/lib/arel/alias_predication.rb +9 -0
  255. data/lib/arel/attributes/attribute.rb +41 -0
  256. data/lib/arel/collectors/bind.rb +29 -0
  257. data/lib/arel/collectors/composite.rb +39 -0
  258. data/lib/arel/collectors/plain_string.rb +20 -0
  259. data/lib/arel/collectors/sql_string.rb +27 -0
  260. data/lib/arel/collectors/substitute_binds.rb +35 -0
  261. data/lib/arel/crud.rb +42 -0
  262. data/lib/arel/delete_manager.rb +18 -0
  263. data/lib/arel/errors.rb +9 -0
  264. data/lib/arel/expressions.rb +29 -0
  265. data/lib/arel/factory_methods.rb +49 -0
  266. data/lib/arel/insert_manager.rb +49 -0
  267. data/lib/arel/math.rb +45 -0
  268. data/lib/arel/nodes/and.rb +32 -0
  269. data/lib/arel/nodes/ascending.rb +23 -0
  270. data/lib/arel/nodes/binary.rb +126 -0
  271. data/lib/arel/nodes/bind_param.rb +44 -0
  272. data/lib/arel/nodes/case.rb +55 -0
  273. data/lib/arel/nodes/casted.rb +62 -0
  274. data/lib/arel/nodes/comment.rb +29 -0
  275. data/lib/arel/nodes/count.rb +12 -0
  276. data/lib/arel/nodes/delete_statement.rb +45 -0
  277. data/lib/arel/nodes/descending.rb +23 -0
  278. data/lib/arel/nodes/equality.rb +15 -0
  279. data/lib/arel/nodes/extract.rb +24 -0
  280. data/lib/arel/nodes/false.rb +16 -0
  281. data/lib/arel/nodes/full_outer_join.rb +8 -0
  282. data/lib/arel/nodes/function.rb +44 -0
  283. data/lib/arel/nodes/grouping.rb +11 -0
  284. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  285. data/lib/arel/nodes/in.rb +15 -0
  286. data/lib/arel/nodes/infix_operation.rb +92 -0
  287. data/lib/arel/nodes/inner_join.rb +8 -0
  288. data/lib/arel/nodes/insert_statement.rb +37 -0
  289. data/lib/arel/nodes/join_source.rb +20 -0
  290. data/lib/arel/nodes/matches.rb +18 -0
  291. data/lib/arel/nodes/named_function.rb +23 -0
  292. data/lib/arel/nodes/node.rb +51 -0
  293. data/lib/arel/nodes/node_expression.rb +13 -0
  294. data/lib/arel/nodes/ordering.rb +27 -0
  295. data/lib/arel/nodes/outer_join.rb +8 -0
  296. data/lib/arel/nodes/over.rb +15 -0
  297. data/lib/arel/nodes/regexp.rb +16 -0
  298. data/lib/arel/nodes/right_outer_join.rb +8 -0
  299. data/lib/arel/nodes/select_core.rb +67 -0
  300. data/lib/arel/nodes/select_statement.rb +41 -0
  301. data/lib/arel/nodes/sql_literal.rb +19 -0
  302. data/lib/arel/nodes/string_join.rb +11 -0
  303. data/lib/arel/nodes/table_alias.rb +31 -0
  304. data/lib/arel/nodes/terminal.rb +16 -0
  305. data/lib/arel/nodes/true.rb +16 -0
  306. data/lib/arel/nodes/unary.rb +44 -0
  307. data/lib/arel/nodes/unary_operation.rb +20 -0
  308. data/lib/arel/nodes/unqualified_column.rb +22 -0
  309. data/lib/arel/nodes/update_statement.rb +41 -0
  310. data/lib/arel/nodes/values_list.rb +9 -0
  311. data/lib/arel/nodes/window.rb +126 -0
  312. data/lib/arel/nodes/with.rb +11 -0
  313. data/lib/arel/nodes.rb +70 -0
  314. data/lib/arel/order_predications.rb +13 -0
  315. data/lib/arel/predications.rb +250 -0
  316. data/lib/arel/select_manager.rb +270 -0
  317. data/lib/arel/table.rb +118 -0
  318. data/lib/arel/tree_manager.rb +72 -0
  319. data/lib/arel/update_manager.rb +34 -0
  320. data/lib/arel/visitors/dot.rb +308 -0
  321. data/lib/arel/visitors/mysql.rb +93 -0
  322. data/lib/arel/visitors/postgresql.rb +120 -0
  323. data/lib/arel/visitors/sqlite.rb +38 -0
  324. data/lib/arel/visitors/to_sql.rb +899 -0
  325. data/lib/arel/visitors/visitor.rb +45 -0
  326. data/lib/arel/visitors.rb +13 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/arel.rb +54 -0
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  330. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  331. data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -37
  332. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +26 -0
  333. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +13 -10
  334. data/lib/rails/generators/active_record/migration.rb +35 -1
  335. data/lib/rails/generators/active_record/model/model_generator.rb +55 -22
  336. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  337. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  338. data/lib/rails/generators/active_record.rb +7 -5
  339. metadata +175 -65
  340. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  341. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  342. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  343. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  344. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  345. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  346. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  347. data/lib/active_record/attribute.rb +0 -149
  348. data/lib/active_record/attribute_decorators.rb +0 -66
  349. data/lib/active_record/attribute_set/builder.rb +0 -86
  350. data/lib/active_record/attribute_set.rb +0 -77
  351. data/lib/active_record/connection_adapters/connection_specification.rb +0 -275
  352. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  353. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  354. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  355. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  356. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  357. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  358. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  359. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  360. data/lib/active_record/type/big_integer.rb +0 -13
  361. data/lib/active_record/type/binary.rb +0 -50
  362. data/lib/active_record/type/boolean.rb +0 -30
  363. data/lib/active_record/type/decimal.rb +0 -40
  364. data/lib/active_record/type/decorator.rb +0 -14
  365. data/lib/active_record/type/float.rb +0 -19
  366. data/lib/active_record/type/integer.rb +0 -55
  367. data/lib/active_record/type/mutable.rb +0 -16
  368. data/lib/active_record/type/numeric.rb +0 -36
  369. data/lib/active_record/type/string.rb +0 -36
  370. data/lib/active_record/type/time_value.rb +0 -38
  371. data/lib/active_record/type/value.rb +0 -101
  372. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -22
  373. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
  374. /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/array/extract"
4
+
1
5
  module ActiveRecord
2
6
  module ConnectionAdapters
3
7
  module PostgreSQL
@@ -13,13 +17,13 @@ module ActiveRecord
13
17
  end
14
18
 
15
19
  def run(records)
16
- nodes = records.reject { |row| @store.key? row['oid'].to_i }
17
- mapped, nodes = nodes.partition { |row| @store.key? row['typname'] }
18
- ranges, nodes = nodes.partition { |row| row['typtype'] == 'r' }
19
- enums, nodes = nodes.partition { |row| row['typtype'] == 'e' }
20
- domains, nodes = nodes.partition { |row| row['typtype'] == 'd' }
21
- arrays, nodes = nodes.partition { |row| row['typinput'] == 'array_in' }
22
- composites, nodes = nodes.partition { |row| row['typelem'] != '0' }
20
+ nodes = records.reject { |row| @store.key? row["oid"].to_i }
21
+ mapped = nodes.extract! { |row| @store.key? row["typname"] }
22
+ ranges = nodes.extract! { |row| row["typtype"] == "r" }
23
+ enums = nodes.extract! { |row| row["typtype"] == "e" }
24
+ domains = nodes.extract! { |row| row["typtype"] == "d" }
25
+ arrays = nodes.extract! { |row| row["typinput"] == "array_in" }
26
+ composites = nodes.extract! { |row| row["typelem"].to_i != 0 }
23
27
 
24
28
  mapped.each { |row| register_mapped_type(row) }
25
29
  enums.each { |row| register_enum_type(row) }
@@ -29,67 +33,79 @@ module ActiveRecord
29
33
  composites.each { |row| register_composite_type(row) }
30
34
  end
31
35
 
32
- private
33
- def register_mapped_type(row)
34
- alias_type row['oid'], row['typname']
36
+ def query_conditions_for_initial_load
37
+ known_type_names = @store.keys.map { |n| "'#{n}'" }
38
+ known_type_types = %w('r' 'e' 'd')
39
+ <<~SQL % [known_type_names.join(", "), known_type_types.join(", ")]
40
+ WHERE
41
+ t.typname IN (%s)
42
+ OR t.typtype IN (%s)
43
+ OR t.typinput = 'array_in(cstring,oid,integer)'::regprocedure
44
+ OR t.typelem != 0
45
+ SQL
35
46
  end
36
47
 
37
- def register_enum_type(row)
38
- register row['oid'], OID::Enum.new
39
- end
48
+ private
49
+ def register_mapped_type(row)
50
+ alias_type row["oid"], row["typname"]
51
+ end
40
52
 
41
- def register_array_type(row)
42
- register_with_subtype(row['oid'], row['typelem'].to_i) do |subtype|
43
- OID::Array.new(subtype, row['typdelim'])
53
+ def register_enum_type(row)
54
+ register row["oid"], OID::Enum.new
44
55
  end
45
- end
46
56
 
47
- def register_range_type(row)
48
- register_with_subtype(row['oid'], row['rngsubtype'].to_i) do |subtype|
49
- OID::Range.new(subtype, row['typname'].to_sym)
57
+ def register_array_type(row)
58
+ register_with_subtype(row["oid"], row["typelem"].to_i) do |subtype|
59
+ OID::Array.new(subtype, row["typdelim"])
60
+ end
50
61
  end
51
- end
52
62
 
53
- def register_domain_type(row)
54
- if base_type = @store.lookup(row["typbasetype"].to_i)
55
- register row['oid'], base_type
56
- else
57
- warn "unknown base type (OID: #{row["typbasetype"]}) for domain #{row["typname"]}."
63
+ def register_range_type(row)
64
+ register_with_subtype(row["oid"], row["rngsubtype"].to_i) do |subtype|
65
+ OID::Range.new(subtype, row["typname"].to_sym)
66
+ end
58
67
  end
59
- end
60
68
 
61
- def register_composite_type(row)
62
- if subtype = @store.lookup(row['typelem'].to_i)
63
- register row['oid'], OID::Vector.new(row['typdelim'], subtype)
69
+ def register_domain_type(row)
70
+ if base_type = @store.lookup(row["typbasetype"].to_i)
71
+ register row["oid"], base_type
72
+ else
73
+ warn "unknown base type (OID: #{row["typbasetype"]}) for domain #{row["typname"]}."
74
+ end
64
75
  end
65
- end
66
76
 
67
- def register(oid, oid_type = nil, &block)
68
- oid = assert_valid_registration(oid, oid_type || block)
69
- if block_given?
70
- @store.register_type(oid, &block)
71
- else
72
- @store.register_type(oid, oid_type)
77
+ def register_composite_type(row)
78
+ if subtype = @store.lookup(row["typelem"].to_i)
79
+ register row["oid"], OID::Vector.new(row["typdelim"], subtype)
80
+ end
73
81
  end
74
- end
75
82
 
76
- def alias_type(oid, target)
77
- oid = assert_valid_registration(oid, target)
78
- @store.alias_type(oid, target)
79
- end
83
+ def register(oid, oid_type = nil, &block)
84
+ oid = assert_valid_registration(oid, oid_type || block)
85
+ if block_given?
86
+ @store.register_type(oid, &block)
87
+ else
88
+ @store.register_type(oid, oid_type)
89
+ end
90
+ end
80
91
 
81
- def register_with_subtype(oid, target_oid)
82
- if @store.key?(target_oid)
83
- register(oid) do |_, *args|
84
- yield @store.lookup(target_oid, *args)
92
+ def alias_type(oid, target)
93
+ oid = assert_valid_registration(oid, target)
94
+ @store.alias_type(oid, target)
95
+ end
96
+
97
+ def register_with_subtype(oid, target_oid)
98
+ if @store.key?(target_oid)
99
+ register(oid) do |_, *args|
100
+ yield @store.lookup(target_oid, *args)
101
+ end
85
102
  end
86
103
  end
87
- end
88
104
 
89
- def assert_valid_registration(oid, oid_type)
90
- raise ArgumentError, "can't register nil type for OID #{oid}" if oid_type.nil?
91
- oid.to_i
92
- end
105
+ def assert_valid_registration(oid, oid_type)
106
+ raise ArgumentError, "can't register nil type for OID #{oid}" if oid_type.nil?
107
+ oid.to_i
108
+ end
93
109
  end
94
110
  end
95
111
  end
@@ -1,19 +1,33 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
4
6
  module OID # :nodoc:
5
7
  class Uuid < Type::Value # :nodoc:
6
- ACCEPTABLE_UUID = %r{\A\{?([a-fA-F0-9]{4}-?){8}\}?\z}x
8
+ ACCEPTABLE_UUID = %r{\A(\{)?([a-fA-F0-9]{4}-?){8}(?(1)\}|)\z}
7
9
 
8
- alias_method :type_cast_for_database, :type_cast_from_database
10
+ alias :serialize :deserialize
9
11
 
10
12
  def type
11
13
  :uuid
12
14
  end
13
15
 
14
- def type_cast(value)
15
- value.to_s[ACCEPTABLE_UUID, 0]
16
+ def changed?(old_value, new_value, _new_value_before_type_cast)
17
+ old_value.class != new_value.class ||
18
+ new_value && old_value.casecmp(new_value) != 0
19
+ end
20
+
21
+ def changed_in_place?(raw_old_value, new_value)
22
+ raw_old_value.class != new_value.class ||
23
+ new_value && raw_old_value.casecmp(new_value) != 0
16
24
  end
25
+
26
+ private
27
+ def cast_value(value)
28
+ casted = value.to_s
29
+ casted if casted.match?(ACCEPTABLE_UUID)
30
+ end
17
31
  end
18
32
  end
19
33
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
@@ -16,7 +18,7 @@ module ActiveRecord
16
18
  # FIXME: this should probably split on +delim+ and use +subtype+
17
19
  # to cast the values. Unfortunately, the current Rails behavior
18
20
  # is to just return the string.
19
- def type_cast(value)
21
+ def cast(value)
20
22
  value
21
23
  end
22
24
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
@@ -7,7 +9,7 @@ module ActiveRecord
7
9
  :xml
8
10
  end
9
11
 
10
- def type_cast_for_database(value)
12
+ def serialize(value)
11
13
  return unless value
12
14
  Data.new(super)
13
15
  end
@@ -1,30 +1,30 @@
1
- require 'active_record/connection_adapters/postgresql/oid/infinity'
1
+ # frozen_string_literal: true
2
2
 
3
- require 'active_record/connection_adapters/postgresql/oid/array'
4
- require 'active_record/connection_adapters/postgresql/oid/bit'
5
- require 'active_record/connection_adapters/postgresql/oid/bit_varying'
6
- require 'active_record/connection_adapters/postgresql/oid/bytea'
7
- require 'active_record/connection_adapters/postgresql/oid/cidr'
8
- require 'active_record/connection_adapters/postgresql/oid/date'
9
- require 'active_record/connection_adapters/postgresql/oid/date_time'
10
- require 'active_record/connection_adapters/postgresql/oid/decimal'
11
- require 'active_record/connection_adapters/postgresql/oid/enum'
12
- require 'active_record/connection_adapters/postgresql/oid/float'
13
- require 'active_record/connection_adapters/postgresql/oid/hstore'
14
- require 'active_record/connection_adapters/postgresql/oid/inet'
15
- require 'active_record/connection_adapters/postgresql/oid/integer'
16
- require 'active_record/connection_adapters/postgresql/oid/json'
17
- require 'active_record/connection_adapters/postgresql/oid/jsonb'
18
- require 'active_record/connection_adapters/postgresql/oid/money'
19
- require 'active_record/connection_adapters/postgresql/oid/point'
20
- require 'active_record/connection_adapters/postgresql/oid/range'
21
- require 'active_record/connection_adapters/postgresql/oid/specialized_string'
22
- require 'active_record/connection_adapters/postgresql/oid/time'
23
- require 'active_record/connection_adapters/postgresql/oid/uuid'
24
- require 'active_record/connection_adapters/postgresql/oid/vector'
25
- require 'active_record/connection_adapters/postgresql/oid/xml'
3
+ require "active_record/connection_adapters/postgresql/oid/array"
4
+ require "active_record/connection_adapters/postgresql/oid/bit"
5
+ require "active_record/connection_adapters/postgresql/oid/bit_varying"
6
+ require "active_record/connection_adapters/postgresql/oid/bytea"
7
+ require "active_record/connection_adapters/postgresql/oid/cidr"
8
+ require "active_record/connection_adapters/postgresql/oid/date"
9
+ require "active_record/connection_adapters/postgresql/oid/date_time"
10
+ require "active_record/connection_adapters/postgresql/oid/decimal"
11
+ require "active_record/connection_adapters/postgresql/oid/enum"
12
+ require "active_record/connection_adapters/postgresql/oid/hstore"
13
+ require "active_record/connection_adapters/postgresql/oid/inet"
14
+ require "active_record/connection_adapters/postgresql/oid/interval"
15
+ require "active_record/connection_adapters/postgresql/oid/jsonb"
16
+ require "active_record/connection_adapters/postgresql/oid/macaddr"
17
+ require "active_record/connection_adapters/postgresql/oid/money"
18
+ require "active_record/connection_adapters/postgresql/oid/oid"
19
+ require "active_record/connection_adapters/postgresql/oid/point"
20
+ require "active_record/connection_adapters/postgresql/oid/legacy_point"
21
+ require "active_record/connection_adapters/postgresql/oid/range"
22
+ require "active_record/connection_adapters/postgresql/oid/specialized_string"
23
+ require "active_record/connection_adapters/postgresql/oid/uuid"
24
+ require "active_record/connection_adapters/postgresql/oid/vector"
25
+ require "active_record/connection_adapters/postgresql/oid/xml"
26
26
 
27
- require 'active_record/connection_adapters/postgresql/oid/type_map_initializer'
27
+ require "active_record/connection_adapters/postgresql/oid/type_map_initializer"
28
28
 
29
29
  module ActiveRecord
30
30
  module ConnectionAdapters
@@ -1,7 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
4
6
  module Quoting
7
+ class IntegerOutOf64BitRange < StandardError
8
+ def initialize(msg)
9
+ super(msg)
10
+ end
11
+ end
12
+
5
13
  # Escapes binary strings for bytea input to the database.
6
14
  def escape_bytea(value)
7
15
  @connection.escape_bytea(value) if value
@@ -16,7 +24,7 @@ module ActiveRecord
16
24
 
17
25
  # Quotes strings for use in SQL input.
18
26
  def quote_string(s) #:nodoc:
19
- @connection.escape(s)
27
+ PG::Connection.escape(s)
20
28
  end
21
29
 
22
30
  # Checks the following cases:
@@ -27,8 +35,13 @@ module ActiveRecord
27
35
  # - schema_name."table.name"
28
36
  # - "schema.name".table_name
29
37
  # - "schema.name"."table.name"
30
- def quote_table_name(name)
31
- Utils.extract_schema_qualified_name(name.to_s).quoted
38
+ def quote_table_name(name) # :nodoc:
39
+ self.class.quoted_table_names[name] ||= Utils.extract_schema_qualified_name(name.to_s).quoted.freeze
40
+ end
41
+
42
+ # Quotes schema names for use in SQL queries.
43
+ def quote_schema_name(name)
44
+ PG::Connection.quote_ident(name)
32
45
  end
33
46
 
34
47
  def quote_table_name_for_assignment(table, attr)
@@ -36,72 +49,182 @@ module ActiveRecord
36
49
  end
37
50
 
38
51
  # Quotes column names for use in SQL queries.
39
- def quote_column_name(name) #:nodoc:
40
- PGconn.quote_ident(name.to_s)
52
+ def quote_column_name(name) # :nodoc:
53
+ self.class.quoted_column_names[name] ||= PG::Connection.quote_ident(super).freeze
41
54
  end
42
55
 
43
- # Quote date/time values for use in SQL input. Includes microseconds
44
- # if the value is a Time responding to usec.
56
+ # Quote date/time values for use in SQL input.
45
57
  def quoted_date(value) #:nodoc:
46
- result = super
47
- if value.acts_like?(:time) && value.respond_to?(:usec)
48
- result = "#{result}.#{sprintf("%06d", value.usec)}"
49
- end
50
-
51
58
  if value.year <= 0
52
59
  bce_year = format("%04d", -value.year + 1)
53
- result = result.sub(/^-?\d+/, bce_year) + " BC"
60
+ super.sub(/^-?\d+/, bce_year) + " BC"
61
+ else
62
+ super
54
63
  end
55
- result
56
64
  end
57
65
 
58
- # Does not quote function default values for UUID columns
59
- def quote_default_value(value, column) #:nodoc:
60
- if column.type == :uuid && value =~ /\(\)/
61
- value
66
+ def quoted_binary(value) # :nodoc:
67
+ "'#{escape_bytea(value.to_s)}'"
68
+ end
69
+
70
+ def quote_default_expression(value, column) # :nodoc:
71
+ if value.is_a?(Proc)
72
+ value.call
73
+ elsif column.type == :uuid && value.is_a?(String) && /\(\)/.match?(value)
74
+ value # Does not quote function default values for UUID columns
75
+ elsif column.respond_to?(:array?)
76
+ type = lookup_cast_type_from_column(column)
77
+ quote(type.serialize(value))
62
78
  else
63
- quote(value, column)
79
+ super
64
80
  end
65
81
  end
66
82
 
83
+ def lookup_cast_type_from_column(column) # :nodoc:
84
+ type_map.lookup(column.oid, column.fmod, column.sql_type)
85
+ end
86
+
87
+ def column_name_matcher
88
+ COLUMN_NAME
89
+ end
90
+
91
+ def column_name_with_order_matcher
92
+ COLUMN_NAME_WITH_ORDER
93
+ end
94
+
95
+ COLUMN_NAME = /
96
+ \A
97
+ (
98
+ (?:
99
+ # "table_name"."column_name"::type_name | function(one or no argument)::type_name
100
+ ((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")(?:::\w+)?) | \w+\((?:|\g<2>)\)(?:::\w+)?
101
+ )
102
+ (?:(?:\s+AS)?\s+(?:\w+|"\w+"))?
103
+ )
104
+ (?:\s*,\s*\g<1>)*
105
+ \z
106
+ /ix
107
+
108
+ COLUMN_NAME_WITH_ORDER = /
109
+ \A
110
+ (
111
+ (?:
112
+ # "table_name"."column_name"::type_name | function(one or no argument)::type_name
113
+ ((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")(?:::\w+)?) | \w+\((?:|\g<2>)\)(?:::\w+)?
114
+ )
115
+ (?:\s+ASC|\s+DESC)?
116
+ (?:\s+NULLS\s+(?:FIRST|LAST))?
117
+ )
118
+ (?:\s*,\s*\g<1>)*
119
+ \z
120
+ /ix
121
+
122
+ private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
123
+
67
124
  private
125
+ def lookup_cast_type(sql_type)
126
+ super(query_value("SELECT #{quote(sql_type)}::regtype::oid", "SCHEMA").to_i)
127
+ end
128
+
129
+ def check_int_in_range(value)
130
+ if value.to_int > 9223372036854775807 || value.to_int < -9223372036854775808
131
+ exception = <<~ERROR
132
+ Provided value outside of the range of a signed 64bit integer.
133
+
134
+ PostgreSQL will treat the column type in question as a numeric.
135
+ This may result in a slow sequential scan due to a comparison
136
+ being performed between an integer or bigint value and a numeric value.
137
+
138
+ To allow for this potentially unwanted behavior, set
139
+ ActiveRecord::Base.raise_int_wider_than_64bit to false.
140
+ ERROR
141
+ raise IntegerOutOf64BitRange.new exception
142
+ end
143
+ end
68
144
 
69
- def _quote(value)
70
- case value
71
- when Type::Binary::Data
72
- "'#{escape_bytea(value.to_s)}'"
73
- when OID::Xml::Data
74
- "xml '#{quote_string(value.to_s)}'"
75
- when OID::Bit::Data
76
- if value.binary?
77
- "B'#{value}'"
78
- elsif value.hex?
79
- "X'#{value}'"
145
+ def _quote(value)
146
+ if ActiveRecord::Base.raise_int_wider_than_64bit && value.is_a?(Integer)
147
+ check_int_in_range(value)
80
148
  end
81
- when Float
82
- if value.infinite? || value.nan?
83
- "'#{value}'"
149
+
150
+ case value
151
+ when OID::Xml::Data
152
+ "xml '#{quote_string(value.to_s)}'"
153
+ when OID::Bit::Data
154
+ if value.binary?
155
+ "B'#{value}'"
156
+ elsif value.hex?
157
+ "X'#{value}'"
158
+ end
159
+ when Numeric
160
+ if value.finite?
161
+ super
162
+ else
163
+ "'#{value}'"
164
+ end
165
+ when OID::Array::Data
166
+ _quote(encode_array(value))
167
+ when Range
168
+ _quote(encode_range(value))
84
169
  else
85
170
  super
86
171
  end
87
- else
88
- super
89
172
  end
90
- end
91
173
 
92
- def _type_cast(value)
93
- case value
94
- when Type::Binary::Data
95
- # Return a bind param hash with format as binary.
96
- # See http://deveiate.org/code/pg/PGconn.html#method-i-exec_prepared-doc
97
- # for more information
98
- { value: value.to_s, format: 1 }
99
- when OID::Xml::Data, OID::Bit::Data
100
- value.to_s
101
- else
102
- super
174
+ def _type_cast(value)
175
+ case value
176
+ when Type::Binary::Data
177
+ # Return a bind param hash with format as binary.
178
+ # See https://deveiate.org/code/pg/PG/Connection.html#method-i-exec_prepared-doc
179
+ # for more information
180
+ { value: value.to_s, format: 1 }
181
+ when OID::Xml::Data, OID::Bit::Data
182
+ value.to_s
183
+ when OID::Array::Data
184
+ encode_array(value)
185
+ when Range
186
+ encode_range(value)
187
+ else
188
+ super
189
+ end
190
+ end
191
+
192
+ def encode_array(array_data)
193
+ encoder = array_data.encoder
194
+ values = type_cast_array(array_data.values)
195
+
196
+ result = encoder.encode(values)
197
+ if encoding = determine_encoding_of_strings_in_array(values)
198
+ result.force_encoding(encoding)
199
+ end
200
+ result
201
+ end
202
+
203
+ def encode_range(range)
204
+ "[#{type_cast_range_value(range.begin)},#{type_cast_range_value(range.end)}#{range.exclude_end? ? ')' : ']'}"
205
+ end
206
+
207
+ def determine_encoding_of_strings_in_array(value)
208
+ case value
209
+ when ::Array then determine_encoding_of_strings_in_array(value.first)
210
+ when ::String then value.encoding
211
+ end
212
+ end
213
+
214
+ def type_cast_array(values)
215
+ case values
216
+ when ::Array then values.map { |item| type_cast_array(item) }
217
+ else _type_cast(values)
218
+ end
219
+ end
220
+
221
+ def type_cast_range_value(value)
222
+ infinity?(value) ? "" : type_cast(value)
223
+ end
224
+
225
+ def infinity?(value)
226
+ value.respond_to?(:infinite?) && value.infinite?
103
227
  end
104
- end
105
228
  end
106
229
  end
107
230
  end
@@ -1,27 +1,40 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
4
6
  module ReferentialIntegrity # :nodoc:
5
- def supports_disable_referential_integrity? # :nodoc:
6
- true
7
- end
8
-
9
7
  def disable_referential_integrity # :nodoc:
10
- if supports_disable_referential_integrity?
11
- begin
8
+ original_exception = nil
9
+
10
+ begin
11
+ transaction(requires_new: true) do
12
12
  execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} DISABLE TRIGGER ALL" }.join(";"))
13
- rescue
14
- execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} DISABLE TRIGGER USER" }.join(";"))
15
13
  end
14
+ rescue ActiveRecord::ActiveRecordError => e
15
+ original_exception = e
16
+ end
17
+
18
+ begin
19
+ yield
20
+ rescue ActiveRecord::InvalidForeignKey => e
21
+ warn <<-WARNING
22
+ WARNING: Rails was not able to disable referential integrity.
23
+
24
+ This is most likely caused due to missing permissions.
25
+ Rails needs superuser privileges to disable referential integrity.
26
+
27
+ cause: #{original_exception&.message}
28
+
29
+ WARNING
30
+ raise e
16
31
  end
17
- yield
18
- ensure
19
- if supports_disable_referential_integrity?
20
- begin
32
+
33
+ begin
34
+ transaction(requires_new: true) do
21
35
  execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} ENABLE TRIGGER ALL" }.join(";"))
22
- rescue
23
- execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} ENABLE TRIGGER USER" }.join(";"))
24
36
  end
37
+ rescue ActiveRecord::ActiveRecordError
25
38
  end
26
39
  end
27
40
  end