activerecord 3.2.6 → 6.0.0

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 (371) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +611 -6417
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +44 -47
  5. data/examples/performance.rb +79 -71
  6. data/examples/simple.rb +6 -5
  7. data/lib/active_record/aggregations.rb +268 -238
  8. data/lib/active_record/association_relation.rb +40 -0
  9. data/lib/active_record/associations/alias_tracker.rb +47 -42
  10. data/lib/active_record/associations/association.rb +173 -81
  11. data/lib/active_record/associations/association_scope.rb +124 -92
  12. data/lib/active_record/associations/belongs_to_association.rb +83 -38
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +11 -9
  14. data/lib/active_record/associations/builder/association.rb +113 -32
  15. data/lib/active_record/associations/builder/belongs_to.rb +105 -60
  16. data/lib/active_record/associations/builder/collection_association.rb +53 -56
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +98 -41
  18. data/lib/active_record/associations/builder/has_many.rb +11 -63
  19. data/lib/active_record/associations/builder/has_one.rb +47 -45
  20. data/lib/active_record/associations/builder/singular_association.rb +30 -18
  21. data/lib/active_record/associations/collection_association.rb +217 -295
  22. data/lib/active_record/associations/collection_proxy.rb +1074 -77
  23. data/lib/active_record/associations/foreign_association.rb +20 -0
  24. data/lib/active_record/associations/has_many_association.rb +78 -50
  25. data/lib/active_record/associations/has_many_through_association.rb +99 -61
  26. data/lib/active_record/associations/has_one_association.rb +75 -30
  27. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  28. data/lib/active_record/associations/join_dependency/join_association.rb +45 -119
  29. data/lib/active_record/associations/join_dependency/join_base.rb +11 -12
  30. data/lib/active_record/associations/join_dependency/join_part.rb +35 -42
  31. data/lib/active_record/associations/join_dependency.rb +208 -164
  32. data/lib/active_record/associations/preloader/association.rb +93 -87
  33. data/lib/active_record/associations/preloader/through_association.rb +87 -38
  34. data/lib/active_record/associations/preloader.rb +134 -110
  35. data/lib/active_record/associations/singular_association.rb +19 -24
  36. data/lib/active_record/associations/through_association.rb +61 -27
  37. data/lib/active_record/associations.rb +1766 -1505
  38. data/lib/active_record/attribute_assignment.rb +57 -193
  39. data/lib/active_record/attribute_decorators.rb +90 -0
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +58 -8
  41. data/lib/active_record/attribute_methods/dirty.rb +187 -67
  42. data/lib/active_record/attribute_methods/primary_key.rb +100 -78
  43. data/lib/active_record/attribute_methods/query.rb +10 -8
  44. data/lib/active_record/attribute_methods/read.rb +29 -118
  45. data/lib/active_record/attribute_methods/serialization.rb +60 -72
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +69 -42
  47. data/lib/active_record/attribute_methods/write.rb +36 -44
  48. data/lib/active_record/attribute_methods.rb +306 -161
  49. data/lib/active_record/attributes.rb +279 -0
  50. data/lib/active_record/autosave_association.rb +324 -238
  51. data/lib/active_record/base.rb +114 -507
  52. data/lib/active_record/callbacks.rb +147 -83
  53. data/lib/active_record/coders/json.rb +15 -0
  54. data/lib/active_record/coders/yaml_column.rb +32 -23
  55. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +962 -279
  56. data/lib/active_record/connection_adapters/abstract/database_limits.rb +32 -5
  57. data/lib/active_record/connection_adapters/abstract/database_statements.rb +331 -209
  58. data/lib/active_record/connection_adapters/abstract/query_cache.rb +95 -23
  59. data/lib/active_record/connection_adapters/abstract/quoting.rb +201 -65
  60. data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
  61. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +510 -289
  63. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +93 -0
  64. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1182 -313
  65. data/lib/active_record/connection_adapters/abstract/transaction.rb +323 -0
  66. data/lib/active_record/connection_adapters/abstract_adapter.rb +585 -120
  67. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +610 -463
  68. data/lib/active_record/connection_adapters/column.rb +58 -233
  69. data/lib/active_record/connection_adapters/connection_specification.rb +297 -0
  70. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
  71. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  72. data/lib/active_record/connection_adapters/mysql/database_statements.rb +200 -0
  73. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  74. data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  79. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
  80. data/lib/active_record/connection_adapters/mysql2_adapter.rb +75 -207
  81. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -0
  82. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +182 -0
  83. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  84. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +92 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +53 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +23 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +41 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +113 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +26 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
  107. data/lib/active_record/connection_adapters/postgresql/quoting.rb +205 -0
  108. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
  109. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +222 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +776 -0
  113. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
  114. data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
  115. data/lib/active_record/connection_adapters/postgresql_adapter.rb +695 -1052
  116. data/lib/active_record/connection_adapters/schema_cache.rb +115 -24
  117. data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
  118. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
  119. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  120. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -0
  121. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +528 -26
  126. data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
  127. data/lib/active_record/connection_handling.rb +267 -0
  128. data/lib/active_record/core.rb +599 -0
  129. data/lib/active_record/counter_cache.rb +177 -103
  130. data/lib/active_record/database_configurations/database_config.rb +37 -0
  131. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  132. data/lib/active_record/database_configurations/url_config.rb +79 -0
  133. data/lib/active_record/database_configurations.rb +233 -0
  134. data/lib/active_record/define_callbacks.rb +22 -0
  135. data/lib/active_record/dynamic_matchers.rb +107 -64
  136. data/lib/active_record/enum.rb +274 -0
  137. data/lib/active_record/errors.rb +254 -61
  138. data/lib/active_record/explain.rb +35 -70
  139. data/lib/active_record/explain_registry.rb +32 -0
  140. data/lib/active_record/explain_subscriber.rb +18 -8
  141. data/lib/active_record/fixture_set/file.rb +82 -0
  142. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  143. data/lib/active_record/fixture_set/render_context.rb +17 -0
  144. data/lib/active_record/fixture_set/table_row.rb +153 -0
  145. data/lib/active_record/fixture_set/table_rows.rb +47 -0
  146. data/lib/active_record/fixtures.rb +291 -475
  147. data/lib/active_record/gem_version.rb +17 -0
  148. data/lib/active_record/inheritance.rb +219 -100
  149. data/lib/active_record/insert_all.rb +179 -0
  150. data/lib/active_record/integration.rb +175 -17
  151. data/lib/active_record/internal_metadata.rb +53 -0
  152. data/lib/active_record/legacy_yaml_adapter.rb +48 -0
  153. data/lib/active_record/locale/en.yml +9 -1
  154. data/lib/active_record/locking/optimistic.rb +106 -92
  155. data/lib/active_record/locking/pessimistic.rb +23 -11
  156. data/lib/active_record/log_subscriber.rb +80 -30
  157. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  158. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  159. data/lib/active_record/middleware/database_selector.rb +75 -0
  160. data/lib/active_record/migration/command_recorder.rb +235 -56
  161. data/lib/active_record/migration/compatibility.rb +244 -0
  162. data/lib/active_record/migration/join_table.rb +17 -0
  163. data/lib/active_record/migration.rb +917 -301
  164. data/lib/active_record/model_schema.rb +351 -175
  165. data/lib/active_record/nested_attributes.rb +366 -235
  166. data/lib/active_record/no_touching.rb +65 -0
  167. data/lib/active_record/null_relation.rb +68 -0
  168. data/lib/active_record/persistence.rb +761 -166
  169. data/lib/active_record/query_cache.rb +22 -44
  170. data/lib/active_record/querying.rb +55 -31
  171. data/lib/active_record/railtie.rb +185 -47
  172. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  173. data/lib/active_record/railties/console_sandbox.rb +5 -4
  174. data/lib/active_record/railties/controller_runtime.rb +35 -33
  175. data/lib/active_record/railties/databases.rake +366 -463
  176. data/lib/active_record/readonly_attributes.rb +4 -6
  177. data/lib/active_record/reflection.rb +736 -228
  178. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  179. data/lib/active_record/relation/batches.rb +252 -52
  180. data/lib/active_record/relation/calculations.rb +340 -270
  181. data/lib/active_record/relation/delegation.rb +117 -36
  182. data/lib/active_record/relation/finder_methods.rb +439 -286
  183. data/lib/active_record/relation/from_clause.rb +26 -0
  184. data/lib/active_record/relation/merger.rb +184 -0
  185. data/lib/active_record/relation/predicate_builder/array_handler.rb +49 -0
  186. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  187. data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
  188. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  189. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  190. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  191. data/lib/active_record/relation/predicate_builder/relation_handler.rb +19 -0
  192. data/lib/active_record/relation/predicate_builder.rb +131 -39
  193. data/lib/active_record/relation/query_attribute.rb +50 -0
  194. data/lib/active_record/relation/query_methods.rb +1163 -221
  195. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  196. data/lib/active_record/relation/spawn_methods.rb +49 -120
  197. data/lib/active_record/relation/where_clause.rb +190 -0
  198. data/lib/active_record/relation/where_clause_factory.rb +33 -0
  199. data/lib/active_record/relation.rb +671 -349
  200. data/lib/active_record/result.rb +149 -15
  201. data/lib/active_record/runtime_registry.rb +24 -0
  202. data/lib/active_record/sanitization.rb +153 -133
  203. data/lib/active_record/schema.rb +22 -19
  204. data/lib/active_record/schema_dumper.rb +178 -112
  205. data/lib/active_record/schema_migration.rb +60 -0
  206. data/lib/active_record/scoping/default.rb +107 -98
  207. data/lib/active_record/scoping/named.rb +130 -115
  208. data/lib/active_record/scoping.rb +77 -123
  209. data/lib/active_record/secure_token.rb +40 -0
  210. data/lib/active_record/serialization.rb +10 -6
  211. data/lib/active_record/statement_cache.rb +148 -0
  212. data/lib/active_record/store.rb +256 -16
  213. data/lib/active_record/suppressor.rb +61 -0
  214. data/lib/active_record/table_metadata.rb +75 -0
  215. data/lib/active_record/tasks/database_tasks.rb +506 -0
  216. data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
  217. data/lib/active_record/tasks/postgresql_database_tasks.rb +141 -0
  218. data/lib/active_record/tasks/sqlite_database_tasks.rb +77 -0
  219. data/lib/active_record/test_databases.rb +23 -0
  220. data/lib/active_record/test_fixtures.rb +224 -0
  221. data/lib/active_record/timestamp.rb +93 -39
  222. data/lib/active_record/touch_later.rb +66 -0
  223. data/lib/active_record/transactions.rb +260 -129
  224. data/lib/active_record/translation.rb +3 -1
  225. data/lib/active_record/type/adapter_specific_registry.rb +129 -0
  226. data/lib/active_record/type/date.rb +9 -0
  227. data/lib/active_record/type/date_time.rb +9 -0
  228. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  229. data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
  230. data/lib/active_record/type/internal/timezone.rb +17 -0
  231. data/lib/active_record/type/json.rb +30 -0
  232. data/lib/active_record/type/serialized.rb +71 -0
  233. data/lib/active_record/type/text.rb +11 -0
  234. data/lib/active_record/type/time.rb +21 -0
  235. data/lib/active_record/type/type_map.rb +62 -0
  236. data/lib/active_record/type/unsigned_integer.rb +17 -0
  237. data/lib/active_record/type.rb +78 -0
  238. data/lib/active_record/type_caster/connection.rb +34 -0
  239. data/lib/active_record/type_caster/map.rb +20 -0
  240. data/lib/active_record/type_caster.rb +9 -0
  241. data/lib/active_record/validations/absence.rb +25 -0
  242. data/lib/active_record/validations/associated.rb +35 -18
  243. data/lib/active_record/validations/length.rb +26 -0
  244. data/lib/active_record/validations/presence.rb +68 -0
  245. data/lib/active_record/validations/uniqueness.rb +123 -77
  246. data/lib/active_record/validations.rb +54 -43
  247. data/lib/active_record/version.rb +7 -7
  248. data/lib/active_record.rb +97 -49
  249. data/lib/arel/alias_predication.rb +9 -0
  250. data/lib/arel/attributes/attribute.rb +37 -0
  251. data/lib/arel/attributes.rb +22 -0
  252. data/lib/arel/collectors/bind.rb +24 -0
  253. data/lib/arel/collectors/composite.rb +31 -0
  254. data/lib/arel/collectors/plain_string.rb +20 -0
  255. data/lib/arel/collectors/sql_string.rb +20 -0
  256. data/lib/arel/collectors/substitute_binds.rb +28 -0
  257. data/lib/arel/crud.rb +42 -0
  258. data/lib/arel/delete_manager.rb +18 -0
  259. data/lib/arel/errors.rb +9 -0
  260. data/lib/arel/expressions.rb +29 -0
  261. data/lib/arel/factory_methods.rb +49 -0
  262. data/lib/arel/insert_manager.rb +49 -0
  263. data/lib/arel/math.rb +45 -0
  264. data/lib/arel/nodes/and.rb +32 -0
  265. data/lib/arel/nodes/ascending.rb +23 -0
  266. data/lib/arel/nodes/binary.rb +52 -0
  267. data/lib/arel/nodes/bind_param.rb +36 -0
  268. data/lib/arel/nodes/case.rb +55 -0
  269. data/lib/arel/nodes/casted.rb +50 -0
  270. data/lib/arel/nodes/comment.rb +29 -0
  271. data/lib/arel/nodes/count.rb +12 -0
  272. data/lib/arel/nodes/delete_statement.rb +45 -0
  273. data/lib/arel/nodes/descending.rb +23 -0
  274. data/lib/arel/nodes/equality.rb +18 -0
  275. data/lib/arel/nodes/extract.rb +24 -0
  276. data/lib/arel/nodes/false.rb +16 -0
  277. data/lib/arel/nodes/full_outer_join.rb +8 -0
  278. data/lib/arel/nodes/function.rb +44 -0
  279. data/lib/arel/nodes/grouping.rb +8 -0
  280. data/lib/arel/nodes/in.rb +8 -0
  281. data/lib/arel/nodes/infix_operation.rb +80 -0
  282. data/lib/arel/nodes/inner_join.rb +8 -0
  283. data/lib/arel/nodes/insert_statement.rb +37 -0
  284. data/lib/arel/nodes/join_source.rb +20 -0
  285. data/lib/arel/nodes/matches.rb +18 -0
  286. data/lib/arel/nodes/named_function.rb +23 -0
  287. data/lib/arel/nodes/node.rb +50 -0
  288. data/lib/arel/nodes/node_expression.rb +13 -0
  289. data/lib/arel/nodes/outer_join.rb +8 -0
  290. data/lib/arel/nodes/over.rb +15 -0
  291. data/lib/arel/nodes/regexp.rb +16 -0
  292. data/lib/arel/nodes/right_outer_join.rb +8 -0
  293. data/lib/arel/nodes/select_core.rb +67 -0
  294. data/lib/arel/nodes/select_statement.rb +41 -0
  295. data/lib/arel/nodes/sql_literal.rb +16 -0
  296. data/lib/arel/nodes/string_join.rb +11 -0
  297. data/lib/arel/nodes/table_alias.rb +27 -0
  298. data/lib/arel/nodes/terminal.rb +16 -0
  299. data/lib/arel/nodes/true.rb +16 -0
  300. data/lib/arel/nodes/unary.rb +45 -0
  301. data/lib/arel/nodes/unary_operation.rb +20 -0
  302. data/lib/arel/nodes/unqualified_column.rb +22 -0
  303. data/lib/arel/nodes/update_statement.rb +41 -0
  304. data/lib/arel/nodes/values_list.rb +9 -0
  305. data/lib/arel/nodes/window.rb +126 -0
  306. data/lib/arel/nodes/with.rb +11 -0
  307. data/lib/arel/nodes.rb +68 -0
  308. data/lib/arel/order_predications.rb +13 -0
  309. data/lib/arel/predications.rb +257 -0
  310. data/lib/arel/select_manager.rb +271 -0
  311. data/lib/arel/table.rb +110 -0
  312. data/lib/arel/tree_manager.rb +72 -0
  313. data/lib/arel/update_manager.rb +34 -0
  314. data/lib/arel/visitors/depth_first.rb +204 -0
  315. data/lib/arel/visitors/dot.rb +297 -0
  316. data/lib/arel/visitors/ibm_db.rb +34 -0
  317. data/lib/arel/visitors/informix.rb +62 -0
  318. data/lib/arel/visitors/mssql.rb +157 -0
  319. data/lib/arel/visitors/mysql.rb +83 -0
  320. data/lib/arel/visitors/oracle.rb +159 -0
  321. data/lib/arel/visitors/oracle12.rb +66 -0
  322. data/lib/arel/visitors/postgresql.rb +110 -0
  323. data/lib/arel/visitors/sqlite.rb +39 -0
  324. data/lib/arel/visitors/to_sql.rb +889 -0
  325. data/lib/arel/visitors/visitor.rb +46 -0
  326. data/lib/arel/visitors/where_sql.rb +23 -0
  327. data/lib/arel/visitors.rb +20 -0
  328. data/lib/arel/window_predications.rb +9 -0
  329. data/lib/arel.rb +51 -0
  330. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  331. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  332. data/lib/rails/generators/active_record/migration/migration_generator.rb +59 -9
  333. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  334. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +48 -0
  335. data/lib/rails/generators/active_record/migration.rb +41 -8
  336. data/lib/rails/generators/active_record/model/model_generator.rb +24 -22
  337. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  338. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +1 -1
  339. data/lib/rails/generators/active_record.rb +10 -16
  340. metadata +285 -149
  341. data/examples/associations.png +0 -0
  342. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -63
  343. data/lib/active_record/associations/join_helper.rb +0 -55
  344. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  345. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  346. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
  347. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  348. data/lib/active_record/associations/preloader/has_many_through.rb +0 -15
  349. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  350. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  351. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  352. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
  353. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -188
  354. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -426
  355. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -579
  356. data/lib/active_record/dynamic_finder_match.rb +0 -68
  357. data/lib/active_record/dynamic_scope_match.rb +0 -23
  358. data/lib/active_record/fixtures/file.rb +0 -65
  359. data/lib/active_record/identity_map.rb +0 -162
  360. data/lib/active_record/observer.rb +0 -121
  361. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  362. data/lib/active_record/serializers/xml_serializer.rb +0 -203
  363. data/lib/active_record/session_store.rb +0 -358
  364. data/lib/active_record/test_case.rb +0 -73
  365. data/lib/rails/generators/active_record/migration/templates/migration.rb +0 -34
  366. data/lib/rails/generators/active_record/model/templates/migration.rb +0 -15
  367. data/lib/rails/generators/active_record/model/templates/model.rb +0 -12
  368. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  369. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  370. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  371. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -1,124 +1,196 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters # :nodoc:
