hooks/syncschema.py
changeset 4042 f85a4c846aad
parent 4011 394f853bb653
child 4043 39ae94e0c8b8
equal deleted inserted replaced
4041:be6e473e6b43 4042:f85a4c846aad
    10 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
    10 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
    11 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
    11 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
    12 """
    12 """
    13 __docformat__ = "restructuredtext en"
    13 __docformat__ = "restructuredtext en"
    14 
    14 
    15 from yams.schema import BASE_TYPES, RelationSchema
    15 from yams.schema import BASE_TYPES, RelationSchema, RelationDefinitionSchema
    16 from yams.buildobjs import EntityType, RelationType, RelationDefinition
    16 from yams.buildobjs import EntityType, RelationType, RelationDefinition
    17 from yams.schema2sql import eschema2sql, rschema2sql, type_from_constraints
    17 from yams.schema2sql import eschema2sql, rschema2sql, type_from_constraints
    18 
    18 
    19 from logilab.common.decorators import clear_cache
    19 from logilab.common.decorators import clear_cache
    20 
    20 
   145 
   145 
   146     def __init__(self, session):
   146     def __init__(self, session):
   147         hook.SingleLastOperation.__init__(self, session)
   147         hook.SingleLastOperation.__init__(self, session)
   148 
   148 
   149     def precommit_event(self):
   149     def precommit_event(self):
   150         for eschema in self.repo.schema.entities():
   150         for eschema in self.session.repo.schema.entities():
   151             if not eschema.final:
   151             if not eschema.final:
   152                 clear_cache(eschema, 'ordered_relations')
   152                 clear_cache(eschema, 'ordered_relations')
   153 
   153 
   154     def commit_event(self):
   154     def commit_event(self):
   155         rebuildinfered = self.session.data.get('rebuild-infered', True)
   155         rebuildinfered = self.session.data.get('rebuild-infered', True)
   156         self.repo.set_schema(self.repo.schema, rebuildinfered=rebuildinfered)
   156         repo = self.session.repo
       
   157         repo.set_schema(repo.schema, rebuildinfered=rebuildinfered)
   157         # CWUser class might have changed, update current session users
   158         # CWUser class might have changed, update current session users
   158         cwuser_cls = self.session.vreg['etypes'].etype_class('CWUser')
   159         cwuser_cls = self.session.vreg['etypes'].etype_class('CWUser')
   159         for session in self.repo._sessions.values():
   160         for session in repo._sessions.values():
   160             session.user.__class__ = cwuser_cls
   161             session.user.__class__ = cwuser_cls
   161 
   162 
   162     def rollback_event(self):
   163     def rollback_event(self):
   163         self.precommit_event()
   164         self.precommit_event()
   164 
   165 
   172         hook.Operation.__init__(self, session, **kwargs)
   173         hook.Operation.__init__(self, session, **kwargs)
   173         # every schema operation is triggering a schema update
   174         # every schema operation is triggering a schema update
   174         MemSchemaNotifyChanges(session)
   175         MemSchemaNotifyChanges(session)
   175 
   176 
   176     def prepare_constraints(self, subjtype, rtype, objtype):
   177     def prepare_constraints(self, subjtype, rtype, objtype):
   177         constraints = rtype.rproperty(subjtype, objtype, 'constraints')
   178         rdef = rtype.rdef(subjtype, objtype)
       
   179         constraints = rdef.constraints
   178         self.constraints = list(constraints)
   180         self.constraints = list(constraints)
   179         rtype.set_rproperty(subjtype, objtype, 'constraints', self.constraints)
   181         rdef.constraints = self.constraints
   180 
   182 
   181 
   183 
   182 class MemSchemaEarlyOperation(MemSchemaOperation):
   184 class MemSchemaEarlyOperation(MemSchemaOperation):
   183     def insert_index(self):
   185     def insert_index(self):
   184         """schema operation which are inserted at the begining of the queue
   186         """schema operation which are inserted at the begining of the queue
   354             except Exception, ex:
   356             except Exception, ex:
   355                 self.error('error while creating index for %s.%s: %s',
   357                 self.error('error while creating index for %s.%s: %s',
   356                            table, column, ex)
   358                            table, column, ex)
   357         # final relations are not infered, propagate
   359         # final relations are not infered, propagate
   358         try:
   360         try:
   359             eschema = self._cw.vreg.schema.eschema(rdef.subject)
   361             eschema = session.vreg.schema.eschema(rdef.subject)
   360         except KeyError:
   362         except KeyError:
   361             return # entity type currently being added
   363             return # entity type currently being added
   362         # propagate attribute to children classes
   364         # propagate attribute to children classes
   363         rschema = self._cw.vreg.schema.rschema(rdef.name)
   365         rschema = session.vreg.schema.rschema(rdef.name)
   364         # if relation type has been inserted in the same transaction, its final
   366         # if relation type has been inserted in the same transaction, its final
   365         # attribute is still set to False, so we've to ensure it's False
   367         # attribute is still set to False, so we've to ensure it's False
   366         rschema.final = True
   368         rschema.final = True
   367         # XXX 'infered': True/False, not clear actually
   369         # XXX 'infered': True/False, not clear actually
   368         props.update({'constraints': rdef.constraints,
   370         props.update({'constraints': rdef.constraints,
   459             if not adbh.alter_column_support:
   461             if not adbh.alter_column_support:
   460                 # not supported (and NOT NULL not set by yams in that case, so
   462                 # not supported (and NOT NULL not set by yams in that case, so
   461                 # no worry)
   463                 # no worry)
   462                 return
   464                 return
   463             atype = self.rschema.objects(etype)[0]
   465             atype = self.rschema.objects(etype)[0]
   464             constraints = self.rschema.rproperty(etype, atype, 'constraints')
   466             constraints = self.rschema.rdef(etype, atype).constraints
   465             coltype = type_from_constraints(adbh, atype, constraints,
   467             coltype = type_from_constraints(adbh, atype, constraints,
   466                                             creating=False)
   468                                             creating=False)
   467             # XXX check self.values['cardinality'][0] actually changed?
   469             # XXX check self.values['cardinality'][0] actually changed?
   468             sql = adbh.sql_set_null_allowed(table, column, coltype,
   470             sql = adbh.sql_set_null_allowed(table, column, coltype,
   469                                             self.values['cardinality'][0] != '1')
   471                                             self.values['cardinality'][0] != '1')
   492         column = SQL_PREFIX + str(rtype)
   494         column = SQL_PREFIX + str(rtype)
   493         # alter the physical schema on size constraint changes
   495         # alter the physical schema on size constraint changes
   494         if newcstr.type() == 'SizeConstraint' and (
   496         if newcstr.type() == 'SizeConstraint' and (
   495             oldcstr is None or oldcstr.max != newcstr.max):
   497             oldcstr is None or oldcstr.max != newcstr.max):
   496             adbh = self.session.pool.source('system').dbhelper
   498             adbh = self.session.pool.source('system').dbhelper
   497             card = rtype.rproperty(subjtype, objtype, 'cardinality')
   499             card = rtype.rdef(subjtype, objtype).cardinality
   498             coltype = type_from_constraints(adbh, objtype, [newcstr],
   500             coltype = type_from_constraints(adbh, objtype, [newcstr],
   499                                             creating=False)
   501                                             creating=False)
   500             sql = adbh.sql_change_col_type(table, column, coltype, card != '1')
   502             sql = adbh.sql_change_col_type(table, column, coltype, card != '1')
   501             try:
   503             try:
   502                 session.system_sql(sql, rollback_on_failure=False)
   504                 session.system_sql(sql, rollback_on_failure=False)
   798                            meta=entity.get('meta')) # don't care about final
   800                            meta=entity.get('meta')) # don't care about final
   799         # fake we add it to the schema now to get a correctly initialized schema
   801         # fake we add it to the schema now to get a correctly initialized schema
   800         # but remove it before doing anything more dangerous...
   802         # but remove it before doing anything more dangerous...
   801         schema = self._cw.vreg.schema
   803         schema = self._cw.vreg.schema
   802         eschema = schema.add_entity_type(etype)
   804         eschema = schema.add_entity_type(etype)
   803         eschema.set_default_groups()
       
   804         # generate table sql and rql to add metadata
   805         # generate table sql and rql to add metadata
   805         tablesql = eschema2sql(self._cw.pool.source('system').dbhelper, eschema,
   806         tablesql = eschema2sql(self._cw.pool.source('system').dbhelper, eschema,
   806                                prefix=SQL_PREFIX)
   807                                prefix=SQL_PREFIX)
   807         relrqls = []
   808         relrqls = []
   808         for rtype in (META_RTYPES - VIRTUAL_RTYPES):
   809         for rtype in (META_RTYPES - VIRTUAL_RTYPES):
   976                 DropColumn(session, table=SQL_PREFIX + subjschema.type,
   977                 DropColumn(session, table=SQL_PREFIX + subjschema.type,
   977                            column=SQL_PREFIX + rschema.type)
   978                            column=SQL_PREFIX + rschema.type)
   978         elif lastrel:
   979         elif lastrel:
   979             DropRelationTable(session, rschema.type)
   980             DropRelationTable(session, rschema.type)
   980         # if this is the last instance, drop associated relation type
   981         # if this is the last instance, drop associated relation type
   981         if lastrel and not rteid in pendings:
   982         if lastrel and not self.eidto in pendings:
   982             execute('DELETE CWRType X WHERE X eid %(x)s', {'x': self.eidto}, 'x')
   983             execute('DELETE CWRType X WHERE X eid %(x)s', {'x': self.eidto}, 'x')
   983         MemSchemaRDefDel(session, (subjschema, rschema, objschema))
   984         MemSchemaRDefDel(session, (subjschema, rschema, objschema))
   984 
   985 
   985 
   986 
   986 # CWAttribute / CWRelation hooks ###############################################
   987 # CWAttribute / CWRelation hooks ###############################################
  1013         if self._cw.deleted_in_transaction(entity.eid):
  1014         if self._cw.deleted_in_transaction(entity.eid):
  1014             return
  1015             return
  1015         desttype = entity.otype.name
  1016         desttype = entity.otype.name
  1016         rschema = self._cw.vreg.schema[entity.rtype.name]
  1017         rschema = self._cw.vreg.schema[entity.rtype.name]
  1017         newvalues = {}
  1018         newvalues = {}
  1018         for prop in rschema.rproperty_defs(desttype):
  1019         for prop in RelationDefinitionSchema.rproperty_defs(desttype):
  1019             if prop == 'constraints':
  1020             if prop == 'constraints':
  1020                 continue
  1021                 continue
  1021             if prop == 'order':
  1022             if prop == 'order':
  1022                 prop = 'ordernum'
  1023                 prop = 'ordernum'
  1023             if prop in entity.edited_attributes:
  1024             if prop in entity.edited_attributes: