A custom query_cls POC to define in the sessionmaker (i simplify thing by 
only supporting queries which only request one entity):
WrapperQuery : 
==> the wrapper checks SA object session before getting an SA object 
attribute (and if needed we merge it with a new session)
==> merging seems to be costly so i think it must be used with 
scoped_session
==> awfully unefficient if the object is shared between multiples threads 
which get attributes on the same object at the same time
MemoizeWrapperQuery: 
==> the wrapper also memoizes every SA object attributes. 
==> it avoid to check session and merge SA object even when getting SA 
object already loaded attribute
==> we could improve memoize by memoizing SA object already loaded 
attributes on wrapper __init__

Both are not only usable if used for read actions

merging seems to be costly so i think i should

class Wrapper(object):
>     def __init__(self, wrapped):
>         self._wrapped = wrapped
>         self._lock = threading.Lock()
>
>     def __getattr__(self, name):
>         if name == '_sa_instance_state':
>             return self._wrapped._sa_instance_state
>         old_session = object_session(self._wrapped)
>         new_session = api.get_session()
>         with self._lock:
>             if old_session is not new_session:
>                 self._wrapped = new_session.merge(self._wrapped)
>             return getattr(self._wrapped, name)
>
> class CachedWrapper(object):
>     def __init__(self, wrapped):
>         self._wrapped = wrapped
>         self._lock = threading.Lock()
>
>     def __getattr__(self, name):
>         if name == '_sa_instance_state':
>             return self._wrapped._sa_instance_state
>         old_session = object_session(self._wrapped)
>         new_session = api.get_session()
>         with self._lock:
>             if old_session is not new_session:
>                 self._wrapped = new_session.merge(self._wrapped)
>             value = getattr(self._wrapped, name)
>             setattr(self, name, value)
>             return value
>
> class XQuery(query.Query):
>     def __init__(self, wrapper_cls, entities, session=None):
>         super(XQuery, self).__init__(entities, session=session)
>         self._wrapper_cls = wrapper_cls
>     def instances(self, cursor, context):
>         for cursor in super(XQuery, self).instances(cursor, context):
>             yield self._wrapper_cls(cursor)
>
> WrapperQuery = functools.partial(XQuery, Wrapper)
> MemoizeWrapperQuery = functools.partial(XQuery, MemoizeWrapper)
>

Is it the right way ?
Will it be more elegant by customizing the declarative_base() ? 

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sqlalchemy/-/-I8SiXWqkk8J.
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