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?
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 <[email protected]>
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---