161 |
161 |
162 class _CheckConstraintsOp(hook.LateOperation): |
162 class _CheckConstraintsOp(hook.LateOperation): |
163 """check a new relation satisfy its constraints |
163 """check a new relation satisfy its constraints |
164 """ |
164 """ |
165 def precommit_event(self): |
165 def precommit_event(self): |
166 eidfrom, rtype, eidto = self.rdef |
166 session = self.session |
167 # first check related entities have not been deleted in the same |
167 for values in session.transaction_data['check_constraints_op']: |
168 # transaction |
168 eidfrom, rtype, eidto = values[:3] |
169 if self.session.deleted_in_transaction(eidfrom): |
169 # first check related entities have not been deleted in the same |
170 return |
170 # transaction |
171 if self.session.deleted_in_transaction(eidto): |
171 if session.deleted_in_transaction(eidfrom): |
172 return |
172 return |
173 for constraint in self.constraints: |
173 if session.deleted_in_transaction(eidto): |
174 # XXX |
174 return |
175 # * lock RQLConstraint as well? |
175 constraints = values[3:] |
176 # * use a constraint id to use per constraint lock and avoid |
176 for constraint in constraints: |
177 # unnecessary commit serialization ? |
177 # XXX |
178 if isinstance(constraint, RQLUniqueConstraint): |
178 # * lock RQLConstraint as well? |
179 _acquire_unique_cstr_lock(self.session) |
179 # * use a constraint id to use per constraint lock and avoid |
180 try: |
180 # unnecessary commit serialization ? |
181 constraint.repo_check(self.session, eidfrom, rtype, eidto) |
181 if isinstance(constraint, RQLUniqueConstraint): |
182 except NotImplementedError: |
182 _acquire_unique_cstr_lock(session) |
183 self.critical('can\'t check constraint %s, not supported', |
183 try: |
184 constraint) |
184 constraint.repo_check(session, eidfrom, rtype, eidto) |
|
185 except NotImplementedError: |
|
186 self.critical('can\'t check constraint %s, not supported', |
|
187 constraint) |
185 |
188 |
186 def commit_event(self): |
189 def commit_event(self): |
187 pass |
190 pass |
188 |
191 |
189 |
192 |
199 def __call__(self): |
202 def __call__(self): |
200 # XXX get only RQL[Unique]Constraints? |
203 # XXX get only RQL[Unique]Constraints? |
201 constraints = self._cw.schema_rproperty(self.rtype, self.eidfrom, self.eidto, |
204 constraints = self._cw.schema_rproperty(self.rtype, self.eidfrom, self.eidto, |
202 'constraints') |
205 'constraints') |
203 if constraints: |
206 if constraints: |
204 _CheckConstraintsOp(self._cw, constraints=constraints, |
207 hook.set_operation(self._cw, 'check_constraints_op', |
205 rdef=(self.eidfrom, self.rtype, self.eidto)) |
208 (self.eidfrom, self.rtype, self.eidto) + tuple(constraints), |
|
209 _CheckConstraintsOp) |
206 |
210 |
207 |
211 |
208 class CheckAttributeConstraintHook(IntegrityHook): |
212 class CheckAttributeConstraintHook(IntegrityHook): |
209 """check the attribute relation satisfy its constraints |
213 """check the attribute relation satisfy its constraints |
210 |
214 |
219 for attr in self.entity.edited_attributes: |
223 for attr in self.entity.edited_attributes: |
220 if eschema.subjrels[attr].final: |
224 if eschema.subjrels[attr].final: |
221 constraints = [c for c in eschema.rdef(attr).constraints |
225 constraints = [c for c in eschema.rdef(attr).constraints |
222 if isinstance(c, (RQLUniqueConstraint, RQLConstraint))] |
226 if isinstance(c, (RQLUniqueConstraint, RQLConstraint))] |
223 if constraints: |
227 if constraints: |
224 _CheckConstraintsOp(self._cw, constraints=constraints, |
228 hook.set_operation(self._cw, 'check_constraint_op', |
225 rdef=(self.entity.eid, attr, None)) |
229 (self.entity.eid, attr, None) + tuple(constraints), |
|
230 _CheckConstraintsOp) |
226 |
231 |
227 |
232 |
228 class CheckUniqueHook(IntegrityHook): |
233 class CheckUniqueHook(IntegrityHook): |
229 __regid__ = 'checkunique' |
234 __regid__ = 'checkunique' |
230 events = ('before_add_entity', 'before_update_entity') |
235 events = ('before_add_entity', 'before_update_entity') |