activerecord 2.3.18 → 3.2.22

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 (454) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1014 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +222 -0
  5. data/examples/performance.rb +100 -126
  6. data/examples/simple.rb +14 -0
  7. data/lib/active_record/aggregations.rb +93 -99
  8. data/lib/active_record/associations/alias_tracker.rb +76 -0
  9. data/lib/active_record/associations/association.rb +247 -0
  10. data/lib/active_record/associations/association_scope.rb +134 -0
  11. data/lib/active_record/associations/belongs_to_association.rb +54 -61
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +17 -59
  13. data/lib/active_record/associations/builder/association.rb +55 -0
  14. data/lib/active_record/associations/builder/belongs_to.rb +88 -0
  15. data/lib/active_record/associations/builder/collection_association.rb +75 -0
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +57 -0
  17. data/lib/active_record/associations/builder/has_many.rb +71 -0
  18. data/lib/active_record/associations/builder/has_one.rb +62 -0
  19. data/lib/active_record/associations/builder/singular_association.rb +32 -0
  20. data/lib/active_record/associations/collection_association.rb +580 -0
  21. data/lib/active_record/associations/collection_proxy.rb +133 -0
  22. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +39 -119
  23. data/lib/active_record/associations/has_many_association.rb +60 -79
  24. data/lib/active_record/associations/has_many_through_association.rb +127 -206
  25. data/lib/active_record/associations/has_one_association.rb +55 -114
  26. data/lib/active_record/associations/has_one_through_association.rb +25 -26
  27. data/lib/active_record/associations/join_dependency/join_association.rb +159 -0
  28. data/lib/active_record/associations/join_dependency/join_base.rb +24 -0
  29. data/lib/active_record/associations/join_dependency/join_part.rb +78 -0
  30. data/lib/active_record/associations/join_dependency.rb +214 -0
  31. data/lib/active_record/associations/join_helper.rb +55 -0
  32. data/lib/active_record/associations/preloader/association.rb +125 -0
  33. data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
  34. data/lib/active_record/associations/preloader/collection_association.rb +24 -0
  35. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +60 -0
  36. data/lib/active_record/associations/preloader/has_many.rb +17 -0
  37. data/lib/active_record/associations/preloader/has_many_through.rb +15 -0
  38. data/lib/active_record/associations/preloader/has_one.rb +23 -0
  39. data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
  40. data/lib/active_record/associations/preloader/singular_association.rb +21 -0
  41. data/lib/active_record/associations/preloader/through_association.rb +67 -0
  42. data/lib/active_record/associations/preloader.rb +181 -0
  43. data/lib/active_record/associations/singular_association.rb +64 -0
  44. data/lib/active_record/associations/through_association.rb +87 -0
  45. data/lib/active_record/associations.rb +693 -1337
  46. data/lib/active_record/attribute_assignment.rb +221 -0
  47. data/lib/active_record/attribute_methods/before_type_cast.rb +31 -0
  48. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +32 -0
  49. data/lib/active_record/attribute_methods/dirty.rb +111 -0
  50. data/lib/active_record/attribute_methods/primary_key.rb +114 -0
  51. data/lib/active_record/attribute_methods/query.rb +39 -0
  52. data/lib/active_record/attribute_methods/read.rb +136 -0
  53. data/lib/active_record/attribute_methods/serialization.rb +120 -0
  54. data/lib/active_record/attribute_methods/time_zone_conversion.rb +65 -0
  55. data/lib/active_record/attribute_methods/write.rb +70 -0
  56. data/lib/active_record/attribute_methods.rb +211 -339
  57. data/lib/active_record/autosave_association.rb +179 -149
  58. data/lib/active_record/base.rb +401 -2907
  59. data/lib/active_record/callbacks.rb +91 -176
  60. data/lib/active_record/coders/yaml_column.rb +41 -0
  61. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +236 -119
  62. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +110 -58
  63. data/lib/active_record/connection_adapters/abstract/database_limits.rb +12 -11
  64. data/lib/active_record/connection_adapters/abstract/database_statements.rb +175 -74
  65. data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -35
  66. data/lib/active_record/connection_adapters/abstract/quoting.rb +71 -21
  67. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +81 -311
  68. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +194 -78
  69. data/lib/active_record/connection_adapters/abstract_adapter.rb +130 -83
  70. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +676 -0
  71. data/lib/active_record/connection_adapters/column.rb +296 -0
  72. data/lib/active_record/connection_adapters/mysql2_adapter.rb +280 -0
  73. data/lib/active_record/connection_adapters/mysql_adapter.rb +272 -493
  74. data/lib/active_record/connection_adapters/postgresql_adapter.rb +650 -405
  75. data/lib/active_record/connection_adapters/schema_cache.rb +69 -0
  76. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +30 -9
  77. data/lib/active_record/connection_adapters/sqlite_adapter.rb +276 -147
  78. data/lib/active_record/connection_adapters/statement_pool.rb +40 -0
  79. data/lib/active_record/counter_cache.rb +123 -0
  80. data/lib/active_record/dynamic_finder_match.rb +41 -14
  81. data/lib/active_record/dynamic_matchers.rb +84 -0
  82. data/lib/active_record/dynamic_scope_match.rb +13 -15
  83. data/lib/active_record/errors.rb +195 -0
  84. data/lib/active_record/explain.rb +86 -0
  85. data/lib/active_record/explain_subscriber.rb +25 -0
  86. data/lib/active_record/fixtures/file.rb +65 -0
  87. data/lib/active_record/fixtures.rb +695 -770
  88. data/lib/active_record/identity_map.rb +162 -0
  89. data/lib/active_record/inheritance.rb +174 -0
  90. data/lib/active_record/integration.rb +60 -0
  91. data/lib/active_record/locale/en.yml +9 -27
  92. data/lib/active_record/locking/optimistic.rb +76 -73
  93. data/lib/active_record/locking/pessimistic.rb +32 -10
  94. data/lib/active_record/log_subscriber.rb +72 -0
  95. data/lib/active_record/migration/command_recorder.rb +105 -0
  96. data/lib/active_record/migration.rb +415 -205
  97. data/lib/active_record/model_schema.rb +368 -0
  98. data/lib/active_record/nested_attributes.rb +153 -63
  99. data/lib/active_record/observer.rb +27 -103
  100. data/lib/active_record/persistence.rb +376 -0
  101. data/lib/active_record/query_cache.rb +49 -8
  102. data/lib/active_record/querying.rb +58 -0
  103. data/lib/active_record/railtie.rb +131 -0
  104. data/lib/active_record/railties/console_sandbox.rb +6 -0
  105. data/lib/active_record/railties/controller_runtime.rb +49 -0
  106. data/lib/active_record/railties/databases.rake +659 -0
  107. data/lib/active_record/railties/jdbcmysql_error.rb +16 -0
  108. data/lib/active_record/readonly_attributes.rb +26 -0
  109. data/lib/active_record/reflection.rb +269 -120
  110. data/lib/active_record/relation/batches.rb +90 -0
  111. data/lib/active_record/relation/calculations.rb +372 -0
  112. data/lib/active_record/relation/delegation.rb +49 -0
  113. data/lib/active_record/relation/finder_methods.rb +402 -0
  114. data/lib/active_record/relation/predicate_builder.rb +63 -0
  115. data/lib/active_record/relation/query_methods.rb +417 -0
  116. data/lib/active_record/relation/spawn_methods.rb +180 -0
  117. data/lib/active_record/relation.rb +537 -0
  118. data/lib/active_record/result.rb +40 -0
  119. data/lib/active_record/sanitization.rb +194 -0
  120. data/lib/active_record/schema.rb +9 -6
  121. data/lib/active_record/schema_dumper.rb +55 -32
  122. data/lib/active_record/scoping/default.rb +142 -0
  123. data/lib/active_record/scoping/named.rb +200 -0
  124. data/lib/active_record/scoping.rb +152 -0
  125. data/lib/active_record/serialization.rb +8 -91
  126. data/lib/active_record/serializers/xml_serializer.rb +43 -197
  127. data/lib/active_record/session_store.rb +129 -103
  128. data/lib/active_record/store.rb +52 -0
  129. data/lib/active_record/test_case.rb +30 -23
  130. data/lib/active_record/timestamp.rb +95 -52
  131. data/lib/active_record/transactions.rb +212 -66
  132. data/lib/active_record/translation.rb +22 -0
  133. data/lib/active_record/validations/associated.rb +43 -0
  134. data/lib/active_record/validations/uniqueness.rb +180 -0
  135. data/lib/active_record/validations.rb +43 -1106
  136. data/lib/active_record/version.rb +5 -4
  137. data/lib/active_record.rb +121 -48
  138. data/lib/rails/generators/active_record/migration/migration_generator.rb +25 -0
  139. data/lib/rails/generators/active_record/migration/templates/migration.rb +34 -0
  140. data/lib/rails/generators/active_record/migration.rb +15 -0
  141. data/lib/rails/generators/active_record/model/model_generator.rb +47 -0
  142. data/lib/rails/generators/active_record/model/templates/migration.rb +15 -0
  143. data/lib/rails/generators/active_record/model/templates/model.rb +12 -0
  144. data/lib/rails/generators/active_record/model/templates/module.rb +7 -0
  145. data/lib/rails/generators/active_record/observer/observer_generator.rb +15 -0
  146. data/lib/rails/generators/active_record/observer/templates/observer.rb +4 -0
  147. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +25 -0
  148. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +12 -0
  149. data/lib/rails/generators/active_record.rb +25 -0
  150. metadata +187 -363
  151. data/CHANGELOG +0 -5904
  152. data/README +0 -351
  153. data/RUNNING_UNIT_TESTS +0 -36
  154. data/Rakefile +0 -268
  155. data/install.rb +0 -30
  156. data/lib/active_record/association_preload.rb +0 -406
  157. data/lib/active_record/associations/association_collection.rb +0 -533
  158. data/lib/active_record/associations/association_proxy.rb +0 -288
  159. data/lib/active_record/batches.rb +0 -85
  160. data/lib/active_record/calculations.rb +0 -321
  161. data/lib/active_record/dirty.rb +0 -183
  162. data/lib/active_record/named_scope.rb +0 -197
  163. data/lib/active_record/serializers/json_serializer.rb +0 -91
  164. data/lib/activerecord.rb +0 -2
  165. data/test/assets/example.log +0 -1
  166. data/test/assets/flowers.jpg +0 -0
  167. data/test/cases/aaa_create_tables_test.rb +0 -24
  168. data/test/cases/active_schema_test_mysql.rb +0 -122
  169. data/test/cases/active_schema_test_postgresql.rb +0 -24
  170. data/test/cases/adapter_test.rb +0 -144
  171. data/test/cases/aggregations_test.rb +0 -167
  172. data/test/cases/ar_schema_test.rb +0 -32
  173. data/test/cases/associations/belongs_to_associations_test.rb +0 -438
  174. data/test/cases/associations/callbacks_test.rb +0 -161
  175. data/test/cases/associations/cascaded_eager_loading_test.rb +0 -131
  176. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +0 -36
  177. data/test/cases/associations/eager_load_nested_include_test.rb +0 -131
  178. data/test/cases/associations/eager_load_nested_polymorphic_include.rb +0 -19
  179. data/test/cases/associations/eager_singularization_test.rb +0 -145
  180. data/test/cases/associations/eager_test.rb +0 -852
  181. data/test/cases/associations/extension_test.rb +0 -62
  182. data/test/cases/associations/habtm_join_table_test.rb +0 -56
  183. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +0 -827
  184. data/test/cases/associations/has_many_associations_test.rb +0 -1273
  185. data/test/cases/associations/has_many_through_associations_test.rb +0 -360
  186. data/test/cases/associations/has_one_associations_test.rb +0 -330
  187. data/test/cases/associations/has_one_through_associations_test.rb +0 -209
  188. data/test/cases/associations/inner_join_association_test.rb +0 -93
  189. data/test/cases/associations/inverse_associations_test.rb +0 -566
  190. data/test/cases/associations/join_model_test.rb +0 -712
  191. data/test/cases/associations_test.rb +0 -282
  192. data/test/cases/attribute_methods_test.rb +0 -305
  193. data/test/cases/autosave_association_test.rb +0 -1218
  194. data/test/cases/base_test.rb +0 -2166
  195. data/test/cases/batches_test.rb +0 -81
  196. data/test/cases/binary_test.rb +0 -30
  197. data/test/cases/calculations_test.rb +0 -360
  198. data/test/cases/callbacks_observers_test.rb +0 -38
  199. data/test/cases/callbacks_test.rb +0 -438
  200. data/test/cases/class_inheritable_attributes_test.rb +0 -32
  201. data/test/cases/column_alias_test.rb +0 -17
  202. data/test/cases/column_definition_test.rb +0 -70
  203. data/test/cases/connection_pool_test.rb +0 -25
  204. data/test/cases/connection_test_firebird.rb +0 -8
  205. data/test/cases/connection_test_mysql.rb +0 -65
  206. data/test/cases/copy_table_test_sqlite.rb +0 -80
  207. data/test/cases/counter_cache_test.rb +0 -84
  208. data/test/cases/database_statements_test.rb +0 -12
  209. data/test/cases/datatype_test_postgresql.rb +0 -204
  210. data/test/cases/date_time_test.rb +0 -37
  211. data/test/cases/default_test_firebird.rb +0 -16
  212. data/test/cases/defaults_test.rb +0 -111
  213. data/test/cases/deprecated_finder_test.rb +0 -30
  214. data/test/cases/dirty_test.rb +0 -316
  215. data/test/cases/finder_respond_to_test.rb +0 -76
  216. data/test/cases/finder_test.rb +0 -1098
  217. data/test/cases/fixtures_test.rb +0 -661
  218. data/test/cases/helper.rb +0 -68
  219. data/test/cases/i18n_test.rb +0 -46
  220. data/test/cases/inheritance_test.rb +0 -262
  221. data/test/cases/invalid_date_test.rb +0 -24
  222. data/test/cases/json_serialization_test.rb +0 -219
  223. data/test/cases/lifecycle_test.rb +0 -193
  224. data/test/cases/locking_test.rb +0 -350
  225. data/test/cases/method_scoping_test.rb +0 -704
  226. data/test/cases/migration_test.rb +0 -1649
  227. data/test/cases/migration_test_firebird.rb +0 -124
  228. data/test/cases/mixin_test.rb +0 -96
  229. data/test/cases/modules_test.rb +0 -109
  230. data/test/cases/multiple_db_test.rb +0 -85
  231. data/test/cases/named_scope_test.rb +0 -372
  232. data/test/cases/nested_attributes_test.rb +0 -840
  233. data/test/cases/pk_test.rb +0 -119
  234. data/test/cases/pooled_connections_test.rb +0 -103
  235. data/test/cases/query_cache_test.rb +0 -129
  236. data/test/cases/readonly_test.rb +0 -107
  237. data/test/cases/reflection_test.rb +0 -234
  238. data/test/cases/reload_models_test.rb +0 -22
  239. data/test/cases/repair_helper.rb +0 -50
  240. data/test/cases/reserved_word_test_mysql.rb +0 -176
  241. data/test/cases/sanitize_test.rb +0 -25
  242. data/test/cases/schema_authorization_test_postgresql.rb +0 -75
  243. data/test/cases/schema_dumper_test.rb +0 -211
  244. data/test/cases/schema_test_postgresql.rb +0 -178
  245. data/test/cases/serialization_test.rb +0 -47
  246. data/test/cases/sp_test_mysql.rb +0 -16
  247. data/test/cases/synonym_test_oracle.rb +0 -17
  248. data/test/cases/timestamp_test.rb +0 -75
  249. data/test/cases/transactions_test.rb +0 -543
  250. data/test/cases/unconnected_test.rb +0 -32
  251. data/test/cases/validations_i18n_test.rb +0 -925
  252. data/test/cases/validations_test.rb +0 -1684
  253. data/test/cases/xml_serialization_test.rb +0 -240
  254. data/test/cases/yaml_serialization_test.rb +0 -11
  255. data/test/config.rb +0 -5
  256. data/test/connections/jdbc_jdbcderby/connection.rb +0 -18
  257. data/test/connections/jdbc_jdbch2/connection.rb +0 -18
  258. data/test/connections/jdbc_jdbchsqldb/connection.rb +0 -18
  259. data/test/connections/jdbc_jdbcmysql/connection.rb +0 -26
  260. data/test/connections/jdbc_jdbcpostgresql/connection.rb +0 -26
  261. data/test/connections/jdbc_jdbcsqlite3/connection.rb +0 -25
  262. data/test/connections/native_db2/connection.rb +0 -25
  263. data/test/connections/native_firebird/connection.rb +0 -26
  264. data/test/connections/native_frontbase/connection.rb +0 -27
  265. data/test/connections/native_mysql/connection.rb +0 -25
  266. data/test/connections/native_openbase/connection.rb +0 -21
  267. data/test/connections/native_oracle/connection.rb +0 -27
  268. data/test/connections/native_postgresql/connection.rb +0 -21
  269. data/test/connections/native_sqlite/connection.rb +0 -25
  270. data/test/connections/native_sqlite3/connection.rb +0 -25
  271. data/test/connections/native_sqlite3/in_memory_connection.rb +0 -18
  272. data/test/connections/native_sybase/connection.rb +0 -23
  273. data/test/fixtures/accounts.yml +0 -29
  274. data/test/fixtures/all/developers.yml +0 -0
  275. data/test/fixtures/all/people.csv +0 -0
  276. data/test/fixtures/all/tasks.yml +0 -0
  277. data/test/fixtures/author_addresses.yml +0 -5
  278. data/test/fixtures/author_favorites.yml +0 -4
  279. data/test/fixtures/authors.yml +0 -9
  280. data/test/fixtures/binaries.yml +0 -132
  281. data/test/fixtures/books.yml +0 -7
  282. data/test/fixtures/categories/special_categories.yml +0 -9
  283. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +0 -4
  284. data/test/fixtures/categories.yml +0 -14
  285. data/test/fixtures/categories_ordered.yml +0 -7
  286. data/test/fixtures/categories_posts.yml +0 -23
  287. data/test/fixtures/categorizations.yml +0 -17
  288. data/test/fixtures/clubs.yml +0 -6
  289. data/test/fixtures/comments.yml +0 -59
  290. data/test/fixtures/companies.yml +0 -56
  291. data/test/fixtures/computers.yml +0 -4
  292. data/test/fixtures/courses.yml +0 -7
  293. data/test/fixtures/customers.yml +0 -26
  294. data/test/fixtures/developers.yml +0 -21
  295. data/test/fixtures/developers_projects.yml +0 -17
  296. data/test/fixtures/edges.yml +0 -6
  297. data/test/fixtures/entrants.yml +0 -14
  298. data/test/fixtures/faces.yml +0 -11
  299. data/test/fixtures/fk_test_has_fk.yml +0 -3
  300. data/test/fixtures/fk_test_has_pk.yml +0 -2
  301. data/test/fixtures/funny_jokes.yml +0 -10
  302. data/test/fixtures/interests.yml +0 -33
  303. data/test/fixtures/items.yml +0 -4
  304. data/test/fixtures/jobs.yml +0 -7
  305. data/test/fixtures/legacy_things.yml +0 -3
  306. data/test/fixtures/mateys.yml +0 -4
  307. data/test/fixtures/member_types.yml +0 -6
  308. data/test/fixtures/members.yml +0 -6
  309. data/test/fixtures/memberships.yml +0 -20
  310. data/test/fixtures/men.yml +0 -5
  311. data/test/fixtures/minimalistics.yml +0 -2
  312. data/test/fixtures/mixed_case_monkeys.yml +0 -6
  313. data/test/fixtures/mixins.yml +0 -29
  314. data/test/fixtures/movies.yml +0 -7
  315. data/test/fixtures/naked/csv/accounts.csv +0 -1
  316. data/test/fixtures/naked/yml/accounts.yml +0 -1
  317. data/test/fixtures/naked/yml/companies.yml +0 -1
  318. data/test/fixtures/naked/yml/courses.yml +0 -1
  319. data/test/fixtures/organizations.yml +0 -5
  320. data/test/fixtures/owners.yml +0 -7
  321. data/test/fixtures/parrots.yml +0 -27
  322. data/test/fixtures/parrots_pirates.yml +0 -7
  323. data/test/fixtures/people.yml +0 -15
  324. data/test/fixtures/pets.yml +0 -14
  325. data/test/fixtures/pirates.yml +0 -9
  326. data/test/fixtures/polymorphic_designs.yml +0 -19
  327. data/test/fixtures/polymorphic_prices.yml +0 -19
  328. data/test/fixtures/posts.yml +0 -52
  329. data/test/fixtures/price_estimates.yml +0 -7
  330. data/test/fixtures/projects.yml +0 -7
  331. data/test/fixtures/readers.yml +0 -9
  332. data/test/fixtures/references.yml +0 -17
  333. data/test/fixtures/reserved_words/distinct.yml +0 -5
  334. data/test/fixtures/reserved_words/distincts_selects.yml +0 -11
  335. data/test/fixtures/reserved_words/group.yml +0 -14
  336. data/test/fixtures/reserved_words/select.yml +0 -8
  337. data/test/fixtures/reserved_words/values.yml +0 -7
  338. data/test/fixtures/ships.yml +0 -5
  339. data/test/fixtures/sponsors.yml +0 -9
  340. data/test/fixtures/subscribers.yml +0 -7
  341. data/test/fixtures/subscriptions.yml +0 -12
  342. data/test/fixtures/taggings.yml +0 -28
  343. data/test/fixtures/tags.yml +0 -7
  344. data/test/fixtures/tasks.yml +0 -7
  345. data/test/fixtures/tees.yml +0 -4
  346. data/test/fixtures/ties.yml +0 -4
  347. data/test/fixtures/topics.yml +0 -42
  348. data/test/fixtures/toys.yml +0 -4
  349. data/test/fixtures/treasures.yml +0 -10
  350. data/test/fixtures/vertices.yml +0 -4
  351. data/test/fixtures/warehouse-things.yml +0 -3
  352. data/test/fixtures/zines.yml +0 -5
  353. data/test/migrations/broken/100_migration_that_raises_exception.rb +0 -10
  354. data/test/migrations/decimal/1_give_me_big_numbers.rb +0 -15
  355. data/test/migrations/duplicate/1_people_have_last_names.rb +0 -9
  356. data/test/migrations/duplicate/2_we_need_reminders.rb +0 -12
  357. data/test/migrations/duplicate/3_foo.rb +0 -7
  358. data/test/migrations/duplicate/3_innocent_jointable.rb +0 -12
  359. data/test/migrations/duplicate_names/20080507052938_chunky.rb +0 -7
  360. data/test/migrations/duplicate_names/20080507053028_chunky.rb +0 -7
  361. data/test/migrations/interleaved/pass_1/3_innocent_jointable.rb +0 -12
  362. data/test/migrations/interleaved/pass_2/1_people_have_last_names.rb +0 -9
  363. data/test/migrations/interleaved/pass_2/3_innocent_jointable.rb +0 -12
  364. data/test/migrations/interleaved/pass_3/1_people_have_last_names.rb +0 -9
  365. data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +0 -8
  366. data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +0 -12
  367. data/test/migrations/missing/1000_people_have_middle_names.rb +0 -9
  368. data/test/migrations/missing/1_people_have_last_names.rb +0 -9
  369. data/test/migrations/missing/3_we_need_reminders.rb +0 -12
  370. data/test/migrations/missing/4_innocent_jointable.rb +0 -12
  371. data/test/migrations/valid/1_people_have_last_names.rb +0 -9
  372. data/test/migrations/valid/2_we_need_reminders.rb +0 -12
  373. data/test/migrations/valid/3_innocent_jointable.rb +0 -12
  374. data/test/models/author.rb +0 -151
  375. data/test/models/auto_id.rb +0 -4
  376. data/test/models/binary.rb +0 -2
  377. data/test/models/bird.rb +0 -9
  378. data/test/models/book.rb +0 -4
  379. data/test/models/categorization.rb +0 -5
  380. data/test/models/category.rb +0 -34
  381. data/test/models/citation.rb +0 -6
  382. data/test/models/club.rb +0 -13
  383. data/test/models/column_name.rb +0 -3
  384. data/test/models/comment.rb +0 -29
  385. data/test/models/company.rb +0 -173
  386. data/test/models/company_in_module.rb +0 -78
  387. data/test/models/computer.rb +0 -3
  388. data/test/models/contact.rb +0 -16
  389. data/test/models/contract.rb +0 -5
  390. data/test/models/course.rb +0 -3
  391. data/test/models/customer.rb +0 -73
  392. data/test/models/default.rb +0 -2
  393. data/test/models/developer.rb +0 -101
  394. data/test/models/edge.rb +0 -5
  395. data/test/models/entrant.rb +0 -3
  396. data/test/models/essay.rb +0 -3
  397. data/test/models/event.rb +0 -3
  398. data/test/models/event_author.rb +0 -8
  399. data/test/models/face.rb +0 -7
  400. data/test/models/guid.rb +0 -2
  401. data/test/models/interest.rb +0 -5
  402. data/test/models/invoice.rb +0 -4
  403. data/test/models/item.rb +0 -7
  404. data/test/models/job.rb +0 -5
  405. data/test/models/joke.rb +0 -3
  406. data/test/models/keyboard.rb +0 -3
  407. data/test/models/legacy_thing.rb +0 -3
  408. data/test/models/line_item.rb +0 -3
  409. data/test/models/man.rb +0 -9
  410. data/test/models/matey.rb +0 -4
  411. data/test/models/member.rb +0 -12
  412. data/test/models/member_detail.rb +0 -5
  413. data/test/models/member_type.rb +0 -3
  414. data/test/models/membership.rb +0 -9
  415. data/test/models/minimalistic.rb +0 -2
  416. data/test/models/mixed_case_monkey.rb +0 -3
  417. data/test/models/movie.rb +0 -5
  418. data/test/models/order.rb +0 -4
  419. data/test/models/organization.rb +0 -6
  420. data/test/models/owner.rb +0 -5
  421. data/test/models/parrot.rb +0 -22
  422. data/test/models/person.rb +0 -16
  423. data/test/models/pet.rb +0 -5
  424. data/test/models/pirate.rb +0 -80
  425. data/test/models/polymorphic_design.rb +0 -3
  426. data/test/models/polymorphic_price.rb +0 -3
  427. data/test/models/post.rb +0 -102
  428. data/test/models/price_estimate.rb +0 -3
  429. data/test/models/project.rb +0 -30
  430. data/test/models/reader.rb +0 -4
  431. data/test/models/reference.rb +0 -4
  432. data/test/models/reply.rb +0 -46
  433. data/test/models/ship.rb +0 -19
  434. data/test/models/ship_part.rb +0 -7
  435. data/test/models/sponsor.rb +0 -4
  436. data/test/models/subject.rb +0 -4
  437. data/test/models/subscriber.rb +0 -8
  438. data/test/models/subscription.rb +0 -4
  439. data/test/models/tag.rb +0 -7
  440. data/test/models/tagging.rb +0 -10
  441. data/test/models/task.rb +0 -3
  442. data/test/models/tee.rb +0 -4
  443. data/test/models/tie.rb +0 -4
  444. data/test/models/topic.rb +0 -80
  445. data/test/models/toy.rb +0 -6
  446. data/test/models/treasure.rb +0 -8
  447. data/test/models/vertex.rb +0 -9
  448. data/test/models/warehouse_thing.rb +0 -5
  449. data/test/models/zine.rb +0 -3
  450. data/test/schema/mysql_specific_schema.rb +0 -31
  451. data/test/schema/postgresql_specific_schema.rb +0 -114
  452. data/test/schema/schema.rb +0 -550
  453. data/test/schema/schema2.rb +0 -6
  454. data/test/schema/sqlite_specific_schema.rb +0 -25
