fast_change_table 0.0.6 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,18 +1,43 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fast_change_table (0.0.2)
5
- activerecord (~> 2.3)
4
+ fast_change_table (1.0.0)
5
+ activerecord (>= 2.3)
6
6
 
7
7
  GEM
8
8
  remote: http://rubygems.org/
9
9
  specs:
10
- activerecord (2.3.14)
11
- activesupport (= 2.3.14)
12
- activesupport (2.3.14)
10
+ activemodel (3.2.0)
11
+ activesupport (= 3.2.0)
12
+ builder (~> 3.0.0)
13
+ activerecord (3.2.0)
14
+ activemodel (= 3.2.0)
15
+ activesupport (= 3.2.0)
16
+ arel (~> 3.0.0)
17
+ tzinfo (~> 0.3.29)
18
+ activesupport (3.2.0)
19
+ i18n (~> 0.6)
20
+ multi_json (~> 1.0)
21
+ arel (3.0.0)
22
+ builder (3.0.0)
23
+ diff-lcs (1.1.3)
24
+ i18n (0.6.0)
25
+ multi_json (1.0.4)
26
+ mysql2 (0.3.11)
27
+ rspec (2.8.0)
28
+ rspec-core (~> 2.8.0)
29
+ rspec-expectations (~> 2.8.0)
30
+ rspec-mocks (~> 2.8.0)
31
+ rspec-core (2.8.0)
32
+ rspec-expectations (2.8.0)
33
+ diff-lcs (~> 1.1.2)
34
+ rspec-mocks (2.8.0)
35
+ tzinfo (0.3.31)
13
36
 
14
37
  PLATFORMS
15
38
  ruby
16
39
 
17
40
  DEPENDENCIES
18
41
  fast_change_table!
42
+ mysql2
43
+ rspec
data/README.md ADDED
@@ -0,0 +1,54 @@
1
+ #Fast Change Table
2
+
3
+ Use fast\_change\_table instead of change_table in your migrations on large tables of data. Uses a duplication pattern to speed things up.
4
+
5
+
6
+ uses ordinary change_table syntax but adds two options
7
+
8
+ * "replace\_keys" to remove all indexes; new indexes will be specified
9
+ - "disable\_keys" to remove indexes and apply them after data load; this is a tremendous performance enhancement for a dbms with fast index creation
10
+
11
+ __Example:__
12
+
13
+ fast_change_table :table_name, :disable_keys => true do |t|
14
+ t.change :old_string, :string, :limit => 64
15
+ t.rename :old_string, :new_string
16
+ t.integer :an_integer
17
+ end
18
+
19
+
20
+ __other methods:__
21
+
22
+ create\_table\_like(orignal\_table, table\_to\_copy\_to)
23
+ creates a table with the same structure
24
+
25
+ disable\_indexes(table)
26
+ removes all indexes from a table, returns a list of index objects removed
27
+
28
+ enable\_indexes(table, list\_of\_indexes)
29
+ restores a list of indexes to a table
30
+
31
+ fast\_add\_indexes(table, &block)
32
+ allows you to pass a block to add indexes. For mysql creates specified indexes in one statement; allows the data to be scanned once.
33
+
34
+ __Example:__
35
+
36
+
37
+ fast_add_indexes :sometable do |t|
38
+ t.index :some_column
39
+ t.index [:some_other_column, :column_three], :name => "a_multicolumn_index"
40
+ end
41
+
42
+ copy\_table(from\_table, to\_table, remaps = [])
43
+
44
+ * copies rows from one table into another. this probably only works with Mysql.
45
+ by default copies data from column of from_table to to_table of same name.
46
+ will not copy data where there is no corresponding column.
47
+ the remaps argument can be supplied to tell copy table how to handle unmatched columns or override this behavior
48
+
49
+ __Examples:__
50
+
51
+
52
+ copy_table(old_users_without_email_hash, new_table, ['MD5(email)', 'email_hash'])
53
+
54
+ copy_table(old_users_without_total, new_table, ['sum(payments)', 'total_payments'])
data/Rakefile CHANGED
@@ -1 +1,7 @@
1
1
  require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new('spec')
