Author: astaric
Date: Wed Apr 24 11:17:27 2013
New Revision: 1471368

URL: http://svn.apache.org/r1471368
Log:
More robust upgrade of attachments.

Can handle orphan attachments. When system wikis are duplicated
to the product env, attachment are copied as well. New tests.

Modified:
    bloodhound/trunk/bloodhound_multiproduct/multiproduct/api.py
    bloodhound/trunk/bloodhound_multiproduct/tests/upgrade.py

Modified: bloodhound/trunk/bloodhound_multiproduct/multiproduct/api.py
URL: 
http://svn.apache.org/viewvc/bloodhound/trunk/bloodhound_multiproduct/multiproduct/api.py?rev=1471368&r1=1471367&r2=1471368&view=diff
==============================================================================
--- bloodhound/trunk/bloodhound_multiproduct/multiproduct/api.py (original)
+++ bloodhound/trunk/bloodhound_multiproduct/multiproduct/api.py Wed Apr 24 
11:17:27 2013
@@ -295,11 +295,18 @@ class MultiProductSystem(Component):
 
                 for table in TICKET_TABLES:
                     if table == 'attachment':
-                        db("""UPDATE attachment
-                              SET product=(SELECT ticket.product FROM ticket
-                                           WHERE ticket.id=%s)
-                              WHERE attachment.type='ticket'
-                           """ %(db.cast('attachment.id', 'integer'),))
+                        db("""
+                            UPDATE attachment
+                               SET product=(SELECT ticket.product
+                                              FROM ticket
+                                             WHERE %(ticket_id)s=attachment.id
+                                             LIMIT 1)
+                             WHERE attachment.type='ticket'
+                               AND EXISTS(SELECT ticket.product
+                                            FROM ticket
+                                           WHERE %(ticket_id)s=attachment.id)
+                           """ % dict(
+                            ticket_id=db.cast('attachment.id', 'text')))
                     else:
                         db("""UPDATE %s
                               SET product=(SELECT ticket.product FROM ticket 
WHERE ticket.id=%s.ticket)""" %
@@ -334,9 +341,14 @@ class MultiProductSystem(Component):
                 temp_table_name, cols = create_temp_table(table)
                 self.log.info("Migrating wikis to global context")
                 db("""INSERT INTO %s (%s, product) SELECT %s, '' FROM %s""" %
-                      (table, cols, cols, temp_table_name))
+                   (table, cols, cols, temp_table_name))
+                db("""UPDATE attachment
+                         SET product=''
+                       WHERE attachment.type='wiki'""")
+
                 for wiki_name, wiki_version, wiki_product in db("""
                         SELECT name, version, product FROM %s""" % table):
+                    attachment_cols = ','.join(table_columns['attachment'])
                     if wiki_name in self.system_wiki_list:
                         for product in all_products:
                             db("""INSERT INTO %s (%s, product)
@@ -344,6 +356,20 @@ class MultiProductSystem(Component):
                                   WHERE name='%s' AND version=%s AND 
product='%s'""" %
                                   (table, cols, cols, product.prefix, table,
                                    wiki_name, wiki_version, wiki_product))
