activerecord 2.3.18 → 3.0.0.beta

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 (378) hide show
  1. data/CHANGELOG +105 -34
  2. data/examples/performance.rb +3 -39
  3. data/examples/simple.rb +14 -0
  4. data/lib/active_record.rb +81 -47
  5. data/lib/active_record/aggregations.rb +1 -3
  6. data/lib/active_record/association_preload.rb +39 -54
  7. data/lib/active_record/associations.rb +262 -419
  8. data/lib/active_record/associations/association_collection.rb +85 -100
  9. data/lib/active_record/associations/association_proxy.rb +20 -18
  10. data/lib/active_record/associations/belongs_to_association.rb +8 -8
  11. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +13 -35
  12. data/lib/active_record/associations/has_many_association.rb +11 -19
  13. data/lib/active_record/associations/has_many_through_association.rb +30 -183
  14. data/lib/active_record/associations/has_one_association.rb +10 -10
  15. data/lib/active_record/associations/has_one_through_association.rb +13 -11
  16. data/lib/active_record/associations/through_association_scope.rb +153 -0
  17. data/lib/active_record/attribute_methods.rb +17 -370
  18. data/lib/active_record/attribute_methods/before_type_cast.rb +33 -0
  19. data/lib/active_record/attribute_methods/dirty.rb +87 -0
  20. data/lib/active_record/attribute_methods/primary_key.rb +44 -0
  21. data/lib/active_record/attribute_methods/query.rb +37 -0
  22. data/lib/active_record/attribute_methods/read.rb +116 -0
  23. data/lib/active_record/attribute_methods/time_zone_conversion.rb +60 -0
  24. data/lib/active_record/attribute_methods/write.rb +37 -0
  25. data/lib/active_record/autosave_association.rb +20 -41
  26. data/lib/active_record/base.rb +357 -1180
  27. data/lib/active_record/batches.rb +10 -16
  28. data/lib/active_record/callbacks.rb +66 -126
  29. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +17 -13
  30. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +5 -25
  31. data/lib/active_record/connection_adapters/abstract/database_statements.rb +4 -43
  32. data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -2
  33. data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -4
  34. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +1 -1
  35. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +18 -72
  36. data/lib/active_record/connection_adapters/abstract_adapter.rb +16 -49
  37. data/lib/active_record/connection_adapters/mysql_adapter.rb +15 -27
  38. data/lib/active_record/connection_adapters/postgresql_adapter.rb +84 -46
  39. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +9 -3
  40. data/lib/active_record/connection_adapters/sqlite_adapter.rb +34 -65
  41. data/lib/active_record/fixtures.rb +21 -25
  42. data/lib/active_record/locale/en.yml +9 -27
  43. data/lib/active_record/locking/optimistic.rb +16 -48
  44. data/lib/active_record/migration.rb +59 -46
  45. data/lib/active_record/named_scope.rb +85 -92
  46. data/lib/active_record/nested_attributes.rb +18 -24
  47. data/lib/active_record/observer.rb +18 -94
  48. data/lib/active_record/railtie.rb +83 -0
  49. data/lib/active_record/railties/controller_runtime.rb +38 -0
  50. data/lib/active_record/railties/databases.rake +477 -0
  51. data/lib/active_record/railties/subscriber.rb +27 -0
  52. data/lib/active_record/reflection.rb +2 -15
  53. data/lib/active_record/relation.rb +339 -0
  54. data/lib/active_record/relation/calculations.rb +259 -0
  55. data/lib/active_record/relation/finder_methods.rb +315 -0
  56. data/lib/active_record/relation/predicate_builder.rb +46 -0
  57. data/lib/active_record/relation/query_methods.rb +218 -0
  58. data/lib/active_record/relation/spawn_methods.rb +102 -0
  59. data/lib/active_record/schema_dumper.rb +10 -6
  60. data/lib/active_record/serialization.rb +31 -74
  61. data/lib/active_record/serializers/xml_serializer.rb +33 -121
  62. data/lib/active_record/session_store.rb +1 -9
  63. data/lib/active_record/test_case.rb +1 -3
  64. data/lib/active_record/timestamp.rb +7 -5
  65. data/lib/active_record/transactions.rb +9 -9
  66. data/lib/active_record/validations.rb +51 -1100
  67. data/lib/active_record/validations/associated.rb +47 -0
  68. data/lib/active_record/validations/uniqueness.rb +181 -0
  69. data/lib/active_record/version.rb +3 -3
  70. data/lib/generators/active_record.rb +30 -0
  71. data/lib/generators/active_record/migration/migration_generator.rb +25 -0
  72. data/lib/generators/active_record/migration/templates/migration.rb +11 -0
  73. data/lib/generators/active_record/model/model_generator.rb +33 -0
  74. data/lib/generators/active_record/model/templates/migration.rb +16 -0
  75. data/lib/generators/active_record/model/templates/model.rb +5 -0
  76. data/lib/generators/active_record/observer/observer_generator.rb +15 -0
  77. data/lib/generators/active_record/observer/templates/observer.rb +2 -0
  78. data/lib/generators/active_record/session_migration/session_migration_generator.rb +24 -0
  79. data/lib/generators/active_record/session_migration/templates/migration.rb +16 -0
  80. metadata +67 -325
  81. data/RUNNING_UNIT_TESTS +0 -36
  82. data/Rakefile +0 -268
  83. data/install.rb +0 -30
  84. data/lib/active_record/calculations.rb +0 -321
  85. data/lib/active_record/connection_adapters/abstract/database_limits.rb +0 -57
  86. data/lib/active_record/dirty.rb +0 -183
  87. data/lib/active_record/serializers/json_serializer.rb +0 -91
  88. data/lib/activerecord.rb +0 -2
  89. data/test/assets/example.log +0 -1
  90. data/test/assets/flowers.jpg +0 -0
  91. data/test/cases/aaa_create_tables_test.rb +0 -24
  92. data/test/cases/active_schema_test_mysql.rb +0 -122
  93. data/test/cases/active_schema_test_postgresql.rb +0 -24
  94. data/test/cases/adapter_test.rb +0 -144
  95. data/test/cases/aggregations_test.rb +0 -167
  96. data/test/cases/ar_schema_test.rb +0 -32
  97. data/test/cases/associations/belongs_to_associations_test.rb +0 -438
  98. data/test/cases/associations/callbacks_test.rb +0 -161
  99. data/test/cases/associations/cascaded_eager_loading_test.rb +0 -131
  100. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +0 -36
  101. data/test/cases/associations/eager_load_nested_include_test.rb +0 -131
  102. data/test/cases/associations/eager_load_nested_polymorphic_include.rb +0 -19
  103. data/test/cases/associations/eager_singularization_test.rb +0 -145
  104. data/test/cases/associations/eager_test.rb +0 -852
  105. data/test/cases/associations/extension_test.rb +0 -62
  106. data/test/cases/associations/habtm_join_table_test.rb +0 -56
  107. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +0 -827
  108. data/test/cases/associations/has_many_associations_test.rb +0 -1273
  109. data/test/cases/associations/has_many_through_associations_test.rb +0 -360
  110. data/test/cases/associations/has_one_associations_test.rb +0 -330
  111. data/test/cases/associations/has_one_through_associations_test.rb +0 -209
  112. data/test/cases/associations/inner_join_association_test.rb +0 -93
  113. data/test/cases/associations/inverse_associations_test.rb +0 -566
  114. data/test/cases/associations/join_model_test.rb +0 -712
  115. data/test/cases/associations_test.rb +0 -282
  116. data/test/cases/attribute_methods_test.rb +0 -305
  117. data/test/cases/autosave_association_test.rb +0 -1218
  118. data/test/cases/base_test.rb +0 -2166
  119. data/test/cases/batches_test.rb +0 -81
  120. data/test/cases/binary_test.rb +0 -30
  121. data/test/cases/calculations_test.rb +0 -360
  122. data/test/cases/callbacks_observers_test.rb +0 -38
  123. data/test/cases/callbacks_test.rb +0 -438
  124. data/test/cases/class_inheritable_attributes_test.rb +0 -32
  125. data/test/cases/column_alias_test.rb +0 -17
  126. data/test/cases/column_definition_test.rb +0 -70
  127. data/test/cases/connection_pool_test.rb +0 -25
  128. data/test/cases/connection_test_firebird.rb +0 -8
  129. data/test/cases/connection_test_mysql.rb +0 -65
  130. data/test/cases/copy_table_test_sqlite.rb +0 -80
  131. data/test/cases/counter_cache_test.rb +0 -84
  132. data/test/cases/database_statements_test.rb +0 -12
  133. data/test/cases/datatype_test_postgresql.rb +0 -204
  134. data/test/cases/date_time_test.rb +0 -37
  135. data/test/cases/default_test_firebird.rb +0 -16
  136. data/test/cases/defaults_test.rb +0 -111
  137. data/test/cases/deprecated_finder_test.rb +0 -30
  138. data/test/cases/dirty_test.rb +0 -316
  139. data/test/cases/finder_respond_to_test.rb +0 -76
  140. data/test/cases/finder_test.rb +0 -1098
  141. data/test/cases/fixtures_test.rb +0 -661
  142. data/test/cases/helper.rb +0 -68
  143. data/test/cases/i18n_test.rb +0 -46
  144. data/test/cases/inheritance_test.rb +0 -262
  145. data/test/cases/invalid_date_test.rb +0 -24
  146. data/test/cases/json_serialization_test.rb +0 -219
  147. data/test/cases/lifecycle_test.rb +0 -193
  148. data/test/cases/locking_test.rb +0 -350
  149. data/test/cases/method_scoping_test.rb +0 -704
  150. data/test/cases/migration_test.rb +0 -1649
  151. data/test/cases/migration_test_firebird.rb +0 -124
  152. data/test/cases/mixin_test.rb +0 -96
  153. data/test/cases/modules_test.rb +0 -109
  154. data/test/cases/multiple_db_test.rb +0 -85
  155. data/test/cases/named_scope_test.rb +0 -372
  156. data/test/cases/nested_attributes_test.rb +0 -840
  157. data/test/cases/pk_test.rb +0 -119
  158. data/test/cases/pooled_connections_test.rb +0 -103
  159. data/test/cases/query_cache_test.rb +0 -129
  160. data/test/cases/readonly_test.rb +0 -107
  161. data/test/cases/reflection_test.rb +0 -234
  162. data/test/cases/reload_models_test.rb +0 -22
  163. data/test/cases/repair_helper.rb +0 -50
  164. data/test/cases/reserved_word_test_mysql.rb +0 -176
  165. data/test/cases/sanitize_test.rb +0 -25
  166. data/test/cases/schema_authorization_test_postgresql.rb +0 -75
  167. data/test/cases/schema_dumper_test.rb +0 -211
  168. data/test/cases/schema_test_postgresql.rb +0 -178
  169. data/test/cases/serialization_test.rb +0 -47
  170. data/test/cases/sp_test_mysql.rb +0 -16
  171. data/test/cases/synonym_test_oracle.rb +0 -17
  172. data/test/cases/timestamp_test.rb +0 -75
  173. data/test/cases/transactions_test.rb +0 -543
  174. data/test/cases/unconnected_test.rb +0 -32
  175. data/test/cases/validations_i18n_test.rb +0 -925
  176. data/test/cases/validations_test.rb +0 -1684
  177. data/test/cases/xml_serialization_test.rb +0 -240
  178. data/test/cases/yaml_serialization_test.rb +0 -11
  179. data/test/config.rb +0 -5
  180. data/test/connections/jdbc_jdbcderby/connection.rb +0 -18
  181. data/test/connections/jdbc_jdbch2/connection.rb +0 -18
  182. data/test/connections/jdbc_jdbchsqldb/connection.rb +0 -18
  183. data/test/connections/jdbc_jdbcmysql/connection.rb +0 -26
  184. data/test/connections/jdbc_jdbcpostgresql/connection.rb +0 -26
  185. data/test/connections/jdbc_jdbcsqlite3/connection.rb +0 -25
  186. data/test/connections/native_db2/connection.rb +0 -25
  187. data/test/connections/native_firebird/connection.rb +0 -26
  188. data/test/connections/native_frontbase/connection.rb +0 -27
  189. data/test/connections/native_mysql/connection.rb +0 -25
  190. data/test/connections/native_openbase/connection.rb +0 -21
  191. data/test/connections/native_oracle/connection.rb +0 -27
  192. data/test/connections/native_postgresql/connection.rb +0 -21
  193. data/test/connections/native_sqlite/connection.rb +0 -25
  194. data/test/connections/native_sqlite3/connection.rb +0 -25
  195. data/test/connections/native_sqlite3/in_memory_connection.rb +0 -18
  196. data/test/connections/native_sybase/connection.rb +0 -23
  197. data/test/fixtures/accounts.yml +0 -29
  198. data/test/fixtures/all/developers.yml +0 -0
  199. data/test/fixtures/all/people.csv +0 -0
  200. data/test/fixtures/all/tasks.yml +0 -0
  201. data/test/fixtures/author_addresses.yml +0 -5
  202. data/test/fixtures/author_favorites.yml +0 -4
  203. data/test/fixtures/authors.yml +0 -9
  204. data/test/fixtures/binaries.yml +0 -132
  205. data/test/fixtures/books.yml +0 -7
  206. data/test/fixtures/categories.yml +0 -14
  207. data/test/fixtures/categories/special_categories.yml +0 -9
  208. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +0 -4
  209. data/test/fixtures/categories_ordered.yml +0 -7
  210. data/test/fixtures/categories_posts.yml +0 -23
  211. data/test/fixtures/categorizations.yml +0 -17
  212. data/test/fixtures/clubs.yml +0 -6
  213. data/test/fixtures/comments.yml +0 -59
  214. data/test/fixtures/companies.yml +0 -56
  215. data/test/fixtures/computers.yml +0 -4
  216. data/test/fixtures/courses.yml +0 -7
  217. data/test/fixtures/customers.yml +0 -26
  218. data/test/fixtures/developers.yml +0 -21
  219. data/test/fixtures/developers_projects.yml +0 -17
  220. data/test/fixtures/edges.yml +0 -6
  221. data/test/fixtures/entrants.yml +0 -14
  222. data/test/fixtures/faces.yml +0 -11
  223. data/test/fixtures/fk_test_has_fk.yml +0 -3
  224. data/test/fixtures/fk_test_has_pk.yml +0 -2
  225. data/test/fixtures/funny_jokes.yml +0 -10
  226. data/test/fixtures/interests.yml +0 -33
  227. data/test/fixtures/items.yml +0 -4
  228. data/test/fixtures/jobs.yml +0 -7
  229. data/test/fixtures/legacy_things.yml +0 -3
  230. data/test/fixtures/mateys.yml +0 -4
  231. data/test/fixtures/member_types.yml +0 -6
  232. data/test/fixtures/members.yml +0 -6
  233. data/test/fixtures/memberships.yml +0 -20
  234. data/test/fixtures/men.yml +0 -5
  235. data/test/fixtures/minimalistics.yml +0 -2
  236. data/test/fixtures/mixed_case_monkeys.yml +0 -6
  237. data/test/fixtures/mixins.yml +0 -29
  238. data/test/fixtures/movies.yml +0 -7
  239. data/test/fixtures/naked/csv/accounts.csv +0 -1
  240. data/test/fixtures/naked/yml/accounts.yml +0 -1
  241. data/test/fixtures/naked/yml/companies.yml +0 -1
  242. data/test/fixtures/naked/yml/courses.yml +0 -1
  243. data/test/fixtures/organizations.yml +0 -5
  244. data/test/fixtures/owners.yml +0 -7
  245. data/test/fixtures/parrots.yml +0 -27
  246. data/test/fixtures/parrots_pirates.yml +0 -7
  247. data/test/fixtures/people.yml +0 -15
  248. data/test/fixtures/pets.yml +0 -14
  249. data/test/fixtures/pirates.yml +0 -9
  250. data/test/fixtures/polymorphic_designs.yml +0 -19
  251. data/test/fixtures/polymorphic_prices.yml +0 -19
  252. data/test/fixtures/posts.yml +0 -52
  253. data/test/fixtures/price_estimates.yml +0 -7
  254. data/test/fixtures/projects.yml +0 -7
  255. data/test/fixtures/readers.yml +0 -9
  256. data/test/fixtures/references.yml +0 -17
  257. data/test/fixtures/reserved_words/distinct.yml +0 -5
  258. data/test/fixtures/reserved_words/distincts_selects.yml +0 -11
  259. data/test/fixtures/reserved_words/group.yml +0 -14
  260. data/test/fixtures/reserved_words/select.yml +0 -8
  261. data/test/fixtures/reserved_words/values.yml +0 -7
  262. data/test/fixtures/ships.yml +0 -5
  263. data/test/fixtures/sponsors.yml +0 -9
  264. data/test/fixtures/subscribers.yml +0 -7
  265. data/test/fixtures/subscriptions.yml +0 -12
  266. data/test/fixtures/taggings.yml +0 -28
  267. data/test/fixtures/tags.yml +0 -7
  268. data/test/fixtures/tasks.yml +0 -7
  269. data/test/fixtures/tees.yml +0 -4
  270. data/test/fixtures/ties.yml +0 -4
  271. data/test/fixtures/topics.yml +0 -42
  272. data/test/fixtures/toys.yml +0 -4
  273. data/test/fixtures/treasures.yml +0 -10
  274. data/test/fixtures/vertices.yml +0 -4
  275. data/test/fixtures/warehouse-things.yml +0 -3
  276. data/test/fixtures/zines.yml +0 -5
  277. data/test/migrations/broken/100_migration_that_raises_exception.rb +0 -10
  278. data/test/migrations/decimal/1_give_me_big_numbers.rb +0 -15
  279. data/test/migrations/duplicate/1_people_have_last_names.rb +0 -9
  280. data/test/migrations/duplicate/2_we_need_reminders.rb +0 -12
  281. data/test/migrations/duplicate/3_foo.rb +0 -7
  282. data/test/migrations/duplicate/3_innocent_jointable.rb +0 -12
  283. data/test/migrations/duplicate_names/20080507052938_chunky.rb +0 -7
  284. data/test/migrations/duplicate_names/20080507053028_chunky.rb +0 -7
  285. data/test/migrations/interleaved/pass_1/3_innocent_jointable.rb +0 -12
  286. data/test/migrations/interleaved/pass_2/1_people_have_last_names.rb +0 -9
  287. data/test/migrations/interleaved/pass_2/3_innocent_jointable.rb +0 -12
  288. data/test/migrations/interleaved/pass_3/1_people_have_last_names.rb +0 -9
  289. data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +0 -8
  290. data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +0 -12
  291. data/test/migrations/missing/1000_people_have_middle_names.rb +0 -9
  292. data/test/migrations/missing/1_people_have_last_names.rb +0 -9
  293. data/test/migrations/missing/3_we_need_reminders.rb +0 -12
  294. data/test/migrations/missing/4_innocent_jointable.rb +0 -12
  295. data/test/migrations/valid/1_people_have_last_names.rb +0 -9
  296. data/test/migrations/valid/2_we_need_reminders.rb +0 -12
  297. data/test/migrations/valid/3_innocent_jointable.rb +0 -12
  298. data/test/models/author.rb +0 -151
  299. data/test/models/auto_id.rb +0 -4
  300. data/test/models/binary.rb +0 -2
  301. data/test/models/bird.rb +0 -9
  302. data/test/models/book.rb +0 -4
  303. data/test/models/categorization.rb +0 -5
  304. data/test/models/category.rb +0 -34
  305. data/test/models/citation.rb +0 -6
  306. data/test/models/club.rb +0 -13
  307. data/test/models/column_name.rb +0 -3
  308. data/test/models/comment.rb +0 -29
  309. data/test/models/company.rb +0 -173
  310. data/test/models/company_in_module.rb +0 -78
  311. data/test/models/computer.rb +0 -3
  312. data/test/models/contact.rb +0 -16
  313. data/test/models/contract.rb +0 -5
  314. data/test/models/course.rb +0 -3
  315. data/test/models/customer.rb +0 -73
  316. data/test/models/default.rb +0 -2
  317. data/test/models/developer.rb +0 -101
  318. data/test/models/edge.rb +0 -5
  319. data/test/models/entrant.rb +0 -3
  320. data/test/models/essay.rb +0 -3
  321. data/test/models/event.rb +0 -3
  322. data/test/models/event_author.rb +0 -8
  323. data/test/models/face.rb +0 -7
  324. data/test/models/guid.rb +0 -2
  325. data/test/models/interest.rb +0 -5
  326. data/test/models/invoice.rb +0 -4
  327. data/test/models/item.rb +0 -7
  328. data/test/models/job.rb +0 -5
  329. data/test/models/joke.rb +0 -3
  330. data/test/models/keyboard.rb +0 -3
  331. data/test/models/legacy_thing.rb +0 -3
  332. data/test/models/line_item.rb +0 -3
  333. data/test/models/man.rb +0 -9
  334. data/test/models/matey.rb +0 -4
  335. data/test/models/member.rb +0 -12
  336. data/test/models/member_detail.rb +0 -5
  337. data/test/models/member_type.rb +0 -3
  338. data/test/models/membership.rb +0 -9
  339. data/test/models/minimalistic.rb +0 -2
  340. data/test/models/mixed_case_monkey.rb +0 -3
  341. data/test/models/movie.rb +0 -5
  342. data/test/models/order.rb +0 -4
  343. data/test/models/organization.rb +0 -6
  344. data/test/models/owner.rb +0 -5
  345. data/test/models/parrot.rb +0 -22
  346. data/test/models/person.rb +0 -16
  347. data/test/models/pet.rb +0 -5
  348. data/test/models/pirate.rb +0 -80
  349. data/test/models/polymorphic_design.rb +0 -3
  350. data/test/models/polymorphic_price.rb +0 -3
  351. data/test/models/post.rb +0 -102
  352. data/test/models/price_estimate.rb +0 -3
  353. data/test/models/project.rb +0 -30
  354. data/test/models/reader.rb +0 -4
  355. data/test/models/reference.rb +0 -4
  356. data/test/models/reply.rb +0 -46
  357. data/test/models/ship.rb +0 -19
  358. data/test/models/ship_part.rb +0 -7
  359. data/test/models/sponsor.rb +0 -4
  360. data/test/models/subject.rb +0 -4
  361. data/test/models/subscriber.rb +0 -8
  362. data/test/models/subscription.rb +0 -4
  363. data/test/models/tag.rb +0 -7
  364. data/test/models/tagging.rb +0 -10
  365. data/test/models/task.rb +0 -3
  366. data/test/models/tee.rb +0 -4
  367. data/test/models/tie.rb +0 -4
  368. data/test/models/topic.rb +0 -80
  369. data/test/models/toy.rb +0 -6
  370. data/test/models/treasure.rb +0 -8
  371. data/test/models/vertex.rb +0 -9
  372. data/test/models/warehouse_thing.rb +0 -5
  373. data/test/models/zine.rb +0 -3
  374. data/test/schema/mysql_specific_schema.rb +0 -31
  375. data/test/schema/postgresql_specific_schema.rb +0 -114
  376. data/test/schema/schema.rb +0 -550
  377. data/test/schema/schema2.rb +0 -6
  378. data/test/schema/sqlite_specific_schema.rb +0 -25
