server/schemahooks.py
changeset 1251 af40e615dc89
parent 0 b97547f5f1fa
child 1263 01152fffd593
--- a/server/schemahooks.py	Mon Apr 06 16:11:38 2009 +0200
+++ b/server/schemahooks.py	Mon Apr 06 16:18:46 2009 +0200
@@ -6,7 +6,7 @@
 checking for schema consistency is done in hooks.py
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
@@ -17,6 +17,7 @@
 
 from cubicweb import ValidationError, RepositoryError
 from cubicweb.server import schemaserial as ss
+from cubicweb.server.sqlutils import SQL_PREFIX
 from cubicweb.server.pool import Operation, SingleLastOperation, PreCommitOperation
 from cubicweb.server.hookhelper import (entity_attr, entity_name,
                                      check_internal_entity)
@@ -44,19 +45,22 @@
 
 def add_inline_relation_column(session, etype, rtype):
     """add necessary column and index for an inlined relation"""
+    table = SQL_PREFIX + etype
+    column = SQL_PREFIX + rtype
     try:
         session.system_sql(str('ALTER TABLE %s ADD COLUMN %s integer'
-                               % (etype, rtype)))
-        session.info('added column %s to table %s', rtype, etype)
+                               % (table, column)))
+        session.info('added column %s to table %s', column, table)
     except:
         # silent exception here, if this error has not been raised because the 
         # column already exists, index creation will fail anyway
-        session.exception('error while adding column %s to table %s', etype, rtype)
+        session.exception('error while adding column %s to table %s',
+                          table, column)
     # create index before alter table which may expectingly fail during test
     # (sqlite) while index creation should never fail (test for index existence
     # is done by the dbhelper)
-    session.pool.source('system').create_index(session, etype, rtype)
-    session.info('added index on %s(%s)', etype, rtype)
+    session.pool.source('system').create_index(session, table, column)
+    session.info('added index on %s(%s)', table, column)
     session.add_query_data('createdattrs', '%s.%s' % (etype, rtype))
 
 
@@ -148,7 +152,7 @@
     name = check_internal_entity(session, eid, CORE_ETYPES)
     # delete every entities of this type
     session.unsafe_execute('DELETE %s X' % name)
-    DropTableOp(session, table=name)
+    DropTableOp(session, table=SQL_PREFIX + name)
     DeleteEETypeOp(session, name)
 
 def after_del_eetype(session, eid):
@@ -223,7 +227,8 @@
                        'R eid %%(x)s, X from_entity E, E name %%(name)s'
                        % rdeftype, {'x': rteid, 'name': str(subjschema)})
         if rset[0][0] == 0 and not subjschema.eid in pendings:
-            DropColumnOp(session, table=subjschema.type, column=rschema.type)
+            DropColumnOp(session, table=SQL_PREFIX + subjschema.type,
+                         column=SQL_PREFIX + rschema.type)
     elif lastrel:
         DropTableOp(session, table='%s_relation' % rschema.type)
     # if this is the last instance, drop associated relation type
@@ -270,7 +275,8 @@
     eschema = schema.add_entity_type(etype)
     eschema.set_default_groups()
     # generate table sql and rql to add metadata
-    tablesql = eschema2sql(session.pool.source('system').dbhelper, eschema)
+    tablesql = eschema2sql(session.pool.source('system').dbhelper, eschema,
+                           prefix=SQL_PREFIX)
     relrqls = []
     for rtype in ('is', 'is_instance_of', 'creation_date', 'modification_date',
                   'created_by', 'owned_by'):
@@ -393,22 +399,24 @@
             extra_unique_index = False
         # added some str() wrapping query since some backend (eg psycopg) don't
         # allow unicode queries
