]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
(no commit message)
authorMike Bayer <mike_mp@zzzcomputing.com>
Sun, 28 Aug 2005 19:36:41 +0000 (19:36 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 28 Aug 2005 19:36:41 +0000 (19:36 +0000)
lib/sqlalchemy/ansisql.py
lib/sqlalchemy/engine.py
lib/sqlalchemy/mapper.py
test/mapper.py
test/select.py

index e0dcc58bd7d772a5fa81ba1c0a80052255a38b12..1782a29f086c21492aa92019b08dbf5f734d2fd2 100644 (file)
@@ -68,12 +68,17 @@ class ANSICompiler(sql.Compiled):
 
     def get_whereclause(self, obj):
         return self.wheres.get(obj, None)
-        
+
     def get_params(self, **params):
         """returns the bind params for this compiled object, with values overridden by 
         those given in the **params dictionary"""
         d = {}
-        for key, value in params.iteritems():
+        if self.bindparams is not None:
+            bindparams = self.bindparams.copy()
+        else:
+            bindparams = {}
+        bindparams.update(params)
+        for key, value in bindparams.iteritems():
             try:
                 b = self.binds[key]
             except KeyError:
@@ -84,7 +89,7 @@ class ANSICompiler(sql.Compiled):
             d.setdefault(b.key, b.value)
 
         return d
-        
+
     def visit_column(self, column):
         if column.table.name is None:
             self.strings[column] = column.name
@@ -121,19 +126,18 @@ class ANSICompiler(sql.Compiled):
         result += " " + self.get_str(binary.right)
         if binary.parens:
             result = "(" + result + ")"
-        
         self.strings[binary] = result
-        
+
     def visit_bindparam(self, bindparam):
         self.binds[bindparam.shortname] = bindparam
-        
         count = 1
         key = bindparam.key
-        
+
+        # redefine the generated name of the bind param in the case
+        # that we have multiple conflicting bind parameters.
         while self.binds.setdefault(key, bindparam) is not bindparam:
             key = "%s_%d" % (bindparam.key, count)
             count += 1
-            
         self.strings[bindparam] = ":" + key
 
     def visit_alias(self, alias):
index e6183c328fbcc6ebfef92a3829057cea15b4c893..7689c53e82571a8504e2acd48a8c4c94db92bab1 100644 (file)
@@ -132,7 +132,7 @@ class SQLEngine(schema.SchemaEngine):
 
         if echo is True or self._echo:
             self.log(statement)
-            self.log(repr(parameters))
+            self.log("here are the params: " + repr(parameters))
 
         if connection is None:
             poolconn = self.connection()
index d8b6caf465796dde4e71250f7977d9d397a7c1f4..c5d2e8c193d3c693337d75e2bf3962c4e60eed15 100644 (file)
@@ -166,7 +166,7 @@ class Mapper(object):
         *options is a list of options directives, which include eagerload() and lazyload()"""
 
         hashkey = hash_key(self) + "->" + repr([hash_key(o) for o in options])
-        print "HASHKEY: " + hashkey
+        #print "HASHKEY: " + hashkey
         try:
             return _mappers[hashkey]
         except KeyError:
@@ -321,6 +321,8 @@ class Mapper(object):
 
 
 class MapperOption:
+    """describes a modification to a Mapper in the context of making a copy
+    of it.  This is used to assist in the prototype pattern used by mapper.options()."""
     def process(self, mapper):
         raise NotImplementedError()
     
@@ -328,7 +330,7 @@ class MapperOption:
         return repr(self)
 
 class MapperProperty:
-    """an element attached to a Mapper that describes the loading and population
+    """an element attached to a Mapper that describes and assists in the loading and saving 
     of an attribute on an object instance."""
     def execute(self, instance, row, identitykey, localmap, isduplicate):
         """called when the mapper receives a row.  instance is the parent instance corresponding
@@ -337,7 +339,8 @@ class MapperProperty:
 
     def hash_key(self):
         """describes this property and its instantiated arguments in such a way
-        as to uniquely identify the concept this MapperProperty represents"""
+        as to uniquely identify the concept this MapperProperty represents,within 
+        a process."""
         raise NotImplementedError()
 
     def setup(self, key, primarytable, statement, **options):
@@ -347,15 +350,17 @@ class MapperProperty:
     def init(self, key, parent, root):
         """called when the MapperProperty is first attached to a new parent Mapper."""
         pass
-    
+
     def save(self, object, traverse, refetch):
+        """called when the instance is being saved"""
         pass
-    
+
     def delete(self, object):
+        """called when the instance is being deleted"""
         pass
 
 class ColumnProperty(MapperProperty):
-    """describes an object attribute that corresponds to the value in a result set column."""
+    """describes an object attribute that corresponds to a table column."""
     def __init__(self, column):
         self.column = column
 
@@ -379,27 +384,6 @@ class ColumnProperty(MapperProperty):
                 setattr(instance, self.key, row[self.column.label])
 
 
-def hash_key(obj):
-    if obj is None:
-        return 'None'
-    else:
-        return obj.hash_key()
-
-def mapper_hash_key(class_, selectable, table = None, properties = None, identitymap = None, use_smart_properties = True, isroot = True, echo = None):
-    if properties is None:
-        properties = {}
-    return (
-        "Mapper(%s, %s, table=%s, properties=%s, identitymap=%s, use_smart_properties=%s, echo=%s)" % (
-            repr(class_),
-            hash_key(selectable),
-            hash_key(table),
-            repr(dict([(k, hash_key(p)) for k,p in properties.iteritems()])),
-            hash_key(identitymap),
-            repr(use_smart_properties),
-            repr(echo)
-
-        )
-    )
 
 class PropertyLoader(MapperProperty):
     def __init__(self, mapper, secondary, primaryjoin, secondaryjoin):
@@ -448,9 +432,9 @@ class LazyLoader(PropertyLoader):
         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"
+                raise "LazyLoader can only be used with new-style classes"
             setattr(parent.class_, key, SmartProperty(key).property())
-        
+
     def setup(self, key, primarytable, statement, **options):
         if self.secondaryjoin is not None:
             self.lazywhere = sql.and_(self.primaryjoin, self.secondaryjoin)
@@ -465,17 +449,37 @@ class LazyLoader(PropertyLoader):
         if not isduplicate:
             setattr(instance, self.key, LazyLoadInstance(self, row))
 
+class LazyIzer(sql.ClauseVisitor):
+    """converts an expression which refers to a table column into an
+    expression refers to a Bind Param, i.e. a specific value.  
+    e.g. the clause 'WHERE tablea.foo=tableb.foo' becomes 'WHERE tablea.foo=:foo'.  
+    this is used to turn a join expression into one useable by a lazy load
+    for a specific parent row."""
+
+    def __init__(self, table):
+        self.table = table
+        self.binds = {}
+
+    def visit_binary(self, binary):
+        if isinstance(binary.left, schema.Column) and binary.left.table == self.table:
+            binary.left = self.binds.setdefault(self.table.name + "_" + binary.left.name,
+                    sql.BindParamClause(self.table.name + "_" + binary.left.name, None, shortname = binary.left.name))
+
+        if isinstance(binary.right, schema.Column) and binary.right.table == self.table:
+            binary.right = self.binds.setdefault(self.table.name + "_" + binary.right.name,
+                    sql.BindParamClause(self.table.name + "_" + binary.right.name, None, shortname = binary.right.name))
+
 class LazyLoadInstance(object):
-    """attached to a specific object instance to load related rows.  this is implemetned
-    as a callable object, rather than a closure, to allow serialization of the target object"""
+    """attached to a specific object instance to load related rows."""
     def __init__(self, lazyloader, row):
         self.params = {}
         for key, value in lazyloader.binds.iteritems():
             self.params[key] = row[key]
-        # TODO: dont attach to the mapper, its huge.
-        # figure out some way to shrink this.
+        # TODO: this still sucks. the mapper points to tables, which point
+        # to dbengines, which cant be serialized, or are too huge to be serialized
+        # quickly, so an object with a lazyloader still cant really be serialized
         self.mapper = lazyloader.mapper
-
+        self.lazywhere = lazyloader.lazywhere
     def __call__(self):
         return self.mapper.select(self.lazywhere, **self.params)
 
@@ -535,7 +539,7 @@ class EagerLazySwitcher(MapperOption):
 
     def hash_key(self):
         return "EagerLazySwitcher(%s, %s)" % (repr(self.key), repr(self.toeager))
-        
+
     def process(self, mapper):
         oldprop = mapper.props[self.key]
         if self.toeager:
@@ -545,6 +549,7 @@ class EagerLazySwitcher(MapperOption):
         mapper.set_property(self.key, class_(oldprop.mapper, oldprop.secondary, primaryjoin = oldprop.primaryjoin, secondaryjoin = oldprop.secondaryjoin))
 
 class Aliasizer(sql.ClauseVisitor):
+    """converts a table instance within an expression to be an alias of that table."""
     def __init__(self, table, aliasname):
         self.table = table
         self.alias = sql.alias(table, aliasname)
@@ -556,19 +561,6 @@ class Aliasizer(sql.ClauseVisitor):
         if isinstance(binary.right, schema.Column) and binary.right.table == self.table:
             binary.right = self.alias.c[binary.right.name]
 
-class LazyIzer(sql.ClauseVisitor):
-    def __init__(self, table):
-        self.table = table
-        self.binds = {}
-        
-    def visit_binary(self, binary):
-        if isinstance(binary.left, schema.Column) and binary.left.table == self.table:
-            binary.left = self.binds.setdefault(self.table.name + "_" + binary.left.name,
-                    sql.BindParamClause(self.table.name + "_" + binary.left.name, None, shortname = binary.left.name))
-
-        if isinstance(binary.right, schema.Column) and binary.right.table == self.table:
-            binary.right = self.binds.setdefault(self.table.name + "_" + binary.right.name,
-                    sql.BindParamClause(self.table.name + "_" + binary.right.name, None, shortname = binary.left.name))
     
 class LazyRow(MapperProperty):
     def __init__(self, table, whereclause, **options):
@@ -598,18 +590,11 @@ class SmartProperty(object):
                 v = s.__dict__[self.key]
             except KeyError:
                 raise AttributeError(self.key)
-            if isinstance(v, types.FunctionType):
+            if callable(v):
                 s.__dict__[self.key] = v()
             return s.__dict__[self.key]
         return property(get_prop, set_prop, del_prop)
 
-def match_primaries(primary, secondary):
-    pk = primary.primary_keys
-    if len(pk) == 1:
-        return (pk[0] == secondary.c[pk[0].name])
-    else:
-        return sql.and_([pk == secondary.c[pk.name] for pk in primary.primary_keys])
-
 class IdentityMap(dict):
     def get_id_key(self, ident, class_, table, selectable):
         return (class_, table, tuple(ident))
@@ -620,5 +605,36 @@ class IdentityMap(dict):
     def hash_key(self):
         return "IdentityMap(%s)" % id(self)
 
+
+def hash_key(obj):
+    if obj is None:
+        return 'None'
+    else:
+        return obj.hash_key()
+
+def mapper_hash_key(class_, selectable, table = None, properties = None, identitymap = None, use_smart_properties = True, isroot = True, echo = None):
+    if properties is None:
+        properties = {}
+    return (
+        "Mapper(%s, %s, table=%s, properties=%s, identitymap=%s, use_smart_properties=%s, echo=%s)" % (
+            repr(class_),
+            hash_key(selectable),
+            hash_key(table),
+            repr(dict([(k, hash_key(p)) for k,p in properties.iteritems()])),
+            hash_key(identitymap),
+            repr(use_smart_properties),
+            repr(echo)
+
+        )
+    )
+
+def match_primaries(primary, secondary):
+    pk = primary.primary_keys
+    if len(pk) == 1:
+        return (pk[0] == secondary.c[pk[0].name])
+    else:
+        return sql.and_([pk == secondary.c[pk.name] for pk in primary.primary_keys])
+
+
 _global_identitymap = IdentityMap()
 
index 1e2eabd92686b86c42fe9b09680668f879540c91..c44d8dcfc5b8c6b4a86f2ae0cec6293daade4086 100644 (file)
@@ -39,7 +39,7 @@ class AssertMixin(PersistTest):
         print repr(result)
         self.assert_list(result, class_, objects)
     def assert_list(self, result, class_, list):
-        for i in range(0, len(result)):
+        for i in range(0, len(list)):
             self.assert_row(class_, result[i], list[i])
     def assert_row(self, class_, rowobj, desc):
         self.assert_(rowobj.__class__ is class_, "item class is not " + repr(class_))
index 1c2e4562cd293f63c5344c828a590676e0f099c0..b55d414b884ae45bd67421b5d9dfab38bff1c479 100644 (file)
@@ -286,6 +286,12 @@ EXISTS (select yay from foo where boo = lar)",
 FROM mytable, myothertable WHERE mytable.myid = myothertable.otherid AND mytable.name = :mytablename"
                 )
 
+        # check that the bind params sent along with a compile() call
+        # get preserved when the params are retreived later
+        s = select([table], table.c.id == bindparam('test'))
+        c = s.compile(bindparams = {'test' : 7})
+        self.assert_(c.get_params() == {'test' : 7})
+
     def testcorrelatedsubquery(self):
         self.runtest(
             select([table], table.c.id == select([table2.c.id], table.c.name == table2.c.name)),