5
+
6
+ # If you want to make this the default task
7
+ task :default => :spec
@@ -21,7 +21,11 @@ Gem::Specification.new do |s|
21
21
  # specify any dependencies here; for example:
22
22
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
23
23
  s.add_runtime_dependency('activerecord', '>= 2.3')
24
+ s.add_development_dependency("rspec")
25
+ s.add_development_dependency("mysql2")
24
26
  else
25
27
  s.add_dependency('activerecord', '>= 2.3')
28
+ s.add_development_dependency("rspec")
29
+ s.add_development_dependency("mysql2")
26
30
  end
27
31
  end
@@ -1,164 +1,12 @@
1
- module ActiveRecord
2
- module ConnectionAdapters #:nodoc:
3
-
4
- module SchemaStatements
5
- def change_table_with_remaps(table_name)
6
- t = Table.new(table_name, self)
7
- yield t
8
- return t.renamed_columns
9
- end
10
- end
11
-
12
- class Table
13
-
14
- def initialize(table_name, base)
15
- @table_name = table_name
16
- @base = base
17
- @renamed_columns = []
18
- end
19
-
20
- def renamed_columns
21
- @renamed_columns
22
- end
23
-
24
- def rename(column_name, new_column_name)
25
- @renamed_columns << [column_name, new_column_name]
26
- @base.rename_column(@table_name, column_name, new_column_name)
27
- end
28
-
29
- end
30
- end
31
- end
1
+ require 'active_record'
2
+ require 'fast_change_table/connection_adapters'
3
+ require 'fast_change_table/fast_change_table'
4
+ require 'fast_change_table/version'
32
5
 
33
6
  module FastChangeTable
34
7
  def self.included(base)
35
8
  base.extend ClassMethods
36
9
  end
