Skip to content
This repository has been archived by the owner on Feb 7, 2019. It is now read-only.

Commit

Permalink
Added a condition such that querytime filters get added only a single…
Browse files Browse the repository at this point in the history
… time; extended unittest documentation
  • Loading branch information
maennel committed Jan 29, 2015
1 parent 8636abe commit 30b86d2
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 4 deletions.
6 changes: 4 additions & 2 deletions versions/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ def get_compiler(self, *args, **kwargs):
(e.g. by adding a filter to the queryset) does not allow the caching of related
object to work (they are attached to a queryset; filter() returns a new queryset).
"""
if self.querytime.active:
if self.querytime.active and (not hasattr(self, '_querytime_filter_added') or not self._querytime_filter_added):
time = self.querytime.time
if time is None:
self.add_q(Q(version_end_date__isnull=True))
Expand All @@ -318,6 +318,9 @@ def get_compiler(self, *args, **kwargs):
(Q(version_end_date__gt=time) | Q(version_end_date__isnull=True))
& Q(version_start_date__lte=time)
)
# Ensure applying these filters happens only a single time (even if it doesn't falsify the query, it's
# just not very comfortable to read)
self._querytime_filter_added = True
return super(VersionedQuery, self).get_compiler(*args, **kwargs)


Expand Down Expand Up @@ -504,7 +507,6 @@ def get_joining_columns(self, reverse_join=False):
return joining_columns



class VersionedManyToManyField(ManyToManyField):
def __init__(self, *args, **kwargs):
super(VersionedManyToManyField, self).__init__(*args, **kwargs)
Expand Down
29 changes: 27 additions & 2 deletions versions_tests/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,10 @@ def setUp(self):

self.t1 = get_utc_now()
sleep(0.1)
# State at t1
# Players: [p1.v1, p2.v1]
# Teams: [t.v1]
# t.player_set = [p1, p2]

team.player_set.remove(p2)

Expand All @@ -687,6 +691,10 @@ def setUp(self):

self.t2 = get_utc_now()
sleep(0.1)
# State at t2
# Players: [p1.v1, p2.v1, p2.v2]
# Teams: [t.v1]
# t.player_set = [p1]

team.player_set.remove(p1)

Expand All @@ -696,6 +704,10 @@ def setUp(self):

self.t3 = get_utc_now()
sleep(0.1)
# State at t3
# Players: [p1.v1, p2.v1, p2.v2, p1.v2]
# Teams: [t.v1]
# t.player_set = []

# Let's get those players back into the game!
team.player_set.add(p1)
Expand All @@ -711,10 +723,18 @@ def setUp(self):

self.t4 = get_utc_now()
sleep(0.1)
# State at t4
# Players: [p1.v1, p2.v1, p2.v2, p1.v2, p2.v3, p1.v3]
# Teams: [t.v1]
# t.player_set = [p1, p2]

p1.delete()

self.t5 = get_utc_now()
# State at t4
# Players: [p1.v1, p2.v1, p2.v2, p1.v2, p2.v3, p1.v3]
# Teams: [t.v1]
# t.player_set = [p2]

def test_filtering_on_the_other_side_of_the_relation(self):
self.assertEqual(1, Team.objects.all().count())
Expand Down Expand Up @@ -774,6 +794,8 @@ def test_filtering_for_deleted_player_at_t5(self):
@skipUnless(connection.vendor == 'sqlite', 'SQL is database specific, only sqlite is tested here.')
def test_query_created_by_filtering_for_deleted_player_at_t5(self):
team_none_queryset = Team.objects.as_of(self.t5).filter(player__name__startswith='p1')
# Validating the current query prior to analyzing the generated SQL
self.assertEqual([], list(team_none_queryset))
team_none_query = str(team_none_queryset.query)

team_table = Team._meta.db_table
Expand Down Expand Up @@ -1566,7 +1588,10 @@ def test_select_related(self):

@skipUnless(connection.vendor == 'sqlite', 'SQL is database specific, only sqlite is tested here.')
def test_select_related_query_sqlite(self):
select_related_query = str(Player.objects.as_of(self.t1).select_related('team').all().query)
select_related_queryset = Player.objects.as_of(self.t1).select_related('team').all()
# Validating the query before verifying the SQL string
self.assertEqual(['pl1.v1', 'pl2.v1'], [player.name for player in select_related_queryset])
select_related_query = str(select_related_queryset.query)

team_table = Team._meta.db_table
player_table = Player._meta.db_table
Expand Down Expand Up @@ -1625,7 +1650,7 @@ def test_select_related_query_postgresql(self):
"{team_table}"."name",
"{team_table}"."city_id"
FROM "{player_table}"
LEFT OUTER JOIN "{team_table}" ON ("{player_table}"."team_id" = "{team_table}"."id"
LEFT OUTER JOIN "{team_table}" ON ("{player_table}"."team_id" = "{team_table}"."identity"
AND (({team_table}.version_start_date <= {ts}
AND ({team_table}.version_end_date > {ts}
OR {team_table}.version_end_date IS NULL))))
Expand Down

0 comments on commit 30b86d2

Please sign in to comment.