@@ -13,7 +13,7 @@ module ActiveRecord
13
13
 
14
14
  def dirties_query_cache(base, *method_names)
15
15
  method_names.each do |method_name|
16
- base.class_eval <<-end_code, __FILE__, __LINE__ + 1
16
+ base.class_eval <<-end_code, __FILE__, __LINE__
17
17
  def #{method_name}_with_query_dirty(*args) # def update_with_query_dirty(*args)
18
18
  clear_query_cache if @query_cache_enabled # clear_query_cache if @query_cache_enabled
19
19
  #{method_name}_without_query_dirty(*args) # update_without_query_dirty(*args)
@@ -75,7 +75,8 @@ module ActiveRecord
75
75
  def cache_sql(sql)
76
76
  result =
77
77
  if @query_cache.has_key?(sql)
78
- log_info(sql, "CACHE", 0.0)
78
+ ActiveSupport::Notifications.instrument("active_record.sql",
79
+ :sql => sql, :name => "CACHE", :connection_id => self.object_id)
79
80
  @query_cache[sql]
80
81
  else
81
82
  @query_cache[sql] = yield
@@ -1,3 +1,5 @@
1
+ require 'active_support/core_ext/big_decimal/conversions'
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters # :nodoc:
3
5
  module Quoting
@@ -11,12 +13,12 @@ module ActiveRecord
11
13
  when String, ActiveSupport::Multibyte::Chars
