activerecord 4.2.0 → 6.1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (374) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1221 -796
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +15 -14
  5. data/examples/performance.rb +33 -32
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/aggregations.rb +267 -249
  8. data/lib/active_record/association_relation.rb +45 -7
  9. data/lib/active_record/associations/alias_tracker.rb +40 -43
  10. data/lib/active_record/associations/association.rb +172 -67
  11. data/lib/active_record/associations/association_scope.rb +105 -129
  12. data/lib/active_record/associations/belongs_to_association.rb +85 -59
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
  14. data/lib/active_record/associations/builder/association.rb +57 -43
  15. data/lib/active_record/associations/builder/belongs_to.rb +74 -57
  16. data/lib/active_record/associations/builder/collection_association.rb +15 -33
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +57 -70
  18. data/lib/active_record/associations/builder/has_many.rb +13 -5
  19. data/lib/active_record/associations/builder/has_one.rb +44 -6
  20. data/lib/active_record/associations/builder/singular_association.rb +16 -10
  21. data/lib/active_record/associations/collection_association.rb +168 -279
  22. data/lib/active_record/associations/collection_proxy.rb +263 -155
  23. data/lib/active_record/associations/foreign_association.rb +33 -0
  24. data/lib/active_record/associations/has_many_association.rb +57 -84
  25. data/lib/active_record/associations/has_many_through_association.rb +70 -82
  26. data/lib/active_record/associations/has_one_association.rb +74 -47
  27. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  28. data/lib/active_record/associations/join_dependency/join_association.rb +54 -73
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  31. data/lib/active_record/associations/join_dependency.rb +175 -164
  32. data/lib/active_record/associations/preloader/association.rb +107 -112
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  34. data/lib/active_record/associations/preloader.rb +99 -96
  35. data/lib/active_record/associations/singular_association.rb +18 -45
  36. data/lib/active_record/associations/through_association.rb +49 -24
  37. data/lib/active_record/associations.rb +1845 -1597
  38. data/lib/active_record/attribute_assignment.rb +59 -185
  39. data/lib/active_record/attribute_methods/before_type_cast.rb +20 -7
  40. data/lib/active_record/attribute_methods/dirty.rb +168 -138
  41. data/lib/active_record/attribute_methods/primary_key.rb +93 -83
  42. data/lib/active_record/attribute_methods/query.rb +8 -10
  43. data/lib/active_record/attribute_methods/read.rb +19 -79
  44. data/lib/active_record/attribute_methods/serialization.rb +49 -24
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +59 -36
  46. data/lib/active_record/attribute_methods/write.rb +25 -56
  47. data/lib/active_record/attribute_methods.rb +153 -162
  48. data/lib/active_record/attributes.rb +234 -70
  49. data/lib/active_record/autosave_association.rb +157 -69
  50. data/lib/active_record/base.rb +49 -50
  51. data/lib/active_record/callbacks.rb +234 -79
  52. data/lib/active_record/coders/json.rb +3 -1
  53. data/lib/active_record/coders/yaml_column.rb +46 -13
  54. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -317
  55. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
  56. data/lib/active_record/connection_adapters/abstract/database_statements.rb +301 -113
  57. data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
  58. data/lib/active_record/connection_adapters/abstract/quoting.rb +187 -60
  59. data/lib/active_record/connection_adapters/abstract/savepoints.rb +9 -7
  60. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
  61. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +485 -253
  62. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  63. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +909 -263
  64. data/lib/active_record/connection_adapters/abstract/transaction.rb +254 -92
  65. data/lib/active_record/connection_adapters/abstract_adapter.rb +492 -221
  66. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +580 -608
  67. data/lib/active_record/connection_adapters/column.rb +67 -40
  68. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  69. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  70. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  71. data/lib/active_record/connection_adapters/mysql/database_statements.rb +196 -0
  72. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
  73. data/lib/active_record/connection_adapters/mysql/quoting.rb +96 -0
  74. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +97 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +103 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +91 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +271 -0
  78. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
  79. data/lib/active_record/connection_adapters/mysql2_adapter.rb +81 -199
  80. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  81. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +44 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +78 -161
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -57
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +5 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +8 -6
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +17 -13
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +6 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -20
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  98. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  101. data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +67 -51
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  109. data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -25
  110. data/lib/active_record/connection_adapters/postgresql/quoting.rb +171 -48
  111. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  112. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
  114. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
  115. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +499 -293
  116. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
  117. data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
  118. data/lib/active_record/connection_adapters/postgresql_adapter.rb +595 -382
  119. data/lib/active_record/connection_adapters/schema_cache.rb +191 -29
  120. data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
  121. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
  122. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  123. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +21 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  126. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  127. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
  128. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +322 -389
  129. data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
  130. data/lib/active_record/connection_adapters.rb +52 -0
  131. data/lib/active_record/connection_handling.rb +314 -41
  132. data/lib/active_record/core.rb +488 -243
  133. data/lib/active_record/counter_cache.rb +71 -50
  134. data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
  135. data/lib/active_record/database_configurations/database_config.rb +80 -0
  136. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  137. data/lib/active_record/database_configurations/url_config.rb +53 -0
  138. data/lib/active_record/database_configurations.rb +273 -0
  139. data/lib/active_record/delegated_type.rb +209 -0
  140. data/lib/active_record/destroy_association_async_job.rb +36 -0
  141. data/lib/active_record/dynamic_matchers.rb +87 -106
  142. data/lib/active_record/enum.rb +212 -94
  143. data/lib/active_record/errors.rb +225 -54
  144. data/lib/active_record/explain.rb +27 -11
  145. data/lib/active_record/explain_registry.rb +4 -2
  146. data/lib/active_record/explain_subscriber.rb +11 -6
  147. data/lib/active_record/fixture_set/file.rb +33 -14
  148. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  149. data/lib/active_record/fixture_set/render_context.rb +17 -0
  150. data/lib/active_record/fixture_set/table_row.rb +152 -0
  151. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  152. data/lib/active_record/fixtures.rb +273 -496
  153. data/lib/active_record/gem_version.rb +6 -4
  154. data/lib/active_record/inheritance.rb +175 -110
  155. data/lib/active_record/insert_all.rb +212 -0
  156. data/lib/active_record/integration.rb +121 -29
  157. data/lib/active_record/internal_metadata.rb +64 -0
  158. data/lib/active_record/legacy_yaml_adapter.rb +52 -0
  159. data/lib/active_record/locale/en.yml +3 -2
  160. data/lib/active_record/locking/optimistic.rb +103 -95
  161. data/lib/active_record/locking/pessimistic.rb +22 -6
  162. data/lib/active_record/log_subscriber.rb +93 -31
  163. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  164. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  165. data/lib/active_record/middleware/database_selector.rb +77 -0
  166. data/lib/active_record/migration/command_recorder.rb +185 -90
  167. data/lib/active_record/migration/compatibility.rb +298 -0
  168. data/lib/active_record/migration/join_table.rb +8 -7
  169. data/lib/active_record/migration.rb +685 -309
  170. data/lib/active_record/model_schema.rb +420 -113
  171. data/lib/active_record/nested_attributes.rb +265 -216
  172. data/lib/active_record/no_touching.rb +15 -2
  173. data/lib/active_record/null_relation.rb +24 -38
  174. data/lib/active_record/persistence.rb +574 -135
  175. data/lib/active_record/query_cache.rb +29 -23
  176. data/lib/active_record/querying.rb +50 -31
  177. data/lib/active_record/railtie.rb +175 -54
  178. data/lib/active_record/railties/console_sandbox.rb +3 -3
  179. data/lib/active_record/railties/controller_runtime.rb +34 -33
  180. data/lib/active_record/railties/databases.rake +533 -216
  181. data/lib/active_record/readonly_attributes.rb +9 -4
  182. data/lib/active_record/reflection.rb +485 -310
  183. data/lib/active_record/relation/batches/batch_enumerator.rb +85 -0
  184. data/lib/active_record/relation/batches.rb +217 -59
  185. data/lib/active_record/relation/calculations.rb +326 -244
  186. data/lib/active_record/relation/delegation.rb +76 -84
  187. data/lib/active_record/relation/finder_methods.rb +318 -256
  188. data/lib/active_record/relation/from_clause.rb +30 -0
  189. data/lib/active_record/relation/merger.rb +99 -84
  190. data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -25
  191. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
  192. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  193. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +57 -0
  194. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  195. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  196. data/lib/active_record/relation/predicate_builder.rb +139 -96
  197. data/lib/active_record/relation/query_attribute.rb +50 -0
  198. data/lib/active_record/relation/query_methods.rb +757 -409
  199. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  200. data/lib/active_record/relation/spawn_methods.rb +23 -21
  201. data/lib/active_record/relation/where_clause.rb +239 -0
  202. data/lib/active_record/relation.rb +554 -342
  203. data/lib/active_record/result.rb +91 -47
  204. data/lib/active_record/runtime_registry.rb +6 -4
  205. data/lib/active_record/sanitization.rb +134 -122
  206. data/lib/active_record/schema.rb +21 -24
  207. data/lib/active_record/schema_dumper.rb +141 -92
  208. data/lib/active_record/schema_migration.rb +24 -26
  209. data/lib/active_record/scoping/default.rb +96 -82
  210. data/lib/active_record/scoping/named.rb +78 -36
  211. data/lib/active_record/scoping.rb +45 -27
  212. data/lib/active_record/secure_token.rb +48 -0
  213. data/lib/active_record/serialization.rb +8 -6
  214. data/lib/active_record/signed_id.rb +116 -0
  215. data/lib/active_record/statement_cache.rb +89 -36
  216. data/lib/active_record/store.rb +133 -43
  217. data/lib/active_record/suppressor.rb +61 -0
  218. data/lib/active_record/table_metadata.rb +81 -0
  219. data/lib/active_record/tasks/database_tasks.rb +366 -129
  220. data/lib/active_record/tasks/mysql_database_tasks.rb +68 -100
  221. data/lib/active_record/tasks/postgresql_database_tasks.rb +87 -39
  222. data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -19
  223. data/lib/active_record/test_databases.rb +24 -0
  224. data/lib/active_record/test_fixtures.rb +291 -0
  225. data/lib/active_record/timestamp.rb +86 -43
  226. data/lib/active_record/touch_later.rb +65 -0
  227. data/lib/active_record/transactions.rb +181 -152
  228. data/lib/active_record/translation.rb +3 -1
  229. data/lib/active_record/type/adapter_specific_registry.rb +126 -0
  230. data/lib/active_record/type/date.rb +4 -41
  231. data/lib/active_record/type/date_time.rb +4 -38
  232. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  233. data/lib/active_record/type/hash_lookup_type_map.rb +12 -5
  234. data/lib/active_record/type/internal/timezone.rb +17 -0
  235. data/lib/active_record/type/json.rb +30 -0
  236. data/lib/active_record/type/serialized.rb +33 -15
  237. data/lib/active_record/type/text.rb +2 -2
  238. data/lib/active_record/type/time.rb +21 -16
  239. data/lib/active_record/type/type_map.rb +16 -19
  240. data/lib/active_record/type/unsigned_integer.rb +9 -8
  241. data/lib/active_record/type.rb +84 -23
  242. data/lib/active_record/type_caster/connection.rb +33 -0
  243. data/lib/active_record/type_caster/map.rb +23 -0
  244. data/lib/active_record/type_caster.rb +9 -0
  245. data/lib/active_record/validations/absence.rb +25 -0
  246. data/lib/active_record/validations/associated.rb +12 -4
  247. data/lib/active_record/validations/length.rb +26 -0
  248. data/lib/active_record/validations/numericality.rb +35 -0
  249. data/lib/active_record/validations/presence.rb +14 -13
  250. data/lib/active_record/validations/uniqueness.rb +65 -48
  251. data/lib/active_record/validations.rb +39 -35
  252. data/lib/active_record/version.rb +3 -1
  253. data/lib/active_record.rb +44 -28
  254. data/lib/arel/alias_predication.rb +9 -0
  255. data/lib/arel/attributes/attribute.rb +41 -0
  256. data/lib/arel/collectors/bind.rb +29 -0
  257. data/lib/arel/collectors/composite.rb +39 -0
  258. data/lib/arel/collectors/plain_string.rb +20 -0
  259. data/lib/arel/collectors/sql_string.rb +27 -0
  260. data/lib/arel/collectors/substitute_binds.rb +35 -0
  261. data/lib/arel/crud.rb +42 -0
  262. data/lib/arel/delete_manager.rb +18 -0
  263. data/lib/arel/errors.rb +9 -0
  264. data/lib/arel/expressions.rb +29 -0
  265. data/lib/arel/factory_methods.rb +49 -0
  266. data/lib/arel/insert_manager.rb +49 -0
  267. data/lib/arel/math.rb +45 -0
  268. data/lib/arel/nodes/and.rb +32 -0
  269. data/lib/arel/nodes/ascending.rb +23 -0
  270. data/lib/arel/nodes/binary.rb +126 -0
  271. data/lib/arel/nodes/bind_param.rb +44 -0
  272. data/lib/arel/nodes/case.rb +55 -0
  273. data/lib/arel/nodes/casted.rb +62 -0
  274. data/lib/arel/nodes/comment.rb +29 -0
  275. data/lib/arel/nodes/count.rb +12 -0
  276. data/lib/arel/nodes/delete_statement.rb +45 -0
  277. data/lib/arel/nodes/descending.rb +23 -0
  278. data/lib/arel/nodes/equality.rb +15 -0
  279. data/lib/arel/nodes/extract.rb +24 -0
  280. data/lib/arel/nodes/false.rb +16 -0
  281. data/lib/arel/nodes/full_outer_join.rb +8 -0
  282. data/lib/arel/nodes/function.rb +44 -0
  283. data/lib/arel/nodes/grouping.rb +11 -0
  284. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  285. data/lib/arel/nodes/in.rb +15 -0
  286. data/lib/arel/nodes/infix_operation.rb +92 -0
  287. data/lib/arel/nodes/inner_join.rb +8 -0
  288. data/lib/arel/nodes/insert_statement.rb +37 -0
  289. data/lib/arel/nodes/join_source.rb +20 -0
  290. data/lib/arel/nodes/matches.rb +18 -0
  291. data/lib/arel/nodes/named_function.rb +23 -0
  292. data/lib/arel/nodes/node.rb +51 -0
  293. data/lib/arel/nodes/node_expression.rb +13 -0
  294. data/lib/arel/nodes/ordering.rb +27 -0
  295. data/lib/arel/nodes/outer_join.rb +8 -0
  296. data/lib/arel/nodes/over.rb +15 -0
  297. data/lib/arel/nodes/regexp.rb +16 -0
  298. data/lib/arel/nodes/right_outer_join.rb +8 -0
  299. data/lib/arel/nodes/select_core.rb +67 -0
  300. data/lib/arel/nodes/select_statement.rb +41 -0
  301. data/lib/arel/nodes/sql_literal.rb +19 -0
  302. data/lib/arel/nodes/string_join.rb +11 -0
  303. data/lib/arel/nodes/table_alias.rb +31 -0
  304. data/lib/arel/nodes/terminal.rb +16 -0
  305. data/lib/arel/nodes/true.rb +16 -0
  306. data/lib/arel/nodes/unary.rb +44 -0
  307. data/lib/arel/nodes/unary_operation.rb +20 -0
  308. data/lib/arel/nodes/unqualified_column.rb +22 -0
  309. data/lib/arel/nodes/update_statement.rb +41 -0
  310. data/lib/arel/nodes/values_list.rb +9 -0
  311. data/lib/arel/nodes/window.rb +126 -0
  312. data/lib/arel/nodes/with.rb +11 -0
  313. data/lib/arel/nodes.rb +70 -0
  314. data/lib/arel/order_predications.rb +13 -0
  315. data/lib/arel/predications.rb +250 -0
  316. data/lib/arel/select_manager.rb +270 -0
  317. data/lib/arel/table.rb +118 -0
  318. data/lib/arel/tree_manager.rb +72 -0
  319. data/lib/arel/update_manager.rb +34 -0
  320. data/lib/arel/visitors/dot.rb +308 -0
  321. data/lib/arel/visitors/mysql.rb +93 -0
  322. data/lib/arel/visitors/postgresql.rb +120 -0
  323. data/lib/arel/visitors/sqlite.rb +38 -0
  324. data/lib/arel/visitors/to_sql.rb +899 -0
  325. data/lib/arel/visitors/visitor.rb +45 -0
  326. data/lib/arel/visitors.rb +13 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/arel.rb +54 -0
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  330. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  331. data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -37
  332. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +26 -0
  333. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +13 -10
  334. data/lib/rails/generators/active_record/migration.rb +35 -1
  335. data/lib/rails/generators/active_record/model/model_generator.rb +55 -22
  336. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  337. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  338. data/lib/rails/generators/active_record.rb +7 -5
  339. metadata +175 -65
  340. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  341. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  342. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  343. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  344. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  345. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  346. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  347. data/lib/active_record/attribute.rb +0 -149
  348. data/lib/active_record/attribute_decorators.rb +0 -66
  349. data/lib/active_record/attribute_set/builder.rb +0 -86
  350. data/lib/active_record/attribute_set.rb +0 -77
  351. data/lib/active_record/connection_adapters/connection_specification.rb +0 -275
  352. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  353. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  354. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  355. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  356. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  357. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  358. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  359. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  360. data/lib/active_record/type/big_integer.rb +0 -13
  361. data/lib/active_record/type/binary.rb +0 -50
  362. data/lib/active_record/type/boolean.rb +0 -30
  363. data/lib/active_record/type/decimal.rb +0 -40
  364. data/lib/active_record/type/decorator.rb +0 -14
  365. data/lib/active_record/type/float.rb +0 -19
  366. data/lib/active_record/type/integer.rb +0 -55
  367. data/lib/active_record/type/mutable.rb +0 -16
  368. data/lib/active_record/type/numeric.rb +0 -36
  369. data/lib/active_record/type/string.rb +0 -36
  370. data/lib/active_record/type/time_value.rb +0 -38
  371. data/lib/active_record/type/value.rb +0 -101
  372. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -22
  373. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
  374. /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters # :nodoc:
