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,83 +1,23 @@
1
- # encoding: binary
2
1
  require 'active_record/connection_adapters/abstract_adapter'
2
+ require 'active_record/connection_adapters/statement_pool'
3
+ require 'active_support/core_ext/string/encoding'
4
+ require 'arel/visitors/bind_visitor'
3
5
 
4
6
  module ActiveRecord
5
- class Base
6
- class << self
7
- # Establishes a connection to the database that's used by all Active Record objects
8
- def sqlite_connection(config) # :nodoc:
9
- parse_sqlite_config!(config)
10
-
11
- unless self.class.const_defined?(:SQLite)
12
- require_library_or_gem(config[:adapter])
13
-
14
- db = SQLite::Database.new(config[:database], 0)
15
- db.show_datatypes = "ON" if !defined? SQLite::Version
16
- db.results_as_hash = true if defined? SQLite::Version
17
- db.type_translation = false
18
-
19
- message = "Support for SQLite2Adapter and DeprecatedSQLiteAdapter has been removed from Rails 3. "
20
- message << "You should migrate to SQLite 3+ or use the plugin from git://github.com/rails/sqlite2_adapter.git with Rails 3."
21
- ActiveSupport::Deprecation.warn(message)
22
-
23
- # "Downgrade" deprecated sqlite API
24
- if SQLite.const_defined?(:Version)
25
- ConnectionAdapters::SQLite2Adapter.new(db, logger, config)
26
- else
27
- ConnectionAdapters::DeprecatedSQLiteAdapter.new(db, logger, config)
28
- end
29
- end
30
- end
31
-
32
- private
33
- def parse_sqlite_config!(config)
34
- if config.include?(:dbfile)
35
- ActiveSupport::Deprecation.warn "Please update config/database.yml to use 'database' instead of 'dbfile'"
36
- end
37
-
38
- config[:database] ||= config[:dbfile]
39
- # Require database.
40
- unless config[:database]
41
- raise ArgumentError, "No database file specified. Missing argument: database"
42
- end
43
-
44
- # Allow database path relative to RAILS_ROOT, but only if
45
- # the database path is not the special path that tells
46
- # Sqlite to build a database only in memory.
47
- if Object.const_defined?(:RAILS_ROOT) && ':memory:' != config[:database]
48
- config[:database] = File.expand_path(config[:database], RAILS_ROOT)
49
- end
50
- end
51
- end
52
- end
53
-
54
7
  module ConnectionAdapters #:nodoc:
55
8
  class SQLiteColumn < Column #:nodoc:
56
9
  class << self
57
- def string_to_binary(value)
58
- value = value.dup.force_encoding(Encoding::BINARY) if value.respond_to?(:force_encoding)
59
- value.gsub(/\0|\%/n) do |b|
60
- case b
61
- when "\0" then "%00"
62
- when "%" then "%25"
63
- end
64
- end
65
- end
66
-
67
10
  def binary_to_string(value)
68
- value = value.dup.force_encoding(Encoding::BINARY) if value.respond_to?(:force_encoding)
69
- value.gsub(/%00|%25/n) do |b|
70
- case b
71
- when "%00" then "\0"
72
- when "%25" then "%"
73
- end
11
+ if value.respond_to?(:force_encoding) && value.encoding != Encoding::ASCII_8BIT
12
+ value = value.force_encoding(Encoding::ASCII_8BIT)
74
13
  end
14
+ value
75
15
  end
76
16
  end
77
17
  end
78
18
 
79
- # The SQLite adapter works with both the 2.x and 3.x series of SQLite with the sqlite-ruby drivers (available both as gems and
80
- # from http://rubyforge.org/projects/sqlite-ruby/).
19
+ # The SQLite adapter works with both the 2.x and 3.x series of SQLite with the sqlite-ruby
20
+ # drivers (available both as gems and from http://rubyforge.org/projects/sqlite-ruby/).
81
21
  #
82
22
  # Options:
83
23
  #
@@ -87,56 +27,137 @@ module ActiveRecord
87
27
  include Comparable
88
28
 
89
29
  def initialize(version_string)
90
- @version = version_string.split('.').map(&:to_i)
30
+ @version = version_string.split('.').map { |v| v.to_i }
91
31
  end
92
32
 
93
33
  def <=>(version_string)