@@ -1,3 +1,5 @@
1
+ require 'uri'
2
+
1
3
  module ActiveRecord
2
4
  class Base
3
5
  class ConnectionSpecification #:nodoc:
@@ -5,12 +7,81 @@ module ActiveRecord
5
7
  def initialize (config, adapter_method)
6
8
  @config, @adapter_method = config, adapter_method
7
9
  end
10
+
11
+ ##
12
+ # Builds a ConnectionSpecification from user input
13
+ class Resolver # :nodoc:
14
+ attr_reader :config, :klass, :configurations
15
+
16
+ def initialize(config, configurations)
17
+ @config = config
18
+ @configurations = configurations
19
+ end
20
+
21
+ def spec
22
+ case config
23
+ when nil
24
+ raise AdapterNotSpecified unless defined?(Rails.env)
25
+ resolve_string_connection Rails.env
26
+ when Symbol, String
27
+ resolve_string_connection config.to_s
28
+ when Hash
29
+ resolve_hash_connection config
30
+ end
31
+ end
32
+
33
+ private
34
+ def resolve_string_connection(spec) # :nodoc:
35
+ hash = configurations.fetch(spec) do |k|
36
+ connection_url_to_hash(k)
37
+ end
38
+
39
+ raise(AdapterNotSpecified, "#{spec} database is not configured") unless hash
40
+
41
+ resolve_hash_connection hash
42
+ end
43
+
44
+ def resolve_hash_connection(spec) # :nodoc:
45
+ spec = spec.symbolize_keys
46
+
47
+ raise(AdapterNotSpecified, "database configuration does not specify adapter") unless spec.key?(:adapter)
48
+
49
+ begin
50
+ require "active_record/connection_adapters/#{spec[:adapter]}_adapter"
51
+ rescue LoadError => e
52
+ raise LoadError, "Please install the #{spec[:adapter]} adapter: `gem install activerecord-#{spec[:adapter]}-adapter` (#{e.message})", e.backtrace
53
+ end
54
+
55
+ adapter_method = "#{spec[:adapter]}_connection"
56
+
57
+ ConnectionSpecification.new(spec, adapter_method)
58
+ end
59
+
60
+ def connection_url_to_hash(url) # :nodoc:
61
+ config = URI.parse url
62
+ adapter = config.scheme
63
+ adapter = "postgresql" if adapter == "postgres"
64
+ spec = { :adapter => adapter,
65
+ :username => config.user,
66
+ :password => config.password,
67
+ :port => config.port,
68
+ :database => config.path.sub(%r{^/},""),
69
+ :host => config.host }
70
+ spec.reject!{ |_,value| value.blank? }
71
+ spec.map { |key,value| spec[key] = URI.unescape(value) if value.is_a?(String) }
72
+ if config.query
73
+ options = Hash[config.query.split("&").map{ |pair| pair.split("=") }].symbolize_keys
74
+ spec.merge!(options)
75
+ end
76
+ spec
77
+ end
78
+ end
8
79
  end
