2 module MissingFunctionalityHelper
3 #Taken from SQLite adapter
5 def alter_table(table_name, options = {}) #:nodoc:
6 table_name = table_name.to_s.downcase
7 altered_table_name = "altered_#{table_name}"
8 caller = lambda {|definition| yield definition if block_given?}
11 # A temporary table might improve performance here, but
12 # it doesn't seem to maintain indices across the whole move.
13 move_table(table_name, altered_table_name,
15 move_table(altered_table_name, table_name, &caller)
19 def move_table(from, to, options = {}, &block) #:nodoc:
20 copy_table(from, to, options, &block)
24 def copy_table(from, to, options = {}) #:nodoc:
25 options = options.merge(:id => (!columns(from).detect{|c| c.name == 'id'}.nil? && 'id' == primary_key(from).to_s))
26 create_table(to, options) do |definition|
27 @definition = definition
28 columns(from).each do |column|
29 column_name = options[:rename] ?
30 (options[:rename][column.name] ||
31 options[:rename][column.name.to_sym] ||
32 column.name) : column.name
34 @definition.column(column_name, column.type,
35 :limit => column.limit, :default => column.default,
38 @definition.primary_key(primary_key(from)) if primary_key(from)
39 yield @definition if block_given?
42 copy_table_indexes(from, to, options[:rename] || {})
43 copy_table_contents(from, to,
44 @definition.columns.map {|column| column.name},
45 options[:rename] || {})
48 def copy_table_indexes(from, to, rename = {}) #:nodoc:
49 indexes(from).each do |index|
50 name = index.name.downcase
51 if to == "altered_#{from}"
53 elsif from == "altered_#{to}"
57 to_column_names = columns(to).map(&:name)
58 columns = index.columns.map {|c| rename[c] || c }.select do |column|
59 to_column_names.include?(column)
63 # index name can't be the same
64 opts = { :name => name.gsub(/(_?)(#{from})_/, "\\1#{to}_") }
65 opts[:unique] = true if index.unique
66 add_index(to, columns, opts)
71 def copy_table_contents(from, to, columns, rename = {}) #:nodoc:
72 column_mappings = Hash[*columns.map {|name| [name, name]}.flatten]
73 rename.inject(column_mappings) {|map, a| map[a.last] = a.first; map}
74 from_columns = columns(from).collect {|col| col.name}
75 columns = columns.find_all{|col| from_columns.include?(column_mappings[col])}
76 quoted_columns = columns.map { |col| quote_column_name(col) } * ','
78 quoted_to = quote_table_name(to)
79 execute("SELECT * FROM #{quote_table_name(from)}").each do |row|
80 sql = "INSERT INTO #{quoted_to} (#{quoted_columns}) VALUES ("
81 sql << columns.map {|col| quote row[column_mappings[col]]} * ', '