activerecord 5.0.7.2 → 6.1.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 (363) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +829 -2015
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +11 -9
  5. data/examples/performance.rb +31 -29
  6. data/examples/simple.rb +5 -3
  7. data/lib/active_record.rb +37 -29
  8. data/lib/active_record/aggregations.rb +249 -247
  9. data/lib/active_record/association_relation.rb +30 -18
  10. data/lib/active_record/associations.rb +1714 -1596
  11. data/lib/active_record/associations/alias_tracker.rb +36 -42
  12. data/lib/active_record/associations/association.rb +143 -68
  13. data/lib/active_record/associations/association_scope.rb +98 -94
  14. data/lib/active_record/associations/belongs_to_association.rb +76 -46
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
  16. data/lib/active_record/associations/builder/association.rb +27 -28
  17. data/lib/active_record/associations/builder/belongs_to.rb +52 -60
  18. data/lib/active_record/associations/builder/collection_association.rb +12 -22
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +40 -62
  20. data/lib/active_record/associations/builder/has_many.rb +10 -2
  21. data/lib/active_record/associations/builder/has_one.rb +35 -2
  22. data/lib/active_record/associations/builder/singular_association.rb +5 -1
  23. data/lib/active_record/associations/collection_association.rb +104 -259
  24. data/lib/active_record/associations/collection_proxy.rb +169 -125
  25. data/lib/active_record/associations/foreign_association.rb +22 -0
  26. data/lib/active_record/associations/has_many_association.rb +46 -31
  27. data/lib/active_record/associations/has_many_through_association.rb +66 -46
  28. data/lib/active_record/associations/has_one_association.rb +71 -52
  29. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  30. data/lib/active_record/associations/join_dependency.rb +169 -180
  31. data/lib/active_record/associations/join_dependency/join_association.rb +53 -79
  32. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  33. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  34. data/lib/active_record/associations/preloader.rb +97 -104
  35. data/lib/active_record/associations/preloader/association.rb +109 -97
  36. data/lib/active_record/associations/preloader/through_association.rb +77 -76
  37. data/lib/active_record/associations/singular_association.rb +12 -45
  38. data/lib/active_record/associations/through_association.rb +27 -15
  39. data/lib/active_record/attribute_assignment.rb +55 -60
  40. data/lib/active_record/attribute_methods.rb +111 -141
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +17 -9
  42. data/lib/active_record/attribute_methods/dirty.rb +172 -112
  43. data/lib/active_record/attribute_methods/primary_key.rb +88 -91
  44. data/lib/active_record/attribute_methods/query.rb +6 -8
  45. data/lib/active_record/attribute_methods/read.rb +18 -50
  46. data/lib/active_record/attribute_methods/serialization.rb +38 -10
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +38 -66
  48. data/lib/active_record/attribute_methods/write.rb +25 -32
  49. data/lib/active_record/attributes.rb +69 -31
  50. data/lib/active_record/autosave_association.rb +102 -66
  51. data/lib/active_record/base.rb +16 -25
  52. data/lib/active_record/callbacks.rb +202 -43
  53. data/lib/active_record/coders/json.rb +2 -0
  54. data/lib/active_record/coders/yaml_column.rb +11 -12
  55. data/lib/active_record/connection_adapters.rb +50 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +661 -375
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +14 -38
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +269 -105
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +54 -35
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +137 -93
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +155 -113
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +328 -162
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +591 -259
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +229 -91
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +392 -244
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +457 -582
  69. data/lib/active_record/connection_adapters/column.rb +55 -13
  70. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  71. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +135 -49
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -23
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +79 -49
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +66 -56
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +20 -12
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +74 -37
  82. data/lib/active_record/connection_adapters/pool_config.rb +63 -0
  83. data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
  84. data/lib/active_record/connection_adapters/postgresql/column.rb +39 -28
  85. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +70 -101
  86. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
  87. data/lib/active_record/connection_adapters/postgresql/oid.rb +26 -21
  88. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -11
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
  90. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -6
  93. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +14 -4
  95. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  96. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
  97. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -18
  98. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  101. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
  104. data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +30 -9
  106. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -30
  107. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  108. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  109. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
  110. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  111. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  112. data/lib/active_record/connection_adapters/postgresql/quoting.rb +98 -38
  113. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +21 -27
  114. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
  115. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
  116. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +34 -32
  117. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +426 -324
  118. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +32 -23
  119. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -6
  120. data/lib/active_record/connection_adapters/postgresql_adapter.rb +418 -293
  121. data/lib/active_record/connection_adapters/schema_cache.rb +135 -18
  122. data/lib/active_record/connection_adapters/sql_type_metadata.rb +22 -7
  123. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
  124. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
  125. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +72 -18
  126. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -6
  127. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  128. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  129. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
  130. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +282 -290
  131. data/lib/active_record/connection_adapters/statement_pool.rb +9 -8
  132. data/lib/active_record/connection_handling.rb +287 -45
  133. data/lib/active_record/core.rb +385 -181
  134. data/lib/active_record/counter_cache.rb +60 -28
  135. data/lib/active_record/database_configurations.rb +272 -0
  136. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  137. data/lib/active_record/database_configurations/database_config.rb +80 -0
  138. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  139. data/lib/active_record/database_configurations/url_config.rb +53 -0
  140. data/lib/active_record/delegated_type.rb +209 -0
  141. data/lib/active_record/destroy_association_async_job.rb +36 -0
  142. data/lib/active_record/dynamic_matchers.rb +87 -87
  143. data/lib/active_record/enum.rb +122 -47
  144. data/lib/active_record/errors.rb +153 -22
  145. data/lib/active_record/explain.rb +13 -8
  146. data/lib/active_record/explain_registry.rb +3 -1
  147. data/lib/active_record/explain_subscriber.rb +9 -4
  148. data/lib/active_record/fixture_set/file.rb +20 -22
  149. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  150. data/lib/active_record/fixture_set/render_context.rb +17 -0
  151. data/lib/active_record/fixture_set/table_row.rb +152 -0
  152. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  153. data/lib/active_record/fixtures.rb +246 -507
  154. data/lib/active_record/gem_version.rb +6 -4
  155. data/lib/active_record/inheritance.rb +168 -95
  156. data/lib/active_record/insert_all.rb +208 -0
  157. data/lib/active_record/integration.rb +114 -25
  158. data/lib/active_record/internal_metadata.rb +30 -24
  159. data/lib/active_record/legacy_yaml_adapter.rb +11 -5
  160. data/lib/active_record/locking/optimistic.rb +81 -85
  161. data/lib/active_record/locking/pessimistic.rb +22 -6
  162. data/lib/active_record/log_subscriber.rb +68 -31
  163. data/lib/active_record/middleware/database_selector.rb +77 -0
  164. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  165. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  166. data/lib/active_record/migration.rb +439 -342
  167. data/lib/active_record/migration/command_recorder.rb +152 -98
  168. data/lib/active_record/migration/compatibility.rb +229 -60
  169. data/lib/active_record/migration/join_table.rb +8 -7
  170. data/lib/active_record/model_schema.rb +230 -122
  171. data/lib/active_record/nested_attributes.rb +213 -203
  172. data/lib/active_record/no_touching.rb +11 -2
  173. data/lib/active_record/null_relation.rb +12 -34
  174. data/lib/active_record/persistence.rb +471 -97
  175. data/lib/active_record/query_cache.rb +23 -12
  176. data/lib/active_record/querying.rb +43 -25
  177. data/lib/active_record/railtie.rb +155 -43
  178. data/lib/active_record/railties/console_sandbox.rb +2 -0
  179. data/lib/active_record/railties/controller_runtime.rb +34 -33
  180. data/lib/active_record/railties/databases.rake +507 -195
  181. data/lib/active_record/readonly_attributes.rb +9 -4
  182. data/lib/active_record/reflection.rb +245 -269
  183. data/lib/active_record/relation.rb +475 -324
  184. data/lib/active_record/relation/batches.rb +125 -72
  185. data/lib/active_record/relation/batches/batch_enumerator.rb +28 -10
  186. data/lib/active_record/relation/calculations.rb +267 -171
  187. data/lib/active_record/relation/delegation.rb +73 -69
  188. data/lib/active_record/relation/finder_methods.rb +238 -248
  189. data/lib/active_record/relation/from_clause.rb +7 -9
  190. data/lib/active_record/relation/merger.rb +95 -77
  191. data/lib/active_record/relation/predicate_builder.rb +109 -110
  192. data/lib/active_record/relation/predicate_builder/array_handler.rb +22 -17
  193. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
  194. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
  195. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +55 -0
  196. data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
  197. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  198. data/lib/active_record/relation/query_attribute.rb +33 -2
  199. data/lib/active_record/relation/query_methods.rb +654 -374
  200. data/lib/active_record/relation/record_fetch_warning.rb +8 -6
  201. data/lib/active_record/relation/spawn_methods.rb +15 -14
  202. data/lib/active_record/relation/where_clause.rb +171 -109
  203. data/lib/active_record/result.rb +88 -51
  204. data/lib/active_record/runtime_registry.rb +5 -3
  205. data/lib/active_record/sanitization.rb +73 -100
  206. data/lib/active_record/schema.rb +7 -14
  207. data/lib/active_record/schema_dumper.rb +101 -69
  208. data/lib/active_record/schema_migration.rb +16 -12
  209. data/lib/active_record/scoping.rb +20 -20
  210. data/lib/active_record/scoping/default.rb +92 -95
  211. data/lib/active_record/scoping/named.rb +39 -30
  212. data/lib/active_record/secure_token.rb +19 -9
  213. data/lib/active_record/serialization.rb +7 -3
  214. data/lib/active_record/signed_id.rb +116 -0
  215. data/lib/active_record/statement_cache.rb +80 -29
  216. data/lib/active_record/store.rb +122 -42
  217. data/lib/active_record/suppressor.rb +6 -3
  218. data/lib/active_record/table_metadata.rb +51 -39
  219. data/lib/active_record/tasks/database_tasks.rb +332 -115
  220. data/lib/active_record/tasks/mysql_database_tasks.rb +66 -104
  221. data/lib/active_record/tasks/postgresql_database_tasks.rb +84 -56
  222. data/lib/active_record/tasks/sqlite_database_tasks.rb +40 -19
  223. data/lib/active_record/test_databases.rb +24 -0
  224. data/lib/active_record/test_fixtures.rb +246 -0
  225. data/lib/active_record/timestamp.rb +70 -38
  226. data/lib/active_record/touch_later.rb +26 -24
  227. data/lib/active_record/transactions.rb +121 -184
  228. data/lib/active_record/translation.rb +3 -1
  229. data/lib/active_record/type.rb +29 -17
  230. data/lib/active_record/type/adapter_specific_registry.rb +44 -48
  231. data/lib/active_record/type/date.rb +2 -0
  232. data/lib/active_record/type/date_time.rb +2 -0
  233. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  234. data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
  235. data/lib/active_record/type/internal/timezone.rb +2 -0
  236. data/lib/active_record/type/json.rb +30 -0
  237. data/lib/active_record/type/serialized.rb +20 -9
  238. data/lib/active_record/type/text.rb +11 -0
  239. data/lib/active_record/type/time.rb +12 -1
  240. data/lib/active_record/type/type_map.rb +14 -17
  241. data/lib/active_record/type/unsigned_integer.rb +16 -0
  242. data/lib/active_record/type_caster.rb +4 -2
  243. data/lib/active_record/type_caster/connection.rb +17 -13
  244. data/lib/active_record/type_caster/map.rb +10 -6
  245. data/lib/active_record/validations.rb +8 -5
  246. data/lib/active_record/validations/absence.rb +2 -0
  247. data/lib/active_record/validations/associated.rb +4 -3
  248. data/lib/active_record/validations/length.rb +2 -0
  249. data/lib/active_record/validations/numericality.rb +35 -0
  250. data/lib/active_record/validations/presence.rb +4 -2
  251. data/lib/active_record/validations/uniqueness.rb +52 -45
  252. data/lib/active_record/version.rb +3 -1
  253. data/lib/arel.rb +54 -0
  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.rb +70 -0
  269. data/lib/arel/nodes/and.rb +32 -0
  270. data/lib/arel/nodes/ascending.rb +23 -0
  271. data/lib/arel/nodes/binary.rb +126 -0
  272. data/lib/arel/nodes/bind_param.rb +44 -0
  273. data/lib/arel/nodes/case.rb +55 -0
  274. data/lib/arel/nodes/casted.rb +62 -0
  275. data/lib/arel/nodes/comment.rb +29 -0
  276. data/lib/arel/nodes/count.rb +12 -0
  277. data/lib/arel/nodes/delete_statement.rb +45 -0
  278. data/lib/arel/nodes/descending.rb +23 -0
  279. data/lib/arel/nodes/equality.rb +15 -0
  280. data/lib/arel/nodes/extract.rb +24 -0
  281. data/lib/arel/nodes/false.rb +16 -0
  282. data/lib/arel/nodes/full_outer_join.rb +8 -0
  283. data/lib/arel/nodes/function.rb +44 -0
  284. data/lib/arel/nodes/grouping.rb +11 -0
  285. data/lib/arel/nodes/homogeneous_in.rb +72 -0
  286. data/lib/arel/nodes/in.rb +15 -0
  287. data/lib/arel/nodes/infix_operation.rb +92 -0
  288. data/lib/arel/nodes/inner_join.rb +8 -0
  289. data/lib/arel/nodes/insert_statement.rb +37 -0
  290. data/lib/arel/nodes/join_source.rb +20 -0
  291. data/lib/arel/nodes/matches.rb +18 -0
  292. data/lib/arel/nodes/named_function.rb +23 -0
  293. data/lib/arel/nodes/node.rb +51 -0
  294. data/lib/arel/nodes/node_expression.rb +13 -0
  295. data/lib/arel/nodes/ordering.rb +27 -0
  296. data/lib/arel/nodes/outer_join.rb +8 -0
  297. data/lib/arel/nodes/over.rb +15 -0
  298. data/lib/arel/nodes/regexp.rb +16 -0
  299. data/lib/arel/nodes/right_outer_join.rb +8 -0
  300. data/lib/arel/nodes/select_core.rb +67 -0
  301. data/lib/arel/nodes/select_statement.rb +41 -0
  302. data/lib/arel/nodes/sql_literal.rb +19 -0
  303. data/lib/arel/nodes/string_join.rb +11 -0
  304. data/lib/arel/nodes/table_alias.rb +31 -0
  305. data/lib/arel/nodes/terminal.rb +16 -0
  306. data/lib/arel/nodes/true.rb +16 -0
  307. data/lib/arel/nodes/unary.rb +44 -0
  308. data/lib/arel/nodes/unary_operation.rb +20 -0
  309. data/lib/arel/nodes/unqualified_column.rb +22 -0
  310. data/lib/arel/nodes/update_statement.rb +41 -0
  311. data/lib/arel/nodes/values_list.rb +9 -0
  312. data/lib/arel/nodes/window.rb +126 -0
  313. data/lib/arel/nodes/with.rb +11 -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.rb +13 -0
  321. data/lib/arel/visitors/dot.rb +308 -0
  322. data/lib/arel/visitors/mysql.rb +93 -0
  323. data/lib/arel/visitors/postgresql.rb +120 -0
  324. data/lib/arel/visitors/sqlite.rb +38 -0
  325. data/lib/arel/visitors/to_sql.rb +899 -0
  326. data/lib/arel/visitors/visitor.rb +45 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/rails/generators/active_record.rb +7 -5
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  330. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  331. data/lib/rails/generators/active_record/migration.rb +22 -3
  332. data/lib/rails/generators/active_record/migration/migration_generator.rb +38 -35
  333. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +3 -1
  334. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +7 -5
  335. data/lib/rails/generators/active_record/model/model_generator.rb +41 -25
  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 → model.rb.tt} +10 -1
  338. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  339. metadata +141 -57
  340. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  341. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  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 -15
  345. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  346. data/lib/active_record/associations/preloader/singular_association.rb +0 -20
  347. data/lib/active_record/attribute.rb +0 -213
  348. data/lib/active_record/attribute/user_provided_default.rb +0 -28
  349. data/lib/active_record/attribute_decorators.rb +0 -67
  350. data/lib/active_record/attribute_mutation_tracker.rb +0 -70
  351. data/lib/active_record/attribute_set.rb +0 -110
  352. data/lib/active_record/attribute_set/builder.rb +0 -132
  353. data/lib/active_record/collection_cache_key.rb +0 -50
  354. data/lib/active_record/connection_adapters/connection_specification.rb +0 -263
  355. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -22
  356. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
  357. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  358. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  359. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -17
  360. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
  361. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
  362. data/lib/active_record/relation/where_clause_factory.rb +0 -38
  363. data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,20 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters # :nodoc:
