Skip to content

Commit 10abcc6

Browse files
lukesneeringerlandrito
authored andcommitted
Allow Table.read_rows to take an inclusive end key. (googleapis#3744)
This commit adds the `end_inclusive` keyword argument, which can be explicitly passed to get `[start:end]` rather than `[start:end)`.
1 parent b3c2277 commit 10abcc6

File tree

2 files changed

+29
-6
lines changed

2 files changed

+29
-6
lines changed

bigtable/google/cloud/bigtable/table.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ def read_row(self, row_key, filter_=None):
257257
return rows_data.rows[row_key]
258258

259259
def read_rows(self, start_key=None, end_key=None, limit=None,
260-
filter_=None):
260+
filter_=None, end_inclusive=False):
261261
"""Read rows from this table.
262262
263263
:type start_key: bytes
@@ -280,13 +280,17 @@ def read_rows(self, start_key=None, end_key=None, limit=None,
280280
specified row(s). If unset, reads every column in
281281
each row.
282282
283+
:type end_inclusive: bool
284+
:param end_inclusive: (Optional) Whether the ``end_key`` should be
285+
considered inclusive. The default is False (exclusive).
286+
283287
:rtype: :class:`.PartialRowsData`
284288
:returns: A :class:`.PartialRowsData` convenience wrapper for consuming
285289
the streamed results.
286290
"""
287291
request_pb = _create_row_request(
288292
self.name, start_key=start_key, end_key=end_key, filter_=filter_,
289-
limit=limit)
293+
limit=limit, end_inclusive=end_inclusive)
290294
client = self._instance._client
291295
response_iterator = client._data_stub.ReadRows(request_pb)
292296
# We expect an iterator of `data_messages_v2_pb2.ReadRowsResponse`
@@ -360,7 +364,7 @@ def sample_row_keys(self):
360364

361365

362366
def _create_row_request(table_name, row_key=None, start_key=None, end_key=None,
363-
filter_=None, limit=None):
367+
filter_=None, limit=None, end_inclusive=False):
364368
"""Creates a request to read rows in a table.
365369
366370
:type table_name: str
@@ -388,6 +392,10 @@ def _create_row_request(table_name, row_key=None, start_key=None, end_key=None,
388392
rows' worth of results. The default (zero) is to return
389393
all results.
390394
395+
:type end_inclusive: bool
396+
:param end_inclusive: (Optional) Whether the ``end_key`` should be
397+
considered inclusive. The default is False (exclusive).
398+
391399
:rtype: :class:`data_messages_v2_pb2.ReadRowsRequest`
392400
:returns: The ``ReadRowsRequest`` protobuf corresponding to the inputs.
393401
:raises: :class:`ValueError <exceptions.ValueError>` if both
@@ -403,7 +411,10 @@ def _create_row_request(table_name, row_key=None, start_key=None, end_key=None,
403411
if start_key is not None:
404412
range_kwargs['start_key_closed'] = _to_bytes(start_key)
405413
if end_key is not None:
406-
range_kwargs['end_key_open'] = _to_bytes(end_key)
414+
end_key_key = 'end_key_open'
415+
if end_inclusive:
416+
end_key_key = 'end_key_closed'
417+
range_kwargs[end_key_key] = _to_bytes(end_key)
407418
if filter_ is not None:
408419
request_kwargs['filter'] = filter_.to_pb()
409420
if limit is not None:

bigtable/tests/unit/test_table.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,7 @@ def mock_create_row_request(table_name, **kwargs):
537537
'end_key': end_key,
538538
'filter_': filter_obj,
539539
'limit': limit,
540+
'end_inclusive': False,
540541
}
541542
self.assertEqual(mock_created, [(table.name, created_kwargs)])
542543

@@ -572,12 +573,12 @@ def test_sample_row_keys(self):
572573
class Test__create_row_request(unittest.TestCase):
573574

574575
def _call_fut(self, table_name, row_key=None, start_key=None, end_key=None,
575-
filter_=None, limit=None):
576+
filter_=None, limit=None, end_inclusive=False):
576577
from google.cloud.bigtable.table import _create_row_request
577578

578579
return _create_row_request(
579580
table_name, row_key=row_key, start_key=start_key, end_key=end_key,
580-
filter_=filter_, limit=limit)
581+
filter_=filter_, limit=limit, end_inclusive=end_inclusive)
581582

582583
def test_table_name_only(self):
583584
table_name = 'table_name'
@@ -627,6 +628,17 @@ def test_row_range_both_keys(self):
627628
start_key_closed=start_key, end_key_open=end_key)
628629
self.assertEqual(result, expected_result)
629630

631+
def test_row_range_both_keys_inclusive(self):
632+
table_name = 'table_name'
633+
start_key = b'start_key'
634+
end_key = b'end_key'
635+
result = self._call_fut(table_name, start_key=start_key,
636+
end_key=end_key, end_inclusive=True)
637+
expected_result = _ReadRowsRequestPB(table_name=table_name)
638+
expected_result.rows.row_ranges.add(
639+
start_key_closed=start_key, end_key_closed=end_key)
640+
self.assertEqual(result, expected_result)
641+
630642
def test_with_filter(self):
631643
from google.cloud.bigtable.row_filters import RowSampleFilter
632644

0 commit comments

Comments
 (0)