3
5
  module DatabaseStatements
6
+ def initialize
7
+ super
8
+ reset_transaction
9
+ end
10
+
4
11
  # Converts an arel AST to SQL
5
- def to_sql(arel, binds = [])
6
- if arel.respond_to?(:ast)
7
- visitor.accept(arel.ast) do
8
- quote(*binds.shift.reverse)
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 = []) # :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
+ if prepared_statements
25
+ sql, binds = visitor.compile(arel_or_sql_string.ast, collector)
26
+
27
+ if binds.length > bind_params_length
28
+ unprepared_statement do
29
+ sql, binds = to_sql_and_binds(arel_or_sql_string)
30
+ visitor.preparable = false
31
+ end
32
+ end
33
+ else
34
+ sql = visitor.compile(arel_or_sql_string.ast, collector)
9
35
  end
36
+ [sql.freeze, binds]
37
+ else
38
+ visitor.preparable = false if prepared_statements
39
+ [arel_or_sql_string.dup.freeze, binds]
40
+ end
41
+ end
42
+ private :to_sql_and_binds
43
+
44
+ # This is used in the StatementCache object. It returns an object that
45
+ # can be used to query the database repeatedly.
46
+ def cacheable_query(klass, arel) # :nodoc:
47
+ if prepared_statements
48
+ sql, binds = visitor.compile(arel.ast, collector)
49
+ query = klass.query(sql)
10
50
  else