3
5
  module DatabaseLimits
4
-
5
- # Returns the maximum length of a table alias.
6
- def table_alias_length
7
- 255
8
- end
9
-
10
- # Returns the maximum length of a column name.
11
- def column_name_length
6
+ def max_identifier_length # :nodoc:
12
7
  64
13
8
  end
14
9
 
15
- # Returns the maximum length of a table name.
16
- def table_name_length
17
- 64
10
+ # Returns the maximum length of a table alias.
11
+ def table_alias_length
12
+ max_identifier_length
18
13
  end
19
14
 
20
15
  # Returns the maximum allowed length for an index name. This
@@ -25,43 +20,24 @@ module ActiveRecord
25
20
  def allowed_index_name_length
26
21
  index_name_length
27
22
  end
23
+ deprecate :allowed_index_name_length
28
24
 
29
25
  # Returns the maximum length of an index name.
30
26
  def index_name_length
31
- 64
32
- end
33
-
34
- # Returns the maximum number of columns per table.
35
- def columns_per_table
36
- 1024
37
- end
38
-
39
- # Returns the maximum number of indexes per table.
40
- def indexes_per_table
41
- 16
42
- end
43
-
44
- # Returns the maximum number of columns in a multicolumn index.
45
- def columns_per_multicolumn_index
46
- 16
27
+ max_identifier_length
47
28
  end
