Skip to content

Commit c3763d3

Browse files
rzhang10shardulm94rdsryukuai518wmoustafa
committed
Rebase LI-Iceberg changes on top of Apache Iceberg 1.0.0 release
* Hive Catalog: Add a hive catalog that does not override existing Hive metadata (linkedin#10) Add custom hive catalog to not override existing Hive metadata Fail early with a proper exception if the metadata file is not existing Simplify CustomHiveCatalog (linkedin#22) * Shading: Add a iceberg-runtime shaded module (linkedin#12) * ORC: Add test for reading files without Iceberg IDs (linkedin#16) * Hive Metadata Scan: Support reading tables with only Hive metadata (linkedin#23, linkedin#24, linkedin#25, linkedin#26) - Support for non string partition columns (linkedin#24) - Support for Hive tables without avro.schema.literal (linkedin#25) - Hive Metadata Scan: Notify ScanEvent listeners on planning (linkedin#35) - Hive Metadata Scan: Do not use table snapshot summary for estimating statistics (linkedin#37) - Hive Metadata Scan: Return empty statistics (linkedin#49) - Hive Metadata Scan: Do not throw an exception on dangling partitions; log warning message (linkedin#50) - Hive Metadata Scan: Fix pushdown of non-partition predicates within NOT (linkedin#51) Co-authored-by: Ratandeep Ratti <rratti@linkedin.com> Co-authored-by: Kuai Yu <kuyu@linkedin.com> Co-authored-by: Walaa Eldin Moustafa <wmoustafa@linkedin.com> * Row level filtering: Allow table scans to pass a row level filter for ORC files - ORC: Support NameMapping with row-level filtering (linkedin#53) * Hive: Made Predicate Pushdown dynamic based on the Hive Version * Hive: Fix uppercase bug and determine catalog from table properties (linkedin#38) * Hive: Return lowercase fieldname from IcebergRecordStructField * Hive: Determine catalog from table property * Hive: Fix schema not forwarded to SerDe on MR jobs (linkedin#45) (linkedin#47) * Hive: Use Hive table location in HiveIcebergSplit * Hive: Fix schema not passed to Serde * Hive: Refactor tests for tables with unqualified location URI Co-authored-by: Shardul Mahadik <smahadik@linkedin.com> * Hive Metadata Scan: Support case insensitive name mapping (linkedin#52) * Hive Metadata Scan: Merge Hive and Avro schemas to fix datatype inconsistencies (linkedin#57) Hive Metadata Scan: Fix Hive primitive to Avro logical type conversion (linkedin#58) Hive Metadata Scan: Fix support for Hive timestamp type (linkedin#61) Co-authored-by: Raymond Zhang <razhang@linkedin.com> Co-authored-by: Shardul Mahadik <smahadik@linkedin.com> Fix HasDuplicateLowercaseColumnNames's visit method to use a new visi… (linkedin#67) * Fix HasDuplicateLowercaseColumnNames's visit method to use a new visitor instance every time * Trigger CI (cherry picked from commit b90e838) * Stop using serdeToFileFormat to unblock formats other than Avro or Orc (linkedin#64) * Stop using serdeToFileFormat to unblock formats other than Avro or Orc * Fix style check * Do not delete metadata location when HMS has been successfully updated (linkedin#68) (cherry picked from commit 766407e) * Support reading Avro complex union types (linkedin#73) Co-authored-by: Wenye Zhang <wyzhang@wyzhang-mn1.linkedin.biz> * [#2039] Support default value semantic for AVRO (linkedin#75) (cherry picked from commit c18f4c4) * Support hive non string partition cols (linkedin#78) * Support non-string hive type partition columns in LegacyHiveTableScan * Leverage eval against partition filter expression to filter non-string columns * Support default value read for ORC format in spark (linkedin#76) * Support default value read for ORC format in spark * Refactor common code for ReadBuilder for both non-vectorized and vectorized read * Fix code style issue * Add special handling of ROW_POSITION metadata column * Add corner case check for partition field * Use BaseDataReader.convertConstant to convert constants, and expand its functionality to support nested-type contants such as array/map/struct * Support nested type default value for vectorized read * Support deeply nested type default value for vectorized read * Support reading ORC complex union types (linkedin#74) * Support reading orc complex union types * add more tests * support union in VectorizedSparkOrcReaders and improve tests * support union in VectorizedSparkOrcReaders and improve tests - continued * fix checkstyle Co-authored-by: Wenye Zhang <wyzhang@wyzhang-mn1.linkedin.biz> * Support avro.schema.literal/hive union types in Hive legacy table to Iceberg conversion (linkedin#80) * Fix ORC schema visitors to support reading ORC files with deeply nest… (linkedin#81) * Fix ORC schema visitors to support reading ORC files with deeply nested union type schema * Added test for vectorized read * Disable avro validation for default values Co-authored-by: Shenoda Guirguis <sguirgui@linkedin.com> * Fix spark avro reader reading union schema data (linkedin#83) * Fix spark avro reader to read correctly structured nested data values * Make sure field-id mapping is correctly maintained given arbitrary nested schema that contains union * Avro: Change union read schema from hive to trino (linkedin#84) * [LI] Avro: Refactor union-to-struct schema - Part 1. changes to support reading Avro * ORC: Change union read schema from hive to trino (linkedin#85) * [LI] ORC: Refactor union-to-struct schema - Part 2. changes to support reading ORC * Change Hive type to Iceberg type conversion for union * Recorder hive table properties to align the avro.schema.literal placement contract (linkedin#86) * [#2039] Support default value semantic for AVRO (cherry picked from commit c18f4c4) * reverting commits 2c59857 and f362aed (linkedin#88) Co-authored-by: Shenoda Guirguis <sguirgui@sguirgui-mn1.linkedin.biz> * logically patching PR 2328 on HiveMetadataPreservingTableOperations * Support timestamp as partition type (linkedin#91) * Support timestamp in partition types * Address comment * Separate classes under hive legacy package to new hivelink module (linkedin#87) * separate class under legacy to new hiveberg module * fix build * remove hiveberg dependency in iceberg-spark2 module * Revert "remove hiveberg dependency in iceberg-spark2 module" This reverts commit 2e8b743. * rename hiveberg module to hivelink Co-authored-by: Wenye Zhang <wyzhang@wyzhang-mn1.linkedin.biz> * [LI] Align default value validation align with avro semantics in terms of nullable (nested) fields (linkedin#92) * Align default value validation align with avro semantics in terms of nullable (nested) fields * Allow setting null as default value for nested fields in record default * [LI][Spark][Avro] read avro union using decoder instead of directly returning v… (linkedin#94) * [LI][Spark] read avro union using decoder instead of directly returning value * Add a comment for the schema * Improve the logging when the deserailzed index is invalid to read the symbol from enum (linkedin#96) * Move custom hive catalog to hivelink-core (linkedin#99) * Handle non-nullable union of single type for Avro (linkedin#98) * Handle non-nullable union of single type Co-authored-by: Wenye Zhang <wyzhang@wyzhang-mn1.linkedin.biz> * Handle null default in nested type default value situations (linkedin#100) * Move 'Hive Metadata Scan: Support case insensitive name mapping' (PR 52) to hivelink-core (linkedin#102) * Remove activeSparkSession (linkedin#103) * Disable default value preserving (linkedin#106) * Disable default value preserving * [LI][Avro] Do not reorder elements inside a Avro union schema (linkedin#93) * handle single type union properly in AvroSchemaVisitor for deep nested schema (linkedin#107) * Handle non-nullable union of single type for ORC spark non-vectorized reader (linkedin#104) * Handle single type union for non-vectorized reader * [Avro] Retain the type of field while copying the default values. (linkedin#109) * Retain the type of field while copying the default values. * [Hivelink] Refactor support hive non string partition cols to rid of … (linkedin#110) * [Hivelink] Refactor support hive non string partition cols to rid of Iceberg-oss code changes * Release automation overhaul: Sonatype Nexus, Shipkit and GH Actions (linkedin#101) * Add scm and developer info (linkedin#111) * [Core] Fix and refactor schema parser (linkedin#112) * [Core] Fix/Refactor SchemaParser to fix multiple bugs * Enhance the UT for testing required fields with default values (linkedin#113) * Enhance the UT for testing required fields with default values * Addressed review comments * Addressed review comment * Support single type union for ORC-vectorization reader (linkedin#114) * Support single type union for ORC-vectorization reader * Support single type union for ORC-vectorization reader Co-authored-by: Yiqiang Ding <yiqding@yiqding-mn1.linkedin.biz> * Refactor HMS code upon cherry-pick * Check for schema corruption and fix it on commit (linkedin#117) * Check for schema corruption and fix it on commit * ORC: Handle query where select and filter only uses default value col… (linkedin#118) * ORC: Handle query where select and filter only use default value columns * Set ORC columns and fix case-sensitivity issue with schema check (linkedin#119) * Hive: Return null for currentSnapshot() (linkedin#121) * Hive: Return null for currentSnapshot() * Handle snapshots() * Fix MergeHiveSchemaWithAvro to make it copy full Avro schema attributes (linkedin#120) * Fix MergeHiveSchemaWithAvro to make it copy full Avro schema attributes * Add logic to derive partition column id from partition.column.ids pro… (linkedin#122) * Add logic to derive partition column id from partition.column.ids property * Do not push down filter to ORC for union type schema (linkedin#123) * Bug fix: MergeHiveSchemaWithAvro should retain avro properties for li… (linkedin#125) * Bug fix: MergeHiveSchemaWithAvro should retain avro properties for list and map when they are nullable * LinkedIn rebase draft * Refactor hivelink 1 * Make hivelink module test all pass * Make spark 2.4 module work * Fix mr module * Make spark 3.1 module work * Fix TestSparkMetadataColumns * Minor fix for spark 2.4 * Update default spark version to 3.1 * Update java ci to only run spark 2.4 and 3.1 * Minor fix HiveTableOperations * Adapt github CI to 0.14.x branch * Fix mr module checkstyle * Fix checkstyle for orc module * Fix spark2.4 checkstyle * Refactor catalog loading logic using CatalogUtil * Minor change to CI/release Co-authored-by: Shardul Mahadik <smahadik@linkedin.com> Co-authored-by: Ratandeep Ratti <rratti@linkedin.com> Co-authored-by: Shardul Mahadik <shardul.m@somaiya.edu> Co-authored-by: Kuai Yu <kuyu@linkedin.com> Co-authored-by: Walaa Eldin Moustafa <wmoustafa@linkedin.com> Co-authored-by: Sushant Raikar <sraikar@linkedin.com> Co-authored-by: ZihanLi58 <48699939+ZihanLi58@users.noreply.github.com> Co-authored-by: Wenye Zhang <wyzhang@linkedin.com> Co-authored-by: Wenye Zhang <wyzhang@wyzhang-mn1.linkedin.biz> Co-authored-by: Shenoda Guirguis <sguirguis@linkedin.com> Co-authored-by: Shenoda Guirguis <sguirgui@linkedin.com> Co-authored-by: Shenoda Guirguis <sguirgui@sguirgui-mn1.linkedin.biz> Co-authored-by: Lei Sun <lesun@linkedin.com> Co-authored-by: Jiefan <jiefli@linkedin.com> Co-authored-by: yiqiangin <103528904+yiqiangin@users.noreply.github.com> Co-authored-by: Malini Mahalakshmi Venkatachari <maluchari@gmail.com> Co-authored-by: Yiqiang Ding <yiqding@linkedin.com> Co-authored-by: Yiqiang Ding <yiqding@yiqding-mn1.linkedin.biz> Co-authored-by: Jack Moseley <jmoseley@linkedin.com>
1 parent e2bb9ad commit c3763d3

File tree

124 files changed

+13979
-367
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

124 files changed

+13979
-367
lines changed

.github/workflows/java-ci.yml

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ name: "Java CI"
2121
on:
2222
push:
2323
branches:
24-
- 'master'
25-
- '0.**'
26-
tags:
27-
- 'apache-iceberg-**'
24+
- 'li-1.0.x'
25+
tags-ignore: [v*] # release tags are autogenerated after a successful CI, no need to run CI against them
2826
pull_request:
27+
branches:
28+
- 'li-1.0.x'
2929
paths-ignore:
3030
- '.github/workflows/python-ci.yml'
3131
- '.github/workflows/spark-ci.yml'
@@ -53,28 +53,28 @@ jobs:
5353
runs-on: ubuntu-20.04
5454
strategy:
5555
matrix:
56-
jvm: [8, 11]
56+
jvm: [ 8, 11 ]
5757
env:
5858
SPARK_LOCAL_IP: localhost
5959
steps:
60-
- uses: actions/checkout@v3
61-
- uses: actions/setup-java@v3
62-
with:
63-
distribution: zulu
64-
java-version: ${{ matrix.jvm }}
65-
- uses: actions/cache@v3
66-
with:
67-
path: ~/.gradle/caches
68-
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
69-
restore-keys: ${{ runner.os }}-gradle
70-
- run: echo -e "$(ip addr show eth0 | grep "inet\b" | awk '{print $2}' | cut -d/ -f1)\t$(hostname -f) $(hostname -s)" | sudo tee -a /etc/hosts
71-
- run: ./gradlew check -DsparkVersions= -DhiveVersions= -DflinkVersions= -Pquick=true -x javadoc
72-
- uses: actions/upload-artifact@v3
73-
if: failure()
74-
with:
75-
name: test logs
76-
path: |
77-
**/build/testlogs
60+
- uses: actions/checkout@v3
61+
- uses: actions/setup-java@v3
62+
with:
63+
distribution: zulu
64+
java-version: ${{ matrix.jvm }}
65+
- uses: actions/cache@v3
66+
with:
67+
path: ~/.gradle/caches
68+
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
69+
restore-keys: ${{ runner.os }}-gradle
70+
- run: echo -e "$(ip addr show eth0 | grep "inet\b" | awk '{print $2}' | cut -d/ -f1)\t$(hostname -f) $(hostname -s)" | sudo tee -a /etc/hosts
71+
- run: ./gradlew check -DsparkVersions= -DhiveVersions= -DflinkVersions= -Pquick=true -x javadoc
72+
- uses: actions/upload-artifact@v3
73+
if: failure()
74+
with:
75+
name: test logs
76+
path: |
77+
**/build/testlogs
7878
7979
build-checks:
8080
runs-on: ubuntu-20.04
@@ -84,7 +84,7 @@ jobs:
8484
with:
8585
distribution: zulu
8686
java-version: 8
87-
- run: ./gradlew -DflinkVersions=1.13,1.14,1.15 -DsparkVersions=2.4,3.0,3.1,3.2,3.3 -DhiveVersions=2,3 build -x test -x javadoc -x integrationTest
87+
- run: ./gradlew -DflinkVersions=1.13,1.14,1.15 -DsparkVersions=2.4,3.1 -DhiveVersions=2,3 build -x test -x javadoc -x integrationTest
8888

8989
build-javadoc:
9090
runs-on: ubuntu-20.04
@@ -94,4 +94,32 @@ jobs:
9494
with:
9595
distribution: zulu
9696
java-version: 8
97-
- run: ./gradlew -Pquick=true javadoc
97+
- run: ./gradlew -P=true javadoc
98+
99+
release:
100+
if: ${{ github.event_name == 'push' }}
101+
runs-on: ubuntu-20.04
102+
steps:
103+
- uses: actions/checkout@v3
104+
with:
105+
fetch-depth: '0' # https://github.com/shipkit/shipkit-changelog#fetch-depth-on-ci
106+
- uses: actions/setup-java@v3
107+
with:
108+
distribution: zulu
109+
java-version: 8
110+
- run: echo -e "$(ip addr show eth0 | grep "inet\b" | awk '{print $2}' | cut -d/ -f1)\t$(hostname -f) $(hostname -s)" | sudo tee -a /etc/hosts
111+
- run: ./gradlew build -DflinkVersions= -DsparkVersions=2.4,3.1 -DhiveVersions= -Pquick=true build -x javadoc
112+
- name: Perform release
113+
# Release job, only for pushes to the main development branch
114+
if: ${{ github.event_name == 'push'
115+
&& github.ref == 'refs/heads/li-1.0.x'
116+
&& github.repository == 'linkedin/iceberg'
117+
&& !contains(toJSON(github.event.commits.*.message), '[skip release]') }}
118+
119+
run: ./gradlew -DsparkVersions=2.4,3.1 -DhiveVersions= githubRelease publishToSonatype closeAndReleaseStagingRepository
120+
env:
121+
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
122+
SONATYPE_USER: ${{secrets.SONATYPE_USER}}
123+
SONATYPE_PWD: ${{secrets.SONATYPE_PWD}}
124+
PGP_KEY: ${{secrets.PGP_KEY}}
125+
PGP_PWD: ${{secrets.PGP_PWD}}

.github/workflows/spark-ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ name: "Spark CI"
2121
on:
2222
push:
2323
branches:
24-
- 'master'
25-
- '0.**'
24+
- 'li-1.0.x'
2625
tags:
2726
- 'apache-iceberg-**'
2827
pull_request:
@@ -83,7 +82,7 @@ jobs:
8382
strategy:
8483
matrix:
8584
jvm: [8, 11]
86-
spark: ['3.0', '3.1', '3.2', '3.3']
85+
spark: ['3.1']
8786
env:
8887
SPARK_LOCAL_IP: localhost
8988
steps:
@@ -107,6 +106,7 @@ jobs:
107106
**/build/testlogs
108107
109108
spark-3x-scala-2-13-tests:
109+
if: ${{ false }}
110110
runs-on: ubuntu-20.04
111111
strategy:
112112
matrix:

api/src/main/java/org/apache/iceberg/types/PruneColumns.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,19 @@ public Type struct(Types.StructType struct, List<Type> fieldResults) {
6868
if (field.isOptional()) {
6969
selectedFields.add(
7070
Types.NestedField.optional(
71-
field.fieldId(), field.name(), projectedType, field.doc()));
71+
field.fieldId(),
72+
field.name(),
73+
projectedType,
74+
field.getDefaultValue(),
75+
field.doc()));
7276
} else {
7377
selectedFields.add(
7478
Types.NestedField.required(
75-
field.fieldId(), field.name(), projectedType, field.doc()));
79+
field.fieldId(),
80+
field.name(),
81+
projectedType,
82+
field.getDefaultValue(),
83+
field.doc()));
7684
}
7785
}
7886
}