11
- arel
51
+ collector = klass.partial_query_collector
52
+ parts, binds = visitor.compile(arel.ast, collector)
53
+ query = klass.partial_query(parts)
12
54
  end
55
+ [query, binds]
13
56
  end
14
57
 
15
- # Returns an array of record hashes with the column names as keys and
16
- # column values as values.
17
- def select_all(arel, name = nil, binds = [])
18
- select(to_sql(arel, binds), name, binds)
58
+ # Returns an ActiveRecord::Result instance.
59
+ def select_all(arel, name = nil, binds = [], preparable: nil)
60
+ arel = arel_from_relation(arel)
61
+ sql, binds = to_sql_and_binds(arel, binds)
62
+
63
+ if preparable.nil?
64
+ preparable = prepared_statements ? visitor.preparable : false
65
+ end
66
+
67
+ if prepared_statements && preparable
68
+ select_prepared(sql, name, binds)
69
+ else
70
+ select(sql, name, binds)
71
+ end
19
72
  end
20
73
 
21
74
  # Returns a record hash with the column names as keys and column values
22
75
  # as values.
23
- def select_one(arel, name = nil)
24
- result = select_all(arel, name)
25
- result.first if result
76
+ def select_one(arel, name = nil, binds = [])
77
+ select_all(arel, name, binds).first
26
78
  end
