summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-01-07 22:09:17 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2010-01-07 22:09:17 +0000
commited6cbe607c33df6deb1388578dffccfe72cb9714 (patch)
tree42a567f1aeacc6e44b8cfbd79a659ea7bc407190 /test
parent9ee458a619b443a24b195d4374759cff2e54e4bd (diff)
downloadsqlalchemy-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.py85
-rw-r--r--test/orm/test_merge.py40
-rw-r--r--test/orm/test_query.py1
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)