9
80
 
10
81
  ##
11
82
  # :singleton-method:
12
83
  # The connection handler
13
- class_attribute :connection_handler
84
+ class_attribute :connection_handler, :instance_writer => false
14
85
  self.connection_handler = ConnectionAdapters::ConnectionHandler.new
15
86
 
16
87
  # Returns the connection currently associated with the class. This can
@@ -46,84 +117,61 @@ module ActiveRecord
46
117
  # "database" => "path/to/dbfile"
47
118
  # )
48
119
  #
120
+ # Or a URL:
121
+ #
122
+ # ActiveRecord::Base.establish_connection(
123
+ # "postgres://myuser:mypass@localhost/somedatabase"
124
+ # )
125
+ #
49
126
  # The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError
50
127
  # may be returned on an error.
51
- def self.establish_connection(spec = nil)
52
- case spec
53
- when nil
54
- raise AdapterNotSpecified unless defined? RAILS_ENV
55
- establish_connection(RAILS_ENV)
56
- when ConnectionSpecification
57
- self.connection_handler.establish_connection(name, spec)
58
- when Symbol, String
59
- if configuration = configurations[spec.to_s]
60
- establish_connection(configuration)
61
- else
62
- raise AdapterNotSpecified, "#{spec} database is not configured"
63
- end
64
- else
65
- spec = spec.symbolize_keys
66
- unless spec.key?(:adapter) then raise AdapterNotSpecified, "database configuration does not specify adapter" end
67
-
68
- begin
69
- require 'rubygems'
70
- gem "activerecord-#{spec[:adapter]}-adapter"
71
- require "active_record/connection_adapters/#{spec[:adapter]}_adapter"
72
- rescue LoadError
73
- begin
74
- require "active_record/connection_adapters/#{spec[:adapter]}_adapter"
75
- rescue LoadError
76
- raise "Please install the #{spec[:adapter]} adapter: `gem install activerecord-#{spec[:adapter]}-adapter` (#{$!})"
77
- end
78
- end
79
-
80
- adapter_method = "#{spec[:adapter]}_connection"
81
- if !respond_to?(adapter_method)
82
- raise AdapterNotFound, "database configuration specifies nonexistent #{spec[:adapter]} adapter"
83
- end
128
+ def self.establish_connection(spec = ENV["DATABASE_URL"])
129
+ resolver = ConnectionSpecification::Resolver.new spec, configurations
130
+ spec = resolver.spec
84
131
 
