Skip to content

Commit 9fd9792

Browse files
committed
added result format flag to explain
fixed container waits
1 parent bcc45ba commit 9fd9792

File tree

12 files changed

+91
-21
lines changed

12 files changed

+91
-21
lines changed

tests/aio/query/test_query_session.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import pytest
44

55
import ydb
6+
from ydb import QueryExplainResultFormat
67
from ydb.aio.query.session import QuerySession
78

89

@@ -139,10 +140,17 @@ async def test_explain(self, pool: ydb.aio.query.QuerySessionPool):
139140
async def callee(session: QuerySession):
140141
nonlocal plan_fullscan, plan_lookup
141142

142-
plan_fullscan = await session.explain("SELECT * FROM test_explain")
143+
plan = await session.explain("SELECT * FROM test_explain", result_format=QueryExplainResultFormat.STR)
144+
isinstance(plan, str)
145+
assert "FullScan" in plan
146+
147+
plan_fullscan = await session.explain(
148+
"SELECT * FROM test_explain", result_format=QueryExplainResultFormat.DICT
149+
)
143150
plan_lookup = await session.explain(
144151
"SELECT * FROM test_explain WHERE id = $id",
145152
{"$id": 1},
153+
result_format=QueryExplainResultFormat.DICT,
146154
)
147155

148156
await pool.retry_operation_async(callee)

tests/aio/query/test_query_session_pool.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from typing import Optional
88

99
from tests.conftest import wait_container_ready_async
10+
from ydb import QueryExplainResultFormat
1011
from ydb.aio.query.pool import QuerySessionPool
1112
from ydb.aio.query.session import QuerySession, QuerySessionStateEnum
1213
from ydb.aio.query.transaction import QueryTxContext
@@ -189,13 +190,22 @@ async def test_explain_with_retries(self, pool: QuerySessionPool):
189190
await pool.execute_with_retries("DROP TABLE IF EXISTS test_explain")
190191
await pool.execute_with_retries("CREATE TABLE test_explain (id Int64, PRIMARY KEY (id))")
191192
try:
192-
plan = await pool.explain_with_retries("SELECT * FROM test_explain")
193+
plan = await pool.explain_with_retries(
194+
"SELECT * FROM test_explain", result_format=QueryExplainResultFormat.STR
195+
)
196+
isinstance(plan, str)
197+
assert "FullScan" in plan
198+
199+
plan = await pool.explain_with_retries(
200+
"SELECT * FROM test_explain", result_format=QueryExplainResultFormat.DICT
201+
)
193202
plan_string = json.dumps(plan)
194203
assert "FullScan" in plan_string
195204

196205
plan = await pool.explain_with_retries(
197206
"SELECT * FROM test_explain WHERE id = $id",
198207
{"$id": 1},
208+
result_format=QueryExplainResultFormat.DICT,
199209
)
200210
plan_string = json.dumps(plan)
201211
assert "Lookup" in plan_string

tests/aio/test_connection_pool.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ async def restart_docker():
109109
await asyncio.gather(*coros, return_exceptions=False)
110110

111111
docker_project.start()
112-
await driver.stop()
113112
await wait_container_ready_async(driver)
113+
await driver.stop()
114114

115115

116116
@pytest.mark.asyncio
@@ -134,8 +134,8 @@ async def test_disconnect_by_call(endpoint, database, docker_project):
134134
await asyncio.sleep(5)
135135
assert len(driver._store.connections) == 0
136136
docker_project.start()
137-
await driver.stop()
138137
await wait_container_ready_async(driver)
138+
await driver.stop()
139139

140140

141141
@pytest.mark.asyncio

tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ async def wait_container_ready_async(driver):
3737
async with ydb.aio.SessionPool(driver, 1) as pool:
3838

3939
started_at = time.time()
40-
while time.time() - started_at < 120:
40+
while time.time() - started_at < 30:
4141
try:
4242
async with pool.checkout() as session:
4343
await session.execute_scheme("create table `.sys_health/test_table` (A int32, primary key(A));")

tests/query/test_query_session.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from unittest import mock
88

99
from ydb import QuerySessionPool
10-
from ydb.query.base import QueryStatsMode
10+
from ydb.query.base import QueryStatsMode, QueryExplainResultFormat
1111
from ydb.query.session import QuerySession
1212

1313

@@ -187,10 +187,19 @@ def test_explain(self, pool: QuerySessionPool):
187187

188188
def callee(session: QuerySession):
189189
nonlocal plan_fullscan, plan_lookup
190-
plan_fullscan = session.explain("SELECT * FROM test_explain")
190+
191+
plan = session.explain("SELECT * FROM test_explain", result_format=QueryExplainResultFormat.STR)
192+
isinstance(plan, str)
193+
assert "FullScan" in plan
194+
195+
plan_fullscan = session.explain(
196+
"SELECT * FROM test_explain", result_format=QueryExplainResultFormat.DICT
197+
)
198+
191199
plan_lookup = session.explain(
192200
"SELECT * FROM test_explain WHERE id = $id",
193201
{"$id": 1},
202+
result_format=QueryExplainResultFormat.DICT,
194203
)
195204

196205
pool.retry_operation_sync(callee)

tests/query/test_query_session_pool.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from typing import Optional
99

