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: |