Skip to content

Commit a8841f8

Browse files
author
Jesse Whitehouse
committed
PR: Split out tests into individual units of work. One test per primitive,
parameter type, and inferrence level. Signed-off-by: Jesse Whitehouse <jesse.whitehouse@databricks.com>
1 parent 554623f commit a8841f8

1 file changed

Lines changed: 130 additions & 167 deletions

File tree

Lines changed: 130 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
from datetime import datetime
1+
import datetime
22
from decimal import Decimal
3+
from typing import Dict, List, Tuple, Union
34

45
import pytz
56

@@ -10,172 +11,134 @@
1011
class PySQLParameterizedQueryTestSuiteMixin:
1112
"""Namespace for tests of server-side parameterized queries"""
1213

13-
def test_parameterized_query_named_and_inferred_e2e(self):
14-
"""Verify that named parameters passed to the database as a dict are returned of the correct type
15-
All types are inferred.
16-
"""
17-
18-
conn: Connection
19-
20-
query = """
21-
SELECT
22-
:p_bool AS col_bool,
23-
:p_int AS col_int,
24-
:p_double AS col_double,
25-
:p_date as col_date,
26-
:p_timestamp as col_timestamp,
27-
:p_str AS col_str
28-
"""
29-
30-
named_parameters = {
31-
"p_bool": True,
32-
"p_int": 1234,
33-
"p_double": 3.14,
34-
"p_date": datetime(2023, 9, 6, 3, 14, 27, 843, tzinfo=pytz.UTC).date(),
35-
"p_timestamp": datetime(2023, 9, 6, 3, 14, 27, 843, tzinfo=pytz.UTC),
36-
"p_str": "Hello",
37-
}
38-
with self.connection() as conn:
39-
cursor = conn.cursor()
40-
cursor.execute(query, parameters=named_parameters)
41-
result = cursor.fetchone()
42-
43-
assert result.col_bool == True
44-
assert result.col_int == 1234
45-
46-
# For equality, we use Decimal to quantize these values
47-
assert Decimal(result.col_double).quantize(Decimal("0.00")) == Decimal(
48-
3.14
49-
).quantize(Decimal("0.00"))
50-
51-
assert result.col_date == datetime(
52-
2023, 9, 6, 3, 14, 27, 843, tzinfo=pytz.UTC
53-
).date()
54-
assert result.col_timestamp == datetime(
55-
2023, 9, 6, 3, 14, 27, 843, tzinfo=pytz.UTC
56-
)
57-
assert result.col_str == "Hello"
58-
59-
def test_parameterized_query_named_dict_and_inferred_e2e(self):
60-
"""Verify that named parameters passed to the database as a list are returned of the correct type
61-
All types are inferred.
62-
"""
63-
64-
conn: Connection
65-
66-
query = """
67-
SELECT
68-
:p_bool AS col_bool,
69-
:p_int AS col_int,
70-
:p_double AS col_double,
71-
:p_date as col_date,
72-
:p_timestamp as col_timestamp,
73-
:p_str AS col_str
74-
"""
75-
76-
named_parameters = [
77-
DbSqlParameter(
78-
name="p_bool",
79-
value=True,
80-
),
81-
DbSqlParameter(
82-
name="p_int",
83-
value=1234,
84-
),
85-
DbSqlParameter(
86-
name="p_double",
87-
value=3.14,
88-
),
89-
DbSqlParameter(
90-
name="p_date",
91-
value=datetime(2023, 9, 6, 3, 14, 27, 843, tzinfo=pytz.UTC).date(),
92-
),
93-
DbSqlParameter(
94-
name="p_timestamp",
95-
value=datetime(2023, 9, 6, 3, 14, 27, 843, tzinfo=pytz.UTC),
96-
),
97-
DbSqlParameter(name="p_str", value="Hello"),
98-
]
14+
QUERY = "SELECT :p AS col"
9915