94
- @version <=> version_string.split('.').map(&:to_i)
34
+ @version <=> version_string.split('.').map { |v| v.to_i }
35
+ end
36
+ end
37
+
38
+ class StatementPool < ConnectionAdapters::StatementPool
39
+ def initialize(connection, max)
40
+ super
41
+ @cache = Hash.new { |h,pid| h[pid] = {} }
42
+ end
43
+
44
+ def each(&block); cache.each(&block); end
45
+ def key?(key); cache.key?(key); end
46
+ def [](key); cache[key]; end
47
+ def length; cache.length; end
48
+
49
+ def []=(sql, key)
50
+ while @max <= cache.size
51
+ dealloc(cache.shift.last[:stmt])
52
+ end
53
+ cache[sql] = key
54
+ end
55
+
56
+ def clear
57
+ cache.values.each do |hash|
58
+ dealloc hash[:stmt]
59
+ end
60
+ cache.clear
61
+ end
62
+
63
+ private
64
+ def cache
65
+ @cache[$$]
95
66
  end
67
+
68
+ def dealloc(stmt)
69
+ stmt.close unless stmt.closed?
70
+ end
71
+ end
72
+
73
+ class BindSubstitution < Arel::Visitors::SQLite # :nodoc:
74
+ include Arel::Visitors::BindVisitor
96
75
  end
97
76
 
98
77
  def initialize(connection, logger, config)
99
78
  super(connection, logger)
79
+ @statements = StatementPool.new(@connection,
80
+ config.fetch(:statement_limit) { 1000 })
100
81
  @config = config
82
+
83
+ if config.fetch(:prepared_statements) { true }
84
+ @visitor = Arel::Visitors::SQLite.new self
85
+ else
86
+ @visitor = BindSubstitution.new self
87
+ end
101
88
  end
102
89
 
103
90
  def adapter_name #:nodoc:
104
91
  'SQLite'
105
92
  end
106
93
 
94
+ # Returns true if SQLite version is '2.0.0' or greater, false otherwise.
107
95
  def supports_ddl_transactions?
108
96
  sqlite_version >= '2.0.0'
109
97
  end
110
98
 
99
+ # Returns true if SQLite version is '3.6.8' or greater, false otherwise.
100
+ def supports_savepoints?
101
+ sqlite_version >= '3.6.8'
102
+ end
103
+
104
+ # Returns true, since this connection adapter supports prepared statement
105
+ # caching.
106
+ def supports_statement_cache?
107
+ true
108
+ end
109
+
110
+ # Returns true, since this connection adapter supports migrations.
111
111
  def supports_migrations? #:nodoc:
112
112
  true
113
113
  end
114
114
 
115
+ # Returns true.
115
116
  def supports_primary_key? #:nodoc:
116
117
  true
117
118
  end
118
119
 
120
+ # Returns true.
121
+ def supports_explain?
122
+ true
123
+ end
124
+
119
125
  def requires_reloading?
120
126
  true
121
127
  end
122
128
 
129
+ # Returns true if SQLite version is '3.1.6' or greater, false otherwise.
123
130
  def supports_add_column?
124
131
  sqlite_version >= '3.1.6'
125
132
  end
126
-
133
+
134
+ # Disconnects from the database if already connected. Otherwise, this
135
+ # method does nothing.
127
136
  def disconnect!
128
137
  super
138
+ clear_cache!
129
139
  @connection.close rescue nil
130
140
  end
131
141
 
142
+ # Clears the prepared statements cache.
143
+ def clear_cache!
144
+ @statements.clear
145
+ end
146
+
147
+ # Returns true if SQLite version is '3.2.6' or greater, false otherwise.
132
148
  def supports_count_distinct? #:nodoc:
133
149
  sqlite_version >= '3.2.6'
134
150
  end
135
151
 
152
+ # Returns true if SQLite version is '3.1.0' or greater, false otherwise.
136
153
  def supports_autoincrement? #:nodoc:
137
154
  sqlite_version >= '3.1.0'
138
155
  end
139
156
 
157
+ def supports_index_sort_order?
158
+ sqlite_version >= '3.3.0'
159
+ end
160
+
140
161
  def native_database_types #:nodoc:
