Skip to content

Commit 0ff6515

Browse files
committed
add e2e tests
1 parent 41c639f commit 0ff6515

1 file changed

Lines changed: 114 additions & 0 deletions

File tree

tests/fast/test_template_e2e.py

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
from __future__ import annotations
2+
3+
import pytest
4+
5+
import duckdb
6+
from duckdb.template import param, template
7+
8+
9+
def test_connection_sql_accepts_sql_template() -> None:
10+
conn = duckdb.connect()
11+
query = template("SELECT i FROM range(5) t(i) WHERE i >= ", 2, " ORDER BY i")
12+
assert conn.sql(query).fetchall() == [(2,), (3,), (4,)]
13+
14+
15+
def test_connection_query_accepts_sql_template() -> None:
16+
conn = duckdb.connect()
17+
query = template("SELECT i FROM range(3) t(i) WHERE i < ", 2, " ORDER BY i")
18+
assert conn.query(query).fetchall() == [(0,), (1,)]
19+
20+
21+
def test_connection_from_query_accepts_sql_template() -> None:
22+
conn = duckdb.connect()
23+
query = template("SELECT i FROM range(4) t(i) WHERE i % ", 2, " = 0 ORDER BY i")
24+
assert conn.from_query(query).fetchall() == [(0,), (2,)]
25+
26+
27+
def test_connection_execute_accepts_sql_template() -> None:
28+
conn = duckdb.connect()
29+
query = template("SELECT ", 42)
30+
assert conn.execute(query).fetchone() == (42,)
31+
32+
33+
def test_module_level_sql_apis_accept_sql_template() -> None:
34+
conn = duckdb.connect()
35+
query = template("SELECT i FROM range(5) t(i) WHERE i BETWEEN ", 1, " AND ", 3, " ORDER BY i")
36+
37+
assert duckdb.sql(query, connection=conn).fetchall() == [(1,), (2,), (3,)]
38+
assert duckdb.query(query, connection=conn).fetchall() == [(1,), (2,), (3,)]
39+
assert duckdb.from_query(query, connection=conn).fetchall() == [(1,), (2,), (3,)]
40+
41+
42+
def test_module_level_execute_accepts_sql_template() -> None:
43+
conn = duckdb.connect()
44+
query = template("SELECT ", "hello")
45+
assert duckdb.execute(query, connection=conn).fetchone() == ("hello",)
46+
47+
48+
def test_connection_sql_accepts_alias_kwarg_with_template() -> None:
49+
conn = duckdb.connect()
50+
inner = conn.sql(template("SELECT 42 AS x"), alias="my_alias")
51+
assert inner.alias == "my_alias"
52+
outer = conn.sql(template("SELECT x FROM (", inner, ")"))
53+
assert outer.fetchall() == [(42,)]
54+
55+
56+
def test_connection_sql_template_can_merge_additional_params() -> None:
57+
conn = duckdb.connect()
58+
query = template("SELECT ", 10, " + $another")
59+
assert conn.sql(query, params={"another": 5}).fetchall() == [(15,)]
60+
61+
62+
def test_connection_sql_template_param_name_conflict_with_additional_params_raises() -> None:
63+
conn = duckdb.connect()
64+
query = template("SELECT ", param(10, "num"), " + $num")
65+
with pytest.raises((duckdb.InvalidInputException, ValueError)):
66+
conn.sql(query, params={"num": 5}).fetchall()
67+
68+
69+
def test_sql_apis_accept_compiled_sql() -> None:
70+
conn = duckdb.connect()
71+
compiled = template("SELECT i FROM range(5) t(i) WHERE i >= ", 3, " ORDER BY i").compile()
72+
73+
assert conn.sql(compiled).fetchall() == [(3,), (4,)]
74+
assert conn.query(compiled).fetchall() == [(3,), (4,)]
75+
assert conn.from_query(compiled).fetchall() == [(3,), (4,)]
76+
assert conn.execute(compiled).fetchall() == [(3,), (4,)]
77+
78+
79+
def test_relation_interpolation_works_end_to_end() -> None:
80+
conn = duckdb.connect()
81+
rel = conn.sql("SELECT i FROM range(6) t(i)")
82+
query = template("SELECT i FROM (", rel, ") WHERE i % ", 2, " = 0 ORDER BY i")
83+
assert conn.sql(query).fetchall() == [(0,), (2,), (4,)]
84+
85+
86+
def test_interpolated_strings_are_parameterized_by_default() -> None:
87+
conn = duckdb.connect()
88+
conn.execute("CREATE TABLE names(name VARCHAR)")
89+
conn.execute("INSERT INTO names VALUES ('alice'), ('bob')")
90+
91+
untrusted = "alice' OR 1=1 --"
92+
query = template("SELECT count(*) FROM names WHERE name = ", untrusted)
93+
assert conn.sql(query).fetchone() == (0,)
94+
95+
96+
def test_builtin_duckdbpytype_object_interpolates_in_template() -> None:
97+
conn = duckdb.connect()
98+
integer_type = duckdb.sqltype("INTEGER")
99+
query = template("SELECT 42::", integer_type)
100+
assert conn.sql(query).fetchall() == [(42,)]
101+
102+
103+
def test_builtin_expression_object_interpolates_in_template() -> None:
104+
conn = duckdb.connect()
105+
expr = duckdb.ColumnExpression("i")
106+
query = template("SELECT ", expr, " FROM range(3) t(i) ORDER BY i")
107+
assert conn.sql(query).fetchall() == [(0,), (1,), (2,)]
108+
109+
110+
def test_builtin_sqlexpression_object_interpolates_in_template() -> None:
111+
conn = duckdb.connect()
112+
expr = duckdb.SQLExpression("i + 1")
113+
query = template("SELECT ", expr, " FROM range(3) t(i) ORDER BY i")
114+
assert conn.sql(query).fetchall() == [(1,), (2,), (3,)]

0 commit comments

Comments
 (0)