@@ -229,7 +229,18 @@ std::shared_ptr<::arrow::Field> updateFieldNameRecursive(
229229 arrowMapType->item_field (), *mapType.valueType ());
230230 return newField->WithType (
231231 ::arrow::map (newKeyField->type (), newValueField->type()));
232- } else if (name != " " ) {
232+ } else if (type.isDecimal()) {
233+ // Parquet type is set from the column type rather than inferred from the
234+ // field data.
235+ auto precisionScale = getDecimalPrecisionScale (type);
236+ if (!name.empty ()) {
237+ auto newField = field->WithName (name);
238+ return newField->WithType (
239+ ::arrow::decimal (precisionScale.first, precisionScale.second));
240+ }
241+ return field->WithType (
242+ ::arrow::decimal (precisionScale.first, precisionScale.second));
243+ } else if (!name.empty ()) {
233244 return field->WithName (name);
234245 } else {
235246 return field;
@@ -318,6 +329,72 @@ std::optional<std::string> getParquetCreatedBy(
318329 return std::nullopt ;
319330}
320331
332+ bool equivalentWithSimilarDecimal (
333+ const Type& dataType,
334+ const Type& schemaType) {
335+ if (!(typeid (dataType) == typeid (schemaType))) {
336+ return false ;
337+ }
338+ if (schemaType.isRow ()) {
339+ const auto & schemaTyped = schemaType.asRow ();
340+ if (schemaTyped.size () != dataType.size ()) {
341+ return false ;
342+ }
343+ for (size_t i = 0 ; i < dataType.size (); ++i) {
344+ if (schemaTyped.childAt (i)->isDecimal ()) {
345+ auto presicisonScaleSchema =
346+ getDecimalPrecisionScale (*schemaTyped.childAt (i));
347+ auto precisionScaleData =
348+ getDecimalPrecisionScale (*dataType.childAt (i));
349+ // Table precision can be larger than or equal to the inserted data, but
350+ // the scale must be the same.
351+ if (presicisonScaleSchema.first < precisionScaleData.first ||
352+ presicisonScaleSchema.second != precisionScaleData.second ) {
353+ return false ;
354+ }
355+ } else if (!equivalentWithSimilarDecimal (
356+ *dataType.childAt (i), *schemaTyped.childAt (i))) {
357+ return false ;
358+ }
359+ }
360+ } else if (schemaType.isArray ()) {
361+ const auto & schemaTyped = schemaType.asArray ();
362+ const auto & dataTyped = dataType.asArray ();
363+ if (schemaTyped.childAt (0 )->isDecimal ()) {
364+ auto presicisonScaleSchema =
365+ getDecimalPrecisionScale (*schemaTyped.childAt (0 ));
366+ auto precisionScaleData = getDecimalPrecisionScale (*dataType.childAt (0 ));
367+ if (presicisonScaleSchema.first < precisionScaleData.first ||
368+ presicisonScaleSchema.second != precisionScaleData.second ) {
369+ return false ;
370+ }
371+ }
372+ return equivalentWithSimilarDecimal (
373+ *dataTyped.elementType (), *schemaTyped.elementType ());
374+ } else if (schemaType.isMap ()) {
375+ auto & schemaTyped = schemaType.asMap ();
376+ auto & dataTyped = dataType.asMap ();
377+ return equivalentWithSimilarDecimal (
378+ *dataTyped.keyType (), *schemaTyped.keyType ()) &&
379+ equivalentWithSimilarDecimal (
380+ *dataTyped.valueType (), *schemaTyped.valueType ());
381+ } else if (schemaType.isFunction ()) {
382+ auto & schemaTyped = schemaType.asFunction ();
383+ auto & dataTyped = dataType.asFunction ();
384+ if (dataTyped.size () != schemaTyped.size ()) {
385+ return false ;
386+ }
387+ for (auto i = 0 ; i < schemaTyped.size (); ++i) {
388+ if (!equivalentWithSimilarDecimal (
389+ *dataTyped.childAt (i), *schemaTyped.childAt (i))) {
390+ return false ;
391+ }
392+ }
393+ return true ;
394+ }
395+ return true ;
396+ }
397+
321398} // namespace
322399
323400Writer::Writer (
@@ -425,7 +502,7 @@ dwio::common::StripeProgress getStripeProgress(
425502 */
426503void Writer::write (const VectorPtr& data) {
427504 VELOX_USER_CHECK (
428- data->type ()-> equivalent ( *schema_),
505+ equivalentWithSimilarDecimal (* data->type (), *schema_),
429506 " The file schema type should be equal with the input rowvector type." );
430507
431508 VectorPtr exportData = data;
0 commit comments