27
79
 
28
80
  # Returns a single value from a record
29
- def select_value(arel, name = nil)
30
- if result = select_one(arel, name)
31
- result.values.first
32
- end
81
+ def select_value(arel, name = nil, binds = [])
82
+ single_value_from_rows(select_rows(arel, name, binds))
33
83
  end
34
84
 
35
85
  # Returns an array of the values of the first column in a select:
36
86
  # select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
37
- def select_values(arel, name = nil)
38
- result = select_rows(to_sql(arel, []), name)
39
- result.map { |v| v[0] }
87
+ def select_values(arel, name = nil, binds = [])
88
+ select_rows(arel, name, binds).map(&:first)
40
89
  end
41
90
 
42
91
  # Returns an array of arrays containing the field values.
43
92
  # Order is the same as that returned by +columns+.
44
- def select_rows(sql, name = nil)
93
+ def select_rows(arel, name = nil, binds = [])
94
+ select_all(arel, name, binds).rows
95
+ end
96
+
97
+ def query_value(sql, name = nil) # :nodoc:
98
+ single_value_from_rows(query(sql, name))
99
+ end
100
+
101
+ def query_values(sql, name = nil) # :nodoc:
102
+ query(sql, name).map(&:first)
45
103
  end
46
- undef_method :select_rows
47
104
 
