#343488: SQL error in migration script (depends on a new release of yams and lgc)
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Tue, 02 Jun 2009 18:14:38 +0200
changeset 2019 399a930e10ef
parent 2018 5abd684d5b9d
child 2021 1eb93a80c127
#343488: SQL error in migration script (depends on a new release of yams and lgc)
debian/control
server/schemahooks.py
--- a/debian/control	Sun May 31 19:53:41 2009 +0200
+++ b/debian/control	Tue Jun 02 18:14:38 2009 +0200
@@ -75,7 +75,7 @@
 Package: cubicweb-common
 Architecture: all
 XB-Python-Version: ${python:Versions}
-Depends: ${python:Depends}, graphviz, gettext, python-logilab-mtconverter (>= 0.6.0), python-logilab-common (>= 0.40.0), python-yams (>= 0.22.0), python-rql (>= 0.22.0)
+Depends: ${python:Depends}, graphviz, gettext, python-logilab-mtconverter (>= 0.6.0), python-logilab-common (>= 0.41.0), python-yams (>= 0.23.0), python-rql (>= 0.22.0)
 Recommends: python-simpletal (>= 4.0), python-lxml
 Conflicts: cubicweb-core
 Replaces: cubicweb-core
--- a/server/schemahooks.py	Sun May 31 19:53:41 2009 +0200
+++ b/server/schemahooks.py	Tue Jun 02 18:14:38 2009 +0200
@@ -14,7 +14,7 @@
 
 from yams.schema import BASE_TYPES
 from yams.buildobjs import EntityType, RelationType, RelationDefinition
-from yams.schema2sql import eschema2sql, rschema2sql, _type_from_constraints
+from yams.schema2sql import eschema2sql, rschema2sql, type_from_constraints
 
 from cubicweb import ValidationError, RepositoryError
 from cubicweb.server import schemaserial as ss
@@ -393,8 +393,8 @@
                                   constraints=constraints,
                                   eid=entity.eid)
         sysource = session.pool.source('system')
-        attrtype = _type_from_constraints(sysource.dbhelper, rdef.object,
-                                          constraints)
+        attrtype = type_from_constraints(sysource.dbhelper, rdef.object,
+                                         constraints)
         # XXX should be moved somehow into lgc.adbh: sqlite doesn't support to
         # add a new column with UNIQUE, it should be added after the ALTER TABLE
         # using ADD INDEX
@@ -423,20 +423,6 @@
             except Exception, ex:
                 self.error('error while creating index for %s.%s: %s',
                            table, column, ex)
-        # postgres doesn't implement, so do it in two times
-        # ALTER TABLE %s ADD COLUMN %s %s SET DEFAULT %s
-        if default is not None:
-            if isinstance(default, unicode):
-                default = default.encode(sysource.encoding)
-            try:
-                session.system_sql('ALTER TABLE %s ALTER COLUMN %s SET DEFAULT '
-                                   '%%(default)s' % (table, column),
-                                   {'default': default})
-            except Exception, ex:
-                # not supported by sqlite for instance
-                self.error('error while altering table %s: %s', table, ex)
-            session.system_sql('UPDATE %s SET %s=%%(default)s' % (table, column),
-                               {'default': default})
         AddErdefOp(session, rdef)
 
 def after_add_efrdef(session, entity):
@@ -567,28 +553,28 @@
     rschema = values = None # make pylint happy
 
     def precommit_event(self):
+        etype = self.kobj[0]
+        table = SQL_PREFIX + etype
+        column = SQL_PREFIX + self.rschema.type
         if 'indexed' in self.values:
             sysource = self.session.pool.source('system')
-            etype, rtype = self.kobj[0], self.rschema.type
-            table = SQL_PREFIX + etype
-            column = SQL_PREFIX + rtype
             if self.values['indexed']:
                 sysource.create_index(self.session, table, column)
             else:
                 sysource.drop_index(self.session, table, column)
         if 'cardinality' in self.values and self.rschema.is_final():
-            if self.session.pool.source('system').dbdriver == 'sqlite':
+            adbh = self.session.pool.source('system').dbhelper
+            if not adbh.alter_column_support:
                 # not supported (and NOT NULL not set by yams in that case, so
                 # no worry)
                 return
-            sqlexec = self.session.system_sql
-            etype, rtype = self.kobj[0], self.rschema.type
-            if self.values['cardinality'][0] == '1':
-                cmd = 'SET'
-            else:
-                cmd = 'DROP'
-            sqlexec('ALTER TABLE %s ALTER COLUMN %s %s NOT NULL' % (
-                SQL_PREFIX + etype, SQL_PREFIX + rtype, cmd))
+            atype = self.rschema.objects(etype)[0]
+            constraints = self.rschema.rproperty(etype, atype, 'constraints')
+            coltype = type_from_constraints(adbh, atype, constraints,
+                                            creating=False)
+            sql = adbh.sql_set_null_allowed(table, column, coltype,
+                                            self.values['cardinality'][0] != '1')
+            self.session.system_sql(sql)
 
     def commit_event(self):
         # structure should be clean, not need to remove entity's relations
@@ -726,9 +712,13 @@
         # alter the physical schema on size constraint changes
         if self._cstr.type() == 'SizeConstraint' and (
             self.cstr is None or self.cstr.max != self._cstr.max):
+            adbh = self.session.pool.source('system').dbhelper
+            card = rtype.rproperty(subjtype, objtype, 'cardinality')
+            coltype = type_from_constraints(adbh, objtype, [self._cstr],
+                                            creating=False)
+            sql = adbh.sql_change_col_type(table, column, coltype, card != '1')
             try:
-                session.system_sql('ALTER TABLE %s ALTER COLUMN %s TYPE VARCHAR(%s)'
-                                   % (table, column, self._cstr.max))
+                session.system_sql(sql)
                 self.info('altered column %s of table %s: now VARCHAR(%s)',
                           column, table, self._cstr.max)
             except Exception, ex:
@@ -741,7 +731,7 @@
     def commit_event(self):
         if self.cancelled:
             return
-        # in-place removing
+        # in-place modification
         if not self.cstr is None:
             self.constraints.remove(self.cstr)
         self.constraints.append(self._cstr)