Coverage for tests/test_expressions.py: 38%
Shortcuts on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
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 lsst.daf.butler import DimensionUniverse
25from lsst.daf.butler.core import NamedKeyDict, TimespanDatabaseRepresentation
26from lsst.daf.butler.registry.queries._structs import QueryColumns
27from lsst.daf.butler.registry.queries.expressions import ParserYacc, convertExpressionToSql
28from sqlalchemy.dialects import postgresql, sqlite
29from sqlalchemy.schema import Column
32class FakeDatasetRecordStorageManager:
33 ingestDate = Column("ingest_date")
36class ConvertExpressionToSqlTestCase(unittest.TestCase):
37 """A test case for convertExpressionToSql method"""
39 def setUp(self):
40 self.universe = DimensionUniverse()
42 def test_simple(self):
43 """Test with a trivial expression"""
45 parser = ParserYacc()
46 tree = parser.parse("1 > 0")
47 self.assertIsNotNone(tree)
49 columns = QueryColumns()
50 elements = NamedKeyDict()
51 column_element = convertExpressionToSql(
52 tree, self.universe, columns, elements, {}, TimespanDatabaseRepresentation.Compound
53 )
54 self.assertEqual(str(column_element.compile()), ":param_1 > :param_2")
55 self.assertEqual(str(column_element.compile(compile_kwargs={"literal_binds": True})), "1 > 0")
57 def test_time(self):
58 """Test with a trivial expression including times"""
60 parser = ParserYacc()
61 tree = parser.parse("T'1970-01-01 00:00/tai' < T'2020-01-01 00:00/tai'")
62 self.assertIsNotNone(tree)
64 columns = QueryColumns()
65 elements = NamedKeyDict()
66 column_element = convertExpressionToSql(
67 tree, self.universe, columns, elements, {}, TimespanDatabaseRepresentation.Compound
68 )
69 self.assertEqual(str(column_element.compile()), ":param_1 < :param_2")
70 self.assertEqual(
71 str(column_element.compile(compile_kwargs={"literal_binds": True})), "0 < 1577836800000000000"
72 )
74 def test_ingest_date(self):
75 """Test with an expression including ingest_date which is native UTC"""
77 parser = ParserYacc()
78 tree = parser.parse("ingest_date < T'2020-01-01 00:00/utc'")
79 self.assertIsNotNone(tree)
81 columns = QueryColumns()
82 columns.datasets = FakeDatasetRecordStorageManager()
83 elements = NamedKeyDict()
84 column_element = convertExpressionToSql(
85 tree, self.universe, columns, elements, {}, TimespanDatabaseRepresentation.Compound
86 )
88 # render it, needs specific dialect to convert column to expression
89 dialect = postgresql.dialect()
90 self.assertEqual(str(column_element.compile(dialect=dialect)), "ingest_date < TIMESTAMP %(param_1)s")
91 self.assertEqual(
92 str(column_element.compile(dialect=dialect, compile_kwargs={"literal_binds": True})),
93 "ingest_date < TIMESTAMP '2020-01-01 00:00:00.000000'",
94 )
96 dialect = sqlite.dialect()
97 self.assertEqual(str(column_element.compile(dialect=dialect)), "datetime(ingest_date) < datetime(?)")
98 self.assertEqual(
99 str(column_element.compile(dialect=dialect, compile_kwargs={"literal_binds": True})),
100 "datetime(ingest_date) < datetime('2020-01-01 00:00:00.000000')",
101 )
104if __name__ == "__main__": 104 ↛ 105line 104 didn't jump to line 105, because the condition on line 104 was never true
105 unittest.main()