Author: phd
Date: 2005-02-10 18:46:08 +0000 (Thu, 10 Feb 2005)
New Revision: 599
Added:
home/phd/SQLObject/inheritance/sqlobject/sresults.py
Modified:
home/phd/SQLObject/inheritance/sqlobject/main.py
Log:
Merged patch from revision 598: class SelectResults has been moved to sresults.py.
Modified: home/phd/SQLObject/inheritance/sqlobject/main.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/main.py 2005-02-10 18:32:10 UTC (rev 598)
+++ home/phd/SQLObject/inheritance/sqlobject/main.py 2005-02-10 18:46:08 UTC (rev 599)
@@ -4,6 +4,14 @@
SQLObject is a object-relational mapper. See SQLObject.html or
SQLObject.txt for more.
+Modified by
+ Daniel Savard, Xsoli Inc <sqlobject xsoli.com> 7 Feb 2004
+ - Added support for simple table inheritance.
+
+ Oleg Broytmann, SIA "ANK" <ph...@ph...> 3 Feb 2005
+ - Split inheritance support into a number of separate modules and classes -
+ InheritableSQLObject at al.
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
@@ -31,6 +39,7 @@
import index
import classregistry
import declarative
+from sresults import SelectResults
import sys
if sys.version_info[:3] < (2, 2, 0):
@@ -195,164 +204,6 @@
if warnings_level is not None and warnings_level <= level:
warnings.warn(message, DeprecationWarning, stacklevel=2)
-class SelectResults(object):
- IterationClass = dbconnection.Iteration
-
- def __init__(self, sourceClass, clause, clauseTables=None,
- **ops):
- self.sourceClass = sourceClass
- if clause is None or isinstance(clause, str) and clause == 'all':
- clause = sqlbuilder.SQLTrueClause
- self.clause = clause
- tablesDict = sqlbuilder.tablesUsedDict(self.clause)
- tablesDict[sourceClass._table] = 1
- if clauseTables:
- for table in clauseTables:
- tablesDict[table] = 1
- self.clauseTables = clauseTables
- self.tables = tablesDict.keys()
- self.ops = ops
- if self.ops.get('orderBy', NoDefault) is NoDefault:
- self.ops['orderBy'] = sourceClass._defaultOrder
- orderBy = self.ops['orderBy']
- if isinstance(orderBy, list) or isinstance(orderBy, tuple):
- orderBy = map(self._mungeOrderBy, orderBy)
- else:
- orderBy = self._mungeOrderBy(orderBy)
- #print "OUT: %r; in: %r" % (sourceClass.sqlrepr(orderBy), sourceClass.sqlrepr(self.ops['orderBy']))
- self.ops['dbOrderBy'] = orderBy
- if ops.has_key('connection') and ops['connection'] is None:
- del ops['connection']
-
- def _mungeOrderBy(self, orderBy):
- if isinstance(orderBy, str) and orderBy.startswith('-'):
- orderBy = orderBy[1:]
- desc = True
- else:
- desc = False
- if isinstance(orderBy, (str, unicode)):
- if self.sourceClass._SO_columnDict.has_key(orderBy):
- val = self.sourceClass._SO_columnDict[orderBy].dbName
- if desc:
- return '-' + val
- else:
- return val
- else:
- if desc:
- return '-' + orderBy
- else:
- return orderBy
- else:
- return orderBy
-
- def clone(self, **newOps):
- ops = self.ops.copy()
- ops.update(newOps)
- return self.__class__(self.sourceClass, self.clause,
- self.clauseTables, **ops)
-
- def orderBy(self, orderBy):
- return self.clone(orderBy=orderBy)
-
- def connection(self, conn):
- return self.clone(connection=conn)
-
- def limit(self, limit):
- return self[:limit]
-
- def lazyColumns(self, value):
- return self.clone(lazyColumns=value)
-
- def reversed(self):
- return self.clone(reversed=not self.ops.get('reversed', False))
-
- def distinct(self):
- return self.clone(distinct=True)
-
- def __getitem__(self, value):
- if type(value) is type(slice(1)):
- assert not value.step, "Slices do not support steps"
- if not value.start and not value.stop:
- # No need to copy, I'm immutable
- return self
-
- # Negative indexes aren't handled (and everything we
- # don't handle ourselves we just create a list to
- # handle)
- if (value.start and value.start < 0) \
- or (value.stop and value.stop < 0):
- if value.start:
- if value.stop:
- return list(self)[value.start:value.stop]
- return list(self)[value.start:]
- return list(self)[:value.stop]
-
-
- if value.start:
- assert value.start >= 0
- start = self.ops.get('start', 0) + value.start
- if value.stop is not None:
- assert value.stop >= 0
- if value.stop < value.start:
- # an empty result:
- end = start
- else:
- end = value.stop + self.ops.get('start', 0)
- if self.ops.get('end', None) is not None \
- and value['end'] < end:
- # truncated by previous slice:
- end = self.ops['end']
- else:
- end = self.ops.get('end', None)
- else:
- start = self.ops.get('start', 0)
- end = value.stop + start
- if self.ops.get('end', None) is not None \
- and self.ops['end'] < end:
- end = self.ops['end']
- return self.clone(start=start, end=end)
- else:
- if value < 0:
- return list(iter(self))[value]
- else:
- start = self.ops.get('start', 0) + value
- return list(self.clone(start=start, end=start+1))[0]
-
- def __iter__(self):
- conn = self.ops.get('connection', self.sourceClass._connection)
- return conn.iterSelect(self)
-
- def accumulate(self, expression):
- """ Use an accumulate expression to select result
- using another SQL select through current
- connection.
- Return the accumulate result
- """
- conn = self.ops.get('connection', self.sourceClass._connection)
- return conn.accumulateSelect(self, expression)
-
- def count(self):
- """ Counting elements of current select results """
- assert not self.ops.get('distinct'), "It is not currently supported to count distinct objects"
-
- count = self.accumulate('COUNT(*)')
- if self.ops.get('start'):
- count -= self.ops['start']
- if self.ops.get('end'):
- count = min(self.ops['end'] - self.ops.get('start', 0), count)
- return count
-
- def sum(self, attribute):
- """ Making the sum of a given select result attribute.
- `attribute` can be a column name (like 'a_column')
- or a dot-q attribute (like Table.q.aColumn)
- """
- if type(attribute) == type(''):
- expression = 'SUM(%s)' % attribute
- else:
- expression = sqlbuilder.func.SUM(attribute)
- return self.accumulate(expression)
-
# SQLObject is the superclass for all SQLObject classes, of
# course. All the deeper magic is done in MetaSQLObject, and
# only lesser magic is done here. All the actual work is done
Added: home/phd/SQLObject/inheritance/sqlobject/sresults.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/sresults.py 2005-02-10 18:32:10 UTC (rev 598)
+++ home/phd/SQLObject/inheritance/sqlobject/sresults.py 2005-02-10 18:46:08 UTC (rev 599)
@@ -0,0 +1,161 @@
+import sqlbuilder
+import dbconnection
+
+class SelectResults(object):
+ IterationClass = dbconnection.Iteration
+
+ def __init__(self, sourceClass, clause, clauseTables=None,
+ **ops):
+ self.sourceClass = sourceClass
+ if clause is None or isinstance(clause, str) and clause == 'all':
+ clause = sqlbuilder.SQLTrueClause
+ self.clause = clause
+ tablesDict = sqlbuilder.tablesUsedDict(self.clause)
+ tablesDict[sourceClass._table] = 1
+ if clauseTables:
+ for table in clauseTables:
+ tablesDict[table] = 1
+ self.clauseTables = clauseTables
+ self.tables = tablesDict.keys()
+ self.ops = ops
+ if self.ops.get('orderBy', sqlbuilder.NoDefault) is sqlbuilder.NoDefault:
+ self.ops['orderBy'] = sourceClass._defaultOrder
+ orderBy = self.ops['orderBy']
+ if isinstance(orderBy, list) or isinstance(orderBy, tuple):
+ orderBy = map(self._mungeOrderBy, orderBy)
+ else:
+ orderBy = self._mungeOrderBy(orderBy)
+ self.ops['dbOrderBy'] = orderBy
+ if ops.has_key('connection') and ops['connection'] is None:
+ del ops['connection']
+
+ def _mungeOrderBy(self, orderBy):
+ if isinstance(orderBy, str) and orderBy.startswith('-'):
+ orderBy = orderBy[1:]
+ desc = True
+ else:
+ desc = False
+ if isinstance(orderBy, (str, unicode)):
+ if self.sourceClass._SO_columnDict.has_key(orderBy):
+ val = self.sourceClass._SO_columnDict[orderBy].dbName
+ if desc:
+ return '-' + val
+ else:
+ return val
+ else:
+ if desc:
+ return '-' + orderBy
+ else:
+ return orderBy
+ else:
+ return orderBy
+
+ def clone(self, **newOps):
+ ops = self.ops.copy()
+ ops.update(newOps)
+ return self.__class__(self.sourceClass, self.clause,
+ self.clauseTables, **ops)
+
+ def orderBy(self, orderBy):
+ return self.clone(orderBy=orderBy)
+
+ def connection(self, conn):
+ return self.clone(connection=conn)
+
+ def limit(self, limit):
+ return self[:limit]
+
+ def lazyColumns(self, value):
+ return self.clone(lazyColumns=value)
+
+ def reversed(self):
+ return self.clone(reversed=not self.ops.get('reversed', False))
+
+ def distinct(self):
+ return self.clone(distinct=True)
+
+ def __getitem__(self, value):
+ if type(value) is type(slice(1)):
+ assert not value.step, "Slices do not support steps"
+ if not value.start and not value.stop:
+ # No need to copy, I'm immutable
+ return self
+
+ # Negative indexes aren't handled (and everything we
+ # don't handle ourselves we just create a list to
+ # handle)
+ if (value.start and value.start < 0) \
+ or (value.stop and value.stop < 0):
+ if value.start:
+ if value.stop:
+ return list(self)[value.start:value.stop]
+ return list(self)[value.start:]
+ return list(self)[:value.stop]
+
+
+ if value.start:
+ assert value.start >= 0
+ start = self.ops.get('start', 0) + value.start
+ if value.stop is not None:
+ assert value.stop >= 0
+ if value.stop < value.start:
+ # an empty result:
+ end = start
+ else:
+ end = value.stop + self.ops.get('start', 0)
+ if self.ops.get('end', None) is not None \
+ and value['end'] < end:
+ # truncated by previous slice:
+ end = self.ops['end']
+ else:
+ end = self.ops.get('end', None)
+ else:
+ start = self.ops.get('start', 0)
+ end = value.stop + start
+ if self.ops.get('end', None) is not None \
+ and self.ops['end'] < end:
+ end = self.ops['end']
+ return self.clone(start=start, end=end)
+ else:
+ if value < 0:
+ return list(iter(self))[value]
+ else:
+ start = self.ops.get('start', 0) + value
+ return list(self.clone(start=start, end=start+1))[0]
+
+ def __iter__(self):
+ conn = self.ops.get('connection', self.sourceClass._connection)
+ return conn.iterSelect(self)
+
+ def accumulate(self, expression):
+ """ Use an accumulate expression to select result
+ using another SQL select through current
+ connection.
+ Return the accumulate result
+ """
+ conn = self.ops.get('connection', self.sourceClass._connection)
+ return conn.accumulateSelect(self, expression)
+
+ def count(self):
+ """ Counting elements of current select results """
+ assert not self.ops.get('distinct'), "It is not currently supported to count distinct objects"
+
+ count = self.accumulate('COUNT(*)')
+ if self.ops.get('start'):
+ count -= self.ops['start']
+ if self.ops.get('end'):
+ count = min(self.ops['end'] - self.ops.get('start', 0), count)
+ return count
+
+ def sum(self, attribute):
+ """ Making the sum of a given select result attribute.
+ `attribute` can be a column name (like 'a_column')
+ or a dot-q attribute (like Table.q.aColumn)
+ """
+ if type(attribute) == type(''):
+ expression = 'SUM(%s)' % attribute
+ else:
+ expression = sqlbuilder.func.SUM(attribute)
+ return self.accumulate(expression)
+
+__all__ = ['SelectResults']
|