hooks/syncschema.py
changeset 5811 e77cea9721e7
parent 5774 0d792bceb25d
parent 5805 560cde8a4f9f
child 5849 9db65b381028
equal deleted inserted replaced
5797:7183f32fad13 5811:e77cea9721e7
    19 
    19 
    20 - synchronize the living schema object with the persistent schema
    20 - synchronize the living schema object with the persistent schema
    21 - perform physical update on the source when necessary
    21 - perform physical update on the source when necessary
    22 
    22 
    23 checking for schema consistency is done in hooks.py
    23 checking for schema consistency is done in hooks.py
    24 
       
    25 """
    24 """
       
    25 
    26 __docformat__ = "restructuredtext en"
    26 __docformat__ = "restructuredtext en"
    27 
    27 
    28 from copy import copy
    28 from copy import copy
    29 from yams.schema import BASE_TYPES, RelationSchema, RelationDefinitionSchema
    29 from yams.schema import BASE_TYPES, RelationSchema, RelationDefinitionSchema
    30 from yams import buildobjs as ybo, schema2sql as y2sql
    30 from yams import buildobjs as ybo, schema2sql as y2sql
    82 def add_inline_relation_column(session, etype, rtype):
    82 def add_inline_relation_column(session, etype, rtype):
    83     """add necessary column and index for an inlined relation"""
    83     """add necessary column and index for an inlined relation"""
    84     table = SQL_PREFIX + etype
    84     table = SQL_PREFIX + etype
    85     column = SQL_PREFIX + rtype
    85     column = SQL_PREFIX + rtype
    86     try:
    86     try:
    87         session.system_sql(str('ALTER TABLE %s ADD COLUMN %s integer'
    87         session.system_sql(str('ALTER TABLE %s ADD %s integer'
    88                                % (table, column)), rollback_on_failure=False)
    88                                % (table, column)), rollback_on_failure=False)
    89         session.info('added column %s to table %s', column, table)
    89         session.info('added column %s to table %s', column, table)
    90     except:
    90     except:
    91         # silent exception here, if this error has not been raised because the
    91         # silent exception here, if this error has not been raised because the
    92         # column already exists, index creation will fail anyway
    92         # column already exists, index creation will fail anyway
   143     database
   143     database
   144     """
   144     """
   145     table = column = None # make pylint happy
   145     table = column = None # make pylint happy
   146     def precommit_event(self):
   146     def precommit_event(self):
   147         session, table, column = self.session, self.table, self.column
   147         session, table, column = self.session, self.table, self.column
       
   148         source = session.repo.system_source
   148         # drop index if any
   149         # drop index if any
   149         session.pool.source('system').drop_index(session, table, column)
   150         source.drop_index(session, table, column)
   150         try:
   151         if source.dbhelper.alter_column_support:
   151             session.system_sql('ALTER TABLE %s DROP COLUMN %s'
   152             session.system_sql('ALTER TABLE %s DROP COLUMN %s'
   152                                % (table, column), rollback_on_failure=False)
   153                                % (table, column), rollback_on_failure=False)
   153             self.info('dropped column %s from table %s', column, table)
   154             self.info('dropped column %s from table %s', column, table)
   154         except Exception, ex:
   155         else:
   155             # not supported by sqlite for instance
   156             # not supported by sqlite for instance
   156             self.error('error while altering table %s: %s', table, ex)
   157             self.error('dropping column not supported by the backend, handle '
       
   158                        'it yourself (%s.%s)', table, column)
   157 
   159 
   158 
   160 
   159 # base operations for in-memory schema synchronization  ########################
   161 # base operations for in-memory schema synchronization  ########################
   160 
   162 
   161 class MemSchemaNotifyChanges(hook.SingleLastOperation):
   163 class MemSchemaNotifyChanges(hook.SingleLastOperation):
   282             for etype in rschema.subjects():
   284             for etype in rschema.subjects():
   283                 table = SQL_PREFIX + str(etype)
   285                 table = SQL_PREFIX + str(etype)
   284                 sqlexec('INSERT INTO %s_relation SELECT %s, %s FROM %s WHERE NOT %s IS NULL'
   286                 sqlexec('INSERT INTO %s_relation SELECT %s, %s FROM %s WHERE NOT %s IS NULL'
   285                         % (rtype, eidcolumn, column, table, column))
   287                         % (rtype, eidcolumn, column, table, column))
   286             # drop existant columns
   288             # drop existant columns
       
   289             #if session.repo.system_source.dbhelper.alter_column_support:
   287             for etype in rschema.subjects():
   290             for etype in rschema.subjects():
   288                 DropColumn(session, table=SQL_PREFIX + str(etype),
   291                 DropColumn(session, table=SQL_PREFIX + str(etype),
   289                              column=SQL_PREFIX + rtype)
   292                            column=SQL_PREFIX + rtype)
   290         else:
   293         else:
   291             for etype in rschema.subjects():
   294             for etype in rschema.subjects():
   292                 try:
   295                 try:
   293                     add_inline_relation_column(session, str(etype), rtype)
   296                     add_inline_relation_column(session, str(etype), rtype)
   294                 except Exception, ex:
   297                 except Exception, ex:
   375         # added some str() wrapping query since some backend (eg psycopg) don't
   378         # added some str() wrapping query since some backend (eg psycopg) don't
   376         # allow unicode queries
   379         # allow unicode queries
   377         table = SQL_PREFIX + rdef.subject
   380         table = SQL_PREFIX + rdef.subject
   378         column = SQL_PREFIX + rdef.name
   381         column = SQL_PREFIX + rdef.name
   379         try:
   382         try:
   380             session.system_sql(str('ALTER TABLE %s ADD COLUMN %s %s'
   383             session.system_sql(str('ALTER TABLE %s ADD %s %s'
   381                                    % (table, column, attrtype)),
   384                                    % (table, column, attrtype)),
   382                                rollback_on_failure=False)
   385                                rollback_on_failure=False)
   383             self.info('added column %s to table %s', table, column)
   386             self.info('added column %s to table %s', table, column)
   384         except Exception, ex:
   387         except Exception, ex:
   385             # the column probably already exists. this occurs when
   388             # the column probably already exists. this occurs when
   550             coltype = y2sql.type_from_constraints(adbh, objtype, [newcstr],
   553             coltype = y2sql.type_from_constraints(adbh, objtype, [newcstr],
   551                                                   creating=False)
   554                                                   creating=False)
   552             sql = adbh.sql_change_col_type(table, column, coltype, card != '1')
   555             sql = adbh.sql_change_col_type(table, column, coltype, card != '1')
   553             try:
   556             try:
   554                 session.system_sql(sql, rollback_on_failure=False)
   557                 session.system_sql(sql, rollback_on_failure=False)
   555                 self.info('altered column %s of table %s: now VARCHAR(%s)',
   558                 self.info('altered column %s of table %s: now %s',
   556                           column, table, newcstr.max)
   559                           column, table, coltype)
   557             except Exception, ex:
   560             except Exception, ex:
   558                 # not supported by sqlite for instance
   561                 # not supported by sqlite for instance
   559                 self.error('error while altering table %s: %s', table, ex)
   562                 self.error('error while altering table %s: %s', table, ex)
   560         elif cstrtype == 'UniqueConstraint' and oldcstr is None:
   563         elif cstrtype == 'UniqueConstraint' and oldcstr is None:
   561             session.pool.source('system').create_index(
   564             session.pool.source('system').create_index(
   566     """actually remove a constraint of a relation definition"""
   569     """actually remove a constraint of a relation definition"""
   567     rtype = subjtype = None # make pylint happy
   570     rtype = subjtype = None # make pylint happy
   568 
   571 
   569     def precommit_event(self):
   572     def precommit_event(self):
   570         cstrtype = self.cstr.type()
   573         cstrtype = self.cstr.type()
   571         table = SQL_PREFIX + str(self.subjtype)
   574         table = SQL_PREFIX + str(self.rdef.subject)
   572         column = SQL_PREFIX + str(self.rtype)
   575         column = SQL_PREFIX + str(self.rdef.rtype)
   573         # alter the physical schema on size/unique constraint changes
   576         # alter the physical schema on size/unique constraint changes
   574         if cstrtype == 'SizeConstraint':
   577         if cstrtype == 'SizeConstraint':
   575             try:
   578             try:
   576                 self.session.system_sql('ALTER TABLE %s ALTER COLUMN %s TYPE TEXT'
   579                 adbh = self.session.pool.source('system').dbhelper
   577                                         % (table, column),
   580                 coltype = y2sql.type_from_constraints(adbh, rdef.object, [],
   578                                         rollback_on_failure=False)
   581                                                       creating=False)
   579                 self.info('altered column %s of table %s: now TEXT',
   582                 sql = adbh.sql_change_col_type(table, column, coltype,
   580                           column, table)
   583                                                rdef.cardinality != '1')
       
   584                 self.session.system_sql(sql, rollback_on_failure=False)
       
   585                 self.info('altered column %s of table %s: now %s',
       
   586                           column, table, coltype)
   581             except Exception, ex:
   587             except Exception, ex:
   582                 # not supported by sqlite for instance
   588                 # not supported by sqlite for instance
   583                 self.error('error while altering table %s: %s', table, ex)
   589                 self.error('error while altering table %s: %s', table, ex)
   584         elif cstrtype == 'UniqueConstraint':
   590         elif cstrtype == 'UniqueConstraint':
   585             self.session.pool.source('system').drop_index(
   591             self.session.pool.source('system').drop_index(
  1110         try:
  1116         try:
  1111             cstr = rdef.constraint_by_type(entity.type)
  1117             cstr = rdef.constraint_by_type(entity.type)
  1112         except IndexError:
  1118         except IndexError:
  1113             self._cw.critical('constraint type no more accessible')
  1119             self._cw.critical('constraint type no more accessible')
  1114         else:
  1120         else:
  1115             SourceDbCWConstraintDel(self._cw, cstr=cstr,
  1121             SourceDbCWConstraintDel(self._cw, rdef=rdef, cstr=cstr)
  1116                                     subjtype=rdef.subject, rtype=rdef.rtype)
       
  1117             MemSchemaCWConstraintDel(self._cw, rdef=rdef, cstr=cstr)
  1122             MemSchemaCWConstraintDel(self._cw, rdef=rdef, cstr=cstr)
  1118 
  1123 
  1119 
  1124 
  1120 # permissions synchronization hooks ############################################
  1125 # permissions synchronization hooks ############################################
  1121 
  1126