On Fri, Oct 20, 2017 at 2:15 PM, Антонио Антуан <a.ch....@gmail.com> wrote:
> Hi.
> I use my own `RoutingSession` and `RoutingQuery` implementation, most of it
> inspired by `sqlalchemy.ext.horizontal_shard`:
>
> class RoutingSession(Session):
>     def get_bind(self, mapper=None, clause=None, shard_id=None, **kwargs):
>         original_bind = None
>         try:
>             original_bind = super(RoutingSession, self).get_bind(mapper,
> clause)
>         except UnboundExecutionError:
>             # may not be bound
>             pass
>         if shard_id is None:
>             shard_id = TenantIDStorage.get_shard_id()  # just global storage
>         bind_for_shard = self.__binds[shard_id]
>         if original_bind is not None and original_bind.url ==
> bind_for_shard.url:
>             return original_bind
>         else:
>             return bind_for_shard
>
>     def __init__(self, shards=None, query_cls=CachingQuery,
> engines_factory=None, **kwargs):
>         super(RoutingSession, self).__init__(query_cls=query_cls, **kwargs)
>         self.__binds = {}
>         self.engines_factory = engines_factory
>         if shards is not None:
>             self.update_shards(**shards)
>
>     def _add_bind(self, key, bind):
>         self.__binds[key] = bind
>
>
>
>
> class RoutingQuery(Query):
>     def __init__(self, *args, **kwargs):
>         super(RoutingQuery, self).__init__(*args, **kwargs)
>         self._shard_id = TenantIDStorage.get_shard_id()
>
>     def get(self, ident):
>         self._check_bound_to_shard()
>         return super(CachingQuery, self).get(ident)
>
>     def _check_bound_to_shard(self):
>         if self._shard_id is None:
>             raise ValueError('query not bound to any shard')
>
>     def _execute_and_instances(self, querycontext):
>         self._check_bound_to_shard()
>         querycontext.attributes['shard_id'] = self._shard_id
>         result = self._connection_from_session(
>             mapper=self._mapper_zero(),
>             shard_id=self._shard_id).execute(
>             querycontext.statement,
>             self._params
>         )
>         return self.instances(result, querycontext)
>
>
>
>
>
>
> Sometimes I got this error:
>
>   File "/home/anton/Projects/proj/admin/proj/admin/views/stats.py", line
> 898, in _get_filters_from_request
>     control_groups = [g.id for g in
> User.get_own_groups_query(current_user.id)]
>   File
> "/home/anton/Projects/proj/.venv/lib/python2.7/site-packages/sqlalchemy/orm/query.py",
> line 2802, in __iter__
>     return self._execute_and_instances(context)
>   File
> "/home/anton/Projects/proj/core/proj/core/orm_extensions/rouing_session.py",
> line 105, in _execute_and_instances
>     shard_id=self._shard_id).execute(
>   File
> "/home/anton/Projects/proj/.venv/lib/python2.7/site-packages/sqlalchemy/orm/query.py",
> line 2806, in _connection_from_session
>     **kw)
>   File
> "/home/anton/Projects/proj/.venv/lib/python2.7/site-packages/sqlalchemy/orm/session.py",
> line 984, in connection
>     bind = self.get_bind(mapper, clause=clause, **kw)
>   File
> "/home/anton/Projects/proj/core/proj/core/orm_extensions/cachingquery.py",
> line 279, in get_bind
>     original_bind = super(RoutingSession, self).get_bind(mapper, clause)
>   File
> "/home/anton/Projects/proj/.venv/lib/python2.7/site-packages/sqlalchemy/orm/session.py",
> line 1336, in get_bind
>     if mapper and mapper.mapped_table.bind:
>   File
> "/home/anton/Projects/proj/.venv/lib/python2.7/site-packages/sqlalchemy/sql/elements.py",
> line 539, in __bool__
>     raise TypeError("Boolean value of this clause is not defined")
> TypeError: Boolean value of this clause is not defined
>
>
>
>
> I found that `mapper` in original `get_bind` always checks with `is not
> None` condition. There is only one place where condition omitted: `if mapper
> and mapper.mapped_table.bind...`.
> Possibly it is not correct? Or my code does not do something important?

Are you able to catch this error in a debugger?

I'm going to make a wild guess that "mapper" at this point is some
sort of SQL construct (such as a column object or mapped property),
rather than an actual mapper.

You don't say which version of SQLAlchemy you are using, but since
you've overridden _execute_and_instances, I wonder if you need to use
something like query._bind_mapper() as used by _get_bind_args:

<https://bitbucket.org/zzzeek/sqlalchemy/src/4b22b01ade6f94cc4db2f2040c802067a25d29a4/lib/sqlalchemy/orm/query.py?at=rel_1_1_14&fileviewer=file-view-default#query.py-2872>

Hope that helps,

Simon

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to