Skip to content

Commit ae98aca

Browse files
authored
Merge pull request googleapis#3404 from GoogleCloudPlatform/3017-spanner-read_with_limit_and_range
Add tests for range reads and reads with limits.
2 parents a623929 + 0187911 commit ae98aca

File tree

1 file changed

+81
-9
lines changed

1 file changed

+81
-9
lines changed

spanner/tests/system.py

Lines changed: 81 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -492,24 +492,29 @@ def _row_data(max_index):
492492
yield [
493493
index,
494494
'First%09d' % (index,),
495-
'Last09%d' % (index),
495+
'Last%09d' % (max_index - index),
496496
'test-%09d@example.com' % (index,),
497497
]
498498

499-
def _set_up_table(self, row_count):
500-
retry = RetryInstanceState(_has_all_ddl)
501-
retry(self._db.reload)()
499+
def _set_up_table(self, row_count, db=None):
502500

503-
session = self._db.session()
501+
if db is None:
502+
db = self._db
503+
retry = RetryInstanceState(_has_all_ddl)
504+
retry(db.reload)()
505+
506+
session = db.session()
504507
session.create()
505508
self.to_delete.append(session)
506509

507-
with session.transaction() as transaction:
508-
transaction.delete(self.TABLE, self.ALL)
510+
def _unit_of_work(transaction, test):
511+
transaction.delete(test.TABLE, test.ALL)
509512
transaction.insert(
510-
self.TABLE, self.COLUMNS, self._row_data(row_count))
513+
test.TABLE, test.COLUMNS, test._row_data(row_count))
514+
515+
committed = session.run_in_transaction(_unit_of_work, test=self)
511516

512-
return session, transaction.committed
517+
return session, committed
513518

514519
def test_read_w_manual_consume(self):
515520
ROW_COUNT = 4000
@@ -531,6 +536,63 @@ def test_read_w_manual_consume(self):
531536
self.assertEqual(streamed._current_row, [])
532537
self.assertEqual(streamed._pending_chunk, None)
533538

539+
def test_read_w_index(self):
540+
ROW_COUNT = 2000
541+
# Indexed reads cannot return non-indexed columns
542+
MY_COLUMNS = self.COLUMNS[0], self.COLUMNS[2]
543+
EXTRA_DDL = [
544+
'CREATE INDEX contacts_by_last_name ON contacts(last_name)',
545+
]
546+
pool = BurstyPool()
547+
temp_db = Config.INSTANCE.database(
548+
'test_read_w_index', ddl_statements=DDL_STATEMENTS + EXTRA_DDL,
549+
pool=pool)
550+
operation = temp_db.create()
551+
self.to_delete.append(_DatabaseDropper(temp_db))
552+
553+
# We want to make sure the operation completes.
554+
operation.result(30) # raises on failure / timeout.
555+
556+
session, committed = self._set_up_table(ROW_COUNT, db=temp_db)
557+
558+
snapshot = session.snapshot(read_timestamp=committed)
559+
rows = list(snapshot.read(
560+
self.TABLE, MY_COLUMNS, self.ALL, index='contacts_by_last_name'))
561+
562+
expected = list(reversed(
563+
[(row[0], row[2]) for row in self._row_data(ROW_COUNT)]))
564+
self._check_row_data(rows, expected)
565+
566+
def test_read_w_limit(self):
567+
ROW_COUNT = 4000
568+
LIMIT = 100
569+
session, committed = self._set_up_table(ROW_COUNT)
570+
571+
snapshot = session.snapshot(read_timestamp=committed)
572+
rows = list(snapshot.read(
573+
self.TABLE, self.COLUMNS, self.ALL, limit=LIMIT))
574+
575+
all_data_rows = list(self._row_data(ROW_COUNT))
576+
expected = all_data_rows[:LIMIT]
577+
self._check_row_data(rows, expected)
578+
579+
def test_read_w_range(self):
580+
from google.cloud.spanner.keyset import KeyRange
581+
ROW_COUNT = 4000
582+
START_CLOSED = 1000
583+
END_OPEN = 2000
584+
session, committed = self._set_up_table(ROW_COUNT)
585+
key_range = KeyRange(start_closed=[START_CLOSED], end_open=[END_OPEN])
586+
keyset = KeySet(ranges=(key_range,))
587+
588+
snapshot = session.snapshot(read_timestamp=committed)
589+
rows = list(snapshot.read(
590+
self.TABLE, self.COLUMNS, keyset))
591+
592+
all_data_rows = list(self._row_data(ROW_COUNT))
593+
expected = all_data_rows[START_CLOSED:END_OPEN]
594+
self._check_row_data(rows, expected)
595+
534596
def test_execute_sql_w_manual_consume(self):
535597
ROW_COUNT = 4000
536598
session, committed = self._set_up_table(ROW_COUNT)
@@ -662,3 +724,13 @@ def test_execute_sql_w_query_param(self):
662724
param_types={'my_list': array_type},
663725
expected=[(u'dog',), (u'cat',)],
664726
)
727+
728+
729+
class _DatabaseDropper(object):
730+
"""Helper for cleaning up databases created on-the-fly."""
731+
732+
def __init__(self, db):
733+
self._db = db
734+
735+
def delete(self):
736+
self._db.drop()

0 commit comments

Comments
 (0)