annotate rhodecode/lib/dbmigrate/migrate/versioning/genmodel.py @ 833:9753e0907827 beta

added dbmigrate package, added model changes moved out upgrade db command to that package
author Marcin Kuzminski <marcin@python-works.com>
date Sat, 11 Dec 2010 01:54:12 +0100
parents
children 08d2dcd71666
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
833
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
1 """
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
2 Code to generate a Python model from a database or differences
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
3 between a model and database.
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
4
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
5 Some of this is borrowed heavily from the AutoCode project at:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
6 http://code.google.com/p/sqlautocode/
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
7 """
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
8
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
9 import sys
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
10 import logging
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
11
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
12 import sqlalchemy
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
13
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
14 import migrate
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
15 import migrate.changeset
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
16
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
17
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
18 log = logging.getLogger(__name__)
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
19 HEADER = """
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
20 ## File autogenerated by genmodel.py
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
21
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
22 from sqlalchemy import *
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
23 meta = MetaData()
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
24 """
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
25
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
26 DECLARATIVE_HEADER = """
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
27 ## File autogenerated by genmodel.py
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
28
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
29 from sqlalchemy import *
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
30 from sqlalchemy.ext import declarative
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
31
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
32 Base = declarative.declarative_base()
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
33 """
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
34
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
35
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
36 class ModelGenerator(object):
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
37
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
38 def __init__(self, diff, engine, declarative=False):
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
39 self.diff = diff
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
40 self.engine = engine
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
41 self.declarative = declarative
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
42
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
43 def column_repr(self, col):
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
44 kwarg = []
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
45 if col.key != col.name:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
46 kwarg.append('key')
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
47 if col.primary_key:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
48 col.primary_key = True # otherwise it dumps it as 1
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
49 kwarg.append('primary_key')
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
50 if not col.nullable:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
51 kwarg.append('nullable')
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
52 if col.onupdate:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
53 kwarg.append('onupdate')
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
54 if col.default:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
55 if col.primary_key:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
56 # I found that PostgreSQL automatically creates a
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
57 # default value for the sequence, but let's not show
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
58 # that.
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
59 pass
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
60 else:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
61 kwarg.append('default')
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
62 ks = ', '.join('%s=%r' % (k, getattr(col, k)) for k in kwarg)
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
63
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
64 # crs: not sure if this is good idea, but it gets rid of extra
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
65 # u''
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
66 name = col.name.encode('utf8')
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
67
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
68 type_ = col.type
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
69 for cls in col.type.__class__.__mro__:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
70 if cls.__module__ == 'sqlalchemy.types' and \
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
71 not cls.__name__.isupper():
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
72 if cls is not type_.__class__:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
73 type_ = cls()
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
74 break
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
75
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
76 data = {
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
77 'name': name,
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
78 'type': type_,
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
79 'constraints': ', '.join([repr(cn) for cn in col.constraints]),
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
80 'args': ks and ks or ''}
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
81
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
82 if data['constraints']:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
83 if data['args']:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
84 data['args'] = ',' + data['args']
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
85
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
86 if data['constraints'] or data['args']:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
87 data['maybeComma'] = ','
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
88 else:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
89 data['maybeComma'] = ''
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
90
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
91 commonStuff = """ %(maybeComma)s %(constraints)s %(args)s)""" % data
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
92 commonStuff = commonStuff.strip()
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
93 data['commonStuff'] = commonStuff
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
94 if self.declarative:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
95 return """%(name)s = Column(%(type)r%(commonStuff)s""" % data
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
96 else:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
97 return """Column(%(name)r, %(type)r%(commonStuff)s""" % data
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
98
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
99 def getTableDefn(self, table):
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
100 out = []
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
101 tableName = table.name
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
102 if self.declarative:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
103 out.append("class %(table)s(Base):" % {'table': tableName})
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
104 out.append(" __tablename__ = '%(table)s'" % {'table': tableName})
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
105 for col in table.columns:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
106 out.append(" %s" % self.column_repr(col))
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
107 else:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
108 out.append("%(table)s = Table('%(table)s', meta," % \
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
109 {'table': tableName})
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
110 for col in table.columns:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
111 out.append(" %s," % self.column_repr(col))
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
112 out.append(")")
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
113 return out
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
114
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
115 def _get_tables(self,missingA=False,missingB=False,modified=False):
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
116 to_process = []
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
117 for bool_,names,metadata in (
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
118 (missingA,self.diff.tables_missing_from_A,self.diff.metadataB),
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
119 (missingB,self.diff.tables_missing_from_B,self.diff.metadataA),
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
120 (modified,self.diff.tables_different,self.diff.metadataA),
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
121 ):
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
122 if bool_:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
123 for name in names:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
124 yield metadata.tables.get(name)
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
125
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
126 def toPython(self):
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
127 """Assume database is current and model is empty."""
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
128 out = []
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
129 if self.declarative:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
130 out.append(DECLARATIVE_HEADER)
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
131 else:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
132 out.append(HEADER)
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
133 out.append("")
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
134 for table in self._get_tables(missingA=True):
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
135 out.extend(self.getTableDefn(table))
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
136 out.append("")
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
137 return '\n'.join(out)
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
138
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
139 def toUpgradeDowngradePython(self, indent=' '):
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
140 ''' Assume model is most current and database is out-of-date. '''
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
141 decls = ['from migrate.changeset import schema',
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
142 'meta = MetaData()']
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
143 for table in self._get_tables(
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
144 missingA=True,missingB=True,modified=True
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
145 ):
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
146 decls.extend(self.getTableDefn(table))
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
147
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
148 upgradeCommands, downgradeCommands = [], []
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
149 for tableName in self.diff.tables_missing_from_A:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
150 upgradeCommands.append("%(table)s.drop()" % {'table': tableName})
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
151 downgradeCommands.append("%(table)s.create()" % \
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
152 {'table': tableName})
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
153 for tableName in self.diff.tables_missing_from_B:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
154 upgradeCommands.append("%(table)s.create()" % {'table': tableName})
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
155 downgradeCommands.append("%(table)s.drop()" % {'table': tableName})
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
156
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
157 for tableName in self.diff.tables_different:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
158 dbTable = self.diff.metadataB.tables[tableName]
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
159 missingInDatabase, missingInModel, diffDecl = \
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
160 self.diff.colDiffs[tableName]
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
161 for col in missingInDatabase:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
162 upgradeCommands.append('%s.columns[%r].create()' % (
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
163 modelTable, col.name))
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
164 downgradeCommands.append('%s.columns[%r].drop()' % (
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
165 modelTable, col.name))
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
166 for col in missingInModel:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
167 upgradeCommands.append('%s.columns[%r].drop()' % (
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
168 modelTable, col.name))
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
169 downgradeCommands.append('%s.columns[%r].create()' % (
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
170 modelTable, col.name))
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
171 for modelCol, databaseCol, modelDecl, databaseDecl in diffDecl:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
172 upgradeCommands.append(
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
173 'assert False, "Can\'t alter columns: %s:%s=>%s"',
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
174 modelTable, modelCol.name, databaseCol.name)
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
175 downgradeCommands.append(
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
176 'assert False, "Can\'t alter columns: %s:%s=>%s"',
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
177 modelTable, modelCol.name, databaseCol.name)
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
178 pre_command = ' meta.bind = migrate_engine'
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
179
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
180 return (
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
181 '\n'.join(decls),
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
182 '\n'.join([pre_command] + ['%s%s' % (indent, line) for line in upgradeCommands]),
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
183 '\n'.join([pre_command] + ['%s%s' % (indent, line) for line in downgradeCommands]))
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
184
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
185 def _db_can_handle_this_change(self,td):
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
186 if (td.columns_missing_from_B
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
187 and not td.columns_missing_from_A
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
188 and not td.columns_different):
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
189 # Even sqlite can handle this.
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
190 return True
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
191 else:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
192 return not self.engine.url.drivername.startswith('sqlite')
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
193
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
194 def applyModel(self):
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
195 """Apply model to current database."""
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
196
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
197 meta = sqlalchemy.MetaData(self.engine)
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
198
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
199 for table in self._get_tables(missingA=True):
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
200 table = table.tometadata(meta)
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
201 table.drop()
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
202 for table in self._get_tables(missingB=True):
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
203 table = table.tometadata(meta)
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
204 table.create()
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
205 for modelTable in self._get_tables(modified=True):
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
206 tableName = modelTable.name
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
207 modelTable = modelTable.tometadata(meta)
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
208 dbTable = self.diff.metadataB.tables[tableName]
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
209
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
210 td = self.diff.tables_different[tableName]
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
211
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
212 if self._db_can_handle_this_change(td):
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
213
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
214 for col in td.columns_missing_from_B:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
215 modelTable.columns[col].create()
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
216 for col in td.columns_missing_from_A:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
217 dbTable.columns[col].drop()
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
218 # XXX handle column changes here.
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
219 else:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
220 # Sqlite doesn't support drop column, so you have to
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
221 # do more: create temp table, copy data to it, drop
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
222 # old table, create new table, copy data back.
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
223 #
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
224 # I wonder if this is guaranteed to be unique?
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
225 tempName = '_temp_%s' % modelTable.name
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
226
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
227 def getCopyStatement():
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
228 preparer = self.engine.dialect.preparer
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
229 commonCols = []
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
230 for modelCol in modelTable.columns:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
231 if modelCol.name in dbTable.columns:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
232 commonCols.append(modelCol.name)
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
233 commonColsStr = ', '.join(commonCols)
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
234 return 'INSERT INTO %s (%s) SELECT %s FROM %s' % \
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
235 (tableName, commonColsStr, commonColsStr, tempName)
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
236
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
237 # Move the data in one transaction, so that we don't
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
238 # leave the database in a nasty state.
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
239 connection = self.engine.connect()
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
240 trans = connection.begin()
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
241 try:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
242 connection.execute(
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
243 'CREATE TEMPORARY TABLE %s as SELECT * from %s' % \
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
244 (tempName, modelTable.name))
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
245 # make sure the drop takes place inside our
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
246 # transaction with the bind parameter
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
247 modelTable.drop(bind=connection)
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
248 modelTable.create(bind=connection)
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
249 connection.execute(getCopyStatement())
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
250 connection.execute('DROP TABLE %s' % tempName)
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
251 trans.commit()
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
252 except:
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
253 trans.rollback()
9753e0907827 added dbmigrate package, added model changes
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
254 raise