48
- # Executes the SQL statement in the context of this connection.
105
+ def query(sql, name = nil) # :nodoc:
106
+ exec_query(sql, name).rows
107
+ end
108
+
109
+ # Determines whether the SQL statement is a write query.
110
+ def write_query?(sql)
111
+ raise NotImplementedError
112
+ end
113
+
114
+ # Executes the SQL statement in the context of this connection and returns
115
+ # the raw result from the connection adapter.
116
+ # Note: depending on your database connector, the result returned by this
117
+ # method may be manually memory managed. Consider using the exec_query
118
+ # wrapper instead.
49
119
  def execute(sql, name = nil)
120
+ raise NotImplementedError
50
121
  end
51
- undef_method :execute
52
122
 
53
123
  # Executes +sql+ statement in the context of this connection using
54
124
  # +binds+ as the bind substitutes. +name+ is logged along with
55
125
  # the executed +sql+ statement.
56
- def exec_query(sql, name = 'SQL', binds = [])
126
+ def exec_query(sql, name = "SQL", binds = [], prepare: false)
127
+ raise NotImplementedError
57
128
  end
58
129
 
59
130
  # Executes insert +sql+ statement in the context of this connection using
60
- # +binds+ as the bind substitutes. +name+ is the logged along with
131
+ # +binds+ as the bind substitutes. +name+ is logged along with
61
132
  # the executed +sql+ statement.
62
- def exec_insert(sql, name, binds)
133
+ def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
134
+ sql, binds = sql_for_insert(sql, pk, binds)
63
135
  exec_query(sql, name, binds)
64
136
  end
65
137
 
66
138
  # Executes delete +sql+ statement in the context of this connection using
67
- # +binds+ as the bind substitutes. +name+ is the logged along with
139
+ # +binds+ as the bind substitutes. +name+ is logged along with
68
140
  # the executed +sql+ statement.
69
- def exec_delete(sql, name, binds)
141
+ def exec_delete(sql, name = nil, binds = [])
70
142
  exec_query(sql, name, binds)
71
143
  end
72
144
 
73
145
  # Executes update +sql+ statement in the context of this connection using
74
- # +binds+ as the bind substitutes. +name+ is the logged along with
146
+ # +binds+ as the bind substitutes. +name+ is logged along with
75
147
  # the executed +sql+ statement.
76
- def exec_update(sql, name, binds)
148
+ def exec_update(sql, name = nil, binds = [])
77
149
  exec_query(sql, name, binds)
78
150
  end
79
151
 
80
- # Returns the last auto-generated ID from the affected table.
152
+ # Executes an INSERT query and returns the new record's ID
81
153
  #
82
- # +id_value+ will be returned unless the value is nil, in
154
+ # +id_value+ will be returned unless the value is +nil+, in
83
155
  # which case the database will attempt to calculate the last inserted
84
156
  # id and return that value.
85
157
  #
86
158
  # If the next id was calculated in advance (as in Oracle), it should be
87
159
  # passed in as +id_value+.
88
160
  def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
89
- sql, binds = sql_for_insert(to_sql(arel, binds), pk, id_value, sequence_name, binds)
90
- value = exec_insert(sql, name, binds)
161
+ sql, binds = to_sql_and_binds(arel, binds)
162
+ value = exec_insert(sql, name, binds, pk, sequence_name)
91
163
  id_value || last_inserted_id(value)
92
164
  end
165
+ alias create insert
93
166
 
94
167
  # Executes the update statement and returns the number of rows affected.
95
168
  def update(arel, name = nil, binds = [])
96
- exec_update(to_sql(arel, binds), name, binds)
169
+ sql, binds = to_sql_and_binds(arel, binds)
170
+ exec_update(sql, name, binds)
97
171
  end
98
172
 
99
173
  # Executes the delete statement and returns the number of rows affected.
100
174
  def delete(arel, name = nil, binds = [])
101
- exec_delete(to_sql(arel, binds), name, binds)
175
+ sql, binds = to_sql_and_binds(arel, binds)
176
+ exec_delete(sql, name, binds)
102
177
  end
103
178
 
104
- # Checks whether there is currently no transaction active. This is done
105
- # by querying the database driver, and does not use the transaction
106
- # house-keeping information recorded by #increment_open_transactions and
107
- # friends.
108
- #
109
- # Returns true if there is no transaction active, false if there is a
110
- # transaction active, and nil if this information is unknown.
111
- #
112
- # Not all adapters supports transaction state introspection. Currently,
113
- # only the PostgreSQL adapter supports this.
114
- def outside_transaction?
115
- nil
179
+ # Executes the truncate statement.
180
+ def truncate(table_name, name = nil)
181
+ execute(build_truncate_statements(table_name), name)
116
182
  end
117
183
 
118
- # Returns +true+ when the connection adapter supports prepared statement
119
- # caching, otherwise returns +false+
120
- def supports_statement_cache?
121
- false
184
+ def truncate_tables(*table_names) # :nodoc:
185
+ return if table_names.empty?
186
+
187
+ with_multi_statements do
188
+ disable_referential_integrity do
189
+ Array(build_truncate_statements(*table_names)).each do |sql|
190
+ execute_batch(sql, "Truncate Tables")
191
+ end
192
+ end
193
+ end
122
194
  end
123
195
 
