Skip to content

Commit 0fff72f

Browse files
committed
Make VariantLogicalType singleton
1 parent 93ad5ca commit 0fff72f

File tree

3 files changed

+56
-6
lines changed

3 files changed

+56
-6
lines changed

hudi-common/src/main/java/org/apache/hudi/common/schema/HoodieSchema.java

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ public static HoodieSchema fromAvroSchema(Schema avroSchema) {
128128
} else if (logicalType instanceof LogicalTypes.TimestampMillis || logicalType instanceof LogicalTypes.TimestampMicros
129129
|| logicalType instanceof LogicalTypes.LocalTimestampMillis || logicalType instanceof LogicalTypes.LocalTimestampMicros) {
130130
return new HoodieSchema.Timestamp(avroSchema);
131-
} else if (logicalType instanceof VariantLogicalType) {
131+
} else if (logicalType == VariantLogicalType.variant()) {
132132
return new HoodieSchema.Variant(avroSchema);
133133
}
134134
}
@@ -531,7 +531,7 @@ public static HoodieSchema.Variant createVariant(String name, String namespace,
531531
recordSchema.setFields(avroFields);
532532

533533
// Add Variant logical type
534-
new VariantLogicalType().addToSchema(recordSchema);
534+
VariantLogicalType.variant().addToSchema(recordSchema);
535535

536536
return new HoodieSchema.Variant(recordSchema);
537537
}
@@ -594,7 +594,7 @@ public static HoodieSchema.Variant createVariantShredded(String name, String nam
594594
recordSchema.setFields(avroFields);
595595

596596
// Add Variant logical type
597-
new VariantLogicalType().addToSchema(recordSchema);
597+
VariantLogicalType.variant().addToSchema(recordSchema);
598598

599599
return new HoodieSchema.Variant(recordSchema);
600600
}
@@ -1479,15 +1479,28 @@ public enum TimePrecision {
14791479
/**
14801480
* Custom Avro LogicalType for Variant.
14811481
* This logical type is applied to RECORD schemas that represent Variant types.
1482+
*
1483+
* <p>This is a singleton type - use {@link #variant()} to get the instance.</p>
14821484
*/
14831485
public static class VariantLogicalType extends LogicalType {
14841486

14851487
private static final String VARIANT_LOGICAL_TYPE_NAME = "variant";
1488+
// Eager initialization of singleton
1489+
private static final VariantLogicalType INSTANCE = new VariantLogicalType();
14861490

1487-
public VariantLogicalType() {
1491+
private VariantLogicalType() {
14881492
super(VariantLogicalType.VARIANT_LOGICAL_TYPE_NAME);
14891493
}
14901494

1495+
/**
1496+
* Returns the singleton instance of VariantLogicalType.
1497+
*
1498+
* @return the Variant logical type instance
1499+
*/
1500+
public static VariantLogicalType variant() {
1501+
return INSTANCE;
1502+
}
1503+
14911504
@Override
14921505
public void validate(Schema schema) {
14931506
super.validate(schema);
@@ -1503,7 +1516,7 @@ public void validate(Schema schema) {
15031516
private static class VariantLogicalTypeFactory implements LogicalTypes.LogicalTypeFactory {
15041517
@Override
15051518
public LogicalType fromSchema(Schema schema) {
1506-
return new VariantLogicalType();
1519+
return VariantLogicalType.variant();
15071520
}
15081521

15091522
@Override

hudi-common/src/test/java/org/apache/hudi/common/schema/TestHoodieSchema.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.apache.hudi.exception.HoodieAvroSchemaException;
2323

2424
import org.apache.avro.JsonProperties;
25+
import org.apache.avro.LogicalType;
2526
import org.apache.avro.LogicalTypes;
2627
import org.apache.avro.Schema;
2728
import org.junit.jupiter.api.Test;
@@ -1529,4 +1530,40 @@ public void testVariantCustomNameAndNamespace() {
15291530
assertTrue(HoodieSchema.Variant.isVariantSchema(customVariant.getAvroSchema()));
15301531
assertEquals(HoodieSchemaType.VARIANT, customVariant.getType());
15311532
}
1533+
1534+
@Test
1535+
public void testVariantLogicalTypeSingleton() {
1536+
// Test that VariantLogicalType is a true singleton
1537+
HoodieSchema.VariantLogicalType instance1 = HoodieSchema.VariantLogicalType.variant();
1538+
HoodieSchema.VariantLogicalType instance2 = HoodieSchema.VariantLogicalType.variant();
1539+
1540+
// Verify they are the exact same instance (reference equality)
1541+
assertSame(instance1, instance2);
1542+
assertTrue(instance1 == instance2);
1543+
1544+
// Verify same identity hash
1545+
assertEquals(System.identityHashCode(instance1), System.identityHashCode(instance2));
1546+
1547+
// Verify same object hash
1548+
assertEquals(instance1.hashCode(), instance2.hashCode());
1549+
1550+
// Verify the singleton is used in variant schemas
1551+
HoodieSchema.Variant variant1 = HoodieSchema.createVariant();
1552+
HoodieSchema.Variant variant2 = HoodieSchema.createVariant();
1553+
1554+
LogicalType logicalType1 = variant1.getAvroSchema().getLogicalType();
1555+
LogicalType logicalType2 = variant2.getAvroSchema().getLogicalType();
1556+
1557+
// Both should reference the same singleton instance
1558+
assertSame(logicalType1, logicalType2);
1559+
assertTrue(logicalType1 == logicalType2);
1560+
assertEquals(HoodieSchema.VariantLogicalType.variant(), logicalType1);
1561+
1562+
// Verify reference equality check works in fromAvroSchema
1563+
HoodieSchema parsedSchema = HoodieSchema.fromAvroSchema(variant1.getAvroSchema());
1564+
assertInstanceOf(HoodieSchema.Variant.class, parsedSchema);
1565+
1566+
// Verify the logical type name
1567+
assertEquals("variant", instance1.getName());
1568+
}
15321569
}

hudi-spark-datasource/hudi-spark/src/test/scala/org/apache/spark/sql/hudi/feature/index/TestExpressionIndex.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ class TestExpressionIndex extends HoodieSparkSqlTestBase with SparkAdapterSuppor
159159
}
160160

161161
test("Test Create Expression Index Syntax") {
162-
withTempDir { tmp =>
162+
withTempDir { tmp =>2
163163
Seq("cow", "mor").foreach { tableType =>
164164
val databaseName = "default"
165165
val tableName = generateTableName

0 commit comments

Comments
 (0)