Project

General

Profile

Defect #10537 » convert.rake

M T, 2012-03-24 03:13

 
1
#
2
# Convert/transfer data from production => development.    This facilitates
3
# a conversion one database adapter type to another (say postgres -> mysql )
4
#
5
# WARNING 1: this script deletes all development data and replaces it with
6
#                     production data
7
#
8
# WARNING 2: This script assumes it is the only user updating either database.
9
#                     Database integrity could be corrupted if other users where 
10
#                     writing to the databases.
11
#
12
# Usage:  rake db:convert:prod2dev
13
#
14
# It assumes the development database has a schema identical to the production 
15
# database, but will delete any data before importing the production data
16
#
17
# A couple of refinements added to Rama's script by M.Taylor:
18
#    * Suppress single-table inheritance behaviour for tables containing a column named "type"
19
#    * Do not copy column id if the table doesn't have one.
20
#
21
# A couple of the outer loops evolved from 
22
#    http://snippets.dzone.com/posts/show/3393
23
#
24
# For further instructions see 
25
#    http://myutil.com/2008/8/31/rake-task-transfer-rails-database-mysql-to-postgres
26
#
27
# The master repository for this script is at github:
28
#    http://github.com/face/rails_db_convert_using_adapters/tree/master
29
#
30
#
31
# Author: Rama McIntosh
32
#         Matson Systems, Inc.
33
#         http://www.matsonsystems.com
34
#
35
# This rake task is released under this BSD license:
36
#
37
# Copyright (c) 2008, Matson Systems, Inc. All rights reserved.
38
# 
39
# Redistribution and use in source and binary forms, with or without
40
# modification, are permitted provided that the following conditions
41
# are met:
42
# 
43
# * Redistributions of source code must retain the above copyright
44
#   notice, this list of conditions and the following disclaimer.
45
# * Redistributions in binary form must reproduce the above copyright
46
#   notice, this list of conditions and the following disclaimer in the
47
#   documentation and/or other materials provided with the distribution.
48
# * Neither the name of Matson Systems, Inc. nor the names of its
49
#   contributors may be used to endorse or promote products derived
50
#   from this software without specific prior written permission.
51
#
52
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
53
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
54
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
55
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
56
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
57
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
58
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
59
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
60
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
62
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
63
# POSSIBILITY OF SUCH DAMAGE.
64

    
65
# PAGE_SIZE is the number of rows updated in a single transaction.
66
# This facilitates tables where the number of rows exceeds the systems
67
# memory
68
PAGE_SIZE=10000
69

    
70
namespace :db do
71
  namespace :convert do    
72
    desc 'Convert/import production data to development.   DANGER Deletes all data in the development database.   Assumes both schemas are already migrated.'
73
    task :prod2dev => :environment do
74

    
75
      # We need unique classes so ActiveRecord can hash different connections
76
      # We do not want to use the real Model classes because any business
77
      # rules will likely get in the way of a database transfer
78
      class ProductionModelClass < ActiveRecord::Base
79
        self.inheritance_column = :_type_disabled
80
      end
81
      class DevelopmentModelClass < ActiveRecord::Base
82
        self.inheritance_column = :_type_disabled
83
      end
84

    
85
      skip_tables = ["schema_info", "schema_migrations"]
86
      
87
      # Generate a list of all tables needing conversion
88
      table_list = (ActiveRecord::Base.connection.tables - skip_tables).sort
89
    
90
      # Use this line to convert just a specific list of tables   
91
      # table_list = ["custom_fields_trackers","custom_fields_projects","groups_users","projects_trackers"]
92
      
93
      ActiveRecord::Base.establish_connection(:production)
94

    
95
      table_list.each do |table_name|
96
 
97
        ProductionModelClass.set_table_name(table_name)
98
        DevelopmentModelClass.set_table_name(table_name)
99
        DevelopmentModelClass.establish_connection(:development)
100
        DevelopmentModelClass.reset_column_information
101
        ProductionModelClass.reset_column_information
102
        DevelopmentModelClass.record_timestamps = false
103

    
104
        # Page through the data in case the table is too large to fit in RAM
105
        offset = count = 0;
106
        print "Converting #{table_name}..."; STDOUT.flush
107
        # First, delete any old dev data
108
        DevelopmentModelClass.delete_all
109
        while ((models = ProductionModelClass.find(:all, 
110
            :offset=>offset, :limit=>PAGE_SIZE)).size > 0)
111

    
112
          count += models.size
113
          offset += PAGE_SIZE
114

    
115
          # Now, write out the prod data to the dev db
116
          DevelopmentModelClass.transaction do
117
            models.each do |model|
118
              new_model = DevelopmentModelClass.new(model.attributes)
119
              if (model.attributes.has_key?('id'))
120
                new_model.id = model.id
121
              end
122
              new_model.save(false)
123
            end
124
          end
125
        end
126
        print "#{count} records converted\n"
127
      end
128
    end
129
  end
130
end
(2-2/3)