124
196
  # Runs the given block in a database transaction, and returns the result
@@ -132,8 +204,9 @@ module ActiveRecord
132
204
  #
133
205
  # In order to get around this problem, #transaction will emulate the effect
134
206
  # of nested transactions, by using savepoints:
135
- # http://dev.mysql.com/doc/refman/5.0/en/savepoint.html
136
- # Savepoints are supported by MySQL and PostgreSQL, but not SQLite3.
207
+ # https://dev.mysql.com/doc/refman/5.7/en/savepoint.html
208
+ # Savepoints are supported by MySQL and PostgreSQL. SQLite3 version >= '3.6.8'
209
+ # supports savepoints.
137
210
  #
138
211
  # It is safe to call this method if a database transaction is already open,
139
212
  # i.e. if #transaction is called within another #transaction block. In case
@@ -158,101 +231,112 @@ module ActiveRecord
158
231
  # already-automatically-released savepoints:
159
232
  #
160
233
  # Model.connection.transaction do # BEGIN
161
- # Model.connection.transaction(:requires_new => true) do # CREATE SAVEPOINT active_record_1
234
+ # Model.connection.transaction(requires_new: true) do # CREATE SAVEPOINT active_record_1
162
235
  # Model.connection.create_table(...)
163
236
  # # active_record_1 now automatically released
164
237
  # end # RELEASE SAVEPOINT active_record_1 <--- BOOM! database error!
165
238
  # end
166
- def transaction(options = {})
167
- options.assert_valid_keys :requires_new, :joinable
168
-
169
- last_transaction_joinable = defined?(@transaction_joinable) ? @transaction_joinable : nil
170
- if options.has_key?(:joinable)
171
- @transaction_joinable = options[:joinable]
172
- else
173
- @transaction_joinable = true
174
- end
175
- requires_new = options[:requires_new] || !last_transaction_joinable
176
-
177
- transaction_open = false
178
- @_current_transaction_records ||= []
179
-
180
- begin
181
- if block_given?
182
- if requires_new || open_transactions == 0
183
- if open_transactions == 0
184
- begin_db_transaction
185
- elsif requires_new
186
- create_savepoint
187
- end
188
- increment_open_transactions
189
- transaction_open = true
190
- @_current_transaction_records.push([])
191
- end
192
- yield
193
- end
194
- rescue Exception => database_transaction_rollback
195
- if transaction_open && !outside_transaction?
196
- transaction_open = false
197
- decrement_open_transactions
198
- if open_transactions == 0
199
- rollback_db_transaction
200
- rollback_transaction_records(true)
201
- else
202
- rollback_to_savepoint
203
- rollback_transaction_records(false)
204
- end
205
- end
206
- raise unless database_transaction_rollback.is_a?(ActiveRecord::Rollback)
207
- end
208
- ensure
209
- @transaction_joinable = last_transaction_joinable
210
-
211
- if outside_transaction?
212
- @open_transactions = 0
213
- elsif transaction_open
214
- decrement_open_transactions
215
- begin
216
- if open_transactions == 0
217
- commit_db_transaction
218
- commit_transaction_records
219
- else
220
- release_savepoint
221
- save_point_records = @_current_transaction_records.pop
222
- unless save_point_records.blank?
223
- @_current_transaction_records.push([]) if @_current_transaction_records.empty?
224
- @_current_transaction_records.last.concat(save_point_records)
225
- end
226
- end
227
- rescue Exception => database_transaction_rollback
228
- if open_transactions == 0
229
- rollback_db_transaction
230
- rollback_transaction_records(true)
231
- else
232
- rollback_to_savepoint
233
- rollback_transaction_records(false)
234
- end
235
- raise
239
+ #
240
+ # == Transaction isolation
241
+ #
242
+ # If your database supports setting the isolation level for a transaction, you can set
243
+ # it like so:
244
+ #
245
+ # Post.transaction(isolation: :serializable) do
246
+ # # ...
247
+ # end
248
+ #
249
+ # Valid isolation levels are:
250
+ #
251
+ # * <tt>:read_uncommitted</tt>
252
+ # * <tt>:read_committed</tt>
253
+ # * <tt>:repeatable_read</tt>
254
+ # * <tt>:serializable</tt>
255
+ #
256
+ # You should consult the documentation for your database to understand the
257
+ # semantics of these different levels:
258
+ #
259
+ # * https://www.postgresql.org/docs/current/static/transaction-iso.html
260
+ # * https://dev.mysql.com/doc/refman/5.7/en/set-transaction.html
261
+ #
262
+ # An ActiveRecord::TransactionIsolationError will be raised if:
263
+ #
264
+ # * The adapter does not support setting the isolation level
265
+ # * You are joining an existing open transaction
266
+ # * You are creating a nested (savepoint) transaction
267
+ #
268
+ # The mysql2 and postgresql adapters support setting the transaction
269
+ # isolation level.
270
+ def transaction(requires_new: nil, isolation: nil, joinable: true)
271
+ if !requires_new && current_transaction.joinable?
272
+ if isolation
273
+ raise ActiveRecord::TransactionIsolationError, "cannot set isolation when joining a transaction"
236
274
  end
275
+ yield
276
+ else
277
+ transaction_manager.within_new_transaction(isolation: isolation, joinable: joinable) { yield }
237
278
  end
279
+ rescue ActiveRecord::Rollback
280
+ # rollbacks are silently swallowed
281
+ end
282
+
283
+ attr_reader :transaction_manager #:nodoc:
284
+
285
+ delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction,
286
+ :commit_transaction, :rollback_transaction, :materialize_transactions,
287
+ :disable_lazy_transactions!, :enable_lazy_transactions!, to: :transaction_manager
288
+
289
+ def transaction_open?
290
+ current_transaction.open?
291
+ end
292
+
293
+ def reset_transaction #:nodoc:
294
+ @transaction_manager = ConnectionAdapters::TransactionManager.new(self)
238
295
  end
