]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
(no commit message)
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 23 Jul 2005 18:55:08 +0000 (18:55 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 23 Jul 2005 18:55:08 +0000 (18:55 +0000)
lib/sqlalchemy/ansisql.py
lib/sqlalchemy/engine.py
lib/sqlalchemy/mapper.py
lib/sqlalchemy/sql.py
test/mapper.py

index e269e7efd7eda8289f0c702c028595c9fe02e2a2..0d93ea5188c3483e82b9e19fbf0dee56ed583030 100644 (file)
@@ -148,7 +148,7 @@ class ANSICompiler(sql.Compiled):
         else:
             collist = string.join([c.fullname for c in inner_columns], ', ')
 
-        text = "SELECT " + collist + " FROM "
+        text = "SELECT " + collist + " \nFROM "
         
         whereclause = select.whereclause
         
@@ -171,7 +171,7 @@ class ANSICompiler(sql.Compiled):
         if whereclause is not None:
             t = self.get_str(whereclause)
             if t:
-                text += " WHERE " + t
+                text += " \nWHERE " + t
 
         for tup in select._clauses:
             text += " " + tup[0] + " " + self.get_str(tup[1])
index 855c2e801ebd9d604b86153bfe66f71b80ae3d16..bfa1e2535579ea4535152117c7ffca2d7689a36c 100644 (file)
@@ -115,11 +115,11 @@ class SQLEngine(schema.SchemaEngine):
                 self.context.transaction = None
                 self.context.tcount = None
                 
-    def execute(self, statement, parameters, connection = None, **params):
+    def execute(self, statement, parameters, connection = None, echo = None, **params):
         if parameters is None:
             parameters = {}
         
-        if self._echo:
+        if echo is True or self._echo:
             self.log(statement)
             self.log(repr(parameters))
             
@@ -143,15 +143,16 @@ class ResultProxy:
         metadata = cursor.description
         self.props = {}
         i = 0
-        for item in metadata:
-            self.props[item[0]] = i
-            self.props[i] = i
-            i+=1
+        if metadata is not None:
+            for item in metadata:
+                self.props[item[0]] = i
+                self.props[i] = i
+                i+=1
 
     def fetchone(self):
         row = self.cursor.fetchone()
         if row is not None:
-            print repr(row)
+            #print repr(row)
             return RowProxy(self, row)
         else:
             return None
index 59b1d5a2afe6e7aea279859c49357cddd93f0b29..7122418cc3392afefcdd1fefcfb1287edb03b171 100644 (file)
@@ -47,10 +47,10 @@ def relation_loader(mapper, secondary = None, primaryjoin = None, secondaryjoin
         return EagerLoader(mapper, secondary, primaryjoin, secondaryjoin, **options)
     
 def relation_mapper(class_, selectable, secondary = None, primaryjoin = None, secondaryjoin = None, table = None, properties = None, lazy = True, **options):
-    return relation_loader(mapper(class_, selectable, table = table, properties = properties, isroot = False), secondary, primaryjoin, secondaryjoin, lazy = lazy, **options)
+    return relation_loader(mapper(class_, selectable, table = table, properties = properties, isroot = False, **options), secondary, primaryjoin, secondaryjoin, lazy = lazy, **options)
 
-def mapper(class_, selectable, table = None, properties = None, identitymap = None, use_smart_properties = True, isroot = True):
-    return Mapper(class_, selectable, table = table, properties = properties, identitymap = identitymap, use_smart_properties = use_smart_properties, isroot = isroot)
+def mapper(*args, **params):
+    return Mapper(*args, **params)
 
 def identitymap():
     return IdentityMap()
@@ -65,7 +65,7 @@ def lazyload(name):
     return LazyOption(name)
 
 class Mapper(object):
-    def __init__(self, class_, selectable, table = None, properties = None, identitymap = None, use_smart_properties = True, isroot = True):
+    def __init__(self, class_, selectable, table = None, properties = None, identitymap = None, use_smart_properties = True, isroot = True, echo = None):
         self.class_ = class_
         self.selectable = selectable
         self.use_smart_properties = use_smart_properties
@@ -74,7 +74,8 @@ class Mapper(object):
         else:
             self.table = table
         self.props = {}
-        
+
+        self.echo = echo
         for column in self.selectable.columns:
             self.props[column.key] = ColumnProperty(column)
 
@@ -97,6 +98,7 @@ class Mapper(object):
     def init(self, root):
         self.root = root
         self.identitymap = root.identitymap
+        self.echo = self.root.echo
         [prop.init(key, self, root) for key, prop in self.props.iteritems()]
             
     def instances(self, cursor):
@@ -122,6 +124,9 @@ class Mapper(object):
         return self._compile(whereclause, **options)
     
     def options(self, *options):
+        """uses this mapper as a prototype for a new mapper with different behavior.
+        
+        *options is a list of options directives, which include eagerload() and lazyload()"""
         mapper = copy.copy(self)
         for option in options:
             option.process(mapper)
@@ -200,6 +205,7 @@ class Mapper(object):
     
     def _select_statement(self, statement, **params):
         statement.use_labels = True
+        statement.echo = self.echo
         return self.instances(statement.execute(**params))
 
     def _identity_key(self, row):
@@ -296,6 +302,14 @@ class PropertyLoader(MapperProperty):
     def init(self, key, parent, root):
         self.key = key
         self.mapper.init(root)
+        if self.secondary is not None:
+            if self.secondaryjoin is None:
+                self.secondaryjoin = match_primaries(self.target, self.secondary)
+            if self.primaryjoin is None:
+                self.primaryjoin = match_primaries(parent.selectable, self.secondary)
+        else:
+            if self.primaryjoin is None:
+                self.primaryjoin = match_primaries(parent.selectable, self.target)
 
     def save(self, object, traverse, refetch):
         # if a mapping table does not exist, save a row for all objects
@@ -316,10 +330,16 @@ class LazyLoader(PropertyLoader):
     def init(self, key, parent, root):
         PropertyLoader.init(self, key, parent, root)
         if not hasattr(parent.class_, key):
+            if not issubclass(parent.class_, object):
+                raise "LazyLoader can only be used with new-style classes, i.e. subclass object"
             setattr(parent.class_, key, SmartProperty(key).property())
-
+        
     def setup(self, key, primarytable, statement, **options):
-        self.lazywhere = self.whereclause.copy_structure()
+        if self.secondaryjoin is not None:
+            self.lazywhere = sql.and_(self.primaryjoin, self.secondaryjoin)
+        else:
+            self.lazywhere = self.primaryjoin
+        self.lazywhere = self.lazywhere.copy_structure()
         li = LazyIzer(primarytable)
         self.lazywhere.accept_visitor(li)
         self.binds = li.binds
@@ -337,16 +357,6 @@ class LazyLoader(PropertyLoader):
 class EagerLoader(PropertyLoader):
     def init(self, key, parent, root):
         PropertyLoader.init(self, key, parent, root)
-        
-        if self.secondary is not None:
-            if self.secondaryjoin is None:
-                self.secondaryjoin = match_primaries(self.target, self.secondary)
-            if self.primaryjoin is None:
-                self.primaryjoin = match_primaries(parent.selectable, self.secondary)
-        else:
-            if self.primaryjoin is None:
-                self.primaryjoin = match_primaries(parent.selectable, self.target)
-        
         self.to_alias = util.Set()
         [self.to_alias.append(f) for f in self.primaryjoin._get_from_objects()]
         if self.secondaryjoin is not None:
@@ -379,7 +389,7 @@ class EagerLoader(PropertyLoader):
         statement.append_from(statement._outerjoin)
         statement.append_column(self.target)
         for key, value in self.mapper.props.iteritems():
-            value.setup(key, self.mapper.selectable, statement) 
+            value.setup(key, self.mapper.selectable, statement)
         
     def execute(self, instance, row, identitykey, localmap, isduplicate):
         """receive a row.  tell our mapper to look for a new object instance in the row, and attach
@@ -399,7 +409,7 @@ class EagerOption(MapperOption):
 
     def process(self, mapper):
         oldprop = mapper.props[self.key]
-        mapper.set_property(self.key, EagerLoader(oldprop.mapper, oldprop.whereclause))
+        mapper.set_property(self.key, EagerLoader(oldprop.mapper, oldprop.secondary, primaryjoin = oldprop.primaryjoin, secondaryjoin = oldprop.secondaryjoin))
         
 class LazyOption(MapperOption):
     """an option that switches a PropertyLoader to be a LazyLoader"""
index 1c7efd8777055fee1acc41fe5d9593cb01cd64d6..29de0d34fcc48a6659d78715f0578d5bc44df5ef 100644 (file)
@@ -122,6 +122,10 @@ class ClauseElement(object):
         return engine.compile(self, bindparams = bindparams)
 
     def copy_structure(self):
+        """allows the copying of a statement's containers, so that a modified statement
+        can be produced without affecting the original.  containing clauseelements,
+        like Select, Join, CompoundClause, BinaryClause, etc.,  should produce a copy of 
+        themselves, whereas "leaf-node" clauseelements should return themselves."""
         return self
         
     def _engine(self):
@@ -133,7 +137,7 @@ class ClauseElement(object):
         # TODO: do pre-execute right here, for sequences, if the compiled object
         # defines it
         # TODO: why do we send the params twice, once to compile, once to c.get_params
-        return e.execute(str(c), c.get_params(**params))
+        return e.execute(str(c), c.get_params(**params), echo = getattr(self, 'echo', None))
 
     def result(self, **params):
         e = self._engine()
@@ -277,6 +281,7 @@ class Selectable(FromClause):
     c = property(lambda self: self.columns)
 
     def accept_visitor(self, visitor):
+        print repr(self.__class__)
         raise NotImplementedError()
     
     def select(self, whereclauses = None, **params):
@@ -361,6 +366,9 @@ class ColumnSelectable(Selectable):
         else:
             self.label = self.column.name
             self.fullname = self.column.name
+
+    def copy_structure(self):
+        return self.column
     
     def _get_from_objects(self):
         return [self.column.table]
index 0d5f3f46a4d2a6df8945f06a2c5981958d9ea50a..12d9048d949db991478f0932595603e7f455cd93 100644 (file)
@@ -5,7 +5,7 @@ import sqlalchemy.databases.sqlite as sqllite
 
 memory = True
 if memory:
-    db = sqllite.engine(':memory:', {}, echo = True)
+    db = sqllite.engine(':memory:', {}, echo = False)
 else:
     if os.access('querytest.db', os.F_OK):
         os.remove('querytest.db')
@@ -134,7 +134,6 @@ class MapperTest(PersistTest):
     
     def setUp(self):
         globalidentity().clear()
-    
         
     def testload(self):
         """tests loading rows with a mapper and producing object instances"""
@@ -147,8 +146,8 @@ class MapperTest(PersistTest):
     def testoptions(self):
         """tests that a lazy relation can be upgraded to an eager relation via the options method"""
         m = mapper(User, users, properties = dict(
-            addresses = relation(Address, addresses, users.c.user_id==addresses.c.user_id, lazy = True)
-        ))
+            addresses = relation(Address, addresses, lazy = True)
+        ), echo = True)
         l = m.options(eagerload('addresses')).select()
         print repr(l)
     
@@ -159,8 +158,8 @@ class LazyTest(PersistTest):
     def testbasic(self):
         """tests a basic one-to-many lazy load"""
         m = mapper(User, users, properties = dict(
-            addresses = relation(Address, addresses, users.c.user_id==addresses.c.user_id, lazy = True)
-        ))
+            addresses = relation(Address, addresses, lazy = True)
+        ), echo = True)
         l = m.select(users.c.user_id == 7)
         user = l[0]
         a = user.addresses
@@ -171,17 +170,13 @@ class LazyTest(PersistTest):
         items = orderitems
 
         m = mapper(Item, items, properties = dict(
-                keywords = relation(Keyword, keywords,
-                    and_(items.c.item_id == itemkeywords.c.item_id, keywords.c.keyword_id == itemkeywords.c.keyword_id), lazy = True),
-            ))
-        l = m.select()
-        print repr(l)
+                keywords = relation(Keyword, keywords, itemkeywords, lazy = True),
+            ), echo = True)
+ #       l = m.select()
+ #       print repr(l)
 
         l = m.select(and_(keywords.c.name == 'red', keywords.c.keyword_id == itemkeywords.c.keyword_id, items.c.item_id==itemkeywords.c.item_id))
-        print repr(l)            
-
-        
-        
+        print repr(l)
 
 class EagerTest(PersistTest):
     
@@ -191,8 +186,8 @@ class EagerTest(PersistTest):
     def testbasic(self):
         """tests a basic one-to-many eager load"""
         m = mapper(User, users, properties = dict(
-            addresses = relation(Address, addresses, lazy = False)
-        ))
+            addresses = relation(Address, addresses, lazy = False),
+        ), echo = True)
         l = m.select()
         print repr(l)
 
@@ -202,14 +197,14 @@ class EagerTest(PersistTest):
         criterion doesnt interfere with the eager load criterion."""
         m = mapper(User, users, properties = dict(
             addresses = relation(Address, addresses, primaryjoin = users.c.user_id==addresses.c.user_id, lazy = False)
-        ))
+        ), echo = True)
         l = m.select(and_(addresses.c.email_address == 'ed@lala.com', addresses.c.user_id==users.c.user_id))
         print repr(l)
 
     def testcompile(self):
         """tests deferred operation of a pre-compiled mapper statement"""
         m = mapper(User, users, properties = dict(
-            addresses = relation(Address, addresses, users.c.user_id==addresses.c.user_id, lazy = False)
+            addresses = relation(Address, addresses, lazy = False)
         ))
         s = m.compile(and_(addresses.c.email_address == bindparam('emailad'), addresses.c.user_id==users.c.user_id))
         c = s.compile()