api/src/main/java/org/apache/iceberg/types/Types.java

Lines changed: 106 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -412,42 +412,124 @@ public int hashCode() {
412412

413413
public static class NestedField implements Serializable {
414414
public static NestedField optional(int id, String name, Type type) {
415-
return new NestedField(true, id, name, type, null);
415+
return new NestedField(true, id, name, type, null, null);
416416
}
417417

418418
public static NestedField optional(int id, String name, Type type, String doc) {
419-
return new NestedField(true, id, name, type, doc);
419+
return new NestedField(true, id, name, type, null, doc);
420+
}
421+
422+
public static NestedField optional(
423+
int id, String name, Type type, Object defaultValue, String doc) {
424+
return new NestedField(true, id, name, type, defaultValue, doc);
420425
}
421426

422427
public static NestedField required(int id, String name, Type type) {
423-
return new NestedField(false, id, name, type, null);
428+
return new NestedField(false, id, name, type, null, null);
424429
}
425430

426431
public static NestedField required(int id, String name, Type type, String doc) {
427-
return new NestedField(false, id, name, type, doc);
432+
return new NestedField(false, id, name, type, null, doc);
433+
}
434+
435+
public static NestedField required(
436+
int id, String name, Type type, Object defaultValue, String doc) {
437+
return new NestedField(false, id, name, type, defaultValue, doc);
428438
}
429439

430440
public static NestedField of(int id, boolean isOptional, String name, Type type) {
431-
return new NestedField(isOptional, id, name, type, null);
441+
return new NestedField(isOptional, id, name, type, null, null);
432442
}
433443

434444
public static NestedField of(int id, boolean isOptional, String name, Type type, String doc) {
435-
return new NestedField(isOptional, id, name, type, doc);
445+
return new NestedField(isOptional, id, name, type, null, doc);
446+
}
447+
448+
public static NestedField of(
449+
int id, boolean isOptional, String name, Type type, Object defaultValue, String doc) {
450+
return new NestedField(isOptional, id, name, type, defaultValue, doc);
451+
}
452+
453+
private static void validateDefaultValue(Object defaultValue, Type type) {
454+
if (defaultValue == null) {
455+
return;
456+
}
457+
switch (type.typeId()) {
458+
case STRUCT:
459+
Preconditions.checkArgument(
460+
defaultValue instanceof Map,
461+
"defaultValue should be a Map from fields names to values, for StructType");
462+
Map<String, Object> defaultStruct = (Map<String, Object>) defaultValue;
463+
if (defaultStruct.isEmpty()) {
464+
return;
465+
}
466+
for (NestedField field : type.asStructType().fields()) {
467+
validateDefaultValue(
468+
defaultStruct.getOrDefault(field.name(), field.getDefaultValue()), field.type());
469+
}
470+
break;
471+
472+
case LIST:
473+
Preconditions.checkArgument(
474+
defaultValue instanceof List,
475+
"defaultValue should be an List of Objects, for ListType");
476+
List<Object> defaultList = (List<Object>) defaultValue;
477+
if (defaultList.size() == 0) {
478+
return;
479+
}
480+
defaultList.forEach(
481+
dv -> NestedField.validateDefaultValue(dv, type.asListType().elementField.type));
482+
break;
483+
484+
case MAP:
485+
Preconditions.checkArgument(
486+
defaultValue instanceof Map, "defaultValue should be an instance of Map for MapType");
487+
Map<Object, Object> defaultMap = (Map<Object, Object>) defaultValue;
488+
if (defaultMap.isEmpty()) {
489+
return;
490+
}
491+
for (Map.Entry<Object, Object> e : defaultMap.entrySet()) {
492+
NestedField.validateDefaultValue(e.getKey(), type.asMapType().keyField.type);
493+
NestedField.validateDefaultValue(e.getValue(), type.asMapType().valueField.type);
494+
}
495+
break;
496+
497+
case FIXED:
498+
case BINARY:
499+
Preconditions.checkArgument(
500+
defaultValue instanceof byte[],
501+
"defaultValue should be an instance of byte[] for TypeId.%s, but defaultValue.class = %s",
502+
type.typeId().name(),
503+
defaultValue.getClass().getCanonicalName());
504+
break;
505+
506+
default:
507+
Preconditions.checkArgument(
508+
type.typeId().javaClass().isInstance(defaultValue),
509+
"defaultValue should be and instance of %s for TypeId.%s, but defaultValue.class = %s",
510+
type.typeId().javaClass(),
511+
type.typeId().name(),
512+
defaultValue.getClass().getCanonicalName());
513+
}
436514
}
437515

438516
private final boolean isOptional;
439517
private final int id;
440518
private final String name;
441519
private final Type type;
520+
private final Object defaultValue;
442521
private final String doc;
443522

444-
private NestedField(boolean isOptional, int id, String name, Type type, String doc) {
523+
private NestedField(
524+
boolean isOptional, int id, String name, Type type, Object defaultValue, String doc) {
445525
Preconditions.checkNotNull(name, "Name cannot be null");
446526
Preconditions.checkNotNull(type, "Type cannot be null");
527+
validateDefaultValue(defaultValue, type);
447528
this.isOptional = isOptional;
448529
this.id = id;
449530
this.name = name;
450531
this.type = type;
532+
this.defaultValue = defaultValue;
451533
this.doc = doc;
452534
}
453535

@@ -459,7 +541,7 @@ public NestedField asOptional() {
459541
if (isOptional) {
460542
return this;
461543
}
462-
return new NestedField(true, id, name, type, doc);
544+
return new NestedField(true, id, name, type, defaultValue, doc);
463545
}
464546

465547
public boolean isRequired() {
@@ -470,7 +552,15 @@ public NestedField asRequired() {
470552
if (!isOptional) {
471553
return this;
472554
}
473-
return new NestedField(false, id, name, type, doc);
555+
return new NestedField(false, id, name, type, defaultValue, doc);
556+
}
557+
558+
public boolean hasDefaultValue() {
559+
return defaultValue != null;
560+
}
561+
562+
public Object getDefaultValue() {
563+
return defaultValue;
474564
}
475565

476566
public int fieldId() {
@@ -492,6 +582,7 @@ public String doc() {
492582
@Override
493583
public String toString() {
494584
return String.format("%d: %s: %s %s", id, name, isOptional ? "optional" : "required", type)
585+
+ (hasDefaultValue() ? ", default value: " + defaultValue + ", " : "")
495586
+ (doc != null ? " (" + doc + ")" : "");
496587
}
497588

@@ -510,6 +601,9 @@ public boolean equals(Object o) {
510601
return false;
511602
} else if (!name.equals(that.name)) {
512603
return false;
604+
} else if (!Objects.equals(defaultValue, that.defaultValue)
605+
&& !Arrays.equals((byte[]) defaultValue, (byte[]) that.defaultValue)) {
606+
return false;
513607
} else if (!Objects.equals(doc, that.doc)) {
514608
return false;
515609
}
@@ -518,7 +612,9 @@ public boolean equals(Object o) {
518612

519613
@Override
520614
public int hashCode() {
521-
return Objects.hash(NestedField.class, id, isOptional, name, type);
615+
return hasDefaultValue()
616+
? Objects.hash(NestedField.class, id, isOptional, name, type, defaultValue)
617+
: Objects.hash(NestedField.class, id, isOptional, name, type);
522618
}
523619
}
524620

@@ -736,7 +832,6 @@ public boolean equals(Object o) {
736832
} else if (!(o instanceof ListType)) {
737833
return false;
738834
}
739-
740835
ListType listType = (ListType) o;
741836
return elementField.equals(listType.elementField);
742837
}

0 commit comments

Comments
 (0)