239
296
 
240
297
  # Register a record with the current transaction so that its after_commit and after_rollback callbacks
241
298
  # can be called.
242
299
  def add_transaction_record(record)
243
- last_batch = @_current_transaction_records.last
244
- last_batch << record if last_batch
300
+ current_transaction.add_record(record)
301
+ end
302
+
303
+ def transaction_state
304
+ current_transaction.state
245
305
  end
246
306
 
247
307
  # Begins the transaction (and turns off auto-committing).
248
308
  def begin_db_transaction() end
249
309
 
310
+ def transaction_isolation_levels
311
+ {
312
+ read_uncommitted: "READ UNCOMMITTED",
313
+ read_committed: "READ COMMITTED",
314
+ repeatable_read: "REPEATABLE READ",
315
+ serializable: "SERIALIZABLE"
316
+ }
317
+ end
318
+
319
+ # Begins the transaction with the isolation level set. Raises an error by
320
+ # default; adapters that support setting the isolation level should implement
321
+ # this method.
322
+ def begin_isolated_db_transaction(isolation)
323
+ raise ActiveRecord::TransactionIsolationError, "adapter does not support setting transaction isolation"
324
+ end
325
+
250
326
  # Commits the transaction (and turns on auto-committing).
251
327
  def commit_db_transaction() end
252
328
 
253
329
  # Rolls back the transaction (and turns on auto-committing). Must be
254
330
  # done if the transaction block raises an exception or returns false.
255
- def rollback_db_transaction() end
331
+ def rollback_db_transaction
332
+ exec_rollback_db_transaction
333
+ end
334
+
335
+ def exec_rollback_db_transaction() end #:nodoc:
336
+
337
+ def rollback_to_savepoint(name = nil)
338
+ exec_rollback_to_savepoint(name)
339
+ end
256
340
 
257
341
  def default_sequence_name(table, column)
258
342
  nil
@@ -265,126 +349,164 @@ module ActiveRecord
265
349
 
266
350
  # Inserts the given fixture into the table. Overridden in adapters that require
267
351
  # something beyond a simple insert (eg. Oracle).
352
+ # Most of adapters should implement `insert_fixtures_set` that leverages bulk SQL insert.
353
+ # We keep this method to provide fallback
354
+ # for databases like sqlite that do not support bulk inserts.
268
355
  def insert_fixture(fixture, table_name)
269
- columns = Hash[columns(table_name).map { |c| [c.name, c] }]
270
-
271
- key_list = []
272
- value_list = fixture.map do |name, value|
273
- key_list << quote_column_name(name)
274
- quote(value, columns[name])
275
- end
276
-
277
- execute "INSERT INTO #{quote_table_name(table_name)} (#{key_list.join(', ')}) VALUES (#{value_list.join(', ')})", 'Fixture Insert'
356
+ execute(build_fixture_sql(Array.wrap(fixture), table_name), "Fixture Insert")
278
357
  end
279
358
 
280
- def empty_insert_statement_value
281
- "VALUES(DEFAULT)"
282
- end
359
+ def insert_fixtures_set(fixture_set, tables_to_delete = [])
360
+ fixture_inserts = build_fixture_statements(fixture_set)
361
+ table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name(table)}" }
362
+ total_sql = Array(combine_multi_statements(table_deletes + fixture_inserts))
283
363
 
284
- def case_sensitive_equality_operator
285
- "="
364
+ with_multi_statements do
365
+ disable_referential_integrity do
366
+ transaction(requires_new: true) do
367
+ total_sql.each do |sql|
368
+ execute_batch(sql, "Fixtures Load")
369
+ end
370
+ end
371
+ end
372
+ end
286
373
  end
287
374
 
288
- def limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key)
289
- "WHERE #{quoted_primary_key} IN (SELECT #{quoted_primary_key} FROM #{quoted_table_name} #{where_sql})"
375
+ def empty_insert_statement_value(primary_key = nil)
376
+ "DEFAULT VALUES"
290
377
  end
291
378
 
292
379
  # Sanitizes the given LIMIT parameter in order to prevent SQL injection.
293
380
  #
294
381
  # The +limit+ may be anything that can evaluate to a string via #to_s. It
295
- # should look like an integer, or a comma-delimited list of integers, or
296
- # an Arel SQL literal.
382
+ # should look like an integer, or an Arel SQL literal.
297
383
  #
298
384
  # Returns Integer and Arel::Nodes::SqlLiteral limits as is.
299
- # Returns the sanitized limit parameter, either as an integer, or as a
300
- # string which contains a comma-delimited list of integers.
301
385
  def sanitize_limit(limit)
302
386
  if limit.is_a?(Integer) || limit.is_a?(Arel::Nodes::SqlLiteral)
303
387
  limit
304
- elsif limit.to_s =~ /,/
305
- Arel.sql limit.to_s.split(',').map{ |i| Integer(i) }.join(',')
306
388
  else
307
389
  Integer(limit)
308
390
  end
309
391
  end
310
392
 
311
- # The default strategy for an UPDATE with joins is to use a subquery. This doesn't work
312
- # on mysql (even when aliasing the tables), but mysql allows using JOIN directly in
313
- # an UPDATE statement, so in the mysql adapters we redefine this to do that.
314
- def join_to_update(update, select) #:nodoc:
315
- subselect = select.clone
316
- subselect.projections = [update.key]
317
-
318
- update.where update.key.in(subselect)
319
- end
320
-
321
- protected
322
- # Returns an array of record hashes with the column names as keys and
323
- # column values as values.
324
- def select(sql, name = nil, binds = [])
393
+ # Fixture value is quoted by Arel, however scalar values
394
+ # are not quotable. In this case we want to convert
395
+ # the column value to YAML.
396
+ def with_yaml_fallback(value) # :nodoc:
397
+ if value.is_a?(Hash) || value.is_a?(Array)
398
+ YAML.dump(value)
399
+ else
400
+ value
325
401
  end
