]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
fixed a _get_criterion mismatch, cleaned up types + updated types doc
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 5 May 2006 17:23:00 +0000 (17:23 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 5 May 2006 17:23:00 +0000 (17:23 +0000)
doc/build/content/document_base.myt
doc/build/content/types.txt
lib/sqlalchemy/mapping/mapper.py
lib/sqlalchemy/mapping/query.py
lib/sqlalchemy/types.py

index ed5c937de143cb5fe62f7265476c692c4346624d..38d13ec811ad7b2ca9a74c7aa9b6962f9b081d1e 100644 (file)
@@ -24,7 +24,7 @@
     onepage='documentation'
     index='index'
     title='SQLAlchemy Documentation'
-    version = '0.1.6'
+    version = '0.1.7'
 </%attr>
 
 <%method title>
index a979035b27417cb1502dbdd0bf79ae807f3670d3..2ed230ac952eb4dd1a5c33a0890bda9404d78173 100644 (file)
@@ -23,6 +23,7 @@ The standard set of generic types are:
     class Float(Numeric):
         def __init__(self, precision=10)
     
+    # DateTime, Date, and Time work with Python datetime objects
     class DateTime(TypeEngine)
     
     class Date(TypeEngine)
@@ -38,11 +39,11 @@ The standard set of generic types are:
     # as bind params, raw bytes to unicode as 
     # rowset values, using the unicode encoding 
     # setting on the engine (defaults to 'utf-8')
-    class Unicode(String)
+    class Unicode(TypeDecorator)
     
     # uses the pickle protocol to serialize data
     # in/out of Binary columns
-    class PickleType(Binary)
+    class PickleType(TypeDecorator)
 
 More specific subclasses of these types are available, which various database engines may choose to implement specifically, allowing finer grained control over types:
 
@@ -76,51 +77,23 @@ Type objects are specified to table meta data using either the class itself, or
 
 ### Creating your Own Types {@name=custom}
 
-User-defined types can be created, to support either database-specific types, or customized pre-processing of query parameters as well as post-processing of result set data.  You can make your own classes to perform these operations.  They are specified by subclassing the desired type class:
+User-defined types can be created, to support either database-specific types, or customized pre-processing of query parameters as well as post-processing of result set data.  You can make your own classes to perform these operations.  To augment the behavior of a `TypeEngine` type, such as `String`, the `TypeDecorator` class is used:
 
     {python title="Basic Example"}
     import sqlalchemy.types as types
 
-    class MyType(types.String):
+    class MyType(types.TypeDecorator):
         """basic type that decorates String, prefixes values with "PREFIX:" on 
         the way in and strips it off on the way out."""
+        impl = types.String
         def convert_bind_param(self, value, engine):
             return "PREFIX:" + value
         def convert_result_value(self, value, engine):
             return value[7:]
+            
+The `Unicode` and `PickleType` classes are instances of `TypeDecorator` already and can be subclassed directly.
 
-A common desire is for a "pickle" type, which overrides a Binary object to provide pickling behavior:
-
-    {python title="Pickle Type"}
-    import cPickle
-
-    class PickleType(Binary):
-        def __init__(self, protocol=pickle.HIGHEST_PROTOCOL):
-            """allows the pickle protocol to be specified"""
-            self.protocol = protocol
-        def convert_result_value(self, value, engine):
-            if value is None:
-              return None
-            buf = Binary.convert_result_value(self, value, engine)
-            return pickle.loads(str(buf))
-        def convert_bind_param(self, value, engine):
-            if value is None:
-              return None
-            return Binary.convert_bind_param(self, pickle.dumps(value, self.protocol), engine)
-        def get_constructor_args(self):
-            return {}
-
-Which can be used like:
-
-    {python}
-    mytable = Table('mytable', engine, 
-            Column('id', Integer, primary_key=True),
-            Column('data', PickleType()))
-        
-    my_object = MyObject()
-    mytable.insert().execute(data=my_object)
-
-Another example, which illustrates a fully defined datatype.  This just overrides the base type class TypeEngine:
+To build a type object from scratch, which will not have a corresponding database-specific implementation, subclass `TypeEngine`:
 
     {python}
     import sqlalchemy.types as types
@@ -134,7 +107,4 @@ Another example, which illustrates a fully defined datatype.  This just override
             return value
         def convert_result_value(self, value, engine):
             return value
-        def adapt_args(self):
-            """allows for the adaptation of this TypeEngine object into a new kind of type depending on its arguments."""
-            return self
 
index 15d197a3400e28ac50a1ac1b9925a4e728d98cf9..7977cae6a68b586b365a7c050da396bada41698f 100644 (file)
@@ -450,6 +450,22 @@ class Mapper(object):
             self._options[optkey] = mapper
             return mapper
 
+    def _get_criterion(self, key, value):
+        """used by select_by to match a key/value pair against
+        local properties, column names, or a matching property in this mapper's
+        list of relations."""
+        if self.props.has_key(key):
+            return self.props[key].columns[0] == value
+        elif self.table.c.has_key(key):
+            return self.table.c[key] == value
+        else:
+            for prop in self.props.values():
+                c = prop.get_criterion(key, value)
+                if c is not None:
+                    return c
+            else:
+                return None
+
     def __getattr__(self, key):
         if (key.startswith('select_by_') or key.startswith('get_by_')):
             return getattr(self.query, key)
index 2ef23c5606792ae04cbd1c6cbc304f354021a3ea..283e8c1890e6b56c015a508986858f68ae405d64 100644 (file)
@@ -177,7 +177,7 @@ class Query(object):
         for key, value in params.iteritems():
             if value is False:
                 continue
-            c = self._get_criterion(key, value)
+            c = self.mapper._get_criterion(key, value)
             if c is None:
                 raise InvalidRequestError("Cant find criterion for property '"+ key + "'")
             if clause is None:
@@ -261,18 +261,3 @@ class Query(object):
             value.setup(key, statement, **kwargs) 
         return statement
 
-    def _get_criterion(self, key, value):
-        """used by select_by to match a key/value pair against
-        local properties, column names, or a matching property in this mapper's
-        list of relations."""
-        if self.props.has_key(key):
-            return self.props[key].columns[0] == value
-        elif self.table.c.has_key(key):
-            return self.table.c[key] == value
-        else:
-            for prop in self.props.values():
-                c = prop.get_criterion(key, value)
-                if c is not None:
-                    return c
-            else:
-                return None
index 40b94bbd8e924d94730e9d71fd7ae8081d187af5..bc894184f9244bfcff770c00199f3a78451c5994 100644 (file)
@@ -67,7 +67,9 @@ class TypeDecorator(AbstractType):
     def convert_result_value(self, value, engine):
         return self.impl.convert_result_value(value, engine)
     def copy(self):
-        raise NotImplementedError()
+        instance = self.__class__.__new__(self.__class__)
+        instance.__dict__.update(self.__dict__)
+        return instance
         
 def to_instance(typeobj):
     if typeobj is None:
@@ -132,8 +134,6 @@ class Unicode(TypeDecorator):
              return value.decode(engine.encoding)
          else:
              return value
-    def copy(self):
-        return Unicode(self.impl.length)
         
 class Integer(TypeEngine):
     """integer datatype"""
@@ -194,8 +194,6 @@ class PickleType(TypeDecorator):
       if value is None:
           return None
       return self.impl.convert_bind_param(pickle.dumps(value, self.protocol), engine)
-    def copy(self):
-        return PickleType(self.protocol)
 
 class Boolean(TypeEngine):
     pass