48
29
 
49
30
  # Returns the maximum number of elements in an IN (x,y,z) clause.
50
- # nil means no limit.
31
+ # +nil+ means no limit.
51
32
  def in_clause_length
52
33
  nil
53
34
  end
35
+ deprecate :in_clause_length
54
36
 
55
- # Returns the maximum length of an SQL query.
56
- def sql_query_length
57
- 1048575
58
- end
59
-
60
- # Returns maximum number of joins in a single query.
61
- def joins_per_query
62
- 256
63
- end
64
-
37
+ private
38
+ def bind_params_length
39
+ 65535
40
+ end
65
41
  end
66
42
  end
67
43
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters # :nodoc:
3
5
  module DatabaseStatements
@@ -7,39 +9,67 @@ module ActiveRecord
7
9
  end
8
10
 
9
11
  # Converts an arel AST to SQL
10
- def to_sql(arel, binds = [])
11
- if arel.respond_to?(:ast)
12
- collected = visitor.accept(arel.ast, collector)
13
- collected.compile(binds.dup, self)
12
+ def to_sql(arel_or_sql_string, binds = [])
13
+ sql, _ = to_sql_and_binds(arel_or_sql_string, binds)
14
+ sql
15
+ end
16
+
17
+ def to_sql_and_binds(arel_or_sql_string, binds = [], preparable = nil) # :nodoc:
18
+ if arel_or_sql_string.respond_to?(:ast)
19
+ unless binds.empty?
20
+ raise "Passing bind parameters with an arel AST is forbidden. " \
21
+ "The values must be stored on the AST directly"
22
+ end
23
+
24
+ collector = collector()
25
+
26
+ if prepared_statements
27
+ collector.preparable = true
28
+ sql, binds = visitor.compile(arel_or_sql_string.ast, collector)
29
+
30
+ if binds.length > bind_params_length
31
+ unprepared_statement do
32
+ return to_sql_and_binds(arel_or_sql_string)
33
+ end
34
+ end
35
+ preparable = collector.preparable
36
+ else
37
+ sql = visitor.compile(arel_or_sql_string.ast, collector)
38
+ end
39
+ [sql.freeze, binds, preparable]
14
40
  else