3
5
  module DatabaseStatements
@@ -7,29 +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
- def select_all(arel, name = nil, binds = [])
31
- arel, binds = binds_from_relation arel, binds
32
- select(to_sql(arel, binds), name, binds)
62
+ def select_all(arel, name = nil, binds = [], preparable: nil)
63
+ arel = arel_from_relation(arel)
64
+ sql, binds, preparable = to_sql_and_binds(arel, binds, preparable)
65
+
66
+ if prepared_statements && preparable
67
+ select_prepared(sql, name, binds)
68
+ else
69
+ select(sql, name, binds)
70
+ end
71
+ rescue ::RangeError
72
+ ActiveRecord::Result.new([], [])
33
73
  end
34
74
 
35
75
  # Returns a record hash with the column names as keys and column values
@@ -40,89 +80,127 @@ module ActiveRecord
40
80
 
41
81
  # Returns a single value from a record
42
82
  def select_value(arel, name = nil, binds = [])
43
- if result = select_one(arel, name, binds)
44
- result.values.first
45
- end
83
+ single_value_from_rows(select_rows(arel, name, binds))
46
84
  end
47
85
 
48
86
  # Returns an array of the values of the first column in a select:
49
87
  # select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
50
- def select_values(arel, name = nil)
51
- arel, binds = binds_from_relation arel, []
52
- select_rows(to_sql(arel, binds), name, binds).map(&:first)
88
+ def select_values(arel, name = nil, binds = [])
89
+ select_rows(arel, name, binds).map(&:first)
53
90
  end
