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,5 +1,7 @@
1
+ require 'thread'
1
2
  require 'monitor'
2
3
  require 'set'
4
+ require 'active_support/core_ext/module/deprecation'
3
5
 
4
6
  module ActiveRecord
5
7
  # Raised when a connection could not be obtained within the connection
@@ -8,7 +10,7 @@ module ActiveRecord
8
10
  end
9
11
 
10
12
  module ConnectionAdapters
11
- # Connection pool base class for managing ActiveRecord database
13
+ # Connection pool base class for managing Active Record database
12
14
  # connections.
13
15
  #
14
16
  # == Introduction
@@ -29,12 +31,12 @@ module ActiveRecord
29
31
  # Connections can be obtained and used from a connection pool in several
30
32
  # ways:
31
33
  #
32
- # 1. Simply use ActiveRecord::Base.connection as with ActiveRecord 2.1 and
34
+ # 1. Simply use ActiveRecord::Base.connection as with Active Record 2.1 and
33
35
  # earlier (pre-connection-pooling). Eventually, when you're done with
34
36
  # the connection(s) and wish it to be returned to the pool, you call
35
37
  # ActiveRecord::Base.clear_active_connections!. This will be the
36
- # default behavior for ActiveRecord when used in conjunction with
37
- # ActionPack's request handling cycle.
38
+ # default behavior for Active Record when used in conjunction with
39
+ # Action Pack's request handling cycle.
38
40
  # 2. Manually check out a connection from the pool with
39
41
  # ActiveRecord::Base.connection_pool.checkout. You are responsible for
40
42
  # returning this connection to the pool when finished by calling
@@ -52,10 +54,16 @@ module ActiveRecord
52
54
  # your database connection configuration:
53
55
  #
54
56
  # * +pool+: number indicating size of connection pool (default 5)
55
- # * +wait_timeout+: number of seconds to block and wait for a connection
56
- # before giving up and raising a timeout error (default 5 seconds).
57
+ # * +checkout _timeout+: number of seconds to block and wait for a
58
+ # connection before giving up and raising a timeout error
59
+ # (default 5 seconds). ('wait_timeout' supported for backwards
60
+ # compatibility, but conflicts with key used for different purpose
61
+ # by mysql2 adapter).
57
62
  class ConnectionPool
58
- attr_reader :spec
63
+ include MonitorMixin
64
+
65
+ attr_accessor :automatic_reconnect
66
+ attr_reader :spec, :connections
59
67
 
60
68
  # Creates a new ConnectionPool object. +spec+ is a ConnectionSpecification
61
69
  # object which describes database connection information (e.g. adapter,
@@ -64,26 +72,24 @@ module ActiveRecord
64
72
  #
65
73
  # The default ConnectionPool maximum size is 5.
66
74
  def initialize(spec)
75
+ super()
76
+
67
77
  @spec = spec
68
78
 
69
79
  # The cache of reserved connections mapped to threads
70
80
  @reserved_connections = {}
71
81
 
72
- # The mutex used to synchronize pool access
73
- @connection_mutex = Monitor.new
74
- @queue = @connection_mutex.new_cond
75
-
76
- # default 5 second timeout unless on ruby 1.9
77
- @timeout =
78
- if RUBY_VERSION < '1.9'
79
- spec.config[:wait_timeout] || 5
80
- end
82
+ @queue = new_cond
83
+ # 'wait_timeout', the backward-compatible key, conflicts with spec key
84
+ # used by mysql2 for something entirely different, checkout_timeout
85
+ # preferred to avoid conflict and allow independent values.
86
+ @timeout = spec.config[:checkout_timeout] || spec.config[:wait_timeout] || 5
81
87
 
82
88
  # default max pool size to 5
83
89
  @size = (spec.config[:pool] && spec.config[:pool].to_i) || 5
84
90
 
85
- @connections = []
86
- @checked_out = []
91
+ @connections = []
92
+ @automatic_reconnect = true
87
93
  end
88
94
 