37
-
38
- module ClassMethods
39
- def fast_change_table(table_name, options = {}, &block)
40
- options.symbolize_keys!
41
- old_table_name = "old_#{table_name}"
42
- rename_table(table_name, old_table_name)
43
- begin
44
- create_table_like(old_table_name, table_name, options)
45
- renamed_columns = change_table_with_remaps(table_name, &block)
46
- index_list = options[:disable_keys] ? disable_indexes(table_name) : []
47
- #prepare the columns names for the insert statements
48
- copy_table(old_table_name, table_name, renamed_columns)
49
- enable_indexes(table_name, index_list) if options[:disable_keys]
50
- drop_table(old_table_name)
51
- rescue Exception => e
52
- puts "#{e}\n#{e.backtrace}"
53
- drop_table(table_name) if table_exists?(table_name)
54
- rename_table(old_table_name, table_name)
55
- raise e
56
- end
57
- end
58
-
59
- def fast_add_indexes(table, &blk)
60
- phoney = PhoneyTable.new(table.to_s)
61
- yield phoney
62
- enable_indexes(table, phoney.indexes)
63
- end
64
-
65
- #create_table_like( :sometable, :newtable, :remove_keys => true)
66
- def create_table_like(like_table, table, options = {})
67
- options.symbolize_keys!
68
- code = table_schema_code(like_table)
69
- code.gsub!(/create_table\s+"#{like_table}"/, "create_table :#{table}")
70
- if options[:replace_keys] or options[:remove_keys]
71
- code.gsub!(/add_index\s+"#{like_table}"/, "#add_index :#{table}")
72
- else
73
- code.gsub!(/add_index\s+"#{like_table}"/, "add_index :#{table}")
74
- end
75
- class_eval(code)
76
- true
77
- end
78
-
79
- #copy_table( :sometable, :newtable, [[:old_column, :new_column]])
80
- def copy_table(from, to, remaps = [])
81
- old = connection.columns(from).collect(&:name)
82
- current = connection.columns(to).collect(&:name)
83
- remapped_columns = remaps.collect {|c| c.first.to_s}.compact
84
- common = (current & old).sort - remapped_columns
85
- from_columns = common.collect {|c| "`#{c}`"}
86
- to_columns = common.collect {|c| "`#{c}`"}
87
- remaps.each do |remap|
88
- remap = [remap].flatten
89
- next if remap.length != 2
90
- from_columns << remap.first
91
- to_columns << remap.last
92
- end
93
- from_columns_to_s = from_columns.join(', ')
94
- to_columns_to_s = to_columns.join(', ')
95
- execute "INSERT INTO #{to}(#{to_columns_to_s}) SELECT #{from_columns_to_s} FROM #{from}"
96
- end
97
-
98
- def table_schema_code(table)
99
- dumper = ActiveRecord::SchemaDumper.send(:new, connection)
100
- stream = StringIO.new
101
- dumper.send(:table, table.to_s, stream)
102
- stream.rewind
103
- code = stream.read
104
- end
105
-
106
- #removes all the indexes
107
- def disable_indexes(table)
108
- list = connection.indexes(table)
109
- list.each do |i|
110
- remove_index table, :name => i.name
111
- end
112
- list
113
- end
114
-
115
- #
116
- def enable_indexes(table, list)
117
- list.each do |i|
118
- options = {}
119
- options[:name] = i.name if i.name
120
- options[:length] = i.lengths if i.lengths
121
- options[:unique] = i.unique if i.unique
122
- add_index table, i.columns, options
123
- end
124
- true
125
- end
126
-
127
- class PhoneyTable
128
-
129
- attr_accessor :indexes
130
-
131
- def initialize(tablename)
132
- @table = tablename
133
- @indexes = []
134
- end
135
-
136
- def index(columns, options = {})
137
- new_index = PhoneyIndex.new(@table, columns, options)
138
- @indexes << new_index unless @indexes.to_a.any? {|i| i == new_index}
139
- end
140
-
141
- def indexes; @indexes.to_a.uniq end
142
- end
143
-
144
- class PhoneyIndex
145
-
146
- attr_accessor :columns, :lengths, :name, :unique
147
-
148
- def initialize(table, cols, options)
149
- cols = [cols].flatten
150
- self.columns = cols.collect(&:to_s)
151
- self.lengths = options[:length]
152
- self.unique = !!options[:unique]
153
- self.name = options[:name] || "index_#{table}_on_#{columns.join('_and_')}"
154
- self.name = "#{columns.join('_')}_idx" if name.length > 64
155
- end
156
-
157
- def ==(val)
158
- columns == val.columns rescue false
159
- end
160
- end
161
- end
162
10
  end
163
11
 
164
12
  ::ActiveRecord::Migration.send :include, FastChangeTable