85
- remove_connection
86
- establish_connection(ConnectionSpecification.new(spec, adapter_method))
132
+ unless respond_to?(spec.adapter_method)
133
+ raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
87
134
  end
135
+
136
+ remove_connection
137
+ connection_handler.establish_connection name, spec
88
138
  end
89
139
 
90
140
  class << self
91
- # Deprecated and no longer has any effect.
92
- def allow_concurrency
93
- ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_concurrency has been deprecated and no longer has any effect. Please remove all references to allow_concurrency.")
94
- end
95
-
96
- # Deprecated and no longer has any effect.
97
- def allow_concurrency=(flag)
98
- ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_concurrency= has been deprecated and no longer has any effect. Please remove all references to allow_concurrency=.")
141
+ # Returns the connection currently associated with the class. This can
142
+ # also be used to "borrow" the connection to do database work unrelated
143
+ # to any of the specific Active Records.
144
+ def connection
145
+ retrieve_connection
99
146
  end
100
147
 
101
- # Deprecated and no longer has any effect.
102
- def verification_timeout
103
- ActiveSupport::Deprecation.warn("ActiveRecord::Base.verification_timeout has been deprecated and no longer has any effect. Please remove all references to verification_timeout.")
148
+ def connection_id
149
+ Thread.current['ActiveRecord::Base.connection_id']
104
150
  end
