def test_many_to_one_delete_all(self):
        mapper(
            Node,
            nodes,
            properties={'parent': relationship(Node, remote_side=nodes.c.id)})
        sess = create_session()

        n1 = Node(data='n1')
        n2, n3 = Node(data='n2', parent=n1), Node(data='n3', parent=n1)

        sess.add_all([n2, n3])
        sess.flush()

        sess.delete(n1)
        sess.delete(n2)
        sess.delete(n3)
        self.assert_sql_execution(
            testing.db, sess.flush,
            CompiledSQL("DELETE FROM nodes WHERE nodes.id = :id",
                        lambda ctx: [{
                            'id': n2.id
                        }, {
                            'id': n3.id
                        }]),
            CompiledSQL("DELETE FROM nodes WHERE nodes.id = :id",
                        lambda ctx: {'id': n1.id}))
    def test_flush_size(self):
        class Node(Base):
            pass

        class FooBar(Base):
            pass

        mapper(Node,
               nodes,
               properties={
                   'children': relationship(Node),
                   'foobars': relationship(FooBar)
               })
        mapper(FooBar, foobars)

        sess = create_session()
        n1 = Node(data='n1')
        n2 = Node(data='n2')
        n1.children.append(n2)
        sess.add(n1)
        # ensure "foobars" doesn't get yanked in here
        self._assert_uow_size(sess, 3)

        n1.foobars.append(FooBar())
        # saveupdateall/deleteall for FooBar added here,
        # plus processstate node.foobars
        # currently the "all" procs stay in pairs
        self._assert_uow_size(sess, 6)

        sess.flush()
    def test_singlecycle_flush_size(self):
        mapper(Node, nodes, properties={'children': relationship(Node)})
        sess = create_session()
        n1 = Node(data='ed')
        sess.add(n1)
        self._assert_uow_size(sess, 2)

        sess.flush()

        n1.data = 'jack'

        self._assert_uow_size(sess, 2)
        sess.flush()

        n2 = Node(data='foo')
        sess.add(n2)
        sess.flush()

        n1.children.append(n2)

        self._assert_uow_size(sess, 3)

        sess.flush()

        sess = create_session()
        n1 = sess.query(Node).first()
        n1.data = 'ed'
        self._assert_uow_size(sess, 2)

        n1.children
        self._assert_uow_size(sess, 2)
    def test_one_to_many_delete_parent(self):
        mapper(Node, nodes, properties={'children': relationship(Node)})
        sess = create_session()

        n2, n3 = Node(data='n2', children=[]), Node(data='n3', children=[])
        n1 = Node(data='n1', children=[n2, n3])

        sess.add(n1)
        sess.flush()

        sess.delete(n1)
        self.assert_sql_execution(
            testing.db, sess.flush,
            AllOf(
                CompiledSQL(
                    "UPDATE nodes SET parent_id=:parent_id "
                    "WHERE nodes.id = :nodes_id", lambda ctx: {
                        'nodes_id': n3.id,
                        'parent_id': None
                    }),
                CompiledSQL(
                    "UPDATE nodes SET parent_id=:parent_id "
                    "WHERE nodes.id = :nodes_id", lambda ctx: {
                        'nodes_id': n2.id,
                        'parent_id': None
                    }),
            ),
            CompiledSQL("DELETE FROM nodes WHERE nodes.id = :id",
                        lambda ctx: {'id': n1.id}))
    def test_many_to_one_save(self):
        mapper(
            Node,
            nodes,
            properties={'parent': relationship(Node, remote_side=nodes.c.id)})
        sess = create_session()

        n1 = Node(data='n1')
        n2, n3 = Node(data='n2', parent=n1), Node(data='n3', parent=n1)

        sess.add_all([n2, n3])

        self.assert_sql_execution(
            testing.db, sess.flush,
            CompiledSQL(
                "INSERT INTO nodes (parent_id, data) VALUES "
                "(:parent_id, :data)", {
                    'parent_id': None,
                    'data': 'n1'
                }),
            AllOf(
                CompiledSQL(
                    "INSERT INTO nodes (parent_id, data) VALUES "
                    "(:parent_id, :data)", lambda ctx: {
                        'parent_id': n1.id,
                        'data': 'n2'
                    }),
                CompiledSQL(
                    "INSERT INTO nodes (parent_id, data) VALUES "
                    "(:parent_id, :data)", lambda ctx: {
                        'parent_id': n1.id,
                        'data': 'n3'
                    }),
            ))
    def test_singlecycle_flush_size(self):
        mapper(Node, nodes, properties={
            'children':relationship(Node)
        })
        sess = create_session()
        n1 = Node(data='ed')
        sess.add(n1)
        self._assert_uow_size(sess, 2)

        sess.flush()

        n1.data='jack'

        self._assert_uow_size(sess, 2)
        sess.flush()

        n2 = Node(data='foo')
        sess.add(n2)
        sess.flush()

        n1.children.append(n2)

        self._assert_uow_size(sess, 3)

        sess.flush()

        sess = create_session()
        n1 = sess.query(Node).first()
        n1.data='ed'
        self._assert_uow_size(sess, 2)

        n1.children
        self._assert_uow_size(sess, 2)
    def test_cycle_rowswitch(self):
        mapper(Node, nodes, properties={'children': relationship(Node)})
        sess = create_session()

        n2, n3 = Node(data='n2', children=[]), Node(data='n3', children=[])
        n1 = Node(data='n1', children=[n2])

        sess.add(n1)
        sess.flush()
        sess.delete(n2)
        n3.id = n2.id
        n1.children.append(n3)
        sess.flush()