@@ -0,0 +1,31 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters #:nodoc:
3
+
4
+ module SchemaStatements
5
+ def change_table_with_remaps(table_name)
6
+ t = Table.new(table_name, self)
7
+ yield t
8
+ return t.renamed_columns
9
+ end
10
+ end
11
+
12
+ class Table
13
+
14
+ def initialize(table_name, base)
15
+ @table_name = table_name
16
+ @base = base
17
+ @renamed_columns = []
18
+ end
19
+
20
+ def renamed_columns
21
+ @renamed_columns
22
+ end
23
+
24
+ def rename(column_name, new_column_name)
25
+ @renamed_columns << [column_name, new_column_name]
26
+ @base.rename_column(@table_name, column_name, new_column_name)
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,132 @@
1
+
2
+
3
+ module FastChangeTable
4
+ def self.included(base)
5
+ base.extend ClassMethods
6
+ end
7
+
8
+ module ClassMethods
9
+ def fast_change_table(table_name, options = {}, &block)
10
+ options.symbolize_keys!
11
+ old_table_name = "old_#{table_name}"
12
+ rename_table(table_name, old_table_name)
13
+ begin
14
+ create_table_like(old_table_name, table_name, options)
15
+ renamed_columns = change_table_with_remaps(table_name, &block)
16
+ index_list = options[:disable_keys] ? disable_indexes(table_name) : []
17
+ #prepare the columns names for the insert statements
18
+ copy_table(old_table_name, table_name, renamed_columns)
19
+ enable_indexes(table_name, index_list) if options[:disable_keys]
20
+ drop_table(old_table_name)
21
+ rescue Exception => e
22
+ puts "#{e}\n#{e.backtrace}"
23
+ drop_table(table_name) if table_exists?(table_name)
24
+ rename_table(old_table_name, table_name)
25
+ raise e
26
+ end
27
+ end
28
+
29
+ def fast_add_indexes(table, &blk)
30
+ phoney = PhoneyTable.new(table.to_s)
31
+ yield phoney
32
+ enable_indexes(table, phoney.indexes)
33
+ end
34
+
35
+ #create_table_like( :sometable, :newtable, :remove_keys => true)
36
+ def create_table_like(like_table, table, options = {})
37
+ options.symbolize_keys!
38
+ code = table_schema_code(like_table)
39
+ code.gsub!(/create_table\s+"#{like_table}"/, "create_table :#{table}")
40
+ if options[:replace_keys] or options[:remove_keys]
41
+ code.gsub!(/add_index\s+"#{like_table}"/, "#add_index :#{table}")
42
+ else
43
+ code.gsub!(/add_index\s+"#{like_table}"/, "add_index :#{table}")
44
+ end
45
+ class_eval(code)
46
+ true
47
+ end
48
+
49
+ #copy_table( :sometable, :newtable, [[:old_column, :new_column]])
50
+ def copy_table(from, to, remaps = [])
51
+ old = connection.columns(from).collect(&:name)
52
+ current = connection.columns(to).collect(&:name)
53
+ remapped_columns = remaps.collect {|c| c.first.to_s}.compact
54
+ common = (current & old).sort - remapped_columns
55
+ from_columns = common.collect {|c| "`#{c}`"}
56
+ to_columns = common.collect {|c| "`#{c}`"}
57
+ remaps.each do |remap|
58
+ remap = [remap].flatten
59
+ next if remap.length != 2
60
+ from_columns << remap.first
61
+ to_columns << remap.last
62
+ end
63
+ from_columns_to_s = from_columns.join(', ')
64
+ to_columns_to_s = to_columns.join(', ')
65
+ execute "INSERT INTO #{to}(#{to_columns_to_s}) SELECT #{from_columns_to_s} FROM #{from}"
66
+ end
67
+
68
+ def table_schema_code(table)
69
+ dumper = ActiveRecord::SchemaDumper.send(:new, connection)
70
+ stream = StringIO.new
71
+ dumper.send(:table, table.to_s, stream)
72
+ stream.rewind
73
+ code = stream.read
74
+ end
75
+
76
+ #removes all the indexes
77
+ def disable_indexes(table)
78
+ list = connection.indexes(table)
79
+ list.each do |i|
80
+ remove_index table, :name => i.name
81
+ end
82
+ list
83
+ end
84
+
85
+ #
86
+ def enable_indexes(table, list)
87
+ list.each do |i|
88
+ options = {}
89
+ options[:name] = i.name if i.name
90
+ options[:length] = i.lengths if i.lengths
91
+ options[:unique] = i.unique if i.unique
92
+ add_index table, i.columns, options
93
+ end
94
+ true
95
+ end
96
+
97
+ class PhoneyTable
98
+
99
+ attr_accessor :indexes
100
+
101
+ def initialize(tablename)
102
+ @table = tablename
103
+ @indexes = []
104
+ end
105
+
106
+ def index(columns, options = {})
107
+ new_index = PhoneyIndex.new(@table, columns, options)
108
+ @indexes << new_index unless @indexes.to_a.any? {|i| i == new_index}
109
+ end
110
+
111
+ def indexes; @indexes.to_a.uniq end
112
+ end
113
+
114
+ class PhoneyIndex
115
+
116
+ attr_accessor :columns, :lengths, :name, :unique
117
+
118
+ def initialize(table, cols, options)
119
+ cols = [cols].flatten
120
+ self.columns = cols.collect(&:to_s)
121
+ self.lengths = options[:length]
122
+ self.unique = !!options[:unique]
123
+ self.name = options[:name] || "index_#{table}_on_#{columns.join('_and_')}"
124
+ self.name = "#{columns.join('_')}_idx" if name.length > 64
125
+ end
126
+
127
+ def ==(val)
128
+ columns == val.columns rescue false
129
+ end
130
+ end
131
+ end
132
+ end
@@ -1,3 +1,3 @@
1
1
  module FastChangeTable