@@ -221,8 +216,8 @@ class EagerTest(PersistTest):
     def testmultieager(self):
         """tests eager loading with two relations simultaneously"""
         m = mapper(User, users, properties = dict(
-            addresses = relation(Address, addresses, users.c.user_id==addresses.c.user_id, lazy = False),
-            orders = relation(Order, orders, users.c.user_id==orders.c.user_id, lazy = False),
+            addresses = relation(Address, addresses, primaryjoin = users.c.user_id==addresses.c.user_id, lazy = False),
+            orders = relation(Order, orders, lazy = False),
         ), identitymap = identitymap())
         l = m.select()
         print repr(l)
@@ -233,8 +228,8 @@ class EagerTest(PersistTest):
         openorders = alias(orders, 'openorders')
         closedorders = alias(orders, 'closedorders')
         m = mapper(User, users, properties = dict(
-            orders_open = relation(Order, openorders, and_(openorders.c.isopen == 1, users.c.user_id==openorders.c.user_id), lazy = False),
-            orders_closed = relation(Order, closedorders, and_(closedorders.c.isopen == 0, users.c.user_id==closedorders.c.user_id), lazy = False)
+            orders_open = relation(Order, openorders, primaryjoin = and_(openorders.c.isopen == 1, users.c.user_id==openorders.c.user_id), lazy = False),
+            orders_closed = relation(Order, closedorders, primaryjoin = and_(closedorders.c.isopen == 0, users.c.user_id==closedorders.c.user_id), lazy = False)
         ), identitymap = identitymap())
         l = m.select()
         print repr(l)
