From 85b910083d329fced347812b1a5810e8a4cd68a7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20=20MENAGER?= <herve.menager@pasteur.fr>
Date: Sun, 29 Jul 2018 13:44:10 +0200
Subject: [PATCH] denormalize ppi name to improve compound query performance

Former-commit-id: efe273eac847d110d0b8791fa2eb89191d212ffa
---
 ippisite/db.sqlite3.REMOVED.git-id          |  2 +-
 ippisite/ippidb/migrations/0009_ppi_name.py | 20 ++++++++++++++++++++
 ippisite/ippidb/models.py                   | 18 ++++++++----------
 3 files changed, 29 insertions(+), 11 deletions(-)
 create mode 100644 ippisite/ippidb/migrations/0009_ppi_name.py

diff --git a/ippisite/db.sqlite3.REMOVED.git-id b/ippisite/db.sqlite3.REMOVED.git-id
index 5e73a6d9..c97e351a 100644
--- a/ippisite/db.sqlite3.REMOVED.git-id
+++ b/ippisite/db.sqlite3.REMOVED.git-id
@@ -1 +1 @@
-a95c9b99cc69a1cae8a8fa13dfa234ef88d45f4e
\ No newline at end of file
+487393aa0af165ca4ce78c99486b57039379f535
\ No newline at end of file
diff --git a/ippisite/ippidb/migrations/0009_ppi_name.py b/ippisite/ippidb/migrations/0009_ppi_name.py
new file mode 100644
index 00000000..d052b637
--- /dev/null
+++ b/ippisite/ippidb/migrations/0009_ppi_name.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11 on 2018-07-29 10:13
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('ippidb', '0008_auto_20180727_0845'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='ppi',
+            name='name',
+            field=models.TextField(blank=True, null=True, verbose_name='PPI name'),
+        ),
+    ]
diff --git a/ippisite/ippidb/models.py b/ippisite/ippidb/models.py
index 6ccd9d07..d6eb9bf9 100644
--- a/ippisite/ippidb/models.py
+++ b/ippisite/ippidb/models.py
@@ -211,22 +211,21 @@ class PpiFamily(models.Model):
         return self.name
 
 
-class Ppi(models.Model):
+class Ppi(AutoFillableModel):
     pdb_id = models.CharField('PDB ID', max_length=4, null=True, blank=True)
     pockets_nb = models.IntegerField(
         'Total number of pockets in the complex', default=1)
     symmetry = models.ForeignKey(Symmetry, models.CASCADE)
     diseases = models.ManyToManyField(Disease)
     family = models.ForeignKey(PpiFamily, models.CASCADE, null=True, blank=True)
+    name = models.TextField('PPI name', null=True, blank=True)
 
     def __str__(self):
         return '{} PPI, PDB:{}'.format(self.symmetry.description, self.pdb_id or 'unknown')
 
-    def get_ppi_complexes(self):
-        """
-        return all ppi complexes belonging to this ppi
-        """
-        return PpiComplex.objects.filter(ppi=self)
+    def autofill(self):
+        # name is denormalized and stored in the database to reduce SQL queries in query mode
+        self.name = self.compute_name_from_protein_names()
 
     def get_ppi_bound_complexes(self):
         """
@@ -235,10 +234,9 @@ class Ppi(models.Model):
         # this is the less efficient query ever seen, FIXME
         return PpiComplex.objects.filter(ppi=self, complex__in=ProteinDomainBoundComplex.objects.all())
 
-    @property
-    def name(self):
+    def compute_name_from_protein_names(self):
         all_protein_names = set(
-            [ppi_complex.complex.protein.short_name for ppi_complex in self.get_ppi_complexes()])
+            [ppi_complex.complex.protein.short_name for ppi_complex in self.ppicomplex_set.all()])
         bound_protein_names = set(
             [ppi_complex.complex.protein.short_name for ppi_complex in self.get_ppi_bound_complexes()])
         partner_protein_names = all_protein_names - bound_protein_names
@@ -614,7 +612,7 @@ class TestActivityDescription(models.Model):
         depends on the modulation type
         """
         if self.test_modulation_type == 'I':
-            return self.ppi.get_ppi_complexes()
+            return self.ppi.ppicomplex_set.all()
         else:
             return self.ppi.get_ppi_bound_complexes()
 
-- 
GitLab