2
- VERSION = "0.0.6"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveRecord::Migration do
4
+ before(:each) do
5
+ ActiveRecord::Migration.create_table :my_table, :force => true do |t|
6
+ t.integer :an_integer
7
+ t.string :a_string
8
+ t.string :a_name
9
+ end
10
+ @connection = ActiveRecord::Migration.connection
11
+ end
12
+
13
+ after(:each) do
14
+ ActiveRecord::Migration.drop_table(:my_copied_table) rescue nil
15
+ end
16
+
17
+ describe "initialize table" do
18
+ it "should have expected starting table" do
19
+ @connection.columns("my_table").all? do |c|
20
+ ["id", "an_integer", "a_string", "a_name"].include?(c.name)
21
+ end.should eq(true)
22
+ end
23
+ end
24
+
25
+ describe "#create_table_like" do
26
+ it "should create an identical table" do
27
+ ActiveRecord::Migration.create_table_like(:my_table, :my_copied_table)
28
+
29
+ @connection.columns("my_copied_table").all? do |c|
30
+ ["id", "an_integer", "a_string", "a_name"].include?(c.name.to_s)
31
+ end.should eq(true)
32
+ end
33
+ end
34
+
35
+ describe "#fast_add_indexes, #disable_indexes, #enable_indexes" do
36
+ it "should add index, remove it then put it back" do
37
+ ActiveRecord::Migration.fast_add_indexes :my_table do |t|
38
+ t.index :an_integer, :name => "an_index"
39
+ end
40
+ @connection.indexes("my_table").collect(&:name).include?("an_index").should eq(true)
41
+
42
+ indexes = ActiveRecord::Migration.disable_indexes("my_table")
43
+ @connection.indexes("my_table").collect(&:name).include?("an_index").should eq(false)
44
+
45
+ ActiveRecord::Migration.enable_indexes("my_table", indexes)
46
+ @connection.indexes("my_table").collect(&:name).include?("an_index").should eq(true)
47
+ end
48
+ end
49
+
50
+ describe "#copy_table" do
51
+ it "should copy the records from one table to another" do
52
+ @connection.execute "INSERT my_table (an_integer, a_string, a_name) VALUES (1,'String','Name')"
53
+ ActiveRecord::Migration.create_table_like(:my_table, :my_copied_table)
54
+ ActiveRecord::Migration.add_column(:my_copied_table, :new_column, :string)
55
+ ActiveRecord::Migration.copy_table(:my_table, :my_copied_table, [["'Nothing'", "new_column"]])
56
+ record = @connection.select_all("select * from my_copied_table").first
57
+ record['an_integer'].should eq(1)
58
+ record['a_string'].should eq('String')
59
+ record['a_name'].should eq('Name')
60
+ record['new_column'].should eq('Nothing')
61
+ end
62
+ end
63
+
64
+ describe "#fast_change_table" do
65
+ it "should bring it all together" do
66
+ @connection.execute "INSERT my_table (an_integer, a_string, a_name) VALUES (1,'String','Name')"
67
+ ActiveRecord::Migration.add_index :my_table, :an_integer, :name => "an_index"
68
+ ActiveRecord::Migration.fast_change_table :my_table, :remove_keys => true do |t|
69
+ t.change :an_integer, :integer
70
+ t.change :a_string, :string
71
+ t.change :a_name, :string
72
+ t.string :new_column
73
+ end
74
+ record = @connection.select_all("select * from my_table").first
75
+ record['an_integer'].should eq(1)
76
+ record['a_string'].should eq('String')
77
+ record['a_name'].should eq('Name')
78
+ record['new_column'].should eq(nil)
79
+ @connection.indexes("my_table").empty?.should eq(true)
80
+ end
81
+ end
82
+ end
83
+
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'fast_change_table'
5
+
6
+ RSpec.configure do |config|
7
+ # some (optional) config here
8
+ end
9
+
10
+ ActiveRecord::Base.establish_connection(
11
+ :adapter => "mysql2",
12
+ :database => "fast_change_table_test"
13
+ )
14
+
15
+
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fast_change_table
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
+ - 1
7
8
  - 0