12
14
  value = value.to_s
13
15
  if column && column.type == :binary && column.class.respond_to?(:string_to_binary)
14
- "'#{quote_string(column.class.string_to_binary(value))}'" # ' (for ruby-mode)
16
+ "#{quoted_string_prefix}'#{quote_string(column.class.string_to_binary(value))}'" # ' (for ruby-mode)
15
17
  elsif column && [:integer, :float].include?(column.type)
16
18
  value = column.type == :integer ? value.to_i : value.to_f
17
19
  value.to_s
18
20
  else
19
- "'#{quote_string(value)}'" # ' (for ruby-mode)
21
+ "#{quoted_string_prefix}'#{quote_string(value)}'" # ' (for ruby-mode)
20
22
  end
21
23
  when NilClass then "NULL"
22
24
  when TrueClass then (column && column.type == :integer ? '1' : quoted_true)
@@ -28,7 +30,7 @@ module ActiveRecord
28
30
  if value.acts_like?(:date) || value.acts_like?(:time)
29
31
  "'#{quoted_date(value)}'"
30
32
  else
31
- "'#{quote_string(value.to_yaml)}'"
33
+ "#{quoted_string_prefix}'#{quote_string(value.to_yaml)}'"
32
34
  end
33
35
  end
34
36
  end
