@@ -647,15 +647,13 @@ impl CreateIndex {
647647 }
648648
649649 pub fn fields_exist_in_dest ( & self , dest_table : & Table ) -> bool {
650- fn column_exists < ' a > ( it : & mut impl Iterator < Item = & ' a str > , column_name : & str ) -> bool {
651- it. any ( |c| * c == * column_name)
650+ fn column_exists ( dest_table : & Table , column_name : & str ) -> bool {
651+ dest_table
652+ . columns
653+ . iter ( )
654+ . any ( |c| c. name . as_str ( ) == column_name)
652655 }
653656
654- fn some_column_contained < ' a > ( expr : & str , it : & mut impl Iterator < Item = & ' a str > ) -> bool {
655- it. any ( |c| expr. contains ( c) )
656- }
657-
658- let cols = & mut dest_table. columns . iter ( ) . map ( |i| i. name . as_str ( ) ) ;
659657 match self {
660658 CreateIndex :: Unknown { defn : _ } => return true ,
661659 CreateIndex :: Parsed {
@@ -665,12 +663,12 @@ impl CreateIndex {
665663 for c in parsed_cols {
666664 match c {
667665 Expr :: Column ( column_name) => {
668- if !column_exists ( cols , column_name) {
666+ if !column_exists ( dest_table , column_name) {
669667 return false ;
670668 }
671669 }
672670 Expr :: Prefix ( column_name, _) => {
673- if !column_exists ( cols , column_name) {
671+ if !column_exists ( dest_table , column_name) {
674672 return false ;
675673 }
676674 }
@@ -686,18 +684,15 @@ impl CreateIndex {
686684 }
687685 }
688686 Expr :: Unknown ( expression) => {
689- if some_column_contained (
690- expression,
691- & mut ( vec ! [ "block_range" ] ) . into_iter ( ) ,
692- ) && dest_table. immutable
693- {
687+ if expression. contains ( "block_range" ) && dest_table. immutable {
694688 return false ;
695689 }
696- if !some_column_contained ( expression, cols)
697- && !some_column_contained (
698- expression,
699- & mut ( vec ! [ "block_range" , "vid" ] ) . into_iter ( ) ,
700- )
690+ if !dest_table
691+ . columns
692+ . iter ( )
693+ . any ( |c| expression. contains ( c. name . as_str ( ) ) )
694+ && !expression. contains ( "block_range" )
695+ && !expression. contains ( "vid" )
701696 {
702697 return false ;
703698 }
@@ -1155,3 +1150,62 @@ fn parse() {
11551150 } ;
11561151 parse_one ( sql, exp) ;
11571152}
1153+
1154+ #[ cfg( test) ]
1155+ fn test_layout ( gql : & str ) -> Layout {
1156+ use std:: collections:: BTreeSet ;
1157+ use std:: sync:: Arc ;
1158+
1159+ use graph:: prelude:: DeploymentHash ;
1160+ use graph:: schema:: InputSchema ;
1161+
1162+ use crate :: layout_for_tests:: { make_dummy_site, Namespace } ;
1163+ use crate :: relational:: Catalog ;
1164+
1165+ let subgraph = DeploymentHash :: new ( "subgraph" ) . unwrap ( ) ;
1166+ let schema = InputSchema :: parse_latest ( gql, subgraph. clone ( ) ) . expect ( "Test schema invalid" ) ;
1167+ let namespace = Namespace :: new ( "sgd0815" . to_owned ( ) ) . unwrap ( ) ;
1168+ let site = Arc :: new ( make_dummy_site ( subgraph, namespace, "anet" . to_string ( ) ) ) ;
1169+ let catalog =
1170+ Catalog :: for_tests ( site. clone ( ) , BTreeSet :: new ( ) ) . expect ( "Can not create catalog" ) ;
1171+ Layout :: new ( site, & schema, catalog) . expect ( "Failed to construct Layout" )
1172+ }
1173+
1174+ #[ test]
1175+ fn fields_exist_in_dest_out_of_order ( ) {
1176+ let gql = "type Thing @entity {
1177+ id: Bytes!
1178+ early: String!
1179+ mid: String!
1180+ late: String!
1181+ }" ;
1182+ let layout = test_layout ( gql) ;
1183+ let table = layout
1184+ . table_for_entity ( & layout. input_schema . entity_type ( "Thing" ) . unwrap ( ) )
1185+ . unwrap ( ) ;
1186+
1187+ // Index references columns in reverse order vs the table definition.
1188+ // Table columns: id, early, mid, late
1189+ // Index columns: late, mid, early
1190+ // The consuming iterator finds 'late', advances past 'mid' and 'early',
1191+ // then can't find 'mid' because the iterator is already past it.
1192+ let index = CreateIndex :: Parsed {
1193+ unique : false ,
1194+ name : "test_reverse" . to_string ( ) ,
1195+ nsp : "sgd0815" . to_string ( ) ,
1196+ table : "thing" . to_string ( ) ,
1197+ method : Method :: BTree ,
1198+ columns : vec ! [
1199+ Expr :: Column ( "late" . to_string( ) ) ,
1200+ Expr :: Column ( "mid" . to_string( ) ) ,
1201+ Expr :: Column ( "early" . to_string( ) ) ,
1202+ ] ,
1203+ cond : None ,
1204+ with : None ,
1205+ } ;
1206+
1207+ assert ! (
1208+ index. fields_exist_in_dest( table) ,
1209+ "index columns exist in table regardless of order"
1210+ ) ;
1211+ }
0 commit comments