1010
from tests.conftest import wait_container_ready
11+
from ydb import QueryExplainResultFormat
1112
from ydb.query.pool import QuerySessionPool
1213
from ydb.query.session import QuerySession, QuerySessionStateEnum
1314
from ydb.query.transaction import QueryTxContext
@@ -150,8 +151,8 @@ def test_no_session_leak(self, driver_sync, docker_project):
150151
assert pool._current_size == 0
151152

152153
docker_project.start()
154+
wait_container_ready(driver_sync)
153155
pool.stop()
154-
wait_container_ready(driver)
155156

156157
def test_execute_with_retries_async(self, pool: QuerySessionPool):
157158
fut = pool.execute_with_retries_async("select 1;")
@@ -209,13 +210,21 @@ def test_explain_with_retries(self, pool: QuerySessionPool):
209210
pool.execute_with_retries("DROP TABLE IF EXISTS test_explain")
210211
pool.execute_with_retries("CREATE TABLE test_explain (id Int64, PRIMARY KEY (id))")
211212
try:
212-
plan = pool.explain_with_retries("SELECT * FROM test_explain")
213+
214+
plan = pool.explain_with_retries("SELECT * FROM test_explain", result_format=QueryExplainResultFormat.STR)
215+
isinstance(plan, str)
216+
assert "FullScan" in plan
217+
218+
plan = pool.explain_with_retries("SELECT * FROM test_explain", result_format=QueryExplainResultFormat.DICT)
219+
assert isinstance(plan, dict)
220+
213221
plan_string = json.dumps(plan)
214222
assert "FullScan" in plan_string
215223

216224
plan = pool.explain_with_retries(
217225
"SELECT * FROM test_explain WHERE id = $id",
218226
{"$id": 1},
227+
result_format=ydb.QueryExplainResultFormat.DICT,
219228
)
220229
plan_string = json.dumps(plan)
221230
assert "Lookup" in plan_string

ydb/aio/query/pool.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
List,
77
Dict,
88
Any,
9+
Union,
910
)
1011

1112
from .session import (
@@ -15,7 +16,7 @@
1516
RetrySettings,
1617
retry_operation_async,
1718
)
18-
from ...query.base import BaseQueryTxMode
19+
from ...query.base import BaseQueryTxMode, QueryExplainResultFormat
1920
from ...query.base import QueryClientSettings
2021
from ... import convert
2122
from ..._grpc.grpcwrapper import common_utils
@@ -201,19 +202,21 @@ async def explain_with_retries(
201202
query: str,
202203
parameters: Optional[dict] = None,
203204
*,
205+
result_format: QueryExplainResultFormat = QueryExplainResultFormat.STR,
204206
retry_settings: Optional[RetrySettings] = None,
205-
) -> Dict[str, Any]:
207+
) -> Union[str, Dict[str, Any]]:
206208
"""
207209
Explain a query in retriable way. No real query execution will happen.
208210
209211
:param query: A query, yql or sql text.
210212
:param parameters: dict with parameters and YDB types;
213+
:param result_format: Return format: string or dict.
211214
:param retry_settings: RetrySettings object.
212215
:return: Parsed query plan.
213216
"""
214217

215218
async def callee(session: QuerySession):
216-
return await session.explain(query, parameters)
219+
return await session.explain(query, parameters, result_format=result_format)
217220

218221
return await self.retry_operation_async(callee, retry_settings)
219222

ydb/aio/query/session.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
Optional,
66
Dict,
77
Any,
8+
Union,
89
)
910

1011
from .base import AsyncResponseContextIterator
@@ -166,10 +167,16 @@ async def execute(
166167
error_converter=stream_error_converter,
167168
)
168169

169-
async def explain(self, query: str, parameters: Optional[dict] = None) -> Dict[str, Any]:
170+
async def explain(
171+
self,
172+
query: str,
173+
parameters: Optional[dict] = None,
174+
result_format: base.QueryExplainResultFormat = base.QueryExplainResultFormat.STR,
175+
) -> Union[str, Dict[str, Any]]:
170176
"""Explains query result
171177
:param query: YQL or SQL query.
172178
:param parameters: dict with parameters and YDB types;
179+
:param result_format: Return format: string or dict.
173180
:return: Parsed query plan.
174181
"""
175182

@@ -179,6 +186,9 @@ async def explain(self, query: str, parameters: Optional[dict] = None) -> Dict[s
179186
async for _ in res:
180187
pass
181188

182-
plan_text = self.last_query_stats.query_plan
183-
plan = json.loads(plan_text)
189+
plan = self.last_query_stats.query_plan
190+
191+
if result_format == base.QueryExplainResultFormat.DICT:
192+
plan = json.loads(plan)
193+
184194
return plan

ydb/query/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
__all__ = [
22
"BaseQueryTxMode",
3+
"QueryExplainResultFormat",
34
"QueryOnlineReadOnly",
45
"QuerySerializableReadWrite",
56
"QuerySnapshotReadOnly",
@@ -15,6 +16,7 @@
1516

1617
from .base import (
1718
QueryClientSettings,
19+
QueryExplainResultFormat,
1820
QueryStatsMode,
1921
)
2022

ydb/query/base.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ class QueryExecMode(enum.IntEnum):
4242
EXECUTE = 50
4343

4444

45+
class QueryExplainResultFormat(enum.Enum):
46+
STR = 0
47+
DICT = 10
48+
49+
4550
class QueryStatsMode(enum.IntEnum):
4651
UNSPECIFIED = 0
4752
NONE = 10

0 commit comments

Comments
 (0)