@@ -58,7 +60,16 @@ module ActiveRecord
58
60
  end
59
61
 
60
62
  def quoted_date(value)
61
- value.to_s(:db)
63
+ if value.acts_like?(:time)
64
+ zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
65
+ value.respond_to?(zone_conversion_method) ? value.send(zone_conversion_method) : value
66
+ else
67
+ value
68
+ end.to_s(:db)
69
+ end
70
+
71
+ def quoted_string_prefix
72
+ ''
62
73
  end
63
74
  end
64
75
  end
@@ -256,7 +256,7 @@ module ActiveRecord
256
256
  end
257
257
  end
258
258
 
259
- class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths) #:nodoc:
259
+ class IndexDefinition < Struct.new(:table, :name, :unique, :columns) #:nodoc:
260
260
  end
261
261
 
262
262
  # Abstract representation of a column definition. Instances of this type
@@ -8,6 +8,11 @@ module ActiveRecord
8
8
  {}
9
9
  end
10
10
 
11
+ # This is the maximum length a table alias can be
12
+ def table_alias_length
13
+ 255
14
+ end
15
+
11
16
  # Truncates a table alias according to the limits of the current adapter.
12
17
  def table_alias_for(table_name)
13
18
  table_name[0..table_alias_length-1].gsub(/\./, '_')
