From 6939767a0f7e688cefa875dbf5af2f17e325cd4a Mon Sep 17 00:00:00 2001
From: Dmitry Shelepnev <mitshel@mail.ru>
Date: Thu, 16 Mar 2017 21:13:49 +0300
Subject: [PATCH] Add sopds_util pg_optimize cmd for PostgreSQL Optimization

---
 .../management/commands/sopds_util.py         | 12 +++++++--
 opds_catalog/opdsdb.py                        | 27 +++++++++++++------
 opds_catalog/settings.py                      |  3 +--
 3 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/opds_catalog/management/commands/sopds_util.py b/opds_catalog/management/commands/sopds_util.py
index 62dc81c..f17ab40 100644
--- a/opds_catalog/management/commands/sopds_util.py
+++ b/opds_catalog/management/commands/sopds_util.py
@@ -1,6 +1,7 @@
 from django.core.management.base import BaseCommand
 from django.core.management import call_command
 from django.db import transaction
+from django.db import connection
 from django.conf import settings as main_settings
 
 from opds_catalog import opdsdb
@@ -14,7 +15,7 @@ class Command(BaseCommand):
     verbose = False
         
     def add_arguments(self, parser):
-        parser.add_argument('command', action="store", nargs='*', help='Use [ clear | info | save_mygenres | load_mygenres | setconf | getconf ]') 
+        parser.add_argument('command', action="store", nargs='*', help='Use [ clear | info | save_mygenres | load_mygenres | setconf | getconf | pg_optimize ]')
         parser.add_argument('--verbose',action='store_true', dest='verbose', default=False, help='Set verbosity level for books collection scan.')  
         parser.add_argument('--nogenres',action='store_true', dest='nogenres', default=False, help='Not install genres fom fixtures.')              
 
@@ -39,7 +40,9 @@ class Command(BaseCommand):
             self.setconf(self.confparam, self.confvalue)         
         elif action == "getconf":
             self.confparam = options['command'][1] if len(options['command'])>1 else None
-            self.getconf(self.confparam)   
+            self.getconf(self.confparam)
+        elif action == "pg_optimize":
+            self.pg_optimize()
 
     def clear(self):
         with transaction.atomic():
@@ -47,6 +50,7 @@ class Command(BaseCommand):
         if not self.nogenres:
             call_command('loaddata', 'genre.json', app_label='opds_catalog') 
         Counter.objects.update_known_counters()
+        opdsdb.pg_optimize(False)
         
     def info(self):
         Counter.objects.update_known_counters()
@@ -78,5 +82,9 @@ class Command(BaseCommand):
         else:
             call_command('constance', 'list', app_label='opds_catalog')
 
+    def pg_optimize(self):
+        opdsdb.pg_optimize(True)
+
+
             
 
diff --git a/opds_catalog/opdsdb.py b/opds_catalog/opdsdb.py
index 58c097d..863b901 100644
--- a/opds_catalog/opdsdb.py
+++ b/opds_catalog/opdsdb.py
@@ -42,6 +42,17 @@ unknown_genre=_(unknown_genre_en)
 #
 utfhigh = re.compile(u'[\U00010000-\U0010ffff]')
 
+def pg_optimize(verbose=False):
+    """ TODO: Table optimizations for Postgre """
+    if connection.vendor != 'postgresql':
+        if verbose:
+            print('No PostgreSql connection backend detected...')
+    else:
+        cursor = connection.cursor()
+        cursor.execute('alter table opds_catalog_book SET ( fillfactor = 50)')
+        cursor.execute('VACUUM FULL opds_catalog_book')
+        print('PostgreSql tables internal structure optimized...')
+
 def clear_all(verbose=False):
     cursor = connection.cursor()
     cursor.execute('delete from opds_catalog_bseries')
@@ -187,24 +198,24 @@ def findbook(name, path, setavail=0):
         book.save()
 
     return book
-
-def addbook(name, path, cat, exten, title, annotation, docdate, lang, size=0, archive=0):
+
+def addbook(name, path, cat, exten, title, annotation, docdate, lang, size=0, archive=0):
     book = Book.objects.create(filename=name[:SIZE_BOOK_FILENAME],path=path[:SIZE_BOOK_PATH],catalog=cat,filesize=size,format=exten.lower()[:SIZE_BOOK_FORMAT],
                 title=title[:SIZE_BOOK_TITLE],search_title=title.upper()[:SIZE_BOOK_TITLE],annotation=p(annotation,SIZE_BOOK_ANNOTATION),
                 docdate=docdate[:SIZE_BOOK_DOCDATE],lang=lang[:SIZE_BOOK_LANG],cat_type=archive,avail=2, lang_code=getlangcode(title))
     return book
 
 def findauthor(full_name):
-    try:
-        author = Author.objects.filter(full_name=full_name[:SIZE_AUTHOR_NAME])[:1]
+    try:
+        author = Author.objects.filter(full_name=full_name[:SIZE_AUTHOR_NAME])[:1]
     except Author.DoesNotExist:
         author = None
 
     return author
-
+
 def addauthor(full_name):
     author, created = Author.objects.get_or_create(full_name=full_name[:SIZE_AUTHOR_NAME], defaults={'search_full_name':full_name.upper()[:SIZE_AUTHOR_NAME], 
-                                                                                                     'lang_code':getlangcode(full_name)})
+                                                                                                     'lang_code':getlangcode(full_name)})
     return author
 
 def addbauthor(book, author):
@@ -219,8 +230,8 @@ def addbgenre(book, genre):
     bg = bgenre(book=book, genre=genre)
     bg.save()
 
-def addseries(ser):
-    series, created = Series.objects.get_or_create(ser=ser[:SIZE_SERIES], defaults={'search_ser':ser.upper()[:SIZE_SERIES], 'lang_code':getlangcode(ser)})
+def addseries(ser):
+    series, created = Series.objects.get_or_create(ser=ser[:SIZE_SERIES], defaults={'search_ser':ser.upper()[:SIZE_SERIES], 'lang_code':getlangcode(ser)})
     return series
 
 def addbseries(book, ser, ser_no):
diff --git a/opds_catalog/settings.py b/opds_catalog/settings.py
index 06cc8d0..d2a1d8f 100644
--- a/opds_catalog/settings.py
+++ b/opds_catalog/settings.py
@@ -27,8 +27,7 @@ from django.dispatch import receiver
 #    if updated_key == 'SOPDS_LANGUAGE':
 #        translation.activate(new_value)
 #        print(new_value)
-    
-    
+
 def constance_update_all():
     pass
     
-- 
GitLab