Lokasi ngalangkungan proxy:   [ UP ]  
[Ngawartoskeun bug]   [Panyetelan cookie]                
Skip to content
This repository was archived by the owner on Feb 24, 2026. It is now read-only.

Commit df7c6e9

Browse files
chore: return row-level error information via an AppendSerializtionError (#1813)
exception.
1 parent 505f318 commit df7c6e9

2 files changed

Lines changed: 80 additions & 0 deletions

File tree

google-cloud-bigquerystorage/src/main/java/com/google/cloud/bigquery/storage/v1/ConnectionWorker.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.google.auto.value.AutoValue;
2222
import com.google.cloud.bigquery.storage.util.Errors;
2323
import com.google.cloud.bigquery.storage.v1.AppendRowsRequest.ProtoData;
24+
import com.google.cloud.bigquery.storage.v1.Exceptions.AppendSerializtionError;
2425
import com.google.cloud.bigquery.storage.v1.StreamConnection.DoneCallback;
2526
import com.google.cloud.bigquery.storage.v1.StreamConnection.RequestCallback;
2627
import com.google.common.annotations.VisibleForTesting;
@@ -32,7 +33,9 @@
3233
import java.io.IOException;
3334
import java.util.Comparator;
3435
import java.util.Deque;
36+
import java.util.HashMap;
3537
import java.util.LinkedList;
38+
import java.util.Map;
3639
import java.util.Set;
3740
import java.util.UUID;
3841
import java.util.concurrent.ConcurrentHashMap;
@@ -633,6 +636,15 @@ private void requestCallback(AppendRowsResponse response) {
633636
Exceptions.toStorageException(response.getError(), null);
634637
if (storageException != null) {
635638
requestWrapper.appendResult.setException(storageException);
639+
} else if (response.getRowErrorsCount() > 0) {
640+
Map<Integer, String> rowIndexToErrorMessage = new HashMap<>();
641+
for (int i = 0; i < response.getRowErrorsCount(); i++) {
642+
RowError rowError = response.getRowErrors(i);
643+
rowIndexToErrorMessage.put(Math.toIntExact(rowError.getIndex()), rowError.getMessage());
644+
}
645+
AppendSerializtionError exception =
646+
new AppendSerializtionError(streamName, rowIndexToErrorMessage);
647+
requestWrapper.appendResult.setException(exception);
636648
} else {
637649
StatusRuntimeException exception =
638650
new StatusRuntimeException(

google-cloud-bigquerystorage/src/test/java/com/google/cloud/bigquery/storage/v1/it/ITBigQueryWriteManualClientTest.java

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.google.cloud.bigquery.Schema;
2929
import com.google.cloud.bigquery.storage.test.Test.*;
3030
import com.google.cloud.bigquery.storage.v1.*;
31+
import com.google.cloud.bigquery.storage.v1.Exceptions.AppendSerializtionError;
3132
import com.google.cloud.bigquery.storage.v1.Exceptions.OffsetAlreadyExists;
3233
import com.google.cloud.bigquery.storage.v1.Exceptions.OffsetOutOfRange;
3334
import com.google.cloud.bigquery.storage.v1.Exceptions.SchemaMismatchedException;
@@ -313,6 +314,73 @@ public void testJsonStreamWriterCommittedStream()
313314
}
314315
}
315316

317+
@Test
318+
public void testRowErrors()
319+
throws IOException, InterruptedException, ExecutionException,
320+
Descriptors.DescriptorValidationException {
321+
String tableName = "_default";
322+
TableInfo tableInfo =
323+
TableInfo.newBuilder(
324+
TableId.of(DATASET, tableName),
325+
StandardTableDefinition.of(
326+
Schema.of(
327+
com.google.cloud.bigquery.Field.newBuilder(
328+
"foo", StandardSQLTypeName.STRING)
329+
.setMaxLength(10L)
330+
.build())))
331+
.build();
332+
bigquery.create(tableInfo);
333+
TableName parent = TableName.of(ServiceOptions.getDefaultProjectId(), DATASET, tableName);
334+
WriteStream writeStream =
335+
client.createWriteStream(
336+
CreateWriteStreamRequest.newBuilder()
337+
.setParent(parent.toString())
338+
.setWriteStream(
339+
WriteStream.newBuilder().setType(WriteStream.Type.COMMITTED).build())
340+
.build());
341+
StreamWriter streamWriter =
342+
StreamWriter.newBuilder(writeStream.getName())
343+
.setWriterSchema(ProtoSchemaConverter.convert(FooType.getDescriptor()))
344+
.build();
345+
LOG.info("Sending three messages");
346+
ApiFuture<AppendRowsResponse> futureResponse =
347+
streamWriter.append(
348+
CreateProtoRows(new String[] {"aaabbbcccddd", "bbb", "cccdddeeefffggg"}), -1);
349+
AppendRowsResponse actualResponse = null;
350+
try {
351+
actualResponse = futureResponse.get();
352+
} catch (Throwable t) {
353+
assertTrue(t instanceof ExecutionException);
354+
t = t.getCause();
355+
assertTrue(t instanceof AppendSerializtionError);
356+
AppendSerializtionError e = (AppendSerializtionError) t;
357+
LOG.info("Found row errors on stream: " + e.getStreamName());
358+
assertEquals(
359+
"Field foo: STRING(10) has maximum length 10 but got a value with length 12 on field foo.",
360+
e.getRowIndexToErrorMessage().get(0));
361+
assertEquals(
362+
"Field foo: STRING(10) has maximum length 10 but got a value with length 15 on field foo.",
363+
e.getRowIndexToErrorMessage().get(2));
364+
for (Map.Entry<Integer, String> entry : e.getRowIndexToErrorMessage().entrySet()) {
365+
LOG.info("Bad row index: " + entry.getKey() + ", has problem: " + entry.getValue());
366+
}
367+
}
368+
assertEquals(null, actualResponse);
369+
LOG.info("Resending with three good messages");
370+
ApiFuture<AppendRowsResponse> futureResponse1 =
371+
streamWriter.append(CreateProtoRows(new String[] {"aaa", "bbb", "ccc"}), -1);
372+
assertEquals(3, futureResponse1.get().getAppendResult().getOffset().getValue());
373+
374+
TableResult result =
375+
bigquery.listTableData(tableInfo.getTableId(), BigQuery.TableDataListOption.startIndex(0L));
376+
Iterator<FieldValueList> iter = result.getValues().iterator();
377+
FieldValueList currentRow = iter.next();
378+
assertEquals("aaa", currentRow.get(0).getStringValue());
379+
assertEquals("bbb", iter.next().get(0).getStringValue());
380+
assertEquals("ccc", iter.next().get(0).getStringValue());
381+
assertEquals(false, iter.hasNext());
382+
}
383+
316384
@Test
317385
public void testJsonStreamWriterWithDefaultSchema()
318386
throws IOException, InterruptedException, ExecutionException,

0 commit comments

Comments
 (0)