105
151
 
106
- # Deprecated and no longer has any effect.
107
- def verification_timeout=(flag)
108
- ActiveSupport::Deprecation.warn("ActiveRecord::Base.verification_timeout= has been deprecated and no longer has any effect. Please remove all references to verification_timeout=.")
152
+ def connection_id=(connection_id)
153
+ Thread.current['ActiveRecord::Base.connection_id'] = connection_id
109
154
  end
110
155
 
111
- # Returns the connection currently associated with the class. This can
112
- # also be used to "borrow" the connection to do database work unrelated
113
- # to any of the specific Active Records.
114
- def connection
115
- retrieve_connection
156
+ # Returns the configuration of the associated connection as a hash:
157
+ #
158
+ # ActiveRecord::Base.connection_config
159
+ # # => {:pool=>5, :timeout=>5000, :database=>"db/development.sqlite3", :adapter=>"sqlite3"}
160
+ #
161
+ # Please use only for reading.
162
+ def connection_config
163
+ connection_pool.spec.config
116
164
  end
117
165
 
118
166
  def connection_pool
119
- connection_handler.retrieve_connection_pool(self)
167
+ connection_handler.retrieve_connection_pool(self) or raise ConnectionNotEstablished
120
168
  end
121
169
 
122
170
  def retrieve_connection
