source: subversion/sites/rails_port_branches/i18n_2/lib/migrate.rb @ 15391

Last change on this file since 15391 was 15383, checked in by tomhughes, 10 years ago

Add a remove_foreign_key method and make migration 34 reversible.

File size: 6.9 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        types
63      end
64
65      def change_column(table_name, column_name, type, options = {})
66        unless options_include_default?(options)
67          options[:default] = select_one("SHOW COLUMNS FROM #{table_name} LIKE '#{column_name}'")["Default"]
68
69          unless type == :string or type == :text
70            options.delete(:default) if options[:default] = "";
71          end
72        end
73
74        change_column_sql = "ALTER TABLE #{table_name} CHANGE #{column_name} #{column_name} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
75        add_column_options!(change_column_sql, options)
76        execute(change_column_sql) 
77      end
78
79      def myisam_table
80        return { :id => false, :force => true, :options => "ENGINE=MyIsam" }
81      end
82
83      def innodb_table
84        return { :id => false, :force => true, :options => "ENGINE=InnoDB" }
85      end
86
87      def innodb_option
88        return "ENGINE=InnoDB"
89      end
90
91      def change_engine (table_name, engine)
92        execute "ALTER TABLE #{table_name} ENGINE = #{engine}"
93      end
94
95      def add_fulltext_index (table_name, column)
96        execute "CREATE FULLTEXT INDEX `#{table_name}_#{column}_idx` ON `#{table_name}` (`#{column}`)"
97      end
98
99      def alter_column_nwr_enum (table_name, column)
100        execute "alter table #{table_name} change column #{column} #{column} enum('Node','Way','Relation');"
101      end
102
103      def alter_primary_key(table_name, new_columns)
104        execute("alter table #{table_name} drop primary key, add primary key (#{new_columns.join(',')})")
105      end
106
107      def interval_constant(interval)
108        "'#{interval}'"
109      end
110    end
111
112    class PostgreSQLAdapter
113      if PostgreSQLAdapter.public_instance_methods(false).include?('native_database_types')
114        alias_method :old_native_database_types, :native_database_types
115      end
116
117      def native_database_types
118        types = old_native_database_types
119        types[:double] = { :name => "double precision" }
120        types[:integer_pk] = { :name => "serial PRIMARY KEY" }
121        types[:bigint_pk] = { :name => "bigserial PRIMARY KEY" }
122        types[:bigint_pk_64] = { :name => "bigserial PRIMARY KEY" }
123        types[:bigint_auto_64] = { :name => "bigint" } #fixme: need autoincrement?
124        types[:bigint_auto_11] = { :name => "bigint" } #fixme: need autoincrement?
125        types[:bigint_auto_20] = { :name => "bigint" } #fixme: need autoincrement?
126        types[:four_byte_unsigned] = { :name => "bigint" } # meh
127        types[:inet] = { :name=> "inet" }
128        types
129      end
130
131      def myisam_table
132        return { :id => false, :force => true, :options => ""}
133      end
134
135      def innodb_table
136        return { :id => false, :force => true, :options => ""}
137      end
138
139      def innodb_option
140        return ""
141      end
142 
143      def change_engine (table_name, engine)
144      end
145
146      def add_fulltext_index (table_name, column)
147        execute "CREATE INDEX #{table_name}_#{column}_idx on #{table_name} (#{column})"
148      end
149
150      def alter_column_nwr_enum (table_name, column)
151        response = select_one("select count(*) as count from pg_type where typname = 'nwr_enum'")
152        if response['count'] == "0" #yep, as a string
153          execute "create type nwr_enum as ENUM ('Node', 'Way', 'Relation')"
154        end
155        execute "alter table #{table_name} drop #{column}"
156        execute "alter table #{table_name} add #{column} nwr_enum"
157      end
158
159      def alter_primary_key(table_name, new_columns)
160        execute "alter table #{table_name} drop constraint #{table_name}_pkey; alter table #{table_name} add primary key (#{new_columns.join(',')})"
161      end
162
163      def interval_constant(interval)
164        "'#{interval}'::interval"
165      end
166
167      def add_index(table_name, column_name, options = {})
168        column_names = Array(column_name)
169        index_name   = index_name(table_name, :column => column_names)
170
171        if Hash === options # legacy support, since this param was a string
172          index_type = options[:unique] ? "UNIQUE" : ""
173          index_name = options[:name] || index_name
174          index_method = options[:method] || "BTREE"
175        else
176          index_type = options
177        end
178        quoted_column_names = column_names.map { |e| quote_column_name(e) }.join(", ")
179        execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} USING #{index_method} (#{quoted_column_names})"
180      end
181    end
182  end
183end
Note: See TracBrowser for help on using the repository browser.