89
95
  # Retrieve the connection associated with the current thread, or call
@@ -92,73 +98,124 @@ module ActiveRecord
92
98
  # #connection can be called any number of times; the connection is
93
99
  # held in a hash keyed by the thread id.
94
100
  def connection
95
- if conn = @reserved_connections[current_connection_id]
96
- conn
97
- else
98
- @reserved_connections[current_connection_id] = checkout
101
+ synchronize do
102
+ @reserved_connections[current_connection_id] ||= checkout
103
+ end
104
+ end
105
+
106
+ # Is there an open connection that is being used for the current thread?
107
+ def active_connection?
108
+ synchronize do
109
+ @reserved_connections.fetch(current_connection_id) {
110
+ return false
111
+ }.in_use?
99
112
  end
100
113
  end
101
114
 
102
115
  # Signal that the thread is finished with the current connection.
103
116
  # #release_connection releases the connection-thread association
104
117
  # and returns the connection to the pool.
105
- def release_connection
106
- conn = @reserved_connections.delete(current_connection_id)
118
+ def release_connection(with_id = current_connection_id)
119
+ conn = synchronize { @reserved_connections.delete(with_id) }
107
120
  checkin conn if conn
108
121
  end
109
122
 
110
- # Reserve a connection, and yield it to a block. Ensure the connection is
111
- # checked back in when finished.
123
+ # If a connection already exists yield it to the block. If no connection
124
+ # exists checkout a connection, yield it to the block, and checkin the
125
+ # connection when finished.
112
126
  def with_connection
113
- conn = checkout
114
- yield conn
127
+ connection_id = current_connection_id
128
+ fresh_connection = true unless active_connection?
129
+ yield connection
115
130
  ensure
116
- checkin conn
131
+ release_connection(connection_id) if fresh_connection
117
132
  end
118
133
 
119
134
  # Returns true if a connection has already been opened.
120
135
  def connected?
121
- !@connections.empty?
136
+ synchronize { @connections.any? }
122
137
  end
123
138
 
124
139
  # Disconnects all connections in the pool, and clears the pool.
125
140
  def disconnect!
126
- @reserved_connections.each do |name,conn|
127
- checkin conn
128
- end
129
- @reserved_connections = {}
130
- @connections.each do |conn|
131
- conn.disconnect!
141
+ synchronize do
142
+ @reserved_connections = {}
143
+ @connections.each do |conn|
144
+ checkin conn
145
+ conn.disconnect!
146
+ end
147
+ @connections = []
132
148
  end
133
- @connections = []
134
149
  end
135
150
 
136
- # Clears the cache which maps classes
151
+ # Clears the cache which maps classes.
137
152
  def clear_reloadable_connections!
138
- @reserved_connections.each do |name, conn|
139
- checkin conn
140
- end
141
- @reserved_connections = {}
142
- @connections.each do |conn|
143
- conn.disconnect! if conn.requires_reloading?
153
+ synchronize do
154
+ @reserved_connections = {}
155
+ @connections.each do |conn|
156
+ checkin conn
157
+ conn.disconnect! if conn.requires_reloading?
158
+ end
159
+ @connections.delete_if do |conn|
160
+ conn.requires_reloading?
161
+ end
144
162
  end
145
- @connections = []
146
163
  end
147
164
 
148
165
  # Verify active connections and remove and disconnect connections
149
166
  # associated with stale threads.
150
167
  def verify_active_connections! #:nodoc:
151
- clear_stale_cached_connections!
152
- @connections.each do |connection|
153
- connection.verify!
168
+ synchronize do
169
+ clear_stale_cached_connections!
170
+ @connections.each do |connection|
171
+ connection.verify!
172
+ end
173
+ end
174
+ end
175
+
176
+ def columns
177
+ with_connection do |c|
178
+ c.schema_cache.columns
179
+ end
180
+ end
181
+ deprecate :columns
182
+
183
+ def columns_hash
184
+ with_connection do |c|
185
+ c.schema_cache.columns_hash
186
+ end
187
+ end
188
+ deprecate :columns_hash
189
+
190
+ def primary_keys
191
+ with_connection do |c|
192
+ c.schema_cache.primary_keys
154
193
  end
