Merge 3.26
authorPhilippe Pepiot <philippe.pepiot@logilab.fr>
Wed, 09 Oct 2019 11:44:22 +0200
changeset 12731 8e5f2c449e60
parent 12730 6c48a49cd3c2 (current diff)
parent 12728 6bcd8899f71b (diff)
child 12732 7e6aafa089d2
Merge 3.26
cubicweb/devtools/test/unittest_dbfill.py
cubicweb/server/sources/native.py
cubicweb/server/test/unittest_repository.py
--- a/cubicweb/devtools/test/unittest_dbfill.py	Wed May 22 01:16:55 2019 +0200
+++ b/cubicweb/devtools/test/unittest_dbfill.py	Wed Oct 09 11:44:22 2019 +0200
@@ -108,12 +108,5 @@
         self.assertEqual(self.person_valgen.generate_attribute_value({}, 'description', 12),
                           u'yo')
 
-
-class ConstraintInsertionTC(TestCase):
-
-    def test_writeme(self):
-        self.skipTest('Test automatic insertion / Schema Constraints')
-
-
 if __name__ == '__main__':
     unittest_main()
--- a/cubicweb/server/sources/native.py	Wed May 22 01:16:55 2019 +0200
+++ b/cubicweb/server/sources/native.py	Wed Oct 09 11:44:22 2019 +0200
@@ -648,6 +648,18 @@
     def delete_relation(self, cnx, subject, rtype, object):
         """delete a relation from the source"""
         rschema = self.schema.rschema(rtype)
+        # we should not issue UPDATE on inlined relations when subject is going
+        # to be deleted.
+        # Unless object is also going to be deleted and is not equal to the
+        # subject, in this case DELETE should occur in a order which cubicweb
+        # doesn't handle (yet). For example
+        # cubicweb/server/test/unittest_migractions.py::MigrationCommandsTC::test_add_drop_entity_type
+        # trigger such case.
+        if (
+            rschema.inlined and cnx.deleted_in_transaction(subject)
+            and (subject == object or not cnx.deleted_in_transaction(object))
+        ):
+            return
         self._delete_relation(cnx, subject, rtype, object, rschema.inlined)
         if cnx.ertype_supports_undo(rtype):
             self._record_tx_action(cnx, 'tx_relation_actions', u'R',
--- a/cubicweb/server/test/unittest_repository.py	Wed May 22 01:16:55 2019 +0200
+++ b/cubicweb/server/test/unittest_repository.py	Wed Oct 09 11:44:22 2019 +0200
@@ -320,6 +320,58 @@
             cnx.commit()
             self.assertEqual(bk.title, 'root')
 
+    def test_delete_entity_with_inlined_relation(self):
+        """Test deletion of entity with inlined relations.
+
+        In this case, inlined relation column should not be deleted (= e.g. not
+        updated to NULL), but hooks before_delete_relation and
+        afer_delete_relation must be called.
+        """
+        class OnDeleteInlined(Hook):
+            __regid__ = 'on_delete_inlined'
+            __select__ = Hook.__select__ & hook.match_rtype('personne_inlined')
+            events = ('before_delete_relation', 'after_delete_relation')
+            CALLED = []
+
+            def __call__(self):
+                OnDeleteInlined.CALLED.append(self.event)
+
+        with self.admin_access.cnx() as cnx:
+            # allow only one null on cw_personne_inlined column
+            cnx.system_sql(
+                'CREATE UNIQUE INDEX test_composite_idx ON cw_personne(true) '
+                'WHERE cw_personne_inlined is NULL')
+            cnx.commit()
+
+            # deletion of p1 should not set personne_inlined to NULL (otherwise
+            # the unique index will raise)
+            p0 = cnx.create_entity('Personne', nom=u'p0')
+            p1 = cnx.create_entity('Personne', nom=u'p1', personne_inlined=p0)
+            cnx.commit()
+            with self.temporary_appobjects(OnDeleteInlined):
+                cnx.entity_from_eid(p1.eid).cw_delete()
+            assert OnDeleteInlined.CALLED == [
+                'before_delete_relation', 'after_delete_relation']
+            cnx.commit()
+
+            # XXX: This case is not handled because entities need to be deleted
+            # in a specific order
+            # p1 = cnx.create_entity('Personne', nom=u'p1', personne_inlined=p0)
+            # cnx.commit()
+            # cnx.execute('DELETE Personne X WHERE X eid IN ({}, {})'.format(p1.eid, p0.eid))
+            # cnx.commit()
+            cnx.entity_from_eid(p0.eid).cw_delete()
+            cnx.commit()
+
+            # deletion of p1 should not set personne_inlined to NULL
+            p1 = cnx.create_entity('Personne', nom=u'p1')
+            p1.cw_set(personne_inlined=p1)
+            p0 = cnx.create_entity('Personne', nom=u'p0')
+            cnx.commit()
+            cnx.entity_from_eid(p1.eid).cw_delete()
+            cnx.commit()
+
+
 class SchemaDeserialTC(CubicWebTC):
 
     appid = 'data-schemaserial'
--- a/cubicweb/web/views/undohistory.py	Wed May 22 01:16:55 2019 +0200
+++ b/cubicweb/web/views/undohistory.py	Wed Oct 09 11:44:22 2019 +0200
@@ -45,8 +45,7 @@
         self.action_type = action_type
 
     def __str__(self):
-        return '%s(%s)' % (self.__class__.__name__, ', '.join(
-            "%s=%v" % (str(k), str(v)) for k, v in kwargs.items() ))
+        return '%s()' % (self.__class__.__name__)
 
     def __call__(self, cls, req, tx_action=None, **kwargs):
         # tx_action is expected to be a transaction.AbstractAction
--- a/doc/changes/3.21.rst	Wed May 22 01:16:55 2019 +0200
+++ b/doc/changes/3.21.rst	Wed Oct 09 11:44:22 2019 +0200
@@ -24,7 +24,7 @@
 User-visible changes
 --------------------
 
-* the use of fckeditor for text form fields is disabled by default
+* the use of fckeditor for text form fields is disabled by default, to re-enable it simply install the `cubicweb-ckeditor` cube (then `add_cude('ckeditor')` in a migration or in the shell)
 
 * the 'https-deny-anonymous' configuration setting no longer exists