Example #8
0
    def test_bidirectional_mutations_one(self):
        mapper(Node, nodes, properties={
            'children':relationship(Node, 
                                    backref=backref('parent',
                                                remote_side=nodes.c.id))
        })
        sess = create_session()

        n2, n3 = Node(data='n2', children=[]), Node(data='n3', children=[])
        n1 = Node(data='n1', children=[n2])
        sess.add(n1)
        sess.flush()
        sess.delete(n2)
        n1.children.append(n3)
        sess.flush()
        
        sess.delete(n1)
        sess.delete(n3)
        sess.flush()
    def test_one_to_many_delete_all(self):
        mapper(Node, nodes, properties={'children': relationship(Node)})
        sess = create_session()

        n2, n3 = Node(data='n2', children=[]), Node(data='n3', children=[])
        n1 = Node(data='n1', children=[n2, n3])

        sess.add(n1)
        sess.flush()

        sess.delete(n1)
        sess.delete(n2)
        sess.delete(n3)
        self.assert_sql_execution(
            testing.db, sess.flush,
            CompiledSQL("DELETE FROM nodes WHERE nodes.id = :id",
                        lambda ctx: [{
                            'id': n2.id
                        }, {
                            'id': n3.id
                        }]),
            CompiledSQL("DELETE FROM nodes WHERE nodes.id = :id",
                        lambda ctx: {'id': n1.id}))
