On Sep 18, 2009, at 7:47 PM, Mike Orr wrote:

>
> I have the following TypeDecorator type to store a tuple of strings as
> a delimited string.  It works fine but I discovered an abnormality
> with LIKE.  The right side of a like expression is being passed to the
> converter, so it has to be a one-item tuple instead of a string.  This
> makes my model unintuitive.  Am I doing something wrong or is this
> just a corollary of how TypeDecorator works?

the purpose of process_bind_param() is to marshal data from a  
particular in-python format into a format that is understood by the  
database.    It seems here that you'd like it in some situations to  
allow the database-understood format to pass right through, and that  
maybe you're using it more as a "validator" specific to INSERT/UPDATE  
statements and not SELECT.

The two ways around it would be to allow your process_bind_param() to  
accept strings, or to place your validation at a level that does  
distinguish between CRUD and SELECT - validation with the ORM is  
easiest by using the @validates decorator, for example.

There's a ticket out there which would add some extra capabilities to  
types, allowing them to be consulted to generate SQL expressions for  
example.   Maybe additional info about the statement could be passed  
to the bind/result methods (i.e. the ExecutionContext).


>
>
> m.Chemical.synonyms.like((like,))     # Ugly
>
> q = q.filter(m.UN.synonyms.like(("%" + term + "%",)))     # Ugly
>
>
> class MultiText(sa.types.TypeDecorator):
>    """Store a tuple of string values as a single delimited string.
>
>    Legal values are a tuple of strings, or ``None`` for NULL.
>    Lists are not allowed because SQLAlchemy can't recognize in-place
>    modifications.
>
>    Note that during SQL queries (e.g., column LIKE "%ABC%"), the
>    comparision is against the delimited string.  This may cause  
> unexpected
>    results if the control value contains the delimeter as a substring.
>    """
>
>    impl = sa.types.Text
>
>    def __init__(self, delimiter, *args, **kw):
>        """Constructor.
>
>        The first positional arg is the delimiter, and is required.
>
>        All other positional and keyword args are passed to the  
> underlying
>        column type.
>        """
>        if not isinstance(delimiter, basestring):
>            msg = "arg ``delimiter`` must be string, not %r"
>            raise TypeError(msg % delimiter)
>        self.delimiter = delimiter
>        sa.types.TypeDecorator.__init__(self, *args, **kw)
>
>    def process_bind_param(self, value, dialect):
>        """Convert a tuple of strings to a single delimited string.
>
>        Exceptions:
>            ``TypeError`` if the value is neither a tuple nor ``None``.
>            ``TypeError`` if any element is not a string.
>            ``ValueError`` if any element contains the delimeter as a  
> substring.
>        """
>        if value is None:
>            return None
>        if not isinstance(value, tuple):
>            msg = "%s value must be a tuple, not %r"
>            tup = self.__class__.__name__, value
>            raise TypeError(msg % tup)
>        for i, element in enumerate(value):
>            if self.delimiter in element:
>                msg = "delimiter %r found in index %d of %s: %r"
>                tup = (self.delimiter, i, self.__class__.__name, value)
>                raise ValueError(msg % tup)
>        return self.delimiter.join(value)
>
>    def process_result_value(self, value, dialect):
>        """Convert a delimited string to a tuple of strings."""
>        if value is None:
>            return None
>        elif value == "":
>            return ()
>        elements = value.split(self.delimiter)
>        return tuple(elements)
>
>    def copy(self):
>        return self.__class__(self.delimiter, self.impl.length)
>
>
>
>
> -- 
> Mike Orr <sluggos...@gmail.com>
>
> >


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to