def instances(self, cursor):
result = []
cursor = ResultProxy(cursor)
+ lastinstance = None
while True:
row = cursor.fetchone()
if row is None:
break
- result.append(self.identitymap.get(row, self.class_, self.table, creator = self._create))
+ instance = self._instance(row)
+ if instance != lastinstance:
+ result.append(instance)
+ lastinstance = instance
+ else:
+ for key, prop in self.props.iteritems():
+ prop.execute(instance, key, row, True)
+
return result
def get(self, id):
statement.use_labels = True
return self.instances(statement.execute(**params))
+ def _instance(self, row):
+ return self.identitymap.get(row, self.class_, self.table, creator = self._create)
+
def _create(self, row):
instance = self.class_()
for key, prop in self.props.iteritems():
- prop.execute(instance, key, row)
-
+ prop.execute(instance, key, row, False)
return instance
class MapperProperty:
- def execute(self, instance, key, row):
+ def execute(self, instance, key, row, isduplicate):
raise NotImplementedError()
def setup(self, primarytable, statement):
pass
-
+
class ColumnProperty(MapperProperty):
def __init__(self, column):
self.column = column
- def execute(self, instance, key, row):
- setattr(instance, key, row[self.column.label])
+ def execute(self, instance, key, row, isduplicate):
+ if not isduplicate:
+ setattr(instance, key, row[self.column.label])
class EagerLoader(MapperProperty):
def __init__(self, mapper, whereclause):
self.mapper = mapper
self.whereclause = whereclause
def setup(self, primarytable, statement):
- statement.append_from(sql.outerjoin(primarytable, self.mapper.table, self.whereclause))
+ if hasattr(statement, '_outerjoin'):
+ statement._outerjoin.right = sql.outerjoin(primarytable, self.mapper.table, self.whereclause)
+ else:
+ statement._outerjoin = sql.outerjoin(primarytable, self.mapper.table, self.whereclause)
+ statement.append_from(statement._outerjoin)
statement.append_column(self.mapper.table)
- def execute(self, instance, key, row):
- print "eagerloader exec for key " + key
- list = getattr(instance, key, [])
- list.append(self.mapper._create(row))
-
-
-
+ def execute(self, instance, key, row, isduplicate):
+ try:
+ list = getattr(instance, key)
+ except AttributeError:
+ list = []
+ setattr(instance, key, list)
+ subinstance = self.mapper._instance(row)
+ if subinstance is not None:
+ list.append(subinstance)
+
class ResultProxy:
def __init__(self, cursor):
self.cursor = cursor
def fetchone(self):
row = self.cursor.fetchone()
+ print "row: " + repr(row)
if row is not None:
return RowProxy(self, row)
else:
try:
return self.map[key]
except KeyError:
- return self.map.setdefault(key, creator(row))
+ newinstance = creator(row)
+ for column in table.primary_keys:
+ if row[column.label] is None:
+ return None
+ return self.map.setdefault(key, newinstance)
--- /dev/null
+from testbase import PersistTest
+import unittest, sys
+
+import sqlalchemy.databases.sqlite as sqllite
+
+db = sqllite.engine('querytest.db', echo = False)
+
+from sqlalchemy.sql import *
+from sqlalchemy.schema import *
+
+import sqlalchemy.mapper as mapper
+
+class User:
+ def __repr__(self):
+ return "User: " + repr(self.user_id) + " " + self.user_name
+
+class MapperTest(PersistTest):
+
+ def setUp(self):
+ self.users = Table('users', db,
+ Column('user_id', INT, primary_key = True),
+ Column('user_name', VARCHAR(20)),
+ )
+
+ self.users.build()
+ self.users.insert().execute(user_id = 7, user_name = 'jack')
+ self.users.insert().execute(user_id = 8, user_name = 'ed')
+
+ def testmapper(self):
+ m = mapper.Mapper(User, self.users)
+ l = m.select()
+ print repr(l)
+
+ def tearDown(self):
+ self.users.drop()
+
+if __name__ == "__main__":
+ unittest.main()