Example #10
0
 def test_bidirectional_multilevel_save(self):
     mapper(Node, nodes, properties={
         'children':relationship(Node, 
             backref=backref('parent', remote_side=nodes.c.id)
         )
     })
     sess = create_session()
     n1 = Node(data='n1')
     n1.children.append(Node(data='n11'))
     n1.children.append(Node(data='n12'))
     n1.children.append(Node(data='n13'))
     n1.children[1].children.append(Node(data='n121'))
     n1.children[1].children.append(Node(data='n122'))
     n1.children[1].children.append(Node(data='n123'))
     sess.add(n1)
     sess.flush()
    def test_many_to_many_one(self):
        class Node(Base):
            pass

        mapper(
            Node,
            nodes,
            properties={
                'children':
                relationship(
                    Node,
                    secondary=node_to_nodes,
                    primaryjoin=nodes.c.id == node_to_nodes.c.left_node_id,
                    secondaryjoin=nodes.c.id == node_to_nodes.c.right_node_id,
                    backref='parents'),
                'favorite':
                relationship(Node, remote_side=nodes.c.id)
            })

        sess = create_session()
        n1 = Node(data='n1')
        n2 = Node(data='n2')
        n3 = Node(data='n3')
        n4 = Node(data='n4')
        n5 = Node(data='n5')

        n4.favorite = n3
        n1.favorite = n5
        n5.favorite = n2

        n1.children = [n2, n3, n4]
        n2.children = [n3, n5]
        n3.children = [n5, n4]

        sess.add_all([n1, n2, n3, n4, n5])

        # can't really assert the SQL on this easily
        # since there's too many ways to insert the rows.
        # so check the end result
        sess.flush()
        eq_(
            sess.query(node_to_nodes.c.left_node_id,
                            node_to_nodes.c.right_node_id).\
                    order_by(node_to_nodes.c.left_node_id,
                            node_to_nodes.c.right_node_id).\
                    all(),
            sorted([
                    (n1.id, n2.id), (n1.id, n3.id), (n1.id, n4.id),
                    (n2.id, n3.id), (n2.id, n5.id),
                    (n3.id, n5.id), (n3.id, n4.id)
                ])
        )

        sess.delete(n1)

        self.assert_sql_execution(
            testing.db,
            sess.flush,
            # this is n1.parents firing off, as it should, since
            # passive_deletes is False for n1.parents
            CompiledSQL(
                "SELECT nodes.id AS nodes_id, nodes.data AS nodes_data, "
                "nodes.favorite_node_id AS nodes_favorite_node_id FROM "
                "nodes, node_to_nodes WHERE :param_1 = "
                "node_to_nodes.right_node_id AND nodes.id = "
                "node_to_nodes.left_node_id",
                lambda ctx: {u'param_1': n1.id},
            ),
            CompiledSQL(
                "DELETE FROM node_to_nodes WHERE "
                "node_to_nodes.left_node_id = :left_node_id AND "
                "node_to_nodes.right_node_id = :right_node_id",
                lambda ctx: [{
                    'right_node_id': n2.id,
                    'left_node_id': n1.id
                }, {
                    'right_node_id': n3.id,
                    'left_node_id': n1.id
                }, {
                    'right_node_id': n4.id,
                    'left_node_id': n1.id
                }]),
            CompiledSQL("DELETE FROM nodes WHERE nodes.id = :id",
                        lambda ctx: {'id': n1.id}),
        )

        for n in [n2, n3, n4, n5]:
            sess.delete(n)

        # load these collections
        # outside of the flush() below
        n4.children
        n5.children

        self.assert_sql_execution(
            testing.db,
            sess.flush,
            CompiledSQL(
                "DELETE FROM node_to_nodes WHERE node_to_nodes.left_node_id "
                "= :left_node_id AND node_to_nodes.right_node_id = "
                ":right_node_id", lambda ctx: [{
                    'right_node_id': n5.id,
                    'left_node_id': n3.id
                }, {
                    'right_node_id': n4.id,
                    'left_node_id': n3.id
                }, {
                    'right_node_id': n3.id,
                    'left_node_id': n2.id
                }, {
                    'right_node_id': n5.id,
                    'left_node_id': n2.id
                }]),
            CompiledSQL("DELETE FROM nodes WHERE nodes.id = :id",
                        lambda ctx: [{
                            'id': n4.id
                        }, {
                            'id': n5.id
                        }]),
            CompiledSQL("DELETE FROM nodes WHERE nodes.id = :id",
                        lambda ctx: [{
                            'id': n2.id
                        }, {
                            'id': n3.id
                        }]),
        )
    def test_delete_unloaded_m2o(self):
        mapper(
            Node,
            nodes,
            properties={'parent': relationship(Node, remote_side=nodes.c.id)})

        parent = Node()
        c1, c2 = Node(parent=parent), Node(parent=parent)

        session = Session()
        session.add_all([c1, c2])
        session.add(parent)

        session.flush()

        pid = parent.id
        c1id = c1.id
        c2id = c2.id

        session.expire(parent)
        session.expire(c1)
        session.expire(c2)

        session.delete(c1)
        session.delete(c2)
        session.delete(parent)

        # testing that relationships
        # are loaded even if all ids/references are
        # expired
        self.assert_sql_execution(
            testing.db,
            session.flush,
            AllOf(
                # ensure all three m2os are loaded.
                # the selects here are in fact unexpiring
                # each row - the m2o comes from the identity map.
                CompiledSQL(
                    "SELECT nodes.id AS nodes_id, nodes.parent_id AS "
                    "nodes_parent_id, "
                    "nodes.data AS nodes_data FROM nodes "
                    "WHERE nodes.id = :param_1", lambda ctx: {'param_1': pid}),
                CompiledSQL(
                    "SELECT nodes.id AS nodes_id, nodes.parent_id AS "
                    "nodes_parent_id, "
                    "nodes.data AS nodes_data FROM nodes "
                    "WHERE nodes.id = :param_1",
                    lambda ctx: {'param_1': c1id}),
                CompiledSQL(
                    "SELECT nodes.id AS nodes_id, nodes.parent_id AS "
                    "nodes_parent_id, "
                    "nodes.data AS nodes_data FROM nodes "
                    "WHERE nodes.id = :param_1",
                    lambda ctx: {'param_1': c2id}),
            ),
            CompiledSQL("DELETE FROM nodes WHERE nodes.id = :id",
                        lambda ctx: [{
                            'id': c1id
                        }, {
                            'id': c2id
                        }]),
            CompiledSQL("DELETE FROM nodes WHERE nodes.id = :id",
                        lambda ctx: {'id': pid}),
        )
 def test_bidirectional_multilevel_save(self):
     mapper(Node,
            nodes,
            properties={
                'children':
                relationship(Node,
                             backref=backref('parent',
                                             remote_side=nodes.c.id))
            })
     sess = create_session()
     n1 = Node(data='n1')
     n1.children.append(Node(data='n11'))
     n12 = Node(data='n12')
     n1.children.append(n12)
     n1.children.append(Node(data='n13'))
     n1.children[1].children.append(Node(data='n121'))
     n1.children[1].children.append(Node(data='n122'))
     n1.children[1].children.append(Node(data='n123'))
     sess.add(n1)
     self.assert_sql_execution(
         testing.db,
         sess.flush,
         CompiledSQL(
             "INSERT INTO nodes (parent_id, data) VALUES "
             "(:parent_id, :data)", lambda ctx: {
                 'parent_id': None,
                 'data': 'n1'
             }),
         CompiledSQL(
             "INSERT INTO nodes (parent_id, data) VALUES "
             "(:parent_id, :data)", lambda ctx: {
                 'parent_id': n1.id,
                 'data': 'n11'
             }),
         CompiledSQL(
             "INSERT INTO nodes (parent_id, data) VALUES "
             "(:parent_id, :data)", lambda ctx: {
                 'parent_id': n1.id,
                 'data': 'n12'
             }),
         CompiledSQL(
             "INSERT INTO nodes (parent_id, data) VALUES "
             "(:parent_id, :data)", lambda ctx: {
                 'parent_id': n1.id,
                 'data': 'n13'
             }),
         CompiledSQL(
             "INSERT INTO nodes (parent_id, data) VALUES "
             "(:parent_id, :data)", lambda ctx: {
                 'parent_id': n12.id,
                 'data': 'n121'
             }),
         CompiledSQL(
             "INSERT INTO nodes (parent_id, data) VALUES "
             "(:parent_id, :data)", lambda ctx: {
                 'parent_id': n12.id,
                 'data': 'n122'
             }),
         CompiledSQL(
             "INSERT INTO nodes (parent_id, data) VALUES "
             "(:parent_id, :data)", lambda ctx: {
                 'parent_id': n12.id,
                 'data': 'n123'
             }),
     )
    def test_many_to_many_one(self):
        class Node(Base):
            pass

        mapper(Node, nodes, properties={
            'children':relationship(Node, secondary=node_to_nodes,
                primaryjoin=nodes.c.id==node_to_nodes.c.left_node_id,
                secondaryjoin=nodes.c.id==node_to_nodes.c.right_node_id,
                backref='parents'
            ),
            'favorite':relationship(Node, remote_side=nodes.c.id)
        })

        sess = create_session()
        n1 = Node(data='n1')
        n2 = Node(data='n2')
        n3 = Node(data='n3')
        n4 = Node(data='n4')
        n5 = Node(data='n5')

        n4.favorite = n3
        n1.favorite = n5
        n5.favorite = n2

        n1.children = [n2, n3, n4]
        n2.children = [n3, n5]
        n3.children = [n5, n4]

        sess.add_all([n1, n2, n3, n4, n5])

        # can't really assert the SQL on this easily
        # since there's too many ways to insert the rows.
        # so check the end result
        sess.flush()
        eq_(
            sess.query(node_to_nodes.c.left_node_id,
                            node_to_nodes.c.right_node_id).\
                    order_by(node_to_nodes.c.left_node_id,
                            node_to_nodes.c.right_node_id).\
                    all(), 
            sorted([
                    (n1.id, n2.id), (n1.id, n3.id), (n1.id, n4.id), 
                    (n2.id, n3.id), (n2.id, n5.id), 
                    (n3.id, n5.id), (n3.id, n4.id)
                ])
        )

        sess.delete(n1)

        self.assert_sql_execution(
                testing.db,
                sess.flush,
                # this is n1.parents firing off, as it should, since
                # passive_deletes is False for n1.parents
                CompiledSQL(
                    "SELECT nodes.id AS nodes_id, nodes.data AS nodes_data, "
                    "nodes.favorite_node_id AS nodes_favorite_node_id FROM "
                    "nodes, node_to_nodes WHERE :param_1 = "
                    "node_to_nodes.right_node_id AND nodes.id = "
                    "node_to_nodes.left_node_id" ,
                    lambda ctx:{u'param_1': n1.id},
                ),
                CompiledSQL(
                    "DELETE FROM node_to_nodes WHERE "
                    "node_to_nodes.left_node_id = :left_node_id AND "
                    "node_to_nodes.right_node_id = :right_node_id",
                    lambda ctx:[
                        {'right_node_id': n2.id, 'left_node_id': n1.id}, 
                        {'right_node_id': n3.id, 'left_node_id': n1.id}, 
                        {'right_node_id': n4.id, 'left_node_id': n1.id}
                    ]
                ),
                CompiledSQL(
                    "DELETE FROM nodes WHERE nodes.id = :id",
                    lambda ctx:{'id': n1.id}
                ),
        )

        for n in [n2, n3, n4, n5]:
            sess.delete(n)

        # load these collections
        # outside of the flush() below
        n4.children
        n5.children

        self.assert_sql_execution(
            testing.db,
            sess.flush,
            CompiledSQL(
                "DELETE FROM node_to_nodes WHERE node_to_nodes.left_node_id "
                "= :left_node_id AND node_to_nodes.right_node_id = "
                ":right_node_id",
                lambda ctx:[
                    {'right_node_id': n5.id, 'left_node_id': n3.id}, 
                    {'right_node_id': n4.id, 'left_node_id': n3.id}, 
                    {'right_node_id': n3.id, 'left_node_id': n2.id}, 
                    {'right_node_id': n5.id, 'left_node_id': n2.id}
                ]
            ),
            CompiledSQL(
                "DELETE FROM nodes WHERE nodes.id = :id",
                lambda ctx:[{'id': n4.id}, {'id': n5.id}]
            ),
            CompiledSQL(
                "DELETE FROM nodes WHERE nodes.id = :id",
                lambda ctx:[{'id': n2.id}, {'id': n3.id}]
            ),
        )