15
- arel
41
+ arel_or_sql_string = arel_or_sql_string.dup.freeze unless arel_or_sql_string.frozen?
42
+ [arel_or_sql_string, binds, preparable]
16
43
  end
17
44
  end
45
+ private :to_sql_and_binds
18
46
 
19
47
  # This is used in the StatementCache object. It returns an object that
20
48
  # can be used to query the database repeatedly.
21
- def cacheable_query(arel) # :nodoc:
49
+ def cacheable_query(klass, arel) # :nodoc:
22
50
  if prepared_statements
23
- ActiveRecord::StatementCache.query visitor, arel.ast
51
+ sql, binds = visitor.compile(arel.ast, collector)
52
+ query = klass.query(sql)
24
53
  else
25
- ActiveRecord::StatementCache.partial_query visitor, arel.ast, collector
54
+ collector = klass.partial_query_collector
55
+ parts, binds = visitor.compile(arel.ast, collector)
56
+ query = klass.partial_query(parts)
26
57
  end
58
+ [query, binds]
27
59
  end
28
60
 
29
61
  # Returns an ActiveRecord::Result instance.
30
62
  def select_all(arel, name = nil, binds = [], preparable: nil)
31
- arel, binds = binds_from_relation arel, binds
32
- sql = to_sql(arel, binds)
33
- if !prepared_statements || (arel.is_a?(String) && preparable.nil?)
34
- preparable = false
35
- else
36
- preparable = visitor.preparable
37
- end
63
+ arel = arel_from_relation(arel)
64
+ sql, binds, preparable = to_sql_and_binds(arel, binds, preparable)
65
+
38
66
  if prepared_statements && preparable