+        table = SQL_PREFIX + subj
+        column = SQL_PREFIX + rtype
         try:
             session.system_sql(str('ALTER TABLE %s ADD COLUMN %s %s'
-                                   % (subj, rtype, attrtype)))
-            self.info('added column %s to table %s', rtype, subj)
+                                   % (table, column, attrtype)))
+            self.info('added column %s to table %s', table, column)
         except Exception, ex:
             # the column probably already exists. this occurs when
             # the entity's type has just been added or if the column
             # has not been previously dropped
-            self.error('error while altering table %s: %s', subj, ex)
+            self.error('error while altering table %s: %s', table, ex)
         if extra_unique_index or entity.indexed:
             try:
-                sysource.create_index(session, subj, rtype,
+                sysource.create_index(session, table, column,
                                       unique=extra_unique_index)
             except Exception, ex:
                 self.error('error while creating index for %s.%s: %s',
-                           subj, rtype, ex)
+                           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:
@@ -416,12 +424,12 @@
                 default = default.encode(sysource.encoding)
             try:
                 session.system_sql('ALTER TABLE %s ALTER COLUMN %s SET DEFAULT '
-                                   '%%(default)s' % (subj, rtype),
+                                   '%%(default)s' % (table, column),
                                    {'default': default})
             except Exception, ex:
                 # not supported by sqlite for instance
-                self.error('error while altering table %s: %s', subj, ex)
-            session.system_sql('UPDATE %s SET %s=%%(default)s' % (subj, rtype),
+                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)
 
@@ -534,7 +542,8 @@
     def precommit_event(self):
         # we need sql to operate physical changes on the system database
         sqlexec = self.session.system_sql
-        sqlexec('ALTER TABLE %s RENAME TO %s' % (self.oldname, self.newname))
+        sqlexec('ALTER TABLE %s%s RENAME TO %s%s' % (SQL_PREFIX, self.oldname,
+                                                     SQL_PREFIX, self.newname))
         self.info('renamed table %s to %s', self.oldname, self.newname)
         sqlexec('UPDATE entities SET type=%s WHERE type=%s',
                 (self.newname, self.oldname))
@@ -551,7 +560,9 @@
     def precommit_event(self):
         if 'indexed' in self.values:
             sysource = self.session.pool.source('system')
-            table, column = self.kobj[0], self.rschema.type
+            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:
@@ -561,6 +572,7 @@
         # structure should be clean, not need to remove entity's relations
         # at this point
         self.rschema._rproperties[self.kobj].update(self.values)
+
     
 def after_update_erdef(session, entity):
     desttype = entity.to_entity[0].name
@@ -593,6 +605,7 @@
         # inlined changed, make necessary physical changes!
         sqlexec = self.session.system_sql
         rtype = rschema.type
+        eidcolumn = SQL_PREFIX + 'eid'
         if not inlined:
             # need to create the relation if it has not been already done by another
             # event of the same transaction
@@ -604,12 +617,15 @@
                         sqlexec(sql)
                 session.add_query_data('createdtables', rschema.type)
             # copy existant data
+            column = SQL_PREFIX + rtype
             for etype in rschema.subjects():
-                sqlexec('INSERT INTO %s_relation SELECT eid, %s FROM %s WHERE NOT %s IS NULL'
-                        % (rtype, rtype, etype, rtype))
+                table = SQL_PREFIX + str(etype)
+                sqlexec('INSERT INTO %s_relation SELECT %s, %s FROM %s WHERE NOT %s IS NULL'
+                        % (rtype, eidcolumn, column, table, column))
             # drop existant columns
             for etype in rschema.subjects():
-                DropColumnOp(session, table=str(etype), column=rtype)
+                DropColumnOp(session, table=SQL_PREFIX + str(etype),
+                             column=SQL_PREFIX + rtype)
         else:
             for etype in rschema.subjects():
                 try:
@@ -625,13 +641,15 @@
                 #        'FROM %(rtype)s_relation '
                 #        'WHERE %(etype)s.eid=%(rtype)s_relation.eid_from'
                 #        % locals())
-                cursor = sqlexec('SELECT eid_from, eid_to FROM %(etype)s, '
-                                 '%(rtype)s_relation WHERE %(etype)s.eid='
+                table = SQL_PREFIX + str(etype)
+                cursor = sqlexec('SELECT eid_from, eid_to FROM %(table)s, '
+                                 '%(rtype)s_relation WHERE %(table)s.%(eidcolumn)s='
                                  '%(rtype)s_relation.eid_from' % locals())
                 args = [{'val': eid_to, 'x': eid} for eid, eid_to in cursor.fetchall()]
                 if args:
-                    cursor.executemany('UPDATE %s SET %s=%%(val)s WHERE eid=%%(x)s'
-                                       % (etype, rtype), args)
+                    column = SQL_PREFIX + rtype
+                    cursor.executemany('UPDATE %s SET %s=%%(val)s WHERE %s=%%(x)s'
+                                       % (table, column, eidcolumn), args)
                 # drop existant table
                 DropTableOp(session, table='%s_relation' % rtype)
 
@@ -677,20 +695,22 @@
         self.cstr = rtype.constraint_by_type(subjtype, objtype, cstrtype)
         self._cstr = CONSTRAINTS[cstrtype].deserialize(self.entity.value)
         self._cstr.eid = self.entity.eid
+        table = SQL_PREFIX + str(subjtype)
+        column = SQL_PREFIX + str(rtype)
         # 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):
             try:
                 session.system_sql('ALTER TABLE %s ALTER COLUMN %s TYPE VARCHAR(%s)'
-                                   % (subjtype, rtype, self._cstr.max))
+                                   % (table, column, self._cstr.max))
                 self.info('altered column %s of table %s: now VARCHAR(%s)',
-                          rtype, subjtype, self._cstr.max)
+                          column, table, self._cstr.max)
             except Exception, ex:
                 # not supported by sqlite for instance
