Skip to content

Commit 72e9186

Browse files
committed
Adding Bigtable Table.read_rows().
1 parent 112ff67 commit 72e9186

File tree

2 files changed

+115
-3
lines changed

2 files changed

+115
-3
lines changed

gcloud/bigtable/table.py

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from gcloud.bigtable.column_family import ColumnFamily
2626
from gcloud.bigtable.row import Row
2727
from gcloud.bigtable.row_data import PartialRowData
28+
from gcloud.bigtable.row_data import PartialRowsData
2829

2930

3031
class Table(object):
@@ -255,6 +256,59 @@ def read_row(self, row_key, filter_=None):
255256
raise ValueError('The row remains partial / is not committed.')
256257
return result
257258

259+
def read_rows(self, start_key=None, end_key=None,
260+
allow_row_interleaving=None, limit=None, filter_=None):
261+
"""Read rows from this table.
262+
263+
:type start_key: bytes
264+
:param start_key: (Optional) The beginning of a range of row keys to
265+
read from. The range will include ``start_key``. If
266+
left empty, will be interpreted as the empty string.
267+
268+
:type end_key: bytes
269+
:param end_key: (Optional) The end of a range of row keys to read from.
270+
The range will not include ``end_key``. If left empty,
271+
will be interpreted as an infinite string.
272+
273+
:type allow_row_interleaving: bool
274+
:param allow_row_interleaving: (Optional) By default, rows are read
275+
sequentially, producing results which
276+
are guaranteed to arrive in increasing
277+
row order. Setting
278+
``allow_row_interleaving`` to
279+
:data:`True` allows multiple rows to be
280+
interleaved in the response stream,
281+
which increases throughput but breaks
282+
this guarantee, and may force the
283+
client to use more memory to buffer
284+
partially-received rows.
285+
286+
:type limit: int
287+
:param limit: (Optional) The read will terminate after committing to N
288+
rows' worth of results. The default (zero) is to return
289+
all results. Note that if ``allow_row_interleaving`` is
290+
set to :data:`True`, partial results may be returned for
291+
more than N rows. However, only N ``commit_row`` chunks
292+
will be sent.
293+
294+
:type filter_: :class:`.row.RowFilter`
295+
:param filter_: (Optional) The filter to apply to the contents of the
296+
specified row(s). If unset, reads every column in
297+
each row.
298+
299+
:rtype: :class:`.PartialRowsData`
300+
:returns: A :class:`.PartialRowsData` convenience wrapper for consuming
301+
the streamed results.
302+
"""
303+
request_pb = _create_row_request(
304+
self.name, start_key=start_key, end_key=end_key, filter_=filter_,
305+
allow_row_interleaving=allow_row_interleaving, limit=limit)
306+
client = self._cluster._client
307+
response_iterator = client._data_stub.ReadRows(request_pb,
308+
client.timeout_seconds)
309+
# We expect an iterator of `data_messages_pb2.ReadRowsResponse`
310+
return PartialRowsData(response_iterator)
311+
258312
def sample_row_keys(self):
259313
"""Read a sample of row keys in the table.
260314
@@ -314,9 +368,7 @@ def _create_row_request(table_name, row_key=None, start_key=None, end_key=None,
314368
The range will not include ``end_key``. If left empty,
315369
will be interpreted as an infinite string.
316370
317-
:type filter_: :class:`.row.RowFilter`, :class:`.row.RowFilterChain`,
318-
:class:`.row.RowFilterUnion` or
319-
:class:`.row.ConditionalRowFilter`
371+
:type filter_: :class:`.row.RowFilter`
320372
:param filter_: (Optional) The filter to apply to the contents of the
321373
specified row(s). If unset, reads the entire table.
322374

gcloud/bigtable/test_table.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,66 @@ def test_read_row_still_partial(self):
370370
with self.assertRaises(ValueError):
371371
self._read_row_helper(chunks)
372372

373+
def test_read_rows(self):
374+
from gcloud._testing import _Monkey
375+
from gcloud.bigtable._testing import _FakeStub
376+
from gcloud.bigtable.row_data import PartialRowsData
377+
from gcloud.bigtable import table as MUT
378+
379+
project_id = 'project-id'
380+
zone = 'zone'
381+
cluster_id = 'cluster-id'
382+
table_id = 'table-id'
383+
timeout_seconds = 1111
384+
client = _Client(timeout_seconds=timeout_seconds)
385+
cluster_name = ('projects/' + project_id + '/zones/' + zone +
386+
'/clusters/' + cluster_id)
387+
cluster = _Cluster(cluster_name, client=client)
388+
table = self._makeOne(table_id, cluster)
389+
390+
# Create request_pb
391+
request_pb = object() # Returned by our mock.
392+
mock_created = []
393+
394+
def mock_create_row_request(table_name, **kwargs):
395+
mock_created.append((table_name, kwargs))
396+
return request_pb
397+
398+
# Create response_iterator
399+
response_iterator = object()
400+
401+
# Patch the stub used by the API method.
402+
client._data_stub = stub = _FakeStub(response_iterator)
403+
404+
# Create expected_result.
405+
expected_result = PartialRowsData(response_iterator)
406+
407+
# Perform the method and check the result.
408+
start_key = b'start-key'
409+
end_key = b'end-key'
410+
filter_obj = object()
411+
allow_row_interleaving = True
412+
limit = 22
413+
with _Monkey(MUT, _create_row_request=mock_create_row_request):
414+
result = table.read_rows(
415+
start_key=start_key, end_key=end_key, filter_=filter_obj,
416+
allow_row_interleaving=allow_row_interleaving, limit=limit)
417+
418+
self.assertEqual(result, expected_result)
419+
self.assertEqual(stub.method_calls, [(
420+
'ReadRows',
421+
(request_pb, timeout_seconds),
422+
{},
423+
)])
424+
created_kwargs = {
425+
'start_key': start_key,
426+
'end_key': end_key,
427+
'filter_': filter_obj,
428+
'allow_row_interleaving': allow_row_interleaving,
429+
'limit': limit,
430+
}
431+
self.assertEqual(mock_created, [(table.name, created_kwargs)])
432+
373433
def test_sample_row_keys(self):
374434
from gcloud.bigtable._generated import (
375435
bigtable_service_messages_pb2 as messages_pb2)

0 commit comments

Comments
 (0)