]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
(no commit message)
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 16 Jul 2005 05:43:29 +0000 (05:43 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 16 Jul 2005 05:43:29 +0000 (05:43 +0000)
lib/sqlalchemy/mapper.py
test/mapper.py [new file with mode: 0644]

index 0558eac4f4dce855a62cc509a1aa2a81880ab46a..2e8252aa5a0b5045a134f7a0d9637ef20ba0a13c 100644 (file)
@@ -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 (file)
index 0000000..048e867
--- /dev/null
@@ -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()