This is an automated email from the ASF dual-hosted git repository.
luchunliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/inlong.git
The following commit(s) were added to refs/heads/master by this push:
new a6239e016c [INLONG-12141][SDK] PbSourceData returns protobuf default
values instead of null for unset fields (#12142)
a6239e016c is described below
commit a6239e016c2efe8518188bc24205c914ae3555b7
Author: ChunLiang Lu <[email protected]>
AuthorDate: Thu Jun 25 10:36:18 2026 +0800
[INLONG-12141][SDK] PbSourceData returns protobuf default values instead of
null for unset fields (#12142)
* [INLONG-12141][SDK] PbSourceData returns protobuf default values instead
of null for unset fields, causing incorrect data written to Iceberg/Parquet
sinks
* [INLONG-12141][SDK] PbSourceData returns protobuf default values instead
of null for unset fields, causing incorrect data written to Iceberg/Parquet
sinks
---
.../inlong/sdk/transform/decode/PbSourceData.java | 31 +++++++++++++++++-----
.../sdk/transform/decode/PbSourceDecoder.java | 2 +-
.../sdk/transform/process/TransformProcessor.java | 2 +-
.../temporal/TestFromUnixTimeFunction.java | 9 +++++++
.../process/processor/TestPb2RowDataProcessor.java | 2 +-
5 files changed, 36 insertions(+), 10 deletions(-)
diff --git
a/inlong-sdk/transform-sdk/src/main/java/org/apache/inlong/sdk/transform/decode/PbSourceData.java
b/inlong-sdk/transform-sdk/src/main/java/org/apache/inlong/sdk/transform/decode/PbSourceData.java
index f5d3569c2c..7f6fbcdf85 100644
---
a/inlong-sdk/transform-sdk/src/main/java/org/apache/inlong/sdk/transform/decode/PbSourceData.java
+++
b/inlong-sdk/transform-sdk/src/main/java/org/apache/inlong/sdk/transform/decode/PbSourceData.java
@@ -256,6 +256,10 @@ public class PbSourceData extends AbstractSourceData {
GenericRowData result = new
GenericRowData(messageType.getFields().size());
int index = 0;
for (FieldDescriptor fieldDesc : messageType.getFields()) {
+ if (!fieldDesc.isRepeated() && !msgObj.hasField(fieldDesc)) {
+ result.setField(index++, null);
+ continue;
+ }
Object fieldValue = msgObj.getField(fieldDesc);
if (fieldValue == null) {
result.setField(index++, null);
@@ -301,10 +305,12 @@ public class PbSourceData extends AbstractSourceData {
continue;
}
DynamicMessage subnodeValue = (DynamicMessage) value;
- Object keyValue = buildFieldValue(keyField,
subnodeValue.getField(keyField));
- Object valueValue = buildFieldValue(valueField,
subnodeValue.getField(valueField));
- if (keyValue != null && valueValue != null) {
- result.put(keyValue, valueValue);
+ if (subnodeValue.hasField(keyField) &&
subnodeValue.hasField(valueField)) {
+ Object keyValue = buildFieldValue(keyField,
subnodeValue.getField(keyField));
+ Object valueValue = buildFieldValue(valueField,
subnodeValue.getField(valueField));
+ if (keyValue != null && valueValue != null) {
+ result.put(keyValue, valueValue);
+ }
}
}
return new GenericMapData(result);
@@ -562,9 +568,11 @@ public class PbSourceData extends AbstractSourceData {
continue;
}
DynamicMessage msg = (DynamicMessage) value;
- Object keyValue = msg.getField(node.getMapKeyDesc());
- Object valueValue = msg.getField(node.getMapValueDesc());
- mapCache.put(keyValue, valueValue);
+ if (msg.hasField(node.getMapKeyDesc()) &&
msg.hasField(node.getMapValueDesc())) {
+ Object keyValue = msg.getField(node.getMapKeyDesc());
+ Object valueValue = msg.getField(node.getMapValueDesc());
+ mapCache.put(keyValue, valueValue);
+ }
}
return mapCache;
}
@@ -578,6 +586,9 @@ public class PbSourceData extends AbstractSourceData {
DynamicMessage current = root;
for (int i = 0; i < childNodes.size(); i++) {
PbNode node = childNodes.get(i);
+ if (!node.getFieldDesc().isRepeated() &&
!current.hasField(node.getFieldDesc())) {
+ break;
+ }
Object nodeValue = current.getField(node.getFieldDesc());
if (nodeValue == null) {
// error data
@@ -815,6 +826,9 @@ public class PbSourceData extends AbstractSourceData {
continue;
}
DynamicMessage entryMsg = (DynamicMessage) entry;
+ if (!entryMsg.hasField(mapKeyDesc) ||
!entryMsg.hasField(mapValueDesc)) {
+ continue;
+ }
Object keyVal = entryMsg.getField(mapKeyDesc);
if (keyVal == null || !Objects.equals(node.getMapKey(),
keyVal)) {
continue;
@@ -873,6 +887,9 @@ public class PbSourceData extends AbstractSourceData {
for (int i = 0; i < count; i++) {
Object entry = builder.getRepeatedField(fd, i);
if (entry instanceof DynamicMessage) {
+ if (!((DynamicMessage) entry).hasField(mapKeyDesc)) {
+ continue;
+ }
Object keyVal = ((DynamicMessage) entry).getField(mapKeyDesc);
if (Objects.equals(targetKey, keyVal)) {
removed = true;
diff --git
a/inlong-sdk/transform-sdk/src/main/java/org/apache/inlong/sdk/transform/decode/PbSourceDecoder.java
b/inlong-sdk/transform-sdk/src/main/java/org/apache/inlong/sdk/transform/decode/PbSourceDecoder.java
index 46ce0215f1..146063201f 100644
---
a/inlong-sdk/transform-sdk/src/main/java/org/apache/inlong/sdk/transform/decode/PbSourceDecoder.java
+++
b/inlong-sdk/transform-sdk/src/main/java/org/apache/inlong/sdk/transform/decode/PbSourceDecoder.java
@@ -107,7 +107,7 @@ public class PbSourceDecoder extends SourceDecoder<String> {
try {
// decode
DynamicMessage.Builder builder =
DynamicMessage.newBuilder(rootDesc);
- DynamicMessage root = builder.mergeFrom(srcBytes).build();
+ DynamicMessage root = builder.mergeFrom(srcBytes).buildPartial();
// child
List<DynamicMessage> childRoot = null;
if (this.childNodes != null && this.childNodes.size() > 0) {
diff --git
a/inlong-sdk/transform-sdk/src/main/java/org/apache/inlong/sdk/transform/process/TransformProcessor.java
b/inlong-sdk/transform-sdk/src/main/java/org/apache/inlong/sdk/transform/process/TransformProcessor.java
index cc70ee3f95..f0e39c04bd 100644
---
a/inlong-sdk/transform-sdk/src/main/java/org/apache/inlong/sdk/transform/process/TransformProcessor.java
+++
b/inlong-sdk/transform-sdk/src/main/java/org/apache/inlong/sdk/transform/process/TransformProcessor.java
@@ -230,7 +230,7 @@ public class TransformProcessor<I, O> {
try {
Object fieldValue = parser.parse(sourceData, i, context);
if (fieldValue == null) {
- sinkData.addField(fieldName, "");
+ sinkData.addField(fieldName, null);
} else {
sinkData.addField(fieldName, fieldValue);
}
diff --git
a/inlong-sdk/transform-sdk/src/test/java/org/apache/inlong/sdk/transform/process/function/temporal/TestFromUnixTimeFunction.java
b/inlong-sdk/transform-sdk/src/test/java/org/apache/inlong/sdk/transform/process/function/temporal/TestFromUnixTimeFunction.java
index 9d8c24d7b4..0be60f8338 100644
---
a/inlong-sdk/transform-sdk/src/test/java/org/apache/inlong/sdk/transform/process/function/temporal/TestFromUnixTimeFunction.java
+++
b/inlong-sdk/transform-sdk/src/test/java/org/apache/inlong/sdk/transform/process/function/temporal/TestFromUnixTimeFunction.java
@@ -91,5 +91,14 @@ public class TestFromUnixTimeFunction extends
AbstractFunctionTemporalTestBase {
List<String> output6 =
processor6.transform("can|apple|cloud|1753353737123|1|3", new HashMap<>());
Assert.assertEquals(1, output6.size());
Assert.assertEquals(output6.get(0), "result=2025-07-24 18:00:00");
+
+ String transformSql7 = "select from_unix_time(now()/1000,'yyyyMMddHH')
as partitionTime from source";
+ TransformConfig config7 = new TransformConfig(transformSql7);
+ TransformProcessor<String, String> processor7 = TransformProcessor
+ .create(config7,
SourceDecoderFactory.createCsvDecoder(csvSource),
+ SinkEncoderFactory.createKvEncoder(kvSink));
+ // case7: from_unix_time(now()/1000,'yyyyMMddHH')
+ List<String> output7 =
processor7.transform("can|apple|cloud|1753353737123|1|3", new HashMap<>());
+ Assert.assertEquals(1, output7.size());
}
}
diff --git
a/inlong-sdk/transform-sdk/src/test/java/org/apache/inlong/sdk/transform/process/processor/TestPb2RowDataProcessor.java
b/inlong-sdk/transform-sdk/src/test/java/org/apache/inlong/sdk/transform/process/processor/TestPb2RowDataProcessor.java
index 88d023bf38..495172d627 100644
---
a/inlong-sdk/transform-sdk/src/test/java/org/apache/inlong/sdk/transform/process/processor/TestPb2RowDataProcessor.java
+++
b/inlong-sdk/transform-sdk/src/test/java/org/apache/inlong/sdk/transform/process/processor/TestPb2RowDataProcessor.java
@@ -247,7 +247,7 @@ public class TestPb2RowDataProcessor extends
AbstractProcessorTestBase {
Assert.assertEquals(output.get(0).getString(1).toString(), "1");
Assert.assertEquals(output.get(0).getString(2).toString(),
"1713243918000");
- Assert.assertEquals(((GenericRowData) output.get(0).getRow(3,
3)).getBinary(0).length, 0);
+ Assert.assertEquals(((GenericRowData) output.get(0).getRow(3,
3)).getBinary(0), null);
Assert.assertEquals(((GenericRowData) output.get(0).getRow(3,
3)).getLong(1), 1713243918000L);
Assert.assertEquals(((GenericRowData) output.get(0).getRow(3,
3)).getMap(2).size(), 0);