Source code for sqlalchemy_mptt.tests.cases.integrity
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2015 uralbash <root@uralbash.ru>
#
# Distributed under terms of the MIT license.
from sqlalchemy.sql import func
[docs]
class DataIntegrity(object):
[docs]
def test_left_is_always_less_than_right(self):
""" The left key is always less than the right.
The following example should return an empty result.
.. code-block:: sql
SELECT id FROM tree WHERE left >= right
"""
table = self.model
nop = self.session.query(table).filter(table.left >= table.right).all()
self.assertEqual(nop, [])
[docs]
def test_lowest_left_is_always_1(self):
""" The lowest left key is always 1.
The following example should return 1.
.. code-block:: sql
SELECT MIN(left) FROM tree
"""
table = self.model
one = self.session.query(func.min(table.left)).scalar()
self.assertEqual(one, 1)
[docs]
def test_greatest_right_is_always_double_number_of_nodes(self):
""" The greatest right key is always double the number of nodes.
The following example should match COUNT(id) * 2 equal MAX(right).
.. code-block:: sql
SELECT COUNT(id), MAX(right) FROM tree
"""
table = self.model
result = self.session.query(
func.count(table.get_pk_name()),
func.max(table.right)).group_by(table.tree_id).all()
for tree in result:
self.assertEqual(tree[0] * 2, tree[1])
[docs]
def test_right_minus_left_always_odd(self):
""" Difference between left and right keys are always an odd number.
The following example should return an empty result.
.. code-block:: sql
SELECT MOD((right - left) / 2) AS modulo
FROM tree WHERE modulo = 0
"""
table = self.model
modulo = (table.right - table.left) % 2
nop = self.session.query(table).filter(modulo == 0).all()
self.assertEqual(nop, [])
[docs]
def test_level_odd_when_left_odd_and_vice_versa(self):
""" If the node number is odd then the left key is always an odd
number, and the same goes for the even numbers.
The following example should return an empty result.
.. code-block:: sql
SELECT id, MOD((left - level + 2) / 2) AS modulo FROM tree
WHERE modulo = 1
"""
table = self.model
level_delta = pow(0, table.get_default_level() % 2)
modulo = (table.left - table.level + level_delta + 2) % 2
nop = self.session.query(table).filter(modulo == 1).all()
self.assertEqual(nop, [])
[docs]
def test_left_and_right_always_unique_number(self):
""" left and right always is unique.
"""
table = self.model
left = self.session.query(table.left)
right = self.session.query(table.right)
keys = [x[0] for x in left.union(right)]
self.assertEqual(len(keys), len(set(keys)))
[docs]
def test_hierarchy_structure(self):
""" Nodes with left < self and right > self are considered ancestors,
while nodes with left > self and right < self are considered
descendants
"""
table = self.model
pivot = self.session.query(table).filter(
table.right - table.left != 1
).filter(table.parent_id != None).first() # noqa
# Exclusive Tests
ancestors = self.session.query(table).filter(
table.is_ancestor_of(pivot)
).all()
for ancestor in ancestors:
self.assertTrue(ancestor.is_ancestor_of(pivot))
self.assertNotIn(pivot, ancestors)
descendants = self.session.query(table).filter(
table.is_descendant_of(pivot)
).all()
for descendant in descendants:
self.assertTrue(descendant.is_descendant_of(pivot))
self.assertNotIn(pivot, descendants)
self.assertEqual(set(), set(ancestors).intersection(set(descendants)))
# Inclusive Tests - because sometimes inclusivity is nice, like with
# self joins
ancestors = self.session.query(table).filter(
table.is_ancestor_of(pivot, inclusive=True)
).all()
for ancestor in ancestors:
self.assertTrue(ancestor.is_ancestor_of(pivot, inclusive=True))
self.assertIn(pivot, ancestors)
descendants = self.session.query(table).filter(
table.is_descendant_of(pivot, inclusive=True)
).all()
for descendant in descendants:
self.assertTrue(descendant.is_descendant_of(pivot, inclusive=True))
self.assertIn(pivot, descendants)
self.assertEqual(
set([pivot]),
set(ancestors).intersection(set(descendants))
)