cc1  v2.1
CC1 source code docs
 All Classes Namespaces Files Functions Variables Pages
mysql_migrate.py
Go to the documentation of this file.
1 # -*- coding: utf-8 -*-
2 # @COPYRIGHT_begin
3 #
4 # Copyright [2010-2014] Institute of Nuclear Physics PAN, Krakow, Poland
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18 # @COPYRIGHT_end
19 
20 # -*- coding: utf-8 -*-
21 from datetime import datetime
22 from django.core.management.base import BaseCommand
23 import sys
24 import traceback
25 from django.conf import settings
26 from django.db import connections
27 from django.db import transaction
28 from optparse import make_option
29 
30 
31 tables = {
32  'cluster': {
33  'name': 'clm_cluster'
34  },
35  'message': {
36  'name': 'clm_message',
37  },
38  'news': {
39  'name': 'clm_news',
40  },
41  'user': {
42  'name': 'clm_user',
43  },
44  'user_group': {
45  'name': 'clm_usergroup',
46  },
47 }
48 
49 MCURSOR = None
50 PCURSOR = None
51 
52 
53 def mselect(query):
54  # print "MYSQL: %s" % query
55  MCURSOR.execute(query)
56  return MCURSOR.fetchall()
57 
58 
59 def pinsert(query):
60  # print "POSTGRESQL: %s" % query
61  PCURSOR.execute(query)
62 
63 
64 def pselect(query):
65  # print "POSTGRESQL: %s" % query
66  PCURSOR.execute(query)
67  return PCURSOR.fetchall()
68 
69 
70 def prepare(row):
71  nrow = []
72  for i in row:
73  if i is None:
74  nrow.append('NULL')
75  elif type(i) == long:
76  nrow.append("%d" % i)
77  else:
78  #nrow.append("E'%s'" % str(i).replace("'", "\\'"))
79  nrow.append("E'%s'" % str(i).replace("'", "\\'").decode('utf-8'))
80  return ','.join(nrow)
81 
82 
83 class Command(BaseCommand):
84  args = ''
85  help = 'Run migration from version 1.7'
86  option_list = BaseCommand.option_list + (
87  make_option('--name',
88  action='store',
89  dest='name',
90  default='clm',
91  help='MySQL database name'),
92  make_option('--password',
93  action='store',
94  dest='password',
95  default='cc1',
96  help='MySQL database password'),
97  make_option('--user',
98  action='store',
99  dest='user',
100  default='cc1',
101  help='MySQL database user'),
102  make_option('--host',
103  action='store',
104  dest='host',
105  default='127.0.0.1',
106  help='MySQL database host'),
107  make_option('--port',
108  action='store',
109  dest='port',
110  default='3306',
111  help='MySQL database port'),
112  )
113 
114  def handle(self, *args, **options):
115  sys.stdout.write('Run migration at: %s\n' % datetime.now())
116 
117  settings.DATABASES.update({
118  'mysql': {
119  'ENGINE': 'django.db.backends.mysql',
120  'NAME': options['name'],
121  'USER': options['user'],
122  'PASSWORD': options['password'],
123  'HOST': options['host'],
124  'PORT': options['port'],
125  }
126  })
127  try:
128  global MCURSOR
129  MCURSOR = connections['mysql'].cursor()
130  except Exception, e:
131  print 'Cannot connect to MySQL database: %s' % e
132  sys.exit(1)
133 
134  try:
135  global PCURSOR
136  PCURSOR = connections['default'].cursor()
137  except Exception, e:
138  print 'Cannot connect to PostgresSQL database: %s' % e
139  sys.exit(1)
140 
141  with transaction.commit_manually():
142  try:
143  # migrate table from dictionary
144  for table, desc in tables.iteritems():
145  print 'Migrate table %s' % table
146  new_table = desc.get('name') or 'cm_%s' % table
147  old_cols = [i[0] for i in mselect("describe %s;" % table)]
148  for name in desc.get('drop_column', []):
149  old_cols.remove(name)
150  new_cols = old_cols[:]
151  rename_columns = desc.get('rename_columns')
152  if rename_columns:
153  for i, c in enumerate(old_cols):
154  if c in rename_columns:
155  new_cols[i] = rename_columns[c]
156 
157  values = mselect('select %s from %s;' % (','.join(old_cols), table))
158 
159  for row in values:
160  print row
161  pinsert("insert into %s(%s) values (%s);" % (new_table, ','.join(new_cols), prepare(row)))
162 
163  seq_id_table = new_table + '_id_seq'
164  if pselect("select column_name from information_schema.columns where table_name='%s' and column_name='id';" % (new_table)):
165  pinsert("select setval('%s', (select max(id) from %s));" % (seq_id_table, new_table))
166  # GROUPS
167  values = mselect("select id,leader_id,name,group.desc from clm.group;")
168  for row in values:
169  pinsert('insert into clm_group (id,leader_id,name,"desc") values(%s);' % prepare(row))
170  pinsert("select setval('%s', (select max(id) from %s));" % ('clm_group_id_seq', 'clm_group'))
171  # KEYS
172  values = mselect("select id,user_id,name,fingerprint,data,creation_date from clm.key;")
173  for row in values:
174  pinsert(
175  "insert into clm_key (id,user_id,name,fingerprint,data,creation_date) values(%s);" % prepare(
176  row))
177  pinsert("select setval('%s', (select max(id) from %s));" % ('clm_key_id_seq', 'clm_key'))
178  transaction.commit()
179  print "Migration complete"
180  except:
181  traceback.print_exc()
182 
183  transaction.rollback()
184