Skip to content

Commit 3435933

Browse files
committed
fix(cdc): skip foreign key tables in scanner
1 parent e6c70b6 commit 3435933

5 files changed

Lines changed: 511 additions & 37 deletions

File tree

pkg/cdc/sql_builder.go

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -248,19 +248,20 @@ const (
248248
"table_name = '%s'"
249249

250250
CDCCollectTableInfoSqlTemplate = "SELECT " +
251-
" rel_id, " +
252-
" relname, " +
253-
" reldatabase_id, " +
254-
" reldatabase, " +
255-
" rel_createsql, " +
256-
" account_id " +
257-
"FROM `mo_catalog`.`mo_tables` " +
251+
" tbl.rel_id, " +
252+
" tbl.relname, " +
253+
" tbl.reldatabase_id, " +
254+
" tbl.reldatabase, " +
255+
" tbl.rel_createsql, " +
256+
" tbl.account_id, " +
257+
" tbl.`constraint` " +
258+
"FROM `mo_catalog`.`mo_tables` tbl " +
258259
"WHERE " +
259-
" account_id IN (%s) " +
260+
" tbl.account_id IN (%s) " +
260261
"%s" +
261262
"%s" +
262-
" AND relkind = '%s' " +
263-
" AND reldatabase NOT IN (%s)"
263+
" AND tbl.relkind = '%s' " +
264+
" AND tbl.reldatabase NOT IN (%s)"
264265
CDCInsertMOISCPLogSqlTemplate = `REPLACE INTO mo_catalog.mo_iscp_log (` +
265266
`account_id,` +
266267
`table_id,` +
@@ -475,6 +476,7 @@ var CDCSQLTemplates = [CDCSqlTemplateCount]struct {
475476
"reldatabase",
476477
"rel_createsql",
477478
"account_id",
479+
"constraint",
478480
},
479481
},
480482
CDCGetWatermarkWhereSqlTemplate_Idx: {
@@ -1071,13 +1073,13 @@ func (b cdcSQLBuilder) CollectTableInfoSQL(accountIDs string, dbNames string, ta
10711073
if dbNames == "*" {
10721074
return ""
10731075
}
1074-
return " AND reldatabase IN (" + dbNames + ") "
1076+
return " AND tbl.reldatabase IN (" + dbNames + ") "
10751077
}(),
10761078
func() string {
10771079
if tableNames == "*" {
10781080
return ""
10791081
}
1080-
return " AND relname IN (" + tableNames + ") "
1082+
return " AND tbl.relname IN (" + tableNames + ") "
10811083
}(),
10821084
catalog.SystemOrdinaryRel,
10831085
AddSingleQuotesJoin(catalog.SystemDatabases),

pkg/cdc/table_scanner.go

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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

4242
const (
@@ -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

Comments
 (0)