@@ -520,7 +520,7 @@ func getSchemaID(tableMap map[int64]*BasicTableInfo, tableID int64) int64 {
520520// schemaName should be "Name.O"
521521func findSchemaIDByName (databaseMap map [int64 ]* BasicDatabaseInfo , schemaName string ) (int64 , bool ) {
522522 for id , info := range databaseMap {
523- if info .Name == schemaName {
523+ if strings . EqualFold ( info .Name , schemaName ) {
524524 return id , true
525525 }
526526 }
@@ -530,7 +530,7 @@ func findSchemaIDByName(databaseMap map[int64]*BasicDatabaseInfo, schemaName str
530530// tableName should be "Name.O"
531531func findTableIDByName (tableMap map [int64 ]* BasicTableInfo , schemaID int64 , tableName string ) (int64 , bool ) {
532532 for id , info := range tableMap {
533- if info .SchemaID == schemaID && info .Name == tableName {
533+ if info .SchemaID == schemaID && strings . EqualFold ( info .Name , tableName ) {
534534 return id , true
535535 }
536536 }
@@ -600,7 +600,7 @@ func buildPersistedDDLEventForDropView(args buildPersistedDDLEventFuncArgs) Pers
600600 // We don't store the relationship: view_id -> table_name, get table name from args.job
601601 event .TableName = args .job .TableName
602602 // The query in job maybe "DROP VIEW test1.view1, test2.view2", we need rebuild it here.
603- event .Query = fmt .Sprintf ("DROP VIEW `%s`.`%s` " , event .SchemaName , event .TableName )
603+ event .Query = fmt .Sprintf ("DROP VIEW %s " , common . QuoteSchema ( event .SchemaName , event .TableName ) )
604604 return event
605605}
606606
@@ -662,7 +662,7 @@ func buildPersistedDDLEventForDropTable(args buildPersistedDDLEventFuncArgs) Per
662662 event .SchemaName = getSchemaName (args .databaseMap , event .SchemaID )
663663 event .TableName = getTableName (args .tableMap , event .TableID )
664664 // The query in job maybe "DROP TABLE test1.table1, test2.table2", we need rebuild it here.
665- event .Query = fmt .Sprintf ("DROP TABLE `%s`.`%s` " , event .SchemaName , event .TableName )
665+ event .Query = fmt .Sprintf ("DROP TABLE %s " , common . QuoteSchema ( event .SchemaName , event .TableName ) )
666666 return event
667667}
668668
@@ -723,6 +723,11 @@ func buildPersistedDDLEventForRenameTable(args buildPersistedDDLEventFuncArgs) P
723723 //
724724 // InvolvingSchemaInfo returns the schema info involved in the job.
725725 // The value should be stored in lower case.
726+ //
727+ // InvolvingSchemaInfo may store normalized lower-case names,
728+ // while the original query can keep user-provided identifier case.
729+ // Prefer names parsed from the original query whenever possible.
730+ // See https://github.com/pingcap/ticdc/pull/2218 for background.
726731 oldSchemaName := args .job .InvolvingSchemaInfo [0 ].Database
727732 oldTableName := args .job .InvolvingSchemaInfo [0 ].Table
728733 stmt , err := parser .New ().ParseOneStmt (args .job .Query , "" , "" )
@@ -744,9 +749,9 @@ func buildPersistedDDLEventForRenameTable(args buildPersistedDDLEventFuncArgs) P
744749 log .Error ("unknown stmt type" , zap .String ("query" , args .job .Query ), zap .Any ("stmt" , stmt ))
745750 }
746751 }
747- event .Query = fmt .Sprintf ("RENAME TABLE `%s`.`%s` TO `%s`.`%s` " ,
748- oldSchemaName , oldTableName ,
749- event .SchemaName , event .TableName )
752+ event .Query = fmt .Sprintf ("RENAME TABLE %s TO %s " ,
753+ common . QuoteSchema ( oldSchemaName , oldTableName ) ,
754+ common . QuoteSchema ( event .SchemaName , event .TableName ) )
750755 }
751756 return event
752757}
@@ -787,8 +792,10 @@ func buildPersistedDDLEventForExchangePartition(args buildPersistedDDLEventFuncA
787792 // Note that partition name should be parsed from original query, not the upperQuery.
788793 partName := strings .TrimSpace (event .Query [idx1 :idx2 ])
789794 partName = strings .Replace (partName , "`" , "" , - 1 )
790- event .Query = fmt .Sprintf ("ALTER TABLE `%s`.`%s` EXCHANGE PARTITION `%s` WITH TABLE `%s`.`%s`" ,
791- event .ExtraSchemaName , event .ExtraTableName , partName , event .SchemaName , event .TableName )
795+ event .Query = fmt .Sprintf ("ALTER TABLE %s EXCHANGE PARTITION %s WITH TABLE %s" ,
796+ common .QuoteSchema (event .ExtraSchemaName , event .ExtraTableName ),
797+ common .QuoteName (partName ),
798+ common .QuoteSchema (event .SchemaName , event .TableName ))
792799
793800 if strings .HasSuffix (upperQuery , "WITHOUT VALIDATION" ) {
794801 event .Query += " WITHOUT VALIDATION"
@@ -800,6 +807,41 @@ func buildPersistedDDLEventForExchangePartition(args buildPersistedDDLEventFuncA
800807 return event
801808}
802809
810+ type renameTableQueryInfo struct {
811+ oldSchemaName string
812+ oldTableName string
813+ newSchemaName string
814+ newTableName string
815+ }
816+
817+ func parseRenameTablesQueryInfos (query string ) ([]renameTableQueryInfo , bool ) {
818+ if query == "" {
819+ return nil , false
820+ }
821+ stmt , err := parser .New ().ParseOneStmt (query , "" , "" )
822+ if err != nil {
823+ log .Warn ("parse rename tables query failed" ,
824+ zap .String ("query" , query ),
825+ zap .Error (err ))
826+ return nil , false
827+ }
828+ renameStmt , ok := stmt .(* ast.RenameTableStmt )
829+ if ! ok {
830+ return nil , false
831+ }
832+
833+ queryInfos := make ([]renameTableQueryInfo , 0 , len (renameStmt .TableToTables ))
834+ for _ , tableToTable := range renameStmt .TableToTables {
835+ queryInfos = append (queryInfos , renameTableQueryInfo {
836+ oldSchemaName : tableToTable .OldTable .Schema .O ,
837+ oldTableName : tableToTable .OldTable .Name .O ,
838+ newSchemaName : tableToTable .NewTable .Schema .O ,
839+ newTableName : tableToTable .NewTable .Name .O ,
840+ })
841+ }
842+ return queryInfos , true
843+ }
844+
803845func buildPersistedDDLEventForRenameTables (args buildPersistedDDLEventFuncArgs ) PersistedDDLEvent {
804846 // TODO: does rename tables has the same problem(finished ts is not the real commit ts) with rename table?
805847 event := buildPersistedDDLEventCommon (args )
@@ -809,25 +851,71 @@ func buildPersistedDDLEventForRenameTables(args buildPersistedDDLEventFuncArgs)
809851 zap .String ("query" , args .job .Query ),
810852 zap .Error (err ))
811853 }
812- if len (renameArgs .RenameTableInfos ) != len (args .job .BinlogInfo .MultipleTableInfos ) {
854+ renameTableInfos := renameArgs .RenameTableInfos
855+ multipleTableInfos := args .job .BinlogInfo .MultipleTableInfos
856+ if len (renameTableInfos ) != len (multipleTableInfos ) {
813857 log .Panic ("should not happen" ,
814- zap .Int ("renameArgsLen" , len (renameArgs .RenameTableInfos )),
815- zap .Int ("multipleTableInfosLen" , len (args .job .BinlogInfo .MultipleTableInfos )))
858+ zap .Int ("renameArgsLen" , len (renameTableInfos )),
859+ zap .Int ("multipleTableInfosLen" , len (multipleTableInfos )),
860+ zap .String ("query" , args .job .Query ))
861+ }
862+
863+ // RenameTableInfos may store normalized lower-case names,
864+ // while the original query can keep user-provided identifier case.
865+ // Prefer names parsed from the original query whenever possible.
866+ // See https://github.com/pingcap/ticdc/pull/2218 for background.
867+ queryInfos , queryParsed := parseRenameTablesQueryInfos (args .job .Query )
868+ if queryParsed && len (queryInfos ) != len (renameTableInfos ) {
869+ log .Panic ("rename tables query info length is inconsistent with args" ,
870+ zap .Int ("queryInfosLen" , len (queryInfos )),
871+ zap .Int ("renameArgsLen" , len (renameTableInfos )),
872+ zap .String ("query" , args .job .Query ))
873+ }
874+
875+ // TiDB <= v8.1 may emit empty old table names for RENAME TABLES args.
876+ // See https://github.com/pingcap/tidb/pull/64421 for the upstream fix.
877+ if ! queryParsed && renameTableInfos [0 ].OldTableName .O == "" {
878+ // TODO: return error instead of falling back to args once builder supports error propagation.
879+ log .Warn ("rename tables args miss old table name and query is unavailable, keep args as-is" ,
880+ zap .Int ("tableCount" , len (renameTableInfos )),
881+ zap .String ("query" , args .job .Query ))
816882 }
817883
818884 var querys []string
819- for _ , info := range renameArgs .RenameTableInfos {
820- event .ExtraSchemaIDs = append (event .ExtraSchemaIDs , info .OldSchemaID )
821- event .ExtraSchemaNames = append (event .ExtraSchemaNames , info .OldSchemaName .O )
822- event .ExtraTableNames = append (event .ExtraTableNames , info .OldTableName .O )
885+ for i , info := range renameTableInfos {
886+ oldSchemaID := info .OldSchemaID
887+ oldSchemaName := info .OldSchemaName .O
888+ oldTableName := info .OldTableName .O
889+ newSchemaName := getSchemaName (args .databaseMap , info .NewSchemaID )
890+ newTableName := info .NewTableName .O
891+ if queryParsed {
892+ queryInfo := queryInfos [i ]
893+ if queryInfo .oldSchemaName != "" {
894+ oldSchemaName = queryInfo .oldSchemaName
895+ }
896+ if queryInfo .oldTableName != "" {
897+ oldTableName = queryInfo .oldTableName
898+ }
899+ if queryInfo .newSchemaName != "" {
900+ newSchemaName = queryInfo .newSchemaName
901+ }
902+ if queryInfo .newTableName != "" {
903+ newTableName = queryInfo .newTableName
904+ }
905+ }
906+
907+ event .ExtraSchemaIDs = append (event .ExtraSchemaIDs , oldSchemaID )
908+ event .ExtraSchemaNames = append (event .ExtraSchemaNames , oldSchemaName )
909+ event .ExtraTableNames = append (event .ExtraTableNames , oldTableName )
823910 event .SchemaIDs = append (event .SchemaIDs , info .NewSchemaID )
824- SchemaName := getSchemaName (args .databaseMap , info .NewSchemaID )
825- event .SchemaNames = append (event .SchemaNames , SchemaName )
826- querys = append (querys , fmt .Sprintf ("RENAME TABLE `%s`.`%s` TO `%s`.`%s`;" , info .OldSchemaName .O , info .OldTableName .O , SchemaName , info .NewTableName .O ))
911+ event .SchemaNames = append (event .SchemaNames , newSchemaName )
912+ querys = append (querys , fmt .Sprintf ("RENAME TABLE %s TO %s;" ,
913+ common .QuoteSchema (oldSchemaName , oldTableName ),
914+ common .QuoteSchema (newSchemaName , newTableName )))
827915 }
828916
829917 event .Query = strings .Join (querys , "" )
830- event .MultipleTableInfos = args . job . BinlogInfo . MultipleTableInfos
918+ event .MultipleTableInfos = multipleTableInfos
831919 // we have to reverse MultipleTableInfos to get correct schema name
832920 // see https://github.com/pingcap/tidb/issues/63710
833921 //
0 commit comments