]> git.openstreetmap.org Git - rails.git/blob - lib/migrate.rb
3d9970d8c35ff10195a5e0ca963969f0f772977c
[rails.git] / lib / migrate.rb
1 module ActiveRecord
2   module ConnectionAdapters
3     module SchemaStatements
4       def quote_column_names(column_name)
5         Array(column_name).map { |e| quote_column_name(e) }.join(", ")
6       end
7
8       def add_primary_key(table_name, column_name, options = {})
9         column_names = Array(column_name)
10         quoted_column_names = column_names.map { |e| quote_column_name(e) }.join(", ")
11         execute "ALTER TABLE #{table_name} ADD PRIMARY KEY (#{quoted_column_names})"
12       end
13
14       def remove_primary_key(table_name)
15         execute "ALTER TABLE #{table_name} DROP PRIMARY KEY"
16       end
17
18       def add_foreign_key(table_name, column_name, reftbl, refcol = nil)
19         execute "ALTER TABLE #{table_name} ADD " +
20           "FOREIGN KEY (#{quote_column_names(column_name)}) " +
21           "REFERENCES #{reftbl} (#{quote_column_names(refcol || column_name)})"
22       end
23
24       def remove_foreign_key(table_name, column_name, reftbl, refcol = nil)
25         execute "ALTER TABLE #{table_name} DROP " +
26           "CONSTRAINT #{table_name}_#{column_name[0]}_fkey"
27       end
28
29       alias_method :old_options_include_default?, :options_include_default?
30
31       def options_include_default?(options)
32         return false if options[:options] =~ /AUTO_INCREMENT/i
33         return old_options_include_default?(options)
34       end
35
36       alias_method :old_add_column_options!, :add_column_options!
37
38       def add_column_options!(sql, options)
39         sql << " UNSIGNED" if options[:unsigned]
40         old_add_column_options!(sql, options)
41         sql << " #{options[:options]}"
42       end
43     end
44
45     class MysqlAdapter
46       alias_method :old_native_database_types, :native_database_types
47
48       def native_database_types
49         types = old_native_database_types
50         types[:bigint] = { :name => "bigint", :limit => 20 }
51         types[:double] = { :name => "double" }
52         types[:integer_pk] = { :name => "integer DEFAULT NULL auto_increment PRIMARY KEY" }
53         types[:bigint_pk] = { :name => "bigint(20) DEFAULT NULL auto_increment PRIMARY KEY" }
54         types[:bigint_pk_64] = { :name => "bigint(64) DEFAULT NULL auto_increment PRIMARY KEY" }
55         types[:bigint_auto_64] = { :name => "bigint(64) DEFAULT NULL auto_increment" }
56         types[:bigint_auto_11] = { :name => "bigint(11) DEFAULT NULL auto_increment" }
57         types[:bigint_auto_20] = { :name => "bigint(20) DEFAULT NULL auto_increment" }
58         types[:four_byte_unsigned] = { :name=> "integer unsigned" }
59         types[:inet] = { :name=> "integer unsigned" }
60
61         enumerations.each do |e,v|
62           types[e.to_sym]= { :name => "enum('#{v.join '\',\''}')" }
63         end
64
65         types
66       end
67
68       def change_column(table_name, column_name, type, options = {})
69         unless options_include_default?(options)
70           options[:default] = select_one("SHOW COLUMNS FROM #{table_name} LIKE '#{column_name}'")["Default"]
71
72           unless type == :string or type == :text
73             options.delete(:default) if options[:default] = "";
74           end
75         end
76
77         change_column_sql = "ALTER TABLE #{table_name} CHANGE #{column_name} #{column_name} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
78         add_column_options!(change_column_sql, options)
79         execute(change_column_sql) 
80       end
81
82       def myisam_table
83         return { :id => false, :force => true, :options => "ENGINE=MyIsam" }
84       end
85
86       def innodb_table
87         return { :id => false, :force => true, :options => "ENGINE=InnoDB" }
88       end
89
90       def innodb_option
91         return "ENGINE=InnoDB"
92       end
93
94       def change_engine (table_name, engine)
95         execute "ALTER TABLE #{table_name} ENGINE = #{engine}"
96       end
97
98       def add_fulltext_index (table_name, column)
99         execute "CREATE FULLTEXT INDEX `#{table_name}_#{column}_idx` ON `#{table_name}` (`#{column}`)"
100       end
101
102       def enumerations
103         @enumerations ||= Hash.new
104       end
105
106       def create_enumeration (enumeration_name, values)
107         enumerations[enumeration_name] = values
108       end
109
110       def drop_enumeration (enumeration_name)
111         enumerations.delete(enumeration_name)
112       end
113
114       def alter_primary_key(table_name, new_columns)
115         execute("alter table #{table_name} drop primary key, add primary key (#{new_columns.join(',')})")
116       end
117
118       def interval_constant(interval)
119         "'#{interval}'"
120       end
121     end
122
123     class PostgreSQLAdapter
124       alias_method :old_native_database_types, :native_database_types
125
126       def native_database_types
127         types = old_native_database_types
128         types[:double] = { :name => "double precision" }
129         types[:integer_pk] = { :name => "serial PRIMARY KEY" }
130         types[:bigint_pk] = { :name => "bigserial PRIMARY KEY" }
131         types[:bigint_pk_64] = { :name => "bigserial PRIMARY KEY" }
132         types[:bigint_auto_64] = { :name => "bigint" } #fixme: need autoincrement?
133         types[:bigint_auto_11] = { :name => "bigint" } #fixme: need autoincrement?
134         types[:bigint_auto_20] = { :name => "bigint" } #fixme: need autoincrement?
135         types[:four_byte_unsigned] = { :name => "bigint" } # meh
136         types[:inet] = { :name=> "inet" }
137
138         enumerations.each_key do |e|
139           types[e.to_sym]= { :name => e }
140         end
141
142         types
143       end
144
145       def myisam_table
146         return { :id => false, :force => true, :options => ""}
147       end
148
149       def innodb_table
150         return { :id => false, :force => true, :options => ""}
151       end
152
153       def innodb_option
154         return ""
155       end
156  
157       def change_engine (table_name, engine)
158       end
159
160       def add_fulltext_index (table_name, column)
161         execute "CREATE INDEX #{table_name}_#{column}_idx on #{table_name} (#{column})"
162       end
163
164       def enumerations
165         @enumerations ||= Hash.new
166       end
167
168       def create_enumeration (enumeration_name, values)
169         enumerations[enumeration_name] = values
170         execute "create type #{enumeration_name} as enum ('#{values.join '\',\''}')"
171       end
172
173       def drop_enumeration (enumeration_name)
174         execute "drop type #{enumeration_name}"
175         enumerations.delete(enumeration_name)
176       end
177
178       def alter_primary_key(table_name, new_columns)
179         execute "alter table #{table_name} drop constraint #{table_name}_pkey; alter table #{table_name} add primary key (#{new_columns.join(',')})"
180       end
181
182       def interval_constant(interval)
183         "'#{interval}'::interval"
184       end
185
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           index_method = options[:method] || "BTREE"
194         else
195           index_type = options
196         end
197
198         quoted_column_names = column_names.map { |e| quote_column_name(e) }
199         if Hash === options and options[:lowercase]
200           quoted_column_names = quoted_column_names.map { |e| "LOWER(#{e})" }
201         end
202         quoted_column_names = quoted_column_names.join(", ")
203
204         execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} USING #{index_method} (#{quoted_column_names})"
205       end
206     end
207   end
208 end