@@ -55,10 +55,19 @@ Status ArrowSchemaValidator::ValidateSchema(const arrow::Schema& schema) {
5555
5656Status ArrowSchemaValidator::ValidateSchemaWithFieldId (const arrow::Schema& schema) {
5757 PAIMON_RETURN_NOT_OK (ValidateSchema (schema));
58- auto struct_type = arrow::struct_ (schema.fields ());
5958 std::set<int32_t > field_id_set;
60- PAIMON_RETURN_NOT_OK (
61- ValidateDataTypeWithFieldId (struct_type, /* key_value_metadata=*/ nullptr , &field_id_set));
59+ for (const auto & field : schema.fields ()) {
60+ PAIMON_ASSIGN_OR_RAISE (DataField data_field,
61+ DataField::ConvertArrowFieldToDataField (field));
62+ auto iter = field_id_set.find (data_field.Id ());
63+ if (iter != field_id_set.end ()) {
64+ return Status::Invalid (
65+ fmt::format (" field id must be unique, duplicate field id {}" , data_field.Id ()));
66+ }
67+ field_id_set.insert (data_field.Id ());
68+ PAIMON_RETURN_NOT_OK (ValidateDataTypeWithFieldId (field->type (), field->metadata (),
69+ /* allow_blob=*/ true , &field_id_set));
70+ }
6271 return Status::OK ();
6372}
6473
@@ -93,7 +102,7 @@ Status ArrowSchemaValidator::ValidateNoWhitespaceOnlyFields(const arrow::FieldVe
93102
94103Status ArrowSchemaValidator::ValidateDataTypeWithFieldId (
95104 const std::shared_ptr<arrow::DataType>& type,
96- const std::shared_ptr<const arrow::KeyValueMetadata>& key_value_metadata,
105+ const std::shared_ptr<const arrow::KeyValueMetadata>& key_value_metadata, bool allow_blob,
97106 std::set<int32_t >* field_id_set) {
98107 const auto kind = type->id ();
99108 switch (kind) {
@@ -114,7 +123,7 @@ Status ArrowSchemaValidator::ValidateDataTypeWithFieldId(
114123 const auto & value_field =
115124 arrow::internal::checked_cast<arrow::BaseListType*>(type.get ())->value_field ();
116125 PAIMON_RETURN_NOT_OK (ValidateDataTypeWithFieldId (
117- value_field->type (), value_field->metadata (), field_id_set));
126+ value_field->type (), value_field->metadata (), /* allow_blob= */ false , field_id_set));
118127 break ;
119128 }
120129 case arrow::Type::type::STRUCT : {
@@ -135,7 +144,7 @@ Status ArrowSchemaValidator::ValidateDataTypeWithFieldId(
135144 }
136145 field_id_set->insert (data_field.Id ());
137146 PAIMON_RETURN_NOT_OK (ValidateDataTypeWithFieldId (
138- sub_field->type (), sub_field->metadata (), field_id_set));
147+ sub_field->type (), sub_field->metadata (), /* allow_blob= */ false , field_id_set));
139148 }
140149 break ;
141150 }
@@ -144,14 +153,17 @@ Status ArrowSchemaValidator::ValidateDataTypeWithFieldId(
144153 arrow::internal::checked_cast<arrow::MapType*>(type.get ())->key_field ();
145154 const auto & item_field =
146155 arrow::internal::checked_cast<arrow::MapType*>(type.get ())->item_field ();
147- PAIMON_RETURN_NOT_OK (ValidateDataTypeWithFieldId (key_field-> type (),
148- key_field->metadata (), field_id_set));
149- PAIMON_RETURN_NOT_OK (ValidateDataTypeWithFieldId (item_field-> type (),
150- item_field->metadata (), field_id_set));
156+ PAIMON_RETURN_NOT_OK (ValidateDataTypeWithFieldId (
157+ key_field-> type (), key_field->metadata (), /* allow_blob= */ false , field_id_set));
158+ PAIMON_RETURN_NOT_OK (ValidateDataTypeWithFieldId (
159+ item_field-> type (), item_field->metadata (), /* allow_blob= */ false , field_id_set));
151160 break ;
152161 }
153162 case arrow::Type::type::LARGE_BINARY : {
154163 if (BlobUtils::IsBlobMetadata (key_value_metadata)) {
164+ if (!allow_blob) {
165+ return Status::Invalid (" Blob field must be a top-level field." );
166+ }
155167 break ;
156168 }
157169 [[fallthrough]] ;
@@ -164,6 +176,11 @@ Status ArrowSchemaValidator::ValidateDataTypeWithFieldId(
164176}
165177
166178Status ArrowSchemaValidator::ValidateField (const std::shared_ptr<arrow::Field>& field) {
179+ return ValidateField (field, /* allow_blob=*/ true );
180+ }
181+
182+ Status ArrowSchemaValidator::ValidateField (const std::shared_ptr<arrow::Field>& field,
183+ bool allow_blob) {
167184 const auto kind = field->type ()->id ();
168185 switch (kind) {
169186 case arrow::Type::type::BOOL :
@@ -185,7 +202,7 @@ Status ArrowSchemaValidator::ValidateField(const std::shared_ptr<arrow::Field>&
185202 const auto & value_field =
186203 arrow::internal::checked_cast<const arrow::BaseListType&>(*field->type ())
187204 .value_field ();
188- PAIMON_RETURN_NOT_OK (ValidateField (value_field));
205+ PAIMON_RETURN_NOT_OK (ValidateField (value_field, /* allow_blob= */ false ));
189206 break ;
190207 }
191208 case arrow::Type::type::STRUCT : {
@@ -202,7 +219,7 @@ Status ArrowSchemaValidator::ValidateField(const std::shared_ptr<arrow::Field>&
202219 arrow::FieldVector arrow_fields =
203220 arrow::internal::checked_cast<const arrow::StructType&>(*field->type ()).fields ();
204221 for (const auto & sub_field : arrow_fields) {
205- PAIMON_RETURN_NOT_OK (ValidateField (sub_field));
222+ PAIMON_RETURN_NOT_OK (ValidateField (sub_field, /* allow_blob= */ false ));
206223 }
207224 break ;
208225 }
@@ -211,12 +228,15 @@ Status ArrowSchemaValidator::ValidateField(const std::shared_ptr<arrow::Field>&
211228 arrow::internal::checked_cast<const arrow::MapType&>(*field->type ()).key_field ();
212229 const auto & item_field =
213230 arrow::internal::checked_cast<const arrow::MapType&>(*field->type ()).item_field ();
214- PAIMON_RETURN_NOT_OK (ValidateField (key_field));
215- PAIMON_RETURN_NOT_OK (ValidateField (item_field));
231+ PAIMON_RETURN_NOT_OK (ValidateField (key_field, /* allow_blob= */ false ));
232+ PAIMON_RETURN_NOT_OK (ValidateField (item_field, /* allow_blob= */ false ));
216233 break ;
217234 }
218235 case arrow::Type::type::LARGE_BINARY : {
219236 if (BlobUtils::IsBlobField (field)) {
237+ if (!allow_blob) {
238+ return Status::Invalid (" Blob field must be a top-level field." );
239+ }
220240 break ;
221241 }
222242 [[fallthrough]] ;
0 commit comments