39
67
  select_prepared(sql, name, binds)
40
68
  else
41
69
  select(sql, name, binds)
42
70
  end
71
+ rescue ::RangeError
72
+ ActiveRecord::Result.new([], [])
43
73
  end
44
74
 
45
75
  # Returns a record hash with the column names as keys and column values
@@ -50,23 +80,36 @@ module ActiveRecord
50
80
 
51
81
  # Returns a single value from a record
52
82
  def select_value(arel, name = nil, binds = [])
53
- arel, binds = binds_from_relation arel, binds
54
- if result = select_rows(to_sql(arel, binds), name, binds).first
55
- result.first
56
- end
83
+ single_value_from_rows(select_rows(arel, name, binds))
57
84
  end
58
85
 
59
86
  # Returns an array of the values of the first column in a select:
60
87
  # select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
61
88
  def select_values(arel, name = nil, binds = [])
62
- arel, binds = binds_from_relation arel, binds
63
- select_rows(to_sql(arel, binds), name, binds).map(&:first)
89
+ select_rows(arel, name, binds).map(&:first)
64
90
  end
65
91
 
66
92
  # Returns an array of arrays containing the field values.
67
93
  # Order is the same as that returned by +columns+.
68
- def select_rows(sql, name = nil, binds = [])
69
- exec_query(sql, name, binds).rows
94
+ def select_rows(arel, name = nil, binds = [])
95
+ select_all(arel, name, binds).rows
96
+ end
97
+
98
+ def query_value(sql, name = nil) # :nodoc:
99
+ single_value_from_rows(query(sql, name))
100
+ end
101
+
102
+ def query_values(sql, name = nil) # :nodoc:
103
+ query(sql, name).map(&:first)
104
+ end
105
+
106
+ def query(sql, name = nil) # :nodoc:
107
+ exec_query(sql, name).rows
108
+ end
109
+
110
+ # Determines whether the SQL statement is a write query.
111
+ def write_query?(sql)
112
+ raise NotImplementedError
70
113
  end
71
114
 
72
115
  # Executes the SQL statement in the context of this connection and returns
@@ -81,71 +124,83 @@ module ActiveRecord
81
124
  # Executes +sql+ statement in the context of this connection using
82
125
  # +binds+ as the bind substitutes. +name+ is logged along with
83
126
  # the executed +sql+ statement.
84
- def exec_query(sql, name = 'SQL', binds = [], prepare: false)
127
+ def exec_query(sql, name = "SQL", binds = [], prepare: false)
85
128
  raise NotImplementedError
86
129
  end
87
130
 
88
131
  # Executes insert +sql+ statement in the context of this connection using
89
132
  # +binds+ as the bind substitutes. +name+ is logged along with
90
133
  # the executed +sql+ statement.
91
- def exec_insert(sql, name, binds, pk = nil, sequence_name = nil)
134
+ def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
135
+ sql, binds = sql_for_insert(sql, pk, binds)
92
136
  exec_query(sql, name, binds)
93
137
  end
94
138
 
95
139
  # Executes delete +sql+ statement in the context of this connection using
96
140
  # +binds+ as the bind substitutes. +name+ is logged along with
97
141
  # the executed +sql+ statement.
98
- def exec_delete(sql, name, binds)
142
+ def exec_delete(sql, name = nil, binds = [])
99
143
  exec_query(sql, name, binds)
100
144
  end
101
145
 
102
- # Executes the truncate statement.
103
- def truncate(table_name, name = nil)
104
- raise NotImplementedError
105
- end
106
-
107
146
  # Executes update +sql+ statement in the context of this connection using
108
147
  # +binds+ as the bind substitutes. +name+ is logged along with
109
148
  # the executed +sql+ statement.
110
- def exec_update(sql, name, binds)
149
+ def exec_update(sql, name = nil, binds = [])
111
150
  exec_query(sql, name, binds)
112
151
  end
113
152
 
