that patch is in for 0.8 and 0.9.

On Feb 27, 2014, at 7:29 PM, Michael Bayer <mike...@zzzcomputing.com> wrote:

> 
> On Feb 27, 2014, at 4:38 PM, Rob Crowell <rob.crow...@moat.com> wrote:
> 
>> 
>>     # in_ clause with 1 STRING, 1 BINARY
>>     filter_cols = tuple_(HashTest.hash_val, HashTest.hash_type)
>>     filter_vals = ((encoded_hash, 'md5'),)
>> 
>>     q = session.query(HashTest)
>>     q = q.filter(filter_cols.in_((filter_vals)))
>>                                                              ^
>> HINT:  No operator matches the given name and argument type(s). You might 
>> need to add explicit type casts.
>>  'SELECT hashtest.hash_test.hash_val AS hashtest_hash_test_hash_val, 
>> hashtest.hash_test.hash_type AS hashtest_hash_test_hash_type, 
>> hashtest.hash_test.region AS hashtest_hash_test_region \nFROM 
>> hashtest.hash_test \nWHERE (hashtest.hash_test.hash_val, 
>> hashtest.hash_test.hash_type) IN ((%(param_1)s, %(param_2)s))' {'param_1': 
>> <psycopg2._psycopg.Binary object at 0x2d9d850>, 'param_2': 
>> <psycopg2._psycopg.Binary object at 0x2c18940>}
>> 
>> 
>> It's complaining about an improper encoding for the BINARY column.
> 
> this has nothing to do with encoding and instead is about typing.   you can 
> see in the output that SQLAlchemy is turning both elements of the IN tuple 
> into a Binary which would appear to be inappropriate here - the 
> sqlalchemy.sql.Tuple object isn’t yet smart enough to handle heterogeneous 
> types.    There’s a patch which will resolve this attached to 
> https://bitbucket.org/zzzeek/sqlalchemy/issue/2977/tuple_-needs-to-record-heterogeneous-types
>  .   
> 
> In the meantime you can actually lift and use that Tuple class that’s in the 
> patch:
> 
> from sqlalchemy.sql.expression import ClauseList, ColumnElement, \
>         _literal_as_binds, BindParameter
> from sqlalchemy import types
> 
> class tuple_(ClauseList, ColumnElement):
>     def __init__(self, *clauses, **kw):
>         clauses = [_literal_as_binds(c) for c in clauses]
>         self.type = types.NULLTYPE
>         self._type_tuple = [arg.type for arg in clauses]
> 
>         super(tuple_, self).__init__(*clauses, **kw)
> 
>     @property
>     def _select_iterable(self):
>         return (self, )
> 
>     def _bind_param(self, operator, obj):
>         return tuple_(*[
>             BindParameter(None, o, _compared_to_operator=operator,
>                              _compared_to_type=type_, unique=True)
>             for o, type_ in zip(obj, self._type_tuple)
>         ]).self_group()
> 
> 
> 

Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail

Reply via email to