123
171
  connection_handler.retrieve_connection(self)
124
172
  end
125
173
 
126
- # Returns true if +ActiveRecord+ is connected.
174
+ # Returns true if Active Record is connected.
127
175
  def connected?
128
176
  connection_handler.connected?(self)
129
177
  end
@@ -132,7 +180,11 @@ module ActiveRecord
132
180
  connection_handler.remove_connection(klass)
133
181
  end
134
182
 
135
- delegate :clear_active_connections!, :clear_reloadable_connections!,
183
+ def clear_active_connections!
184
+ connection_handler.clear_active_connections!
185
+ end
186
+
187
+ delegate :clear_reloadable_connections!,
136
188
  :clear_all_connections!,:verify_active_connections!, :to => :connection_handler
137
189
  end
138
190
  end
@@ -2,52 +2,53 @@ module ActiveRecord
2
2
  module ConnectionAdapters # :nodoc:
3
3
  module DatabaseLimits
4
4
 
5
- # the maximum length of a table alias
5
+ # Returns the maximum length of a table alias.
6
6
  def table_alias_length
7
7
  255
8
8
  end
9
9
 
10
- # the maximum length of a column name
10
+ # Returns the maximum length of a column name.
11
11
  def column_name_length
12
12
  64
13
13
  end
14
14
 
15
- # the maximum length of a table name
15
+ # Returns the maximum length of a table name.
16
16
  def table_name_length
17
17
  64
18
18
  end
19
19
 
20
- # the maximum length of an index name
20
+ # Returns the maximum length of an index name.
21
21
  def index_name_length
22
22
  64
23
23
  end
24
24
 
25
- # the maximum number of columns per table
25
+ # Returns the maximum number of columns per table.
26
26
  def columns_per_table
27
27
  1024
28
28
  end
29
29
 
30
- # the maximum number of indexes per table
30
+ # Returns the maximum number of indexes per table.
31
31
  def indexes_per_table
32
32
  16
33
33
  end
34
34
 
35
- # the maximum number of columns in a multicolumn index
35
+ # Returns the maximum number of columns in a multicolumn index.
36
36
  def columns_per_multicolumn_index
37
37
  16
38
38
  end
39
39
 
40
- # the maximum number of elements in an IN (x,y,z) clause
40
+ # Returns the maximum number of elements in an IN (x,y,z) clause.
41
+ # nil means no limit.
41
42
  def in_clause_length
42
- 65535
43
+ nil
43
44
  end
44
45
 
45
- # the maximum length of a SQL query
46
+ # Returns the maximum length of an SQL query.
46
47
  def sql_query_length
47
48
  1048575
48
49
  end
49
50
 
50
- # maximum number of joins in a single query
51
+ # Returns maximum number of joins in a single query.
51
52
  def joins_per_query
52
53
  256
53
54
  end
