def test_window_frame_repr(self): self.assertEqual( repr(RowRange(start=-1)), '<RowRange: ROWS BETWEEN 1 PRECEDING AND UNBOUNDED FOLLOWING>') self.assertEqual( repr(ValueRange(start=None, end=1)), '<ValueRange: RANGE BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING>') self.assertEqual( repr(ValueRange(start=0, end=0)), '<ValueRange: RANGE BETWEEN CURRENT ROW AND CURRENT ROW>') self.assertEqual( repr(RowRange(start=0, end=0)), '<RowRange: ROWS BETWEEN CURRENT ROW AND CURRENT ROW>')
def test_range_unbound(self): """A query with RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING.""" qs = Employee.objects.annotate(sum=Window( expression=Sum('salary'), partition_by='age', order_by=[F('age').asc()], frame=ValueRange(start=None, end=None), )).order_by('department', 'hire_date', 'name') self.assertIn( 'RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING', str(qs.query)) self.assertQuerysetEqual( qs, [('Jones', 'Accounting', 45000, datetime.date(2005, 11, 1), 165000), ('Jenson', 'Accounting', 45000, datetime.date(2008, 4, 1), 165000), ('Williams', 'Accounting', 37000, datetime.date(2009, 6, 1), 165000), ('Adams', 'Accounting', 50000, datetime.date(2013, 7, 1), 130000), ('Wilkinson', 'IT', 60000, datetime.date(2011, 3, 1), 194000), ('Moore', 'IT', 34000, datetime.date(2013, 8, 1), 194000), ('Miller', 'Management', 100000, datetime.date(2005, 6, 1), 194000), ('Johnson', 'Management', 80000, datetime.date(2005, 7, 1), 130000), ('Smith', 'Marketing', 38000, datetime.date(2009, 10, 1), 165000), ('Johnson', 'Marketing', 40000, datetime.date(2012, 3, 1), 148000), ('Smith', 'Sales', 55000, datetime.date(2007, 6, 1), 148000), ('Brown', 'Sales', 53000, datetime.date(2009, 9, 1), 148000)], transform=lambda row: (row.name, row.department, row.salary, row.hire_date, row.sum))
def test_range_n_preceding_and_following(self): qs = Employee.objects.annotate(sum=Window( expression=Sum('salary'), order_by=F('salary').asc(), partition_by='department', frame=ValueRange(start=-2, end=2), )) self.assertIn('RANGE BETWEEN 2 PRECEDING AND 2 FOLLOWING', str(qs.query)) self.assertQuerysetEqual(qs, [ ('Williams', 37000, 'Accounting', datetime.date(2009, 6, 1), 37000), ('Jones', 45000, 'Accounting', datetime.date(2005, 11, 1), 90000), ('Jenson', 45000, 'Accounting', datetime.date(2008, 4, 1), 90000), ('Adams', 50000, 'Accounting', datetime.date(2013, 7, 1), 50000), ('Brown', 53000, 'Sales', datetime.date(2009, 9, 1), 53000), ('Smith', 55000, 'Sales', datetime.date(2007, 6, 1), 55000), ('Johnson', 40000, 'Marketing', datetime.date(2012, 3, 1), 40000), ('Smith', 38000, 'Marketing', datetime.date(2009, 10, 1), 38000), ('Wilkinson', 60000, 'IT', datetime.date(2011, 3, 1), 60000), ('Moore', 34000, 'IT', datetime.date(2013, 8, 1), 34000), ('Miller', 100000, 'Management', datetime.date(2005, 6, 1), 100000), ('Johnson', 80000, 'Management', datetime.date(2005, 7, 1), 80000), ], transform=lambda row: (row.name, row.salary, row.department, row. hire_date, row.sum), ordered=False)
def test_invalid_type_start_value_range(self): msg = "start argument must be a negative integer, zero, or None, but got 'a'." with self.assertRaisesMessage(ValueError, msg): list( Employee.objects.annotate(test=Window( expression=Sum('salary'), frame=ValueRange(start='a'), )))
def test_postgresql_illegal_range_frame_end(self): msg = 'PostgreSQL only supports UNBOUNDED together with PRECEDING and FOLLOWING.' with self.assertRaisesMessage(NotSupportedError, msg): list( Employee.objects.annotate(test=Window( expression=Sum('salary'), order_by=F('hire_date').asc(), frame=ValueRange(end=1), )))
def test_invalid_type_end_value_range(self): msg = "end argument must be a positive integer, zero, or None, but got 'a'." with self.assertRaisesMessage(ValueError, msg): list( Employee.objects.annotate(test=Window( expression=Sum('salary'), order_by=F('hire_date').asc(), frame=ValueRange(end='a'), )))