326
- undef_method :select
402
+ end
327
403
 
328
- # Returns the last auto-generated ID from the affected table.
329
- def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
404
+ private
405
+ def execute_batch(sql, name = nil)
330
406
  execute(sql, name)
331
- id_value
332
407
  end
333
408
 
334
- # Executes the update statement and returns the number of rows affected.
335
- def update_sql(sql, name = nil)
336
- execute(sql, name)
337
- end
409
+ DEFAULT_INSERT_VALUE = Arel.sql("DEFAULT").freeze
410
+ private_constant :DEFAULT_INSERT_VALUE
338
411
 
339
- # Executes the delete statement and returns the number of rows affected.
340
- def delete_sql(sql, name = nil)
341
- update_sql(sql, name)
412
+ def default_insert_value(column)
413
+ DEFAULT_INSERT_VALUE
342
414
  end
343
415
 
344
- # Send a rollback message to all records after they have been rolled back. If rollback
345
- # is false, only rollback records since the last save point.
346
- def rollback_transaction_records(rollback)
347
- if rollback
348
- records = @_current_transaction_records.flatten
349
- @_current_transaction_records.clear
350
- else
351
- records = @_current_transaction_records.pop
352
- end
416
+ def build_fixture_sql(fixtures, table_name)
417
+ columns = schema_cache.columns_hash(table_name)
353
418
 
354
- unless records.blank?
355
- records.uniq.each do |record|
356
- begin
357
- record.rolledback!(rollback)
358
- rescue Exception => e
359
- record.logger.error(e) if record.respond_to?(:logger) && record.logger
419
+ values_list = fixtures.map do |fixture|
420
+ fixture = fixture.stringify_keys
421
+
422
+ unknown_columns = fixture.keys - columns.keys
423
+ if unknown_columns.any?
424
+ raise Fixture::FixtureError, %(table "#{table_name}" has no columns named #{unknown_columns.map(&:inspect).join(', ')}.)
425
+ end
426
+
427
+ columns.map do |name, column|
428
+ if fixture.key?(name)
429
+ type = lookup_cast_type_from_column(column)
430
+ with_yaml_fallback(type.serialize(fixture[name]))
431
+ else
432
+ default_insert_value(column)
360
433
  end
361
434
  end
362
435
  end
363
- end
364
436
 
365
- # Send a commit message to all records after they have been committed.
366
- def commit_transaction_records
367
- records = @_current_transaction_records.flatten
368
- @_current_transaction_records.clear
369
- unless records.blank?
370
- records.uniq.each do |record|
371
- begin
372
- record.committed!
373
- rescue Exception => e
374
- record.logger.error(e) if record.respond_to?(:logger) && record.logger
437
+ table = Arel::Table.new(table_name)
438
+ manager = Arel::InsertManager.new
439
+ manager.into(table)
440
+
441
+ if values_list.size == 1
442
+ values = values_list.shift
443
+ new_values = []
444
+ columns.each_key.with_index { |column, i|
445
+ unless values[i].equal?(DEFAULT_INSERT_VALUE)
446
+ new_values << values[i]
447
+ manager.columns << table[column]
375
448
  end
376
- end
449
+ }
450
+ values_list << new_values
451
+ else
452
+ columns.each_key { |column| manager.columns << table[column] }
377
453
  end
454
+
455
+ manager.values = manager.create_values_list(values_list)
456
+ manager.to_sql
378
457
  end
379
458
 
380
- def sql_for_insert(sql, pk, id_value, sequence_name, binds)
381
- [sql, binds]
382
- end
459
+ def build_fixture_statements(fixture_set)
460
+ fixture_set.map do |table_name, fixtures|
461
+ next if fixtures.empty?
462
+ build_fixture_sql(fixtures, table_name)
463
+ end.compact
464
+ end
383
465
 
384
- def last_inserted_id(result)
385
- row = result.rows.first
386
- row && row.first
387
- end
466
+ def build_truncate_statements(*table_names)
467
+ truncate_tables = table_names.map do |table_name|
468
+ "TRUNCATE TABLE #{quote_table_name(table_name)}"
469
+ end
470
+ combine_multi_statements(truncate_tables)
471
+ end
472
+
473
+ def with_multi_statements
474
+ yield
475
+ end
476
+
477
+ def combine_multi_statements(total_sql)
478
+ total_sql.join(";\n")
479
+ end
480
+
481
+ # Returns an ActiveRecord::Result instance.
482
+ def select(sql, name = nil, binds = [])
483
+ exec_query(sql, name, binds, prepare: false)
484
+ end
485
+
486
+ def select_prepared(sql, name = nil, binds = [])
487
+ exec_query(sql, name, binds, prepare: true)
488
+ end
489
+
490
+ def sql_for_insert(sql, pk, binds)
491
+ [sql, binds]
492
+ end
493
+
494
+ def last_inserted_id(result)
495
+ single_value_from_rows(result.rows)
496
+ end
497
+
498
+ def single_value_from_rows(rows)
499
+ row = rows.first
500
+ row && row.first
501
+ end
502
+
503
+ def arel_from_relation(relation)
504
+ if relation.is_a?(Relation)
505
+ relation.arel
506
+ else
507
+ relation
508
+ end
509
+ end
388
510
  end
389
511
  end
390
512
  end