@@ -36,11 +41,19 @@ module ActiveRecord
36
41
  # # create_table() passes a TableDefinition object to the block.
37
42
  # # This form will not only create the table, but also columns for the
38
43
  # # table.
44
+ #
39
45
  # create_table(:suppliers) do |t|
40
46
  # t.column :name, :string, :limit => 60
41
47
  # # Other fields here
42
48
  # end
43
49
  #
50
+ # === Block form, with shorthand
51
+ # # You can also use the column types as method calls, rather than calling the column method.
52
+ # create_table(:suppliers) do |t|
53
+ # t.string :name, :limit => 60
54
+ # # Other fields here
55
+ # end
56
+ #
44
57
  # === Regular form
45
58
  # # Creates a table called 'suppliers' with no columns.
46
59
  # create_table(:suppliers)
@@ -195,7 +208,6 @@ module ActiveRecord
195
208
  # remove_column(:suppliers, :qualification)
196
209
  # remove_columns(:suppliers, :qualification, :experience)
197
210
  def remove_column(table_name, *column_names)
198
- raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_names.empty?
199
211
  column_names.flatten.each do |column_name|
200
212
  execute "ALTER TABLE #{quote_table_name(table_name)} DROP #{quote_column_name(column_name)}"
201
213
  end
@@ -242,53 +254,29 @@ module ActiveRecord
242
254
  # name.
