@@ -78,7 +78,7 @@ impl MySqlTableDesc {
7878 pub fn determine_compatibility (
7979 & self ,
8080 other : & MySqlTableDesc ,
81- full_metadata : bool ,
81+ binlog_full_metadata : bool ,
8282 ) -> Result < ( ) , anyhow:: Error > {
8383 if self == other {
8484 return Ok ( ( ) ) ;
@@ -95,28 +95,41 @@ impl MySqlTableDesc {
9595 }
9696
9797 // In the case that we don't have full binlog row metadata, `columns` is ordered by the
98- // ordinal_position of each column in the table, so as long as `self.columns` is a
98+ // ordinal position of each column in the table, so as long as `self.columns` is a
9999 // compatible prefix of `other.columns`, we can ignore extra columns from `other.columns`.
100100 //
101101 // If we do have full metadata, then we can match columns by name and just check that all
102102 // columns in `self.columns` are present and compatible with columns in `other.columns`.
103- let mut other_columns = other. columns . iter ( ) ;
104- for self_column in self . columns . iter ( ) {
105- let other_column = if full_metadata {
106- if self_column. column_type . is_none ( ) {
107- // This is an excluded column and can be ignored, as it may not have a
108- // corresponding column in `other.columns` if the column was dropped upstream.
109- continue ;
110- }
111- other. columns . iter ( ) . find ( |c| c. name == self_column. name )
112- } else {
113- other_columns. next ( )
114- } ;
103+ for ( i, self_column) in self . columns . iter ( ) . enumerate ( ) {
115104 if self_column. column_type . is_none ( ) {
116105 // This is an excluded column and can be ignored.
117106 continue ;
118107 }
119- let other_column = other_column. ok_or_else ( || {
108+ let wire_idx = if !binlog_full_metadata {
109+ // No column name metadata, so we match by index.
110+ ( i < other. columns . len ( ) ) . then_some ( i)
111+ } else {
112+ // This means the row from the binlog has column name included in the metadata,
113+ // so we can match on that instead of position.
114+ other
115+ . columns
116+ . iter ( )
117+ . position ( |oc| oc. name . as_str ( ) == self_column. name . as_str ( ) )
118+ } ;
119+
120+ let wire_idx = match wire_idx {
121+ Some ( idx) => idx,
122+ None => {
123+ // We could not find a column in the incoming row that matches this descriptor column.
124+ // This is an error as the column is not ignored (ignored columns have already been skipped).
125+ return Err ( anyhow:: anyhow!(
126+ "column {} no longer present in table {}" ,
127+ self_column. name,
128+ self . name
129+ ) ) ;
130+ }
131+ } ;
132+ let other_column = other. columns . get ( wire_idx) . ok_or_else ( || {
120133 anyhow:: anyhow!(
121134 "column {} no longer present in table {}" ,
122135 self_column. name,
0 commit comments