155
194
  end
195
+ deprecate :primary_keys
196
+
197
+ def clear_cache!
198
+ with_connection do |c|
199
+ c.schema_cache.clear!
200
+ end
201
+ end
202
+ deprecate :clear_cache!
156
203
 
157
204
  # Return any checked-out connections back to the pool by threads that
158
205
  # are no longer alive.
159
206
  def clear_stale_cached_connections!
160
- remove_stale_cached_threads!(@reserved_connections) do |name, conn|
207
+ keys = @reserved_connections.keys - Thread.list.find_all { |t|
208
+ t.alive?
209
+ }.map { |thread| thread.object_id }
210
+ keys.each do |key|
211
+ conn = @reserved_connections[key]
212
+ ActiveSupport::Deprecation.warn(<<-eowarn) if conn.in_use?
213
+ Database connections will not be closed automatically, please close your
214
+ database connection at the end of the thread by calling `close` on your
215
+ connection. For example: ActiveRecord::Base.connection.close
216
+ eowarn
161
217
  checkin conn
218
+ @reserved_connections.delete(key)
162
219
  end
163
220
  end
164
221
 
@@ -179,25 +236,43 @@ module ActiveRecord
179
236
  # - ConnectionTimeoutError: no connection can be obtained from the pool
180
237
  # within the timeout period.
181
238
  def checkout
182
- # Checkout an available connection
183
- @connection_mutex.synchronize do
239
+ synchronize do
240
+ waited_time = 0
241
+
184
242
  loop do
185
- conn = if @checked_out.size < @connections.size
186
- checkout_existing_connection
187
- elsif @connections.size < @size
188
- checkout_new_connection
189
- end
190
- return conn if conn
191
- # No connections available; wait for one
192
- if @queue.wait(@timeout)
193
- next
194
- else
195
- # try looting dead threads
196
- clear_stale_cached_connections!
197
- if @size == @checked_out.size
198
- raise ConnectionTimeoutError, "could not obtain a database connection#{" within #{@timeout} seconds" if @timeout}. The max pool size is currently #{@size}; consider increasing it."
243
+ conn = @connections.find { |c| c.lease }
244
+
245
+ unless conn
246
+ if @connections.size < @size
247
+ conn = checkout_new_connection
248
+ conn.lease
199
249
  end
200
250
  end
251
+
252
+ if conn
253
+ checkout_and_verify conn
254
+ return conn
255
+ end
256
+
257
+ if waited_time >= @timeout
258
+ raise ConnectionTimeoutError, "could not obtain a database connection#{" within #{@timeout} seconds" if @timeout} (waited #{waited_time} seconds). The max pool size is currently #{@size}; consider increasing it."
259
+ end
260
+
261
+ # Sometimes our wait can end because a connection is available,
262
+ # but another thread can snatch it up first. If timeout hasn't
263
+ # passed but no connection is avail, looks like that happened --
264
+ # loop and wait again, for the time remaining on our timeout.
265
+ before_wait = Time.now
266
+ @queue.wait( [@timeout - waited_time, 0].max )
267
+ waited_time += (Time.now - before_wait)
268
+
269
+ # Will go away in Rails 4, when we don't clean up
270
+ # after leaked connections automatically anymore. Right now, clean
271
+ # up after we've returned from a 'wait' if it looks like it's
272
+ # needed, then loop and try again.
273
+ if(active_connections.size >= @connections.size)
274
+ clear_stale_cached_connections!
275
+ end
201
276
  end
202
277
  end
203
278
  end
@@ -208,60 +283,65 @@ module ActiveRecord
208
283
  # +conn+: an AbstractAdapter object, which was obtained by earlier by
209
284
  # calling +checkout+ on this pool.
210
285
  def checkin(conn)
