source: subversion/sites/rails_port/lib/migrate.rb @ 17044

Last change on this file since 17044 was 16834, checked in by tomhughes, 10 years ago

Replace hard coded nwr enumeration support with a more generic
system for defining enumerations.

File size: 7.3 KB
Line 
1module 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      if MysqlAdapter.public_instance_methods(false).include?('native_database_types')
47        alias_method :old_native_database_types, :native_database_types
48      end
49
50      def native_database_types
51        types = old_native_database_types
52        types[:bigint] = { :name => "bigint", :limit => 20 }
53        types[:double] = { :name => "double" }
54        types[:integer_pk] = { :name => "integer DEFAULT NULL auto_increment PRIMARY KEY" }
55        types[:bigint_pk] = { :name => "bigint(20) DEFAULT NULL auto_increment PRIMARY KEY" }
56        types[:bigint_pk_64] = { :name => "bigint(64) DEFAULT NULL auto_increment PRIMARY KEY" }
57        types[:bigint_auto_64] = { :name => "bigint(64) DEFAULT NULL auto_increment" }
58        types[:bigint_auto_11] = { :name => "bigint(11) DEFAULT NULL auto_increment" }
59        types[:bigint_auto_20] = { :name => "bigint(20) DEFAULT NULL auto_increment" }
60        types[:four_byte_unsigned] = { :name=> "integer unsigned" }
61        types[:inet] = { :name=> "integer unsigned" }
62
63        enumerations.each do |e,v|
64          types[e.to_sym]= { :name => "enum('#{v.join '\',\''}')" }
65        end
66
67        types
68      end
69
70      def change_column(table_name, column_name, type, options = {})
71        unless options_include_default?(options)
72          options[:default] = select_one("SHOW COLUMNS FROM #{table_name} LIKE '#{column_name}'")["Default"]
73
74          unless type == :string or type == :text
75            options.delete(:default) if options[:default] = "";
76          end
77        end
78
79        change_column_sql = "ALTER TABLE #{table_name} CHANGE #{column_name} #{column_name} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
80        add_column_options!(change_column_sql, options)
81        execute(change_column_sql) 
82      end
83
84      def myisam_table
85        return { :id => false, :force => true, :options => "ENGINE=MyIsam" }
86      end
87
88      def innodb_table
89        return { :id => false, :force => true, :options => "ENGINE=InnoDB" }
90      end
91
92      def innodb_option
93        return "ENGINE=InnoDB"
94      end
95
96      def change_engine (table_name, engine)
97        execute "ALTER TABLE #{table_name} ENGINE = #{engine}"
98      end
99
100      def add_fulltext_index (table_name, column)
101        execute "CREATE FULLTEXT INDEX `#{table_name}_#{column}_idx` ON `#{table_name}` (`#{column}`)"
102      end
103
104      def enumerations
105        @enumerations ||= Hash.new
106      end
107
108      def create_enumeration (enumeration_name, values)
109        enumerations[enumeration_name] = values
110      end
111
112      def drop_enumeration (enumeration_name)
113        enumerations.delete(enumeration_name)
114      end
115
116      def alter_primary_key(table_name, new_columns)
117        execute("alter table #{table_name} drop primary key, add primary key (#{new_columns.join(',')})")
118      end
119
120      def interval_constant(interval)
121        "'#{interval}'"
122      end
123    end
124
125    class PostgreSQLAdapter
126      if PostgreSQLAdapter.public_instance_methods(false).include?('native_database_types')
127        alias_method :old_native_database_types, :native_database_types
128      end
129
130      def native_database_types
131        types = old_native_database_types
132        types[:double] = { :name => "double precision" }
133        types[:integer_pk] = { :name => "serial PRIMARY KEY" }
134        types[:bigint_pk] = { :name => "bigserial PRIMARY KEY" }
135        types[:bigint_pk_64] = { :name => "bigserial PRIMARY KEY" }
136        types[:bigint_auto_64] = { :name => "bigint" } #fixme: need autoincrement?
137        types[:bigint_auto_11] = { :name => "bigint" } #fixme: need autoincrement?
138        types[:bigint_auto_20] = { :name => "bigint" } #fixme: need autoincrement?
139        types[:four_byte_unsigned] = { :name => "bigint" } # meh
140        types[:inet] = { :name=> "inet" }
141
142        enumerations.each_key do |e|
143          types[e.to_sym]= { :name => e }
144        end
145
146        types
147      end
148
149      def myisam_table
150        return { :id => false, :force => true, :options => ""}
151      end
152
153      def innodb_table
154        return { :id => false, :force => true, :options => ""}
155      end
156
157      def innodb_option
158        return ""
159      end
160 
161      def change_engine (table_name, engine)
162      end
163
164      def add_fulltext_index (table_name, column)
165        execute "CREATE INDEX #{table_name}_#{column}_idx on #{table_name} (#{column})"
166      end
167
168      def enumerations
169        @enumerations ||= Hash.new
170      end
171
172      def create_enumeration (enumeration_name, values)
173        enumerations[enumeration_name] = values
174        execute "create type #{enumeration_name} as enum ('#{values.join '\',\''}')"
175      end
176
177      def drop_enumeration (enumeration_name)
178        execute "drop type #{enumeration_name}"
179        enumerations.delete(enumeration_name)
180      end
181
182      def alter_primary_key(table_name, new_columns)
183        execute "alter table #{table_name} drop constraint #{table_name}_pkey; alter table #{table_name} add primary key (#{new_columns.join(',')})"
184      end
185
186      def interval_constant(interval)
187        "'#{interval}'::interval"
188      end
189
190      def add_index(table_name, column_name, options = {})
191        column_names = Array(column_name)
192        index_name   = index_name(table_name, :column => column_names)
193
194        if Hash === options # legacy support, since this param was a string
195          index_type = options[:unique] ? "UNIQUE" : ""
196          index_name = options[:name] || index_name
197          index_method = options[:method] || "BTREE"
198        else
199          index_type = options
200        end
201        quoted_column_names = column_names.map { |e| quote_column_name(e) }.join(", ")
202        execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} USING #{index_method} (#{quoted_column_names})"
203      end
204    end
205  end
206end
Note: See TracBrowser for help on using the repository browser.