54
91
 
55
92
  # Returns an array of arrays containing the field values.
56
93
  # Order is the same as that returned by +columns+.
57
- def select_rows(sql, name = nil, binds = [])
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))
58
100
  end
59
- undef_method :select_rows
60
101
 
61
- # Executes the SQL statement in the context of this connection.
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
113
+ end
114
+
115
+ # Executes the SQL statement in the context of this connection and returns
116
+ # the raw result from the connection adapter.
117
+ # Note: depending on your database connector, the result returned by this
118
+ # method may be manually memory managed. Consider using the exec_query
119
+ # wrapper instead.
62
120
  def execute(sql, name = nil)
121
+ raise NotImplementedError
63
122
  end
64
- undef_method :execute
65
123
 
66
124
  # Executes +sql+ statement in the context of this connection using
67
125
  # +binds+ as the bind substitutes. +name+ is logged along with
68
126
  # the executed +sql+ statement.
69
- def exec_query(sql, name = 'SQL', binds = [])
127
+ def exec_query(sql, name = "SQL", binds = [], prepare: false)
128
+ raise NotImplementedError
70
129
  end
71
130
 
72
131
  # Executes insert +sql+ statement in the context of this connection using
73
132
  # +binds+ as the bind substitutes. +name+ is logged along with
74
133
  # the executed +sql+ statement.
