@@ -447,45 +447,56 @@ public static PartitionData toPartitionData(StructLike sourceKey, Types.StructTy
447447 public static Expression generateExpressionFromPartitionSpec (Table table , Map <String , String > partitionSpec ,
448448 boolean latestSpecOnly ) throws SemanticException {
449449
450- Map <String , PartitionField > partitionFieldsByName = getPartitionFields (table , latestSpecOnly ).stream ()
451- .collect (Collectors .toMap (
452- partitionField -> table .schema ().findColumnName (partitionField .sourceId ()),
453- Function .identity ())
450+ // Group partition fields by source column name to handle partition evolution
451+ // where the same source column may have multiple transforms across different specs
452+ Map <String , List <PartitionField >> partitionFieldsBySourceName = getPartitionFields (table , latestSpecOnly ).stream ()
453+ .collect (Collectors .groupingBy (
454+ partitionField -> table .schema ().findColumnName (partitionField .sourceId ()))
454455 );
455456
456457 Expression predicate = Expressions .alwaysTrue ();
457458
458459 for (Map .Entry <String , String > entry : partitionSpec .entrySet ()) {
459460 String partitionColumn = entry .getKey ();
460- PartitionField partitionField = partitionFieldsByName .get (partitionColumn );
461+ List < PartitionField > partitionFields = partitionFieldsBySourceName .get (partitionColumn );
461462
462- if (partitionField == null ) {
463+ if (partitionFields == null || partitionFields . isEmpty () ) {
463464 throw new SemanticException (String .format ("No partition column by the name: %s" , partitionColumn ));
464465 }
465- Types .NestedField sourceField = table .schema ().findField (partitionField .sourceId ());
466- Object sourceValue = Conversions .fromPartitionString (sourceField .type (), entry .getValue ());
467- // Apply the transform to the source value
468- @ SuppressWarnings ("unchecked" )
469- Transform <Object , Object > transform = (Transform <Object , Object >) partitionField .transform ();
470- Object transformedValue = transform .bind (sourceField .type ()).apply (sourceValue );
471-
472- TransformSpec transformSpec = TransformSpec .fromString (transform .toString ().toUpperCase (), sourceField .name ());
473- UnboundTerm <Object > term = SchemaUtils .toTerm (transformSpec );
474-
475- predicate = Expressions .and (
476- predicate , Expressions .equal (term , transformedValue ));
466+
467+ // When there are multiple partition fields for the same source column (due to partition evolution),
468+ // create an OR expression that matches any of the transforms
469+ Expression columnPredicate = Expressions .alwaysFalse ();
470+
471+ for (PartitionField partitionField : partitionFields ) {
472+ Types .NestedField sourceField = table .schema ().findField (partitionField .sourceId ());
473+ Object sourceValue = Conversions .fromPartitionString (sourceField .type (), entry .getValue ());
474+ // Apply the transform to the source value
475+ @ SuppressWarnings ("unchecked" )
476+ Transform <Object , Object > transform = (Transform <Object , Object >) partitionField .transform ();
477+ Object transformedValue = transform .bind (sourceField .type ()).apply (sourceValue );
478+
479+ TransformSpec transformSpec = TransformSpec .fromString (transform .toString ().toUpperCase (), sourceField .name ());
480+ UnboundTerm <Object > term = SchemaUtils .toTerm (transformSpec );
481+
482+ columnPredicate = Expressions .or (
483+ columnPredicate , Expressions .equal (term , transformedValue ));
484+ }
485+
486+ predicate = Expressions .and (predicate , columnPredicate );
477487 }
478488
479489 return predicate ;
480490 }
481491
482492 public static List <PartitionField > getPartitionFields (Table table , boolean latestSpecOnly ) {
483- return latestSpecOnly ? table .spec ().fields () :
484- table .specs ().values ().stream ()
485- .flatMap (spec -> spec .fields ().stream ()
486- .filter (f -> !f .transform ().isVoid ()))
487- .distinct ()
488- .collect (Collectors .toList ());
493+ if (latestSpecOnly ) {
494+ return table .spec ().fields ();
495+ }
496+ return table .specs ().values ().stream ()
497+ .flatMap (spec -> spec .fields ().stream ())
498+ .filter (f -> !f .transform ().isVoid ())
499+ .toList ();
489500 }
490501
491502 public static Partition getPartition (Configuration conf ,
@@ -499,6 +510,7 @@ public static Partition getPartition(Configuration conf,
499510 }
500511
501512 try {
513+ // Use the actual partition path (with transforms) as the partition name
502514 String partitionName = partitionNames .getFirst ();
503515 if (partitionSpec .size () != Warehouse .makeSpecFromName (partitionName ).size ()) {
504516 return null ;
0 commit comments