You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hudi.apache.org by GitBox <gi...@apache.org> on 2020/09/28 16:38:36 UTC
[GitHub] [hudi] lw309637554 opened a new pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
lw309637554 opened a new pull request #2127:
URL: https://github.com/apache/hudi/pull/2127
## *Tips*
- *Thank you very much for contributing to Apache Hudi.*
- *Please review https://hudi.apache.org/contributing.html before opening a pull request.*
## What is the purpose of the pull request
* add more test for schema evolution failed. future we can resolve some of the scenario.
## Brief change log
*(for example:)*
- *Modify AnnotationLocation checkstyle rule in checkstyle.xml*
## Verify this pull request
*(Please pick either of the following options)*
This pull request is a trivial rework / code cleanup without any test coverage.
*(or)*
This pull request is already covered by existing tests, such as *(please describe tests)*.
(or)
This change added tests and can be verified as follows:
*(example:)*
- *Added integration tests for end-to-end.*
- *Added HoodieClientWriteTest to verify the change.*
- *Manually verified the change by running a job locally.*
## Committer checklist
- [ ] Has a corresponding JIRA in PR title & commit
- [ ] Commit message is descriptive of the change
- [ ] CI is green
- [ ] Necessary doc changes done or have another open PR
- [ ] For large changes, please consider breaking it into sub-tasks under an umbrella JIRA.
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] lw309637554 commented on a change in pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
lw309637554 commented on a change in pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#discussion_r499165943
##########
File path: hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/client/TestUpdateSchemaEvolution.java
##########
@@ -68,61 +71,62 @@ public void tearDown() throws IOException {
cleanupResources();
}
- @Test
- public void testSchemaEvolutionOnUpdate() throws Exception {
+ private WriteStatus prepareFirstCommitData(List<String> recordsStrs) throws IOException {
// Create a bunch of records with a old version of schema
final HoodieWriteConfig config = makeHoodieClientConfig("/exampleSchema.txt");
final HoodieSparkTable table = HoodieSparkTable.create(config, context);
-
final List<WriteStatus> statuses = jsc.parallelize(Arrays.asList(1)).map(x -> {
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
- String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
- String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
List<HoodieRecord> insertRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1));
- RawTripTestPayload rowChange2 = new RawTripTestPayload(recordStr2);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange2.getRowKey(), rowChange2.getPartitionPath()), rowChange2));
- RawTripTestPayload rowChange3 = new RawTripTestPayload(recordStr3);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange3.getRowKey(), rowChange3.getPartitionPath()), rowChange3));
-
+ for (String recordStr : recordsStrs) {
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ insertRecords
+ .add(new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange));
+ }
Map<String, HoodieRecord> insertRecordMap = insertRecords.stream()
.collect(Collectors.toMap(r -> r.getRecordKey(), Function.identity()));
HoodieCreateHandle createHandle =
- new HoodieCreateHandle(config, "100", table, rowChange1.getPartitionPath(), "f1-0", insertRecordMap, supplier);
+ new HoodieCreateHandle(config, "100", table, insertRecords.get(0).getPartitionPath(), "f1-0", insertRecordMap, supplier);
createHandle.write();
return createHandle.close();
}).collect();
final Path commitFile = new Path(config.getBasePath() + "/.hoodie/" + HoodieTimeline.makeCommitFileName("100"));
FSUtils.getFs(basePath, HoodieTestUtils.getDefaultHadoopConf()).create(commitFile);
+ return statuses.get(0);
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateSuccessWithAddColumnHaveDefault() throws Exception {
+ List<String> recordsStrs = new ArrayList<>();
+ String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
+ String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
+ String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
+ recordsStrs.add(recordStr1);
+ recordsStrs.add(recordStr2);
+ recordsStrs.add(recordStr3);
// Now try an update with an evolved schema
// Evolved schema does not have guarantee on preserving the original field ordering
final HoodieWriteConfig config2 = makeHoodieClientConfig("/exampleEvolvedSchema.txt");
- final WriteStatus insertResult = statuses.get(0);
+ final WriteStatus insertResult = prepareFirstCommitData(recordsStrs);
String fileId = insertResult.getFileId();
- final HoodieSparkTable table2 = HoodieSparkTable.create(config, context);
+ final HoodieSparkTable table2 = HoodieSparkTable.create(config2, context);
assertEquals(1, jsc.parallelize(Arrays.asList(1)).map(x -> {
Review comment:
can not removing jsc.parallelize() and just retain the lambda block.
because HoodieMergeHandle need the param supplier. supplier implement need
" return () -> TaskContext.get().stageId();"
so jsc.parallelize can init the TaskContext. if we mock supplier, will bring "Task not serializable".
so i will remove assertEquals, but remain jsc.parallelize just like TestCopyOnWriteActionExecutor
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] pratyakshsharma commented on a change in pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
pratyakshsharma commented on a change in pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#discussion_r504234269
##########
File path: hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/client/TestUpdateSchemaEvolution.java
##########
@@ -68,77 +71,158 @@ public void tearDown() throws IOException {
cleanupResources();
}
- @Test
- public void testSchemaEvolutionOnUpdate() throws Exception {
+ private WriteStatus prepareFirstRecordCommit(List<String> recordsStrs) throws IOException {
// Create a bunch of records with a old version of schema
final HoodieWriteConfig config = makeHoodieClientConfig("/exampleSchema.txt");
final HoodieSparkTable table = HoodieSparkTable.create(config, context);
-
final List<WriteStatus> statuses = jsc.parallelize(Arrays.asList(1)).map(x -> {
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
- String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
- String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
List<HoodieRecord> insertRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1));
- RawTripTestPayload rowChange2 = new RawTripTestPayload(recordStr2);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange2.getRowKey(), rowChange2.getPartitionPath()), rowChange2));
- RawTripTestPayload rowChange3 = new RawTripTestPayload(recordStr3);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange3.getRowKey(), rowChange3.getPartitionPath()), rowChange3));
-
+ for (String recordStr : recordsStrs) {
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ insertRecords
+ .add(new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange));
+ }
Map<String, HoodieRecord> insertRecordMap = insertRecords.stream()
.collect(Collectors.toMap(r -> r.getRecordKey(), Function.identity()));
HoodieCreateHandle createHandle =
- new HoodieCreateHandle(config, "100", table, rowChange1.getPartitionPath(), "f1-0", insertRecordMap, supplier);
+ new HoodieCreateHandle(config, "100", table, insertRecords.get(0).getPartitionPath(), "f1-0", insertRecordMap, supplier);
createHandle.write();
return createHandle.close();
}).collect();
final Path commitFile = new Path(config.getBasePath() + "/.hoodie/" + HoodieTimeline.makeCommitFileName("100"));
FSUtils.getFs(basePath, HoodieTestUtils.getDefaultHadoopConf()).create(commitFile);
+ return statuses.get(0);
+ }
- // Now try an update with an evolved schema
- // Evolved schema does not have guarantee on preserving the original field ordering
- final HoodieWriteConfig config2 = makeHoodieClientConfig("/exampleEvolvedSchema.txt");
- final WriteStatus insertResult = statuses.get(0);
- String fileId = insertResult.getFileId();
-
- final HoodieSparkTable table2 = HoodieSparkTable.create(config, context);
- assertEquals(1, jsc.parallelize(Arrays.asList(1)).map(x -> {
- // New content with values for the newly added field
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12,\"added_field\":1}";
- List<HoodieRecord> updateRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- HoodieRecord record1 =
- new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1);
- record1.unseal();
- record1.setCurrentLocation(new HoodieRecordLocation("100", fileId));
- record1.seal();
- updateRecords.add(record1);
-
- assertDoesNotThrow(() -> {
- HoodieMergeHandle mergeHandle = new HoodieMergeHandle(config2, "101", table2,
- updateRecords.iterator(), record1.getPartitionPath(), fileId, supplier);
- Configuration conf = new Configuration();
- AvroReadSupport.setAvroReadSchema(conf, mergeHandle.getWriterSchemaWithMetafields());
- List<GenericRecord> oldRecords = ParquetUtils.readAvroRecords(conf,
- new Path(config2.getBasePath() + "/" + insertResult.getStat().getPath()));
+ private List<String> generateMultiRecordsForExampleSchema() {
+ List<String> recordsStrs = new ArrayList<>();
+ String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
+ String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
+ String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
+ recordsStrs.add(recordStr1);
+ recordsStrs.add(recordStr2);
+ recordsStrs.add(recordStr3);
+ return recordsStrs;
+ }
+
+ private List<String> generateOneRecordForExampleSchema() {
+ List<String> recordsStrs = new ArrayList<>();
+ String recordStr = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
+ recordsStrs.add(recordStr);
+ return recordsStrs;
+ }
+
+ private void assertSchemaEvolutionOnUpdateResult(WriteStatus insertResult, HoodieSparkTable updateTable,
+ List<HoodieRecord> updateRecords, String assertMsg, boolean isAssertThrow, Class expectedExceptionType) {
+ jsc.parallelize(Arrays.asList(1)).map(x -> {
+ Executable executable = () -> {
+ HoodieMergeHandle mergeHandle = new HoodieMergeHandle(updateTable.getConfig(), "101", updateTable,
+ updateRecords.iterator(), updateRecords.get(0).getPartitionPath(), insertResult.getFileId(), supplier);
+ AvroReadSupport.setAvroReadSchema(updateTable.getHadoopConf(), mergeHandle.getWriterSchemaWithMetafields());
+ List<GenericRecord> oldRecords = ParquetUtils.readAvroRecords(updateTable.getHadoopConf(),
+ new Path(updateTable.getConfig().getBasePath() + "/" + insertResult.getStat().getPath()));
for (GenericRecord rec : oldRecords) {
mergeHandle.write(rec);
}
mergeHandle.close();
- }, "UpdateFunction could not read records written with exampleSchema.txt using the "
- + "exampleEvolvedSchema.txt");
-
+ };
+ if (isAssertThrow) {
+ assertThrows(expectedExceptionType, executable, assertMsg);
+ } else {
+ assertDoesNotThrow(executable, assertMsg);
+ }
return 1;
- }).collect().size());
+ }).collect();
+ }
+
+ private List<HoodieRecord> buildUpdateRecords(String recordStr, String insertFileId) throws IOException {
+ List<HoodieRecord> updateRecords = new ArrayList<>();
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ HoodieRecord record =
+ new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange);
+ record.setCurrentLocation(new HoodieRecordLocation("101", insertFileId));
+ record.seal();
+ updateRecords.add(record);
+ return updateRecords;
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateSuccessWithAddColumnHaveDefault() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateMultiRecordsForExampleSchema());
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchema.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ // New content with values for the newly added field
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12,\"added_field\":1}";
+ List<HoodieRecord> updateRecords = buildUpdateRecords(recordStr, insertResult.getFileId());
+ String assertMsg = "UpdateFunction could not read records written with exampleSchema.txt using the "
+ + "exampleEvolvedSchema.txt";
+ assertSchemaEvolutionOnUpdateResult(insertResult, table, updateRecords, assertMsg, false, null);
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateSuccessWithChangeColumnOrder() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateMultiRecordsForExampleSchema());
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaChangeOrder.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"added_field\":1},\"number\":12";
+ List<HoodieRecord> updateRecords = buildUpdateRecords(recordStr, insertResult.getFileId());
+ String assertMsg = "UpdateFunction could not read records written with exampleSchema.txt using the "
+ + "exampleEvolvedSchemaChangeOrder.txt as column order change";
+ assertSchemaEvolutionOnUpdateResult(insertResult, table, updateRecords, assertMsg, false, null);
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateMisMatchWithDeleteColumn() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateOneRecordForExampleSchema());
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaDeleteColumn.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\"}";
+ List<HoodieRecord> updateRecords = buildUpdateRecords(recordStr, insertResult.getFileId());
+ String assertMsg = "UpdateFunction when delete column ,Parquet/Avro schema mismatch: Avro field 'xxx' not found";
+ assertSchemaEvolutionOnUpdateResult(insertResult, table, updateRecords, assertMsg, true, InvalidRecordException.class);
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateMisMatchWithAddColumnNotHaveDefault() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateOneRecordForExampleSchema());
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaColumnRequire.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12,\"added_field\":1}";
+ List<HoodieRecord> updateRecords = buildUpdateRecords(recordStr, insertResult.getFileId());
+ String assertMsg = "UpdateFunction could not read records written with exampleSchema.txt using the "
+ + "exampleEvolvedSchemaColumnRequire.txt ,because oldrecords do not have required column added_field";
Review comment:
exampleEvolvedSchemaColumnRequire.txt ,because -> exampleEvolvedSchemaColumnRequire.txt, because
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] lw309637554 commented on pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
lw309637554 commented on pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#issuecomment-712536085
> @lw309637554 looks like comments from @pratyakshsharma were addressed. sorry about the delay. merging now. Thank you @lw309637554 for adding the cases!
Thanks
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] xushiyan commented on a change in pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
xushiyan commented on a change in pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#discussion_r499154318
##########
File path: hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/client/TestUpdateSchemaEvolution.java
##########
@@ -68,61 +71,62 @@ public void tearDown() throws IOException {
cleanupResources();
}
- @Test
- public void testSchemaEvolutionOnUpdate() throws Exception {
+ private WriteStatus prepareFirstCommitData(List<String> recordsStrs) throws IOException {
// Create a bunch of records with a old version of schema
final HoodieWriteConfig config = makeHoodieClientConfig("/exampleSchema.txt");
final HoodieSparkTable table = HoodieSparkTable.create(config, context);
-
final List<WriteStatus> statuses = jsc.parallelize(Arrays.asList(1)).map(x -> {
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
- String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
- String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
List<HoodieRecord> insertRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1));
- RawTripTestPayload rowChange2 = new RawTripTestPayload(recordStr2);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange2.getRowKey(), rowChange2.getPartitionPath()), rowChange2));
- RawTripTestPayload rowChange3 = new RawTripTestPayload(recordStr3);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange3.getRowKey(), rowChange3.getPartitionPath()), rowChange3));
-
+ for (String recordStr : recordsStrs) {
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ insertRecords
+ .add(new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange));
+ }
Map<String, HoodieRecord> insertRecordMap = insertRecords.stream()
.collect(Collectors.toMap(r -> r.getRecordKey(), Function.identity()));
HoodieCreateHandle createHandle =
- new HoodieCreateHandle(config, "100", table, rowChange1.getPartitionPath(), "f1-0", insertRecordMap, supplier);
+ new HoodieCreateHandle(config, "100", table, insertRecords.get(0).getPartitionPath(), "f1-0", insertRecordMap, supplier);
createHandle.write();
return createHandle.close();
}).collect();
final Path commitFile = new Path(config.getBasePath() + "/.hoodie/" + HoodieTimeline.makeCommitFileName("100"));
FSUtils.getFs(basePath, HoodieTestUtils.getDefaultHadoopConf()).create(commitFile);
+ return statuses.get(0);
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateSuccessWithAddColumnHaveDefault() throws Exception {
+ List<String> recordsStrs = new ArrayList<>();
+ String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
+ String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
+ String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
+ recordsStrs.add(recordStr1);
+ recordsStrs.add(recordStr2);
+ recordsStrs.add(recordStr3);
Review comment:
these 3 local vars could be removed
##########
File path: hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/client/TestUpdateSchemaEvolution.java
##########
@@ -68,61 +71,62 @@ public void tearDown() throws IOException {
cleanupResources();
}
- @Test
- public void testSchemaEvolutionOnUpdate() throws Exception {
+ private WriteStatus prepareFirstCommitData(List<String> recordsStrs) throws IOException {
// Create a bunch of records with a old version of schema
final HoodieWriteConfig config = makeHoodieClientConfig("/exampleSchema.txt");
final HoodieSparkTable table = HoodieSparkTable.create(config, context);
-
final List<WriteStatus> statuses = jsc.parallelize(Arrays.asList(1)).map(x -> {
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
- String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
- String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
List<HoodieRecord> insertRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1));
- RawTripTestPayload rowChange2 = new RawTripTestPayload(recordStr2);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange2.getRowKey(), rowChange2.getPartitionPath()), rowChange2));
- RawTripTestPayload rowChange3 = new RawTripTestPayload(recordStr3);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange3.getRowKey(), rowChange3.getPartitionPath()), rowChange3));
-
+ for (String recordStr : recordsStrs) {
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ insertRecords
+ .add(new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange));
+ }
Map<String, HoodieRecord> insertRecordMap = insertRecords.stream()
.collect(Collectors.toMap(r -> r.getRecordKey(), Function.identity()));
HoodieCreateHandle createHandle =
- new HoodieCreateHandle(config, "100", table, rowChange1.getPartitionPath(), "f1-0", insertRecordMap, supplier);
+ new HoodieCreateHandle(config, "100", table, insertRecords.get(0).getPartitionPath(), "f1-0", insertRecordMap, supplier);
createHandle.write();
return createHandle.close();
}).collect();
final Path commitFile = new Path(config.getBasePath() + "/.hoodie/" + HoodieTimeline.makeCommitFileName("100"));
FSUtils.getFs(basePath, HoodieTestUtils.getDefaultHadoopConf()).create(commitFile);
+ return statuses.get(0);
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateSuccessWithAddColumnHaveDefault() throws Exception {
+ List<String> recordsStrs = new ArrayList<>();
+ String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
+ String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
+ String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
+ recordsStrs.add(recordStr1);
+ recordsStrs.add(recordStr2);
+ recordsStrs.add(recordStr3);
// Now try an update with an evolved schema
// Evolved schema does not have guarantee on preserving the original field ordering
final HoodieWriteConfig config2 = makeHoodieClientConfig("/exampleEvolvedSchema.txt");
- final WriteStatus insertResult = statuses.get(0);
+ final WriteStatus insertResult = prepareFirstCommitData(recordsStrs);
String fileId = insertResult.getFileId();
- final HoodieSparkTable table2 = HoodieSparkTable.create(config, context);
+ final HoodieSparkTable table2 = HoodieSparkTable.create(config2, context);
Review comment:
could we call them table and config instead of table2 and config2? since the method is split and they are the only vars left.
##########
File path: hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/client/TestUpdateSchemaEvolution.java
##########
@@ -68,61 +71,62 @@ public void tearDown() throws IOException {
cleanupResources();
}
- @Test
- public void testSchemaEvolutionOnUpdate() throws Exception {
+ private WriteStatus prepareFirstCommitData(List<String> recordsStrs) throws IOException {
Review comment:
to avoid ambiguity, could we call this `prepareFirstRecordCommit()`?
##########
File path: hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/client/TestUpdateSchemaEvolution.java
##########
@@ -68,61 +71,62 @@ public void tearDown() throws IOException {
cleanupResources();
}
- @Test
- public void testSchemaEvolutionOnUpdate() throws Exception {
+ private WriteStatus prepareFirstCommitData(List<String> recordsStrs) throws IOException {
// Create a bunch of records with a old version of schema
final HoodieWriteConfig config = makeHoodieClientConfig("/exampleSchema.txt");
final HoodieSparkTable table = HoodieSparkTable.create(config, context);
-
final List<WriteStatus> statuses = jsc.parallelize(Arrays.asList(1)).map(x -> {
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
- String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
- String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
List<HoodieRecord> insertRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1));
- RawTripTestPayload rowChange2 = new RawTripTestPayload(recordStr2);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange2.getRowKey(), rowChange2.getPartitionPath()), rowChange2));
- RawTripTestPayload rowChange3 = new RawTripTestPayload(recordStr3);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange3.getRowKey(), rowChange3.getPartitionPath()), rowChange3));
-
+ for (String recordStr : recordsStrs) {
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ insertRecords
+ .add(new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange));
+ }
Map<String, HoodieRecord> insertRecordMap = insertRecords.stream()
.collect(Collectors.toMap(r -> r.getRecordKey(), Function.identity()));
HoodieCreateHandle createHandle =
- new HoodieCreateHandle(config, "100", table, rowChange1.getPartitionPath(), "f1-0", insertRecordMap, supplier);
+ new HoodieCreateHandle(config, "100", table, insertRecords.get(0).getPartitionPath(), "f1-0", insertRecordMap, supplier);
createHandle.write();
return createHandle.close();
}).collect();
final Path commitFile = new Path(config.getBasePath() + "/.hoodie/" + HoodieTimeline.makeCommitFileName("100"));
FSUtils.getFs(basePath, HoodieTestUtils.getDefaultHadoopConf()).create(commitFile);
+ return statuses.get(0);
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateSuccessWithAddColumnHaveDefault() throws Exception {
+ List<String> recordsStrs = new ArrayList<>();
+ String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
+ String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
+ String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
+ recordsStrs.add(recordStr1);
+ recordsStrs.add(recordStr2);
+ recordsStrs.add(recordStr3);
// Now try an update with an evolved schema
// Evolved schema does not have guarantee on preserving the original field ordering
final HoodieWriteConfig config2 = makeHoodieClientConfig("/exampleEvolvedSchema.txt");
- final WriteStatus insertResult = statuses.get(0);
+ final WriteStatus insertResult = prepareFirstCommitData(recordsStrs);
String fileId = insertResult.getFileId();
- final HoodieSparkTable table2 = HoodieSparkTable.create(config, context);
+ final HoodieSparkTable table2 = HoodieSparkTable.create(config2, context);
assertEquals(1, jsc.parallelize(Arrays.asList(1)).map(x -> {
Review comment:
seeing this is original code. i don't see why it needs to assert 1 equals to 1 returned eventually. could we simplify this by removing `jsc.parallelize()` and just retain the lambda block?
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] xushiyan merged pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
xushiyan merged pull request #2127:
URL: https://github.com/apache/hudi/pull/2127
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] xushiyan commented on a change in pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
xushiyan commented on a change in pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#discussion_r499304034
##########
File path: hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/client/TestUpdateSchemaEvolution.java
##########
@@ -68,77 +71,232 @@ public void tearDown() throws IOException {
cleanupResources();
}
- @Test
- public void testSchemaEvolutionOnUpdate() throws Exception {
+ private WriteStatus prepareFirstRecordCommit(List<String> recordsStrs) throws IOException {
// Create a bunch of records with a old version of schema
final HoodieWriteConfig config = makeHoodieClientConfig("/exampleSchema.txt");
final HoodieSparkTable table = HoodieSparkTable.create(config, context);
-
final List<WriteStatus> statuses = jsc.parallelize(Arrays.asList(1)).map(x -> {
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
- String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
- String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
List<HoodieRecord> insertRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1));
- RawTripTestPayload rowChange2 = new RawTripTestPayload(recordStr2);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange2.getRowKey(), rowChange2.getPartitionPath()), rowChange2));
- RawTripTestPayload rowChange3 = new RawTripTestPayload(recordStr3);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange3.getRowKey(), rowChange3.getPartitionPath()), rowChange3));
-
+ for (String recordStr : recordsStrs) {
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ insertRecords
+ .add(new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange));
+ }
Map<String, HoodieRecord> insertRecordMap = insertRecords.stream()
.collect(Collectors.toMap(r -> r.getRecordKey(), Function.identity()));
HoodieCreateHandle createHandle =
- new HoodieCreateHandle(config, "100", table, rowChange1.getPartitionPath(), "f1-0", insertRecordMap, supplier);
+ new HoodieCreateHandle(config, "100", table, insertRecords.get(0).getPartitionPath(), "f1-0", insertRecordMap, supplier);
createHandle.write();
return createHandle.close();
}).collect();
final Path commitFile = new Path(config.getBasePath() + "/.hoodie/" + HoodieTimeline.makeCommitFileName("100"));
FSUtils.getFs(basePath, HoodieTestUtils.getDefaultHadoopConf()).create(commitFile);
+ return statuses.get(0);
+ }
- // Now try an update with an evolved schema
- // Evolved schema does not have guarantee on preserving the original field ordering
- final HoodieWriteConfig config2 = makeHoodieClientConfig("/exampleEvolvedSchema.txt");
- final WriteStatus insertResult = statuses.get(0);
+ private List<String> generateMultiRecordsForExampleSchema() {
+ List<String> recordsStrs = new ArrayList<>();
+ String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
+ String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
+ String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
+ recordsStrs.add(recordStr1);
+ recordsStrs.add(recordStr2);
+ recordsStrs.add(recordStr3);
+ return recordsStrs;
+ }
+
+ private List<String> generateOneRecordForExampleSchema() {
+ List<String> recordsStrs = new ArrayList<>();
+ String recordStr = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
+ recordsStrs.add(recordStr);
+ return recordsStrs;
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateSuccessWithAddColumnHaveDefault() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateMultiRecordsForExampleSchema());
String fileId = insertResult.getFileId();
- final HoodieSparkTable table2 = HoodieSparkTable.create(config, context);
- assertEquals(1, jsc.parallelize(Arrays.asList(1)).map(x -> {
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchema.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ jsc.parallelize(Arrays.asList(1)).map(x -> {
// New content with values for the newly added field
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12,\"added_field\":1}";
List<HoodieRecord> updateRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- HoodieRecord record1 =
- new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1);
- record1.unseal();
- record1.setCurrentLocation(new HoodieRecordLocation("100", fileId));
- record1.seal();
- updateRecords.add(record1);
-
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ HoodieRecord record =
+ new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange);
+ record.unseal();
+ record.setCurrentLocation(new HoodieRecordLocation("101", fileId));
+ record.seal();
+ updateRecords.add(record);
assertDoesNotThrow(() -> {
- HoodieMergeHandle mergeHandle = new HoodieMergeHandle(config2, "101", table2,
- updateRecords.iterator(), record1.getPartitionPath(), fileId, supplier);
+ HoodieMergeHandle mergeHandle = new HoodieMergeHandle(config, "101", table,
+ updateRecords.iterator(), record.getPartitionPath(), fileId, supplier);
Configuration conf = new Configuration();
AvroReadSupport.setAvroReadSchema(conf, mergeHandle.getWriterSchemaWithMetafields());
List<GenericRecord> oldRecords = ParquetUtils.readAvroRecords(conf,
- new Path(config2.getBasePath() + "/" + insertResult.getStat().getPath()));
+ new Path(config.getBasePath() + "/" + insertResult.getStat().getPath()));
for (GenericRecord rec : oldRecords) {
mergeHandle.write(rec);
}
mergeHandle.close();
}, "UpdateFunction could not read records written with exampleSchema.txt using the "
+ "exampleEvolvedSchema.txt");
+ return 1;
+ }).collect();
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateSuccessWithChangeColumnOrder() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateMultiRecordsForExampleSchema());
+ String fileId = insertResult.getFileId();
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaChangeOrder.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ jsc.parallelize(Arrays.asList(1)).map(x -> {
+ // New content with values for the newly added field
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"added_field\":1},\"number\":12";
+ List<HoodieRecord> updateRecords = new ArrayList<>();
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ HoodieRecord record =
+ new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange);
+ record.unseal();
+ record.setCurrentLocation(new HoodieRecordLocation("101", fileId));
+ record.seal();
+ updateRecords.add(record);
+ assertDoesNotThrow(() -> {
+ HoodieMergeHandle mergeHandle = new HoodieMergeHandle(config, "101", table,
+ updateRecords.iterator(), record.getPartitionPath(), fileId, supplier);
+ Configuration conf = new Configuration();
+ AvroReadSupport.setAvroReadSchema(conf, mergeHandle.getWriterSchemaWithMetafields());
+ List<GenericRecord> oldRecords = ParquetUtils.readAvroRecords(conf,
+ new Path(config.getBasePath() + "/" + insertResult.getStat().getPath()));
+ for (GenericRecord rec : oldRecords) {
+ mergeHandle.write(rec);
+ }
+ mergeHandle.close();
+ }, "UpdateFunction could not read records written with exampleSchema.txt using the "
+ + "exampleEvolvedSchemaChangeOrder.txt as column order change");
return 1;
- }).collect().size());
+ }).collect();
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateMisMatchWithDeleteColumn() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateOneRecordForExampleSchema());
+ String fileId = insertResult.getFileId();
+
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaDeleteColumn.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ jsc.parallelize(Arrays.asList(1)).map(x -> {
+ // New content with values for the newly added field
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\"}";
+ List<HoodieRecord> updateRecords = new ArrayList<>();
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ HoodieRecord record =
+ new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange);
+ record.unseal();
+ record.setCurrentLocation(new HoodieRecordLocation("101", fileId));
+ record.seal();
+ updateRecords.add(record);
+ HoodieMergeHandle mergeHandle = new HoodieMergeHandle(config, "101", table,
+ updateRecords.iterator(), record.getPartitionPath(), fileId, supplier);
+ Configuration conf = new Configuration();
+ AvroReadSupport.setAvroReadSchema(conf, mergeHandle.getWriterSchemaWithMetafields());
+ assertThrows(InvalidRecordException.class, () -> {
+ List<GenericRecord> oldRecords = ParquetUtils.readAvroRecords(conf,
+ new Path(config.getBasePath() + "/" + insertResult.getStat().getPath()));
+ }, "UpdateFunction when delete column ,Parquet/Avro schema mismatch: Avro field 'xxx' not found");
+ mergeHandle.close();
+ return 1;
+ }).collect();
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateMisMatchWithAddColumnNotHaveDefault() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateOneRecordForExampleSchema());
+ String fileId = insertResult.getFileId();
+
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaColumnRequire.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ jsc.parallelize(Arrays.asList(1)).map(x -> {
+ // New content with values for the newly added field
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12,\"added_field\":1}";
+ List<HoodieRecord> updateRecords = new ArrayList<>();
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ HoodieRecord record =
+ new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange);
+ record.unseal();
+ record.setCurrentLocation(new HoodieRecordLocation("101", fileId));
+ record.seal();
+ updateRecords.add(record);
+ assertThrows(HoodieUpsertException.class, () -> {
+ HoodieMergeHandle mergeHandle = new HoodieMergeHandle(config, "101", table,
+ updateRecords.iterator(), record.getPartitionPath(), fileId, supplier);
+ Configuration conf = new Configuration();
+ AvroReadSupport.setAvroReadSchema(conf, mergeHandle.getWriterSchemaWithMetafields());
+ List<GenericRecord> oldRecords = ParquetUtils.readAvroRecords(conf,
+ new Path(config.getBasePath() + "/" + insertResult.getStat().getPath()));
+ for (GenericRecord rec : oldRecords) {
+ mergeHandle.write(rec);
+ }
+ mergeHandle.close();
+ }, "UpdateFunction could not read records written with exampleSchema.txt using the "
+ + "exampleEvolvedSchemaColumnRequire.txt ,because oldrecords do not have required column added_field");
+ return 1;
+ }).collect();
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateMisMatchWithChangeColumnType() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateOneRecordForExampleSchema());
+ String fileId = insertResult.getFileId();
+
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaColumnType.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ jsc.parallelize(Arrays.asList(1)).map(x -> {
Review comment:
```suggestion
jsc.parallelize(Arrays.asList(1)).foreach(x -> {
```
##########
File path: hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/client/TestUpdateSchemaEvolution.java
##########
@@ -68,77 +71,232 @@ public void tearDown() throws IOException {
cleanupResources();
}
- @Test
- public void testSchemaEvolutionOnUpdate() throws Exception {
+ private WriteStatus prepareFirstRecordCommit(List<String> recordsStrs) throws IOException {
// Create a bunch of records with a old version of schema
final HoodieWriteConfig config = makeHoodieClientConfig("/exampleSchema.txt");
final HoodieSparkTable table = HoodieSparkTable.create(config, context);
-
final List<WriteStatus> statuses = jsc.parallelize(Arrays.asList(1)).map(x -> {
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
- String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
- String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
List<HoodieRecord> insertRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1));
- RawTripTestPayload rowChange2 = new RawTripTestPayload(recordStr2);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange2.getRowKey(), rowChange2.getPartitionPath()), rowChange2));
- RawTripTestPayload rowChange3 = new RawTripTestPayload(recordStr3);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange3.getRowKey(), rowChange3.getPartitionPath()), rowChange3));
-
+ for (String recordStr : recordsStrs) {
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ insertRecords
+ .add(new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange));
+ }
Map<String, HoodieRecord> insertRecordMap = insertRecords.stream()
.collect(Collectors.toMap(r -> r.getRecordKey(), Function.identity()));
HoodieCreateHandle createHandle =
- new HoodieCreateHandle(config, "100", table, rowChange1.getPartitionPath(), "f1-0", insertRecordMap, supplier);
+ new HoodieCreateHandle(config, "100", table, insertRecords.get(0).getPartitionPath(), "f1-0", insertRecordMap, supplier);
createHandle.write();
return createHandle.close();
}).collect();
final Path commitFile = new Path(config.getBasePath() + "/.hoodie/" + HoodieTimeline.makeCommitFileName("100"));
FSUtils.getFs(basePath, HoodieTestUtils.getDefaultHadoopConf()).create(commitFile);
+ return statuses.get(0);
+ }
- // Now try an update with an evolved schema
- // Evolved schema does not have guarantee on preserving the original field ordering
- final HoodieWriteConfig config2 = makeHoodieClientConfig("/exampleEvolvedSchema.txt");
- final WriteStatus insertResult = statuses.get(0);
+ private List<String> generateMultiRecordsForExampleSchema() {
+ List<String> recordsStrs = new ArrayList<>();
+ String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
+ String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
+ String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
+ recordsStrs.add(recordStr1);
+ recordsStrs.add(recordStr2);
+ recordsStrs.add(recordStr3);
+ return recordsStrs;
+ }
+
+ private List<String> generateOneRecordForExampleSchema() {
+ List<String> recordsStrs = new ArrayList<>();
+ String recordStr = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
+ recordsStrs.add(recordStr);
+ return recordsStrs;
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateSuccessWithAddColumnHaveDefault() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateMultiRecordsForExampleSchema());
String fileId = insertResult.getFileId();
- final HoodieSparkTable table2 = HoodieSparkTable.create(config, context);
- assertEquals(1, jsc.parallelize(Arrays.asList(1)).map(x -> {
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchema.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ jsc.parallelize(Arrays.asList(1)).map(x -> {
// New content with values for the newly added field
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12,\"added_field\":1}";
List<HoodieRecord> updateRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- HoodieRecord record1 =
- new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1);
- record1.unseal();
- record1.setCurrentLocation(new HoodieRecordLocation("100", fileId));
- record1.seal();
- updateRecords.add(record1);
-
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ HoodieRecord record =
+ new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange);
+ record.unseal();
+ record.setCurrentLocation(new HoodieRecordLocation("101", fileId));
+ record.seal();
+ updateRecords.add(record);
assertDoesNotThrow(() -> {
- HoodieMergeHandle mergeHandle = new HoodieMergeHandle(config2, "101", table2,
- updateRecords.iterator(), record1.getPartitionPath(), fileId, supplier);
+ HoodieMergeHandle mergeHandle = new HoodieMergeHandle(config, "101", table,
+ updateRecords.iterator(), record.getPartitionPath(), fileId, supplier);
Configuration conf = new Configuration();
AvroReadSupport.setAvroReadSchema(conf, mergeHandle.getWriterSchemaWithMetafields());
List<GenericRecord> oldRecords = ParquetUtils.readAvroRecords(conf,
- new Path(config2.getBasePath() + "/" + insertResult.getStat().getPath()));
+ new Path(config.getBasePath() + "/" + insertResult.getStat().getPath()));
for (GenericRecord rec : oldRecords) {
mergeHandle.write(rec);
}
mergeHandle.close();
}, "UpdateFunction could not read records written with exampleSchema.txt using the "
+ "exampleEvolvedSchema.txt");
+ return 1;
+ }).collect();
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateSuccessWithChangeColumnOrder() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateMultiRecordsForExampleSchema());
+ String fileId = insertResult.getFileId();
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaChangeOrder.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ jsc.parallelize(Arrays.asList(1)).map(x -> {
+ // New content with values for the newly added field
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"added_field\":1},\"number\":12";
+ List<HoodieRecord> updateRecords = new ArrayList<>();
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ HoodieRecord record =
+ new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange);
+ record.unseal();
+ record.setCurrentLocation(new HoodieRecordLocation("101", fileId));
+ record.seal();
+ updateRecords.add(record);
+ assertDoesNotThrow(() -> {
+ HoodieMergeHandle mergeHandle = new HoodieMergeHandle(config, "101", table,
+ updateRecords.iterator(), record.getPartitionPath(), fileId, supplier);
+ Configuration conf = new Configuration();
+ AvroReadSupport.setAvroReadSchema(conf, mergeHandle.getWriterSchemaWithMetafields());
+ List<GenericRecord> oldRecords = ParquetUtils.readAvroRecords(conf,
+ new Path(config.getBasePath() + "/" + insertResult.getStat().getPath()));
+ for (GenericRecord rec : oldRecords) {
+ mergeHandle.write(rec);
+ }
+ mergeHandle.close();
+ }, "UpdateFunction could not read records written with exampleSchema.txt using the "
+ + "exampleEvolvedSchemaChangeOrder.txt as column order change");
return 1;
- }).collect().size());
+ }).collect();
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateMisMatchWithDeleteColumn() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateOneRecordForExampleSchema());
+ String fileId = insertResult.getFileId();
+
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaDeleteColumn.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ jsc.parallelize(Arrays.asList(1)).map(x -> {
+ // New content with values for the newly added field
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\"}";
+ List<HoodieRecord> updateRecords = new ArrayList<>();
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ HoodieRecord record =
+ new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange);
+ record.unseal();
+ record.setCurrentLocation(new HoodieRecordLocation("101", fileId));
+ record.seal();
+ updateRecords.add(record);
+ HoodieMergeHandle mergeHandle = new HoodieMergeHandle(config, "101", table,
+ updateRecords.iterator(), record.getPartitionPath(), fileId, supplier);
+ Configuration conf = new Configuration();
+ AvroReadSupport.setAvroReadSchema(conf, mergeHandle.getWriterSchemaWithMetafields());
+ assertThrows(InvalidRecordException.class, () -> {
+ List<GenericRecord> oldRecords = ParquetUtils.readAvroRecords(conf,
+ new Path(config.getBasePath() + "/" + insertResult.getStat().getPath()));
+ }, "UpdateFunction when delete column ,Parquet/Avro schema mismatch: Avro field 'xxx' not found");
+ mergeHandle.close();
+ return 1;
+ }).collect();
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateMisMatchWithAddColumnNotHaveDefault() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateOneRecordForExampleSchema());
+ String fileId = insertResult.getFileId();
+
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaColumnRequire.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ jsc.parallelize(Arrays.asList(1)).map(x -> {
+ // New content with values for the newly added field
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12,\"added_field\":1}";
+ List<HoodieRecord> updateRecords = new ArrayList<>();
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ HoodieRecord record =
+ new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange);
+ record.unseal();
+ record.setCurrentLocation(new HoodieRecordLocation("101", fileId));
+ record.seal();
+ updateRecords.add(record);
+ assertThrows(HoodieUpsertException.class, () -> {
+ HoodieMergeHandle mergeHandle = new HoodieMergeHandle(config, "101", table,
+ updateRecords.iterator(), record.getPartitionPath(), fileId, supplier);
+ Configuration conf = new Configuration();
+ AvroReadSupport.setAvroReadSchema(conf, mergeHandle.getWriterSchemaWithMetafields());
+ List<GenericRecord> oldRecords = ParquetUtils.readAvroRecords(conf,
+ new Path(config.getBasePath() + "/" + insertResult.getStat().getPath()));
+ for (GenericRecord rec : oldRecords) {
+ mergeHandle.write(rec);
+ }
+ mergeHandle.close();
+ }, "UpdateFunction could not read records written with exampleSchema.txt using the "
+ + "exampleEvolvedSchemaColumnRequire.txt ,because oldrecords do not have required column added_field");
+ return 1;
+ }).collect();
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateMisMatchWithChangeColumnType() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateOneRecordForExampleSchema());
+ String fileId = insertResult.getFileId();
+
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaColumnType.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ jsc.parallelize(Arrays.asList(1)).map(x -> {
+ // New content with values for the newly added field
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":\"12\"}";
+ List<HoodieRecord> updateRecords = new ArrayList<>();
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ HoodieRecord record =
+ new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange);
+ record.unseal();
Review comment:
Default sealed is false. we could skip unsealing.
##########
File path: hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/client/TestUpdateSchemaEvolution.java
##########
@@ -68,77 +71,232 @@ public void tearDown() throws IOException {
cleanupResources();
}
- @Test
- public void testSchemaEvolutionOnUpdate() throws Exception {
+ private WriteStatus prepareFirstRecordCommit(List<String> recordsStrs) throws IOException {
// Create a bunch of records with a old version of schema
final HoodieWriteConfig config = makeHoodieClientConfig("/exampleSchema.txt");
final HoodieSparkTable table = HoodieSparkTable.create(config, context);
-
final List<WriteStatus> statuses = jsc.parallelize(Arrays.asList(1)).map(x -> {
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
- String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
- String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
List<HoodieRecord> insertRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1));
- RawTripTestPayload rowChange2 = new RawTripTestPayload(recordStr2);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange2.getRowKey(), rowChange2.getPartitionPath()), rowChange2));
- RawTripTestPayload rowChange3 = new RawTripTestPayload(recordStr3);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange3.getRowKey(), rowChange3.getPartitionPath()), rowChange3));
-
+ for (String recordStr : recordsStrs) {
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ insertRecords
+ .add(new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange));
+ }
Map<String, HoodieRecord> insertRecordMap = insertRecords.stream()
.collect(Collectors.toMap(r -> r.getRecordKey(), Function.identity()));
HoodieCreateHandle createHandle =
- new HoodieCreateHandle(config, "100", table, rowChange1.getPartitionPath(), "f1-0", insertRecordMap, supplier);
+ new HoodieCreateHandle(config, "100", table, insertRecords.get(0).getPartitionPath(), "f1-0", insertRecordMap, supplier);
createHandle.write();
return createHandle.close();
}).collect();
final Path commitFile = new Path(config.getBasePath() + "/.hoodie/" + HoodieTimeline.makeCommitFileName("100"));
FSUtils.getFs(basePath, HoodieTestUtils.getDefaultHadoopConf()).create(commitFile);
+ return statuses.get(0);
+ }
- // Now try an update with an evolved schema
- // Evolved schema does not have guarantee on preserving the original field ordering
- final HoodieWriteConfig config2 = makeHoodieClientConfig("/exampleEvolvedSchema.txt");
- final WriteStatus insertResult = statuses.get(0);
+ private List<String> generateMultiRecordsForExampleSchema() {
+ List<String> recordsStrs = new ArrayList<>();
+ String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
+ String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
+ String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
+ recordsStrs.add(recordStr1);
+ recordsStrs.add(recordStr2);
+ recordsStrs.add(recordStr3);
+ return recordsStrs;
+ }
+
+ private List<String> generateOneRecordForExampleSchema() {
+ List<String> recordsStrs = new ArrayList<>();
+ String recordStr = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
+ recordsStrs.add(recordStr);
+ return recordsStrs;
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateSuccessWithAddColumnHaveDefault() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateMultiRecordsForExampleSchema());
String fileId = insertResult.getFileId();
- final HoodieSparkTable table2 = HoodieSparkTable.create(config, context);
- assertEquals(1, jsc.parallelize(Arrays.asList(1)).map(x -> {
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchema.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ jsc.parallelize(Arrays.asList(1)).map(x -> {
// New content with values for the newly added field
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12,\"added_field\":1}";
List<HoodieRecord> updateRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- HoodieRecord record1 =
- new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1);
- record1.unseal();
- record1.setCurrentLocation(new HoodieRecordLocation("100", fileId));
- record1.seal();
- updateRecords.add(record1);
-
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ HoodieRecord record =
+ new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange);
+ record.unseal();
+ record.setCurrentLocation(new HoodieRecordLocation("101", fileId));
+ record.seal();
+ updateRecords.add(record);
assertDoesNotThrow(() -> {
- HoodieMergeHandle mergeHandle = new HoodieMergeHandle(config2, "101", table2,
- updateRecords.iterator(), record1.getPartitionPath(), fileId, supplier);
+ HoodieMergeHandle mergeHandle = new HoodieMergeHandle(config, "101", table,
+ updateRecords.iterator(), record.getPartitionPath(), fileId, supplier);
Configuration conf = new Configuration();
AvroReadSupport.setAvroReadSchema(conf, mergeHandle.getWriterSchemaWithMetafields());
List<GenericRecord> oldRecords = ParquetUtils.readAvroRecords(conf,
- new Path(config2.getBasePath() + "/" + insertResult.getStat().getPath()));
+ new Path(config.getBasePath() + "/" + insertResult.getStat().getPath()));
for (GenericRecord rec : oldRecords) {
mergeHandle.write(rec);
}
mergeHandle.close();
}, "UpdateFunction could not read records written with exampleSchema.txt using the "
+ "exampleEvolvedSchema.txt");
+ return 1;
+ }).collect();
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateSuccessWithChangeColumnOrder() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateMultiRecordsForExampleSchema());
+ String fileId = insertResult.getFileId();
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaChangeOrder.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ jsc.parallelize(Arrays.asList(1)).map(x -> {
+ // New content with values for the newly added field
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"added_field\":1},\"number\":12";
+ List<HoodieRecord> updateRecords = new ArrayList<>();
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ HoodieRecord record =
+ new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange);
+ record.unseal();
+ record.setCurrentLocation(new HoodieRecordLocation("101", fileId));
+ record.seal();
+ updateRecords.add(record);
+ assertDoesNotThrow(() -> {
+ HoodieMergeHandle mergeHandle = new HoodieMergeHandle(config, "101", table,
+ updateRecords.iterator(), record.getPartitionPath(), fileId, supplier);
+ Configuration conf = new Configuration();
+ AvroReadSupport.setAvroReadSchema(conf, mergeHandle.getWriterSchemaWithMetafields());
+ List<GenericRecord> oldRecords = ParquetUtils.readAvroRecords(conf,
+ new Path(config.getBasePath() + "/" + insertResult.getStat().getPath()));
+ for (GenericRecord rec : oldRecords) {
+ mergeHandle.write(rec);
+ }
+ mergeHandle.close();
+ }, "UpdateFunction could not read records written with exampleSchema.txt using the "
+ + "exampleEvolvedSchemaChangeOrder.txt as column order change");
return 1;
- }).collect().size());
+ }).collect();
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateMisMatchWithDeleteColumn() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateOneRecordForExampleSchema());
+ String fileId = insertResult.getFileId();
+
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaDeleteColumn.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ jsc.parallelize(Arrays.asList(1)).map(x -> {
+ // New content with values for the newly added field
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\"}";
+ List<HoodieRecord> updateRecords = new ArrayList<>();
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ HoodieRecord record =
+ new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange);
+ record.unseal();
+ record.setCurrentLocation(new HoodieRecordLocation("101", fileId));
+ record.seal();
+ updateRecords.add(record);
+ HoodieMergeHandle mergeHandle = new HoodieMergeHandle(config, "101", table,
+ updateRecords.iterator(), record.getPartitionPath(), fileId, supplier);
+ Configuration conf = new Configuration();
+ AvroReadSupport.setAvroReadSchema(conf, mergeHandle.getWriterSchemaWithMetafields());
+ assertThrows(InvalidRecordException.class, () -> {
+ List<GenericRecord> oldRecords = ParquetUtils.readAvroRecords(conf,
+ new Path(config.getBasePath() + "/" + insertResult.getStat().getPath()));
+ }, "UpdateFunction when delete column ,Parquet/Avro schema mismatch: Avro field 'xxx' not found");
+ mergeHandle.close();
+ return 1;
+ }).collect();
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateMisMatchWithAddColumnNotHaveDefault() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateOneRecordForExampleSchema());
+ String fileId = insertResult.getFileId();
+
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaColumnRequire.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ jsc.parallelize(Arrays.asList(1)).map(x -> {
+ // New content with values for the newly added field
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12,\"added_field\":1}";
+ List<HoodieRecord> updateRecords = new ArrayList<>();
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ HoodieRecord record =
+ new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange);
+ record.unseal();
+ record.setCurrentLocation(new HoodieRecordLocation("101", fileId));
+ record.seal();
+ updateRecords.add(record);
+ assertThrows(HoodieUpsertException.class, () -> {
+ HoodieMergeHandle mergeHandle = new HoodieMergeHandle(config, "101", table,
+ updateRecords.iterator(), record.getPartitionPath(), fileId, supplier);
+ Configuration conf = new Configuration();
+ AvroReadSupport.setAvroReadSchema(conf, mergeHandle.getWriterSchemaWithMetafields());
+ List<GenericRecord> oldRecords = ParquetUtils.readAvroRecords(conf,
+ new Path(config.getBasePath() + "/" + insertResult.getStat().getPath()));
+ for (GenericRecord rec : oldRecords) {
+ mergeHandle.write(rec);
+ }
+ mergeHandle.close();
+ }, "UpdateFunction could not read records written with exampleSchema.txt using the "
+ + "exampleEvolvedSchemaColumnRequire.txt ,because oldrecords do not have required column added_field");
+ return 1;
+ }).collect();
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateMisMatchWithChangeColumnType() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateOneRecordForExampleSchema());
+ String fileId = insertResult.getFileId();
+
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaColumnType.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ jsc.parallelize(Arrays.asList(1)).map(x -> {
+ // New content with values for the newly added field
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":\"12\"}";
+ List<HoodieRecord> updateRecords = new ArrayList<>();
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ HoodieRecord record =
+ new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange);
+ record.unseal();
+ record.setCurrentLocation(new HoodieRecordLocation("101", fileId));
+ record.seal();
+ updateRecords.add(record);
+ HoodieMergeHandle mergeHandle = new HoodieMergeHandle(config, "101", table,
+ updateRecords.iterator(), record.getPartitionPath(), fileId, supplier);
+ Configuration conf = new Configuration();
+ AvroReadSupport.setAvroReadSchema(conf, mergeHandle.getWriterSchemaWithMetafields());
Review comment:
instead of creating a new Configuration, would it be better with `table.getHadoopConf()`?
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] pratyakshsharma commented on a change in pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
pratyakshsharma commented on a change in pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#discussion_r504233760
##########
File path: hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/client/TestUpdateSchemaEvolution.java
##########
@@ -68,77 +71,158 @@ public void tearDown() throws IOException {
cleanupResources();
}
- @Test
- public void testSchemaEvolutionOnUpdate() throws Exception {
+ private WriteStatus prepareFirstRecordCommit(List<String> recordsStrs) throws IOException {
// Create a bunch of records with a old version of schema
final HoodieWriteConfig config = makeHoodieClientConfig("/exampleSchema.txt");
final HoodieSparkTable table = HoodieSparkTable.create(config, context);
-
final List<WriteStatus> statuses = jsc.parallelize(Arrays.asList(1)).map(x -> {
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
- String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
- String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
List<HoodieRecord> insertRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1));
- RawTripTestPayload rowChange2 = new RawTripTestPayload(recordStr2);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange2.getRowKey(), rowChange2.getPartitionPath()), rowChange2));
- RawTripTestPayload rowChange3 = new RawTripTestPayload(recordStr3);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange3.getRowKey(), rowChange3.getPartitionPath()), rowChange3));
-
+ for (String recordStr : recordsStrs) {
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ insertRecords
+ .add(new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange));
+ }
Map<String, HoodieRecord> insertRecordMap = insertRecords.stream()
.collect(Collectors.toMap(r -> r.getRecordKey(), Function.identity()));
HoodieCreateHandle createHandle =
- new HoodieCreateHandle(config, "100", table, rowChange1.getPartitionPath(), "f1-0", insertRecordMap, supplier);
+ new HoodieCreateHandle(config, "100", table, insertRecords.get(0).getPartitionPath(), "f1-0", insertRecordMap, supplier);
createHandle.write();
return createHandle.close();
}).collect();
final Path commitFile = new Path(config.getBasePath() + "/.hoodie/" + HoodieTimeline.makeCommitFileName("100"));
FSUtils.getFs(basePath, HoodieTestUtils.getDefaultHadoopConf()).create(commitFile);
+ return statuses.get(0);
+ }
- // Now try an update with an evolved schema
- // Evolved schema does not have guarantee on preserving the original field ordering
- final HoodieWriteConfig config2 = makeHoodieClientConfig("/exampleEvolvedSchema.txt");
- final WriteStatus insertResult = statuses.get(0);
- String fileId = insertResult.getFileId();
-
- final HoodieSparkTable table2 = HoodieSparkTable.create(config, context);
- assertEquals(1, jsc.parallelize(Arrays.asList(1)).map(x -> {
- // New content with values for the newly added field
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12,\"added_field\":1}";
- List<HoodieRecord> updateRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- HoodieRecord record1 =
- new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1);
- record1.unseal();
- record1.setCurrentLocation(new HoodieRecordLocation("100", fileId));
- record1.seal();
- updateRecords.add(record1);
-
- assertDoesNotThrow(() -> {
- HoodieMergeHandle mergeHandle = new HoodieMergeHandle(config2, "101", table2,
- updateRecords.iterator(), record1.getPartitionPath(), fileId, supplier);
- Configuration conf = new Configuration();
- AvroReadSupport.setAvroReadSchema(conf, mergeHandle.getWriterSchemaWithMetafields());
- List<GenericRecord> oldRecords = ParquetUtils.readAvroRecords(conf,
- new Path(config2.getBasePath() + "/" + insertResult.getStat().getPath()));
+ private List<String> generateMultiRecordsForExampleSchema() {
+ List<String> recordsStrs = new ArrayList<>();
+ String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
+ String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
+ String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
+ recordsStrs.add(recordStr1);
+ recordsStrs.add(recordStr2);
+ recordsStrs.add(recordStr3);
+ return recordsStrs;
+ }
+
+ private List<String> generateOneRecordForExampleSchema() {
+ List<String> recordsStrs = new ArrayList<>();
+ String recordStr = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
+ recordsStrs.add(recordStr);
+ return recordsStrs;
+ }
+
+ private void assertSchemaEvolutionOnUpdateResult(WriteStatus insertResult, HoodieSparkTable updateTable,
+ List<HoodieRecord> updateRecords, String assertMsg, boolean isAssertThrow, Class expectedExceptionType) {
+ jsc.parallelize(Arrays.asList(1)).map(x -> {
+ Executable executable = () -> {
+ HoodieMergeHandle mergeHandle = new HoodieMergeHandle(updateTable.getConfig(), "101", updateTable,
+ updateRecords.iterator(), updateRecords.get(0).getPartitionPath(), insertResult.getFileId(), supplier);
+ AvroReadSupport.setAvroReadSchema(updateTable.getHadoopConf(), mergeHandle.getWriterSchemaWithMetafields());
+ List<GenericRecord> oldRecords = ParquetUtils.readAvroRecords(updateTable.getHadoopConf(),
+ new Path(updateTable.getConfig().getBasePath() + "/" + insertResult.getStat().getPath()));
for (GenericRecord rec : oldRecords) {
mergeHandle.write(rec);
}
mergeHandle.close();
- }, "UpdateFunction could not read records written with exampleSchema.txt using the "
- + "exampleEvolvedSchema.txt");
-
+ };
+ if (isAssertThrow) {
+ assertThrows(expectedExceptionType, executable, assertMsg);
+ } else {
+ assertDoesNotThrow(executable, assertMsg);
+ }
return 1;
- }).collect().size());
+ }).collect();
+ }
+
+ private List<HoodieRecord> buildUpdateRecords(String recordStr, String insertFileId) throws IOException {
+ List<HoodieRecord> updateRecords = new ArrayList<>();
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ HoodieRecord record =
+ new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange);
+ record.setCurrentLocation(new HoodieRecordLocation("101", insertFileId));
+ record.seal();
+ updateRecords.add(record);
+ return updateRecords;
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateSuccessWithAddColumnHaveDefault() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateMultiRecordsForExampleSchema());
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchema.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ // New content with values for the newly added field
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12,\"added_field\":1}";
+ List<HoodieRecord> updateRecords = buildUpdateRecords(recordStr, insertResult.getFileId());
+ String assertMsg = "UpdateFunction could not read records written with exampleSchema.txt using the "
+ + "exampleEvolvedSchema.txt";
+ assertSchemaEvolutionOnUpdateResult(insertResult, table, updateRecords, assertMsg, false, null);
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateSuccessWithChangeColumnOrder() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateMultiRecordsForExampleSchema());
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaChangeOrder.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"added_field\":1},\"number\":12";
+ List<HoodieRecord> updateRecords = buildUpdateRecords(recordStr, insertResult.getFileId());
+ String assertMsg = "UpdateFunction could not read records written with exampleSchema.txt using the "
+ + "exampleEvolvedSchemaChangeOrder.txt as column order change";
+ assertSchemaEvolutionOnUpdateResult(insertResult, table, updateRecords, assertMsg, false, null);
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateMisMatchWithDeleteColumn() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateOneRecordForExampleSchema());
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaDeleteColumn.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\"}";
+ List<HoodieRecord> updateRecords = buildUpdateRecords(recordStr, insertResult.getFileId());
+ String assertMsg = "UpdateFunction when delete column ,Parquet/Avro schema mismatch: Avro field 'xxx' not found";
+ assertSchemaEvolutionOnUpdateResult(insertResult, table, updateRecords, assertMsg, true, InvalidRecordException.class);
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateMisMatchWithAddColumnNotHaveDefault() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateOneRecordForExampleSchema());
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaColumnRequire.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12,\"added_field\":1}";
+ List<HoodieRecord> updateRecords = buildUpdateRecords(recordStr, insertResult.getFileId());
+ String assertMsg = "UpdateFunction could not read records written with exampleSchema.txt using the "
+ + "exampleEvolvedSchemaColumnRequire.txt ,because oldrecords do not have required column added_field";
Review comment:
oldrecords -> old records
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] lw309637554 commented on pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
lw309637554 commented on pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#issuecomment-712104176
@pratyakshsharma @xushiyan @vinothchandar hello,
Is there anything that needs to be fixed?
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] lw309637554 commented on a change in pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
lw309637554 commented on a change in pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#discussion_r499648617
##########
File path: hudi-client/hudi-client-common/src/main/java/org/apache/hudi/io/HoodieMergeHandle.java
##########
@@ -254,6 +253,10 @@ public void write(GenericRecord oldRecord) {
LOG.error("Failed to merge old record into new file for key " + key + " from old file " + getOldFilePath()
+ " to new file " + newFilePath, e);
throw new HoodieUpsertException(errMsg, e);
+ } catch (RuntimeException e) {
+ LOG.error("Summary is " + e.getMessage() + ", detail is schema mismatch when rewriting old record " + oldRecord + " from file " + getOldFilePath()
Review comment:
make sense .done
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] vinothchandar commented on pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
vinothchandar commented on pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#issuecomment-707550877
@pratyakshsharma are you able to complete this today? if not, i can take over and help . lmk :)
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] pratyakshsharma commented on pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
pratyakshsharma commented on pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#issuecomment-707990175
Have left few minor comments. @lw309637554
Rest looks good.
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] lw309637554 commented on pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
lw309637554 commented on pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#issuecomment-706813674
> lagging a bit. Will take a pass today and circle back.
thanks,please help to review
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] lw309637554 commented on a change in pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
lw309637554 commented on a change in pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#discussion_r499161908
##########
File path: hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/client/TestUpdateSchemaEvolution.java
##########
@@ -68,61 +71,62 @@ public void tearDown() throws IOException {
cleanupResources();
}
- @Test
- public void testSchemaEvolutionOnUpdate() throws Exception {
+ private WriteStatus prepareFirstCommitData(List<String> recordsStrs) throws IOException {
Review comment:
thanks, make sense
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] pratyakshsharma commented on a change in pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
pratyakshsharma commented on a change in pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#discussion_r504227517
##########
File path: hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/client/TestUpdateSchemaEvolution.java
##########
@@ -68,77 +71,158 @@ public void tearDown() throws IOException {
cleanupResources();
}
- @Test
- public void testSchemaEvolutionOnUpdate() throws Exception {
+ private WriteStatus prepareFirstRecordCommit(List<String> recordsStrs) throws IOException {
// Create a bunch of records with a old version of schema
Review comment:
a old -> an old
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] pratyakshsharma commented on a change in pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
pratyakshsharma commented on a change in pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#discussion_r504228785
##########
File path: hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/client/TestUpdateSchemaEvolution.java
##########
@@ -68,77 +71,158 @@ public void tearDown() throws IOException {
cleanupResources();
}
- @Test
- public void testSchemaEvolutionOnUpdate() throws Exception {
+ private WriteStatus prepareFirstRecordCommit(List<String> recordsStrs) throws IOException {
// Create a bunch of records with a old version of schema
final HoodieWriteConfig config = makeHoodieClientConfig("/exampleSchema.txt");
final HoodieSparkTable table = HoodieSparkTable.create(config, context);
-
final List<WriteStatus> statuses = jsc.parallelize(Arrays.asList(1)).map(x -> {
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
- String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
- String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
List<HoodieRecord> insertRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1));
- RawTripTestPayload rowChange2 = new RawTripTestPayload(recordStr2);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange2.getRowKey(), rowChange2.getPartitionPath()), rowChange2));
- RawTripTestPayload rowChange3 = new RawTripTestPayload(recordStr3);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange3.getRowKey(), rowChange3.getPartitionPath()), rowChange3));
-
+ for (String recordStr : recordsStrs) {
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ insertRecords
+ .add(new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange));
+ }
Map<String, HoodieRecord> insertRecordMap = insertRecords.stream()
.collect(Collectors.toMap(r -> r.getRecordKey(), Function.identity()));
HoodieCreateHandle createHandle =
- new HoodieCreateHandle(config, "100", table, rowChange1.getPartitionPath(), "f1-0", insertRecordMap, supplier);
+ new HoodieCreateHandle(config, "100", table, insertRecords.get(0).getPartitionPath(), "f1-0", insertRecordMap, supplier);
createHandle.write();
return createHandle.close();
}).collect();
final Path commitFile = new Path(config.getBasePath() + "/.hoodie/" + HoodieTimeline.makeCommitFileName("100"));
FSUtils.getFs(basePath, HoodieTestUtils.getDefaultHadoopConf()).create(commitFile);
+ return statuses.get(0);
+ }
- // Now try an update with an evolved schema
- // Evolved schema does not have guarantee on preserving the original field ordering
- final HoodieWriteConfig config2 = makeHoodieClientConfig("/exampleEvolvedSchema.txt");
- final WriteStatus insertResult = statuses.get(0);
- String fileId = insertResult.getFileId();
-
- final HoodieSparkTable table2 = HoodieSparkTable.create(config, context);
- assertEquals(1, jsc.parallelize(Arrays.asList(1)).map(x -> {
- // New content with values for the newly added field
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12,\"added_field\":1}";
- List<HoodieRecord> updateRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- HoodieRecord record1 =
- new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1);
- record1.unseal();
- record1.setCurrentLocation(new HoodieRecordLocation("100", fileId));
- record1.seal();
- updateRecords.add(record1);
-
- assertDoesNotThrow(() -> {
- HoodieMergeHandle mergeHandle = new HoodieMergeHandle(config2, "101", table2,
- updateRecords.iterator(), record1.getPartitionPath(), fileId, supplier);
- Configuration conf = new Configuration();
- AvroReadSupport.setAvroReadSchema(conf, mergeHandle.getWriterSchemaWithMetafields());
- List<GenericRecord> oldRecords = ParquetUtils.readAvroRecords(conf,
- new Path(config2.getBasePath() + "/" + insertResult.getStat().getPath()));
+ private List<String> generateMultiRecordsForExampleSchema() {
Review comment:
generateMultiRecordsForExampleSchema -> generateMultipleRecordsForExampleSchema?
@lw309637554 I would leave it upto you to decide though.
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] xushiyan commented on pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
xushiyan commented on pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#issuecomment-712208378
@lw309637554 looks like comments from @pratyakshsharma were addressed. sorry about the delay. merging now. Thank you @lw309637554 for adding the cases!
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] pratyakshsharma commented on pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
pratyakshsharma commented on pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#issuecomment-706608951
lagging a bit. Will take a pass today and circle back.
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] lw309637554 commented on pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
lw309637554 commented on pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#issuecomment-700399285
@vinothchandar hello, can you help review ?
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] lw309637554 edited a comment on pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
lw309637554 edited a comment on pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#issuecomment-706813674
> lagging a bit. Will take a pass today and circle back.
@pratyakshsharma thanks,please help to review
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] pratyakshsharma commented on a change in pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
pratyakshsharma commented on a change in pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#discussion_r504235892
##########
File path: hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/client/TestUpdateSchemaEvolution.java
##########
@@ -68,77 +71,158 @@ public void tearDown() throws IOException {
cleanupResources();
}
- @Test
- public void testSchemaEvolutionOnUpdate() throws Exception {
+ private WriteStatus prepareFirstRecordCommit(List<String> recordsStrs) throws IOException {
// Create a bunch of records with a old version of schema
final HoodieWriteConfig config = makeHoodieClientConfig("/exampleSchema.txt");
final HoodieSparkTable table = HoodieSparkTable.create(config, context);
-
final List<WriteStatus> statuses = jsc.parallelize(Arrays.asList(1)).map(x -> {
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
- String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
- String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
List<HoodieRecord> insertRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1));
- RawTripTestPayload rowChange2 = new RawTripTestPayload(recordStr2);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange2.getRowKey(), rowChange2.getPartitionPath()), rowChange2));
- RawTripTestPayload rowChange3 = new RawTripTestPayload(recordStr3);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange3.getRowKey(), rowChange3.getPartitionPath()), rowChange3));
-
+ for (String recordStr : recordsStrs) {
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ insertRecords
+ .add(new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange));
+ }
Map<String, HoodieRecord> insertRecordMap = insertRecords.stream()
.collect(Collectors.toMap(r -> r.getRecordKey(), Function.identity()));
HoodieCreateHandle createHandle =
- new HoodieCreateHandle(config, "100", table, rowChange1.getPartitionPath(), "f1-0", insertRecordMap, supplier);
+ new HoodieCreateHandle(config, "100", table, insertRecords.get(0).getPartitionPath(), "f1-0", insertRecordMap, supplier);
createHandle.write();
return createHandle.close();
}).collect();
final Path commitFile = new Path(config.getBasePath() + "/.hoodie/" + HoodieTimeline.makeCommitFileName("100"));
FSUtils.getFs(basePath, HoodieTestUtils.getDefaultHadoopConf()).create(commitFile);
+ return statuses.get(0);
+ }
- // Now try an update with an evolved schema
- // Evolved schema does not have guarantee on preserving the original field ordering
- final HoodieWriteConfig config2 = makeHoodieClientConfig("/exampleEvolvedSchema.txt");
- final WriteStatus insertResult = statuses.get(0);
- String fileId = insertResult.getFileId();
-
- final HoodieSparkTable table2 = HoodieSparkTable.create(config, context);
- assertEquals(1, jsc.parallelize(Arrays.asList(1)).map(x -> {
- // New content with values for the newly added field
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12,\"added_field\":1}";
- List<HoodieRecord> updateRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- HoodieRecord record1 =
- new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1);
- record1.unseal();
- record1.setCurrentLocation(new HoodieRecordLocation("100", fileId));
- record1.seal();
- updateRecords.add(record1);
-
- assertDoesNotThrow(() -> {
- HoodieMergeHandle mergeHandle = new HoodieMergeHandle(config2, "101", table2,
- updateRecords.iterator(), record1.getPartitionPath(), fileId, supplier);
- Configuration conf = new Configuration();
- AvroReadSupport.setAvroReadSchema(conf, mergeHandle.getWriterSchemaWithMetafields());
- List<GenericRecord> oldRecords = ParquetUtils.readAvroRecords(conf,
- new Path(config2.getBasePath() + "/" + insertResult.getStat().getPath()));
+ private List<String> generateMultiRecordsForExampleSchema() {
+ List<String> recordsStrs = new ArrayList<>();
+ String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
+ String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
+ String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
+ recordsStrs.add(recordStr1);
+ recordsStrs.add(recordStr2);
+ recordsStrs.add(recordStr3);
+ return recordsStrs;
+ }
+
+ private List<String> generateOneRecordForExampleSchema() {
+ List<String> recordsStrs = new ArrayList<>();
+ String recordStr = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
+ recordsStrs.add(recordStr);
+ return recordsStrs;
+ }
+
+ private void assertSchemaEvolutionOnUpdateResult(WriteStatus insertResult, HoodieSparkTable updateTable,
+ List<HoodieRecord> updateRecords, String assertMsg, boolean isAssertThrow, Class expectedExceptionType) {
+ jsc.parallelize(Arrays.asList(1)).map(x -> {
+ Executable executable = () -> {
+ HoodieMergeHandle mergeHandle = new HoodieMergeHandle(updateTable.getConfig(), "101", updateTable,
+ updateRecords.iterator(), updateRecords.get(0).getPartitionPath(), insertResult.getFileId(), supplier);
+ AvroReadSupport.setAvroReadSchema(updateTable.getHadoopConf(), mergeHandle.getWriterSchemaWithMetafields());
+ List<GenericRecord> oldRecords = ParquetUtils.readAvroRecords(updateTable.getHadoopConf(),
+ new Path(updateTable.getConfig().getBasePath() + "/" + insertResult.getStat().getPath()));
for (GenericRecord rec : oldRecords) {
mergeHandle.write(rec);
}
mergeHandle.close();
- }, "UpdateFunction could not read records written with exampleSchema.txt using the "
- + "exampleEvolvedSchema.txt");
-
+ };
+ if (isAssertThrow) {
+ assertThrows(expectedExceptionType, executable, assertMsg);
+ } else {
+ assertDoesNotThrow(executable, assertMsg);
+ }
return 1;
- }).collect().size());
+ }).collect();
+ }
+
+ private List<HoodieRecord> buildUpdateRecords(String recordStr, String insertFileId) throws IOException {
+ List<HoodieRecord> updateRecords = new ArrayList<>();
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ HoodieRecord record =
+ new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange);
+ record.setCurrentLocation(new HoodieRecordLocation("101", insertFileId));
+ record.seal();
+ updateRecords.add(record);
+ return updateRecords;
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateSuccessWithAddColumnHaveDefault() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateMultiRecordsForExampleSchema());
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchema.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ // New content with values for the newly added field
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12,\"added_field\":1}";
+ List<HoodieRecord> updateRecords = buildUpdateRecords(recordStr, insertResult.getFileId());
+ String assertMsg = "UpdateFunction could not read records written with exampleSchema.txt using the "
+ + "exampleEvolvedSchema.txt";
+ assertSchemaEvolutionOnUpdateResult(insertResult, table, updateRecords, assertMsg, false, null);
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateSuccessWithChangeColumnOrder() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateMultiRecordsForExampleSchema());
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaChangeOrder.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"added_field\":1},\"number\":12";
+ List<HoodieRecord> updateRecords = buildUpdateRecords(recordStr, insertResult.getFileId());
+ String assertMsg = "UpdateFunction could not read records written with exampleSchema.txt using the "
+ + "exampleEvolvedSchemaChangeOrder.txt as column order change";
+ assertSchemaEvolutionOnUpdateResult(insertResult, table, updateRecords, assertMsg, false, null);
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateMisMatchWithDeleteColumn() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateOneRecordForExampleSchema());
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaDeleteColumn.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\"}";
+ List<HoodieRecord> updateRecords = buildUpdateRecords(recordStr, insertResult.getFileId());
+ String assertMsg = "UpdateFunction when delete column ,Parquet/Avro schema mismatch: Avro field 'xxx' not found";
+ assertSchemaEvolutionOnUpdateResult(insertResult, table, updateRecords, assertMsg, true, InvalidRecordException.class);
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateMisMatchWithAddColumnNotHaveDefault() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateOneRecordForExampleSchema());
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaColumnRequire.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12,\"added_field\":1}";
+ List<HoodieRecord> updateRecords = buildUpdateRecords(recordStr, insertResult.getFileId());
+ String assertMsg = "UpdateFunction could not read records written with exampleSchema.txt using the "
+ + "exampleEvolvedSchemaColumnRequire.txt ,because oldrecords do not have required column added_field";
+ assertSchemaEvolutionOnUpdateResult(insertResult, table, updateRecords, assertMsg, true, HoodieUpsertException.class);
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateMisMatchWithChangeColumnType() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateOneRecordForExampleSchema());
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaColumnType.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":\"12\"}";
+ List<HoodieRecord> updateRecords = buildUpdateRecords(recordStr, insertResult.getFileId());
+ String assertMsg = "UpdateFunction when change column type ,org.apache.parquet.avro.AvroConverters$FieldUTF8Converter";
Review comment:
type ,org. -> type, org.
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] pratyakshsharma commented on a change in pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
pratyakshsharma commented on a change in pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#discussion_r504234989
##########
File path: hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/client/TestUpdateSchemaEvolution.java
##########
@@ -68,77 +71,158 @@ public void tearDown() throws IOException {
cleanupResources();
}
- @Test
- public void testSchemaEvolutionOnUpdate() throws Exception {
+ private WriteStatus prepareFirstRecordCommit(List<String> recordsStrs) throws IOException {
// Create a bunch of records with a old version of schema
final HoodieWriteConfig config = makeHoodieClientConfig("/exampleSchema.txt");
final HoodieSparkTable table = HoodieSparkTable.create(config, context);
-
final List<WriteStatus> statuses = jsc.parallelize(Arrays.asList(1)).map(x -> {
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
- String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
- String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
List<HoodieRecord> insertRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1));
- RawTripTestPayload rowChange2 = new RawTripTestPayload(recordStr2);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange2.getRowKey(), rowChange2.getPartitionPath()), rowChange2));
- RawTripTestPayload rowChange3 = new RawTripTestPayload(recordStr3);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange3.getRowKey(), rowChange3.getPartitionPath()), rowChange3));
-
+ for (String recordStr : recordsStrs) {
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ insertRecords
+ .add(new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange));
+ }
Map<String, HoodieRecord> insertRecordMap = insertRecords.stream()
.collect(Collectors.toMap(r -> r.getRecordKey(), Function.identity()));
HoodieCreateHandle createHandle =
- new HoodieCreateHandle(config, "100", table, rowChange1.getPartitionPath(), "f1-0", insertRecordMap, supplier);
+ new HoodieCreateHandle(config, "100", table, insertRecords.get(0).getPartitionPath(), "f1-0", insertRecordMap, supplier);
createHandle.write();
return createHandle.close();
}).collect();
final Path commitFile = new Path(config.getBasePath() + "/.hoodie/" + HoodieTimeline.makeCommitFileName("100"));
FSUtils.getFs(basePath, HoodieTestUtils.getDefaultHadoopConf()).create(commitFile);
+ return statuses.get(0);
+ }
- // Now try an update with an evolved schema
- // Evolved schema does not have guarantee on preserving the original field ordering
- final HoodieWriteConfig config2 = makeHoodieClientConfig("/exampleEvolvedSchema.txt");
- final WriteStatus insertResult = statuses.get(0);
- String fileId = insertResult.getFileId();
-
- final HoodieSparkTable table2 = HoodieSparkTable.create(config, context);
- assertEquals(1, jsc.parallelize(Arrays.asList(1)).map(x -> {
- // New content with values for the newly added field
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12,\"added_field\":1}";
- List<HoodieRecord> updateRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- HoodieRecord record1 =
- new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1);
- record1.unseal();
- record1.setCurrentLocation(new HoodieRecordLocation("100", fileId));
- record1.seal();
- updateRecords.add(record1);
-
- assertDoesNotThrow(() -> {
- HoodieMergeHandle mergeHandle = new HoodieMergeHandle(config2, "101", table2,
- updateRecords.iterator(), record1.getPartitionPath(), fileId, supplier);
- Configuration conf = new Configuration();
- AvroReadSupport.setAvroReadSchema(conf, mergeHandle.getWriterSchemaWithMetafields());
- List<GenericRecord> oldRecords = ParquetUtils.readAvroRecords(conf,
- new Path(config2.getBasePath() + "/" + insertResult.getStat().getPath()));
+ private List<String> generateMultiRecordsForExampleSchema() {
+ List<String> recordsStrs = new ArrayList<>();
+ String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
+ String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
+ String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
+ recordsStrs.add(recordStr1);
+ recordsStrs.add(recordStr2);
+ recordsStrs.add(recordStr3);
+ return recordsStrs;
+ }
+
+ private List<String> generateOneRecordForExampleSchema() {
+ List<String> recordsStrs = new ArrayList<>();
+ String recordStr = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
+ recordsStrs.add(recordStr);
+ return recordsStrs;
+ }
+
+ private void assertSchemaEvolutionOnUpdateResult(WriteStatus insertResult, HoodieSparkTable updateTable,
+ List<HoodieRecord> updateRecords, String assertMsg, boolean isAssertThrow, Class expectedExceptionType) {
+ jsc.parallelize(Arrays.asList(1)).map(x -> {
+ Executable executable = () -> {
+ HoodieMergeHandle mergeHandle = new HoodieMergeHandle(updateTable.getConfig(), "101", updateTable,
+ updateRecords.iterator(), updateRecords.get(0).getPartitionPath(), insertResult.getFileId(), supplier);
+ AvroReadSupport.setAvroReadSchema(updateTable.getHadoopConf(), mergeHandle.getWriterSchemaWithMetafields());
+ List<GenericRecord> oldRecords = ParquetUtils.readAvroRecords(updateTable.getHadoopConf(),
+ new Path(updateTable.getConfig().getBasePath() + "/" + insertResult.getStat().getPath()));
for (GenericRecord rec : oldRecords) {
mergeHandle.write(rec);
}
mergeHandle.close();
- }, "UpdateFunction could not read records written with exampleSchema.txt using the "
- + "exampleEvolvedSchema.txt");
-
+ };
+ if (isAssertThrow) {
+ assertThrows(expectedExceptionType, executable, assertMsg);
+ } else {
+ assertDoesNotThrow(executable, assertMsg);
+ }
return 1;
- }).collect().size());
+ }).collect();
+ }
+
+ private List<HoodieRecord> buildUpdateRecords(String recordStr, String insertFileId) throws IOException {
+ List<HoodieRecord> updateRecords = new ArrayList<>();
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ HoodieRecord record =
+ new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange);
+ record.setCurrentLocation(new HoodieRecordLocation("101", insertFileId));
+ record.seal();
+ updateRecords.add(record);
+ return updateRecords;
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateSuccessWithAddColumnHaveDefault() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateMultiRecordsForExampleSchema());
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchema.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ // New content with values for the newly added field
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12,\"added_field\":1}";
+ List<HoodieRecord> updateRecords = buildUpdateRecords(recordStr, insertResult.getFileId());
+ String assertMsg = "UpdateFunction could not read records written with exampleSchema.txt using the "
+ + "exampleEvolvedSchema.txt";
+ assertSchemaEvolutionOnUpdateResult(insertResult, table, updateRecords, assertMsg, false, null);
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateSuccessWithChangeColumnOrder() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateMultiRecordsForExampleSchema());
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaChangeOrder.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"added_field\":1},\"number\":12";
+ List<HoodieRecord> updateRecords = buildUpdateRecords(recordStr, insertResult.getFileId());
+ String assertMsg = "UpdateFunction could not read records written with exampleSchema.txt using the "
+ + "exampleEvolvedSchemaChangeOrder.txt as column order change";
+ assertSchemaEvolutionOnUpdateResult(insertResult, table, updateRecords, assertMsg, false, null);
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateMisMatchWithDeleteColumn() throws Exception {
+ final WriteStatus insertResult = prepareFirstRecordCommit(generateOneRecordForExampleSchema());
+ // Now try an update with an evolved schema
+ // Evolved schema does not have guarantee on preserving the original field ordering
+ final HoodieWriteConfig config = makeHoodieClientConfig("/exampleEvolvedSchemaDeleteColumn.txt");
+ final HoodieSparkTable table = HoodieSparkTable.create(config, context);
+ String recordStr = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\"}";
+ List<HoodieRecord> updateRecords = buildUpdateRecords(recordStr, insertResult.getFileId());
+ String assertMsg = "UpdateFunction when delete column ,Parquet/Avro schema mismatch: Avro field 'xxx' not found";
Review comment:
delete column ,Parquet/Avro -> delete column, Parquet/Avro
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] lw309637554 commented on pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
lw309637554 commented on pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#issuecomment-703109022
hello, @xushiyan @pratyakshsharma can you help to review?
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] lw309637554 commented on pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
lw309637554 commented on pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#issuecomment-708205243
> Have left few minor comments. @lw309637554
>
> Rest looks good.
@pratyakshsharma thanks for you review. have resolved your suggestion.
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] lw309637554 commented on pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
lw309637554 commented on pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#issuecomment-703727376
@vinothchandar all the comments have resolved.
1. pulling the common structure
2. merge these two catch blocks, and simple log
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] lw309637554 commented on a change in pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
lw309637554 commented on a change in pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#discussion_r499162390
##########
File path: hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/client/TestUpdateSchemaEvolution.java
##########
@@ -68,61 +71,62 @@ public void tearDown() throws IOException {
cleanupResources();
}
- @Test
- public void testSchemaEvolutionOnUpdate() throws Exception {
+ private WriteStatus prepareFirstCommitData(List<String> recordsStrs) throws IOException {
// Create a bunch of records with a old version of schema
final HoodieWriteConfig config = makeHoodieClientConfig("/exampleSchema.txt");
final HoodieSparkTable table = HoodieSparkTable.create(config, context);
-
final List<WriteStatus> statuses = jsc.parallelize(Arrays.asList(1)).map(x -> {
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
- String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
- String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
List<HoodieRecord> insertRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1));
- RawTripTestPayload rowChange2 = new RawTripTestPayload(recordStr2);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange2.getRowKey(), rowChange2.getPartitionPath()), rowChange2));
- RawTripTestPayload rowChange3 = new RawTripTestPayload(recordStr3);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange3.getRowKey(), rowChange3.getPartitionPath()), rowChange3));
-
+ for (String recordStr : recordsStrs) {
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ insertRecords
+ .add(new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange));
+ }
Map<String, HoodieRecord> insertRecordMap = insertRecords.stream()
.collect(Collectors.toMap(r -> r.getRecordKey(), Function.identity()));
HoodieCreateHandle createHandle =
- new HoodieCreateHandle(config, "100", table, rowChange1.getPartitionPath(), "f1-0", insertRecordMap, supplier);
+ new HoodieCreateHandle(config, "100", table, insertRecords.get(0).getPartitionPath(), "f1-0", insertRecordMap, supplier);
createHandle.write();
return createHandle.close();
}).collect();
final Path commitFile = new Path(config.getBasePath() + "/.hoodie/" + HoodieTimeline.makeCommitFileName("100"));
FSUtils.getFs(basePath, HoodieTestUtils.getDefaultHadoopConf()).create(commitFile);
+ return statuses.get(0);
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateSuccessWithAddColumnHaveDefault() throws Exception {
+ List<String> recordsStrs = new ArrayList<>();
+ String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
+ String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
+ String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
+ recordsStrs.add(recordStr1);
+ recordsStrs.add(recordStr2);
+ recordsStrs.add(recordStr3);
Review comment:
thanks ,3 local vars will use for prepareFirstRecordCommit method .i will move it to a method
##########
File path: hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/client/TestUpdateSchemaEvolution.java
##########
@@ -68,61 +71,62 @@ public void tearDown() throws IOException {
cleanupResources();
}
- @Test
- public void testSchemaEvolutionOnUpdate() throws Exception {
+ private WriteStatus prepareFirstCommitData(List<String> recordsStrs) throws IOException {
// Create a bunch of records with a old version of schema
final HoodieWriteConfig config = makeHoodieClientConfig("/exampleSchema.txt");
final HoodieSparkTable table = HoodieSparkTable.create(config, context);
-
final List<WriteStatus> statuses = jsc.parallelize(Arrays.asList(1)).map(x -> {
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
- String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
- String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
List<HoodieRecord> insertRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1));
- RawTripTestPayload rowChange2 = new RawTripTestPayload(recordStr2);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange2.getRowKey(), rowChange2.getPartitionPath()), rowChange2));
- RawTripTestPayload rowChange3 = new RawTripTestPayload(recordStr3);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange3.getRowKey(), rowChange3.getPartitionPath()), rowChange3));
-
+ for (String recordStr : recordsStrs) {
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ insertRecords
+ .add(new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange));
+ }
Map<String, HoodieRecord> insertRecordMap = insertRecords.stream()
.collect(Collectors.toMap(r -> r.getRecordKey(), Function.identity()));
HoodieCreateHandle createHandle =
- new HoodieCreateHandle(config, "100", table, rowChange1.getPartitionPath(), "f1-0", insertRecordMap, supplier);
+ new HoodieCreateHandle(config, "100", table, insertRecords.get(0).getPartitionPath(), "f1-0", insertRecordMap, supplier);
createHandle.write();
return createHandle.close();
}).collect();
final Path commitFile = new Path(config.getBasePath() + "/.hoodie/" + HoodieTimeline.makeCommitFileName("100"));
FSUtils.getFs(basePath, HoodieTestUtils.getDefaultHadoopConf()).create(commitFile);
+ return statuses.get(0);
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateSuccessWithAddColumnHaveDefault() throws Exception {
+ List<String> recordsStrs = new ArrayList<>();
+ String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
+ String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
+ String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
+ recordsStrs.add(recordStr1);
+ recordsStrs.add(recordStr2);
+ recordsStrs.add(recordStr3);
// Now try an update with an evolved schema
// Evolved schema does not have guarantee on preserving the original field ordering
final HoodieWriteConfig config2 = makeHoodieClientConfig("/exampleEvolvedSchema.txt");
- final WriteStatus insertResult = statuses.get(0);
+ final WriteStatus insertResult = prepareFirstCommitData(recordsStrs);
String fileId = insertResult.getFileId();
- final HoodieSparkTable table2 = HoodieSparkTable.create(config, context);
+ final HoodieSparkTable table2 = HoodieSparkTable.create(config2, context);
Review comment:
ok
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] vinothchandar commented on a change in pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
vinothchandar commented on a change in pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#discussion_r499303182
##########
File path: hudi-client/hudi-client-common/src/main/java/org/apache/hudi/io/HoodieMergeHandle.java
##########
@@ -254,6 +253,10 @@ public void write(GenericRecord oldRecord) {
LOG.error("Failed to merge old record into new file for key " + key + " from old file " + getOldFilePath()
+ " to new file " + newFilePath, e);
throw new HoodieUpsertException(errMsg, e);
+ } catch (RuntimeException e) {
+ LOG.error("Summary is " + e.getMessage() + ", detail is schema mismatch when rewriting old record " + oldRecord + " from file " + getOldFilePath()
Review comment:
I think we can merge these two catch blocks? also it's probably better to move the LOG.error to LOG.debug and only log record data when such debug/tracing is enabled? This might just flood the logs.
##########
File path: hudi-client/hudi-spark-client/src/test/java/org/apache/hudi/client/TestUpdateSchemaEvolution.java
##########
@@ -68,77 +71,232 @@ public void tearDown() throws IOException {
cleanupResources();
}
- @Test
- public void testSchemaEvolutionOnUpdate() throws Exception {
+ private WriteStatus prepareFirstRecordCommit(List<String> recordsStrs) throws IOException {
// Create a bunch of records with a old version of schema
final HoodieWriteConfig config = makeHoodieClientConfig("/exampleSchema.txt");
final HoodieSparkTable table = HoodieSparkTable.create(config, context);
-
final List<WriteStatus> statuses = jsc.parallelize(Arrays.asList(1)).map(x -> {
- String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
- String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
- String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
- + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
List<HoodieRecord> insertRecords = new ArrayList<>();
- RawTripTestPayload rowChange1 = new RawTripTestPayload(recordStr1);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange1.getRowKey(), rowChange1.getPartitionPath()), rowChange1));
- RawTripTestPayload rowChange2 = new RawTripTestPayload(recordStr2);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange2.getRowKey(), rowChange2.getPartitionPath()), rowChange2));
- RawTripTestPayload rowChange3 = new RawTripTestPayload(recordStr3);
- insertRecords
- .add(new HoodieRecord(new HoodieKey(rowChange3.getRowKey(), rowChange3.getPartitionPath()), rowChange3));
-
+ for (String recordStr : recordsStrs) {
+ RawTripTestPayload rowChange = new RawTripTestPayload(recordStr);
+ insertRecords
+ .add(new HoodieRecord(new HoodieKey(rowChange.getRowKey(), rowChange.getPartitionPath()), rowChange));
+ }
Map<String, HoodieRecord> insertRecordMap = insertRecords.stream()
.collect(Collectors.toMap(r -> r.getRecordKey(), Function.identity()));
HoodieCreateHandle createHandle =
- new HoodieCreateHandle(config, "100", table, rowChange1.getPartitionPath(), "f1-0", insertRecordMap, supplier);
+ new HoodieCreateHandle(config, "100", table, insertRecords.get(0).getPartitionPath(), "f1-0", insertRecordMap, supplier);
createHandle.write();
return createHandle.close();
}).collect();
final Path commitFile = new Path(config.getBasePath() + "/.hoodie/" + HoodieTimeline.makeCommitFileName("100"));
FSUtils.getFs(basePath, HoodieTestUtils.getDefaultHadoopConf()).create(commitFile);
+ return statuses.get(0);
+ }
- // Now try an update with an evolved schema
- // Evolved schema does not have guarantee on preserving the original field ordering
- final HoodieWriteConfig config2 = makeHoodieClientConfig("/exampleEvolvedSchema.txt");
- final WriteStatus insertResult = statuses.get(0);
+ private List<String> generateMultiRecordsForExampleSchema() {
+ List<String> recordsStrs = new ArrayList<>();
+ String recordStr1 = "{\"_row_key\":\"8eb5b87a-1feh-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":12}";
+ String recordStr2 = "{\"_row_key\":\"8eb5b87b-1feu-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:20:41.415Z\",\"number\":100}";
+ String recordStr3 = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
+ recordsStrs.add(recordStr1);
+ recordsStrs.add(recordStr2);
+ recordsStrs.add(recordStr3);
+ return recordsStrs;
+ }
+
+ private List<String> generateOneRecordForExampleSchema() {
+ List<String> recordsStrs = new ArrayList<>();
+ String recordStr = "{\"_row_key\":\"8eb5b87c-1fej-4edd-87b4-6ec96dc405a0\","
+ + "\"time\":\"2016-01-31T03:16:41.415Z\",\"number\":15}";
+ recordsStrs.add(recordStr);
+ return recordsStrs;
+ }
+
+ @Test
+ public void testSchemaEvolutionOnUpdateSuccessWithAddColumnHaveDefault() throws Exception {
Review comment:
we can reuse some code in this file by pulling the common structure into a helper function ?
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [hudi] pratyakshsharma commented on a change in pull request #2127: [HUDI-284] add more test for UpdateSchemaEvolution
Posted by GitBox <gi...@apache.org>.
pratyakshsharma commented on a change in pull request #2127:
URL: https://github.com/apache/hudi/pull/2127#discussion_r504238129
##########
File path: hudi-client/hudi-client-common/src/test/resources/exampleEvolvedSchemaDeleteColumn.txt
##########
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+{
Review comment:
can we make the schema files as .avsc? @lw309637554
----------------------------------------------------------------
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.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org