Thread: [SQL-CVS] r2339 - in SQLObject/branches/sqlbuilder-views/sqlobject: . tests
SQLObject is a Python ORM.
Brought to you by:
ianbicking,
phd
From: <sub...@co...> - 2007-02-21 21:26:49
|
Author: luke Date: 2007-02-21 14:26:44 -0700 (Wed, 21 Feb 2007) New Revision: 2339 Added: SQLObject/branches/sqlbuilder-views/sqlobject/tests/test_select_through.py Modified: SQLObject/branches/sqlbuilder-views/sqlobject/joins.py SQLObject/branches/sqlbuilder-views/sqlobject/sresults.py Log: SelectResults.throughTo Modified: SQLObject/branches/sqlbuilder-views/sqlobject/joins.py =================================================================== --- SQLObject/branches/sqlbuilder-views/sqlobject/joins.py 2007-02-21 20:29:27 UTC (rev 2338) +++ SQLObject/branches/sqlbuilder-views/sqlobject/joins.py 2007-02-21 21:26:44 UTC (rev 2339) @@ -62,7 +62,7 @@ otherClass, self._setOtherClass) self.joinColumn = joinColumn self.joinMethodName = joinMethodName - self.orderBy = orderBy + self._orderBy = orderBy if not self.joinColumn: # Here we set up the basic join, which is # one-to-many, where the other class points to @@ -70,6 +70,12 @@ self.joinColumn = styles.getStyle( self.soClass).tableReference(self.soClass.sqlmeta.table) + def orderBy(self): + if self._orderBy is NoDefault: + self._orderBy = self.otherClass.sqlmeta.defaultOrder + return self._orderBy + orderBy = property(orderBy) + def _setOtherClass(self, cls): self.otherClass = cls @@ -77,8 +83,6 @@ return False def _applyOrderBy(self, results, defaultSortClass): - if self.orderBy is NoDefault: - self.orderBy = defaultSortClass.sqlmeta.defaultOrder if self.orderBy is not None: results.sort(sorter(self.orderBy)) return results @@ -159,8 +163,6 @@ else: conn = None results = self.otherClass.select(getattr(self.otherClass.q, self.soClass.sqlmeta.style.dbColumnToPythonAttr(self.joinColumn)) == inst.id, connection=conn) - if self.orderBy is NoDefault: - self.orderBy = self.otherClass.sqlmeta.defaultOrder return results.orderBy(self.orderBy) class SQLMultipleJoin(Join): @@ -279,8 +281,6 @@ ), TableToId(self.soClass.sqlmeta.table, self.soClass.sqlmeta.idName, inst.id), ), clauseTables=(self.soClass.sqlmeta.table, self.otherClass.sqlmeta.table, self.intermediateTable)) - if self.orderBy is NoDefault: - self.orderBy = self.otherClass.sqlmeta.defaultOrder return results.orderBy(self.orderBy) class SQLRelatedJoin(RelatedJoin): Modified: SQLObject/branches/sqlbuilder-views/sqlobject/sresults.py =================================================================== --- SQLObject/branches/sqlbuilder-views/sqlobject/sresults.py 2007-02-21 20:29:27 UTC (rev 2338) +++ SQLObject/branches/sqlbuilder-views/sqlobject/sresults.py 2007-02-21 21:26:44 UTC (rev 2339) @@ -1,6 +1,7 @@ import sqlbuilder import dbconnection import main +import joins StringType = type('') @@ -281,4 +282,59 @@ % results) return results[0] + def throughTo(self): + return _throughTo_getter(self) + throughTo = property(throughTo) + + def _throughTo(self, attr): + ref = self.sourceClass.sqlmeta.columns.get(attr.endswith('ID') and attr or attr+'ID', None) + if ref and ref.foreignKey: + return self._throughToFK(ref) + else: + join = [x for x in self.sourceClass.sqlmeta.joins if x.joinMethodName==attr] + if join: + join = join[0] + if hasattr(join, 'otherColumn'): + return self._throughToRelatedJoin(join) + return self._throughToMultipleJoin(join) + + raise AttributeError("throughTo argument (got %s) should be name of foreignKey or SQL*Join in %s" % (attr, self.sourceClass)) + + def _throughToFK(self, col): + otherClass = getattr(self.sourceClass, "_SO_class_"+col.foreignKey) + query = sqlbuilder.Alias(self.queryForSelect(), "%s_%s" % (self.sourceClass.__name__, col.name)) + return otherClass.select(otherClass.q.id==getattr(query.q, getattr(self.sourceClass.q, col.name).fieldName), + distinct=True) + + def _throughToMultipleJoin(self, join): + otherClass = join.otherClass + query = self.queryForSelect() + query = sqlbuilder.Alias(query, "%s_%s" % (self.sourceClass.__name__, join.joinMethodName)) + joinColumn = getattr(otherClass.q, join.soClass.sqlmeta.style.dbColumnToPythonAttr(join.joinColumn)) + return otherClass.select(joinColumn == getattr(query.q, self.sourceClass.q.id.fieldName), + distinct=True, + orderBy=join.orderBy) + + def _throughToRelatedJoin(self, join): + otherClass = join.otherClass + intTable = sqlbuilder.Table(join.intermediateTable) + print join.joinColumn, join.otherColumn + query = self.queryForSelect().newItems([getattr(intTable, join.joinColumn)]) + query = sqlbuilder.Alias(query, "%s_%s" % (self.sourceClass.__name__, join.joinMethodName)) + print query + clause = sqlbuilder.AND(otherClass.q.id == getattr(intTable, join.otherColumn), + getattr(intTable, join.joinColumn) == getattr(query.q, join.joinColumn)) + ret = otherClass.select(clause, + distinct=True, + orderBy=join.orderBy) + print ret + return ret + + +class _throughTo_getter(object): + def __init__(self, inst): + self.sresult = inst + def __getattr__(self, attr): + return self.sresult._throughTo(attr) + __all__ = ['SelectResults'] Added: SQLObject/branches/sqlbuilder-views/sqlobject/tests/test_select_through.py =================================================================== --- SQLObject/branches/sqlbuilder-views/sqlobject/tests/test_select_through.py (rev 0) +++ SQLObject/branches/sqlbuilder-views/sqlobject/tests/test_select_through.py 2007-02-21 21:26:44 UTC (rev 2339) @@ -0,0 +1,53 @@ +from sqlobject import * +from sqlobject.sqlbuilder import * +from sqlobject.tests.dbtest import * + +''' Going to test that complex sqlbuilder constructions are never + prematurely stringified. A straight-forward approach is to use + Bools, since postgresql wants special formatting in queries. + The test is whether a call to sqlrepr(x, 'postgres') includes + the appropriate bool formatting throughout. +''' + +class SRThrough1(SQLObject): + three = ForeignKey('SRThrough3') + twos = SQLMultipleJoin('SRThrough2', joinColumn='oneID') + +class SRThrough2(SQLObject): + one = ForeignKey('SRThrough1') + threes = SQLRelatedJoin('SRThrough3', addRemoveName='Three') + +class SRThrough3(SQLObject): + name = StringCol() + ones = SQLMultipleJoin('SRThrough1', joinColumn='threeID') + twos = SQLRelatedJoin('SRThrough2') + + +def setup_module(mod): + setupClass([mod.SRThrough3, mod.SRThrough1, mod.SRThrough2]) + threes = inserts(mod.SRThrough3, + [('a',),('b',),('c',)], + 'name') + ones = inserts(mod.SRThrough1, + [(threes[0].id,),(threes[0].id,),(threes[2].id,)], + 'threeID') + twos = inserts(mod.SRThrough2, + [(ones[0].id,),(ones[1].id,),(ones[2].id,)], + 'oneID') + twos[0].addThree(threes[0]) + twos[0].addThree(threes[1]) + mod.threes = threes + mod.twos = twos + mod.ones = ones + +def testThroughFK(): + assert list(threes[0].ones.throughTo.three) == [threes[0]] + +def testThroughMultipleJoin(): + assert list(threes[0].ones.throughTo.twos) == [twos[0], twos[1]] + +def testThroughRelatedJoin(): + print [list(x.threes) for x in threes[0].twos] + assert list(threes[0].twos.throughTo.threes) == [threes[0], threes[1]] + + \ No newline at end of file |