243
255
  #
244
256
  # ===== Examples
245
- #
246
257
  # ====== Creating a simple index
247
258
  # add_index(:suppliers, :name)
248
259
  # generates
249
260
  # CREATE INDEX suppliers_name_index ON suppliers(name)
250
- #
251
261
  # ====== Creating a unique index
252
262
  # add_index(:accounts, [:branch_id, :party_id], :unique => true)
253
263
  # generates
254
264
  # CREATE UNIQUE INDEX accounts_branch_id_party_id_index ON accounts(branch_id, party_id)
255
- #
256
265
  # ====== Creating a named index
257
266
  # add_index(:accounts, [:branch_id, :party_id], :unique => true, :name => 'by_branch_party')
258
267
  # generates
259
268
  # CREATE UNIQUE INDEX by_branch_party ON accounts(branch_id, party_id)
260
- #
261
- # ====== Creating an index with specific key length
262
- # add_index(:accounts, :name, :name => 'by_name', :length => 10)
263
- # generates
264
- # CREATE INDEX by_name ON accounts(name(10))
265
- #
266
- # add_index(:accounts, [:name, :surname], :name => 'by_name_surname', :length => {:name => 10, :surname => 15})
267
- # generates
268
- # CREATE INDEX by_name_surname ON accounts(name(10), surname(15))
269
- #
270
- # Note: SQLite doesn't support index length
271
269
  def add_index(table_name, column_name, options = {})
272
270
  column_names = Array(column_name)
273
271
  index_name = index_name(table_name, :column => column_names)
274
272
 
275
273
  if Hash === options # legacy support, since this param was a string
276
274
  index_type = options[:unique] ? "UNIQUE" : ""
277
- index_name = options[:name].to_s if options[:name]
275
+ index_name = options[:name] || index_name
278
276
  else
279
277
  index_type = options
280
278
  end
281
-
282
- if index_name.length > index_name_length
283
- @logger.warn("Index name '#{index_name}' on table '#{table_name}' is too long; the limit is #{index_name_length} characters. Skipping.")
284
- return
285
- end
286
- if index_exists?(table_name, index_name, false)
287
- @logger.warn("Index name '#{index_name}' on table '#{table_name}' already exists. Skipping.")
288
- return
289
- end
290
- quoted_column_names = quoted_columns_for_index(column_names, options).join(", ")
291
-
279
+ quoted_column_names = column_names.map { |e| quote_column_name(e) }.join(", ")
292
280
  execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})"
293
281
  end
294
282
 
@@ -303,28 +291,7 @@ module ActiveRecord
303
291
  # Remove the index named by_branch_party in the accounts table.
304
292
  # remove_index :accounts, :name => :by_branch_party
305
293
  def remove_index(table_name, options = {})
306
- index_name = index_name(table_name, options)
307
- unless index_exists?(table_name, index_name, true)
308
- @logger.warn("Index name '#{index_name}' on table '#{table_name}' does not exist. Skipping.")
309
- return
310
- end
311
- remove_index!(table_name, index_name)
312
- end
313
-
314
- def remove_index!(table_name, index_name) #:nodoc:
315
- execute "DROP INDEX #{quote_column_name(index_name)} ON #{table_name}"
316
- end
317
-
318
- # Rename an index.
319
- #
320
- # Rename the index_people_on_last_name index to index_users_on_last_name
321
- # rename_index :people, 'index_people_on_last_name', 'index_users_on_last_name'
322
- def rename_index(table_name, old_name, new_name)
323
- # this is a naive implementation; some DBs may support this more efficiently (Postgres, for instance)
324
- old_index_def = indexes(table_name).detect { |i| i.name == old_name }
325
- return unless old_index_def
326
- remove_index(table_name, :name => old_name)
327
- add_index(table_name, old_index_def.columns, :name => new_name, :unique => old_index_def.unique)
294
+ execute "DROP INDEX #{quote_column_name(index_name(table_name, options))} ON #{table_name}"
328
295
  end
329
296
 
330
297
  def index_name(table_name, options) #:nodoc:
@@ -341,16 +308,6 @@ module ActiveRecord
341
308
  end
342
309
  end
343
310
 