@@ -1,30 +1,41 @@
1
1
  module ActiveRecord
2
2
  module ConnectionAdapters # :nodoc:
3
3
  module DatabaseStatements
4
+ # 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)
9
+ end
10
+ else
11
+ arel
12
+ end
13
+ end
14
+
4
15
  # Returns an array of record hashes with the column names as keys and
5
16
  # column values as values.
6
- def select_all(sql, name = nil)
7
- select(sql, name)
17
+ def select_all(arel, name = nil, binds = [])
18
+ select(to_sql(arel, binds), name, binds)
8
19
  end
9
20
 
10
21
  # Returns a record hash with the column names as keys and column values
11
22
  # as values.
12
- def select_one(sql, name = nil)
13
- result = select_all(sql, name)
23
+ def select_one(arel, name = nil)
24
+ result = select_all(arel, name)
14
25
  result.first if result
15
26
  end
16
27
 
17
28
  # Returns a single value from a record
18
- def select_value(sql, name = nil)
19
- if result = select_one(sql, name)
29
+ def select_value(arel, name = nil)
30
+ if result = select_one(arel, name)
20
31
  result.values.first
21
32
  end
22
33
  end
23
34
 
24
35
  # Returns an array of the values of the first column in a select:
25
36
  # select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
26
- def select_values(sql, name = nil)
27
- result = select_rows(sql, name)
37
+ def select_values(arel, name = nil)
38
+ result = select_rows(to_sql(arel, []), name)
28
39
  result.map { |v| v[0] }
29
40
  end
30
41
 
@@ -35,25 +46,61 @@ module ActiveRecord
35
46
  undef_method :select_rows
36
47
 
37
48
  # Executes the SQL statement in the context of this connection.
38
- def execute(sql, name = nil, skip_logging = false)
49
+ def execute(sql, name = nil)
39
50
  end
40
51
  undef_method :execute
41
52
 
53
+ # Executes +sql+ statement in the context of this connection using
54
+ # +binds+ as the bind substitutes. +name+ is logged along with
55
+ # the executed +sql+ statement.
56
+ def exec_query(sql, name = 'SQL', binds = [])
57
+ end
58
+
59
+ # Executes insert +sql+ statement in the context of this connection using
60
+ # +binds+ as the bind substitutes. +name+ is the logged along with
61
+ # the executed +sql+ statement.
62
+ def exec_insert(sql, name, binds)
63
+ exec_query(sql, name, binds)
64
+ end
65
+
66
+ # Executes delete +sql+ statement in the context of this connection using
67
+ # +binds+ as the bind substitutes. +name+ is the logged along with
68
+ # the executed +sql+ statement.
69
+ def exec_delete(sql, name, binds)
70
+ exec_query(sql, name, binds)
71
+ end
72
+
73
+ # Executes update +sql+ statement in the context of this connection using
74
+ # +binds+ as the bind substitutes. +name+ is the logged along with
75
+ # the executed +sql+ statement.
76
+ def exec_update(sql, name, binds)
77
+ exec_query(sql, name, binds)
78
+ end
79
+
42
80
  # Returns the last auto-generated ID from the affected table.
43
- def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
44
- insert_sql(sql, name, pk, id_value, sequence_name)
81
+ #
82
+ # +id_value+ will be returned unless the value is nil, in
83
+ # which case the database will attempt to calculate the last inserted
84
+ # id and return that value.
85
+ #
86
+ # If the next id was calculated in advance (as in Oracle), it should be
87
+ # passed in as +id_value+.
88
+ 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)
91
+ id_value || last_inserted_id(value)
45
92
  end
46
93
 
47
94
  # Executes the update statement and returns the number of rows affected.
48
- def update(sql, name = nil)
49
- update_sql(sql, name)
95
+ def update(arel, name = nil, binds = [])
96
+ exec_update(to_sql(arel, binds), name, binds)
50
97
  end
51
98
 
52
99
  # Executes the delete statement and returns the number of rows affected.
53
- def delete(sql, name = nil)
54
- delete_sql(sql, name)
100
+ def delete(arel, name = nil, binds = [])
101
+ exec_delete(to_sql(arel, binds), name, binds)
55
102
  end
56
-
103
+
57
104
  # Checks whether there is currently no transaction active. This is done
58
105
  # by querying the database driver, and does not use the transaction
59
106
  # house-keeping information recorded by #increment_open_transactions and
@@ -68,6 +115,12 @@ module ActiveRecord
68
115
  nil
69
116
  end
70
117
 
118
+ # Returns +true+ when the connection adapter supports prepared statement
119
+ # caching, otherwise returns +false+
120
+ def supports_statement_cache?
121
+ false
122
+ end
123
+
71
124
  # Runs the given block in a database transaction, and returns the result
72
125
  # of the block.
73
126
  #
@@ -79,7 +132,7 @@ module ActiveRecord
79
132
  #
80
133
  # In order to get around this problem, #transaction will emulate the effect
81
134
  # of nested transactions, by using savepoints:
82
- # http://dev.mysql.com/doc/refman/5.0/en/savepoints.html
135
+ # http://dev.mysql.com/doc/refman/5.0/en/savepoint.html
83
136
  # Savepoints are supported by MySQL and PostgreSQL, but not SQLite3.
84
137
  #
85
138
  # It is safe to call this method if a database transaction is already open,
@@ -113,7 +166,7 @@ module ActiveRecord
113
166
  def transaction(options = {})
114
167
  options.assert_valid_keys :requires_new, :joinable
115
168
 
116
- last_transaction_joinable = @transaction_joinable
169
+ last_transaction_joinable = defined?(@transaction_joinable) ? @transaction_joinable : nil
117
170
  if options.has_key?(:joinable)
118
171
  @transaction_joinable = options[:joinable]
119
172
  else
@@ -122,6 +175,8 @@ module ActiveRecord
122
175
  requires_new = options[:requires_new] || !last_transaction_joinable
123
176
 
124
177
  transaction_open = false
178
+ @_current_transaction_records ||= []
179
+
125
180
  begin
126
181
  if block_given?
127
182
  if requires_new || open_transactions == 0
@@ -132,6 +187,7 @@ module ActiveRecord
132
187
  end
133
188
  increment_open_transactions
134
189
  transaction_open = true
190
+ @_current_transaction_records.push([])
135
191
  end
136
192
  yield
137
193
  end
@@ -141,8 +197,10 @@ module ActiveRecord
141
197
  decrement_open_transactions
142
198
  if open_transactions == 0
143
199
  rollback_db_transaction
200
+ rollback_transaction_records(true)
144
201
  else
