@@ -419,10 +419,7 @@ impl DFSchema {
419
419
name : & str ,
420
420
) -> Result < ( Option < & TableReference > , & Field ) > {
421
421
if let Some ( qualifier) = qualifier {
422
- let idx = self
423
- . index_of_column_by_name ( Some ( qualifier) , name)
424
- . ok_or_else ( || field_not_found ( Some ( qualifier. clone ( ) ) , name, self ) ) ?;
425
- Ok ( ( self . field_qualifiers [ idx] . as_ref ( ) , self . field ( idx) ) )
422
+ self . qualified_field_with_qualified_name ( qualifier, name)
426
423
} else {
427
424
self . qualified_field_with_unqualified_name ( name)
428
425
}
@@ -467,6 +464,36 @@ impl DFSchema {
467
464
. collect ( )
468
465
}
469
466
467
+ /// Find all fields that match the given name with qualifier and return them with their qualifier
468
+ pub fn qualified_fields_with_qualified_name (
469
+ & self ,
470
+ qualifier : & TableReference ,
471
+ name : & str ,
472
+ ) -> Vec < ( Option < & TableReference > , & Field ) > {
473
+ self . iter ( )
474
+ . filter ( |( q, f) | match ( qualifier, q) {
475
+ // field to lookup is qualified.
476
+ // current field is qualified and not shared between relations, compare both
477
+ // qualifier and name.
478
+ ( q, Some ( field_q) ) => q. resolved_eq ( field_q) && f. name ( ) == name,
479
+ // field to lookup is qualified but current field is unqualified.
480
+ ( qq, None ) => {
481
+ // the original field may now be aliased with a name that matches the
482
+ // original qualified name
483
+ let column = Column :: from_qualified_name ( f. name ( ) ) ;
484
+ match column {
485
+ Column {
486
+ relation : Some ( r) ,
487
+ name : column_name,
488
+ } => & r == qq && column_name == name,
489
+ _ => false ,
490
+ }
491
+ }
492
+ } )
493
+ . map ( |( qualifier, field) | ( qualifier, field. as_ref ( ) ) )
494
+ . collect ( )
495
+ }
496
+
470
497
/// Find all fields that match the given name and convert to column
471
498
pub fn columns_with_unqualified_name ( & self , name : & str ) -> Vec < Column > {
472
499
self . iter ( )
@@ -519,6 +546,35 @@ impl DFSchema {
519
546
}
520
547
}
521
548
549
+ /// Find the qualified field with the given qualified name
550
+ pub fn qualified_field_with_qualified_name (
551
+ & self ,
552
+ qualifier : & TableReference ,
553
+ name : & str ,
554
+ ) -> Result < ( Option < & TableReference > , & Field ) > {
555
+ let matches = self . qualified_fields_with_qualified_name ( qualifier, name) ;
556
+ match matches. len ( ) {
557
+ 0 => Err ( field_not_found ( Some ( qualifier. clone ( ) ) , name, self ) ) ,
558
+ 1 => Ok ( ( matches[ 0 ] . 0 , ( matches[ 0 ] . 1 ) ) ) ,
559
+ _ => {
560
+ let fields_with_qualifier = matches
561
+ . iter ( )
562
+ . filter ( |( q, _) | q. is_some ( ) )
563
+ . collect :: < Vec < _ > > ( ) ;
564
+ if fields_with_qualifier. len ( ) == 1 {
565
+ Ok ( ( fields_with_qualifier[ 0 ] . 0 , fields_with_qualifier[ 0 ] . 1 ) )
566
+ } else {
567
+ _schema_err ! ( SchemaError :: AmbiguousReference {
568
+ field: Column {
569
+ relation: None ,
570
+ name: name. to_string( ) ,
571
+ } ,
572
+ } )
573
+ }
574
+ }
575
+ }
576
+ }
577
+
522
578
/// Find the field with the given name
523
579
pub fn field_with_unqualified_name ( & self , name : & str ) -> Result < & Field > {
524
580
self . qualified_field_with_unqualified_name ( name)
0 commit comments