activerecord 1.0.0 → 2.0.0

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 (311) hide show
  1. data/CHANGELOG +4928 -3
  2. data/README +45 -46
  3. data/RUNNING_UNIT_TESTS +8 -11
  4. data/Rakefile +247 -0
  5. data/install.rb +8 -38
  6. data/lib/active_record/aggregations.rb +64 -49
  7. data/lib/active_record/associations/association_collection.rb +217 -47
  8. data/lib/active_record/associations/association_proxy.rb +159 -0
  9. data/lib/active_record/associations/belongs_to_association.rb +56 -0
  10. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +50 -0
  11. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +155 -37
  12. data/lib/active_record/associations/has_many_association.rb +145 -75
  13. data/lib/active_record/associations/has_many_through_association.rb +283 -0
  14. data/lib/active_record/associations/has_one_association.rb +96 -0
  15. data/lib/active_record/associations.rb +1537 -304
  16. data/lib/active_record/attribute_methods.rb +328 -0
  17. data/lib/active_record/base.rb +2001 -588
  18. data/lib/active_record/calculations.rb +269 -0
  19. data/lib/active_record/callbacks.rb +169 -165
  20. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +308 -0
  21. data/lib/active_record/connection_adapters/abstract/database_statements.rb +171 -0
  22. data/lib/active_record/connection_adapters/abstract/query_cache.rb +87 -0
  23. data/lib/active_record/connection_adapters/abstract/quoting.rb +69 -0
  24. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +472 -0
  25. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +306 -0
  26. data/lib/active_record/connection_adapters/abstract_adapter.rb +125 -279
  27. data/lib/active_record/connection_adapters/mysql_adapter.rb +442 -77
  28. data/lib/active_record/connection_adapters/postgresql_adapter.rb +805 -135
  29. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +34 -0
  30. data/lib/active_record/connection_adapters/sqlite_adapter.rb +353 -69
  31. data/lib/active_record/fixtures.rb +946 -100
  32. data/lib/active_record/locking/optimistic.rb +144 -0
  33. data/lib/active_record/locking/pessimistic.rb +77 -0
  34. data/lib/active_record/migration.rb +417 -0
  35. data/lib/active_record/observer.rb +142 -32
  36. data/lib/active_record/query_cache.rb +23 -0
  37. data/lib/active_record/reflection.rb +163 -70
  38. data/lib/active_record/schema.rb +58 -0
  39. data/lib/active_record/schema_dumper.rb +171 -0
  40. data/lib/active_record/serialization.rb +98 -0
  41. data/lib/active_record/serializers/json_serializer.rb +71 -0
  42. data/lib/active_record/serializers/xml_serializer.rb +315 -0
  43. data/lib/active_record/timestamp.rb +41 -0
  44. data/lib/active_record/transactions.rb +87 -57
  45. data/lib/active_record/validations.rb +909 -122
  46. data/lib/active_record/vendor/db2.rb +362 -0
  47. data/lib/active_record/vendor/mysql.rb +126 -29
  48. data/lib/active_record/version.rb +9 -0
  49. data/lib/active_record.rb +35 -7
  50. data/lib/activerecord.rb +1 -0
  51. data/test/aaa_create_tables_test.rb +72 -0
  52. data/test/abstract_unit.rb +73 -5
  53. data/test/active_schema_test_mysql.rb +43 -0
  54. data/test/adapter_test.rb +105 -0
  55. data/test/adapter_test_sqlserver.rb +95 -0
  56. data/test/aggregations_test.rb +110 -16
  57. data/test/all.sh +2 -2
  58. data/test/ar_schema_test.rb +33 -0
  59. data/test/association_inheritance_reload.rb +14 -0
  60. data/test/associations/ar_joins_test.rb +0 -0
  61. data/test/associations/callbacks_test.rb +147 -0
  62. data/test/associations/cascaded_eager_loading_test.rb +110 -0
  63. data/test/associations/eager_singularization_test.rb +145 -0
  64. data/test/associations/eager_test.rb +442 -0
  65. data/test/associations/extension_test.rb +47 -0
  66. data/test/associations/inner_join_association_test.rb +88 -0
  67. data/test/associations/join_model_test.rb +553 -0
  68. data/test/associations_test.rb +1930 -267
  69. data/test/attribute_methods_test.rb +146 -0
  70. data/test/base_test.rb +1316 -84
  71. data/test/binary_test.rb +32 -0
  72. data/test/calculations_test.rb +251 -0
  73. data/test/callbacks_test.rb +400 -0
  74. data/test/class_inheritable_attributes_test.rb +3 -4
  75. data/test/column_alias_test.rb +17 -0
  76. data/test/connection_test_firebird.rb +8 -0
  77. data/test/connection_test_mysql.rb +30 -0
  78. data/test/connections/native_db2/connection.rb +25 -0
  79. data/test/connections/native_firebird/connection.rb +26 -0
  80. data/test/connections/native_frontbase/connection.rb +27 -0
  81. data/test/connections/native_mysql/connection.rb +21 -18
  82. data/test/connections/native_openbase/connection.rb +21 -0
  83. data/test/connections/native_oracle/connection.rb +27 -0
  84. data/test/connections/native_postgresql/connection.rb +17 -18
  85. data/test/connections/native_sqlite/connection.rb +17 -16
  86. data/test/connections/native_sqlite3/connection.rb +25 -0
  87. data/test/connections/native_sqlite3/in_memory_connection.rb +18 -0
  88. data/test/connections/native_sybase/connection.rb +23 -0
  89. data/test/copy_table_test_sqlite.rb +69 -0
  90. data/test/datatype_test_postgresql.rb +203 -0
  91. data/test/date_time_test.rb +37 -0
  92. data/test/default_test_firebird.rb +16 -0
  93. data/test/defaults_test.rb +67 -0
  94. data/test/deprecated_finder_test.rb +30 -0
  95. data/test/finder_test.rb +607 -32
  96. data/test/fixtures/accounts.yml +28 -0
  97. data/test/fixtures/all/developers.yml +0 -0
  98. data/test/fixtures/all/people.csv +0 -0
  99. data/test/fixtures/all/tasks.yml +0 -0
  100. data/test/fixtures/author.rb +107 -0
  101. data/test/fixtures/author_favorites.yml +4 -0
  102. data/test/fixtures/authors.yml +7 -0
  103. data/test/fixtures/bad_fixtures/attr_with_numeric_first_char +1 -0
  104. data/test/fixtures/bad_fixtures/attr_with_spaces +1 -0
  105. data/test/fixtures/bad_fixtures/blank_line +3 -0
  106. data/test/fixtures/bad_fixtures/duplicate_attributes +3 -0
  107. data/test/fixtures/bad_fixtures/missing_value +1 -0
  108. data/test/fixtures/binaries.yml +132 -0
  109. data/test/fixtures/binary.rb +2 -0
  110. data/test/fixtures/book.rb +4 -0
  111. data/test/fixtures/books.yml +7 -0
  112. data/test/fixtures/categories/special_categories.yml +9 -0
  113. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
  114. data/test/fixtures/categories.yml +14 -0
  115. data/test/fixtures/categories_ordered.yml +7 -0
  116. data/test/fixtures/categories_posts.yml +23 -0
  117. data/test/fixtures/categorization.rb +5 -0
  118. data/test/fixtures/categorizations.yml +17 -0
  119. data/test/fixtures/category.rb +26 -0
  120. data/test/fixtures/citation.rb +6 -0
  121. data/test/fixtures/comment.rb +23 -0
  122. data/test/fixtures/comments.yml +59 -0
  123. data/test/fixtures/companies.yml +55 -0
  124. data/test/fixtures/company.rb +81 -4
  125. data/test/fixtures/company_in_module.rb +32 -6
  126. data/test/fixtures/computer.rb +4 -0
  127. data/test/fixtures/computers.yml +4 -0
  128. data/test/fixtures/contact.rb +16 -0
  129. data/test/fixtures/courses.yml +7 -0
  130. data/test/fixtures/customer.rb +28 -3
  131. data/test/fixtures/customers.yml +17 -0
  132. data/test/fixtures/db_definitions/db2.drop.sql +33 -0
  133. data/test/fixtures/db_definitions/db2.sql +235 -0
  134. data/test/fixtures/db_definitions/db22.drop.sql +2 -0
  135. data/test/fixtures/db_definitions/db22.sql +5 -0
  136. data/test/fixtures/db_definitions/firebird.drop.sql +65 -0
  137. data/test/fixtures/db_definitions/firebird.sql +310 -0
  138. data/test/fixtures/db_definitions/firebird2.drop.sql +2 -0
  139. data/test/fixtures/db_definitions/firebird2.sql +6 -0
  140. data/test/fixtures/db_definitions/frontbase.drop.sql +33 -0
  141. data/test/fixtures/db_definitions/frontbase.sql +273 -0
  142. data/test/fixtures/db_definitions/frontbase2.drop.sql +1 -0
  143. data/test/fixtures/db_definitions/frontbase2.sql +4 -0
  144. data/test/fixtures/db_definitions/openbase.drop.sql +2 -0
  145. data/test/fixtures/db_definitions/openbase.sql +318 -0
  146. data/test/fixtures/db_definitions/openbase2.drop.sql +2 -0
  147. data/test/fixtures/db_definitions/openbase2.sql +7 -0
  148. data/test/fixtures/db_definitions/oracle.drop.sql +67 -0
  149. data/test/fixtures/db_definitions/oracle.sql +330 -0
  150. data/test/fixtures/db_definitions/oracle2.drop.sql +2 -0
  151. data/test/fixtures/db_definitions/oracle2.sql +6 -0
  152. data/test/fixtures/db_definitions/postgresql.drop.sql +44 -0
  153. data/test/fixtures/db_definitions/postgresql.sql +217 -38
  154. data/test/fixtures/db_definitions/postgresql2.drop.sql +2 -0
  155. data/test/fixtures/db_definitions/postgresql2.sql +2 -2
  156. data/test/fixtures/db_definitions/schema.rb +354 -0
  157. data/test/fixtures/db_definitions/schema2.rb +11 -0
  158. data/test/fixtures/db_definitions/sqlite.drop.sql +33 -0
  159. data/test/fixtures/db_definitions/sqlite.sql +139 -5
  160. data/test/fixtures/db_definitions/sqlite2.drop.sql +2 -0
  161. data/test/fixtures/db_definitions/sqlite2.sql +1 -0
  162. data/test/fixtures/db_definitions/sybase.drop.sql +35 -0
  163. data/test/fixtures/db_definitions/sybase.sql +222 -0
  164. data/test/fixtures/db_definitions/sybase2.drop.sql +4 -0
  165. data/test/fixtures/db_definitions/sybase2.sql +5 -0
  166. data/test/fixtures/developer.rb +70 -6
  167. data/test/fixtures/developers.yml +21 -0
  168. data/test/fixtures/developers_projects/david_action_controller +2 -1
  169. data/test/fixtures/developers_projects/david_active_record +2 -1
  170. data/test/fixtures/developers_projects.yml +17 -0
  171. data/test/fixtures/edge.rb +5 -0
  172. data/test/fixtures/edges.yml +6 -0
  173. data/test/fixtures/entrants.yml +14 -0
  174. data/test/fixtures/example.log +1 -0
  175. data/test/fixtures/fk_test_has_fk.yml +3 -0
  176. data/test/fixtures/fk_test_has_pk.yml +2 -0
  177. data/test/fixtures/flowers.jpg +0 -0
  178. data/test/fixtures/funny_jokes.yml +10 -0
  179. data/test/fixtures/item.rb +7 -0
  180. data/test/fixtures/items.yml +4 -0
  181. data/test/fixtures/joke.rb +3 -0
  182. data/test/fixtures/keyboard.rb +3 -0
  183. data/test/fixtures/legacy_thing.rb +3 -0
  184. data/test/fixtures/legacy_things.yml +3 -0
  185. data/test/fixtures/matey.rb +4 -0
  186. data/test/fixtures/mateys.yml +4 -0
  187. data/test/fixtures/migrations/1_people_have_last_names.rb +9 -0
  188. data/test/fixtures/migrations/2_we_need_reminders.rb +12 -0
  189. data/test/fixtures/migrations/3_innocent_jointable.rb +12 -0
  190. data/test/fixtures/migrations_with_decimal/1_give_me_big_numbers.rb +15 -0
  191. data/test/fixtures/migrations_with_duplicate/1_people_have_last_names.rb +9 -0
  192. data/test/fixtures/migrations_with_duplicate/2_we_need_reminders.rb +12 -0
  193. data/test/fixtures/migrations_with_duplicate/3_foo.rb +7 -0
  194. data/test/fixtures/migrations_with_duplicate/3_innocent_jointable.rb +12 -0
  195. data/test/fixtures/migrations_with_missing_versions/1000_people_have_middle_names.rb +9 -0
  196. data/test/fixtures/migrations_with_missing_versions/1_people_have_last_names.rb +9 -0
  197. data/test/fixtures/migrations_with_missing_versions/3_we_need_reminders.rb +12 -0
  198. data/test/fixtures/migrations_with_missing_versions/4_innocent_jointable.rb +12 -0
  199. data/test/fixtures/minimalistic.rb +2 -0
  200. data/test/fixtures/minimalistics.yml +2 -0
  201. data/test/fixtures/mixed_case_monkey.rb +3 -0
  202. data/test/fixtures/mixed_case_monkeys.yml +6 -0
  203. data/test/fixtures/mixins.yml +29 -0
  204. data/test/fixtures/movies.yml +7 -0
  205. data/test/fixtures/naked/csv/accounts.csv +1 -0
  206. data/test/fixtures/naked/yml/accounts.yml +1 -0
  207. data/test/fixtures/naked/yml/companies.yml +1 -0
  208. data/test/fixtures/naked/yml/courses.yml +1 -0
  209. data/test/fixtures/order.rb +4 -0
  210. data/test/fixtures/parrot.rb +13 -0
  211. data/test/fixtures/parrots.yml +27 -0
  212. data/test/fixtures/parrots_pirates.yml +7 -0
  213. data/test/fixtures/people.yml +3 -0
  214. data/test/fixtures/person.rb +4 -0
  215. data/test/fixtures/pirate.rb +5 -0
  216. data/test/fixtures/pirates.yml +9 -0
  217. data/test/fixtures/post.rb +59 -0
  218. data/test/fixtures/posts.yml +48 -0
  219. data/test/fixtures/project.rb +27 -2
  220. data/test/fixtures/projects.yml +7 -0
  221. data/test/fixtures/reader.rb +4 -0
  222. data/test/fixtures/readers.yml +4 -0
  223. data/test/fixtures/reply.rb +18 -2
  224. data/test/fixtures/reserved_words/distinct.yml +5 -0
  225. data/test/fixtures/reserved_words/distincts_selects.yml +11 -0
  226. data/test/fixtures/reserved_words/group.yml +14 -0
  227. data/test/fixtures/reserved_words/select.yml +8 -0
  228. data/test/fixtures/reserved_words/values.yml +7 -0
  229. data/test/fixtures/ship.rb +3 -0
  230. data/test/fixtures/ships.yml +5 -0
  231. data/test/fixtures/subject.rb +4 -0
  232. data/test/fixtures/subscriber.rb +4 -3
  233. data/test/fixtures/tag.rb +7 -0
  234. data/test/fixtures/tagging.rb +10 -0
  235. data/test/fixtures/taggings.yml +25 -0
  236. data/test/fixtures/tags.yml +7 -0
  237. data/test/fixtures/task.rb +3 -0
  238. data/test/fixtures/tasks.yml +7 -0
  239. data/test/fixtures/topic.rb +20 -3
  240. data/test/fixtures/topics.yml +22 -0
  241. data/test/fixtures/treasure.rb +4 -0
  242. data/test/fixtures/treasures.yml +10 -0
  243. data/test/fixtures/vertex.rb +9 -0
  244. data/test/fixtures/vertices.yml +4 -0
  245. data/test/fixtures_test.rb +574 -8
  246. data/test/inheritance_test.rb +113 -27
  247. data/test/json_serialization_test.rb +180 -0
  248. data/test/lifecycle_test.rb +56 -29
  249. data/test/locking_test.rb +273 -0
  250. data/test/method_scoping_test.rb +416 -0
  251. data/test/migration_test.rb +933 -0
  252. data/test/migration_test_firebird.rb +124 -0
  253. data/test/mixin_test.rb +95 -0
  254. data/test/modules_test.rb +23 -10
  255. data/test/multiple_db_test.rb +17 -3
  256. data/test/pk_test.rb +59 -15
  257. data/test/query_cache_test.rb +104 -0
  258. data/test/readonly_test.rb +107 -0
  259. data/test/reflection_test.rb +124 -27
  260. data/test/reserved_word_test_mysql.rb +177 -0
  261. data/test/schema_authorization_test_postgresql.rb +75 -0
  262. data/test/schema_dumper_test.rb +131 -0
  263. data/test/schema_test_postgresql.rb +64 -0
  264. data/test/serialization_test.rb +47 -0
  265. data/test/synonym_test_oracle.rb +17 -0
  266. data/test/table_name_test_sqlserver.rb +23 -0
  267. data/test/threaded_connections_test.rb +48 -0
  268. data/test/transactions_test.rb +227 -29
  269. data/test/unconnected_test.rb +14 -6
  270. data/test/validations_test.rb +1293 -32
  271. data/test/xml_serialization_test.rb +202 -0
  272. metadata +347 -143
  273. data/dev-utils/eval_debugger.rb +0 -9
  274. data/examples/associations.rb +0 -87
  275. data/examples/shared_setup.rb +0 -15
  276. data/examples/validation.rb +0 -88
  277. data/lib/active_record/deprecated_associations.rb +0 -70
  278. data/lib/active_record/support/class_attribute_accessors.rb +0 -43
  279. data/lib/active_record/support/class_inheritable_attributes.rb +0 -37
  280. data/lib/active_record/support/clean_logger.rb +0 -10
  281. data/lib/active_record/support/inflector.rb +0 -70
  282. data/lib/active_record/vendor/simple.rb +0 -702
  283. data/lib/active_record/wrappers/yaml_wrapper.rb +0 -15
  284. data/lib/active_record/wrappings.rb +0 -59
  285. data/rakefile +0 -122
  286. data/test/deprecated_associations_test.rb +0 -336
  287. data/test/fixtures/accounts/signals37 +0 -3
  288. data/test/fixtures/accounts/unknown +0 -2
  289. data/test/fixtures/companies/first_client +0 -6
  290. data/test/fixtures/companies/first_firm +0 -4
  291. data/test/fixtures/companies/second_client +0 -6
  292. data/test/fixtures/courses/java +0 -2
  293. data/test/fixtures/courses/ruby +0 -2
  294. data/test/fixtures/customers/david +0 -6
  295. data/test/fixtures/db_definitions/mysql.sql +0 -96
  296. data/test/fixtures/db_definitions/mysql2.sql +0 -4
  297. data/test/fixtures/developers/david +0 -2
  298. data/test/fixtures/developers/jamis +0 -2
  299. data/test/fixtures/entrants/first +0 -3
  300. data/test/fixtures/entrants/second +0 -3
  301. data/test/fixtures/entrants/third +0 -3
  302. data/test/fixtures/fixture_database.sqlite +0 -0
  303. data/test/fixtures/fixture_database_2.sqlite +0 -0
  304. data/test/fixtures/movies/first +0 -2
  305. data/test/fixtures/movies/second +0 -2
  306. data/test/fixtures/projects/action_controller +0 -2
  307. data/test/fixtures/projects/active_record +0 -2
  308. data/test/fixtures/topics/first +0 -9
  309. data/test/fixtures/topics/second +0 -8
  310. data/test/inflector_test.rb +0 -104
  311. data/test/thread_safety_test.rb +0 -33
