You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hudi.apache.org by "xushiyan (via GitHub)" <gi...@apache.org> on 2023/05/09 12:41:58 UTC
[GitHub] [hudi] xushiyan opened a new pull request, #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
xushiyan opened a new pull request, #8675:
URL: https://github.com/apache/hudi/pull/8675
### Change Logs
- Add `HoodieAdaptablePayloadDataGenerator` to support testing different payload classes
- Improve test cases for `HoodieMergedReadHandle`
### Impact
More test coverage on different payload classes.
### Risk level
None.
### Documentation Update
NA
### Contributor's checklist
- [ ] Read through [contributor's guide](https://hudi.apache.org/contribute/how-to-contribute)
- [ ] Change Logs and Impact were stated clearly
- [ ] Adequate tests were added if applicable
- [ ] CI passed
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] hudi-bot commented on pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "hudi-bot (via GitHub)" <gi...@apache.org>.
hudi-bot commented on PR #8675:
URL: https://github.com/apache/hudi/pull/8675#issuecomment-1542490157
<!--
Meta data
{
"version" : 1,
"metaDataEntries" : [ {
"hash" : "eb510e9ae89ac152e29375c44becfadd02506674",
"status" : "UNKNOWN",
"url" : "TBD",
"triggerID" : "eb510e9ae89ac152e29375c44becfadd02506674",
"triggerType" : "PUSH"
}, {
"hash" : "e18fd60e894a76e386afb5d5b7cca5ae02c28c02",
"status" : "DELETED",
"url" : "https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16977",
"triggerID" : "e18fd60e894a76e386afb5d5b7cca5ae02c28c02",
"triggerType" : "PUSH"
}, {
"hash" : "f1376bc500e0b86fe595dbfa207d5bd77b8ac5ab",
"status" : "UNKNOWN",
"url" : "TBD",
"triggerID" : "f1376bc500e0b86fe595dbfa207d5bd77b8ac5ab",
"triggerType" : "PUSH"
}, {
"hash" : "fd1a22a9c708bf20c05bc4455121a6ba108b5869",
"status" : "SUCCESS",
"url" : "https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16997",
"triggerID" : "fd1a22a9c708bf20c05bc4455121a6ba108b5869",
"triggerType" : "PUSH"
} ]
}-->
## CI report:
* eb510e9ae89ac152e29375c44becfadd02506674 UNKNOWN
* f1376bc500e0b86fe595dbfa207d5bd77b8ac5ab UNKNOWN
* fd1a22a9c708bf20c05bc4455121a6ba108b5869 Azure: [SUCCESS](https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16997)
<details>
<summary>Bot commands</summary>
@hudi-bot supports the following commands:
- `@hudi-bot run azure` re-run the last Azure build
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] xushiyan commented on a diff in pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "xushiyan (via GitHub)" <gi...@apache.org>.
xushiyan commented on code in PR #8675:
URL: https://github.com/apache/hudi/pull/8675#discussion_r1191050917
##########
hudi-common/src/test/java/org/apache/hudi/common/testutils/HoodieAdaptablePayloadDataGenerator.java:
##########
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.hudi.common.testutils;
+
+import org.apache.hudi.avro.HoodieAvroUtils;
+import org.apache.hudi.common.model.AWSDmsAvroPayload;
+import org.apache.hudi.common.model.DefaultHoodieRecordPayload;
+import org.apache.hudi.common.model.HoodieAvroIndexedRecord;
+import org.apache.hudi.common.model.HoodieRecord;
+import org.apache.hudi.common.model.MetadataValues;
+import org.apache.hudi.common.model.OverwriteNonDefaultsWithLatestAvroPayload;
+import org.apache.hudi.common.model.OverwriteWithLatestAvroPayload;
+import org.apache.hudi.common.model.PartialUpdateAvroPayload;
+import org.apache.hudi.common.model.debezium.DebeziumConstants;
+import org.apache.hudi.common.model.debezium.MySqlDebeziumAvroPayload;
+import org.apache.hudi.common.model.debezium.PostgresDebeziumAvroPayload;
+import org.apache.hudi.common.table.HoodieTableConfig;
+import org.apache.hudi.common.util.Option;
+
+import org.apache.avro.Schema;
+import org.apache.avro.generic.GenericData;
+import org.apache.avro.generic.GenericRecord;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import static org.apache.hudi.common.model.HoodieRecord.HOODIE_IS_DELETED_FIELD;
+import static org.apache.hudi.common.util.ValidationUtils.checkArgument;
+
+public class HoodieAdaptablePayloadDataGenerator {
+
+ public static final Schema SCHEMA = SchemaTestUtil.getSchemaFromResource(HoodieAdaptablePayloadDataGenerator.class, "/adaptable-payload.avsc");
+ public static final Schema SCHEMA_WITH_METAFIELDS = HoodieAvroUtils.addMetadataFields(SCHEMA, false);
+ public static final String SCHEMA_STR = SCHEMA.toString();
+
+ public static Properties getKeyGenProps(Class<?> payloadClass) {
+ String orderingField = new RecordGen(payloadClass).getOrderingField();
+ Properties props = new Properties();
+ props.put("hoodie.datasource.write.recordkey.field", "id");
+ props.put("hoodie.datasource.write.partitionpath.field", "pt");
+ props.put("hoodie.datasource.write.precombine.field", orderingField);
+ props.put(HoodieTableConfig.RECORDKEY_FIELDS.key(), "id");
+ props.put(HoodieTableConfig.PARTITION_FIELDS.key(), "pt");
+ props.put(HoodieTableConfig.PRECOMBINE_FIELD.key(), orderingField);
+ return props;
+ }
+
+ public static Properties getPayloadProps(Class<?> payloadClass) {
+ String orderingField = new RecordGen(payloadClass).getOrderingField();
+ Properties props = new Properties();
+ props.put("hoodie.compaction.payload.class", payloadClass.getName());
+ props.put("hoodie.payload.event.time.field", orderingField);
+ props.put("hoodie.payload.ordering.field", orderingField);
+ return props;
+ }
+
+ public static List<HoodieRecord> getInserts(int n, String partition, long ts, Class<?> payloadClass) throws IOException {
+ return getInserts(n, new String[] {partition}, ts, payloadClass);
+ }
+
+ public static List<HoodieRecord> getInserts(int n, String[] partitions, long ts, Class<?> payloadClass) throws IOException {
+ List<HoodieRecord> inserts = new ArrayList<>();
+ RecordGen recordGen = new RecordGen(payloadClass);
+ for (GenericRecord r : getInserts(n, partitions, ts, recordGen)) {
+ inserts.add(getHoodieRecord(r, recordGen.getPayloadClass()));
+ }
+ return inserts;
+ }
+
+ private static List<GenericRecord> getInserts(int n, String[] partitions, long ts, RecordGen recordGen) {
+ return IntStream.range(0, n).mapToObj(id -> {
+ String pt = partitions.length == 0 ? "" : partitions[id % partitions.length];
+ return getInsert(id, pt, ts, recordGen);
+ }).collect(Collectors.toList());
+ }
+
+ private static GenericRecord getInsert(int id, String pt, long ts, RecordGen recordGen) {
+ GenericRecord r = new GenericData.Record(SCHEMA);
+ r.put("id", id);
+ r.put("pt", pt);
+ return recordGen.populateForInsert(r, ts);
+ }
+
+ public static List<HoodieRecord> getUpdates(List<HoodieRecord> baseRecords, long ts, Class<?> payloadClass) throws IOException {
+ RecordGen recordGen = new RecordGen(payloadClass);
+ List<HoodieRecord> updates = new ArrayList<>();
+ Properties props = new Properties();
+ for (HoodieRecord r : baseRecords) {
+ GenericRecord gr = (GenericRecord) r.toIndexedRecord(SCHEMA, props).get().getData();
+ GenericRecord updated = getUpdate(Integer.parseInt(gr.get("id").toString()), gr.get("pt").toString(), ts, recordGen);
+ updates.add(getHoodieRecord(updated, recordGen.getPayloadClass()));
+ }
+ return updates;
+ }
+
+ private static GenericRecord getUpdate(int id, String pt, long ts, RecordGen recordGen) {
+ GenericRecord r = new GenericData.Record(SCHEMA);
+ r.put("id", id);
Review Comment:
@danny0405 there are payloads like BaseAvroPayload (org.apache.hudi.common.model.BaseAvroPayload#isDeleteRecord) and subclasses actually check the delete marker field to determine if it's delete record. Also like Debezium payload checks `op=d` to determine deletion. so this is to emulate that situation.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] xushiyan commented on a diff in pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "xushiyan (via GitHub)" <gi...@apache.org>.
xushiyan commented on code in PR #8675:
URL: https://github.com/apache/hudi/pull/8675#discussion_r1191050917
##########
hudi-common/src/test/java/org/apache/hudi/common/testutils/HoodieAdaptablePayloadDataGenerator.java:
##########
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.hudi.common.testutils;
+
+import org.apache.hudi.avro.HoodieAvroUtils;
+import org.apache.hudi.common.model.AWSDmsAvroPayload;
+import org.apache.hudi.common.model.DefaultHoodieRecordPayload;
+import org.apache.hudi.common.model.HoodieAvroIndexedRecord;
+import org.apache.hudi.common.model.HoodieRecord;
+import org.apache.hudi.common.model.MetadataValues;
+import org.apache.hudi.common.model.OverwriteNonDefaultsWithLatestAvroPayload;
+import org.apache.hudi.common.model.OverwriteWithLatestAvroPayload;
+import org.apache.hudi.common.model.PartialUpdateAvroPayload;
+import org.apache.hudi.common.model.debezium.DebeziumConstants;
+import org.apache.hudi.common.model.debezium.MySqlDebeziumAvroPayload;
+import org.apache.hudi.common.model.debezium.PostgresDebeziumAvroPayload;
+import org.apache.hudi.common.table.HoodieTableConfig;
+import org.apache.hudi.common.util.Option;
+
+import org.apache.avro.Schema;
+import org.apache.avro.generic.GenericData;
+import org.apache.avro.generic.GenericRecord;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import static org.apache.hudi.common.model.HoodieRecord.HOODIE_IS_DELETED_FIELD;
+import static org.apache.hudi.common.util.ValidationUtils.checkArgument;
+
+public class HoodieAdaptablePayloadDataGenerator {
+
+ public static final Schema SCHEMA = SchemaTestUtil.getSchemaFromResource(HoodieAdaptablePayloadDataGenerator.class, "/adaptable-payload.avsc");
+ public static final Schema SCHEMA_WITH_METAFIELDS = HoodieAvroUtils.addMetadataFields(SCHEMA, false);
+ public static final String SCHEMA_STR = SCHEMA.toString();
+
+ public static Properties getKeyGenProps(Class<?> payloadClass) {
+ String orderingField = new RecordGen(payloadClass).getOrderingField();
+ Properties props = new Properties();
+ props.put("hoodie.datasource.write.recordkey.field", "id");
+ props.put("hoodie.datasource.write.partitionpath.field", "pt");
+ props.put("hoodie.datasource.write.precombine.field", orderingField);
+ props.put(HoodieTableConfig.RECORDKEY_FIELDS.key(), "id");
+ props.put(HoodieTableConfig.PARTITION_FIELDS.key(), "pt");
+ props.put(HoodieTableConfig.PRECOMBINE_FIELD.key(), orderingField);
+ return props;
+ }
+
+ public static Properties getPayloadProps(Class<?> payloadClass) {
+ String orderingField = new RecordGen(payloadClass).getOrderingField();
+ Properties props = new Properties();
+ props.put("hoodie.compaction.payload.class", payloadClass.getName());
+ props.put("hoodie.payload.event.time.field", orderingField);
+ props.put("hoodie.payload.ordering.field", orderingField);
+ return props;
+ }
+
+ public static List<HoodieRecord> getInserts(int n, String partition, long ts, Class<?> payloadClass) throws IOException {
+ return getInserts(n, new String[] {partition}, ts, payloadClass);
+ }
+
+ public static List<HoodieRecord> getInserts(int n, String[] partitions, long ts, Class<?> payloadClass) throws IOException {
+ List<HoodieRecord> inserts = new ArrayList<>();
+ RecordGen recordGen = new RecordGen(payloadClass);
+ for (GenericRecord r : getInserts(n, partitions, ts, recordGen)) {
+ inserts.add(getHoodieRecord(r, recordGen.getPayloadClass()));
+ }
+ return inserts;
+ }
+
+ private static List<GenericRecord> getInserts(int n, String[] partitions, long ts, RecordGen recordGen) {
+ return IntStream.range(0, n).mapToObj(id -> {
+ String pt = partitions.length == 0 ? "" : partitions[id % partitions.length];
+ return getInsert(id, pt, ts, recordGen);
+ }).collect(Collectors.toList());
+ }
+
+ private static GenericRecord getInsert(int id, String pt, long ts, RecordGen recordGen) {
+ GenericRecord r = new GenericData.Record(SCHEMA);
+ r.put("id", id);
+ r.put("pt", pt);
+ return recordGen.populateForInsert(r, ts);
+ }
+
+ public static List<HoodieRecord> getUpdates(List<HoodieRecord> baseRecords, long ts, Class<?> payloadClass) throws IOException {
+ RecordGen recordGen = new RecordGen(payloadClass);
+ List<HoodieRecord> updates = new ArrayList<>();
+ Properties props = new Properties();
+ for (HoodieRecord r : baseRecords) {
+ GenericRecord gr = (GenericRecord) r.toIndexedRecord(SCHEMA, props).get().getData();
+ GenericRecord updated = getUpdate(Integer.parseInt(gr.get("id").toString()), gr.get("pt").toString(), ts, recordGen);
+ updates.add(getHoodieRecord(updated, recordGen.getPayloadClass()));
+ }
+ return updates;
+ }
+
+ private static GenericRecord getUpdate(int id, String pt, long ts, RecordGen recordGen) {
+ GenericRecord r = new GenericData.Record(SCHEMA);
+ r.put("id", id);
Review Comment:
@danny0405 there are payloads like BaseAvroPayload (org.apache.hudi.common.model.BaseAvroPayload#isDeleteRecord) and subclasses actually check the delete marker field to determine if it's delete record. Also like Debezium payload checks `op=u` to determine deletion. so this is to emulate that situation.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] hudi-bot commented on pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "hudi-bot (via GitHub)" <gi...@apache.org>.
hudi-bot commented on PR #8675:
URL: https://github.com/apache/hudi/pull/8675#issuecomment-1542295054
<!--
Meta data
{
"version" : 1,
"metaDataEntries" : [ {
"hash" : "eb510e9ae89ac152e29375c44becfadd02506674",
"status" : "UNKNOWN",
"url" : "TBD",
"triggerID" : "eb510e9ae89ac152e29375c44becfadd02506674",
"triggerType" : "PUSH"
}, {
"hash" : "e18fd60e894a76e386afb5d5b7cca5ae02c28c02",
"status" : "SUCCESS",
"url" : "https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16977",
"triggerID" : "e18fd60e894a76e386afb5d5b7cca5ae02c28c02",
"triggerType" : "PUSH"
}, {
"hash" : "f1376bc500e0b86fe595dbfa207d5bd77b8ac5ab",
"status" : "UNKNOWN",
"url" : "TBD",
"triggerID" : "f1376bc500e0b86fe595dbfa207d5bd77b8ac5ab",
"triggerType" : "PUSH"
}, {
"hash" : "fd1a22a9c708bf20c05bc4455121a6ba108b5869",
"status" : "PENDING",
"url" : "https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16997",
"triggerID" : "fd1a22a9c708bf20c05bc4455121a6ba108b5869",
"triggerType" : "PUSH"
} ]
}-->
## CI report:
* eb510e9ae89ac152e29375c44becfadd02506674 UNKNOWN
* e18fd60e894a76e386afb5d5b7cca5ae02c28c02 Azure: [SUCCESS](https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16977)
* f1376bc500e0b86fe595dbfa207d5bd77b8ac5ab UNKNOWN
* fd1a22a9c708bf20c05bc4455121a6ba108b5869 Azure: [PENDING](https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16997)
<details>
<summary>Bot commands</summary>
@hudi-bot supports the following commands:
- `@hudi-bot run azure` re-run the last Azure build
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] xushiyan commented on a diff in pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "xushiyan (via GitHub)" <gi...@apache.org>.
xushiyan commented on code in PR #8675:
URL: https://github.com/apache/hudi/pull/8675#discussion_r1191040103
##########
hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/io/TestHoodieMergedReadHandle.java:
##########
@@ -38,113 +41,139 @@
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.generic.IndexedRecord;
+import org.apache.spark.api.java.JavaRDD;
import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.EnumSource;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
-import java.util.Properties;
import java.util.stream.Collectors;
-
-import static org.apache.hudi.avro.HoodieAvroUtils.addMetadataFields;
-import static org.apache.hudi.avro.HoodieAvroUtils.createHoodieRecordFromAvro;
-import static org.apache.hudi.common.testutils.HoodieTestDataGenerator.AVRO_SCHEMA;
-import static org.apache.hudi.common.testutils.HoodieTestDataGenerator.DEFAULT_FIRST_PARTITION_PATH;
+import java.util.stream.Stream;
+
+import static org.apache.hudi.common.model.HoodieTableType.COPY_ON_WRITE;
+import static org.apache.hudi.common.model.HoodieTableType.MERGE_ON_READ;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.SCHEMA;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.SCHEMA_STR;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.SCHEMA_WITH_METAFIELDS;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.getDeletes;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.getInserts;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.getKeyGenProps;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.getPayloadProps;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.getUpdates;
import static org.apache.hudi.common.testutils.HoodieTestDataGenerator.getCommitTimeAtUTC;
+import static org.apache.hudi.testutils.Assertions.assertNoWriteErrors;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class TestHoodieMergedReadHandle extends SparkClientFunctionalTestHarness {
- private HoodieTestDataGenerator dataGen = new HoodieTestDataGenerator();
+ private static Stream<Arguments> avroPayloadClasses() {
+ return Stream.of(
+ Arguments.of(COPY_ON_WRITE, OverwriteWithLatestAvroPayload.class),
+ Arguments.of(COPY_ON_WRITE, OverwriteNonDefaultsWithLatestAvroPayload.class),
+ Arguments.of(COPY_ON_WRITE, PartialUpdateAvroPayload.class),
+ Arguments.of(COPY_ON_WRITE, DefaultHoodieRecordPayload.class),
+ Arguments.of(MERGE_ON_READ, OverwriteWithLatestAvroPayload.class),
+ Arguments.of(MERGE_ON_READ, OverwriteNonDefaultsWithLatestAvroPayload.class),
+ Arguments.of(MERGE_ON_READ, PartialUpdateAvroPayload.class),
+ Arguments.of(MERGE_ON_READ, DefaultHoodieRecordPayload.class)
Review Comment:
need to extend the support in `HoodieAdaptablePayloadDataGenerator` as a candidate payload class for data generation
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] hudi-bot commented on pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "hudi-bot (via GitHub)" <gi...@apache.org>.
hudi-bot commented on PR #8675:
URL: https://github.com/apache/hudi/pull/8675#issuecomment-1540106183
<!--
Meta data
{
"version" : 1,
"metaDataEntries" : [ {
"hash" : "eb510e9ae89ac152e29375c44becfadd02506674",
"status" : "UNKNOWN",
"url" : "TBD",
"triggerID" : "eb510e9ae89ac152e29375c44becfadd02506674",
"triggerType" : "PUSH"
} ]
}-->
## CI report:
* eb510e9ae89ac152e29375c44becfadd02506674 UNKNOWN
<details>
<summary>Bot commands</summary>
@hudi-bot supports the following commands:
- `@hudi-bot run azure` re-run the last Azure build
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] hudi-bot commented on pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "hudi-bot (via GitHub)" <gi...@apache.org>.
hudi-bot commented on PR #8675:
URL: https://github.com/apache/hudi/pull/8675#issuecomment-1540899867
<!--
Meta data
{
"version" : 1,
"metaDataEntries" : [ {
"hash" : "eb510e9ae89ac152e29375c44becfadd02506674",
"status" : "UNKNOWN",
"url" : "TBD",
"triggerID" : "eb510e9ae89ac152e29375c44becfadd02506674",
"triggerType" : "PUSH"
}, {
"hash" : "e18fd60e894a76e386afb5d5b7cca5ae02c28c02",
"status" : "SUCCESS",
"url" : "https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16977",
"triggerID" : "e18fd60e894a76e386afb5d5b7cca5ae02c28c02",
"triggerType" : "PUSH"
} ]
}-->
## CI report:
* eb510e9ae89ac152e29375c44becfadd02506674 UNKNOWN
* e18fd60e894a76e386afb5d5b7cca5ae02c28c02 Azure: [SUCCESS](https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16977)
<details>
<summary>Bot commands</summary>
@hudi-bot supports the following commands:
- `@hudi-bot run azure` re-run the last Azure build
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] danny0405 commented on a diff in pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "danny0405 (via GitHub)" <gi...@apache.org>.
danny0405 commented on code in PR #8675:
URL: https://github.com/apache/hudi/pull/8675#discussion_r1190774678
##########
hudi-common/src/test/java/org/apache/hudi/common/testutils/HoodieAdaptablePayloadDataGenerator.java:
##########
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.hudi.common.testutils;
+
+import org.apache.hudi.avro.HoodieAvroUtils;
+import org.apache.hudi.common.model.AWSDmsAvroPayload;
+import org.apache.hudi.common.model.DefaultHoodieRecordPayload;
+import org.apache.hudi.common.model.HoodieAvroIndexedRecord;
+import org.apache.hudi.common.model.HoodieRecord;
+import org.apache.hudi.common.model.MetadataValues;
+import org.apache.hudi.common.model.OverwriteNonDefaultsWithLatestAvroPayload;
+import org.apache.hudi.common.model.OverwriteWithLatestAvroPayload;
+import org.apache.hudi.common.model.PartialUpdateAvroPayload;
+import org.apache.hudi.common.model.debezium.DebeziumConstants;
+import org.apache.hudi.common.model.debezium.MySqlDebeziumAvroPayload;
+import org.apache.hudi.common.model.debezium.PostgresDebeziumAvroPayload;
+import org.apache.hudi.common.table.HoodieTableConfig;
+import org.apache.hudi.common.util.Option;
+
+import org.apache.avro.Schema;
+import org.apache.avro.generic.GenericData;
+import org.apache.avro.generic.GenericRecord;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import static org.apache.hudi.common.model.HoodieRecord.HOODIE_IS_DELETED_FIELD;
+import static org.apache.hudi.common.util.ValidationUtils.checkArgument;
+
+public class HoodieAdaptablePayloadDataGenerator {
+
+ public static final Schema SCHEMA = SchemaTestUtil.getSchemaFromResource(HoodieAdaptablePayloadDataGenerator.class, "/adaptable-payload.avsc");
+ public static final Schema SCHEMA_WITH_METAFIELDS = HoodieAvroUtils.addMetadataFields(SCHEMA, false);
+ public static final String SCHEMA_STR = SCHEMA.toString();
+
+ public static Properties getKeyGenProps(Class<?> payloadClass) {
+ String orderingField = new RecordGen(payloadClass).getOrderingField();
+ Properties props = new Properties();
+ props.put("hoodie.datasource.write.recordkey.field", "id");
+ props.put("hoodie.datasource.write.partitionpath.field", "pt");
+ props.put("hoodie.datasource.write.precombine.field", orderingField);
+ props.put(HoodieTableConfig.RECORDKEY_FIELDS.key(), "id");
+ props.put(HoodieTableConfig.PARTITION_FIELDS.key(), "pt");
+ props.put(HoodieTableConfig.PRECOMBINE_FIELD.key(), orderingField);
+ return props;
+ }
+
+ public static Properties getPayloadProps(Class<?> payloadClass) {
+ String orderingField = new RecordGen(payloadClass).getOrderingField();
+ Properties props = new Properties();
+ props.put("hoodie.compaction.payload.class", payloadClass.getName());
+ props.put("hoodie.payload.event.time.field", orderingField);
+ props.put("hoodie.payload.ordering.field", orderingField);
+ return props;
+ }
+
+ public static List<HoodieRecord> getInserts(int n, String partition, long ts, Class<?> payloadClass) throws IOException {
+ return getInserts(n, new String[] {partition}, ts, payloadClass);
+ }
+
+ public static List<HoodieRecord> getInserts(int n, String[] partitions, long ts, Class<?> payloadClass) throws IOException {
+ List<HoodieRecord> inserts = new ArrayList<>();
+ RecordGen recordGen = new RecordGen(payloadClass);
+ for (GenericRecord r : getInserts(n, partitions, ts, recordGen)) {
+ inserts.add(getHoodieRecord(r, recordGen.getPayloadClass()));
+ }
+ return inserts;
+ }
+
+ private static List<GenericRecord> getInserts(int n, String[] partitions, long ts, RecordGen recordGen) {
+ return IntStream.range(0, n).mapToObj(id -> {
+ String pt = partitions.length == 0 ? "" : partitions[id % partitions.length];
+ return getInsert(id, pt, ts, recordGen);
+ }).collect(Collectors.toList());
+ }
+
+ private static GenericRecord getInsert(int id, String pt, long ts, RecordGen recordGen) {
+ GenericRecord r = new GenericData.Record(SCHEMA);
+ r.put("id", id);
+ r.put("pt", pt);
+ return recordGen.populateForInsert(r, ts);
+ }
+
+ public static List<HoodieRecord> getUpdates(List<HoodieRecord> baseRecords, long ts, Class<?> payloadClass) throws IOException {
+ RecordGen recordGen = new RecordGen(payloadClass);
+ List<HoodieRecord> updates = new ArrayList<>();
+ Properties props = new Properties();
+ for (HoodieRecord r : baseRecords) {
+ GenericRecord gr = (GenericRecord) r.toIndexedRecord(SCHEMA, props).get().getData();
+ GenericRecord updated = getUpdate(Integer.parseInt(gr.get("id").toString()), gr.get("pt").toString(), ts, recordGen);
+ updates.add(getHoodieRecord(updated, recordGen.getPayloadClass()));
+ }
+ return updates;
+ }
+
+ private static GenericRecord getUpdate(int id, String pt, long ts, RecordGen recordGen) {
+ GenericRecord r = new GenericData.Record(SCHEMA);
+ r.put("id", id);
Review Comment:
In reality, the delete record has null/empty payload bytes, for writer path, the record could hold a ordering field, for reader path like the payload serialized from avro logs, the odering field is also null because we can not extract it from the null payload bytes.
Can we follow the real use case for testing?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] danny0405 commented on a diff in pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "danny0405 (via GitHub)" <gi...@apache.org>.
danny0405 commented on code in PR #8675:
URL: https://github.com/apache/hudi/pull/8675#discussion_r1190776241
##########
hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/io/TestHoodieMergedReadHandle.java:
##########
@@ -38,113 +41,139 @@
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.generic.IndexedRecord;
+import org.apache.spark.api.java.JavaRDD;
import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.EnumSource;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
-import java.util.Properties;
import java.util.stream.Collectors;
-
-import static org.apache.hudi.avro.HoodieAvroUtils.addMetadataFields;
-import static org.apache.hudi.avro.HoodieAvroUtils.createHoodieRecordFromAvro;
-import static org.apache.hudi.common.testutils.HoodieTestDataGenerator.AVRO_SCHEMA;
-import static org.apache.hudi.common.testutils.HoodieTestDataGenerator.DEFAULT_FIRST_PARTITION_PATH;
+import java.util.stream.Stream;
+
+import static org.apache.hudi.common.model.HoodieTableType.COPY_ON_WRITE;
+import static org.apache.hudi.common.model.HoodieTableType.MERGE_ON_READ;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.SCHEMA;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.SCHEMA_STR;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.SCHEMA_WITH_METAFIELDS;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.getDeletes;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.getInserts;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.getKeyGenProps;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.getPayloadProps;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.getUpdates;
import static org.apache.hudi.common.testutils.HoodieTestDataGenerator.getCommitTimeAtUTC;
+import static org.apache.hudi.testutils.Assertions.assertNoWriteErrors;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class TestHoodieMergedReadHandle extends SparkClientFunctionalTestHarness {
- private HoodieTestDataGenerator dataGen = new HoodieTestDataGenerator();
+ private static Stream<Arguments> avroPayloadClasses() {
+ return Stream.of(
+ Arguments.of(COPY_ON_WRITE, OverwriteWithLatestAvroPayload.class),
+ Arguments.of(COPY_ON_WRITE, OverwriteNonDefaultsWithLatestAvroPayload.class),
+ Arguments.of(COPY_ON_WRITE, PartialUpdateAvroPayload.class),
+ Arguments.of(COPY_ON_WRITE, DefaultHoodieRecordPayload.class),
+ Arguments.of(MERGE_ON_READ, OverwriteWithLatestAvroPayload.class),
+ Arguments.of(MERGE_ON_READ, OverwriteNonDefaultsWithLatestAvroPayload.class),
+ Arguments.of(MERGE_ON_READ, PartialUpdateAvroPayload.class),
+ Arguments.of(MERGE_ON_READ, DefaultHoodieRecordPayload.class)
Review Comment:
Wondering how to extend the test once we add a new payload clazz ?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] danny0405 commented on pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "danny0405 (via GitHub)" <gi...@apache.org>.
danny0405 commented on PR #8675:
URL: https://github.com/apache/hudi/pull/8675#issuecomment-1545211244
Approved the PR first, we can address the delete tests in following PRs.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] xushiyan merged pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "xushiyan (via GitHub)" <gi...@apache.org>.
xushiyan merged PR #8675:
URL: https://github.com/apache/hudi/pull/8675
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] xushiyan commented on a diff in pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "xushiyan (via GitHub)" <gi...@apache.org>.
xushiyan commented on code in PR #8675:
URL: https://github.com/apache/hudi/pull/8675#discussion_r1191944536
##########
hudi-common/src/test/java/org/apache/hudi/common/testutils/HoodieAdaptablePayloadDataGenerator.java:
##########
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.hudi.common.testutils;
+
+import org.apache.hudi.avro.HoodieAvroUtils;
+import org.apache.hudi.common.model.AWSDmsAvroPayload;
+import org.apache.hudi.common.model.DefaultHoodieRecordPayload;
+import org.apache.hudi.common.model.HoodieAvroIndexedRecord;
+import org.apache.hudi.common.model.HoodieRecord;
+import org.apache.hudi.common.model.MetadataValues;
+import org.apache.hudi.common.model.OverwriteNonDefaultsWithLatestAvroPayload;
+import org.apache.hudi.common.model.OverwriteWithLatestAvroPayload;
+import org.apache.hudi.common.model.PartialUpdateAvroPayload;
+import org.apache.hudi.common.model.debezium.DebeziumConstants;
+import org.apache.hudi.common.model.debezium.MySqlDebeziumAvroPayload;
+import org.apache.hudi.common.model.debezium.PostgresDebeziumAvroPayload;
+import org.apache.hudi.common.table.HoodieTableConfig;
+import org.apache.hudi.common.util.Option;
+
+import org.apache.avro.Schema;
+import org.apache.avro.generic.GenericData;
+import org.apache.avro.generic.GenericRecord;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import static org.apache.hudi.common.model.HoodieRecord.HOODIE_IS_DELETED_FIELD;
+import static org.apache.hudi.common.util.ValidationUtils.checkArgument;
+
+public class HoodieAdaptablePayloadDataGenerator {
+
+ public static final Schema SCHEMA = SchemaTestUtil.getSchemaFromResource(HoodieAdaptablePayloadDataGenerator.class, "/adaptable-payload.avsc");
+ public static final Schema SCHEMA_WITH_METAFIELDS = HoodieAvroUtils.addMetadataFields(SCHEMA, false);
+ public static final String SCHEMA_STR = SCHEMA.toString();
+
+ public static Properties getKeyGenProps(Class<?> payloadClass) {
+ String orderingField = new RecordGen(payloadClass).getOrderingField();
+ Properties props = new Properties();
+ props.put("hoodie.datasource.write.recordkey.field", "id");
+ props.put("hoodie.datasource.write.partitionpath.field", "pt");
+ props.put("hoodie.datasource.write.precombine.field", orderingField);
+ props.put(HoodieTableConfig.RECORDKEY_FIELDS.key(), "id");
+ props.put(HoodieTableConfig.PARTITION_FIELDS.key(), "pt");
+ props.put(HoodieTableConfig.PRECOMBINE_FIELD.key(), orderingField);
+ return props;
+ }
+
+ public static Properties getPayloadProps(Class<?> payloadClass) {
+ String orderingField = new RecordGen(payloadClass).getOrderingField();
+ Properties props = new Properties();
+ props.put("hoodie.compaction.payload.class", payloadClass.getName());
+ props.put("hoodie.payload.event.time.field", orderingField);
+ props.put("hoodie.payload.ordering.field", orderingField);
+ return props;
+ }
+
+ public static List<HoodieRecord> getInserts(int n, String partition, long ts, Class<?> payloadClass) throws IOException {
+ return getInserts(n, new String[] {partition}, ts, payloadClass);
+ }
+
+ public static List<HoodieRecord> getInserts(int n, String[] partitions, long ts, Class<?> payloadClass) throws IOException {
+ List<HoodieRecord> inserts = new ArrayList<>();
+ RecordGen recordGen = new RecordGen(payloadClass);
+ for (GenericRecord r : getInserts(n, partitions, ts, recordGen)) {
+ inserts.add(getHoodieRecord(r, recordGen.getPayloadClass()));
+ }
+ return inserts;
+ }
+
+ private static List<GenericRecord> getInserts(int n, String[] partitions, long ts, RecordGen recordGen) {
+ return IntStream.range(0, n).mapToObj(id -> {
+ String pt = partitions.length == 0 ? "" : partitions[id % partitions.length];
+ return getInsert(id, pt, ts, recordGen);
+ }).collect(Collectors.toList());
+ }
+
+ private static GenericRecord getInsert(int id, String pt, long ts, RecordGen recordGen) {
+ GenericRecord r = new GenericData.Record(SCHEMA);
+ r.put("id", id);
+ r.put("pt", pt);
+ return recordGen.populateForInsert(r, ts);
+ }
+
+ public static List<HoodieRecord> getUpdates(List<HoodieRecord> baseRecords, long ts, Class<?> payloadClass) throws IOException {
+ RecordGen recordGen = new RecordGen(payloadClass);
+ List<HoodieRecord> updates = new ArrayList<>();
+ Properties props = new Properties();
+ for (HoodieRecord r : baseRecords) {
+ GenericRecord gr = (GenericRecord) r.toIndexedRecord(SCHEMA, props).get().getData();
+ GenericRecord updated = getUpdate(Integer.parseInt(gr.get("id").toString()), gr.get("pt").toString(), ts, recordGen);
+ updates.add(getHoodieRecord(updated, recordGen.getPayloadClass()));
+ }
+ return updates;
+ }
+
+ private static GenericRecord getUpdate(int id, String pt, long ts, RecordGen recordGen) {
+ GenericRecord r = new GenericData.Record(SCHEMA);
+ r.put("id", id);
Review Comment:
this will be followed up; this data gen class certainly needs to continuously evolve
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] hudi-bot commented on pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "hudi-bot (via GitHub)" <gi...@apache.org>.
hudi-bot commented on PR #8675:
URL: https://github.com/apache/hudi/pull/8675#issuecomment-1543315375
<!--
Meta data
{
"version" : 1,
"metaDataEntries" : [ {
"hash" : "eb510e9ae89ac152e29375c44becfadd02506674",
"status" : "UNKNOWN",
"url" : "TBD",
"triggerID" : "eb510e9ae89ac152e29375c44becfadd02506674",
"triggerType" : "PUSH"
}, {
"hash" : "e18fd60e894a76e386afb5d5b7cca5ae02c28c02",
"status" : "DELETED",
"url" : "https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16977",
"triggerID" : "e18fd60e894a76e386afb5d5b7cca5ae02c28c02",
"triggerType" : "PUSH"
}, {
"hash" : "f1376bc500e0b86fe595dbfa207d5bd77b8ac5ab",
"status" : "UNKNOWN",
"url" : "TBD",
"triggerID" : "f1376bc500e0b86fe595dbfa207d5bd77b8ac5ab",
"triggerType" : "PUSH"
}, {
"hash" : "fd1a22a9c708bf20c05bc4455121a6ba108b5869",
"status" : "SUCCESS",
"url" : "https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16997",
"triggerID" : "fd1a22a9c708bf20c05bc4455121a6ba108b5869",
"triggerType" : "PUSH"
}, {
"hash" : "875f77fd40a5b93dd7fcfa628e981f575372d6e7",
"status" : "UNKNOWN",
"url" : "TBD",
"triggerID" : "875f77fd40a5b93dd7fcfa628e981f575372d6e7",
"triggerType" : "PUSH"
} ]
}-->
## CI report:
* eb510e9ae89ac152e29375c44becfadd02506674 UNKNOWN
* f1376bc500e0b86fe595dbfa207d5bd77b8ac5ab UNKNOWN
* fd1a22a9c708bf20c05bc4455121a6ba108b5869 Azure: [SUCCESS](https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16997)
* 875f77fd40a5b93dd7fcfa628e981f575372d6e7 UNKNOWN
<details>
<summary>Bot commands</summary>
@hudi-bot supports the following commands:
- `@hudi-bot run azure` re-run the last Azure build
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] xushiyan commented on a diff in pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "xushiyan (via GitHub)" <gi...@apache.org>.
xushiyan commented on code in PR #8675:
URL: https://github.com/apache/hudi/pull/8675#discussion_r1191165570
##########
hudi-common/src/test/java/org/apache/hudi/common/testutils/HoodieAdaptablePayloadDataGenerator.java:
##########
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.hudi.common.testutils;
+
+import org.apache.hudi.avro.HoodieAvroUtils;
+import org.apache.hudi.common.model.AWSDmsAvroPayload;
+import org.apache.hudi.common.model.DefaultHoodieRecordPayload;
+import org.apache.hudi.common.model.HoodieAvroIndexedRecord;
+import org.apache.hudi.common.model.HoodieRecord;
+import org.apache.hudi.common.model.MetadataValues;
+import org.apache.hudi.common.model.OverwriteNonDefaultsWithLatestAvroPayload;
+import org.apache.hudi.common.model.OverwriteWithLatestAvroPayload;
+import org.apache.hudi.common.model.PartialUpdateAvroPayload;
+import org.apache.hudi.common.model.debezium.DebeziumConstants;
+import org.apache.hudi.common.model.debezium.MySqlDebeziumAvroPayload;
+import org.apache.hudi.common.model.debezium.PostgresDebeziumAvroPayload;
+import org.apache.hudi.common.table.HoodieTableConfig;
+import org.apache.hudi.common.util.Option;
+
+import org.apache.avro.Schema;
+import org.apache.avro.generic.GenericData;
+import org.apache.avro.generic.GenericRecord;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import static org.apache.hudi.common.model.HoodieRecord.HOODIE_IS_DELETED_FIELD;
+import static org.apache.hudi.common.util.ValidationUtils.checkArgument;
+
+public class HoodieAdaptablePayloadDataGenerator {
+
+ public static final Schema SCHEMA = SchemaTestUtil.getSchemaFromResource(HoodieAdaptablePayloadDataGenerator.class, "/adaptable-payload.avsc");
+ public static final Schema SCHEMA_WITH_METAFIELDS = HoodieAvroUtils.addMetadataFields(SCHEMA, false);
+ public static final String SCHEMA_STR = SCHEMA.toString();
+
+ public static Properties getKeyGenProps(Class<?> payloadClass) {
+ String orderingField = new RecordGen(payloadClass).getOrderingField();
+ Properties props = new Properties();
+ props.put("hoodie.datasource.write.recordkey.field", "id");
+ props.put("hoodie.datasource.write.partitionpath.field", "pt");
+ props.put("hoodie.datasource.write.precombine.field", orderingField);
+ props.put(HoodieTableConfig.RECORDKEY_FIELDS.key(), "id");
+ props.put(HoodieTableConfig.PARTITION_FIELDS.key(), "pt");
+ props.put(HoodieTableConfig.PRECOMBINE_FIELD.key(), orderingField);
+ return props;
+ }
+
+ public static Properties getPayloadProps(Class<?> payloadClass) {
+ String orderingField = new RecordGen(payloadClass).getOrderingField();
+ Properties props = new Properties();
+ props.put("hoodie.compaction.payload.class", payloadClass.getName());
+ props.put("hoodie.payload.event.time.field", orderingField);
+ props.put("hoodie.payload.ordering.field", orderingField);
+ return props;
+ }
+
+ public static List<HoodieRecord> getInserts(int n, String partition, long ts, Class<?> payloadClass) throws IOException {
+ return getInserts(n, new String[] {partition}, ts, payloadClass);
+ }
+
+ public static List<HoodieRecord> getInserts(int n, String[] partitions, long ts, Class<?> payloadClass) throws IOException {
+ List<HoodieRecord> inserts = new ArrayList<>();
+ RecordGen recordGen = new RecordGen(payloadClass);
+ for (GenericRecord r : getInserts(n, partitions, ts, recordGen)) {
+ inserts.add(getHoodieRecord(r, recordGen.getPayloadClass()));
+ }
+ return inserts;
+ }
+
+ private static List<GenericRecord> getInserts(int n, String[] partitions, long ts, RecordGen recordGen) {
+ return IntStream.range(0, n).mapToObj(id -> {
+ String pt = partitions.length == 0 ? "" : partitions[id % partitions.length];
+ return getInsert(id, pt, ts, recordGen);
+ }).collect(Collectors.toList());
+ }
+
+ private static GenericRecord getInsert(int id, String pt, long ts, RecordGen recordGen) {
+ GenericRecord r = new GenericData.Record(SCHEMA);
+ r.put("id", id);
+ r.put("pt", pt);
+ return recordGen.populateForInsert(r, ts);
+ }
+
+ public static List<HoodieRecord> getUpdates(List<HoodieRecord> baseRecords, long ts, Class<?> payloadClass) throws IOException {
+ RecordGen recordGen = new RecordGen(payloadClass);
+ List<HoodieRecord> updates = new ArrayList<>();
+ Properties props = new Properties();
+ for (HoodieRecord r : baseRecords) {
+ GenericRecord gr = (GenericRecord) r.toIndexedRecord(SCHEMA, props).get().getData();
+ GenericRecord updated = getUpdate(Integer.parseInt(gr.get("id").toString()), gr.get("pt").toString(), ts, recordGen);
+ updates.add(getHoodieRecord(updated, recordGen.getPayloadClass()));
+ }
+ return updates;
+ }
+
+ private static GenericRecord getUpdate(int id, String pt, long ts, RecordGen recordGen) {
+ GenericRecord r = new GenericData.Record(SCHEMA);
+ r.put("id", id);
+ r.put("pt", pt);
+ return recordGen.populateForUpdate(r, ts);
+ }
+
+ public static List<HoodieRecord> getDeletes(List<HoodieRecord> baseRecords, long ts, Class<?> payloadClass) throws IOException {
+ RecordGen recordGen = new RecordGen(payloadClass);
+ List<HoodieRecord> deletes = new ArrayList<>();
+ Properties props = new Properties();
+ for (HoodieRecord r : baseRecords) {
+ GenericRecord gr = (GenericRecord) r.toIndexedRecord(SCHEMA, props).get().getData();
+ GenericRecord deleted = getDelete(Integer.parseInt(gr.get("id").toString()), gr.get("pt").toString(), ts, recordGen);
+ deletes.add(getHoodieRecord(deleted, recordGen.getPayloadClass()));
+ }
+ return deletes;
+ }
+
+ private static GenericRecord getDelete(int id, String pt, long ts, RecordGen recordGen) {
+ GenericRecord r = new GenericData.Record(SCHEMA);
+ r.put("id", id);
+ r.put("pt", pt);
+ return recordGen.populateForDelete(r, ts);
+ }
+
+ private static HoodieRecord getHoodieRecord(GenericRecord r, Class<?> payloadClass) throws IOException {
+ return new HoodieAvroIndexedRecord(r)
+ .prependMetaFields(
+ SCHEMA,
+ SCHEMA_WITH_METAFIELDS,
+ new MetadataValues().setRecordKey(r.get("id").toString()).setPartitionPath(r.get("pt").toString()),
+ new Properties())
+ .wrapIntoHoodieRecordPayloadWithParams(
+ SCHEMA_WITH_METAFIELDS,
+ getPayloadProps(payloadClass),
+ Option.empty(),
+ false,
+ Option.empty(),
+ false,
+ Option.of(SCHEMA));
+ }
+
+ public static class RecordGen {
+
+ public static final Set<Class<?>> SUPPORTED_PAYLOAD_CLASSES = new HashSet<>(Arrays.asList(
+ OverwriteWithLatestAvroPayload.class,
+ OverwriteNonDefaultsWithLatestAvroPayload.class,
+ PartialUpdateAvroPayload.class,
+ DefaultHoodieRecordPayload.class,
+ AWSDmsAvroPayload.class,
+ MySqlDebeziumAvroPayload.class,
+ PostgresDebeziumAvroPayload.class
+ ));
+
+ private final Class<?> payloadClass;
+ private final String orderingField;
+
+ public RecordGen(Class<?> payloadClass) {
+ checkArgument(SUPPORTED_PAYLOAD_CLASSES.contains(payloadClass));
+ this.payloadClass = payloadClass;
+ if (payloadClass == MySqlDebeziumAvroPayload.class) {
+ orderingField = "_event_seq";
+ } else if (payloadClass == PostgresDebeziumAvroPayload.class) {
+ orderingField = "_event_lsn";
+ } else {
+ orderingField = "ts";
+ }
+ }
+
+ public Class<?> getPayloadClass() {
+ return payloadClass;
+ }
+
+ public String getOrderingField() {
+ return orderingField;
+ }
+
+ GenericRecord populateForInsert(GenericRecord r, long ts) {
+ r.put(orderingField, ts);
+ if (payloadClass == AWSDmsAvroPayload.class) {
+ r.put(AWSDmsAvroPayload.OP_FIELD, "I");
+ }
+ return r;
+ }
+
+ GenericRecord populateForUpdate(GenericRecord r, long ts) {
+ r.put(orderingField, ts);
+ if (payloadClass == AWSDmsAvroPayload.class) {
+ r.put(AWSDmsAvroPayload.OP_FIELD, "U");
+ }
+ return r;
+ }
+
+ GenericRecord populateForDelete(GenericRecord r, long ts) {
+ r.put(orderingField, ts);
+ if (payloadClass == MySqlDebeziumAvroPayload.class) {
+ r.put(DebeziumConstants.FLATTENED_OP_COL_NAME, DebeziumConstants.DELETE_OP);
+ } else if (payloadClass == PostgresDebeziumAvroPayload.class) {
+ r.put(DebeziumConstants.FLATTENED_OP_COL_NAME, DebeziumConstants.DELETE_OP);
+ } else if (payloadClass == AWSDmsAvroPayload.class) {
+ r.put(AWSDmsAvroPayload.OP_FIELD, "D");
+ } else {
Review Comment:
it's better for a UT for Default payload itself. The `_hoodie_is_deleted` marker is effectively also a custom marker. plus other custom marker like `op` field covered too.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] hudi-bot commented on pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "hudi-bot (via GitHub)" <gi...@apache.org>.
hudi-bot commented on PR #8675:
URL: https://github.com/apache/hudi/pull/8675#issuecomment-1543320126
<!--
Meta data
{
"version" : 1,
"metaDataEntries" : [ {
"hash" : "eb510e9ae89ac152e29375c44becfadd02506674",
"status" : "UNKNOWN",
"url" : "TBD",
"triggerID" : "eb510e9ae89ac152e29375c44becfadd02506674",
"triggerType" : "PUSH"
}, {
"hash" : "e18fd60e894a76e386afb5d5b7cca5ae02c28c02",
"status" : "DELETED",
"url" : "https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16977",
"triggerID" : "e18fd60e894a76e386afb5d5b7cca5ae02c28c02",
"triggerType" : "PUSH"
}, {
"hash" : "f1376bc500e0b86fe595dbfa207d5bd77b8ac5ab",
"status" : "UNKNOWN",
"url" : "TBD",
"triggerID" : "f1376bc500e0b86fe595dbfa207d5bd77b8ac5ab",
"triggerType" : "PUSH"
}, {
"hash" : "fd1a22a9c708bf20c05bc4455121a6ba108b5869",
"status" : "SUCCESS",
"url" : "https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16997",
"triggerID" : "fd1a22a9c708bf20c05bc4455121a6ba108b5869",
"triggerType" : "PUSH"
}, {
"hash" : "875f77fd40a5b93dd7fcfa628e981f575372d6e7",
"status" : "PENDING",
"url" : "https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=17013",
"triggerID" : "875f77fd40a5b93dd7fcfa628e981f575372d6e7",
"triggerType" : "PUSH"
} ]
}-->
## CI report:
* eb510e9ae89ac152e29375c44becfadd02506674 UNKNOWN
* f1376bc500e0b86fe595dbfa207d5bd77b8ac5ab UNKNOWN
* fd1a22a9c708bf20c05bc4455121a6ba108b5869 Azure: [SUCCESS](https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16997)
* 875f77fd40a5b93dd7fcfa628e981f575372d6e7 Azure: [PENDING](https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=17013)
<details>
<summary>Bot commands</summary>
@hudi-bot supports the following commands:
- `@hudi-bot run azure` re-run the last Azure build
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] hudi-bot commented on pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "hudi-bot (via GitHub)" <gi...@apache.org>.
hudi-bot commented on PR #8675:
URL: https://github.com/apache/hudi/pull/8675#issuecomment-1542223381
<!--
Meta data
{
"version" : 1,
"metaDataEntries" : [ {
"hash" : "eb510e9ae89ac152e29375c44becfadd02506674",
"status" : "UNKNOWN",
"url" : "TBD",
"triggerID" : "eb510e9ae89ac152e29375c44becfadd02506674",
"triggerType" : "PUSH"
}, {
"hash" : "e18fd60e894a76e386afb5d5b7cca5ae02c28c02",
"status" : "SUCCESS",
"url" : "https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16977",
"triggerID" : "e18fd60e894a76e386afb5d5b7cca5ae02c28c02",
"triggerType" : "PUSH"
}, {
"hash" : "f1376bc500e0b86fe595dbfa207d5bd77b8ac5ab",
"status" : "UNKNOWN",
"url" : "TBD",
"triggerID" : "f1376bc500e0b86fe595dbfa207d5bd77b8ac5ab",
"triggerType" : "PUSH"
}, {
"hash" : "fd1a22a9c708bf20c05bc4455121a6ba108b5869",
"status" : "UNKNOWN",
"url" : "TBD",
"triggerID" : "fd1a22a9c708bf20c05bc4455121a6ba108b5869",
"triggerType" : "PUSH"
} ]
}-->
## CI report:
* eb510e9ae89ac152e29375c44becfadd02506674 UNKNOWN
* e18fd60e894a76e386afb5d5b7cca5ae02c28c02 Azure: [SUCCESS](https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16977)
* f1376bc500e0b86fe595dbfa207d5bd77b8ac5ab UNKNOWN
* fd1a22a9c708bf20c05bc4455121a6ba108b5869 UNKNOWN
<details>
<summary>Bot commands</summary>
@hudi-bot supports the following commands:
- `@hudi-bot run azure` re-run the last Azure build
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] nsivabalan commented on a diff in pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "nsivabalan (via GitHub)" <gi...@apache.org>.
nsivabalan commented on code in PR #8675:
URL: https://github.com/apache/hudi/pull/8675#discussion_r1190600637
##########
hudi-common/src/test/java/org/apache/hudi/common/testutils/HoodieAdaptablePayloadDataGenerator.java:
##########
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.hudi.common.testutils;
+
+import org.apache.hudi.avro.HoodieAvroUtils;
+import org.apache.hudi.common.model.AWSDmsAvroPayload;
+import org.apache.hudi.common.model.DefaultHoodieRecordPayload;
+import org.apache.hudi.common.model.HoodieAvroIndexedRecord;
+import org.apache.hudi.common.model.HoodieRecord;
+import org.apache.hudi.common.model.MetadataValues;
+import org.apache.hudi.common.model.OverwriteNonDefaultsWithLatestAvroPayload;
+import org.apache.hudi.common.model.OverwriteWithLatestAvroPayload;
+import org.apache.hudi.common.model.PartialUpdateAvroPayload;
+import org.apache.hudi.common.model.debezium.DebeziumConstants;
+import org.apache.hudi.common.model.debezium.MySqlDebeziumAvroPayload;
+import org.apache.hudi.common.model.debezium.PostgresDebeziumAvroPayload;
+import org.apache.hudi.common.table.HoodieTableConfig;
+import org.apache.hudi.common.util.Option;
+
+import org.apache.avro.Schema;
+import org.apache.avro.generic.GenericData;
+import org.apache.avro.generic.GenericRecord;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import static org.apache.hudi.common.model.HoodieRecord.HOODIE_IS_DELETED_FIELD;
+import static org.apache.hudi.common.util.ValidationUtils.checkArgument;
+
+public class HoodieAdaptablePayloadDataGenerator {
+
+ public static final Schema SCHEMA = SchemaTestUtil.getSchemaFromResource(HoodieAdaptablePayloadDataGenerator.class, "/adaptable-payload.avsc");
+ public static final Schema SCHEMA_WITH_METAFIELDS = HoodieAvroUtils.addMetadataFields(SCHEMA, false);
+ public static final String SCHEMA_STR = SCHEMA.toString();
+
+ public static Properties getKeyGenProps(Class<?> payloadClass) {
+ String orderingField = new RecordGen(payloadClass).getOrderingField();
+ Properties props = new Properties();
+ props.put("hoodie.datasource.write.recordkey.field", "id");
+ props.put("hoodie.datasource.write.partitionpath.field", "pt");
+ props.put("hoodie.datasource.write.precombine.field", orderingField);
+ props.put(HoodieTableConfig.RECORDKEY_FIELDS.key(), "id");
+ props.put(HoodieTableConfig.PARTITION_FIELDS.key(), "pt");
+ props.put(HoodieTableConfig.PRECOMBINE_FIELD.key(), orderingField);
+ return props;
+ }
+
+ public static Properties getPayloadProps(Class<?> payloadClass) {
+ String orderingField = new RecordGen(payloadClass).getOrderingField();
+ Properties props = new Properties();
+ props.put("hoodie.compaction.payload.class", payloadClass.getName());
+ props.put("hoodie.payload.event.time.field", orderingField);
+ props.put("hoodie.payload.ordering.field", orderingField);
+ return props;
+ }
+
+ public static List<HoodieRecord> getInserts(int n, String partition, long ts, Class<?> payloadClass) throws IOException {
+ return getInserts(n, new String[] {partition}, ts, payloadClass);
+ }
+
+ public static List<HoodieRecord> getInserts(int n, String[] partitions, long ts, Class<?> payloadClass) throws IOException {
+ List<HoodieRecord> inserts = new ArrayList<>();
+ RecordGen recordGen = new RecordGen(payloadClass);
+ for (GenericRecord r : getInserts(n, partitions, ts, recordGen)) {
+ inserts.add(getHoodieRecord(r, recordGen.getPayloadClass()));
+ }
+ return inserts;
+ }
+
+ private static List<GenericRecord> getInserts(int n, String[] partitions, long ts, RecordGen recordGen) {
+ return IntStream.range(0, n).mapToObj(id -> {
+ String pt = partitions.length == 0 ? "" : partitions[id % partitions.length];
+ return getInsert(id, pt, ts, recordGen);
+ }).collect(Collectors.toList());
+ }
+
+ private static GenericRecord getInsert(int id, String pt, long ts, RecordGen recordGen) {
+ GenericRecord r = new GenericData.Record(SCHEMA);
+ r.put("id", id);
+ r.put("pt", pt);
+ return recordGen.populateForInsert(r, ts);
+ }
+
+ public static List<HoodieRecord> getUpdates(List<HoodieRecord> baseRecords, long ts, Class<?> payloadClass) throws IOException {
+ RecordGen recordGen = new RecordGen(payloadClass);
+ List<HoodieRecord> updates = new ArrayList<>();
+ Properties props = new Properties();
+ for (HoodieRecord r : baseRecords) {
+ GenericRecord gr = (GenericRecord) r.toIndexedRecord(SCHEMA, props).get().getData();
+ GenericRecord updated = getUpdate(Integer.parseInt(gr.get("id").toString()), gr.get("pt").toString(), ts, recordGen);
+ updates.add(getHoodieRecord(updated, recordGen.getPayloadClass()));
+ }
+ return updates;
+ }
+
+ private static GenericRecord getUpdate(int id, String pt, long ts, RecordGen recordGen) {
+ GenericRecord r = new GenericData.Record(SCHEMA);
+ r.put("id", id);
+ r.put("pt", pt);
+ return recordGen.populateForUpdate(r, ts);
+ }
+
+ public static List<HoodieRecord> getDeletes(List<HoodieRecord> baseRecords, long ts, Class<?> payloadClass) throws IOException {
+ RecordGen recordGen = new RecordGen(payloadClass);
+ List<HoodieRecord> deletes = new ArrayList<>();
+ Properties props = new Properties();
+ for (HoodieRecord r : baseRecords) {
+ GenericRecord gr = (GenericRecord) r.toIndexedRecord(SCHEMA, props).get().getData();
+ GenericRecord deleted = getDelete(Integer.parseInt(gr.get("id").toString()), gr.get("pt").toString(), ts, recordGen);
+ deletes.add(getHoodieRecord(deleted, recordGen.getPayloadClass()));
+ }
+ return deletes;
+ }
+
+ private static GenericRecord getDelete(int id, String pt, long ts, RecordGen recordGen) {
+ GenericRecord r = new GenericData.Record(SCHEMA);
+ r.put("id", id);
+ r.put("pt", pt);
+ return recordGen.populateForDelete(r, ts);
+ }
+
+ private static HoodieRecord getHoodieRecord(GenericRecord r, Class<?> payloadClass) throws IOException {
+ return new HoodieAvroIndexedRecord(r)
+ .prependMetaFields(
+ SCHEMA,
+ SCHEMA_WITH_METAFIELDS,
+ new MetadataValues().setRecordKey(r.get("id").toString()).setPartitionPath(r.get("pt").toString()),
+ new Properties())
+ .wrapIntoHoodieRecordPayloadWithParams(
+ SCHEMA_WITH_METAFIELDS,
+ getPayloadProps(payloadClass),
+ Option.empty(),
+ false,
+ Option.empty(),
+ false,
+ Option.of(SCHEMA));
+ }
+
+ public static class RecordGen {
+
+ public static final Set<Class<?>> SUPPORTED_PAYLOAD_CLASSES = new HashSet<>(Arrays.asList(
+ OverwriteWithLatestAvroPayload.class,
+ OverwriteNonDefaultsWithLatestAvroPayload.class,
Review Comment:
actual update for OverwriteNonDefaultsWithLatestAvroPayload, PartialUpdateAvroPayload might be different. but we should be good for the purpose of this patch. we can try to leverage community if someone really wants to write tests using how real payload might look like.
##########
hudi-common/src/test/java/org/apache/hudi/common/testutils/HoodieAdaptablePayloadDataGenerator.java:
##########
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.hudi.common.testutils;
+
+import org.apache.hudi.avro.HoodieAvroUtils;
+import org.apache.hudi.common.model.AWSDmsAvroPayload;
+import org.apache.hudi.common.model.DefaultHoodieRecordPayload;
+import org.apache.hudi.common.model.HoodieAvroIndexedRecord;
+import org.apache.hudi.common.model.HoodieRecord;
+import org.apache.hudi.common.model.MetadataValues;
+import org.apache.hudi.common.model.OverwriteNonDefaultsWithLatestAvroPayload;
+import org.apache.hudi.common.model.OverwriteWithLatestAvroPayload;
+import org.apache.hudi.common.model.PartialUpdateAvroPayload;
+import org.apache.hudi.common.model.debezium.DebeziumConstants;
+import org.apache.hudi.common.model.debezium.MySqlDebeziumAvroPayload;
+import org.apache.hudi.common.model.debezium.PostgresDebeziumAvroPayload;
+import org.apache.hudi.common.table.HoodieTableConfig;
+import org.apache.hudi.common.util.Option;
+
+import org.apache.avro.Schema;
+import org.apache.avro.generic.GenericData;
+import org.apache.avro.generic.GenericRecord;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import static org.apache.hudi.common.model.HoodieRecord.HOODIE_IS_DELETED_FIELD;
+import static org.apache.hudi.common.util.ValidationUtils.checkArgument;
+
+public class HoodieAdaptablePayloadDataGenerator {
Review Comment:
nice one. we should be able to leverage this class across the board to improve coverage for all diff payload classes.
##########
hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/io/TestHoodieMergedReadHandle.java:
##########
@@ -39,112 +44,143 @@
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.generic.IndexedRecord;
import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.EnumSource;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
-import java.util.Properties;
import java.util.stream.Collectors;
-
-import static org.apache.hudi.avro.HoodieAvroUtils.addMetadataFields;
-import static org.apache.hudi.avro.HoodieAvroUtils.createHoodieRecordFromAvro;
-import static org.apache.hudi.common.testutils.HoodieTestDataGenerator.AVRO_SCHEMA;
-import static org.apache.hudi.common.testutils.HoodieTestDataGenerator.DEFAULT_FIRST_PARTITION_PATH;
+import java.util.stream.Stream;
+
+import static org.apache.hudi.common.model.HoodieTableType.COPY_ON_WRITE;
+import static org.apache.hudi.common.model.HoodieTableType.MERGE_ON_READ;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.SCHEMA;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.SCHEMA_STR;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.SCHEMA_WITH_METAFIELDS;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.getKeyGenProps;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.getPayloadProps;
import static org.apache.hudi.common.testutils.HoodieTestDataGenerator.getCommitTimeAtUTC;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class TestHoodieMergedReadHandle extends SparkClientFunctionalTestHarness {
- private HoodieTestDataGenerator dataGen = new HoodieTestDataGenerator();
+ private HoodieAdaptablePayloadDataGenerator dataGen = new HoodieAdaptablePayloadDataGenerator();
+
+ private static Stream<Arguments> avroPayloadClasses() {
+ return Stream.of(
+ Arguments.of(COPY_ON_WRITE, OverwriteWithLatestAvroPayload.class, "ts"),
Review Comment:
good that we are able to cover all payload classes.
##########
hudi-common/src/test/java/org/apache/hudi/common/testutils/HoodieAdaptablePayloadDataGenerator.java:
##########
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.hudi.common.testutils;
+
+import org.apache.hudi.avro.HoodieAvroUtils;
+import org.apache.hudi.common.model.AWSDmsAvroPayload;
+import org.apache.hudi.common.model.DefaultHoodieRecordPayload;
+import org.apache.hudi.common.model.HoodieAvroIndexedRecord;
+import org.apache.hudi.common.model.HoodieRecord;
+import org.apache.hudi.common.model.MetadataValues;
+import org.apache.hudi.common.model.OverwriteNonDefaultsWithLatestAvroPayload;
+import org.apache.hudi.common.model.OverwriteWithLatestAvroPayload;
+import org.apache.hudi.common.model.PartialUpdateAvroPayload;
+import org.apache.hudi.common.model.debezium.DebeziumConstants;
+import org.apache.hudi.common.model.debezium.MySqlDebeziumAvroPayload;
+import org.apache.hudi.common.model.debezium.PostgresDebeziumAvroPayload;
+import org.apache.hudi.common.table.HoodieTableConfig;
+import org.apache.hudi.common.util.Option;
+
+import org.apache.avro.Schema;
+import org.apache.avro.generic.GenericData;
+import org.apache.avro.generic.GenericRecord;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import static org.apache.hudi.common.model.HoodieRecord.HOODIE_IS_DELETED_FIELD;
+import static org.apache.hudi.common.util.ValidationUtils.checkArgument;
+
+public class HoodieAdaptablePayloadDataGenerator {
+
+ public static final Schema SCHEMA = SchemaTestUtil.getSchemaFromResource(HoodieAdaptablePayloadDataGenerator.class, "/adaptable-payload.avsc");
+ public static final Schema SCHEMA_WITH_METAFIELDS = HoodieAvroUtils.addMetadataFields(SCHEMA, false);
+ public static final String SCHEMA_STR = SCHEMA.toString();
+
+ public static Properties getKeyGenProps(Class<?> payloadClass) {
+ String orderingField = new RecordGen(payloadClass).getOrderingField();
+ Properties props = new Properties();
+ props.put("hoodie.datasource.write.recordkey.field", "id");
+ props.put("hoodie.datasource.write.partitionpath.field", "pt");
+ props.put("hoodie.datasource.write.precombine.field", orderingField);
+ props.put(HoodieTableConfig.RECORDKEY_FIELDS.key(), "id");
+ props.put(HoodieTableConfig.PARTITION_FIELDS.key(), "pt");
+ props.put(HoodieTableConfig.PRECOMBINE_FIELD.key(), orderingField);
+ return props;
+ }
+
+ public static Properties getPayloadProps(Class<?> payloadClass) {
+ String orderingField = new RecordGen(payloadClass).getOrderingField();
+ Properties props = new Properties();
+ props.put("hoodie.compaction.payload.class", payloadClass.getName());
+ props.put("hoodie.payload.event.time.field", orderingField);
+ props.put("hoodie.payload.ordering.field", orderingField);
+ return props;
+ }
+
+ public static List<HoodieRecord> getInserts(int n, String partition, long ts, Class<?> payloadClass) throws IOException {
+ return getInserts(n, new String[] {partition}, ts, payloadClass);
+ }
+
+ public static List<HoodieRecord> getInserts(int n, String[] partitions, long ts, Class<?> payloadClass) throws IOException {
+ List<HoodieRecord> inserts = new ArrayList<>();
+ RecordGen recordGen = new RecordGen(payloadClass);
+ for (GenericRecord r : getInserts(n, partitions, ts, recordGen)) {
+ inserts.add(getHoodieRecord(r, recordGen.getPayloadClass()));
+ }
+ return inserts;
+ }
+
+ private static List<GenericRecord> getInserts(int n, String[] partitions, long ts, RecordGen recordGen) {
+ return IntStream.range(0, n).mapToObj(id -> {
+ String pt = partitions.length == 0 ? "" : partitions[id % partitions.length];
+ return getInsert(id, pt, ts, recordGen);
+ }).collect(Collectors.toList());
+ }
+
+ private static GenericRecord getInsert(int id, String pt, long ts, RecordGen recordGen) {
+ GenericRecord r = new GenericData.Record(SCHEMA);
+ r.put("id", id);
+ r.put("pt", pt);
+ return recordGen.populateForInsert(r, ts);
+ }
+
+ public static List<HoodieRecord> getUpdates(List<HoodieRecord> baseRecords, long ts, Class<?> payloadClass) throws IOException {
+ RecordGen recordGen = new RecordGen(payloadClass);
+ List<HoodieRecord> updates = new ArrayList<>();
+ Properties props = new Properties();
+ for (HoodieRecord r : baseRecords) {
+ GenericRecord gr = (GenericRecord) r.toIndexedRecord(SCHEMA, props).get().getData();
+ GenericRecord updated = getUpdate(Integer.parseInt(gr.get("id").toString()), gr.get("pt").toString(), ts, recordGen);
+ updates.add(getHoodieRecord(updated, recordGen.getPayloadClass()));
+ }
+ return updates;
+ }
+
+ private static GenericRecord getUpdate(int id, String pt, long ts, RecordGen recordGen) {
+ GenericRecord r = new GenericData.Record(SCHEMA);
+ r.put("id", id);
+ r.put("pt", pt);
+ return recordGen.populateForUpdate(r, ts);
+ }
+
+ public static List<HoodieRecord> getDeletes(List<HoodieRecord> baseRecords, long ts, Class<?> payloadClass) throws IOException {
+ RecordGen recordGen = new RecordGen(payloadClass);
+ List<HoodieRecord> deletes = new ArrayList<>();
+ Properties props = new Properties();
+ for (HoodieRecord r : baseRecords) {
+ GenericRecord gr = (GenericRecord) r.toIndexedRecord(SCHEMA, props).get().getData();
+ GenericRecord deleted = getDelete(Integer.parseInt(gr.get("id").toString()), gr.get("pt").toString(), ts, recordGen);
+ deletes.add(getHoodieRecord(deleted, recordGen.getPayloadClass()));
+ }
+ return deletes;
+ }
+
+ private static GenericRecord getDelete(int id, String pt, long ts, RecordGen recordGen) {
+ GenericRecord r = new GenericData.Record(SCHEMA);
+ r.put("id", id);
+ r.put("pt", pt);
+ return recordGen.populateForDelete(r, ts);
+ }
+
+ private static HoodieRecord getHoodieRecord(GenericRecord r, Class<?> payloadClass) throws IOException {
+ return new HoodieAvroIndexedRecord(r)
+ .prependMetaFields(
+ SCHEMA,
+ SCHEMA_WITH_METAFIELDS,
+ new MetadataValues().setRecordKey(r.get("id").toString()).setPartitionPath(r.get("pt").toString()),
+ new Properties())
+ .wrapIntoHoodieRecordPayloadWithParams(
+ SCHEMA_WITH_METAFIELDS,
+ getPayloadProps(payloadClass),
+ Option.empty(),
+ false,
+ Option.empty(),
+ false,
+ Option.of(SCHEMA));
+ }
+
+ public static class RecordGen {
+
+ public static final Set<Class<?>> SUPPORTED_PAYLOAD_CLASSES = new HashSet<>(Arrays.asList(
+ OverwriteWithLatestAvroPayload.class,
+ OverwriteNonDefaultsWithLatestAvroPayload.class,
+ PartialUpdateAvroPayload.class,
+ DefaultHoodieRecordPayload.class,
+ AWSDmsAvroPayload.class,
+ MySqlDebeziumAvroPayload.class,
+ PostgresDebeziumAvroPayload.class
+ ));
+
+ private final Class<?> payloadClass;
+ private final String orderingField;
+
+ public RecordGen(Class<?> payloadClass) {
+ checkArgument(SUPPORTED_PAYLOAD_CLASSES.contains(payloadClass));
+ this.payloadClass = payloadClass;
+ if (payloadClass == MySqlDebeziumAvroPayload.class) {
+ orderingField = "_event_seq";
+ } else if (payloadClass == PostgresDebeziumAvroPayload.class) {
+ orderingField = "_event_lsn";
+ } else {
+ orderingField = "ts";
+ }
+ }
+
+ public Class<?> getPayloadClass() {
+ return payloadClass;
+ }
+
+ public String getOrderingField() {
+ return orderingField;
+ }
+
+ GenericRecord populateForInsert(GenericRecord r, long ts) {
+ r.put(orderingField, ts);
+ if (payloadClass == AWSDmsAvroPayload.class) {
+ r.put(AWSDmsAvroPayload.OP_FIELD, "I");
+ }
+ return r;
+ }
+
+ GenericRecord populateForUpdate(GenericRecord r, long ts) {
+ r.put(orderingField, ts);
+ if (payloadClass == AWSDmsAvroPayload.class) {
+ r.put(AWSDmsAvroPayload.OP_FIELD, "U");
+ }
+ return r;
+ }
+
+ GenericRecord populateForDelete(GenericRecord r, long ts) {
+ r.put(orderingField, ts);
+ if (payloadClass == MySqlDebeziumAvroPayload.class) {
+ r.put(DebeziumConstants.FLATTENED_OP_COL_NAME, DebeziumConstants.DELETE_OP);
+ } else if (payloadClass == PostgresDebeziumAvroPayload.class) {
+ r.put(DebeziumConstants.FLATTENED_OP_COL_NAME, DebeziumConstants.DELETE_OP);
+ } else if (payloadClass == AWSDmsAvroPayload.class) {
+ r.put(AWSDmsAvroPayload.OP_FIELD, "D");
+ } else {
Review Comment:
can we also add DefaultHoodieRecordPayload here where we can use a custom maker.
guess we might need to take in a config may be to optionally leverage delete marker.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] hudi-bot commented on pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "hudi-bot (via GitHub)" <gi...@apache.org>.
hudi-bot commented on PR #8675:
URL: https://github.com/apache/hudi/pull/8675#issuecomment-1542209987
<!--
Meta data
{
"version" : 1,
"metaDataEntries" : [ {
"hash" : "eb510e9ae89ac152e29375c44becfadd02506674",
"status" : "UNKNOWN",
"url" : "TBD",
"triggerID" : "eb510e9ae89ac152e29375c44becfadd02506674",
"triggerType" : "PUSH"
}, {
"hash" : "e18fd60e894a76e386afb5d5b7cca5ae02c28c02",
"status" : "SUCCESS",
"url" : "https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16977",
"triggerID" : "e18fd60e894a76e386afb5d5b7cca5ae02c28c02",
"triggerType" : "PUSH"
}, {
"hash" : "f1376bc500e0b86fe595dbfa207d5bd77b8ac5ab",
"status" : "UNKNOWN",
"url" : "TBD",
"triggerID" : "f1376bc500e0b86fe595dbfa207d5bd77b8ac5ab",
"triggerType" : "PUSH"
} ]
}-->
## CI report:
* eb510e9ae89ac152e29375c44becfadd02506674 UNKNOWN
* e18fd60e894a76e386afb5d5b7cca5ae02c28c02 Azure: [SUCCESS](https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16977)
* f1376bc500e0b86fe595dbfa207d5bd77b8ac5ab UNKNOWN
<details>
<summary>Bot commands</summary>
@hudi-bot supports the following commands:
- `@hudi-bot run azure` re-run the last Azure build
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] hudi-bot commented on pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "hudi-bot (via GitHub)" <gi...@apache.org>.
hudi-bot commented on PR #8675:
URL: https://github.com/apache/hudi/pull/8675#issuecomment-1540137388
<!--
Meta data
{
"version" : 1,
"metaDataEntries" : [ {
"hash" : "eb510e9ae89ac152e29375c44becfadd02506674",
"status" : "UNKNOWN",
"url" : "TBD",
"triggerID" : "eb510e9ae89ac152e29375c44becfadd02506674",
"triggerType" : "PUSH"
}, {
"hash" : "e18fd60e894a76e386afb5d5b7cca5ae02c28c02",
"status" : "PENDING",
"url" : "https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16977",
"triggerID" : "e18fd60e894a76e386afb5d5b7cca5ae02c28c02",
"triggerType" : "PUSH"
} ]
}-->
## CI report:
* eb510e9ae89ac152e29375c44becfadd02506674 UNKNOWN
* e18fd60e894a76e386afb5d5b7cca5ae02c28c02 Azure: [PENDING](https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16977)
<details>
<summary>Bot commands</summary>
@hudi-bot supports the following commands:
- `@hudi-bot run azure` re-run the last Azure build
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] nsivabalan commented on a diff in pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "nsivabalan (via GitHub)" <gi...@apache.org>.
nsivabalan commented on code in PR #8675:
URL: https://github.com/apache/hudi/pull/8675#discussion_r1191341277
##########
hudi-common/src/test/java/org/apache/hudi/common/testutils/HoodieAdaptablePayloadDataGenerator.java:
##########
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.hudi.common.testutils;
+
+import org.apache.hudi.avro.HoodieAvroUtils;
+import org.apache.hudi.common.model.AWSDmsAvroPayload;
+import org.apache.hudi.common.model.DefaultHoodieRecordPayload;
+import org.apache.hudi.common.model.HoodieAvroIndexedRecord;
+import org.apache.hudi.common.model.HoodieRecord;
+import org.apache.hudi.common.model.MetadataValues;
+import org.apache.hudi.common.model.OverwriteNonDefaultsWithLatestAvroPayload;
+import org.apache.hudi.common.model.OverwriteWithLatestAvroPayload;
+import org.apache.hudi.common.model.PartialUpdateAvroPayload;
+import org.apache.hudi.common.model.debezium.DebeziumConstants;
+import org.apache.hudi.common.model.debezium.MySqlDebeziumAvroPayload;
+import org.apache.hudi.common.model.debezium.PostgresDebeziumAvroPayload;
+import org.apache.hudi.common.table.HoodieTableConfig;
+import org.apache.hudi.common.util.Option;
+
+import org.apache.avro.Schema;
+import org.apache.avro.generic.GenericData;
+import org.apache.avro.generic.GenericRecord;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import static org.apache.hudi.common.model.HoodieRecord.HOODIE_IS_DELETED_FIELD;
+import static org.apache.hudi.common.util.ValidationUtils.checkArgument;
+
+public class HoodieAdaptablePayloadDataGenerator {
+
+ public static final Schema SCHEMA = SchemaTestUtil.getSchemaFromResource(HoodieAdaptablePayloadDataGenerator.class, "/adaptable-payload.avsc");
+ public static final Schema SCHEMA_WITH_METAFIELDS = HoodieAvroUtils.addMetadataFields(SCHEMA, false);
+ public static final String SCHEMA_STR = SCHEMA.toString();
+
+ public static Properties getKeyGenProps(Class<?> payloadClass) {
+ String orderingField = new RecordGen(payloadClass).getOrderingField();
+ Properties props = new Properties();
+ props.put("hoodie.datasource.write.recordkey.field", "id");
+ props.put("hoodie.datasource.write.partitionpath.field", "pt");
+ props.put("hoodie.datasource.write.precombine.field", orderingField);
+ props.put(HoodieTableConfig.RECORDKEY_FIELDS.key(), "id");
+ props.put(HoodieTableConfig.PARTITION_FIELDS.key(), "pt");
+ props.put(HoodieTableConfig.PRECOMBINE_FIELD.key(), orderingField);
+ return props;
+ }
+
+ public static Properties getPayloadProps(Class<?> payloadClass) {
+ String orderingField = new RecordGen(payloadClass).getOrderingField();
+ Properties props = new Properties();
+ props.put("hoodie.compaction.payload.class", payloadClass.getName());
+ props.put("hoodie.payload.event.time.field", orderingField);
+ props.put("hoodie.payload.ordering.field", orderingField);
+ return props;
+ }
+
+ public static List<HoodieRecord> getInserts(int n, String partition, long ts, Class<?> payloadClass) throws IOException {
+ return getInserts(n, new String[] {partition}, ts, payloadClass);
+ }
+
+ public static List<HoodieRecord> getInserts(int n, String[] partitions, long ts, Class<?> payloadClass) throws IOException {
+ List<HoodieRecord> inserts = new ArrayList<>();
+ RecordGen recordGen = new RecordGen(payloadClass);
+ for (GenericRecord r : getInserts(n, partitions, ts, recordGen)) {
+ inserts.add(getHoodieRecord(r, recordGen.getPayloadClass()));
+ }
+ return inserts;
+ }
+
+ private static List<GenericRecord> getInserts(int n, String[] partitions, long ts, RecordGen recordGen) {
+ return IntStream.range(0, n).mapToObj(id -> {
+ String pt = partitions.length == 0 ? "" : partitions[id % partitions.length];
+ return getInsert(id, pt, ts, recordGen);
+ }).collect(Collectors.toList());
+ }
+
+ private static GenericRecord getInsert(int id, String pt, long ts, RecordGen recordGen) {
+ GenericRecord r = new GenericData.Record(SCHEMA);
+ r.put("id", id);
+ r.put("pt", pt);
+ return recordGen.populateForInsert(r, ts);
+ }
+
+ public static List<HoodieRecord> getUpdates(List<HoodieRecord> baseRecords, long ts, Class<?> payloadClass) throws IOException {
+ RecordGen recordGen = new RecordGen(payloadClass);
+ List<HoodieRecord> updates = new ArrayList<>();
+ Properties props = new Properties();
+ for (HoodieRecord r : baseRecords) {
+ GenericRecord gr = (GenericRecord) r.toIndexedRecord(SCHEMA, props).get().getData();
+ GenericRecord updated = getUpdate(Integer.parseInt(gr.get("id").toString()), gr.get("pt").toString(), ts, recordGen);
+ updates.add(getHoodieRecord(updated, recordGen.getPayloadClass()));
+ }
+ return updates;
+ }
+
+ private static GenericRecord getUpdate(int id, String pt, long ts, RecordGen recordGen) {
+ GenericRecord r = new GenericData.Record(SCHEMA);
+ r.put("id", id);
Review Comment:
what Danny is suggesting is to go via "EmptyHoodieRecordPayload" and see how that pans out. this is what happens when someone uses "delete" as the operation type, or in global index code path as well.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] xushiyan commented on a diff in pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "xushiyan (via GitHub)" <gi...@apache.org>.
xushiyan commented on code in PR #8675:
URL: https://github.com/apache/hudi/pull/8675#discussion_r1190611852
##########
hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/io/TestHoodieMergedReadHandle.java:
##########
@@ -38,113 +41,139 @@
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.generic.IndexedRecord;
+import org.apache.spark.api.java.JavaRDD;
import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.EnumSource;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
-import java.util.Properties;
import java.util.stream.Collectors;
-
-import static org.apache.hudi.avro.HoodieAvroUtils.addMetadataFields;
-import static org.apache.hudi.avro.HoodieAvroUtils.createHoodieRecordFromAvro;
-import static org.apache.hudi.common.testutils.HoodieTestDataGenerator.AVRO_SCHEMA;
-import static org.apache.hudi.common.testutils.HoodieTestDataGenerator.DEFAULT_FIRST_PARTITION_PATH;
+import java.util.stream.Stream;
+
+import static org.apache.hudi.common.model.HoodieTableType.COPY_ON_WRITE;
+import static org.apache.hudi.common.model.HoodieTableType.MERGE_ON_READ;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.SCHEMA;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.SCHEMA_STR;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.SCHEMA_WITH_METAFIELDS;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.getDeletes;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.getInserts;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.getKeyGenProps;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.getPayloadProps;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.getUpdates;
import static org.apache.hudi.common.testutils.HoodieTestDataGenerator.getCommitTimeAtUTC;
+import static org.apache.hudi.testutils.Assertions.assertNoWriteErrors;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class TestHoodieMergedReadHandle extends SparkClientFunctionalTestHarness {
- private HoodieTestDataGenerator dataGen = new HoodieTestDataGenerator();
+ private static Stream<Arguments> avroPayloadClasses() {
+ return Stream.of(
+ Arguments.of(COPY_ON_WRITE, OverwriteWithLatestAvroPayload.class),
+ Arguments.of(COPY_ON_WRITE, OverwriteNonDefaultsWithLatestAvroPayload.class),
+ Arguments.of(COPY_ON_WRITE, PartialUpdateAvroPayload.class),
+ Arguments.of(COPY_ON_WRITE, DefaultHoodieRecordPayload.class),
+ Arguments.of(MERGE_ON_READ, OverwriteWithLatestAvroPayload.class),
+ Arguments.of(MERGE_ON_READ, OverwriteNonDefaultsWithLatestAvroPayload.class),
+ Arguments.of(MERGE_ON_READ, PartialUpdateAvroPayload.class),
+ Arguments.of(MERGE_ON_READ, DefaultHoodieRecordPayload.class)
Review Comment:
purposely left out AWSDmsPayload and debezium payload cases https://github.com/apache/hudi/pull/8675/commits/875f77fd40a5b93dd7fcfa628e981f575372d6e7
to land this patch. When doing proper fix for payload, those classes can be added here to cover custom delete marker scenario.
##########
hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/io/TestHoodieMergedReadHandle.java:
##########
@@ -38,113 +41,139 @@
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.generic.IndexedRecord;
+import org.apache.spark.api.java.JavaRDD;
import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.EnumSource;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
-import java.util.Properties;
import java.util.stream.Collectors;
-
-import static org.apache.hudi.avro.HoodieAvroUtils.addMetadataFields;
-import static org.apache.hudi.avro.HoodieAvroUtils.createHoodieRecordFromAvro;
-import static org.apache.hudi.common.testutils.HoodieTestDataGenerator.AVRO_SCHEMA;
-import static org.apache.hudi.common.testutils.HoodieTestDataGenerator.DEFAULT_FIRST_PARTITION_PATH;
+import java.util.stream.Stream;
+
+import static org.apache.hudi.common.model.HoodieTableType.COPY_ON_WRITE;
+import static org.apache.hudi.common.model.HoodieTableType.MERGE_ON_READ;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.SCHEMA;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.SCHEMA_STR;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.SCHEMA_WITH_METAFIELDS;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.getDeletes;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.getInserts;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.getKeyGenProps;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.getPayloadProps;
+import static org.apache.hudi.common.testutils.HoodieAdaptablePayloadDataGenerator.getUpdates;
import static org.apache.hudi.common.testutils.HoodieTestDataGenerator.getCommitTimeAtUTC;
+import static org.apache.hudi.testutils.Assertions.assertNoWriteErrors;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class TestHoodieMergedReadHandle extends SparkClientFunctionalTestHarness {
- private HoodieTestDataGenerator dataGen = new HoodieTestDataGenerator();
+ private static Stream<Arguments> avroPayloadClasses() {
+ return Stream.of(
+ Arguments.of(COPY_ON_WRITE, OverwriteWithLatestAvroPayload.class),
+ Arguments.of(COPY_ON_WRITE, OverwriteNonDefaultsWithLatestAvroPayload.class),
+ Arguments.of(COPY_ON_WRITE, PartialUpdateAvroPayload.class),
+ Arguments.of(COPY_ON_WRITE, DefaultHoodieRecordPayload.class),
+ Arguments.of(MERGE_ON_READ, OverwriteWithLatestAvroPayload.class),
+ Arguments.of(MERGE_ON_READ, OverwriteNonDefaultsWithLatestAvroPayload.class),
+ Arguments.of(MERGE_ON_READ, PartialUpdateAvroPayload.class),
+ Arguments.of(MERGE_ON_READ, DefaultHoodieRecordPayload.class)
+ );
+ }
@ParameterizedTest
- @EnumSource(HoodieTableType.class)
- public void testReadLatestRecordsWithDeletes(HoodieTableType tableType) throws IOException {
- HoodieWriteConfig writeConfig = getWriteConfig();
+ @MethodSource("avroPayloadClasses")
+ public void testReadLatestRecordsWithDeletes(HoodieTableType tableType, Class<?> payloadClass) throws IOException {
+ HoodieWriteConfig writeConfig = getWriteConfig(payloadClass);
HoodieTableMetaClient metaClient = getHoodieMetaClient(tableType, writeConfig.getProps());
try (SparkRDDWriteClient client = getHoodieWriteClient(writeConfig)) {
final int totalRecords = 4;
+ final String partition = "foo";
+
// 1st batch: inserts
String commitTimeAtEpoch0 = getCommitTimeAtUTC(0);
- List<HoodieRecord> insertsAtEpoch0 = convertPayload(dataGen
- .generateInsertsForPartition(commitTimeAtEpoch0, totalRecords, DEFAULT_FIRST_PARTITION_PATH), DefaultHoodieRecordPayload.class);
+ List<HoodieRecord> insertsAtEpoch0 = getInserts(totalRecords, partition, 0, payloadClass);
client.startCommitWithTime(commitTimeAtEpoch0);
client.upsert(jsc().parallelize(insertsAtEpoch0, 1), commitTimeAtEpoch0);
- validate(metaClient, writeConfig, totalRecords, commitTimeAtEpoch0, DEFAULT_FIRST_PARTITION_PATH, 0);
+ doMergedReadAndValidate(metaClient, writeConfig, totalRecords, partition, 0, payloadClass);
// 2nd batch: normal updates
String commitTimeAtEpoch5 = getCommitTimeAtUTC(5);
- List<HoodieRecord> updatesAtEpoch5 = convertPayload(dataGen
- .generateUpdatesWithTimestamp(commitTimeAtEpoch5, insertsAtEpoch0, 5), DefaultHoodieRecordPayload.class);
+ List<HoodieRecord> updatesAtEpoch5 = getUpdates(insertsAtEpoch0, 5, payloadClass);
client.startCommitWithTime(commitTimeAtEpoch5);
- client.upsert(jsc().parallelize(updatesAtEpoch5, 1), commitTimeAtEpoch5);
- validate(metaClient, writeConfig, totalRecords, commitTimeAtEpoch5, DEFAULT_FIRST_PARTITION_PATH, 5);
+ JavaRDD<WriteStatus> writeStatusesAtEpoch5 = client.upsert(jsc().parallelize(updatesAtEpoch5, 1), commitTimeAtEpoch5);
+ assertNoWriteErrors(writeStatusesAtEpoch5.collect());
+ doMergedReadAndValidate(metaClient, writeConfig, totalRecords, partition, 5, payloadClass);
- // 3rd batch: delete a record
+ // 3rd batch: delete the record with id 3 (the last one)
String commitTimeAtEpoch6 = getCommitTimeAtUTC(6);
client.startCommitWithTime(commitTimeAtEpoch6);
- List<HoodieRecord> deletesAtEpoch6 = convertPayload(dataGen
- .generateUpdatesWithTimestamp(commitTimeAtEpoch6, Collections.singletonList(insertsAtEpoch0.get(0)), 6), DefaultHoodieRecordPayload.class, true);
- client.upsert(jsc().parallelize(deletesAtEpoch6, 1), commitTimeAtEpoch6);
- validate(metaClient, writeConfig, totalRecords - 1, commitTimeAtEpoch5, DEFAULT_FIRST_PARTITION_PATH, 5);
+ List<HoodieRecord> deletesAtEpoch6 = getDeletes(updatesAtEpoch5.subList(totalRecords - 1, totalRecords), 6, payloadClass);
+ JavaRDD<WriteStatus> writeStatusesAtEpoch6 = client.upsert(jsc().parallelize(deletesAtEpoch6, 1), commitTimeAtEpoch6);
+ assertNoWriteErrors(writeStatusesAtEpoch6.collect());
+ doMergedReadAndValidate(metaClient, writeConfig, totalRecords - 1, partition, 5, payloadClass);
// 4th batch: normal updates
String commitTimeAtEpoch9 = getCommitTimeAtUTC(9);
- List<HoodieRecord> updatesAtEpoch9 = convertPayload(dataGen
- .generateUpdatesWithTimestamp(commitTimeAtEpoch9, insertsAtEpoch0, 9), DefaultHoodieRecordPayload.class);
+ List<HoodieRecord> updatesAtEpoch9 = getUpdates(updatesAtEpoch5, 9, payloadClass);
client.startCommitWithTime(commitTimeAtEpoch9);
client.upsert(jsc().parallelize(updatesAtEpoch9, 1), commitTimeAtEpoch9);
- validate(metaClient, writeConfig, totalRecords, commitTimeAtEpoch9, DEFAULT_FIRST_PARTITION_PATH, 9);
-
+ doMergedReadAndValidate(metaClient, writeConfig, totalRecords, partition, 9, payloadClass);
}
}
+ private static Stream<Arguments> avroPayloadClassesThatHonorOrdering() {
+ return Stream.of(
+ Arguments.of(COPY_ON_WRITE, PartialUpdateAvroPayload.class),
+ Arguments.of(COPY_ON_WRITE, DefaultHoodieRecordPayload.class),
+ Arguments.of(MERGE_ON_READ, PartialUpdateAvroPayload.class),
+ Arguments.of(MERGE_ON_READ, DefaultHoodieRecordPayload.class)
Review Comment:
ditto
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] hudi-bot commented on pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "hudi-bot (via GitHub)" <gi...@apache.org>.
hudi-bot commented on PR #8675:
URL: https://github.com/apache/hudi/pull/8675#issuecomment-1543560233
<!--
Meta data
{
"version" : 1,
"metaDataEntries" : [ {
"hash" : "eb510e9ae89ac152e29375c44becfadd02506674",
"status" : "UNKNOWN",
"url" : "TBD",
"triggerID" : "eb510e9ae89ac152e29375c44becfadd02506674",
"triggerType" : "PUSH"
}, {
"hash" : "e18fd60e894a76e386afb5d5b7cca5ae02c28c02",
"status" : "DELETED",
"url" : "https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16977",
"triggerID" : "e18fd60e894a76e386afb5d5b7cca5ae02c28c02",
"triggerType" : "PUSH"
}, {
"hash" : "f1376bc500e0b86fe595dbfa207d5bd77b8ac5ab",
"status" : "UNKNOWN",
"url" : "TBD",
"triggerID" : "f1376bc500e0b86fe595dbfa207d5bd77b8ac5ab",
"triggerType" : "PUSH"
}, {
"hash" : "fd1a22a9c708bf20c05bc4455121a6ba108b5869",
"status" : "DELETED",
"url" : "https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=16997",
"triggerID" : "fd1a22a9c708bf20c05bc4455121a6ba108b5869",
"triggerType" : "PUSH"
}, {
"hash" : "875f77fd40a5b93dd7fcfa628e981f575372d6e7",
"status" : "SUCCESS",
"url" : "https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=17013",
"triggerID" : "875f77fd40a5b93dd7fcfa628e981f575372d6e7",
"triggerType" : "PUSH"
} ]
}-->
## CI report:
* eb510e9ae89ac152e29375c44becfadd02506674 UNKNOWN
* f1376bc500e0b86fe595dbfa207d5bd77b8ac5ab UNKNOWN
* 875f77fd40a5b93dd7fcfa628e981f575372d6e7 Azure: [SUCCESS](https://dev.azure.com/apache-hudi-ci-org/785b6ef4-2f42-4a89-8f0e-5f0d7039a0cc/_build/results?buildId=17013)
<details>
<summary>Bot commands</summary>
@hudi-bot supports the following commands:
- `@hudi-bot run azure` re-run the last Azure build
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] hudi-bot commented on pull request #8675: [HUDI-6195] Test-cover different payload classes when use HoodieMergedReadHandle
Posted by "hudi-bot (via GitHub)" <gi...@apache.org>.
hudi-bot commented on PR #8675:
URL: https://github.com/apache/hudi/pull/8675#issuecomment-1540121548
<!--
Meta data
{
"version" : 1,
"metaDataEntries" : [ {
"hash" : "eb510e9ae89ac152e29375c44becfadd02506674",
"status" : "UNKNOWN",
"url" : "TBD",
"triggerID" : "eb510e9ae89ac152e29375c44becfadd02506674",
"triggerType" : "PUSH"
}, {
"hash" : "e18fd60e894a76e386afb5d5b7cca5ae02c28c02",
"status" : "UNKNOWN",
"url" : "TBD",
"triggerID" : "e18fd60e894a76e386afb5d5b7cca5ae02c28c02",
"triggerType" : "PUSH"
} ]
}-->
## CI report:
* eb510e9ae89ac152e29375c44becfadd02506674 UNKNOWN
* e18fd60e894a76e386afb5d5b7cca5ae02c28c02 UNKNOWN
<details>
<summary>Bot commands</summary>
@hudi-bot supports the following commands:
- `@hudi-bot run azure` re-run the last Azure build
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@hudi.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org