Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ private Option<HoodieRecord> prepareRecord(HoodieRecord<T> hoodieRecord) {
// Convert GenericRecord to GenericRecord with hoodie commit metadata in schema
HoodieRecord rewrittenRecord = schemaOnReadEnabled ? finalRecord.get().rewriteRecordWithNewSchema(tableSchema, recordProperties, writeSchemaWithMetaFields)
: finalRecord.get().rewriteRecord(tableSchema, recordProperties, writeSchemaWithMetaFields);
HoodieRecord populatedRecord = populateMetadataFields(rewrittenRecord, writeSchemaWithMetaFields, recordProperties);
HoodieRecord populatedRecord = populateMetadataFields(rewrittenRecord.copy(), writeSchemaWithMetaFields, recordProperties);
finalRecord = Option.of(populatedRecord);
if (isUpdateRecord) {
updatedRecordsWritten++;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,15 +157,6 @@ public static HoodieBaseFile getLatestBaseFile(HoodieTable<?, ?, ?, ?> hoodieTab
return baseFileOp.get();
}

@Override
public Schema getWriterSchemaWithMetaFields() {
return writeSchemaWithMetaFields;
}

public Schema getWriterSchema() {
return writeSchema;
}

/**
* Extract old file path, initialize StorageWriter and WriteStatus.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ public Schema getWriterSchemaWithMetaFields() {
return writeSchemaWithMetaFields;
}

public Schema getWriterSchema() {
return writeSchema;
}

/**
* Determines whether we can accept the incoming records, into the current file. Depending on
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public BootstrapRecordConsumer(HoodieBootstrapHandle bootstrapHandle) {

@Override
protected void consumeOneRecord(HoodieRecord record) {
bootstrapHandle.write(record, bootstrapHandle.getWriterSchemaWithMetaFields(), new TypedProperties());
bootstrapHandle.write(record, bootstrapHandle.getWriterSchema(), new TypedProperties());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,20 +132,19 @@ public void runMerge(HoodieTable<T, HoodieData<HoodieRecord<T>>, HoodieData<Hood
readerIterator = getMergingIterator(table, mergeHandle, baseFile, reader, readSchema, externalSchemaTransformation);
} else {
if (needToReWriteRecord) {
readerIterator = new RewriteIterator(reader.getRecordIterator(), readSchema, readSchema, table.getConfig().getProps(), renameCols);
readerIterator = new RewriteIterator(reader.getRecordIterator(), reader.getSchema(), readSchema, table.getConfig().getProps(), renameCols);
} else {
readerIterator = reader.getRecordIterator(readSchema);
}
}

wrapper = new BoundedInMemoryExecutor<>(table.getConfig().getWriteBufferLimitBytes(), readerIterator,
new UpdateHandler(mergeHandle), record -> {
HoodieRecord recordCopy = record.copy();
if (!externalSchemaTransformation) {
return recordCopy;
return record.copy();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add a comment elaborating why we're making a copy here

}
try {
return recordCopy.rewriteRecord(writerSchema, new Properties(), readerSchema);
return record.rewriteRecord(writerSchema, new Properties(), readerSchema).copy();
} catch (IOException e) {
throw new HoodieException(String.format("Failed to rewrite record. WriterSchema: %s; ReaderSchema: %s", writerSchema, readerSchema), e);
}
Expand Down Expand Up @@ -175,10 +174,10 @@ class RewriteIterator implements ClosableIterator<HoodieRecord> {
private final Properties prop;
private final Map<String, String> renameCols;

public RewriteIterator(ClosableIterator<HoodieRecord> iter, Schema newSchema, Schema recordSchema, Properties prop, Map<String, String> renameCols) {
public RewriteIterator(ClosableIterator<HoodieRecord> iter, Schema recordSchema, Schema newSchema, Properties prop, Map<String, String> renameCols) {
this.iter = iter;
this.newSchema = newSchema;
this.recordSchema = recordSchema;
this.newSchema = newSchema;
this.prop = prop;
this.renameCols = renameCols;
}
Expand All @@ -191,7 +190,8 @@ public boolean hasNext() {
@Override
public HoodieRecord next() {
try {
return iter.next().rewriteRecordWithNewSchema(recordSchema, prop, newSchema, renameCols);
HoodieRecord record = iter.next();
return record.rewriteRecordWithNewSchema(recordSchema, prop, newSchema, renameCols);
} catch (IOException e) {
LOG.error("Error rewrite record with new schema", e);
throw new HoodieException(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,11 @@ public void runMerge(HoodieTable<T, List<HoodieRecord<T>>, List<HoodieKey>, List

wrapper = new BoundedInMemoryExecutor<>(table.getConfig().getWriteBufferLimitBytes(), new IteratorBasedQueueProducer<>(readerIterator),
Option.of(new UpdateHandler(mergeHandle)), record -> {
HoodieRecord recordCopy = record.copy();
if (!externalSchemaTransformation) {
return recordCopy;
return record.copy();
}
try {
return recordCopy.rewriteRecord(writerSchema, new Properties(), readerSchema);
return record.rewriteRecord(writerSchema, new Properties(), readerSchema).copy();
} catch (IOException e) {
throw new HoodieException(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,11 @@ public void runMerge(HoodieTable<T, List<HoodieRecord<T>>, List<HoodieKey>, List

wrapper = new BoundedInMemoryExecutor<>(table.getConfig().getWriteBufferLimitBytes(), new IteratorBasedQueueProducer<>(readerIterator),
Option.of(new UpdateHandler(mergeHandle)), record -> {
HoodieRecord recordCopy = record.copy();
if (!externalSchemaTransformation) {
return recordCopy;
return record.copy();
}
try {
return recordCopy.rewriteRecord(writerSchema, new Properties(), readerSchema);
return record.rewriteRecord(writerSchema, new Properties(), readerSchema).copy();
} catch (IOException e) {
throw new HoodieException(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@
import org.apache.spark.unsafe.types.CalendarInterval;
import org.apache.spark.unsafe.types.UTF8String;

import java.util.Arrays;

/**
* Hudi internal implementation of the {@link InternalRow} allowing to extend arbitrary
* {@link InternalRow} overlaying Hudi-internal meta-fields on top of it.
Expand Down Expand Up @@ -231,7 +229,11 @@ public MapData getMap(int ordinal) {

@Override
public InternalRow copy() {
return new HoodieInternalRow(Arrays.copyOf(metaFields, metaFields.length), sourceRow.copy(), sourceContainsMetaFields);
UTF8String[] copyMetaFields = new UTF8String[metaFields.length];
for (int i = 0; i < metaFields.length; i++) {
copyMetaFields[i] = metaFields[i] != null ? metaFields[i].copy() : null;
Comment thread
alexeykudinkin marked this conversation as resolved.
}
return new HoodieInternalRow(copyMetaFields, sourceRow.copy(), sourceContainsMetaFields);
}

private int rebaseOrdinal(int ordinal) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import org.apache.avro.Schema;
import org.apache.hudi.HoodieInternalRowUtils;
import org.apache.hudi.SparkAdapterSupport$;
import org.apache.hudi.client.model.HoodieInternalRow;
import org.apache.hudi.common.model.HoodieAvroIndexedRecord;
Expand All @@ -40,7 +39,7 @@
import org.apache.hudi.keygen.BaseKeyGenerator;
import org.apache.hudi.keygen.SparkKeyGeneratorInterface;
import org.apache.hudi.util.HoodieSparkRecordUtils;
import org.apache.spark.sql.HoodieCatalystExpressionUtils$;
import org.apache.spark.sql.HoodieInternalRowUtils;
import org.apache.spark.sql.HoodieUnsafeRowUtils;
import org.apache.spark.sql.HoodieUnsafeRowUtils.NestedFieldPath;
import org.apache.spark.sql.catalyst.CatalystTypeConverters;
Expand Down Expand Up @@ -116,7 +115,7 @@ public HoodieSparkRecord(HoodieKey key, InternalRow data, StructType schema, boo
}

private HoodieSparkRecord(HoodieKey key, InternalRow data, StructType schema, HoodieOperation operation, boolean copy) {
super(key, data, operation);
super(key, data, operation, Option.empty());

validateRow(data, schema);
this.copy = copy;
Expand Down Expand Up @@ -197,28 +196,31 @@ public HoodieRecord rewriteRecord(Schema recordSchema, Properties props, Schema
StructType structType = HoodieInternalRowUtils.getCachedSchema(recordSchema);
StructType targetStructType = HoodieInternalRowUtils.getCachedSchema(targetSchema);

boolean containMetaFields = hasMetaFields(structType);
UTF8String[] metaFields = tryExtractMetaFields(data, structType);
// TODO HUDI-5281 Rewrite HoodieSparkRecord with UnsafeRowWriter
InternalRow rewriteRecord = HoodieInternalRowUtils.rewriteRecord(this.data, structType, targetStructType);
Comment thread
alexeykudinkin marked this conversation as resolved.
UnsafeRow unsafeRow = HoodieInternalRowUtils.getCachedUnsafeProjection(targetStructType, targetStructType).apply(rewriteRecord);

// TODO add actual rewriting
InternalRow finalRow = new HoodieInternalRow(metaFields, data, containMetaFields);
boolean containMetaFields = hasMetaFields(targetStructType);
UTF8String[] metaFields = tryExtractMetaFields(unsafeRow, targetStructType);
HoodieInternalRow internalRow = new HoodieInternalRow(metaFields, unsafeRow, containMetaFields);

return new HoodieSparkRecord(getKey(), finalRow, targetStructType, getOperation(), this.currentLocation, this.newLocation, copy);
return new HoodieSparkRecord(getKey(), internalRow, targetStructType, getOperation(), this.currentLocation, this.newLocation, false);
}

@Override
public HoodieRecord rewriteRecordWithNewSchema(Schema recordSchema, Properties props, Schema newSchema, Map<String, String> renameCols) throws IOException {
StructType structType = HoodieInternalRowUtils.getCachedSchema(recordSchema);
StructType newStructType = HoodieInternalRowUtils.getCachedSchema(newSchema);

boolean containMetaFields = hasMetaFields(structType);
UTF8String[] metaFields = tryExtractMetaFields(data, structType);
// TODO HUDI-5281 Rewrite HoodieSparkRecord with UnsafeRowWriter
InternalRow rewriteRecord = HoodieInternalRowUtils.rewriteRecordWithNewSchema(this.data, structType, newStructType, renameCols);
UnsafeRow unsafeRow = HoodieInternalRowUtils.getCachedUnsafeProjection(newStructType, newStructType).apply(rewriteRecord);

InternalRow rewrittenRow =
HoodieInternalRowUtils.rewriteRecordWithNewSchema(data, structType, newStructType, renameCols);
HoodieInternalRow finalRow = new HoodieInternalRow(metaFields, rewrittenRow, containMetaFields);
boolean containMetaFields = hasMetaFields(newStructType);
UTF8String[] metaFields = tryExtractMetaFields(unsafeRow, newStructType);
HoodieInternalRow internalRow = new HoodieInternalRow(metaFields, unsafeRow, containMetaFields);

return new HoodieSparkRecord(getKey(), finalRow, newStructType, getOperation(), this.currentLocation, this.newLocation, copy);
return new HoodieSparkRecord(getKey(), internalRow, newStructType, getOperation(), this.currentLocation, this.newLocation, false);
}

@Override
Expand Down Expand Up @@ -299,6 +301,7 @@ public HoodieRecord wrapIntoHoodieRecordPayloadWithKeyGen(Schema recordSchema, P

@Override
public Option<Map<String, String>> getMetadata() {
// TODO HUDI-5282 support metaData
return Option.empty();
}

Expand All @@ -320,7 +323,7 @@ public HoodieSparkRecord copy() {
public Comparable<?> getOrderingValue(Schema recordSchema, Properties props) {
StructType structType = HoodieInternalRowUtils.getCachedSchema(recordSchema);
String orderingField = ConfigUtils.getOrderingField(props);
if (!HoodieCatalystExpressionUtils$.MODULE$.existField(structType, orderingField)) {
if (!HoodieInternalRowUtils.existField(structType, orderingField)) {
return 0;
} else {
NestedFieldPath nestedFieldPath = HoodieInternalRowUtils.getCachedPosList(structType, orderingField);
Expand Down Expand Up @@ -377,7 +380,10 @@ private static HoodieInternalRow wrapIntoUpdatableOverlay(InternalRow data, Stru

private static UTF8String[] tryExtractMetaFields(InternalRow row, StructType structType) {
boolean containsMetaFields = hasMetaFields(structType);
if (containsMetaFields) {
if (containsMetaFields && structType.size() == 1) {
// Support bootstrap with RECORD_KEY_SCHEMA
return new UTF8String[] {row.getUTF8String(0)};
} else if (containsMetaFields) {
return HoodieRecord.HOODIE_META_COLUMNS.stream()
.map(col -> row.getUTF8String(HOODIE_META_COLUMNS_NAME_TO_POS.get(col)))
.toArray(UTF8String[]::new);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import org.apache.avro.Schema;
import org.apache.avro.generic.GenericRecord;
import org.apache.hudi.AvroConversionUtils;
import org.apache.hudi.HoodieInternalRowUtils;
import org.apache.hudi.HoodieSparkUtils;
import org.apache.hudi.SparkConversionUtils;
import org.apache.hudi.client.common.HoodieSparkEngineContext;
Expand All @@ -37,6 +36,7 @@
import org.apache.hudi.config.HoodieClusteringConfig;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.HoodieInternalRowUtils;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.types.StructType;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

package org.apache.hudi.io.storage;

import org.apache.hudi.HoodieInternalRowUtils;
import org.apache.hudi.common.bloom.BloomFilter;
import org.apache.hudi.common.config.HoodieConfig;
import org.apache.hudi.common.config.HoodieStorageConfig;
Expand All @@ -34,6 +33,7 @@
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.Path;
import org.apache.parquet.hadoop.metadata.CompressionCodecName;
import org.apache.spark.sql.HoodieInternalRowUtils;

import java.io.IOException;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import org.apache.avro.Schema;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hudi.HoodieInternalRowUtils;
import org.apache.hudi.SparkAdapterSupport$;
import org.apache.hudi.commmon.model.HoodieSparkRecord;
import org.apache.hudi.common.bloom.BloomFilter;
import org.apache.hudi.common.model.HoodieFileFormat;
Expand All @@ -30,12 +30,18 @@
import org.apache.hudi.common.util.ClosableIterator;
import org.apache.hudi.common.util.MappingIterator;
import org.apache.hudi.common.util.ParquetReaderIterator;
import org.apache.hudi.common.util.ParquetUtils;
import org.apache.hudi.common.util.StringUtils;

import org.apache.parquet.hadoop.ParquetReader;
import org.apache.parquet.hadoop.api.ReadSupport;
import org.apache.parquet.schema.MessageType;
import org.apache.spark.sql.HoodieInternalRowUtils;
import org.apache.spark.sql.catalyst.InternalRow;
import org.apache.spark.sql.catalyst.expressions.UnsafeProjection;
import org.apache.spark.sql.catalyst.expressions.UnsafeRow;
import org.apache.spark.sql.execution.datasources.parquet.ParquetReadSupport;
import org.apache.spark.sql.execution.datasources.parquet.ParquetToSparkSchemaConverter;
import org.apache.spark.sql.internal.SQLConf;
import org.apache.spark.sql.types.StructType;

Expand All @@ -45,6 +51,7 @@
import java.util.Set;

import static org.apache.hudi.common.util.TypeUtils.unsafeCast;
import static org.apache.parquet.avro.AvroSchemaConverter.ADD_LIST_ELEMENT_RECORDS;

public class HoodieSparkParquetReader implements HoodieSparkFileReader {

Expand All @@ -55,7 +62,9 @@ public class HoodieSparkParquetReader implements HoodieSparkFileReader {

public HoodieSparkParquetReader(Configuration conf, Path path) {
this.path = path;
this.conf = conf;
this.conf = new Configuration(conf);
// Avoid adding record in list element when convert parquet schema to avro schema
conf.set(ADD_LIST_ELEMENT_RECORDS, "false");
this.parquetUtils = BaseFileUtils.getInstance(HoodieFileFormat.PARQUET);
}

Expand Down Expand Up @@ -108,7 +117,13 @@ private ClosableIterator<InternalRow> getInternalRowIterator(Schema readerSchema

@Override
public Schema getSchema() {
return parquetUtils.readAvroSchema(conf, path);
// Some types in avro are not compatible with parquet.
// Avro only supports representing Decimals as fixed byte array
// and therefore if we convert to Avro directly we'll lose logical type-info.
MessageType messageType = ((ParquetUtils) parquetUtils).readSchema(conf, path);
StructType structType = new ParquetToSparkSchemaConverter(conf).convert(messageType);
Comment thread
alexeykudinkin marked this conversation as resolved.
return SparkAdapterSupport$.MODULE$.sparkAdapter().getAvroSchemaConverters()
.toAvroType(structType, true, messageType.getName(), StringUtils.EMPTY_STRING);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,10 @@ void executeBootstrap(HoodieBootstrapHandle<?, ?, ?, ?> bootstrapHandle,
wrapper = new BoundedInMemoryExecutor<HoodieRecord, HoodieRecord, Void>(config.getWriteBufferLimitBytes(),
reader.getRecordIterator(), new BootstrapRecordConsumer(bootstrapHandle), record -> {
try {
HoodieRecord recordCopy = record.copy();
String recKey = recordCopy.getRecordKey(reader.getSchema(), Option.of(keyGenerator));
HoodieRecord hoodieRecord = recordCopy.rewriteRecord(reader.getSchema(), config.getProps(), HoodieAvroUtils.RECORD_KEY_SCHEMA);
String recKey = record.getRecordKey(reader.getSchema(), Option.of(keyGenerator));
HoodieRecord hoodieRecord = record
.rewriteRecord(reader.getSchema(), config.getProps(), HoodieAvroUtils.RECORD_KEY_SCHEMA)
.copy();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above

MetadataValues metadataValues = new MetadataValues().setRecordKey(recKey);
return hoodieRecord
.updateMetadataValues(HoodieAvroUtils.RECORD_KEY_SCHEMA, new Properties(), metadataValues)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@

package org.apache.hudi.util;

import org.apache.hudi.HoodieInternalRowUtils;
import org.apache.hudi.common.util.Option;
import org.apache.hudi.common.util.StringUtils;

import org.apache.spark.sql.HoodieCatalystExpressionUtils$;
import org.apache.spark.sql.HoodieInternalRowUtils;
import org.apache.spark.sql.HoodieUnsafeRowUtils;
import org.apache.spark.sql.HoodieUnsafeRowUtils.NestedFieldPath;
import org.apache.spark.sql.catalyst.InternalRow;
Expand All @@ -43,7 +42,7 @@ public static Object getValue(StructType structType, String fieldName, InternalR
* @return the string form of the field or empty if the schema does not contain the field name or the value is null
*/
public static Option<String> getNullableValAsString(StructType structType, InternalRow row, String fieldName) {
String fieldVal = !HoodieCatalystExpressionUtils$.MODULE$.existField(structType, fieldName)
String fieldVal = !HoodieInternalRowUtils.existField(structType, fieldName)
? null : StringUtils.objToString(getValue(structType, fieldName, row));
return Option.ofNullable(fieldVal);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import org.apache.spark.sql.catalyst.expressions.{AttributeReference, Expression
import org.apache.spark.sql.catalyst.plans.logical.{LocalRelation, LogicalPlan}
import org.apache.spark.sql.sources._
import org.apache.spark.sql.types.{DataType, StructType}
import scala.annotation.tailrec

trait HoodieCatalystExpressionUtils {

Expand Down Expand Up @@ -251,10 +252,6 @@ object HoodieCatalystExpressionUtils {
)
}

def existField(structType: StructType, name: String): Boolean = {
structType.getFieldIndex(name).isDefined
}

private def hasUnresolvedRefs(resolvedExpr: Expression): Boolean =
resolvedExpr.collectFirst {
case _: UnresolvedAttribute | _: UnresolvedFunction => true
Expand Down
Loading