16+
def _get_one_result(self, query: str, parameters: Union[Dict, List[Dict]]) -> Tuple:
10017
with self.connection() as conn:
101-
cursor = conn.cursor()
102-
cursor.execute(query, parameters=named_parameters)
103-
result = cursor.fetchone()
104-
105-
assert result.col_bool == True
106-
assert result.col_int == 1234
107-
108-
# For equality, we use Decimal to quantize these values
109-
assert Decimal(result.col_double).quantize(Decimal("0.00")) == Decimal(
110-
3.14
111-
).quantize(Decimal("0.00"))
112-
113-
assert result.col_date == datetime(
114-
2023, 9, 6, 3, 14, 27, 843, tzinfo=pytz.UTC
115-
).date()
116-
assert result.col_timestamp == datetime(
117-
2023, 9, 6, 3, 14, 27, 843, tzinfo=pytz.UTC
118-
)
119-
assert result.col_str == "Hello"
120-
121-
def test_parameterized_query_named_dict_and_not_inferred_e2e(self):
122-
"""Verify that named parameters passed to the database are returned of the correct type
123-
All types are explicitly set.
124-
"""
125-
126-
conn: Connection
127-
128-
query = """
129-
SELECT
130-
:p_bool AS col_bool,
131-
:p_int AS col_int,
132-
:p_double AS col_double,
133-
:p_date as col_date,
134-
:p_timestamp as col_timestamp,
135-
:p_str AS col_str
136-
"""
137-
138-
named_parameters = [
139-
DbSqlParameter(name="p_bool", value=True, type=DbSqlType.BOOLEAN),
140-
DbSqlParameter(name="p_int", value=1234, type=DbSqlType.INTEGER),
141-
DbSqlParameter(name="p_double", value=3.14, type=DbSqlType.FLOAT),
142-
DbSqlParameter(
143-
name="p_date",
144-
value=datetime(2023, 9, 6, 3, 14, 27, 843, tzinfo=pytz.UTC).date(),
145-
type=DbSqlType.DATE,
146-
),
147-
DbSqlParameter(
148-
name="p_timestamp",
149-
value=datetime(2023, 9, 6, 3, 14, 27, 843, tzinfo=pytz.UTC),
150-
type=DbSqlType.TIMESTAMP,
151-
),
152-
DbSqlParameter(name="p_str", value="Hello", type=DbSqlType.STRING),
153-
]
18+
with conn.cursor() as cursor:
19+
cursor.execute(query, parameters=parameters)
20+
return cursor.fetchone()
15421

