Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
* Deprecated the table client scan query methods — `TableClient.scan_query`, `TableClient.async_scan_query` and the async `ydb.aio.TableClient.scan_query`: they now emit a `DeprecationWarning` and keep working as before, use QueryService (`ydb.QuerySessionPool` / `ydb.aio.QuerySessionPool`) instead
* Mark the package as typed so type checkers use the SDK's inline annotations

## 3.32.0 ##
Expand Down
2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ The :doc:`table` page covers ``driver.table_client`` — the lower-level API for
operations that cannot be expressed in YQL: creating tables with custom partitioning,
TTL, secondary indexes, and column families; bulk loading data with ``bulk_upsert``;
point reads by primary key with ``read_rows``; and streaming full-table reads with
``read_table`` or ``scan_query``. Use this
``read_table``. Use this
alongside the Query service when you need fine-grained schema or data-loading control.


Expand Down
7 changes: 7 additions & 0 deletions docs/table.rst
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,13 @@ Pass ``None`` to ``from_bound`` or ``to_bound`` of :class:`~ydb.KeyRange` to mea
scan_query
^^^^^^^^^^

The table-client ``scan_query`` methods are deprecated and emit a
``DeprecationWarning``. Use :class:`~ydb.QuerySessionPool` (or
:class:`~ydb.aio.QuerySessionPool`) and stream results with ``session.execute()``
for new code; see :doc:`query`.
Comment thread
vgvoleg marked this conversation as resolved.

The examples below show legacy usage for applications that have not migrated yet.

``scan_query`` executes a YQL query in streaming mode — the server sends result
chunks as they are produced without buffering the entire result set:

Expand Down
10 changes: 10 additions & 0 deletions ydb/aio/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import logging
import time
import typing
import warnings

