From 9f45dc5ced20fa59f9cf3f0e3a4dc4e93d93d905 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sat, 16 Jul 2005 05:43:29 +0000 Subject: [PATCH] --- lib/sqlalchemy/mapper.py | 55 ++++++++++++++++++++++++++++------------ test/mapper.py | 38 +++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 16 deletions(-) create mode 100644 test/mapper.py diff --git a/lib/sqlalchemy/mapper.py b/lib/sqlalchemy/mapper.py index 0558eac4f4..2e8252aa5a 100644 --- a/lib/sqlalchemy/mapper.py +++ b/lib/sqlalchemy/mapper.py @@ -59,11 +59,19 @@ class Mapper(object): 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): @@ -102,41 +110,51 @@ class Mapper(object): 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 @@ -150,6 +168,7 @@ class ResultProxy: def fetchone(self): row = self.cursor.fetchone() + print "row: " + repr(row) if row is not None: return RowProxy(self, row) else: @@ -177,7 +196,11 @@ class IdentityMap(object): 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) diff --git a/test/mapper.py b/test/mapper.py new file mode 100644 index 0000000000..048e8673f3 --- /dev/null +++ b/test/mapper.py @@ -0,0 +1,38 @@ +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() -- 2.47.2