diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2010-01-07 22:09:17 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2010-01-07 22:09:17 +0000 |
| commit | ed6cbe607c33df6deb1388578dffccfe72cb9714 (patch) | |
| tree | 42a567f1aeacc6e44b8cfbd79a659ea7bc407190 /test | |
| parent | 9ee458a619b443a24b195d4374759cff2e54e4bd (diff) | |
| download | sqlalchemy-ed6cbe607c33df6deb1388578dffccfe72cb9714.tar.gz | |
- Session.merge() is performance optimized, using half the
call counts for "load=False" mode compared to 0.5 and
significantly fewer SQL queries in the case of collections
for "load=True" mode.
Diffstat (limited to 'test')
| -rw-r--r-- | test/aaa_profiling/test_orm.py | 85 | ||||
| -rw-r--r-- | test/orm/test_merge.py | 40 | ||||
| -rw-r--r-- | test/orm/test_query.py | 1 |
3 files changed, 125 insertions, 1 deletions
diff --git a/test/aaa_profiling/test_orm.py b/test/aaa_profiling/test_orm.py new file mode 100644 index 000000000..d88e73c67 --- /dev/null +++ b/test/aaa_profiling/test_orm.py @@ -0,0 +1,85 @@ +from sqlalchemy.test.testing import eq_, assert_raises, assert_raises_message +from sqlalchemy import exc as sa_exc, util, Integer, String, ForeignKey +from sqlalchemy.orm import exc as orm_exc, mapper, relation, sessionmaker + +from sqlalchemy.test import testing, profiling +from test.orm import _base +from sqlalchemy.test.schema import Table, Column + + +class MergeTest(_base.MappedTest): + @classmethod + def define_tables(cls, metadata): + parent = Table('parent', metadata, + Column('id', Integer, primary_key=True, test_needs_autoincrement=True), + Column('data', String(20)) + ) + + child = Table('child', metadata, + Column('id', Integer, primary_key=True, test_needs_autoincrement=True), + Column('data', String(20)), + Column('parent_id', Integer, ForeignKey('parent.id'), nullable=False) + ) + + + @classmethod + def setup_classes(cls): + class Parent(_base.BasicEntity): + pass + class Child(_base.BasicEntity): + pass + + @classmethod + @testing.resolve_artifact_names + def setup_mappers(cls): + mapper(Parent, parent, properties={ + 'children':relation(Child, backref='parent') + }) + mapper(Child, child) + + @classmethod + @testing.resolve_artifact_names + def insert_data(cls): + parent.insert().execute( + {'id':1, 'data':'p1'}, + ) + child.insert().execute( + {'id':1, 'data':'p1c1', 'parent_id':1}, + ) + + @testing.resolve_artifact_names + def test_merge_no_load(self): + sess = sessionmaker()() + sess2 = sessionmaker()() + + p1 = sess.query(Parent).get(1) + p1.children + + # down from 185 on this + # this is a small slice of a usually bigger + # operation so using a small variance + @profiling.function_call_count(106, variance=0.001) + def go(): + p2 = sess2.merge(p1, load=False) + + go() + + @testing.resolve_artifact_names + def test_merge_load(self): + sess = sessionmaker()() + sess2 = sessionmaker()() + + p1 = sess.query(Parent).get(1) + p1.children + + # preloading of collection took this down from 1728 + # to 1192 using sqlite3 + @profiling.function_call_count(1192) + def go(): + p2 = sess2.merge(p1) + go() + + # one more time, count the SQL + sess2 = sessionmaker()() + self.assert_sql_count(testing.db, go, 2) + diff --git a/test/orm/test_merge.py b/test/orm/test_merge.py index 533c3ea5d..c3b28386d 100644 --- a/test/orm/test_merge.py +++ b/test/orm/test_merge.py @@ -4,7 +4,8 @@ from sqlalchemy import Integer, PickleType import operator from sqlalchemy.test import testing from sqlalchemy.util import OrderedSet -from sqlalchemy.orm import mapper, relation, create_session, PropComparator, synonym, comparable_property, sessionmaker +from sqlalchemy.orm import mapper, relation, create_session, PropComparator, \ + synonym, comparable_property, sessionmaker, attributes from sqlalchemy.test.testing import eq_, ne_ from test.orm import _base, _fixtures from sqlalchemy.test.schema import Table, Column @@ -379,6 +380,43 @@ class MergeTest(_fixtures.FixtureTest): eq_(u3.name, 'also fred') @testing.resolve_artifact_names + def test_many_to_one_cascade(self): + mapper(Address, addresses, properties={ + 'user':relation(User) + }) + mapper(User, users) + + u1 = User(id=1, name="u1") + a1 =Address(id=1, email_address="a1", user=u1) + u2 = User(id=2, name="u2") + + sess = create_session() + sess.add_all([a1, u2]) + sess.flush() + + a1.user = u2 + + sess2 = create_session() + a2 = sess2.merge(a1) + eq_( + attributes.get_history(a2, 'user'), + ([u2], (), [attributes.PASSIVE_NO_RESULT]) + ) + assert a2 in sess2.dirty + + sess.refresh(a1) + + sess2 = create_session() + a2 = sess2.merge(a1, load=False) + eq_( + attributes.get_history(a2, 'user'), + ((), [u1], ()) + ) + assert a2 not in sess2.dirty + + + + @testing.resolve_artifact_names def test_many_to_many_cascade(self): mapper(Order, orders, properties={ diff --git a/test/orm/test_query.py b/test/orm/test_query.py index 967d1ac6c..bc3b9e26d 100644 --- a/test/orm/test_query.py +++ b/test/orm/test_query.py @@ -929,6 +929,7 @@ class FromSelfTest(QueryTest, AssertsCompiledSQL): sess.query(User.id).from_self().\ add_column(func.count().label('foo')).\ group_by(User.id).\ + order_by(User.id).\ from_self().all(), [ (7,1), (8, 1), (9, 1), (10, 1) |