75
- 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)
76
136
  exec_query(sql, name, binds)
77
137
  end
78
138
 
79
139
  # Executes delete +sql+ statement in the context of this connection using
80
140
  # +binds+ as the bind substitutes. +name+ is logged along with
81
141
  # the executed +sql+ statement.
82
- def exec_delete(sql, name, binds)
142
+ def exec_delete(sql, name = nil, binds = [])
83
143
  exec_query(sql, name, binds)
84
144
  end
85
145
 
86
- # Executes the truncate statement.
87
- def truncate(table_name, name = nil)
88
- raise NotImplementedError
89
- end
90
-
91
146
  # Executes update +sql+ statement in the context of this connection using
92
147
  # +binds+ as the bind substitutes. +name+ is logged along with
93
148
  # the executed +sql+ statement.
94
- def exec_update(sql, name, binds)
149
+ def exec_update(sql, name = nil, binds = [])
95
150
  exec_query(sql, name, binds)
96
151
  end
97
152
 
98
- # Returns the last auto-generated ID from the affected table.
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
+
161
+ # Executes an INSERT query and returns the new record's ID
99
162
  #
100
- # +id_value+ will be returned unless the value is nil, in
163
+ # +id_value+ will be returned unless the value is +nil+, in
101
164
  # which case the database will attempt to calculate the last inserted