8
9
  - 0
9
- - 6
10
- version: 0.0.6
10
+ version: 1.0.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Grady Griffin
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-01-23 00:00:00 Z
18
+ date: 2012-02-02 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: activerecord
@@ -32,6 +32,34 @@ dependencies:
32
32
  version: "2.3"
33
33
  type: :runtime
34
34
  version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: rspec
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: mysql2
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ type: :development
62
+ version_requirements: *id003
35
63
  description: Uses table duplication to speed up migrations on large tables
36
64
  email:
37
65
  - gradyg@izea.com
@@ -45,12 +73,15 @@ files:
45
73
  - .gitignore
46
74
  - Gemfile
47
75
  - Gemfile.lock
48
- - README
76
+ - README.md
49
77
  - Rakefile
50
78
  - fast_change_table.gemspec
51
79
  - lib/fast_change_table.rb
80
+ - lib/fast_change_table/connection_adapters.rb
81
+ - lib/fast_change_table/fast_change_table.rb
52
82
  - lib/fast_change_table/version.rb
53
- - test/fast_change_table_test.rb
83
+ - spec/fast_change_table_spec.rb
84
+ - spec/spec_helper.rb
54
85
  homepage: https://github.com/moxie/fast_change_table
55
86
  licenses: []
56
87
 
@@ -85,4 +116,5 @@ signing_key:
85
116
  specification_version: 3
86
117
  summary: Faster table changes
87
118
  test_files:
88
- - test/fast_change_table_test.rb
119
+ - spec/fast_change_table_spec.rb
120
+ - spec/spec_helper.rb
data/README DELETED
@@ -1,39 +0,0 @@
1
- Use fast_change_table instead of change_table in your migrations on large tables of data. Uses a duplication pattern to speed things up.
2
-
3
- # Known issues
4
- - Not tested
5
-
6
- uses ordinary change_table syntax but adds two options
7
- - "replace_keys" to remove all indexes; new indexes will be specified
8
- - "disable_keys" to remove indexes and apply them after data load; this is a tremendous performance enhancement for a dbms with fast index creation
9
-
10
- other methods:
11
-
12
- create_table_like(orignal_table, table_to_copy_to)
13
- creates a table with the same structure
14
-
15
- disable_indexes(table)
16
- removes all indexes from a table, returns a list of index objects removed
17
-
18
- enable_indexes(table, list_of_indexes)
19
- restores a list of indexes to a table
20
-
21
- fast_add_indexes(table, &block)
22
- allows you to pass a block to add indexes. For mysql creates specified indexes in one statement; allows the data to be scanned once.
23
- example
24
-
25
- fast_add_indexes :sometable do |t|
26
- t.index :some_column
27
- t.index [:some_other_column, :column_three], :name => "a_multicolumn_index"
28
- end
29
-
30
- copy_table(from_table, to_table, remaps = [])
31
- copies rows from one table into another. this probably only works with Mysql.
32
- by default copies data from column of from_table to to_table of same name.
33
- will not copy data where there is no corresponding column.
34
- the remaps argument can be supplied to tell copy table how to handle unmatched columns or override this behavior
35
- examples
36
-
37
- copy_table(old_users_without_email_hash, new_table, ['MD5(email)', 'email_hash'])
38
-
39
- copy_table(old_users_without_total, new_table, ['sum(payments)', 'total_payments'])
@@ -1 +0,0 @@
1
- require 'test/unit'