Skip to content

Commit 096bb62

Browse files
authored
add query API client (#7)
1 parent aea4179 commit 096bb62

File tree

6 files changed

+402
-26
lines changed

6 files changed

+402
-26
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ The following APIs are available:
121121
* `/v0/datasources`: `client.api.datasources`
122122
* `/v0/events`: `client.api.events`
123123
* `/v0/pipes`: `client.api.pipes`
124+
* `/v0/sql`: `client.api.query`
124125
* `/v0/tokens`: `client.api.tokens`
125126
* `/v0/variables`: `client.api.variables`
126127

tests/integration/test_query.py

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import pytest
2+
3+
4+
class TestQueryApi:
5+
@pytest.fixture(autouse=True)
6+
def _put_records(self, client):
7+
client.api.events.send(
8+
"simple",
9+
wait=True,
10+
records=[
11+
{
12+
"Id": "e7f2af3e-99d1-4d4f-8a8c-d6aee4ab89b0",
13+
"Timestamp": "2024-01-23T10:30:00.123456",
14+
"Key": "foo",
15+
"Value": "bar",
16+
},
17+
{
18+
"Id": "d7792957-21d8-46e6-a4e0-188eb36e2758",
19+
"Timestamp": "2024-02-23T11:45:00.234567",
20+
"Key": "baz",
21+
"Value": "ed",
22+
},
23+
],
24+
)
25+
26+
def test_query_datasource_json(self, client):
27+
response = client.api.query.query("SELECT key, value FROM simple ORDER BY `key` ASC")
28+
29+
assert response.data == [{"key": "baz", "value": "ed"}, {"key": "foo", "value": "bar"}]
30+
assert response.meta == [
31+
{"name": "key", "type": "String"},
32+
{"name": "value", "type": "String"},
33+
]
34+
assert response.rows == 2
35+
assert response.statistics["rows_read"] == 2
36+
37+
def test_query_pipe(self, client):
38+
response = client.api.query.query("SELECT * FROM simple_kv ORDER BY `key` ASC")
39+
40+
assert response.data == [{"key": "baz", "value": "ed"}, {"key": "foo", "value": "bar"}]
41+
assert response.meta == [
42+
{"name": "key", "type": "String"},
43+
{"name": "value", "type": "String"},
44+
]
45+
assert response.rows == 2
46+
assert response.statistics["rows_read"] == 2
47+
48+
def test_query_pipe_parameters(self, client):
49+
response = client.api.query.query(
50+
"SELECT key, value FROM simple_pipe", parameters={"key": "foo"}
51+
)
52+
53+
assert response.data == [{"key": "foo", "value": "bar"}]
54+
assert response.meta == [
55+
{"name": "key", "type": "String"},
56+
{"name": "value", "type": "String"},
57+
]
58+
assert response.rows == 1
59+
assert response.statistics["rows_read"] == 2
60+
61+
def test_query_pipeline_json(self, client):
62+
response = client.api.query.query(
63+
"SELECT * FROM _ ORDER BY `key` ASC", pipeline="simple_kv"
64+
)
65+
66+
assert response.data == [{"key": "baz", "value": "ed"}, {"key": "foo", "value": "bar"}]
67+
assert response.meta == [
68+
{"name": "key", "type": "String"},
69+
{"name": "value", "type": "String"},
70+
]
71+
assert response.rows == 2
72+
assert response.statistics["rows_read"] == 2
73+
74+
def test_query_csv(self, client):
75+
response = client.api.query.query(
76+
"SELECT key, value FROM simple ORDER BY `key` ASC", format="CSV"
77+
)
78+
79+
assert response.text == '"baz","ed"\n"foo","bar"\n'
80+
81+
def test_query_csv_with_names(self, client):
82+
response = client.api.query.query(
83+
"SELECT key, value FROM simple ORDER BY `key` ASC", format="CSVWithNames"
84+
)
85+
86+
assert (
87+
response.text
88+
== '"key","value"\n"baz","ed"\n"foo","bar"\n'
89+
!= '"baz","ed"\n"foo","bar"\n'
90+
)
91+
# CSV with names can be parsed as data!
92+
assert response.data == [{"key": "baz", "value": "ed"}, {"key": "foo", "value": "bar"}]
93+
94+
def test_query_tsv(self, client):
95+
response = client.api.query.query(
96+
"SELECT key, value FROM simple ORDER BY `key` ASC", format="TSV"
97+
)
98+
99+
assert response.text == "baz\ted\nfoo\tbar\n"
100+
101+
def test_query_tsv_with_names(self, client):
102+
response = client.api.query.query(
103+
"SELECT key, value FROM simple ORDER BY `key` ASC", format="TSVWithNames"
104+
)
105+
106+
assert response.text == "key\tvalue\nbaz\ted\nfoo\tbar\n"
107+
assert response.data == [{"key": "baz", "value": "ed"}, {"key": "foo", "value": "bar"}]
108+
109+
def test_query_ndjson(self, client):
110+
response = client.api.query.query(
111+
"SELECT key, value FROM simple ORDER BY `key` ASC", format="JSONEachRow"
112+
)
113+
114+
assert (
115+
response.text
116+
== '{"key":"baz","value":"ed"}\n{"key":"foo","value":"bar"}\n'
117+
!= '"key","value"\n"baz","ed"\n"foo","bar"\n'
118+
)
119+
# CSV with names can be parsed as data!
120+
assert response.data == [{"key": "baz", "value": "ed"}, {"key": "foo", "value": "bar"}]

verdin/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
name = "verdin"
22

3-
__version__ = "0.5.0"
3+
__version__ = "0.5.1"

verdin/api/apis.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from .datasources import DataSourcesApi
22
from .events import EventsApi
33
from .pipes import PipesApi
4+
from .query import QueryApi
45
from .tokens import TokensApi
56
from .variables import VariablesApi
67

@@ -29,6 +30,10 @@ def events(self) -> EventsApi:
2930
def pipes(self) -> PipesApi:
3031
return PipesApi(self._token, self._host)
3132

33+
@property
34+
def query(self) -> QueryApi:
35+
return QueryApi(self._token, self._host)
36+
3237
@property
3338
def tokens(self) -> TokensApi:
3439
return TokensApi(self._token, self._host)

0 commit comments

Comments
 (0)