-                self.error('error while altering table %s: %s', subjtype, ex)
+                self.error('error while altering table %s: %s', table, ex)
         elif cstrtype == 'UniqueConstraint':
             session.pool.source('system').create_index(
-                self.session, str(subjtype), str(rtype), unique=True)
+                self.session, table, column, unique=True)
         
     def commit_event(self):
         if self.cancelled:
@@ -700,32 +720,35 @@
             self.constraints.remove(self.cstr)
         self.constraints.append(self._cstr)
 
+
 def after_add_econstraint(session, entity):
     ConstraintOp(session, entity=entity)
 
 def after_update_econstraint(session, entity):
     ConstraintOp(session, entity=entity)
 
+
 class DelConstraintOp(ConstraintOp):
     """actually remove a constraint of a relation definition"""
     
     def precommit_event(self):
         self.prepare_constraints(self.rtype, self.subjtype, self.objtype)
         cstrtype = self.cstr.type()
+        table = SQL_PREFIX + str(self.subjtype)
+        column = SQL_PREFIX + str(self.rtype)
         # alter the physical schema on size/unique constraint changes
         if cstrtype == 'SizeConstraint':
             try:
                 self.session.system_sql('ALTER TABLE %s ALTER COLUMN %s TYPE TEXT'
-                                        % (self.subjtype, self.rtype))
+                                        % (table, column))
                 self.info('altered column %s of table %s: now TEXT', 
-                          self.rtype,  self.subjtype)
+                          column, table)
             except Exception, ex:
                 # not supported by sqlite for instance
-                self.error('error while altering table %s: %s', 
-                           self.subjtype, ex)
+                self.error('error while altering table %s: %s', table, ex)
         elif cstrtype == 'UniqueConstraint':
             self.session.pool.source('system').drop_index(
-                self.session, str(self.subjtype), str(self.rtype), unique=True)
+                self.session, table, column, unique=True)
                 
     def commit_event(self):
         self.constraints.remove(self.cstr)