Fixed #10142 -- Added docs and an exploding error message to highlight an error present in the implementation of STDDEV_POP and VAR_POP in PostgreSQL 8.2-8.2.4 that will give incorrect answers (the database function mistakenly returns sample, rather than population deviation/variance). Thanks to Vinay Sajip <vinay_sajip@yahoo.co.uk> for the report, and Ian Kelly for pointing out the cause of the problem.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@9804 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Russell Keith-Magee 2009-02-02 12:03:31 +00:00
parent 2b8e768b22
commit 65ad2132ab
4 changed files with 42 additions and 2 deletions

View File

@ -398,6 +398,15 @@ class BaseDatabaseOperations(object):
# Default to a float
return float(value)
def check_aggregate_support(self, aggregate_func):
"""Check that the backend supports the provided aggregate
This is used on specific backends to rule out known aggregates
that are known to have faulty implementations. If the named
aggregate function has a known problem, the backend should
raise NotImplemented.
"""
pass
class BaseDatabaseIntrospection(object):
"""

View File

@ -144,3 +144,14 @@ class DatabaseOperations(BaseDatabaseOperations):
def prep_for_iexact_query(self, x):
return x
def check_aggregate_support(self, aggregate):
"""Check that the backend fully supports the provided aggregate.
The implementation of population statistics (STDDEV_POP and VAR_POP)
under Postgres 8.2 - 8.2.4 is known to be faulty. Raise
NotImplementedError if this is the database in use.
"""
if aggregate.sql_function == 'STDDEV_POP' or aggregate.sql_function == 'VAR_POP':
if self.postgres_version[0] == 8 and self.postgres_version[1] == 2 and self.postgres_version[1] <= 4:
raise NotImplementedError('PostgreSQL 8.2 to 8.2.4 is known to have a faulty implementation of %s. Please upgrade your version of PostgreSQL.' % aggregate.sql_function)

View File

@ -41,8 +41,12 @@ class Aggregate(object):
* is_summary is a boolean that is set True if the aggregate is a
summary value rather than an annotation.
"""
aggregate = getattr(query.aggregates_module, self.name)
query.aggregate_select[alias] = aggregate(col, source=source, is_summary=is_summary, **self.extra)
klass = getattr(query.aggregates_module, self.name)
aggregate = klass(col, source=source, is_summary=is_summary, **self.extra)
# Validate that the backend has a fully supported, correct
# implementation of this aggregate
query.connection.ops.check_aggregate_support(aggregate)
query.aggregate_select[alias] = aggregate
class Avg(Aggregate):
name = 'Avg'

View File

@ -13,6 +13,22 @@ This file describes some of the features that might be relevant to Django
usage. Of course, it is not intended as a replacement for server-specific
documentation or reference manuals.
PostgreSQL notes
================
PostgreSQL 8.2 to 8.2.4
-----------------------
The implementation of the population statistics aggregates ``STDDEV_POP`` and
``VAR_POP`` that shipped with PostgreSQL 8.2 to 8.2.4 are `known to be
faulty`_. Users of these releases of PostgreSQL are advised to upgrade to
`Release 8.2.5`_ or later. Django will raise a ``NotImplementedError`` if you
attempt to use the ``StdDev(sample=False)`` or ``Variance(sample=False)``
aggregate with an database backend falls within the affected release range.
.. _known to be faulty: http://archives.postgresql.org/pgsql-bugs/2007-07/msg00046.php
.. _Release 8.2.5: http://developer.postgresql.org/pgdocs/postgres/release-8-2-5.html
.. _mysql-notes:
MySQL notes