211
- @connection_mutex.synchronize do
212
- conn.run_callbacks :checkin
213
- @checked_out.delete conn
214
- @queue.signal
286
+ synchronize do
287
+ conn.run_callbacks :checkin do
288
+ conn.expire
289
+ @queue.signal
290
+ end
291
+
292
+ release conn
215
293
  end
216
294
  end
217
295
 
218
- synchronize :clear_reloadable_connections!, :verify_active_connections!,
219
- :connected?, :disconnect!, :with => :@connection_mutex
220
-
221
296
  private
297
+
298
+ def release(conn)
299
+ synchronize do
300
+ thread_id = nil
301
+
302
+ if @reserved_connections[current_connection_id] == conn
303
+ thread_id = current_connection_id
304
+ else
305
+ thread_id = @reserved_connections.keys.find { |k|
306
+ @reserved_connections[k] == conn
307
+ }
308
+ end
309
+
310
+ @reserved_connections.delete thread_id if thread_id
311
+ end
312
+ end
313
+
222
314
  def new_connection
223
315
  ActiveRecord::Base.send(spec.adapter_method, spec.config)
224
316
  end
225
317
 
226
318
  def current_connection_id #:nodoc:
227
- Thread.current.object_id
228
- end
229
-
230
- # Remove stale threads from the cache.
231
- def remove_stale_cached_threads!(cache, &block)
232
- keys = Set.new(cache.keys)
233
-
234
- Thread.list.each do |thread|
235
- keys.delete(thread.object_id) if thread.alive?
236
- end
237
- keys.each do |key|
238
- next unless cache.has_key?(key)
239
- block.call(key, cache[key])
240
- cache.delete(key)
241
- end
319
+ ActiveRecord::Base.connection_id ||= Thread.current.object_id
242
320
  end
243
321
 
244
322
  def checkout_new_connection
323
+ raise ConnectionNotEstablished unless @automatic_reconnect
324
+
245
325
  c = new_connection
326
+ c.pool = self
246
327
  @connections << c
247
- checkout_and_verify(c)
248
- end
249
-
250
- def checkout_existing_connection
251
- c = (@connections - @checked_out).first
252
- checkout_and_verify(c)
328
+ c
253
329
  end
254
330
 
255
331
  def checkout_and_verify(c)
256
- c.verify!
257
- c.run_callbacks :checkout
258
- @checked_out << c
332
+ c.run_callbacks :checkout do
333
+ c.verify!
334
+ end
259
335
  c
260
336
  end
337
+
338
+ def active_connections
339
+ @connections.find_all { |c| c.in_use? }
340
+ end
261
341
  end
262
342
 
263
343
  # ConnectionHandler is a collection of ConnectionPool objects. It is used
264
- # for keeping separate connection pools for ActiveRecord models that connect
344
+ # for keeping separate connection pools for Active Record models that connect
265
345
  # to different databases.
266
346
  #
267
347
  # For example, suppose that you have 5 models, with the following hierarchy:
@@ -281,29 +361,33 @@ module ActiveRecord
281
361
  # is not the same as the one used by Book/ScaryBook/GoodBook.
282
362
  #
283
363
  # Normally there is only a single ConnectionHandler instance, accessible via
284
- # ActiveRecord::Base.connection_handler. ActiveRecord models use this to
364
+ # ActiveRecord::Base.connection_handler. Active Record models use this to
285
365
  # determine that connection pool that they should use.
286
366
  class ConnectionHandler
367
+ attr_reader :connection_pools
368
+
287
369
  def initialize(pools = {})
288
370
  @connection_pools = pools
371
+ @class_to_pool = {}
289
372
  end
290
373
 
291
- def connection_pools
292
- @connection_pools ||= {}
374
+ def establish_connection(name, spec)
375
+ @connection_pools[spec] ||= ConnectionAdapters::ConnectionPool.new(spec)
376
+ @class_to_pool[name] = @connection_pools[spec]
293
377
  end
294
378
 