153
+ def exec_insert_all(sql, name) # :nodoc:
154
+ exec_query(sql, name)
155
+ end
156
+
157
+ def explain(arel, binds = []) # :nodoc:
158
+ raise NotImplementedError
159
+ end
160
+
114
161
  # Executes an INSERT query and returns the new record's ID
115
162
  #
116
- # +id_value+ will be returned unless the value is nil, in
163
+ # +id_value+ will be returned unless the value is +nil+, in
117
164
  # which case the database will attempt to calculate the last inserted
118
165
  # id and return that value.
119
166
  #
120
167
  # If the next id was calculated in advance (as in Oracle), it should be
121
168
  # passed in as +id_value+.
122
169
  def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
123
- sql, binds, pk, sequence_name = sql_for_insert(to_sql(arel, binds), pk, id_value, sequence_name, binds)
170
+ sql, binds = to_sql_and_binds(arel, binds)
124
171
  value = exec_insert(sql, name, binds, pk, sequence_name)
125
172
  id_value || last_inserted_id(value)
126
173
  end
127
174
  alias create insert
128
- alias insert_sql insert
129
- deprecate insert_sql: :insert
130
175
 
131
176
  # Executes the update statement and returns the number of rows affected.
132
177
  def update(arel, name = nil, binds = [])
133
- exec_update(to_sql(arel, binds), name, binds)
178
+ sql, binds = to_sql_and_binds(arel, binds)
179
+ exec_update(sql, name, binds)
134
180
  end
135
- alias update_sql update
136
- deprecate update_sql: :update
137
181
 
138
182
  # Executes the delete statement and returns the number of rows affected.
139
183
  def delete(arel, name = nil, binds = [])
140
- exec_delete(to_sql(arel, binds), name, binds)
184
+ sql, binds = to_sql_and_binds(arel, binds)
185
+ exec_delete(sql, name, binds)
186
+ end
187
+
188
+ # Executes the truncate statement.
189
+ def truncate(table_name, name = nil)
190
+ execute(build_truncate_statement(table_name), name)
141
191
  end
142
- alias delete_sql delete
143
- deprecate delete_sql: :delete
144
192
 
145
- # Returns +true+ when the connection adapter supports prepared statement
146
- # caching, otherwise returns +false+
147
- def supports_statement_cache?
148
- false
193
+ def truncate_tables(*table_names) # :nodoc:
194
+ table_names -= [schema_migration.table_name, InternalMetadata.table_name]
195
+
196
+ return if table_names.empty?
197
+
198
+ with_multi_statements do
199
+ disable_referential_integrity do
200
+ statements = build_truncate_statements(table_names)
201
+ execute_batch(statements, "Truncate Tables")
202
+ end
203
+ end
149
204
  end
150
205
 
151
206
  # Runs the given block in a database transaction, and returns the result
@@ -153,15 +208,30 @@ module ActiveRecord
153
208
  #
154
209
  # == Nested transactions support
155
210
  #
211
+ # #transaction calls can be nested. By default, this makes all database
212
+ # statements in the nested transaction block become part of the parent
213
+ # transaction. For example, the following behavior may be surprising:
214
+ #
215
+ # ActiveRecord::Base.transaction do
216
+ # Post.create(title: 'first')
217
+ # ActiveRecord::Base.transaction do
218
+ # Post.create(title: 'second')
219
+ # raise ActiveRecord::Rollback
220
+ # end
221
+ # end
222
+ #
223
+ # This creates both "first" and "second" posts. Reason is the
224
+ # ActiveRecord::Rollback exception in the nested block does not issue a
225
+ # ROLLBACK. Since these exceptions are captured in transaction blocks,
226
+ # the parent block does not see it and the real transaction is committed.
227
+ #
156
228
  # Most databases don't support true nested transactions. At the time of
157
229
  # writing, the only database that supports true nested transactions that
158
230
  # we're aware of, is MS-SQL.
159
231
  #
160
232
  # In order to get around this problem, #transaction will emulate the effect
161
233
  # of nested transactions, by using savepoints:
162
- # http://dev.mysql.com/doc/refman/5.7/en/savepoint.html
163
- # Savepoints are supported by MySQL and PostgreSQL. SQLite3 version >= '3.6.8'
164
- # supports savepoints.
234
+ # https://dev.mysql.com/doc/refman/en/savepoint.html.
165
235
  #
166
236
  # It is safe to call this method if a database transaction is already open,
167
237
  # i.e. if #transaction is called within another #transaction block. In case
@@ -173,6 +243,24 @@ module ActiveRecord
173
243
  # - However, if +:requires_new+ is set, the block will be wrapped in a
174
244
  # database savepoint acting as a sub-transaction.
175
245
  #
246
+ # In order to get a ROLLBACK for the nested transaction you may ask for a
247
+ # real sub-transaction by passing <tt>requires_new: true</tt>.
248
+ # If anything goes wrong, the database rolls back to the beginning of
249
+ # the sub-transaction without rolling back the parent transaction.
250
+ # If we add it to the previous example:
251
+ #
252
+ # ActiveRecord::Base.transaction do
253
+ # Post.create(title: 'first')
254
+ # ActiveRecord::Base.transaction(requires_new: true) do
255
+ # Post.create(title: 'second')
256
+ # raise ActiveRecord::Rollback
257
+ # end
258
+ # end
259
+ #
260
+ # only post with title "first" is created.
261
+ #
262
+ # See ActiveRecord::Transactions to learn more.
263
+ #
176
264
  # === Caveats