145
202
  rollback_to_savepoint
203
+ rollback_transaction_records(false)
146
204
  end
147
205
  end
148
206
  raise unless database_transaction_rollback.is_a?(ActiveRecord::Rollback)
@@ -157,20 +215,35 @@ module ActiveRecord
157
215
  begin
158
216
  if open_transactions == 0
159
217
  commit_db_transaction
218
+ commit_transaction_records
160
219
  else
161
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
162
226
  end
163
227
  rescue Exception => database_transaction_rollback
164
228
  if open_transactions == 0
165
229
  rollback_db_transaction
230
+ rollback_transaction_records(true)
166
231
  else
167
232
  rollback_to_savepoint
233
+ rollback_transaction_records(false)
168
234
  end
169
235
  raise
170
236
  end
171
237
  end
172
238
  end
173
-
239
+
240
+ # Register a record with the current transaction so that its after_commit and after_rollback callbacks
241
+ # can be called.
242
+ def add_transaction_record(record)
243
+ last_batch = @_current_transaction_records.last
244
+ last_batch << record if last_batch
245
+ end
246
+
174
247
  # Begins the transaction (and turns off auto-committing).
175
248
  def begin_db_transaction() end
176
249
 
@@ -181,62 +254,31 @@ module ActiveRecord
181
254
  # done if the transaction block raises an exception or returns false.
182
255
  def rollback_db_transaction() end
183
256
 
184
- # Alias for <tt>add_limit_offset!</tt>.
185
- def add_limit!(sql, options)
186
- add_limit_offset!(sql, options) if options
187
- end
188
-
189
- # Appends +LIMIT+ and +OFFSET+ options to an SQL statement, or some SQL
190
- # fragment that has the same semantics as LIMIT and OFFSET.
191
- #
192
- # +options+ must be a Hash which contains a +:limit+ option (required)
193
- # and an +:offset+ option (optional).
194
- #
195
- # This method *modifies* the +sql+ parameter.
196
- #
197
- # ===== Examples
198
- # add_limit_offset!('SELECT * FROM suppliers', {:limit => 10, :offset => 50})
199
- # generates
200
- # SELECT * FROM suppliers LIMIT 10 OFFSET 50
201
- def add_limit_offset!(sql, options)
202
- if limit = options[:limit]
203
- sql << " LIMIT #{sanitize_limit(limit)}"
204
- if offset = options[:offset]
205
- sql << " OFFSET #{offset.to_i}"
206
- end
207
- end
208
- sql
209
- end
210
-
211
- # Appends a locking clause to an SQL statement.
212
- # This method *modifies* the +sql+ parameter.
213
- # # SELECT * FROM suppliers FOR UPDATE
214
- # add_lock! 'SELECT * FROM suppliers', :lock => true
215
- # add_lock! 'SELECT * FROM suppliers', :lock => ' FOR UPDATE'
216
- def add_lock!(sql, options)
217
- case lock = options[:lock]
218
- when true; sql << ' FOR UPDATE'
219
- when String; sql << " #{lock}"
220
- end
221
- end
222
-
223
257
  def default_sequence_name(table, column)
224
258
  nil
225
259
  end
226
260
 
227
261
  # Set the sequence to the max value of the table's column.
228
262
  def reset_sequence!(table, column, sequence = nil)
229
- # Do nothing by default. Implement for PostgreSQL, Oracle, ...
263
+ # Do nothing by default. Implement for PostgreSQL, Oracle, ...
230
264
  end
231
265
 
232
266
  # Inserts the given fixture into the table. Overridden in adapters that require
233
267
  # something beyond a simple insert (eg. Oracle).
234
268
  def insert_fixture(fixture, table_name)
235
- execute "INSERT INTO #{quote_table_name(table_name)} (#{fixture.key_list}) VALUES (#{fixture.value_list})", 'Fixture Insert'
269
+ columns = schema_cache.columns_hash(table_name)
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'
236
278
  end
237
279
 
238
- def empty_insert_statement(table_name)
239
- "INSERT INTO #{quote_table_name(table_name)} VALUES(DEFAULT)"
280
+ def empty_insert_statement_value
281
+ "VALUES(DEFAULT)"
240
282
  end
241
283
 
242
284
  def case_sensitive_equality_operator
@@ -247,10 +289,39 @@ module ActiveRecord
247
289
  "WHERE #{quoted_primary_key} IN (SELECT #{quoted_primary_key} FROM #{quoted_table_name} #{where_sql})"
248
290
  end
249
291
 
292
+ # Sanitizes the given LIMIT parameter in order to prevent SQL injection.
293
+ #
294
+ # 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.
297
+ #
298
+ # 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
+ def sanitize_limit(limit)
302
+ if limit.is_a?(Integer) || limit.is_a?(Arel::Nodes::SqlLiteral)
303
+ limit
304
+ elsif limit.to_s =~ /,/
305
+ Arel.sql limit.to_s.split(',').map{ |i| Integer(i) }.join(',')
306
+ else
307
+ Integer(limit)
308
+ end
309
+ end
310
+
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
+
250
321
  protected
251
322
  # Returns an array of record hashes with the column names as keys and
252
323
  # column values as values.
253
- def select(sql, name = nil)
324
+ def select(sql, name = nil, binds = [])
254
325
  end
255
326
  undef_method :select
256
327
 
@@ -270,20 +341,50 @@ module ActiveRecord
270
341
  update_sql(sql, name)
271
342
  end
272
343
 
273
- # Sanitizes the given LIMIT parameter in order to prevent SQL injection.
274
- #
275
- # +limit+ may be anything that can evaluate to a string via #to_s. It
276
- # should look like an integer, or a comma-delimited list of integers.
277
- #
278
- # Returns the sanitized limit parameter, either as an integer, or as a
279
- # string which contains a comma-delimited list of integers.
280
- def sanitize_limit(limit)
281
- if limit.to_s =~ /,/
282
- limit.to_s.split(',').map{ |i| i.to_i }.join(',')
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
283
350
  else
284
- limit.to_i
351
+ records = @_current_transaction_records.pop
352
+ end
353
+
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
360
+ end
361
+ end
285
362
  end
286
363
  end
364
+
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
375
+ end
376
+ end
377
+ end
378
+ end
379
+
380
+ def sql_for_insert(sql, pk, id_value, sequence_name, binds)
381
+ [sql, binds]
382
+ end
383
+
384
+ def last_inserted_id(result)
385
+ row = result.rows.first
386
+ row && row.first
387
+ end
287
388
  end
288
389
  end
289
390
  end