@@ -243,12 +238,12 @@ class EagerTest(PersistTest):
         """tests eager loading, where one of the eager loaded items also eager loads its own 
         child items."""
         ordermapper = mapper(Order, orders, properties = dict(
-                items = relation(Item, orderitems, orders.c.order_id == orderitems.c.order_id, lazy = False)
+                items = relation(Item, orderitems, lazy = False)
             ))
 
         m = mapper(User, users, properties = dict(
-            addresses = relation(Address, addresses, users.c.user_id==addresses.c.user_id, lazy = False),
-            orders = relation(ordermapper, users.c.user_id==orders.c.user_id, lazy = False),
+            addresses = relation(Address, addresses, lazy = False),
+            orders = relation(ordermapper, primaryjoin = users.c.user_id==orders.c.user_id, lazy = False),
         ))
         l = m.select()
         print repr(l)
@@ -258,12 +253,26 @@ class EagerTest(PersistTest):
         
         m = mapper(Item, items, properties = dict(
                 keywords = relation(Keyword, keywords, itemkeywords, lazy = False),
-            ))
+            ), echo = True)
         l = m.select()
         print repr(l)
         
         l = m.select(and_(keywords.c.name == 'red', keywords.c.keyword_id == itemkeywords.c.keyword_id, items.c.item_id==itemkeywords.c.item_id))
         print repr(l)            
-        
+    
+    def testoneandmany(self):
+        items = orderitems
+
+        m = mapper(Item, items, properties = dict(
+                keywords = relation(Keyword, keywords, itemkeywords, lazy = False),
+            ))
+        m = mapper(Order, orders, properties = dict(
+                items = relation(m, lazy = False)
+            ), echo = True)
+        l = m.select("orders.order_id in (1,2,3)")
+        print repr(l)
+
+    
+    
 if __name__ == "__main__":
     unittest.main()