@@ -0,0 +1,306 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters # :nodoc:
3
+ module SchemaStatements
4
+ # Returns a Hash of mappings from the abstract data types to the native
5
+ # database types. See TableDefinition#column for details on the recognized
6
+ # abstract data types.
7
+ def native_database_types
8
+ {}
9
+ end
10
+
11
+ # This is the maximum length a table alias can be
12
+ def table_alias_length
13
+ 255
14
+ end
15
+
16
+ # Truncates a table alias according to the limits of the current adapter.
17
+ def table_alias_for(table_name)
18
+ table_name[0..table_alias_length-1].gsub(/\./, '_')
19
+ end
20
+
21
+ # def tables(name = nil) end
22
+
23
+ # Returns an array of indexes for the given table.
24
+ # def indexes(table_name, name = nil) end
25
+
26
+ # Returns an array of Column objects for the table specified by +table_name+.
27
+ # See the concrete implementation for details on the expected parameter values.
28
+ def columns(table_name, name = nil) end
29
+
30
+ # Creates a new table
31
+ # There are two ways to work with #create_table. You can use the block
32
+ # form or the regular form, like this:
33
+ #
34
+ # === Block form
35
+ # # create_table() yields a TableDefinition instance
36
+ # create_table(:suppliers) do |t|
37
+ # t.column :name, :string, :limit => 60
38
+ # # Other fields here
39
+ # end
40
+ #
41
+ # === Regular form
42
+ # create_table(:suppliers)
43
+ # add_column(:suppliers, :name, :string, {:limit => 60})
44
+ #
45
+ # The +options+ hash can include the following keys:
46
+ # [<tt>:id</tt>]
47
+ # Whether to automatically add a primary key column. Defaults to true.
48
+ # Join tables for has_and_belongs_to_many should set :id => false.
49
+ # [<tt>:primary_key</tt>]
50
+ # The name of the primary key, if one is to be added automatically.
51
+ # Defaults to +id+.
52
+ # [<tt>:options</tt>]
53
+ # Any extra options you want appended to the table definition.
54
+ # [<tt>:temporary</tt>]
55
+ # Make a temporary table.
56
+ # [<tt>:force</tt>]
57
+ # Set to true to drop the table before creating it.
58
+ # Defaults to false.
59
+ #
60
+ # ===== Examples
61
+ # ====== Add a backend specific option to the generated SQL (MySQL)
62
+ # create_table(:suppliers, :options => 'ENGINE=InnoDB DEFAULT CHARSET=utf8')
63
+ # generates:
64
+ # CREATE TABLE suppliers (
65
+ # id int(11) DEFAULT NULL auto_increment PRIMARY KEY
66
+ # ) ENGINE=InnoDB DEFAULT CHARSET=utf8
67
+ #
68
+ # ====== Rename the primary key column
69
+ # create_table(:objects, :primary_key => 'guid') do |t|
70
+ # t.column :name, :string, :limit => 80
71
+ # end
72
+ # generates:
73
+ # CREATE TABLE objects (
74
+ # guid int(11) DEFAULT NULL auto_increment PRIMARY KEY,
75
+ # name varchar(80)
76
+ # )
77
+ #
78
+ # ====== Do not add a primary key column
79
+ # create_table(:categories_suppliers, :id => false) do |t|
80
+ # t.column :category_id, :integer
81
+ # t.column :supplier_id, :integer
82
+ # end
83
+ # generates:
84
+ # CREATE TABLE categories_suppliers (
85
+ # category_id int,
86
+ # supplier_id int
87
+ # )
88
+ #
89
+ # See also TableDefinition#column for details on how to create columns.
90
+ def create_table(table_name, options = {})
91
+ table_definition = TableDefinition.new(self)
92
+ table_definition.primary_key(options[:primary_key] || "id") unless options[:id] == false
93
+
94
+ yield table_definition
95
+
96
+ if options[:force]
97
+ drop_table(table_name, options) rescue nil
98
+ end
99
+
100
+ create_sql = "CREATE#{' TEMPORARY' if options[:temporary]} TABLE "
101
+ create_sql << "#{quote_table_name(table_name)} ("
102
+ create_sql << table_definition.to_sql
103
+ create_sql << ") #{options[:options]}"
104
+ execute create_sql
105
+ end
106
+
107
+ # Renames a table.
108
+ # ===== Example
109
+ # rename_table('octopuses', 'octopi')
110
+ def rename_table(table_name, new_name)
111
+ raise NotImplementedError, "rename_table is not implemented"
112
+ end
113
+
114
+ # Drops a table from the database.
115
+ def drop_table(table_name, options = {})
116
+ execute "DROP TABLE #{quote_table_name(table_name)}"
117
+ end
118
+
119
+ # Adds a new column to the named table.
120
+ # See TableDefinition#column for details of the options you can use.
121
+ def add_column(table_name, column_name, type, options = {})
122
+ add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
123
+ add_column_options!(add_column_sql, options)
124
+ execute(add_column_sql)
125
+ end
126
+
127
+ # Removes the column from the table definition.
128
+ # ===== Examples
129
+ # remove_column(:suppliers, :qualification)
130
+ def remove_column(table_name, column_name)
131
+ execute "ALTER TABLE #{quote_table_name(table_name)} DROP #{quote_column_name(column_name)}"
132
+ end
133
+
134
+ # Changes the column's definition according to the new options.
135
+ # See TableDefinition#column for details of the options you can use.
136
+ # ===== Examples
137
+ # change_column(:suppliers, :name, :string, :limit => 80)
138
+ # change_column(:accounts, :description, :text)
139
+ def change_column(table_name, column_name, type, options = {})
140
+ raise NotImplementedError, "change_column is not implemented"
141
+ end
142
+
143
+ # Sets a new default value for a column. If you want to set the default
144
+ # value to +NULL+, you are out of luck. You need to
145
+ # DatabaseStatements#execute the appropriate SQL statement yourself.
146
+ # ===== Examples
147
+ # change_column_default(:suppliers, :qualification, 'new')
148
+ # change_column_default(:accounts, :authorized, 1)
149
+ def change_column_default(table_name, column_name, default)
150
+ raise NotImplementedError, "change_column_default is not implemented"
151
+ end
152
+
153
+ # Renames a column.
154
+ # ===== Example
155
+ # rename_column(:suppliers, :description, :name)
156
+ def rename_column(table_name, column_name, new_column_name)
157
+ raise NotImplementedError, "rename_column is not implemented"
158
+ end
159
+
160
+ # Adds a new index to the table. +column_name+ can be a single Symbol, or
161
+ # an Array of Symbols.
162
+ #
163
+ # The index will be named after the table and the first column name,
164
+ # unless you pass +:name+ as an option.
165
+ #
166
+ # When creating an index on multiple columns, the first column is used as a name
167
+ # for the index. For example, when you specify an index on two columns
168
+ # [+:first+, +:last+], the DBMS creates an index for both columns as well as an
169
+ # index for the first column +:first+. Using just the first name for this index
170
+ # makes sense, because you will never have to create a singular index with this
171
+ # name.
172
+ #
173
+ # ===== Examples
174
+ # ====== Creating a simple index
175
+ # add_index(:suppliers, :name)
176
+ # generates
177
+ # CREATE INDEX suppliers_name_index ON suppliers(name)
178
+ # ====== Creating a unique index
179
+ # add_index(:accounts, [:branch_id, :party_id], :unique => true)
180
+ # generates
181
+ # CREATE UNIQUE INDEX accounts_branch_id_party_id_index ON accounts(branch_id, party_id)
182
+ # ====== Creating a named index
183
+ # add_index(:accounts, [:branch_id, :party_id], :unique => true, :name => 'by_branch_party')
184
+ # generates
185
+ # CREATE UNIQUE INDEX by_branch_party ON accounts(branch_id, party_id)
186
+ def add_index(table_name, column_name, options = {})
187
+ column_names = Array(column_name)
188
+ index_name = index_name(table_name, :column => column_names)
189
+
190
+ if Hash === options # legacy support, since this param was a string
191
+ index_type = options[:unique] ? "UNIQUE" : ""
192
+ index_name = options[:name] || index_name
193
+ else
194
+ index_type = options
195
+ end
196
+ quoted_column_names = column_names.map { |e| quote_column_name(e) }.join(", ")
197
+ execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})"
198
+ end
199
+
200
+ # Remove the given index from the table.
201
+ #
202
+ # Remove the suppliers_name_index in the suppliers table.
203
+ # remove_index :suppliers, :name
204
+ # Remove the index named accounts_branch_id_index in the accounts table.
205
+ # remove_index :accounts, :column => :branch_id
206
+ # Remove the index named accounts_branch_id_party_id_index in the accounts table.
207
+ # remove_index :accounts, :column => [:branch_id, :party_id]
208
+ # Remove the index named by_branch_party in the accounts table.
209
+ # remove_index :accounts, :name => :by_branch_party
210
+ def remove_index(table_name, options = {})
211
+ execute "DROP INDEX #{quote_column_name(index_name(table_name, options))} ON #{table_name}"
212
+ end
213
+
214
+ def index_name(table_name, options) #:nodoc:
215
+ if Hash === options # legacy support
216
+ if options[:column]
217
+ "index_#{table_name}_on_#{Array(options[:column]) * '_and_'}"
218
+ elsif options[:name]
219
+ options[:name]
220
+ else
221
+ raise ArgumentError, "You must specify the index name"
222
+ end
223
+ else
224
+ index_name(table_name, :column => options)
225
+ end
226
+ end
227
+
228
+ # Returns a string of <tt>CREATE TABLE</tt> SQL statement(s) for recreating the
229
+ # entire structure of the database.
230
+ def structure_dump
231
+ end
232
+
233
+ # Should not be called normally, but this operation is non-destructive.
234
+ # The migrations module handles this automatically.
235
+ def initialize_schema_information
236
+ begin
237
+ execute "CREATE TABLE #{quote_table_name(ActiveRecord::Migrator.schema_info_table_name)} (version #{type_to_sql(:integer)})"
238
+ execute "INSERT INTO #{quote_table_name(ActiveRecord::Migrator.schema_info_table_name)} (version) VALUES(0)"
239
+ rescue ActiveRecord::StatementInvalid
240
+ # Schema has been initialized
241
+ end
242
+ end
243
+
244
+ def dump_schema_information #:nodoc:
245
+ begin
246
+ if (current_schema = ActiveRecord::Migrator.current_version) > 0
247
+ return "INSERT INTO #{quote_table_name(ActiveRecord::Migrator.schema_info_table_name)} (version) VALUES (#{current_schema})"
248
+ end
249
+ rescue ActiveRecord::StatementInvalid
250
+ # No Schema Info
251
+ end
252
+ end
253
+
254
+
255
+ def type_to_sql(type, limit = nil, precision = nil, scale = nil) #:nodoc:
256
+ if native = native_database_types[type]
257
+ column_type_sql = native.is_a?(Hash) ? native[:name] : native
258
+ if type == :decimal # ignore limit, use precision and scale
259
+ precision ||= native[:precision]
260
+ scale ||= native[:scale]
261
+ if precision
262
+ if scale
263
+ column_type_sql << "(#{precision},#{scale})"
264
+ else
265
+ column_type_sql << "(#{precision})"
266
+ end
267
+ else
268
+ raise ArgumentError, "Error adding decimal column: precision cannot be empty if scale if specified" if scale
269
+ end
270
+ column_type_sql
271
+ else
272
+ limit ||= native[:limit]
273
+ column_type_sql << "(#{limit})" if limit
274
+ column_type_sql
275
+ end
276
+ else
277
+ column_type_sql = type
278
+ end
279
+ end
280
+
281
+ def add_column_options!(sql, options) #:nodoc:
282
+ sql << " DEFAULT #{quote(options[:default], options[:column])}" if options_include_default?(options)
283
+ sql << " NOT NULL" if options[:null] == false
284
+ end
285
+
286
+ # SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause.
287
+ # Both PostgreSQL and Oracle overrides this for custom DISTINCT syntax.
288
+ #
289
+ # distinct("posts.id", "posts.created_at desc")
290
+ def distinct(columns, order_by)
291
+ "DISTINCT #{columns}"
292
+ end
293
+
294
+ # ORDER BY clause for the passed order option.
295
+ # PostgreSQL overrides this due to its stricter standards compliance.
296
+ def add_order_by_for_association_limiting!(sql, options)
297
+ sql << " ORDER BY #{options[:order]}"
298
+ end
299
+
300
+ protected
301
+ def options_include_default?(options)
302
+ options.include?(:default) && !(options[:null] == false && options[:default].nil?)
303
+ end
304
+ end
305
+ end
306
+ end