295
- def establish_connection(name, spec)
296
- @connection_pools[name] = ConnectionAdapters::ConnectionPool.new(spec)
379
+ # Returns true if there are any active connections among the connection
380
+ # pools that the ConnectionHandler is managing.
381
+ def active_connections?
382
+ connection_pools.values.any? { |pool| pool.active_connection? }
297
383
  end
298
384
 
299
- # Returns any connections in use by the current thread back to the pool,
300
- # and also returns connections to the pool cached by threads that are no
301
- # longer alive.
385
+ # Returns any connections in use by the current thread back to the pool.
302
386
  def clear_active_connections!
303
387
  @connection_pools.each_value {|pool| pool.release_connection }
304
388
  end
305
389
 
306
- # Clears the cache which maps classes
390
+ # Clears the cache which maps classes.
307
391
  def clear_reloadable_connections!
308
392
  @connection_pools.each_value {|pool| pool.clear_reloadable_connections! }
309
393
  end
@@ -330,7 +414,7 @@ module ActiveRecord
330
414
  # already been opened.
331
415
  def connected?(klass)
332
416
  conn = retrieve_connection_pool(klass)
333
- conn ? conn.connected? : false
417
+ conn && conn.connected?
334
418
  end
335
419
 
336
420
  # Remove the connection for this class. This will close the active
@@ -338,14 +422,17 @@ module ActiveRecord
338
422
  # can be used as an argument for establish_connection, for easily
339
423
  # re-establishing the connection.
340
424
  def remove_connection(klass)
341
- pool = @connection_pools[klass.name]
342
- @connection_pools.delete_if { |key, value| value == pool }
343
- pool.disconnect! if pool
344
- pool.spec.config if pool
425
+ pool = @class_to_pool.delete(klass.name)
426
+ return nil unless pool
427
+
428
+ @connection_pools.delete pool.spec
429
+ pool.automatic_reconnect = false
430
+ pool.disconnect!
431
+ pool.spec.config
345
432
  end
346
433
 
347
434
  def retrieve_connection_pool(klass)
348
- pool = @connection_pools[klass.name]
435
+ pool = @class_to_pool[klass.name]
349
436
  return pool if pool
350
437
  return nil if ActiveRecord::Base == klass
351
438
  retrieve_connection_pool klass.superclass
@@ -353,18 +440,48 @@ module ActiveRecord
353
440
  end
354
441
 
355
442
  class ConnectionManagement
443
+ class Proxy # :nodoc:
444
+ attr_reader :body, :testing
445
+
446
+ def initialize(body, testing = false)
447
+ @body = body
448
+ @testing = testing
449
+ end
450
+
451
+ def method_missing(method_sym, *arguments, &block)
452
+ @body.send(method_sym, *arguments, &block)
453
+ end
454
+
455
+ def respond_to?(method_sym, include_private = false)
456
+ super || @body.respond_to?(method_sym)
457
+ end
458
+
459
+ def each(&block)
460
+ body.each(&block)
461
+ end
462
+
463
+ def close
464
+ body.close if body.respond_to?(:close)
465
+
466
+ # Don't return connection (and perform implicit rollback) if
467
+ # this request is a part of integration test
468
+ ActiveRecord::Base.clear_active_connections! unless testing
469
+ end
470
+ end
471
+
356
472
  def initialize(app)
357
473
  @app = app
358
474
  end
359
475
 
360
476
  def call(env)
361
- @app.call(env)
362
- ensure
363
- # Don't return connection (and peform implicit rollback) if
364
- # this request is a part of integration test
365
- unless env.key?("rack.test")
366
- ActiveRecord::Base.clear_active_connections!
367
- end
477
+ testing = env.key?('rack.test')
478
+
479
+ status, headers, body = @app.call(env)
480
+
481
+ [status, headers, Proxy.new(body, testing)]
482
+ rescue
483
+ ActiveRecord::Base.clear_active_connections! unless testing
484
+ raise
368
485
  end
369
486
  end
370
487
  end