@@ -19,7 +19,6 @@ import (
1919 "fmt"
2020 "runtime/debug"
2121 "slices"
22- "strings"
2322 "sync"
2423 "sync/atomic"
2524 "time"
@@ -37,6 +36,7 @@ import (
3736 "github.com/matrixorigin/matrixone/pkg/defines"
3837 "github.com/matrixorigin/matrixone/pkg/logutil"
3938 "github.com/matrixorigin/matrixone/pkg/util/executor"
39+ "github.com/matrixorigin/matrixone/pkg/vm/engine"
4040)
4141
4242const (
@@ -744,6 +744,7 @@ func (s *TableDetector) scanTable() error {
744744 }
745745 defer result .Close ()
746746
747+ var scanErr error
747748 result .ReadRows (func (rows int , cols []* vector.Vector ) bool {
748749 for i := 0 ; i < rows ; i ++ {
749750 tblId := vector.MustFixedColWithTypeCheck [uint64 ](cols [0 ])[i ]
@@ -752,9 +753,21 @@ func (s *TableDetector) scanTable() error {
752753 dbName := cols [3 ].GetStringAt (i )
753754 createSql := cols [4 ].GetStringAt (i )
754755 accountId := vector.MustFixedColWithTypeCheck [uint32 ](cols [5 ])[i ]
756+ hasForeignKey , decodeErr := tableHasForeignKeyConstraint (cols [6 ].GetBytesAt (i ))
757+ if decodeErr != nil {
758+ scanErr = decodeErr
759+ logutil .Warn (
760+ "cdc.table_detector.scan_constraint_failed" ,
761+ zap .Uint32 ("account-id" , accountId ),
762+ zap .String ("db" , dbName ),
763+ zap .String ("table" , tblName ),
764+ zap .Error (decodeErr ),
765+ )
766+ return false
767+ }
755768
756769 // skip table with foreign key
757- if strings . Contains ( strings . ToLower ( "createSql" ), "foreign key" ) {
770+ if hasForeignKey {
758771 continue
759772 }
760773
@@ -776,21 +789,48 @@ func (s *TableDetector) scanTable() error {
776789 mp [accountId ][key ] = newInfo
777790 } else {
778791 idChanged := oldInfo .OnlyDiffinTblId (newInfo )
779- oldInfo .SourceDbId = dbId
780- oldInfo .SourceDbName = dbName
781- oldInfo .SourceTblId = tblId
782- oldInfo .SourceTblName = tblName
783- oldInfo .SourceCreateSql = createSql
784- oldInfo .IdChanged = oldInfo .IdChanged || idChanged
785- mp [accountId ][key ] = oldInfo
792+ updatedInfo := oldInfo .Clone ()
793+ updatedInfo .SourceDbId = dbId
794+ updatedInfo .SourceDbName = dbName
795+ updatedInfo .SourceTblId = tblId
796+ updatedInfo .SourceTblName = tblName
797+ updatedInfo .SourceCreateSql = createSql
798+ updatedInfo .IdChanged = updatedInfo .IdChanged || idChanged
799+ mp [accountId ][key ] = updatedInfo
786800 }
787801 }
788802 return true
789803 })
804+ if scanErr != nil {
805+ return scanErr
806+ }
790807
791808 // replace the old table map
792809 s .mu .Lock ()
793810 s .Mp = mp
794811 s .mu .Unlock ()
795812 return nil
796813}
814+
815+ func tableHasForeignKeyConstraint (data []byte ) (hasForeignKey bool , err error ) {
816+ if len (data ) == 0 {
817+ return false , nil
818+ }
819+
820+ defer func () {
821+ if r := recover (); r != nil {
822+ err = moerr .NewInternalErrorNoCtxf ("unmarshal table constraint failed: %v" , r )
823+ }
824+ }()
825+
826+ constraintDef := & engine.ConstraintDef {}
827+ if err := constraintDef .UnmarshalBinary (data ); err != nil {
828+ return false , err
829+ }
830+ for _ , constraint := range constraintDef .Cts {
831+ if foreignKeyDef , ok := constraint .(* engine.ForeignKeyDef ); ok && len (foreignKeyDef .Fkeys ) > 0 {
832+ return true , nil
833+ }
834+ }
835+ return false , nil
836+ }
0 commit comments