Skip to content
This repository was archived by the owner on Mar 31, 2026. It is now read-only.

Commit a3b66dd

Browse files
perf: Skip gRPC trailers for StreamingRead & ExecuteStreamingSql
1 parent f9fd347 commit a3b66dd

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

google/cloud/spanner_v1/streamed.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ def __init__(
5454
self._column_info = column_info # Column information
5555
self._field_decoders = None
5656
self._lazy_decode = lazy_decode # Return protobuf values
57+
self._done = False
5758

5859
@property
5960
def fields(self):
@@ -159,11 +160,16 @@ def _consume_next(self):
159160

160161
self._merge_values(values)
161162

163+
if response_pb.last:
164+
self._done = True
165+
162166
def __iter__(self):
163167
while True:
164168
iter_rows, self._rows[:] = self._rows[:], ()
165169
while iter_rows:
166170
yield iter_rows.pop(0)
171+
if self._done:
172+
return
167173
try:
168174
self._consume_next()
169175
except StopIteration:

tests/unit/test_streamed.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,12 @@ def _make_result_set_stats(query_plan=None, **kw):
124124

125125
@staticmethod
126126
def _make_partial_result_set(
127-
values, metadata=None, stats=None, chunked_value=False
127+
values, metadata=None, stats=None, chunked_value=False, last=False
128128
):
129129
from google.cloud.spanner_v1 import PartialResultSet
130130

131131
results = PartialResultSet(
132-
metadata=metadata, stats=stats, chunked_value=chunked_value
132+
metadata=metadata, stats=stats, chunked_value=chunked_value, last=last
133133
)
134134
for v in values:
135135
results.values.append(v)
@@ -164,6 +164,35 @@ def test__merge_chunk_bool(self):
164164
with self.assertRaises(Unmergeable):
165165
streamed._merge_chunk(chunk)
166166

167+
def test__PartialResultSetWithLastFlag(self):
168+
from google.cloud.spanner_v1 import TypeCode
169+
170+
fields = [
171+
self._make_scalar_field("ID", TypeCode.INT64),
172+
self._make_scalar_field("NAME", TypeCode.STRING),
173+
]
174+
for length in range(4, 6):
175+
metadata = self._make_result_set_metadata(fields)
176+
result_sets = [
177+
self._make_partial_result_set([self._make_value(0), "google_0"],
178+
metadata=metadata)]
179+
for i in range(1, 5):
180+
bares = [i]
181+
values = [[self._make_value(bare), "google_" + str(bare)] for
182+
bare in bares]
183+
result_sets.append(self._make_partial_result_set(*values,
184+
metadata=metadata,
185+
last=(i == length - 1)))
186+
187+
iterator = _MockCancellableIterator(*result_sets)
188+
streamed = self._make_one(iterator)
189+
count = 0
190+
for row in streamed:
191+
self.assertEqual(row[0], count)
192+
self.assertEqual(row[1], "google_" + str(count))
193+
count += 1
194+
self.assertEqual(count, length)
195+
167196
def test__merge_chunk_numeric(self):
168197
from google.cloud.spanner_v1 import TypeCode
169198

0 commit comments

Comments
 (0)