344
- # Verify the existence of an index.
345
- #
346
- # The default argument is returned if the underlying implementation does not define the indexes method,
347
- # as there's no way to determine the correct answer in that case.
348
- def index_exists?(table_name, index_name, default)
349
- return default unless respond_to?(:indexes)
350
- index_name = index_name.to_s
351
- indexes(table_name).detect { |i| i.name == index_name }
352
- end
353
-
354
311
  # Returns a string of <tt>CREATE TABLE</tt> SQL statement(s) for recreating the
355
312
  # entire structure of the database.
356
313
  def structure_dump
@@ -367,7 +324,7 @@ module ActiveRecord
367
324
  def initialize_schema_migrations_table
368
325
  sm_table = ActiveRecord::Migrator.schema_migrations_table_name
369
326
 
370
- unless tables.detect { |t| t == sm_table }
327
+ unless table_exists?(sm_table)
371
328
  create_table(sm_table, :id => false) do |schema_migrations_table|
372
329
  schema_migrations_table.column :version, :string, :null => false
373
330
  end
@@ -378,7 +335,7 @@ module ActiveRecord
378
335
  # migrated up to that point:
379
336
  si_table = Base.table_name_prefix + 'schema_info' + Base.table_name_suffix
380
337
 
381
- if tables.detect { |t| t == si_table }
338
+ if table_exists?(si_table)
382
339
 
383
340
  old_version = select_value("SELECT version FROM #{quote_table_name(si_table)}").to_i
384
341
  assume_migrated_upto_version(old_version)
@@ -454,12 +411,6 @@ module ActiveRecord
454
411
  "DISTINCT #{columns}"
455
412
  end
456
413
 
457
- # ORDER BY clause for the passed order option.
458
- # PostgreSQL overrides this due to its stricter standards compliance.
459
- def add_order_by_for_association_limiting!(sql, options)
460
- sql << " ORDER BY #{options[:order]}"
461
- end
462
-
463
414
  # Adds timestamps (created_at and updated_at) columns to the named table.
464
415
  # ===== Examples
465
416
  # add_timestamps(:suppliers)
@@ -477,11 +428,6 @@ module ActiveRecord
477
428
  end
478
429
 
479
430
  protected
480
- # Overridden by the mysql adapter for supporting index lengths
481
- def quoted_columns_for_index(column_names, options = {})
482
- column_names.map {|name| quote_column_name(name) }
483
- end
484
-
485
431
  def options_include_default?(options)
486
432
  options.include?(:default) && !(options[:null] == false && options[:default].nil?)
487
433
  end
@@ -1,7 +1,7 @@
1
- require 'benchmark'
2
1
  require 'date'
3
2
  require 'bigdecimal'
4
3
  require 'bigdecimal/util'
4
+ require 'active_support/core_ext/benchmark'
5
5
 
6
6
  # TODO: Autoload these files
7
7
  require 'active_record/connection_adapters/abstract/schema_definitions'
@@ -11,7 +11,6 @@ require 'active_record/connection_adapters/abstract/quoting'
11
11
  require 'active_record/connection_adapters/abstract/connection_pool'
12
12
  require 'active_record/connection_adapters/abstract/connection_specification'
13
13
  require 'active_record/connection_adapters/abstract/query_cache'
14
- require 'active_record/connection_adapters/abstract/database_limits'
15
14
 
16
15
  module ActiveRecord
17
16
  module ConnectionAdapters # :nodoc:
@@ -30,9 +29,9 @@ module ActiveRecord
30
29
  # notably, the instance methods provided by SchemaStatement are very useful.
31
30
  class AbstractAdapter
32
31
  include Quoting, DatabaseStatements, SchemaStatements
33
- include DatabaseLimits
34
32
  include QueryCache
35
33
  include ActiveSupport::Callbacks
34
+
36
35
  define_callbacks :checkout, :checkin
37
36
 
38
37
  @@row_even = true
@@ -40,7 +39,6 @@ module ActiveRecord
40
39
  def initialize(connection, logger = nil) #:nodoc:
41
40
  @connection, @logger = connection, logger
42
41
  @runtime = 0
43
- @last_verification = 0
44
42
  @query_cache_enabled = false
45
43
  end
46
44
 
@@ -75,7 +73,7 @@ module ActiveRecord
75
73
  def supports_ddl_transactions?
76
74
  false
77
75
  end
78
-
76
+
79
77
  # Does this adapter support savepoints? PostgreSQL and MySQL do, SQLite
80
78
  # does not.
81
79
  def supports_savepoints?
@@ -192,58 +190,27 @@ module ActiveRecord
192
190
  "active_record_#{open_transactions}"
193
191
  end
194
192
 
195
- def log_info(sql, name, ms)
196
- if @logger && @logger.debug?
197
- name = '%s (%.1fms)' % [name || 'SQL', ms]
198
- @logger.debug(format_log_entry(name, sql.squeeze(' ')))
199
- end
200
- end
201
-
202
193
  protected
194
+
203
195
  def log(sql, name)
204
- if block_given?
205
- result = nil
206
- ms = Benchmark.ms { result = yield }
207
- @runtime += ms
208
- log_info(sql, name, ms)
209
- result
210
- else
211
- log_info(sql, name, 0)
212
- nil
196
+ name ||= "SQL"
197
+ result = nil
198
+ ActiveSupport::Notifications.instrument("active_record.sql",
199
+ :sql => sql, :name => name, :connection_id => self.object_id) do
200
+ @runtime += Benchmark.ms { result = yield }
213
201
  end
214
- rescue SystemExit, SignalException, NoMemoryError => e
215
- # Don't re-wrap these exceptions. They are probably not being caused by invalid
216
- # sql, but rather some external stimulus beyond the responsibilty of this code.
217
- # Additionaly, wrapping these exceptions with StatementInvalid would lead to
218
- # meaningful loss of data, such as losing SystemExit#status.
219
- raise e
202
+ result
220
203
  rescue Exception => e