102
165
  # id and return that value.
103
166
  #
104
167
  # If the next id was calculated in advance (as in Oracle), it should be
105
168
  # passed in as +id_value+.
106
169
  def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
107
- sql, binds = sql_for_insert(to_sql(arel, binds), pk, id_value, sequence_name, binds)
108
- value = exec_insert(sql, name, binds, pk, sequence_name)
170
+ sql, binds = to_sql_and_binds(arel, binds)
171
+ value = exec_insert(sql, name, binds, pk, sequence_name)
109
172
  id_value || last_inserted_id(value)
110
173
  end
174
+ alias create insert
111
175
 
112
176
  # Executes the update statement and returns the number of rows affected.
113
177
  def update(arel, name = nil, binds = [])
114
- exec_update(to_sql(arel, binds), name, binds)
178
+ sql, binds = to_sql_and_binds(arel, binds)
179
+ exec_update(sql, name, binds)
115
180
  end
116
181
 
117
182
  # Executes the delete statement and returns the number of rows affected.
118
183
  def delete(arel, name = nil, binds = [])
119
- exec_delete(to_sql(arel, binds), name, binds)
184
+ sql, binds = to_sql_and_binds(arel, binds)
185
+ exec_delete(sql, name, binds)
120
186
  end
121
187
 