155-
with self.connection() as conn:
156-
cursor = conn.cursor()
157-
cursor.execute(query, parameters=named_parameters)
158-
result = cursor.fetchone()
159-
160-
assert result.col_bool == True
161-
assert result.col_int == 1234
162-
163-
# For equality, we use Decimal to quantize these values
164-
assert Decimal(result.col_double).quantize(Decimal("0.00")) == Decimal(
165-
3.14
166-
).quantize(Decimal("0.00"))
167-
168-
# Observe that passing a datetime object with timezone information and the type set to DbSqlType.DATE
169-
# strips away the time and tz info
170-
assert (
171-
result.col_date
172-
== datetime(
173-
2023,
174-
9,
175-
6,
176-
).date()
177-
)
178-
assert result.col_timestamp == datetime(
179-
2023, 9, 6, 3, 14, 27, 843, tzinfo=pytz.UTC
180-
)
181-
assert result.col_str == "Hello"
22+
def _quantize(self, input: Union[float, int], place_value=2) -> Decimal:
23+
24+
return Decimal(str(input)).quantize(Decimal("0." + "0" * place_value))
25+
26+
def test_primitive_inferred_bool(self):
27+
28+
params = {"p": True}
29+
result = self._get_one_result(self.QUERY, params)
30+
assert result.col == True
31+
32+
def test_primitive_inferred_integer(self):
33+
34+
params = {"p": 1}
35+
result = self._get_one_result(self.QUERY, params)
36+
assert result.col == 1
37+
38+
def test_primitive_inferred_double(self):
39+
40+
params = {"p": 3.14}
41+
result = self._get_one_result(self.QUERY, params)
42+
assert self._quantize(result.col) == self._quantize(3.14)
43+
44+
def test_primitive_inferred_date(self):
45+
46+
# DATE in Databricks is mapped into a datetime.date object in Python
47+
date_value = datetime.date(2023, 9, 6)
48+
params = {"p": date_value}
49+
result = self._get_one_result(self.QUERY, params)
50+
assert result.col == date_value
51+
52+
def test_primitive_inferred_timestamp(self):
53+
54+
# TIMESTAMP in Databricks is mapped into a datetime.datetime object in Python
55+
date_value = datetime.datetime(2023, 9, 6, 3, 14, 27, 843, tzinfo=pytz.UTC)
56+
params = {"p": date_value}
57+
result = self._get_one_result(self.QUERY, params)
58+
assert result.col == date_value
59+
60+
def test_primitive_inferred_string(self):
61+
62+
params = {"p": "Hello"}
63+
result = self._get_one_result(self.QUERY, params)
64+
assert result.col == "Hello"
65+
66+
def test_dbsqlparam_inferred_bool(self):
67+
68+
params = [DbSqlParameter(name="p", value=True, type=None)]
69+
result = self._get_one_result(self.QUERY, params)
70+
assert result.col == True
71+
72+
def test_dbsqlparam_inferred_integer(self):
73+
74+
params = [DbSqlParameter(name="p", value=1, type=None)]
75+
result = self._get_one_result(self.QUERY, params)
76+
assert result.col == 1
77+
78+
def test_dbsqlparam_inferred_double(self):
79+
80+
params = [DbSqlParameter(name="p", value=3.14, type=None)]
81+
result = self._get_one_result(self.QUERY, params)
82+
assert self._quantize(result.col) == self._quantize(3.14)
83+
84+
def test_dbsqlparam_inferred_date(self):
85+
86+
# DATE in Databricks is mapped into a datetime.date object in Python
87+
date_value = datetime.date(2023, 9, 6)
88+
params = [DbSqlParameter(name="p", value=date_value, type=None)]
89+
result = self._get_one_result(self.QUERY, params)
90+
assert result.col == date_value
91+
92+
def test_dbsqlparam_inferred_timestamp(self):
93+
94+
# TIMESTAMP in Databricks is mapped into a datetime.datetime object in Python
95+
date_value = datetime.datetime(2023, 9, 6, 3, 14, 27, 843, tzinfo=pytz.UTC)
96+
params = [DbSqlParameter(name="p", value=date_value, type=None)]
97+
result = self._get_one_result(self.QUERY, params)
98+
assert result.col == date_value
99+
100+
def test_dbsqlparam_inferred_string(self):
101+
102+
params = [DbSqlParameter(name="p", value="Hello", type=None)]
103+
result = self._get_one_result(self.QUERY, params)
104+
assert result.col == "Hello"
105+
106+
def test_dbsqlparam_explicit_bool(self):
107+
108+
params = [DbSqlParameter(name="p", value=True, type=DbSqlType.BOOLEAN)]
109+
result = self._get_one_result(self.QUERY, params)
110+
assert result.col == True
111+
112+
def test_dbsqlparam_explicit_integer(self):
113+
114+
params = [DbSqlParameter(name="p", value=1, type=DbSqlType.INTEGER)]
115+
result = self._get_one_result(self.QUERY, params)
116+
assert result.col == 1
117+
118+
def test_dbsqlparam_explicit_double(self):
119+
120+
params = [DbSqlParameter(name="p", value=3.14, type=DbSqlType.FLOAT)]
121+
result = self._get_one_result(self.QUERY, params)
122+
assert self._quantize(result.col) == self._quantize(3.14)
123+
124+
def test_dbsqlparam_explicit_date(self):
125+
126+
# DATE in Databricks is mapped into a datetime.date object in Python
127+
date_value = datetime.date(2023, 9, 6)
128+
params = [DbSqlParameter(name="p", value=date_value, type=DbSqlType.DATE)]
129+
result = self._get_one_result(self.QUERY, params)
130+
assert result.col == date_value
131+
132+
def test_dbsqlparam_explicit_timestamp(self):
133+
134+
# TIMESTAMP in Databricks is mapped into a datetime.datetime object in Python
135+
date_value = datetime.datetime(2023, 9, 6, 3, 14, 27, 843, tzinfo=pytz.UTC)
136+
params = [DbSqlParameter(name="p", value=date_value, type=DbSqlType.TIMESTAMP)]
137+
result = self._get_one_result(self.QUERY, params)
138+
assert result.col == date_value
139+
140+
def test_dbsqlparam_explicit_string(self):
141+
142+
params = [DbSqlParameter(name="p", value="Hello", type=DbSqlType.STRING)]
143+
result = self._get_one_result(self.QUERY, params)
144+
assert result.col == "Hello"

0 commit comments

Comments
 (0)