First draft for batch_fetch

This commit is contained in:
Konsta Vesterinen
2013-08-03 18:02:49 +03:00
parent a701505a64
commit 654d6cf599
4 changed files with 59 additions and 7 deletions

View File

@@ -8,6 +8,6 @@ python:
- 2.7 - 2.7
- 3.3 - 3.3
install: install:
- pip install -q -e ".[test]" --use-mirrors - pip install -e ".[test]"
script: script:
- python setup.py test - python setup.py test

View File

@@ -33,7 +33,7 @@ extras_require = {
'Jinja2>=2.3', 'Jinja2>=2.3',
'docutils>=0.10', 'docutils>=0.10',
'flexmock>=0.9.7', 'flexmock>=0.9.7',
'psycopg2>=2.4.6' 'psycopg2>=2.4.6',
], ],
'arrow': ['arrow>=0.3.4'], 'arrow': ['arrow>=0.3.4'],
'phone': [ 'phone': [

View File

@@ -1,7 +1,12 @@
from .exceptions import ImproperlyConfigured from .exceptions import ImproperlyConfigured
from .functions import ( from .functions import (
sort_query, defer_except, escape_like, primary_keys, table_name, batch_fetch,
render_statement defer_except,
escape_like,
primary_keys,
render_statement,
sort_query,
table_name,
) )
from .listeners import coercion_listener from .listeners import coercion_listener
from .merge import merge, Merger from .merge import merge, Merger
@@ -33,9 +38,8 @@ __version__ = '0.16.2'
__all__ = ( __all__ = (
ImproperlyConfigured, batch_fetch,
coercion_listener, coercion_listener,
sort_query,
defer_except, defer_except,
escape_like, escape_like,
instrumented_list, instrumented_list,
@@ -43,10 +47,12 @@ __all__ = (
primary_keys, primary_keys,
proxy_dict, proxy_dict,
render_statement, render_statement,
sort_query,
table_name, table_name,
ArrowType, ArrowType,
ColorType, ColorType,
EmailType, EmailType,
ImproperlyConfigured,
InstrumentedList, InstrumentedList,
IPAddressType, IPAddressType,
Merger, Merger,
@@ -59,8 +65,8 @@ __all__ = (
PhoneNumber, PhoneNumber,
PhoneNumberType, PhoneNumberType,
ProxyDict, ProxyDict,
ScalarListType,
ScalarListException, ScalarListException,
ScalarListType,
TimezoneType, TimezoneType,
TSVectorType, TSVectorType,
UUIDType, UUIDType,

View File

@@ -386,3 +386,49 @@ def render_statement(statement, bind=None):
return super(Compiler, self).render_literal_value(value, type_) return super(Compiler, self).render_literal_value(value, type_)
return Compiler(bind.dialect, statement).process(statement) return Compiler(bind.dialect, statement).process(statement)
from sqlalchemy.orm.session import object_session
from sqlalchemy.orm import RelationshipProperty
from sqlalchemy.orm.attributes import set_committed_value
def batch_fetch(entities, attr):
if entities:
first = entities[0]
if isinstance(attr, six.string_types):
attr = getattr(
first.__class__, attr
)
prop = attr.property
if not isinstance(prop, RelationshipProperty):
raise Exception(
'Given attribute is not a relationship property.'
)
model = prop.mapper.class_
session = object_session(first)
if len(prop.remote_side) > 1:
raise Exception(
'Only relationships with single remote side columns are '
'supported.'
)
column_name = list(prop.remote_side)[0].name
parent_ids = [entity.id for entity in entities]
related_entities = (
session.query(model)
.filter(
getattr(model, column_name).in_(parent_ids)
)
)
parent_dict = dict((entity.id, []) for entity in entities)
for entity in related_entities:
parent_dict[getattr(entity, column_name)].append(entity)
for entity in entities:
set_committed_value(entity, prop.key, parent_dict[entity.id])