122
- # Returns +true+ when the connection adapter supports prepared statement
123
- # caching, otherwise returns +false+
124
- def supports_statement_cache?
125
- false
188
+ # Executes the truncate statement.
189
+ def truncate(table_name, name = nil)
190
+ execute(build_truncate_statement(table_name), name)
191
+ end
192
+
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
126
204
  end
127
205
 
128
206
  # Runs the given block in a database transaction, and returns the result
@@ -130,15 +208,30 @@ module ActiveRecord
130
208
  #
131
209
  # == Nested transactions support
132
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
+ #
133
228
  # Most databases don't support true nested transactions. At the time of
134
229
  # writing, the only database that supports true nested transactions that
135
230
  # we're aware of, is MS-SQL.
136
231
  #
137
232
  # In order to get around this problem, #transaction will emulate the effect
138
233
  # of nested transactions, by using savepoints:
139
- # http://dev.mysql.com/doc/refman/5.0/en/savepoint.html
140
- # Savepoints are supported by MySQL and PostgreSQL. SQLite3 version >= '3.6.8'
141
- # supports savepoints.
234
+ # https://dev.mysql.com/doc/refman/en/savepoint.html.
142
235
  #
143
236
  # It is safe to call this method if a database transaction is already open,
144
237
  # i.e. if #transaction is called within another #transaction block. In case
@@ -150,6 +243,24 @@ module ActiveRecord
150
243
  # - However, if +:requires_new+ is set, the block will be wrapped in a
151
244
  # database savepoint acting as a sub-transaction.
152
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
+ #
153
264
  # === Caveats
154
265
  #
155
266
  # MySQL doesn't support DDL transactions. If you perform a DDL operation,
@@ -188,29 +299,25 @@ module ActiveRecord
188
299
  # You should consult the documentation for your database to understand the
189
300
  # semantics of these different levels:
190
301
  #
191
- # * http://www.postgresql.org/docs/9.1/static/transaction-iso.html
192
- # * https://dev.mysql.com/doc/refman/5.0/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
193
304
  #
194
- # An <tt>ActiveRecord::TransactionIsolationError</tt> will be raised if:
305
+ # An ActiveRecord::TransactionIsolationError will be raised if:
195
306
  #
196
307
  # * The adapter does not support setting the isolation level
197
308
  # * You are joining an existing open transaction
198
309
  # * You are creating a nested (savepoint) transaction
199
310
  #
200
- # The mysql, mysql2 and postgresql adapters support setting the transaction
201
- # isolation level. However, support is disabled for MySQL versions below 5,
202
- # because they are affected by a bug[http://bugs.mysql.com/bug.php?id=39170]
203
- # which means the isolation level gets persisted outside the transaction.
204
- def transaction(options = {})
205
- options.assert_valid_keys :requires_new, :joinable, :isolation
206
-
207
- if !options[:requires_new] && current_transaction.joinable?
208
- if options[:isolation]
311
+ # The mysql2 and postgresql adapters support setting the transaction
312
+ # isolation level.
313
+ def transaction(requires_new: nil, isolation: nil, joinable: true)
314
+ if !requires_new && current_transaction.joinable?
315
+ if isolation
209
316
  raise ActiveRecord::TransactionIsolationError, "cannot set isolation when joining a transaction"
210
317
  end
211
318
  yield
212
319
  else
213
- transaction_manager.within_new_transaction(options) { yield }
320
+ transaction_manager.within_new_transaction(isolation: isolation, joinable: joinable) { yield }
214
321
  end
215
322
  rescue ActiveRecord::Rollback
216
323
  # rollbacks are silently swallowed
@@ -218,20 +325,29 @@ module ActiveRecord
218
325
 
219
326
  attr_reader :transaction_manager #:nodoc:
220
327
 
221
- 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
222
338
 
223
339
  def transaction_open?
224
340
  current_transaction.open?
225
341
  end
226
342
 
227
343
  def reset_transaction #:nodoc:
228
- @transaction_manager = TransactionManager.new(self)
344
+ @transaction_manager = ConnectionAdapters::TransactionManager.new(self)
229
345
  end
230
346
 
231
347
  # Register a record with the current transaction so that its after_commit and after_rollback callbacks
232
348
  # can be called.
233
- def add_transaction_record(record)
234
- current_transaction.add_record(record)
349
+ def add_transaction_record(record, ensure_finalize = true)
350
+ current_transaction.add_record(record, ensure_finalize)
235
351
  end
236
352
 
237
353
  # Begins the transaction (and turns off auto-committing).
@@ -258,7 +374,15 @@ module ActiveRecord
258
374
 
259
375
  # Rolls back the transaction (and turns on auto-committing). Must be
260
376
  # done if the transaction block raises an exception or returns false.
261
- def rollback_db_transaction() end
377
+ def rollback_db_transaction
378
+ exec_rollback_db_transaction
379
+ end
380
+
381
+ def exec_rollback_db_transaction() end #:nodoc:
382
+
383
+ def rollback_to_savepoint(name = nil)
384
+ exec_rollback_to_savepoint(name)
385
+ end
262
386
 
263
387
  def default_sequence_name(table, column)
264
388
  nil
@@ -270,103 +394,167 @@ module ActiveRecord
270
394
  end
271
395
 
272
396
  # Inserts the given fixture into the table. Overridden in adapters that require
273
- # 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.
274
401
  def insert_fixture(fixture, table_name)
275
- columns = schema_cache.columns_hash(table_name)
402
+ execute(build_fixture_sql(Array.wrap(fixture), table_name), "Fixture Insert")
403
+ end
276
404
 
277
- key_list = []
278
- value_list = fixture.map do |name, value|
279
- key_list << quote_column_name(name)
280
- quote(value, columns[name])
281
- end
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
282
409
 
283
- execute "INSERT INTO #{quote_table_name(table_name)} (#{key_list.join(', ')}) VALUES (#{value_list.join(', ')})", 'Fixture Insert'
410
+ with_multi_statements do
411
+ disable_referential_integrity do
412
+ transaction(requires_new: true) do
413
+ execute_batch(statements, "Fixtures Load")
414
+ end
415
+ end
416
+ end
284
417
  end
