diff --git a/spanner/google/cloud/spanner_v1/streamed.py b/spanner/google/cloud/spanner_v1/streamed.py index 4e989e29cb72..bf154af849b5 100644 --- a/spanner/google/cloud/spanner_v1/streamed.py +++ b/spanner/google/cloud/spanner_v1/streamed.py @@ -256,6 +256,12 @@ def _merge_array(lhs, rhs, type_): lhs.list_value.values.extend(rhs.list_value.values) return lhs lhs, rhs = list(lhs.list_value.values), list(rhs.list_value.values) + + # Sanity check: If either list is empty, short-circuit. + # This is effectively a no-op. + if not len(lhs) or not len(rhs): + return Value(list_value=ListValue(values=(lhs + rhs))) + first = rhs.pop(0) if first.HasField('null_value'): # can't merge lhs.append(first) diff --git a/spanner/tests/unit/test_streamed.py b/spanner/tests/unit/test_streamed.py index 4ab5dbc18d48..408e272c9064 100644 --- a/spanner/tests/unit/test_streamed.py +++ b/spanner/tests/unit/test_streamed.py @@ -314,6 +314,22 @@ def test__merge_chunk_array_of_float(self): self.assertEqual(merged, expected) self.assertIsNone(streamed._pending_chunk) + def test__merge_chunk_array_of_string_with_empty(self): + iterator = _MockCancellableIterator() + streamed = self._make_one(iterator) + FIELDS = [ + self._make_array_field('name', element_type_code='STRING'), + ] + streamed._metadata = self._make_result_set_metadata(FIELDS) + streamed._pending_chunk = self._make_list_value([u'A', u'B', u'C']) + chunk = self._make_list_value([]) + + merged = streamed._merge_chunk(chunk) + + expected = self._make_list_value([u'A', u'B', u'C']) + self.assertEqual(merged, expected) + self.assertIsNone(streamed._pending_chunk) + def test__merge_chunk_array_of_string(self): iterator = _MockCancellableIterator() streamed = self._make_one(iterator)