- column defaults and onupdates, executing inline, will add parenthesis
for subqueries and other parenthesis-requiring expressions
+- fixes to ShardedSession to work with deferred columns [ticket:771].
+
+- user-defined shard_chooser() function must accept "clause=None"
+ argument; this is the ClauseElement passed to session.execute(statement)
+ and can be used to determine correct shard id (since execute() doesn't
+ take an instance)
+
0.4.0beta5
----------
from sqlalchemy.orm import *
from sqlalchemy.orm.shard import ShardedSession
from sqlalchemy.sql import operators
+from sqlalchemy import sql
import datetime
# step 2. databases
# note that we need to define conditions for
# the WeatherLocation class, as well as our secondary Report class which will
# point back to its WeatherLocation via its 'location' attribute.
-def shard_chooser(mapper, instance):
+def shard_chooser(mapper, instance, clause=None):
if isinstance(instance, WeatherLocation):
return shard_lookup[instance.continent]
else:
If this ``Session`` is transactional, the connection will be in
the context of this session's transaction. Otherwise, the
- connection is returned by the ``contextual_connect()`` method, which
- some Engines override to return a thread-local connection, and
- will have `close_with_result` set to `True`.
-
- The given `**kwargs` will be sent to the engine's
- ``contextual_connect()`` method, if no transaction is in
- progress.
+ connection is returned by the ``contextual_connect()`` method
+ on the engine.
the "mapper" argument is a class or mapper to which a bound engine
will be located; use this when the Session itself is either bound
to multiple engines or connections, or is not bound to any connectable.
+
+ \**kwargs are additional arguments which will be passed to get_bind().
+ See the get_bind() method for details. Note that the "ShardedSession"
+ subclass takes a different get_bind() argument signature.
"""
- return self.__connection(self.get_bind(mapper))
+ return self.__connection(self.get_bind(mapper, **kwargs))
def __connection(self, engine, **kwargs):
if self.transaction is not None:
self.__binds[table] = bind
- def get_bind(self, mapper, clause=None):
-
+ def get_bind(self, mapper, clause=None, **kwargs):
+ """return an engine corresponding to the given arguments.
+
+ mapper
+ mapper relative to the desired operation
+
+ clause
+ a ClauseElement which is to be executed. if
+ mapper is not present, this may be used to locate
+ Table objects, which are then associated with mappers
+ which have associated binds.
+
+ \**kwargs
+ Subclasses (i.e. ShardedSession) may add additional arguments
+ to get_bind() which are passed through here.
+ """
+
if mapper is None and clause is None:
if self.bind is not None:
return self.bind
"""construct a ShardedSession.
shard_chooser
- a callable which, passed a Mapper and a mapped instance, returns a
- shard ID. this id may be based off of the attributes present within the
- object, or on some round-robin scheme. If the scheme is based on a
- selection, it should set whatever state on the instance to mark it in
- the future as participating in that shard.
+ a callable which, passed a Mapper, a mapped instance, and possibly a
+ SQL clause, returns a shard ID. this id may be based off of the
+ attributes present within the object, or on some round-robin scheme. If
+ the scheme is based on a selection, it should set whatever state on the
+ instance to mark it in the future as participating in that shard.
id_chooser
a callable, passed a query and a tuple of identity values,
else:
return self.get_bind(mapper, shard_id=shard_id, instance=instance).contextual_connect(**kwargs)
- def get_bind(self, mapper, shard_id=None, instance=None):
+ def get_bind(self, mapper, shard_id=None, instance=None, clause=None):
if shard_id is None:
- shard_id = self.shard_chooser(mapper, instance)
+ shard_id = self.shard_chooser(mapper, instance, clause=clause)
return self.__binds[shard_id]
def bind_shard(self, shard_id, bind):
statement = sql.select([p.columns[0] for p in group], clause, from_obj=[localparent.mapped_table], use_labels=True)
else:
statement, params = create_statement()
-
- result = session.execute(statement, params, mapper=localparent)
+
+ conn = session.connection(mapper=localparent, instance=instance)
+ result = conn.execute(statement, params)
try:
row = result.fetchone()
for prop in group:
'South America':'south_america'
}
- def shard_chooser(mapper, instance):
+ def shard_chooser(mapper, instance, clause=None):
if isinstance(instance, WeatherLocation):
return shard_lookup[instance.continent]
else:
self.temperature = temperature
mapper(WeatherLocation, weather_locations, properties={
- 'reports':relation(Report, backref='location')
+ 'reports':relation(Report, backref='location'),
+ 'city': deferred(weather_locations.c.city),
})
mapper(Report, weather_reports)