diff --git a/google/cloud/spanner_v1/streamed.py b/google/cloud/spanner_v1/streamed.py index 1b3e87683c..368d7e6189 100644 --- a/google/cloud/spanner_v1/streamed.py +++ b/google/cloud/spanner_v1/streamed.py @@ -286,7 +286,13 @@ def _merge_struct(lhs, rhs, type_): lhs.append(first) else: last = lhs.pop() - lhs.append(_merge_by_type(last, first, candidate_type)) + try: + merged = _merge_by_type(last, first, candidate_type) + except Unmergeable: + lhs.append(last) + lhs.append(first) + else: + lhs.append(merged) return Value(list_value=ListValue(values=lhs + rhs)) diff --git a/tests/unit/test_streamed.py b/tests/unit/test_streamed.py index 3f3a90108d..d53ba3b21d 100644 --- a/tests/unit/test_streamed.py +++ b/tests/unit/test_streamed.py @@ -448,6 +448,26 @@ def test__merge_chunk_array_of_struct_unmergeable(self): self.assertEqual(merged, expected) self.assertIsNone(streamed._pending_chunk) + def test__merge_chunk_array_of_struct_unmergeable_split(self): + iterator = _MockCancellableIterator() + streamed = self._make_one(iterator) + struct_type = self._make_struct_type( + [("name", "STRING"), ("height", "FLOAT64"), ("eye_color", "STRING")] + ) + FIELDS = [self._make_array_field("test", element_type=struct_type)] + streamed._metadata = self._make_result_set_metadata(FIELDS) + partial = self._make_list_value([u"Phred Phlyntstone", 1.65]) + streamed._pending_chunk = self._make_list_value(value_pbs=[partial]) + rest = self._make_list_value(["brown"]) + chunk = self._make_list_value(value_pbs=[rest]) + + merged = streamed._merge_chunk(chunk) + + struct = self._make_list_value([u"Phred Phlyntstone", 1.65, "brown"]) + expected = self._make_list_value(value_pbs=[struct]) + self.assertEqual(merged, expected) + self.assertIsNone(streamed._pending_chunk) + def test_merge_values_empty_and_empty(self): iterator = _MockCancellableIterator() streamed = self._make_one(iterator)