221
- # Log message and raise exception.
222
- # Set last_verification to 0, so that connection gets verified
223
- # upon reentering the request loop
224
- @last_verification = 0
225
204
  message = "#{e.class.name}: #{e.message}: #{sql}"
226
- log_info(message, name, 0)
227
- raise ActiveRecord::StatementInvalid, message
205
+ @logger.debug message if @logger
206
+ raise translate_exception(e, message)
228
207
  end
229
208
 
230
- def format_log_entry(message, dump = nil)
231
- if ActiveRecord::Base.colorize_logging
232
- if @@row_even
233
- @@row_even = false
234
- message_color, dump_color = "4;36;1", "0;1"
235
- else
236
- @@row_even = true
237
- message_color, dump_color = "4;35;1", "0"
238
- end
239
-
240
- log_entry = " \e[#{message_color}m#{message}\e[0m "
241
- log_entry << "\e[#{dump_color}m%#{String === dump ? 's' : 'p'}\e[0m" % dump if dump
242
- log_entry
243
- else
244
- "%s %s" % [message, dump]
245
- end
209
+ def translate_exception(e, message)
210
+ # override in derived class
211
+ ActiveRecord::StatementInvalid.new(message)
246
212
  end
213
+
247
214
  end
248
215
  end
249
216
  end
@@ -1,4 +1,5 @@
1
1
  require 'active_record/connection_adapters/abstract_adapter'
2
+ require 'active_support/core_ext/kernel/requires'
2
3
  require 'set'
3
4
 
4
5
  module MysqlCompat #:nodoc:
@@ -210,7 +211,7 @@ module ActiveRecord
210
211
  def supports_migrations? #:nodoc:
211
212
  true
212
213
  end
213
-
214
+
214
215
  def supports_primary_key? #:nodoc:
215
216
  true
216
217
  end
@@ -238,7 +239,7 @@ module ActiveRecord
238
239
  end
239
240
 
240
241
  def quote_column_name(name) #:nodoc:
241
- @quoted_column_names[name] ||= "`#{name.to_s.gsub('`', '``')}`"
242
+ @quoted_column_names[name] ||= "`#{name}`"
242
243
  end
243
244
 
244
245
  def quote_table_name(name) #:nodoc:
@@ -315,7 +316,6 @@ module ActiveRecord
315
316
  rows = []
316
317
  result.each { |row| rows << row }
317
318
  result.free
318
- @connection.more_results && @connection.next_result # invoking stored procedures with CLIENT_MULTI_RESULTS requires this to tidy up else connection will be dropped
319
319
  rows
320
320
  end
321
321
 
@@ -334,6 +334,7 @@ module ActiveRecord
334
334
  super sql, name
335
335
  id_value || @connection.insert_id
336
336
  end
337
+ alias :create :insert_sql
337
338
 
338
339
  def update_sql(sql, name = nil) #:nodoc:
339
340
  super
@@ -370,18 +371,6 @@ module ActiveRecord
370
371
  execute("RELEASE SAVEPOINT #{current_savepoint_name}")
371
372
  end
372
373
 
373
- def add_limit_offset!(sql, options) #:nodoc:
374
- if limit = options[:limit]
375
- limit = sanitize_limit(limit)
376
- unless offset = options[:offset]
377
- sql << " LIMIT #{limit}"
378
- else
379
- sql << " LIMIT #{offset.to_i}, #{limit}"
380
- end
381
- end
382
- end
383
-
384
-
385
374
  # SCHEMA STATEMENTS ========================================
386
375
 
387
376
  def structure_dump #:nodoc:
@@ -455,11 +444,10 @@ module ActiveRecord
455
444
  if current_index != row[2]
456
445
  next if row[2] == "PRIMARY" # skip the primary key
457
446
  current_index = row[2]
458
- indexes << IndexDefinition.new(row[0], row[2], row[1] == "0", [], [])
447
+ indexes << IndexDefinition.new(row[0], row[2], row[1] == "0", [])
459
448
  end
460
449
 
461
450
  indexes.last.columns << row[4]
462
- indexes.last.lengths << row[7]
463
451
  end
464
452
  result.free
465
453
  indexes
@@ -589,16 +577,17 @@ module ActiveRecord
589
577
  end
590
578
 
591
579
  protected
592
- def quoted_columns_for_index(column_names, options = {})
593
- length = options[:length] if options.is_a?(Hash)
594
-
595
- quoted_column_names = case length
596
- when Hash
597
- column_names.map {|name| length[name] ? "#{quote_column_name(name)}(#{length[name]})" : quote_column_name(name) }
598
- when Fixnum
599
- column_names.map {|name| "#{quote_column_name(name)}(#{length})"}
580
+
581
+ def translate_exception(exception, message)
582
+ return super unless exception.respond_to?(:errno)
583
+
584
+ case exception.errno
585
+ when 1062
586
+ RecordNotUnique.new(message, exception)
587
+ when 1452
588
+ InvalidForeignKey.new(message, exception)
600
589
  else
601
- column_names.map {|name| quote_column_name(name) }
590
+ super
602
591
  end
603
592
  end
604
593
 
@@ -639,7 +628,6 @@ module ActiveRecord
639
628
  result = execute(sql, name)
640
629
  rows = result.all_hashes
641
630
  result.free
642
- @connection.more_results && @connection.next_result # invoking stored procedures with CLIENT_MULTI_RESULTS requires this to tidy up else connection will be dropped
643
631
  rows
644
632
  end
645
633