Skip to content

Commit 0185222

Browse files
committed
[SHARE- ][Fix] Use a slightly better count estimate function
1 parent b23a57b commit 0185222

19 files changed

Lines changed: 201 additions & 152 deletions

requirements.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ django-oauth-toolkit==0.10.0
1414
django-revproxy==0.9.12
1515
django-mptt==0.8.5
1616
# Django 1.9 compatibility
17-
# django-postgres-fuzzycount==0.1.6
18-
git+https://github.com/stephenmcd/django-postgres-fuzzycount.git@686053fe130c742b9bb0cce338d2aa7eb24fb91c
1917
# Fix the Choices for TypedModel.type when using Django 1.9
2018
# django-typed-models==0.5.0
2119
git+https://github.com/craigds/django-typed-models.git@7c1eaec06e4a5db188b58cee5d86fae6897208b1
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.9.7 on 2017-02-03 16:22
3+
from __future__ import unicode_literals
4+
5+
from django.db import migrations
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
('share', '0017_merge'),
12+
]
13+
14+
operations = [
15+
migrations.RunSQL(
16+
sql='''
17+
CREATE OR REPLACE FUNCTION count_estimate(query text) RETURNS INTEGER AS
18+
$func$
19+
DECLARE
20+
rec record;
21+
ROWS INTEGER;
22+
BEGIN
23+
FOR rec IN EXECUTE 'EXPLAIN ' || query LOOP
24+
ROWS := SUBSTRING(rec."QUERY PLAN" FROM ' rows=([[:digit:]]+)');
25+
EXIT WHEN ROWS IS NOT NULL;
26+
END LOOP;
27+
28+
RETURN ROWS - 1;
29+
END
30+
$func$ LANGUAGE plpgsql;
31+
''',
32+
reverse_sql='DROP FUNCTION count_estimate();',
33+
),
34+
]

share/models/base.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,19 @@
1111
from django.db.models.fields import AutoField
1212
from django.utils.translation import ugettext_lazy as _
1313

14-
from fuzzycount import FuzzyCountManager
14+
from typedmodels import models as typedmodels
1515

1616
from db.deletion import DATABASE_CASCADE
1717

1818
from share.models import fields
1919
from share.models.change import Change
20+
from share.models.fuzzycount import FuzzyCountManager
2021
from share.models.sql import ShareObjectManager
21-
from typedmodels import models as typedmodels
2222

2323

2424
class ShareObjectVersion(models.Model):
2525
action = models.TextField(max_length=10)
26+
objects = FuzzyCountManager()
2627

2728
class Meta:
2829
abstract = True

share/models/celery.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
from fuzzycount import FuzzyCountManager
21
from model_utils import Choices
32

43
from django.conf import settings
54
from django.db import models
65
from django.utils.translation import ugettext as _
76
from typedmodels.models import TypedModel
87

8+
from share.models.fuzzycount import FuzzyCountManager
9+
910

1011
class CeleryTask(TypedModel):
1112
STATUS = Choices(

share/models/change.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
from model_utils import Choices
44

5-
from fuzzycount import FuzzyCountManager
6-
75
from django.apps import apps
86
from django.contrib.contenttypes.fields import GenericForeignKey
97
from django.contrib.contenttypes.models import ContentType
@@ -14,6 +12,7 @@
1412
from django.utils import timezone
1513
from django.utils.translation import ugettext as _
1614

15+
from share.models.fuzzycount import FuzzyCountManager
1716
from share.models import NormalizedData
1817
from share.util import IDObfuscator
1918

@@ -114,7 +113,7 @@ def _resolve_ref(self, ref):
114113
raise Exception('Could not resolve reference {}'.format(ref)) from ex
115114

116115
def __repr__(self):
117-
return '<{}({}, {}, {} changes)>'.format(self.__class__.__name__, self.STATUS[self.status].upper(), self.normalized_data.source, self.changes.count())
116+
return '<{}({}, {}, {} changes)>'.format(self.__class__.__name__, self.STATUS[self.status].upper(), self.normalized_data.source, self.changes.exact_count())
118117

119118

120119
class Change(models.Model):

share/models/core.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@
1313
from django.dispatch import receiver
1414
from django.utils import timezone
1515
from django.utils.translation import ugettext_lazy as _
16-
from fuzzycount import FuzzyCountManager
1716
from oauth2_provider.models import AccessToken, Application
1817

1918
from osf_oauth2_adapter.apps import OsfOauth2AdapterConfig
19+
2020
from share.models.fields import DateTimeAwareJSONField, ShareURLField
21+
from share.models.fuzzycount import FuzzyCountManager
2122
from share.models.validators import JSONLDValidator
2223

2324
logger = logging.getLogger(__name__)

share/models/fuzzycount.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from django.db import connections
2+
from django.db.models import QuerySet, Manager
3+
4+
5+
class FuzzyCountQuerySet(QuerySet):
6+
def count(self):
7+
cursor = connections[self.db].cursor()
8+
cursor.execute('SELECT count_estimate(%s);', (cursor.mogrify(*self.query.sql_with_params()).decode(), ))
9+
return int(cursor.fetchone()[0])
10+
11+
def exact_count(self):
12+
return super().count()
13+
14+
FuzzyCountManager = Manager.from_queryset(FuzzyCountQuerySet)

share/models/meta.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from share.models.base import ShareObject
88
from share.models.fields import ShareForeignKey
9+
from share.models.fuzzycount import FuzzyCountManager
910
from share.util import strip_whitespace
1011

1112

@@ -49,7 +50,7 @@ class Disambiguation:
4950
all = ('name',)
5051

5152

52-
class SubjectManager(models.Manager):
53+
class SubjectManager(FuzzyCountManager):
5354
def get_by_natural_key(self, subject):
5455
return self.get(name=subject)
5556

share/models/sql.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from django.db import connections
2-
from django.db.models.manager import Manager
32
from django.db.models.sql import InsertQuery
43
from django.db.models.sql.compiler import SQLInsertCompiler
54

6-
from fuzzycount import FuzzyCountQuerySet
5+
from share.models.fuzzycount import FuzzyCountManager
6+
from share.models.fuzzycount import FuzzyCountQuerySet
77

88

99
class SQLInsertReturnVersionCompiler(SQLInsertCompiler):
@@ -84,7 +84,7 @@ def _insert(self, objs, fields, return_id=False, raw=False, using=None):
8484
_insert.queryset_only = False
8585

8686

87-
class ShareObjectManager(Manager):
87+
class ShareObjectManager(FuzzyCountManager):
8888
use_for_related_fields = True
8989

9090
def get_queryset(self):

0 commit comments

Comments
 (0)