app/django/db/models/sql/datastructures.py
changeset 54 03e267d67478
child 323 ff1a9aa48cfd
equal deleted inserted replaced
53:57b4279d8c4e 54:03e267d67478
       
     1 """
       
     2 Useful auxilliary data structures for query construction. Not useful outside
       
     3 the SQL domain.
       
     4 """
       
     5 
       
     6 class EmptyResultSet(Exception):
       
     7     pass
       
     8 
       
     9 class FullResultSet(Exception):
       
    10     pass
       
    11 
       
    12 class MultiJoin(Exception):
       
    13     """
       
    14     Used by join construction code to indicate the point at which a
       
    15     multi-valued join was attempted (if the caller wants to treat that
       
    16     exceptionally).
       
    17     """
       
    18     def __init__(self, level):
       
    19         self.level = level
       
    20 
       
    21 class Empty(object):
       
    22     pass
       
    23 
       
    24 class RawValue(object):
       
    25     def __init__(self, value):
       
    26         self.value = value
       
    27 
       
    28 class Aggregate(object):
       
    29     """
       
    30     Base class for all aggregate-related classes (min, max, avg, count, sum).
       
    31     """
       
    32     def relabel_aliases(self, change_map):
       
    33         """
       
    34         Relabel the column alias, if necessary. Must be implemented by
       
    35         subclasses.
       
    36         """
       
    37         raise NotImplementedError
       
    38 
       
    39     def as_sql(self, quote_func=None):
       
    40         """
       
    41         Returns the SQL string fragment for this object.
       
    42 
       
    43         The quote_func function is used to quote the column components. If
       
    44         None, it defaults to doing nothing.
       
    45 
       
    46         Must be implemented by subclasses.
       
    47         """
       
    48         raise NotImplementedError
       
    49 
       
    50 class Count(Aggregate):
       
    51     """
       
    52     Perform a count on the given column.
       
    53     """
       
    54     def __init__(self, col='*', distinct=False):
       
    55         """
       
    56         Set the column to count on (defaults to '*') and set whether the count
       
    57         should be distinct or not.
       
    58         """
       
    59         self.col = col
       
    60         self.distinct = distinct
       
    61 
       
    62     def relabel_aliases(self, change_map):
       
    63         c = self.col
       
    64         if isinstance(c, (list, tuple)):
       
    65             self.col = (change_map.get(c[0], c[0]), c[1])
       
    66 
       
    67     def as_sql(self, quote_func=None):
       
    68         if not quote_func:
       
    69             quote_func = lambda x: x
       
    70         if isinstance(self.col, (list, tuple)):
       
    71             col = ('%s.%s' % tuple([quote_func(c) for c in self.col]))
       
    72         elif hasattr(self.col, 'as_sql'):
       
    73             col = self.col.as_sql(quote_func)
       
    74         else:
       
    75             col = self.col
       
    76         if self.distinct:
       
    77             return 'COUNT(DISTINCT %s)' % col
       
    78         else:
       
    79             return 'COUNT(%s)' % col
       
    80 
       
    81 class Date(object):
       
    82     """
       
    83     Add a date selection column.
       
    84     """
       
    85     def __init__(self, col, lookup_type, date_sql_func):
       
    86         self.col = col
       
    87         self.lookup_type = lookup_type
       
    88         self.date_sql_func= date_sql_func
       
    89 
       
    90     def relabel_aliases(self, change_map):
       
    91         c = self.col
       
    92         if isinstance(c, (list, tuple)):
       
    93             self.col = (change_map.get(c[0], c[0]), c[1])
       
    94 
       
    95     def as_sql(self, quote_func=None):
       
    96         if not quote_func:
       
    97             quote_func = lambda x: x
       
    98         if isinstance(self.col, (list, tuple)):
       
    99             col = '%s.%s' % tuple([quote_func(c) for c in self.col])
       
   100         else:
       
   101             col = self.col
       
   102         return self.date_sql_func(self.lookup_type, col)
       
   103