+                            db("""INSERT INTO attachment (%(cols)s, product)
+                                  SELECT %(cols)s, '%(new_product)s'
+                                    FROM attachment a
+                                   WHERE type='wiki'
+                                     AND id='%(wiki_name)s'
+                                     AND product='%(old_product)s'
+                                     AND NOT EXISTS(SELECT * FROM attachment
+                                                     WHERE type='wiki'
+                                                       AND id='%(wiki_name)s'
+                                                       AND 
product='%(new_product)s')
+                               """ % dict(cols=attachment_cols,
+                                          wiki_name=wiki_name,
+                                          old_product=wiki_product,
+                                          new_product=product.prefix))
                     else:
                         self.log.info("Moving wiki page '%s' to default 
product", wiki_name)
                         db("""UPDATE wiki
@@ -351,13 +377,14 @@ class MultiProductSystem(Component):
                               WHERE name='%s' AND version=%s AND 
product='%s'""" %
                               (DEFAULT_PRODUCT,
                                wiki_name, wiki_version, wiki_product))
+                        db("""UPDATE attachment
+                                 SET product='%s'
+                               WHERE type='wiki'
+                                 AND id='%s'
+                                 AND product='%s'
+                           """ % (DEFAULT_PRODUCT, wiki_name, wiki_product))
                 drop_temp_table(temp_table_name)
 
-                db("""UPDATE attachment
-                      SET product=(SELECT wiki.product FROM wiki
-                                   WHERE wiki.name=attachment.id)
-                      WHERE attachment.type='wiki'""")
-
                 # soft link existing repositories to default product
                 repositories_linked = []
                 for id, name in db("""SELECT id, value FROM repository

Modified: bloodhound/trunk/bloodhound_multiproduct/tests/upgrade.py
URL: 
http://svn.apache.org/viewvc/bloodhound/trunk/bloodhound_multiproduct/tests/upgrade.py?rev=1471368&r1=1471367&r2=1471368&view=diff
==============================================================================
--- bloodhound/trunk/bloodhound_multiproduct/tests/upgrade.py (original)
+++ bloodhound/trunk/bloodhound_multiproduct/tests/upgrade.py Wed Apr 24 
11:17:27 2013
@@ -121,16 +121,16 @@ class EnvironmentUpgradeTestCase(unittes
         with self.env.db_direct_transaction as db:
             for i in range(5):
                 db("INSERT INTO dummy_table (v1) VALUES ('%d')" % i)
-            rows = db("SELECT * FROM dummy_table")
-            self.assertEqual(len(rows), 5)
+            self.assertEqual(
+                len(db("SELECT * FROM dummy_table")), 5)
 
         self._enable_multiproduct()
         self.env.upgrade()
         with self.env.db_direct_transaction as db:
-            rows = db('SELECT * FROM "dummy_table"')
-            self.assertEqual(len(rows), 5)
-            rows = db('SELECT * FROM "@_dummy_table"')
-            self.assertEqual(len(rows), 0)
+            self.assertEqual(
+                len(db('SELECT * FROM "dummy_table"')), 5)
+            self.assertEqual(
+                len(db('SELECT * FROM "@_dummy_table"')), 0)
 
     def test_creating_new_product_calls_environment_created(self):
         self._enable_component(DummyPlugin)
@@ -143,6 +143,81 @@ class EnvironmentUpgradeTestCase(unittes
         with self.env.db_direct_transaction as db:
             db('SELECT * FROM "p1_dummy_table"')
 
+    def test_upgrade_moves_tickets_to_default_product(self):
+        with self.env.db_direct_transaction as db:
+            db("""INSERT INTO ticket (id) VALUES (1)""")
+            db("""INSERT INTO attachment (type, id)
+                         VALUES ('ticket', '1')""")
+
+        self._enable_multiproduct()
+        self.env.upgrade()
+
+        with self.env.db_direct_transaction as db:
+            self.assertEqual(
+                len(db("""SELECT * FROM ticket WHERE product='@'""")), 1)
+            self.assertEqual(
+                len(db("""SELECT * FROM attachment
+                          WHERE product='@'
+                            AND type='ticket'""")), 1)
+
+    def test_upgrade_moves_wikis_to_default_product(self):
+        with self.env.db_direct_transaction as db:
+            db("""INSERT INTO wiki (name, version) VALUES ('MyPage', 1)""")
+            db("""INSERT INTO attachment (type, id)
+                         VALUES ('wiki', 'MyPage')""")
+
+        self._enable_multiproduct()
+        self.env.upgrade()
+
+        with self.env.db_direct_transaction as db:
+            self.assertEqual(
+                len(db("""SELECT * FROM wiki WHERE product='@'""")), 1)
+            self.assertEqual(
+                len(db("""SELECT * FROM attachment
+                           WHERE product='@'
+                             AND type='wiki'""")), 1)
+
+    def test_upgrade_duplicates_system_wikis_to_products(self):
+        with self.env.db_direct_transaction as db:
+            db("""INSERT INTO wiki (name, version) VALUES ('WikiStart', 1)""")
+            db("""INSERT INTO attachment (type, id)
+                         VALUES ('wiki', 'WikiStart')""")
+
+        self._enable_multiproduct()
+        self.env.upgrade()
+
+        with self.env.db_direct_transaction as db:
+            self.assertEqual(
+                len(db("""SELECT * FROM wiki WHERE product='@'""")), 1)
+            self.assertEqual(
+                len(db("""SELECT * FROM attachment
+                           WHERE product='@'
+                             AND type='wiki'""")), 1)
+            self.assertEqual(
+                len(db("""SELECT * FROM wiki WHERE product=''""")), 1)
+            self.assertEqual(
+                len(db("""SELECT * FROM attachment
+                           WHERE product=''
+                             AND type='wiki'""")), 1)
+
+    def test_can_upgrade_database_with_orphaned_attachments(self):
+        with self.env.db_direct_transaction as db:
+            db("""INSERT INTO attachment (id, type)
+                       VALUES ('5', 'ticket')""")
+            db("""INSERT INTO attachment (id, type)
+                       VALUES ('MyWiki', 'wiki')""")
+
+        self._enable_multiproduct()
+        self.env.upgrade()
+
+    def test_can_upgrade_database_with_text_attachment_ids(self):
+        with self.env.db_direct_transaction as db:
+            db("""INSERT INTO attachment (id, type)
+                       VALUES ('abc', 'ticket')""")
+
+        self._enable_multiproduct()
+        self.env.upgrade()
+
     def _enable_multiproduct(self):
         self.env.config.set('components', 'multiproduct.*', 'enabled')
         self.env.config.save()


Reply via email to