141
162
  {
142
163
  :primary_key => default_primary_key_type,
@@ -165,11 +186,96 @@ module ActiveRecord
165
186
  %Q("#{name.to_s.gsub('"', '""')}")
166
187
  end
167
188
 
189
+ # Quote date/time values for use in SQL input. Includes microseconds
190
+ # if the value is a Time responding to usec.
191
+ def quoted_date(value) #:nodoc:
192
+ if value.respond_to?(:usec)
193
+ "#{super}.#{sprintf("%06d", value.usec)}"
194
+ else
195
+ super
196
+ end
197
+ end
198
+
199
+ if "<3".encoding_aware?
200
+ def type_cast(value, column) # :nodoc:
201
+ return value.to_f if BigDecimal === value
202
+ return super unless String === value
203
+ return super unless column && value
204
+
205
+ value = super
206
+ if column.type == :string && value.encoding == Encoding::ASCII_8BIT
207
+ logger.error "Binary data inserted for `string` type on column `#{column.name}`" if logger
208
+ value = value.encode Encoding::UTF_8
209
+ end
210
+ value
211
+ end
212
+ else
213
+ def type_cast(value, column) # :nodoc:
214
+ return super unless BigDecimal === value
215
+
216
+ value.to_f
217
+ end
218
+ end
168
219
 
169
220
  # DATABASE STATEMENTS ======================================
170
221
 
222
+ def explain(arel, binds = [])
223
+ sql = "EXPLAIN QUERY PLAN #{to_sql(arel, binds)}"
224
+ ExplainPrettyPrinter.new.pp(exec_query(sql, 'EXPLAIN', binds))
225
+ end
226
+
227
+ class ExplainPrettyPrinter
228
+ # Pretty prints the result of a EXPLAIN QUERY PLAN in a way that resembles
229
+ # the output of the SQLite shell:
230
+ #
231
+ # 0|0|0|SEARCH TABLE users USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)
232
+ # 0|1|1|SCAN TABLE posts (~100000 rows)
233
+ #
234
+ def pp(result) # :nodoc:
235
+ result.rows.map do |row|
236
+ row.join('|')
237
+ end.join("\n") + "\n"
238
+ end
239
+ end
240
+
241
+ def exec_query(sql, name = nil, binds = [])
242
+ log(sql, name, binds) do
243
+
244
+ # Don't cache statements without bind values
245
+ if binds.empty?
246
+ stmt = @connection.prepare(sql)
247
+ cols = stmt.columns
248
+ records = stmt.to_a
249
+ stmt.close
250
+ stmt = records
251
+ else
252
+ cache = @statements[sql] ||= {
253
+ :stmt => @connection.prepare(sql)
254
+ }
255
+ stmt = cache[:stmt]
256
+ cols = cache[:cols] ||= stmt.columns
257
+ stmt.reset!
258
+ stmt.bind_params binds.map { |col, val|
259
+ type_cast(val, col)
260
+ }
261
+ end
262
+
263
+ ActiveRecord::Result.new(cols, stmt.to_a)
264
+ end
265
+ end
266
+
267
+ def exec_delete(sql, name = 'SQL', binds = [])
268
+ exec_query(sql, name, binds)
269
+ @connection.changes
270
+ end
271
+ alias :exec_update :exec_delete
272
+
273
+ def last_inserted_id(result)
274
+ @connection.last_insert_row_id
275
+ end
276
+
171
277
  def execute(sql, name = nil) #:nodoc:
172
- catch_schema_changes { log(sql, name) { @connection.execute(sql) } }
278
+ log(sql, name) { @connection.execute(sql) }
173
279
  end
174
280
 
175
281
  def update_sql(sql, name = nil) #:nodoc:
@@ -183,73 +289,104 @@ module ActiveRecord
183
289
  end
184
290
 
185
291
  def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
186
- super || @connection.last_insert_row_id
292
+ super
293
+ id_value || @connection.last_insert_row_id
187
294
  end
295
+ alias :create :insert_sql
188
296
 
189
297
  def select_rows(sql, name = nil)
190
- execute(sql, name).map do |row|
191
- (0...(row.size / 2)).map { |i| row[i] }
192
- end
298
+ exec_query(sql, name).rows
193
299
  end
194
300
 
195
- def begin_db_transaction #:nodoc:
196
- catch_schema_changes { @connection.transaction }
301
+ def create_savepoint
302
+ execute("SAVEPOINT #{current_savepoint_name}")
197
303
  end
198
304
 
199
- def commit_db_transaction #:nodoc:
200
- catch_schema_changes { @connection.commit }
305
+ def rollback_to_savepoint
306
+ execute("ROLLBACK TO SAVEPOINT #{current_savepoint_name}")
201
307
  end
202
308
 
203
- def rollback_db_transaction #:nodoc:
204
- catch_schema_changes { @connection.rollback }
309
+ def release_savepoint
310
+ execute("RELEASE SAVEPOINT #{current_savepoint_name}")
311
+ end
312
+
313
+ def begin_db_transaction #:nodoc:
314
+ log('begin transaction',nil) { @connection.transaction }
205
315
  end
206
316
 
207
- # SELECT ... FOR UPDATE is redundant since the table is locked.
208
- def add_lock!(sql, options) #:nodoc:
209
- sql
317
+ def commit_db_transaction #:nodoc:
318
+ log('commit transaction',nil) { @connection.commit }
210
319
  end
211
320
 
321
+ def rollback_db_transaction #:nodoc:
322
+ log('rollback transaction',nil) { @connection.rollback }
323
+ end
212
324
 
213
325
  # SCHEMA STATEMENTS ========================================
214
326
 
215
- def tables(name = nil) #:nodoc:
327
+ def tables(name = 'SCHEMA', table_name = nil) #:nodoc:
216
328
  sql = <<-SQL
217
329
  SELECT name
218
330
  FROM sqlite_master
219
331
  WHERE type = 'table' AND NOT name = 'sqlite_sequence'
220
332
  SQL
333
+ sql << " AND name = #{quote_table_name(table_name)}" if table_name
221
334
 
222
- execute(sql, name).map do |row|
335
+ exec_query(sql, name).map do |row|
223
336
  row['name']
224
337
  end
225
338
  end
226
339
 
340
+ def table_exists?(name)
341
+ name && tables('SCHEMA', name).any?
342
+ end
343
+
344
+ # Returns an array of +SQLiteColumn+ objects for the table specified by +table_name+.
227
345
  def columns(table_name, name = nil) #:nodoc:
228
346
  table_structure(table_name).map do |field|
347
+ case field["dflt_value"]
348
+ when /^null$/i
349
+ field["dflt_value"] = nil
350
+ when /^'(.*)'$/
351
+ field["dflt_value"] = $1.gsub(/''/, "'")
352
+ when /^"(.*)"$/
353
+ field["dflt_value"] = $1.gsub(/""/, '"')
354
+ end
355
+
229
356
  SQLiteColumn.new(field['name'], field['dflt_value'], field['type'], field['notnull'].to_i == 0)
230
357
  end
231
358
  end
232
359
 
360
+ # Returns an array of indexes for the given table.
233
361
  def indexes(table_name, name = nil) #:nodoc:
234
- execute("PRAGMA index_list(#{quote_table_name(table_name)})", name).map do |row|
235
- index = IndexDefinition.new(table_name, row['name'])
236
- index.unique = row['unique'].to_i != 0
237
- index.columns = execute("PRAGMA index_info('#{index.name}')").map { |col| col['name'] }
238
- index
362
+ exec_query("PRAGMA index_list(#{quote_table_name(table_name)})", 'SCHEMA').map do |row|
363
+ IndexDefinition.new(
364
+ table_name,
365
+ row['name'],
366
+ row['unique'] != 0,
367
+ exec_query("PRAGMA index_info('#{row['name']}')", 'SCHEMA').map { |col|
368
+ col['name']
369
+ })
239
370
  end
240
371
  end
241
372
 
242
373
  def primary_key(table_name) #:nodoc:
243
- column = table_structure(table_name).find {|field| field['pk'].to_i == 1}
244
- column ? column['name'] : nil
374
+ column = table_structure(table_name).find { |field|
375
+ field['pk'] == 1
376
+ }
377
+ column && column['name']
245
378
  end
246
379
 
247
380
  def remove_index!(table_name, index_name) #:nodoc:
248
- execute "DROP INDEX #{quote_column_name(index_name)}"
381
+ exec_query "DROP INDEX #{quote_column_name(index_name)}"
249
382
  end
250
383
 
384
+ # Renames a table.
385
+ #
386
+ # Example:
387
+ # rename_table('octopuses', 'octopi')
251
388
  def rename_table(name, new_name)
252
- execute "ALTER TABLE #{name} RENAME TO #{new_name}"
389
+ exec_query "ALTER TABLE #{quote_table_name(name)} RENAME TO #{quote_table_name(new_name)}"
253
390
  end
254
391
 
255
392
  # See: http://www.sqlite.org/lang_altertable.html
@@ -269,8 +406,15 @@ module ActiveRecord
269
406
  end
270
407
 
271
408
  def remove_column(table_name, *column_names) #:nodoc:
272
- raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_names.empty?
273
- column_names.flatten.each do |column_name|
409
+ raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_names.empty?
410
+
411
+ if column_names.flatten!
412
+ message = 'Passing array to remove_columns is deprecated, please use ' +
413
+ 'multiple arguments, like: `remove_columns(:posts, :foo, :bar)`'
414
+ ActiveSupport::Deprecation.warn message, caller
415
+ end
416
+
417
+ column_names.each do |column_name|
274
418
  alter_table(table_name) do |definition|
275
419
  definition.columns.delete(definition[column_name])
276
420
  end
@@ -286,7 +430,7 @@ module ActiveRecord
286
430
 
287
431
  def change_column_null(table_name, column_name, null, default = nil)
288
432
  unless null || default.nil?
289
- execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
433
+ exec_query("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
290
434
  end
291
435
  alter_table(table_name) do |definition|
292
436
  definition[column_name].null = null
@@ -301,6 +445,8 @@ module ActiveRecord
301
445
  self.limit = options[:limit] if options.include?(:limit)
302
446
  self.default = options[:default] if include_default
303
447
  self.null = options[:null] if options.include?(:null)
448
+ self.precision = options[:precision] if options.include?(:precision)
449
+ self.scale = options[:scale] if options.include?(:scale)
304
450
  end
305
451
  end
306
452
  end
@@ -312,27 +458,19 @@ module ActiveRecord
312
458
  alter_table(table_name, :rename => {column_name.to_s => new_column_name.to_s})
313
459
  end
314
460
 
315
- def empty_insert_statement(table_name)
316
- "INSERT INTO #{table_name} VALUES(NULL)"
461
+ def empty_insert_statement_value
462
+ "VALUES(NULL)"
317
463
  end
318
464
 
319
465
  protected
320
- def select(sql, name = nil) #:nodoc:
321
- execute(sql, name).map do |row|
322
- record = {}
323
- row.each_key do |key|
324
- if key.is_a?(String)
325
- record[key.sub(/^"?\w+"?\./, '')] = row[key]
326
- end
327
- end
328
- record
329
- end
466
+ def select(sql, name = nil, binds = []) #:nodoc:
467
+ exec_query(sql, name, binds).to_a
330
468
  end
331
469
 
332
470
  def table_structure(table_name)
333
- execute("PRAGMA table_info(#{quote_table_name(table_name)})").tap do |structure|
334
- raise(ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'") if structure.empty?
335
- end
471
+ structure = exec_query("PRAGMA table_info(#{quote_table_name(table_name)})", 'SCHEMA').to_hash
472
+ raise(ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'") if structure.empty?
473
+ structure
336
474
  end
337
475
 
338
476
  def alter_table(table_name, options = {}) #:nodoc:
@@ -352,7 +490,11 @@ module ActiveRecord
352
490
  end
353
491
 
354
492
  def copy_table(from, to, options = {}) #:nodoc:
355
- options = options.merge(:id => (!columns(from).detect{|c| c.name == 'id'}.nil? && 'id' == primary_key(from).to_s))
493
+ from_primary_key = primary_key(from)
494
+ options[:primary_key] = from_primary_key if from_primary_key != 'id'
495
+ unless options[:primary_key]
496
+ options[:id] = !columns(from).detect{|c| c.name == 'id'}.nil? && 'id' == from_primary_key
497
+ end
356
498
  create_table(to, options) do |definition|
357
499
  @definition = definition
358
500
  columns(from).each do |column|
@@ -360,12 +502,13 @@ module ActiveRecord
360
502
  (options[:rename][column.name] ||
361
503
  options[:rename][column.name.to_sym] ||
362
504
  column.name) : column.name
363
-
505
+
364
506
  @definition.column(column_name, column.type,
365
507
  :limit => column.limit, :default => column.default,
508
+ :precision => column.precision, :scale => column.scale,
366
509
  :null => column.null)
367
510
  end
368
- @definition.primary_key(primary_key(from)) if primary_key(from)
511
+ @definition.primary_key(from_primary_key) if from_primary_key
369
512
  yield @definition if block_given?
370
513
  end
371
514
 
@@ -384,14 +527,14 @@ module ActiveRecord
384
527
  name = name[5..-1]
385
528
  end
386
529
 
387
- to_column_names = columns(to).map(&:name)
530
+ to_column_names = columns(to).map { |c| c.name }
388
531
  columns = index.columns.map {|c| rename[c] || c }.select do |column|
389
532
  to_column_names.include?(column)
390
533
  end
391
534
 
392
535
  unless columns.empty?
393
536
  # index name can't be the same
394
- opts = { :name => name.gsub(/_(#{from})_/, "_#{to}_") }
537
+ opts = { :name => name.gsub(/(^|_)(#{from})_/, "\\1#{to}_") }
395
538
  opts[:unique] = true if index.unique
396
539
  add_index(to, columns, opts)
397
540
  end
@@ -399,29 +542,18 @@ module ActiveRecord
399
542
  end
400
543
 
401
544
  def copy_table_contents(from, to, columns, rename = {}) #:nodoc:
402
- column_mappings = Hash[*columns.map {|name| [name, name]}.flatten]
403
- rename.inject(column_mappings) {|map, a| map[a.last] = a.first; map}
545
+ column_mappings = Hash[columns.map {|name| [name, name]}]
546
+ rename.each { |a| column_mappings[a.last] = a.first }
404
547
  from_columns = columns(from).collect {|col| col.name}
405
548
  columns = columns.find_all{|col| from_columns.include?(column_mappings[col])}
406
549
  quoted_columns = columns.map { |col| quote_column_name(col) } * ','
407
550
 
408
551
  quoted_to = quote_table_name(to)
409
- @connection.execute "SELECT * FROM #{quote_table_name(from)}" do |row|
552
+ exec_query("SELECT * FROM #{quote_table_name(from)}").each do |row|
410
553
  sql = "INSERT INTO #{quoted_to} (#{quoted_columns}) VALUES ("
411
554
  sql << columns.map {|col| quote row[column_mappings[col]]} * ', '
412
555
  sql << ')'
413
- @connection.execute sql
414
- end
415
- end
416
-
417
- def catch_schema_changes
418
- return yield
419
- rescue ActiveRecord::StatementInvalid => exception
420
- if exception.message =~ /database schema has changed/
421
- reconnect!
422
- retry
423
- else
424
- raise
556
+ exec_query sql
425
557
  end
426
558
  end
427
559
 
@@ -431,24 +563,21 @@ module ActiveRecord
431
563
 
432
564
  def default_primary_key_type
433
565
  if supports_autoincrement?
434
- 'INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL'.freeze
566
+ 'INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL'
435
567
  else
436
- 'INTEGER PRIMARY KEY NOT NULL'.freeze
568
+ 'INTEGER PRIMARY KEY NOT NULL'
437
569
  end
438
570
  end
439
- end
440
571
 
441
- class SQLite2Adapter < SQLiteAdapter # :nodoc:
442
- def rename_table(name, new_name)
443
- move_table(name, new_name)
444
- end
445
- end
572
+ def translate_exception(exception, message)
573
+ case exception.message
574
+ when /column(s)? .* (is|are) not unique/
575
+ RecordNotUnique.new(message, exception)
576
+ else
577
+ super
578
+ end
579
+ end
446
580
 
447
- class DeprecatedSQLiteAdapter < SQLite2Adapter # :nodoc:
448
- def insert(sql, name = nil, pk = nil, id_value = nil)
449
- execute(sql, name = nil)
450
- id_value || @connection.last_insert_rowid
451
- end
452
581
  end
453
582
  end
454
583
  end
@@ -0,0 +1,40 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class StatementPool
4
+ include Enumerable
5
+
6
+ def initialize(connection, max = 1000)
7
+ @connection = connection
8
+ @max = max
9
+ end
10
+
11
+ def each
12
+ raise NotImplementedError
13
+ end
14
+
15
+ def key?(key)
16
+ raise NotImplementedError
17
+ end
18
+
19
+ def [](key)
20
+ raise NotImplementedError
21
+ end
22
+
23
+ def length
24
+ raise NotImplementedError
25
+ end
26
+
27
+ def []=(sql, key)
28
+ raise NotImplementedError
29
+ end
30
+
31
+ def clear
32
+ raise NotImplementedError
33
+ end
34
+
35
+ def delete(key)
36
+ raise NotImplementedError
37
+ end
38
+ end
39
+ end
40
+ end