177
265
  #
178
266
  # MySQL doesn't support DDL transactions. If you perform a DDL operation,
@@ -211,8 +299,8 @@ module ActiveRecord
211
299
  # You should consult the documentation for your database to understand the
212
300
  # semantics of these different levels:
213
301
  #
214
- # * http://www.postgresql.org/docs/current/static/transaction-iso.html
215
- # * https://dev.mysql.com/doc/refman/5.7/en/set-transaction.html
302
+ # * https://www.postgresql.org/docs/current/static/transaction-iso.html
303
+ # * https://dev.mysql.com/doc/refman/en/set-transaction.html
216
304
  #
217
305
  # An ActiveRecord::TransactionIsolationError will be raised if:
218
306
  #
@@ -237,7 +325,16 @@ module ActiveRecord
237
325
 
238
326
  attr_reader :transaction_manager #:nodoc:
239
327
 
240
- delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction, :commit_transaction, :rollback_transaction, to: :transaction_manager
328
+ delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction,
329
+ :commit_transaction, :rollback_transaction, :materialize_transactions,
330
+ :disable_lazy_transactions!, :enable_lazy_transactions!, to: :transaction_manager
331
+
332
+ def mark_transaction_written_if_write(sql) # :nodoc:
333
+ transaction = current_transaction
334
+ if transaction.open?
335
+ transaction.written ||= write_query?(sql)
336
+ end
337
+ end
241
338
 
242
339
  def transaction_open?
243
340
  current_transaction.open?
@@ -249,12 +346,8 @@ module ActiveRecord
249
346
 
250
347
  # Register a record with the current transaction so that its after_commit and after_rollback callbacks
251
348
  # can be called.
252
- def add_transaction_record(record)
253
- current_transaction.add_record(record)
254
- end
255
-
256
- def transaction_state
257
- current_transaction.state
349
+ def add_transaction_record(record, ensure_finalize = true)
350
+ current_transaction.add_record(record, ensure_finalize)
258
351
  end
259
352
 
260
353
  # Begins the transaction (and turns off auto-committing).
@@ -301,71 +394,137 @@ module ActiveRecord
301
394
  end
302
395
 
303
396
  # Inserts the given fixture into the table. Overridden in adapters that require
304
- # something beyond a simple insert (eg. Oracle).
397
+ # something beyond a simple insert (e.g. Oracle).
398
+ # Most of adapters should implement `insert_fixtures_set` that leverages bulk SQL insert.
399
+ # We keep this method to provide fallback
400
+ # for databases like sqlite that do not support bulk inserts.
305
401
  def insert_fixture(fixture, table_name)
306
- fixture = fixture.stringify_keys
402
+ execute(build_fixture_sql(Array.wrap(fixture), table_name), "Fixture Insert")
403
+ end
307
404
 
308
- columns = schema_cache.columns_hash(table_name)
309
- binds = fixture.map do |name, value|
310
- if column = columns[name]
311
- type = lookup_cast_type_from_column(column)
312
- Relation::QueryAttribute.new(name, value, type)
313
- else
314
- raise Fixture::FixtureError, %(table "#{table_name}" has no column named #{name.inspect}.)
315
- end
316
- end
317
- key_list = fixture.keys.map { |name| quote_column_name(name) }
318
- value_list = prepare_binds_for_database(binds).map do |value|
319
- begin
320
- quote(value)
321
- rescue TypeError
322
- quote(YAML.dump(value))
405
+ def insert_fixtures_set(fixture_set, tables_to_delete = [])
406
+ fixture_inserts = build_fixture_statements(fixture_set)
407
+ table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name(table)}" }
408
+ statements = table_deletes + fixture_inserts
409
+
410
+ with_multi_statements do
411
+ disable_referential_integrity do
412
+ transaction(requires_new: true) do
413
+ execute_batch(statements, "Fixtures Load")
414
+ end
323
415
  end
324
416
  end
325
-
326
- execute "INSERT INTO #{quote_table_name(table_name)} (#{key_list.join(', ')}) VALUES (#{value_list.join(', ')})", 'Fixture Insert'
327
417
  end
328
418
 
329
- def empty_insert_statement_value
419
+ def empty_insert_statement_value(primary_key = nil)
330
420
  "DEFAULT VALUES"
331
421
  end
332
422
 
333
423
  # Sanitizes the given LIMIT parameter in order to prevent SQL injection.
334
424
  #
335
425
  # The +limit+ may be anything that can evaluate to a string via #to_s. It
336
- # should look like an integer, or a comma-delimited list of integers, or
337
- # an Arel SQL literal.
426
+ # should look like an integer, or an Arel SQL literal.
338
427
  #
339
428
  # Returns Integer and Arel::Nodes::SqlLiteral limits as is.
340
- # Returns the sanitized limit parameter, either as an integer, or as a
341
- # string which contains a comma-delimited list of integers.
342
429
  def sanitize_limit(limit)
343
430
  if limit.is_a?(Integer) || limit.is_a?(Arel::Nodes::SqlLiteral)