from typing import (
Any,
Expand All @@ -19,6 +20,7 @@
from ydb.table import (
BaseSession,
BaseTableClient,
_SCAN_QUERY_DEPRECATION_MESSAGE,
_scan_query_request_factory,
_wrap_scan_query_response,
BaseTxContext,
Expand Down Expand Up @@ -181,6 +183,14 @@ async def describe_system_view(self, path, settings=None): # pylint: disable=W0
return await super().describe_system_view(path, settings)

async def scan_query(self, query, parameters=None, settings=None): # pylint: disable=W0236
"""
Deprecated: use QueryService (:class:`ydb.aio.QuerySessionPool`) instead.
"""
warnings.warn(
_SCAN_QUERY_DEPRECATION_MESSAGE.format(method="scan_query", pool="ydb.aio.QuerySessionPool"),
DeprecationWarning,
stacklevel=2,
)
request = _scan_query_request_factory(query, parameters, settings)
response = await self._driver(
request,
Expand Down
25 changes: 25 additions & 0 deletions ydb/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import logging
import enum
import typing
import warnings

from typing import (
Any,
Expand Down Expand Up @@ -988,6 +989,11 @@ def __init__(self, yql_text, parameters_types):
self.parameters_types = parameters_types


_SCAN_QUERY_DEPRECATION_MESSAGE = (
"{method} is deprecated and will be removed in a future release, use QueryService ({pool}) instead"
)


def _wrap_scan_query_response(response, table_client_settings):
issues._process_response(response)
return ScanQueryResult(response.result, table_client_settings)
Expand Down Expand Up @@ -1184,6 +1190,9 @@ def session(self):

@abstractmethod
def scan_query(self, query, parameters=None, settings=None):
"""
Deprecated: use QueryService (:class:`ydb.QuerySessionPool`) instead.
"""
pass

@abstractmethod
Expand Down Expand Up @@ -1226,6 +1235,14 @@ def session(self):

def scan_query(self, query, parameters=None, settings=None):
# type: (Union[str, ydb.ScanQuery], Optional[Mapping[str, Any]], Optional[ydb.BaseRequestSettings]) -> _utilities.SyncResponseIterator
"""
Deprecated: use QueryService (:class:`ydb.QuerySessionPool`) instead.
"""
warnings.warn(
_SCAN_QUERY_DEPRECATION_MESSAGE.format(method="scan_query", pool="ydb.QuerySessionPool"),
DeprecationWarning,
stacklevel=2,
)
request = _scan_query_request_factory(query, parameters, settings)
stream_it = self._driver(
request,
Expand Down Expand Up @@ -1309,6 +1326,14 @@ def __del__(self):

def async_scan_query(self, query, parameters=None, settings=None):
# type: (Union[str, ydb.ScanQuery], Optional[Mapping[str, Any]], Optional[ydb.BaseRequestSettings]) -> _utilities.AsyncResponseIterator
"""
Deprecated: use QueryService (:class:`ydb.QuerySessionPool`) instead.
"""
warnings.warn(
_SCAN_QUERY_DEPRECATION_MESSAGE.format(method="async_scan_query", pool="ydb.QuerySessionPool"),
DeprecationWarning,
stacklevel=2,
)
request = _scan_query_request_factory(query, parameters, settings)
stream_it = self._driver(
request,
Expand Down
70 changes: 69 additions & 1 deletion ydb/table_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import pytest

from unittest import mock
from . import issues, convert, types, _apis, scheme, _session_impl
from . import issues, convert, types, _apis, scheme, _session_impl, _utilities
from .aio import _utilities as _aio_utilities
from .aio.table import TableClient as AioTableClient
from .table import SystemViewSchemeEntry, TableClient, TableClientSettings

from .retries import (
Expand Down Expand Up @@ -338,6 +340,72 @@ def future(self, request, stub, method, wrap_fn, settings, wrap_args, *rest):
assert entry.sys_view_name == "partition_stats"


class _FakeScanQueryDriver:
def __call__(self, request, stub, method, settings=None):
self.request = request
self.method = method
return iter(())


class _FakeAsyncScanQueryDriver:
async def __call__(self, request, stub, method, settings=None):
self.request = request
self.method = method
return _EmptyAsyncStream()


class _EmptyAsyncStream:
def __aiter__(self):
return self

async def __anext__(self):
raise StopAsyncIteration


def test_scan_query_warns_and_still_returns_iterator():
driver = _FakeScanQueryDriver()

with pytest.warns(DeprecationWarning) as record:
stream = TableClient(driver).scan_query("SELECT 1")

assert str(record[0].message) == (
"scan_query is deprecated and will be removed in a future release, "
"use QueryService (ydb.QuerySessionPool) instead"
)
assert driver.method == _apis.TableService.StreamExecuteScanQuery
assert isinstance(stream, _utilities.SyncResponseIterator)


def test_async_scan_query_warns_and_still_returns_iterator():
driver = _FakeScanQueryDriver()

with pytest.warns(DeprecationWarning) as record:
stream = TableClient(driver).async_scan_query("SELECT 1")

assert str(record[0].message) == (
"async_scan_query is deprecated and will be removed in a future release, "
"use QueryService (ydb.QuerySessionPool) instead"
)
assert driver.method == _apis.TableService.StreamExecuteScanQuery
assert isinstance(stream, _utilities.AsyncResponseIterator)


@pytest.mark.asyncio
async def test_aio_scan_query_warns_and_points_to_async_pool():
Comment thread
Copilot marked this conversation as resolved.
driver = _FakeAsyncScanQueryDriver()

with pytest.warns(DeprecationWarning) as record:
stream = await AioTableClient(driver).scan_query("SELECT 1")

# The async client must not send users to the sync session pool.
assert str(record[0].message) == (
"scan_query is deprecated and will be removed in a future release, "
"use QueryService (ydb.aio.QuerySessionPool) instead"
)
assert driver.method == _apis.TableService.StreamExecuteScanQuery
assert isinstance(stream, _aio_utilities.AsyncResponseIterator)


def _read_rows_key_types():
return types.BulkUpsertColumns().add_column("id", types.PrimitiveType.Uint64)

Expand Down
Loading