@@ -517,6 +517,26 @@ func getSchemaID(tableMap map[int64]*BasicTableInfo, tableID int64) int64 {
517517 return tableInfo .SchemaID
518518}
519519
520+ // schemaName should be "Name.O"
521+ func findSchemaIDByName (databaseMap map [int64 ]* BasicDatabaseInfo , schemaName string ) (int64 , bool ) {
522+ for id , info := range databaseMap {
523+ if info .Name == schemaName {
524+ return id , true
525+ }
526+ }
527+ return 0 , false
528+ }
529+
530+ // tableName should be "Name.O"
531+ func findTableIDByName (tableMap map [int64 ]* BasicTableInfo , schemaID int64 , tableName string ) (int64 , bool ) {
532+ for id , info := range tableMap {
533+ if info .SchemaID == schemaID && info .Name == tableName {
534+ return id , true
535+ }
536+ }
537+ return 0 , false
538+ }
539+
520540// =======
521541// buildPersistedDDLEventFunc start
522542// =======
@@ -588,9 +608,55 @@ func buildPersistedDDLEventForCreateTable(args buildPersistedDDLEventFuncArgs) P
588608 event := buildPersistedDDLEventCommon (args )
589609 event .SchemaName = getSchemaName (args .databaseMap , event .SchemaID )
590610 event .TableName = event .TableInfo .Name .O
611+ setReferTableForCreateTableLike (& event , args )
591612 return event
592613}
593614
615+ func setReferTableForCreateTableLike (event * PersistedDDLEvent , args buildPersistedDDLEventFuncArgs ) {
616+ if event .Query == "" {
617+ return
618+ }
619+ stmt , err := parser .New ().ParseOneStmt (event .Query , "" , "" )
620+ if err != nil {
621+ log .Error ("parse create table ddl failed" ,
622+ zap .String ("query" , event .Query ),
623+ zap .Error (err ))
624+ return
625+ }
626+ createStmt , ok := stmt .(* ast.CreateTableStmt )
627+ if ! ok || createStmt .ReferTable == nil {
628+ return
629+ }
630+ refTable := createStmt .ReferTable .Name .O
631+ refSchema := createStmt .ReferTable .Schema .O
632+ if refSchema == "" {
633+ refSchema = event .SchemaName
634+ }
635+ refSchemaID , ok := findSchemaIDByName (args .databaseMap , refSchema )
636+ if ! ok {
637+ log .Warn ("refer schema not found for create table like" ,
638+ zap .String ("schema" , refSchema ),
639+ zap .String ("table" , refTable ),
640+ zap .String ("query" , event .Query ))
641+ return
642+ }
643+ refTableID , ok := findTableIDByName (args .tableMap , refSchemaID , refTable )
644+ if ! ok {
645+ log .Warn ("refer table not found for create table like" ,
646+ zap .String ("schema" , refSchema ),
647+ zap .String ("table" , refTable ),
648+ zap .String ("query" , event .Query ))
649+ return
650+ }
651+ event .ExtraTableID = refTableID
652+ if partitions , ok := args .partitionMap [refTableID ]; ok {
653+ event .ReferTablePartitionIDs = event .ReferTablePartitionIDs [:0 ]
654+ for id := range partitions {
655+ event .ReferTablePartitionIDs = append (event .ReferTablePartitionIDs , id )
656+ }
657+ }
658+ }
659+
594660func buildPersistedDDLEventForDropTable (args buildPersistedDDLEventFuncArgs ) PersistedDDLEvent {
595661 event := buildPersistedDDLEventCommon (args )
596662 event .SchemaName = getSchemaName (args .databaseMap , event .SchemaID )
@@ -872,8 +938,8 @@ func updateDDLHistoryForSchemaDDL(args updateDDLHistoryFuncArgs) []uint64 {
872938
873939func updateDDLHistoryForAddDropTable (args updateDDLHistoryFuncArgs ) []uint64 {
874940 args .appendTableTriggerDDLHistory (args .ddlEvent .FinishedTs )
875- // Note: for create table, this ddl event will not be sent to table dispatchers.
876- // add it to ddl history is just for building table info store.
941+ // Note: for create table, this ddl event will not be sent to table dispatchers by default .
942+ // adding it to ddl history is just for building table info store.
877943 if isPartitionTable (args .ddlEvent .TableInfo ) {
878944 // for partition table, we only care the ddl history of physical table ids.
879945 for _ , partitionID := range getAllPartitionIDs (args .ddlEvent .TableInfo ) {
@@ -882,6 +948,13 @@ func updateDDLHistoryForAddDropTable(args updateDDLHistoryFuncArgs) []uint64 {
882948 } else {
883949 args .appendTablesDDLHistory (args .ddlEvent .FinishedTs , args .ddlEvent .TableID )
884950 }
951+ if args .ddlEvent .Type == byte (model .ActionCreateTable ) && args .ddlEvent .ExtraTableID != 0 {
952+ if len (args .ddlEvent .ReferTablePartitionIDs ) > 0 {
953+ args .appendTablesDDLHistory (args .ddlEvent .FinishedTs , args .ddlEvent .ReferTablePartitionIDs ... )
954+ } else {
955+ args .appendTablesDDLHistory (args .ddlEvent .FinishedTs , args .ddlEvent .ExtraTableID )
956+ }
957+ }
885958 return args .tableTriggerDDLHistory
886959}
887960
@@ -1383,6 +1456,21 @@ func extractTableInfoFuncForSingleTableDDL(event *PersistedDDLEvent, tableID int
13831456 return common .WrapTableInfo (event .SchemaName , event .TableInfo ), false
13841457 }
13851458 }
1459+
1460+ // The DDL "CREATE TABLE ... LIKE ..." may be added to the ddl history of the referenced table
1461+ // (or its physical partition IDs) to ensure those tables are blocked while this DDL is executing.
1462+ // It does not change the schema of the referenced table itself, so we should ignore it when
1463+ // building the table info store for the referenced table.
1464+ if event .Type == byte (model .ActionCreateTable ) && event .ExtraTableID != 0 {
1465+ if tableID == event .ExtraTableID {
1466+ return nil , false
1467+ }
1468+ for _ , id := range event .ReferTablePartitionIDs {
1469+ if tableID == id {
1470+ return nil , false
1471+ }
1472+ }
1473+ }
13861474 log .Panic ("should not reach here" ,
13871475 zap .Any ("type" , event .Type ),
13881476 zap .String ("query" , event .Query ),
@@ -1783,6 +1871,13 @@ func buildDDLEventForNewTableDDL(rawEvent *PersistedDDLEvent, tableFilter filter
17831871 InfluenceType : commonEvent .InfluenceTypeNormal ,
17841872 TableIDs : []int64 {common .DDLSpanTableID },
17851873 }
1874+ if rawEvent .ExtraTableID != 0 {
1875+ if len (rawEvent .ReferTablePartitionIDs ) > 0 {
1876+ ddlEvent .BlockedTables .TableIDs = append (ddlEvent .BlockedTables .TableIDs , rawEvent .ReferTablePartitionIDs ... )
1877+ } else {
1878+ ddlEvent .BlockedTables .TableIDs = append (ddlEvent .BlockedTables .TableIDs , rawEvent .ExtraTableID )
1879+ }
1880+ }
17861881 if isPartitionTable (rawEvent .TableInfo ) {
17871882 physicalIDs := getAllPartitionIDs (rawEvent .TableInfo )
17881883 ddlEvent .NeedAddedTables = make ([]commonEvent.Table , 0 , len (physicalIDs ))
@@ -1811,6 +1906,28 @@ func buildDDLEventForNewTableDDL(rawEvent *PersistedDDLEvent, tableFilter filter
18111906 },
18121907 },
18131908 }
1909+ if rawEvent .Query != "" {
1910+ stmt , err := parser .New ().ParseOneStmt (rawEvent .Query , "" , "" )
1911+ if err != nil {
1912+ log .Error ("parse create table ddl failed" ,
1913+ zap .String ("query" , rawEvent .Query ),
1914+ zap .Error (err ))
1915+ return ddlEvent , false , err
1916+ }
1917+ if createStmt , ok := stmt .(* ast.CreateTableStmt ); ok && createStmt .ReferTable != nil {
1918+ refTable := createStmt .ReferTable .Name .O
1919+ refSchema := createStmt .ReferTable .Schema .O
1920+ if refSchema == "" {
1921+ refSchema = rawEvent .SchemaName
1922+ }
1923+ ddlEvent .BlockedTableNames = []commonEvent.SchemaTableName {
1924+ {
1925+ SchemaName : refSchema ,
1926+ TableName : refTable ,
1927+ },
1928+ }
1929+ }
1930+ }
18141931 return ddlEvent , true , err
18151932}
18161933
0 commit comments