344
431
  limit
345
- elsif limit.to_s.include?(',')
346
- Arel.sql limit.to_s.split(',').map{ |i| Integer(i) }.join(',')
347
432
  else
348
433
  Integer(limit)
349
434
  end
350
435
  end
351
436
 
352
- # The default strategy for an UPDATE with joins is to use a subquery. This doesn't work
353
- # on MySQL (even when aliasing the tables), but MySQL allows using JOIN directly in
354
- # an UPDATE statement, so in the MySQL adapters we redefine this to do that.
355
- def join_to_update(update, select, key) # :nodoc:
356
- subselect = subquery_for(key, select)
357
-
358
- update.where key.in(subselect)
437
+ # Fixture value is quoted by Arel, however scalar values
438
+ # are not quotable. In this case we want to convert
439
+ # the column value to YAML.
440
+ def with_yaml_fallback(value) # :nodoc:
441
+ if value.is_a?(Hash) || value.is_a?(Array)
442
+ YAML.dump(value)
443
+ else
444
+ value
445
+ end
359
446
  end
360
- alias join_to_delete join_to_update
361
447
 
362
- protected
448
+ private
449
+ def execute_batch(statements, name = nil)
450
+ statements.each do |statement|
451
+ execute(statement, name)
452
+ end
453
+ end
454
+
455
+ DEFAULT_INSERT_VALUE = Arel.sql("DEFAULT").freeze
456
+ private_constant :DEFAULT_INSERT_VALUE
363
457
 
364
- # Returns a subquery for the given key using the join information.
365
- def subquery_for(key, select)
366
- subselect = select.clone
367
- subselect.projections = [key]
368
- subselect
458
+ def default_insert_value(column)
459
+ DEFAULT_INSERT_VALUE
460
+ end
461
+
462
+ def build_fixture_sql(fixtures, table_name)
463
+ columns = schema_cache.columns_hash(table_name)
464
+
465
+ values_list = fixtures.map do |fixture|
466
+ fixture = fixture.stringify_keys
467
+
468
+ unknown_columns = fixture.keys - columns.keys
469
+ if unknown_columns.any?
470
+ raise Fixture::FixtureError, %(table "#{table_name}" has no columns named #{unknown_columns.map(&:inspect).join(', ')}.)
471
+ end
472
+
473
+ columns.map do |name, column|
474
+ if fixture.key?(name)
475
+ type = lookup_cast_type_from_column(column)
476
+ with_yaml_fallback(type.serialize(fixture[name]))
477
+ else
478
+ default_insert_value(column)
479
+ end
480
+ end
481
+ end
482
+
483
+ table = Arel::Table.new(table_name)
484
+ manager = Arel::InsertManager.new
485
+ manager.into(table)
486
+
487
+ if values_list.size == 1
488
+ values = values_list.shift
489
+ new_values = []
490
+ columns.each_key.with_index { |column, i|
491
+ unless values[i].equal?(DEFAULT_INSERT_VALUE)
492
+ new_values << values[i]
493
+ manager.columns << table[column]
494
+ end
495
+ }
496
+ values_list << new_values
497
+ else
498
+ columns.each_key { |column| manager.columns << table[column] }
499
+ end
500
+
501
+ manager.values = manager.create_values_list(values_list)
502
+ visitor.compile(manager.ast)
503
+ end
504
+
505
+ def build_fixture_statements(fixture_set)
506
+ fixture_set.map do |table_name, fixtures|
507
+ next if fixtures.empty?
508
+ build_fixture_sql(fixtures, table_name)
509
+ end.compact
510
+ end
511
+
512
+ def build_truncate_statement(table_name)
513
+ "TRUNCATE TABLE #{quote_table_name(table_name)}"
514
+ end
515
+
516
+ def build_truncate_statements(table_names)
517
+ table_names.map do |table_name|
518
+ build_truncate_statement(table_name)
519
+ end
520
+ end
521
+
522
+ def with_multi_statements
523
+ yield
524
+ end
525
+
526
+ def combine_multi_statements(total_sql)
527
+ total_sql.join(";\n")
369
528
  end
370
529
 
371
530
  # Returns an ActiveRecord::Result instance.
@@ -377,20 +536,25 @@ module ActiveRecord
377
536
  exec_query(sql, name, binds, prepare: true)
378
537
  end
379
538
 
380
- def sql_for_insert(sql, pk, id_value, sequence_name, binds)
381
- [sql, binds, pk, sequence_name]
539
+ def sql_for_insert(sql, pk, binds)
540
+ [sql, binds]
382
541
  end
383
542
 
384
543
  def last_inserted_id(result)
385
- row = result.rows.first
544
+ single_value_from_rows(result.rows)
545
+ end
546
+
547
+ def single_value_from_rows(rows)
548
+ row = rows.first
386
549
  row && row.first
387
550
  end
388
551
 
389
- def binds_from_relation(relation, binds)
390
- if relation.is_a?(Relation) && binds.empty?
391
- relation, binds = relation.arel, relation.bound_attributes
552
+ def arel_from_relation(relation)
553
+ if relation.is_a?(Relation)
554
+ relation.arel
555
+ else
556
+ relation
392
557
  end
393
- [relation, binds]
394
558
  end
395
559
  end
396
560
  end