1- use std:: collections:: HashMap ;
1+ use std:: collections:: { HashMap , HashSet } ;
22
3- use crate :: { config:: config_enums:: DbType , error:: Error , meta:: ddl_meta:: ddl_data:: DdlData } ;
3+ use crate :: {
4+ config:: config_enums:: DbType ,
5+ error:: Error ,
6+ meta:: { ddl_meta:: ddl_data:: DdlData , rdb_meta_manager:: RDB_PRIMARY_KEY_FLAG } ,
7+ } ;
48use anyhow:: { bail, Ok } ;
59use futures:: TryStreamExt ;
610
@@ -82,11 +86,11 @@ impl MysqlMetaFetcher {
8286 ) -> anyhow:: Result < & ' a MysqlTbMeta > {
8387 let full_name = format ! ( "{}.{}" , schema, tb) ;
8488 if !self . cache . contains_key ( & full_name) {
85- let ( cols, col_origin_type_map, col_type_map) =
89+ let ( cols, col_origin_type_map, col_type_map, nullable_cols ) =
8690 Self :: parse_cols ( & self . conn_pool , & self . db_type , schema, tb) . await ?;
8791 let key_map = Self :: parse_keys ( & self . conn_pool , schema, tb) . await ?;
88- let ( order_col , partition_col, id_cols) =
89- RdbMetaManager :: parse_rdb_cols ( & key_map, & cols) ?;
92+ let ( order_cols , partition_col, id_cols) =
93+ RdbMetaManager :: parse_rdb_cols ( & key_map, & cols, & nullable_cols ) ?;
9094 // disable get_foreign_keys since we don't support foreign key check,
9195 // also querying them is very slow, which may cause terrible performance issue if there were many tables in a CDC task.
9296 let ( foreign_keys, ref_by_foreign_keys) = ( vec ! [ ] , vec ! [ ] ) ;
@@ -96,10 +100,12 @@ impl MysqlMetaFetcher {
96100 let basic = RdbTbMeta {
97101 schema : schema. to_string ( ) ,
98102 tb : tb. to_string ( ) ,
103+ order_cols_are_nullable : order_cols. iter ( ) . any ( |col| nullable_cols. contains ( col) ) ,
99104 cols,
105+ nullable_cols,
100106 col_origin_type_map,
101107 key_map,
102- order_col ,
108+ order_cols ,
103109 partition_col,
104110 id_cols,
105111 foreign_keys,
@@ -123,10 +129,12 @@ impl MysqlMetaFetcher {
123129 Vec < String > ,
124130 HashMap < String , String > ,
125131 HashMap < String , MysqlColType > ,
132+ HashSet < String > ,
126133 ) > {
127134 let mut cols = Vec :: new ( ) ;
128135 let mut col_origin_type_map = HashMap :: new ( ) ;
129136 let mut col_type_map = HashMap :: new ( ) ;
137+ let mut nullable_cols = HashSet :: new ( ) ;
130138
131139 let sql = if matches ! ( db_type, DbType :: Mysql ) {
132140 "SELECT * FROM information_schema.columns
@@ -153,7 +161,12 @@ impl MysqlMetaFetcher {
153161 cols. push ( col. clone ( ) ) ;
154162 let ( origin_type, col_type) = Self :: get_col_type ( & row) . await ?;
155163 col_origin_type_map. insert ( col. clone ( ) , origin_type) ;
156- col_type_map. insert ( col, col_type) ;
164+ col_type_map. insert ( col. clone ( ) , col_type) ;
165+
166+ let is_nullable = row. try_get :: < String , _ > ( IS_NULLABLE ) ?. to_lowercase ( ) == "yes" ;
167+ if is_nullable {
168+ nullable_cols. insert ( col) ;
169+ }
157170 }
158171
159172 if cols. is_empty ( ) {
@@ -162,7 +175,7 @@ impl MysqlMetaFetcher {
162175 schema, tb
163176 ) ) }
164177 }
165- Ok ( ( cols, col_origin_type_map, col_type_map) )
178+ Ok ( ( cols, col_origin_type_map, col_type_map, nullable_cols ) )
166179 }
167180
168181 async fn get_col_type ( row : & MySqlRow ) -> anyhow:: Result < ( String , MysqlColType ) > {
@@ -338,7 +351,10 @@ impl MysqlMetaFetcher {
338351 // | a | 0 | PRIMARY | 2 | value | A | 0 | NULL | NULL | | BTREE | | |
339352 // | a | 0 | some_uk_name | 1 | value | A | 0 | NULL | NULL | | BTREE | | |
340353 // +-------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
341- let key_name: String = row. try_get ( "Key_name" ) ?;
354+ let mut key_name: String = row. try_get ( "Key_name" ) ?;
355+ if key_name == "PRIMARY" {
356+ key_name = RDB_PRIMARY_KEY_FLAG . to_string ( ) ;
357+ }
342358 let col_name: String = row. try_get ( "Column_name" ) ?;
343359 if let Some ( key_cols) = key_map. get_mut ( & key_name) {
344360 key_cols. push ( col_name) ;
0 commit comments