285
418
 
286
- def empty_insert_statement_value
419
+ def empty_insert_statement_value(primary_key = nil)
287
420
  "DEFAULT VALUES"
288
421
  end
289
422
 
290
423
  # Sanitizes the given LIMIT parameter in order to prevent SQL injection.
291
424
  #
292
425
  # The +limit+ may be anything that can evaluate to a string via #to_s. It
293
- # should look like an integer, or a comma-delimited list of integers, or
294
- # an Arel SQL literal.
426
+ # should look like an integer, or an Arel SQL literal.
295
427
  #
296
428
  # Returns Integer and Arel::Nodes::SqlLiteral limits as is.
297
- # Returns the sanitized limit parameter, either as an integer, or as a
298
- # string which contains a comma-delimited list of integers.
299
429
  def sanitize_limit(limit)
300
430
  if limit.is_a?(Integer) || limit.is_a?(Arel::Nodes::SqlLiteral)
301
431
  limit
302
- elsif limit.to_s.include?(',')
303
- Arel.sql limit.to_s.split(',').map{ |i| Integer(i) }.join(',')
304
432
  else
305
433
  Integer(limit)
306
434
  end
307
435
  end
308
436
 
309
- # The default strategy for an UPDATE with joins is to use a subquery. This doesn't work
310
- # on MySQL (even when aliasing the tables), but MySQL allows using JOIN directly in
311
- # an UPDATE statement, so in the MySQL adapters we redefine this to do that.
312
- def join_to_update(update, select) #:nodoc:
313
- key = update.key
314
- subselect = subquery_for(key, select)
315
-
316
- 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
317
446
  end
318
447
 
319
- def join_to_delete(delete, select, key) #:nodoc:
320
- subselect = subquery_for(key, select)
448
+ private
449
+ def execute_batch(statements, name = nil)
450
+ statements.each do |statement|
451
+ execute(statement, name)
452
+ end
453
+ end
321
454
 
322
- delete.where key.in(subselect)
323
- end
455
+ DEFAULT_INSERT_VALUE = Arel.sql("DEFAULT").freeze
456
+ private_constant :DEFAULT_INSERT_VALUE
324
457
 
325
- protected
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
326
482
 
327
- # Returns a subquery for the given key using the join information.
328
- def subquery_for(key, select)
329
- subselect = select.clone
330
- subselect.projections = [key]
331
- subselect
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)
332
503
  end
333
504
 
334
- # Returns an ActiveRecord::Result instance.
335
- def select(sql, name = nil, binds = [])
336
- exec_query(sql, name, binds)
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
337
510
  end
338
511
 
512
+ def build_truncate_statement(table_name)
513
+ "TRUNCATE TABLE #{quote_table_name(table_name)}"
514
+ end
339
515
 
340
- # Returns the last auto-generated ID from the affected table.
341
- def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
342
- execute(sql, name)
343
- id_value
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")
344
528
  end
345
529
 
346
- # Executes the update statement and returns the number of rows affected.
347
- def update_sql(sql, name = nil)
348
- execute(sql, name)
530
+ # Returns an ActiveRecord::Result instance.
531
+ def select(sql, name = nil, binds = [])
532
+ exec_query(sql, name, binds, prepare: false)
349
533
  end
350
534
 
351
- # Executes the delete statement and returns the number of rows affected.
352
- def delete_sql(sql, name = nil)
353
- update_sql(sql, name)
535
+ def select_prepared(sql, name = nil, binds = [])
536
+ exec_query(sql, name, binds, prepare: true)
354
537
  end
355
538
 
356
- def sql_for_insert(sql, pk, id_value, sequence_name, binds)
539
+ def sql_for_insert(sql, pk, binds)
357
540
  [sql, binds]
358
541
  end
359
542
 
360
543
  def last_inserted_id(result)
361
- 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
362
549
  row && row.first
363
550
  end
364
551
 
365
- def binds_from_relation(relation, binds)
366
- if relation.is_a?(Relation) && binds.empty?
367
- relation, binds = relation.arel, relation.bind_values
552
+ def arel_from_relation(relation)
553
+ if relation.is_a?(Relation)
554
+ relation.arel
555
+ else
556
+ relation
368
557
  end
369
- [relation, binds]
370
558
  end
371
559
  end
372
560
  end