Coverage for tests/test_expressions.py: 33%
46 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-12-01 19:55 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2022-12-01 19:55 +0000
1# This file is part of daf_butler.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
22import unittest
24from sqlalchemy.schema import Column
25from sqlalchemy.dialects import postgresql, sqlite
27from lsst.daf.butler.registry.queries.expressions import convertExpressionToSql, ParserYacc
28from lsst.daf.butler.registry.queries._structs import QueryColumns
29from lsst.daf.butler import DimensionUniverse
30from lsst.daf.butler.core import NamedKeyDict, TimespanDatabaseRepresentation
33class FakeDatasetRecordStorageManager:
34 ingestDate = Column("ingest_date")
37class ConvertExpressionToSqlTestCase(unittest.TestCase):
38 """A test case for convertExpressionToSql method
39 """
41 def setUp(self):
42 self.universe = DimensionUniverse()
44 def test_simple(self):
45 """Test with a trivial expression"""
47 parser = ParserYacc()
48 tree = parser.parse("1 > 0")
49 self.assertIsNotNone(tree)
51 columns = QueryColumns()
52 elements = NamedKeyDict()
53 column_element = convertExpressionToSql(
54 tree, self.universe, columns, elements, {},
55 TimespanDatabaseRepresentation.Compound
56 )
57 self.assertEqual(str(column_element.compile()), ":param_1 > :param_2")
58 self.assertEqual(str(column_element.compile(compile_kwargs={"literal_binds": True})), "1 > 0")
60 def test_time(self):
61 """Test with a trivial expression including times"""
63 parser = ParserYacc()
64 tree = parser.parse("T'1970-01-01 00:00/tai' < T'2020-01-01 00:00/tai'")
65 self.assertIsNotNone(tree)
67 columns = QueryColumns()
68 elements = NamedKeyDict()
69 column_element = convertExpressionToSql(
70 tree, self.universe, columns, elements, {},
71 TimespanDatabaseRepresentation.Compound
72 )
73 self.assertEqual(str(column_element.compile()), ":param_1 < :param_2")
74 self.assertEqual(str(column_element.compile(compile_kwargs={"literal_binds": True})),
75 "0 < 1577836800000000000")
77 def test_ingest_date(self):
78 """Test with an expression including ingest_date which is native UTC"""
80 parser = ParserYacc()
81 tree = parser.parse("ingest_date < T'2020-01-01 00:00/utc'")
82 self.assertIsNotNone(tree)
84 columns = QueryColumns()
85 columns.datasets = FakeDatasetRecordStorageManager()
86 elements = NamedKeyDict()
87 column_element = convertExpressionToSql(
88 tree, self.universe, columns, elements, {},
89 TimespanDatabaseRepresentation.Compound
90 )
92 # render it, needs specific dialect to convert column to expression
93 dialect = postgresql.dialect()
94 self.assertEqual(str(column_element.compile(dialect=dialect)),
95 "ingest_date < TIMESTAMP %(param_1)s")
96 self.assertEqual(str(column_element.compile(dialect=dialect,
97 compile_kwargs={"literal_binds": True})),
98 "ingest_date < TIMESTAMP '2020-01-01 00:00:00.000000'")
100 dialect = sqlite.dialect()
101 self.assertEqual(str(column_element.compile(dialect=dialect)),
102 "datetime(ingest_date) < datetime(?)")
103 self.assertEqual(str(column_element.compile(dialect=dialect,
104 compile_kwargs={"literal_binds": True})),
105 "datetime(ingest_date) < datetime('2020-01-01 00:00:00.000000')")
108if __name__ == "__main__": 108 ↛ 109line 108 didn't jump to line 109, because the condition on line 108 was never true
109 unittest.main()