Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
a33acff
update
daviszhen Jul 30, 2026
c61fd02
update
daviszhen Jul 30, 2026
4a9e89f
Merge branch 'main' into 0730-fix-fk-meta
mergify[bot] Jul 30, 2026
46772a4
Merge branch 'main' into 0730-fix-fk-meta
mergify[bot] Jul 30, 2026
314d151
update
daviszhen Jul 31, 2026
59904f4
update
daviszhen Jul 31, 2026
f49e0f9
Merge branch 'main' into 0730-fix-fk-meta
daviszhen Jul 31, 2026
9bb26d1
fix: use moerr in v4.0.6 FK upgrade
daviszhen Jul 31, 2026
34152a2
Merge branch 'main' into 0730-fix-fk-meta
daviszhen Jul 31, 2026
738ff07
test: update FK metadata ordinal expectations
daviszhen Jul 31, 2026
c84f0b7
Merge branch '0730-fix-fk-meta' of https://github.com/daviszhen/matri…
daviszhen Jul 31, 2026
e7078c7
Merge branch 'main' into 0730-fix-fk-meta
daviszhen Jul 31, 2026
a37599c
update
daviszhen Jul 31, 2026
6d65d85
Merge branch '0730-fix-fk-meta' of https://github.com/daviszhen/matri…
daviszhen Jul 31, 2026
f8c66fd
Merge branch 'main' into 0730-fix-fk-meta
daviszhen Jul 31, 2026
3761f52
update
daviszhen Aug 3, 2026
9aa2194
update
daviszhen Aug 3, 2026
6819f5d
update
daviszhen Aug 3, 2026
f02b102
update
daviszhen Aug 3, 2026
700975e
update
daviszhen Aug 3, 2026
453f24a
Merge branch '0730-fix-fk-meta' of https://github.com/daviszhen/matri…
daviszhen Aug 3, 2026
a9e70ae
Merge branch 'main' into 0730-fix-fk-meta
daviszhen Aug 3, 2026
5c3fbad
update
daviszhen Aug 3, 2026
faedfbd
update
daviszhen Aug 4, 2026
2fa86ba
update
daviszhen Aug 4, 2026
7558c47
Merge branch 'main' into 0730-fix-fk-meta
daviszhen Aug 4, 2026
f4bc72b
update
daviszhen Aug 4, 2026
a27dce0
update
daviszhen Aug 4, 2026
1415248
Merge branch 'main' into 0730-fix-fk-meta
daviszhen Aug 4, 2026
aeb8489
Merge branch 'main' into 0730-fix-fk-meta
daviszhen Aug 4, 2026
5d9b626
Merge branch 'main' into 0730-fix-fk-meta
daviszhen Aug 4, 2026
5f539b2
Merge branch 'main' into 0730-fix-fk-meta
daviszhen Aug 4, 2026
e2d24be
update
daviszhen Aug 5, 2026
bcaf776
update
daviszhen Aug 5, 2026
6bb24bd
update
daviszhen Aug 5, 2026
f7eddbb
update
daviszhen Aug 5, 2026
17f23ba
update
daviszhen Aug 5, 2026
0c58094
Merge branch 'main' into 0730-fix-fk-meta
daviszhen Aug 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions pkg/bootstrap/service_upgrade_tenant.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,12 @@ func (s *service) asyncUpgradeTenantTask(ctx context.Context) {
zap.String("tenant-version", createVersion),
zap.String("upgrade", upgrade.String()))

// createVersion >= upgrade.ToVersion already upgrade
if versions.Compare(createVersion, upgrade.ToVersion) >= 0 {
// A version-offset refresh can create an upgrade whose source and
// target version strings are identical. Reapply that handler so
// tenants at the old offset receive its idempotent metadata changes.
versionComparison := versions.Compare(createVersion, upgrade.ToVersion)
if versionComparison > 0 ||
(versionComparison == 0 && upgrade.FromVersion != upgrade.ToVersion) {
continue
}

Expand Down
77 changes: 77 additions & 0 deletions pkg/bootstrap/service_upgrade_tenant_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,83 @@ func Test_asyncUpgradeTenantTask_SkipsTenantAtTargetVersion(t *testing.T) {
)
}

func Test_asyncUpgradeTenantTask_ReappliesSameVersionOffsetUpgrade(t *testing.T) {
sid := ""
runtime.RunTest(
sid,
func(rt runtime.Runtime) {
var taskReady atomic.Bool
var finalized atomic.Bool
var tenantVersionUpdated atomic.Bool
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*50)
defer cancel()

sqlExecutor := executor.NewMemExecutor(func(sql string) (executor.Result, error) {
switch {
case strings.Contains(sql, "from mo_upgrade") &&
strings.Contains(sql, "where state = 1") &&
!strings.Contains(sql, "for update"):
return buildUpgradeVersionResult(100, 1, "4.0.6", "4.0.6", 9, 1, 1, 1, 1, 0), nil
case strings.Contains(sql, "from mo_upgrade_tenant where from_account_id >= 0"):
if taskReady.Load() {
return executor.Result{}, nil
}
return buildUpgradeTenantTaskRows([]uint64{200}, []int32{10}, []int32{10}), nil
case strings.Contains(sql, "select account_id, create_version from mo_account where account_id >= 10 and account_id <= 10"):
return buildUpgradeTenantAccountRows([]int32{10}, []string{"4.0.6"}), nil
case strings.Contains(sql, "update mo_account set create_version = '4.0.6' where account_id = 10"):
tenantVersionUpdated.Store(true)
return executor.Result{AffectedRows: 1}, nil
case strings.Contains(sql, "update mo_upgrade_tenant set ready = 1") &&
strings.Contains(sql, "where id = 200"):
taskReady.Store(true)
return executor.Result{AffectedRows: 1}, nil
case strings.Contains(sql, "select 1 from mo_upgrade_tenant where upgrade_id = 100 and ready = 0"):
return executor.Result{}, nil
case strings.Contains(sql, "from mo_upgrade") &&
strings.Contains(sql, "where id = 100 for update"):
return buildUpgradeVersionResult(100, 1, "4.0.6", "4.0.6", 9, 1, 1, 1, 1, 0), nil
case strings.Contains(sql, "update mo_upgrade set total_tenant = 1, ready_tenant = 0"):
return executor.Result{AffectedRows: 1}, nil
case strings.Contains(sql, "update mo_upgrade set total_tenant = 1, ready_tenant = 1") &&
strings.Contains(sql, "state = 2"):
finalized.Store(true)
cancel()
return executor.Result{AffectedRows: 1}, nil
default:
return executor.Result{}, fmt.Errorf("unexpected sql: %s", sql)
}
})

h := newTestVersionHandler("4.0.6", "4.0.5", versions.Yes, versions.Yes, 9)
s := newServiceForTest(
sid,
&memLocker{},
clock.NewHLCClock(func() int64 { return 0 }, 0),
nil,
sqlExecutor,
func(s *service) {
s.handles = append(s.handles, h)
},
WithCheckUpgradeTenantDuration(time.Millisecond),
)

txnOperator := mock_frontend.NewMockTxnOperator(gomock.NewController(t))
txnOperator.EXPECT().TxnOptions().Return(txn.TxnOptions{CN: sid}).AnyTimes()

s.exec = executor.NewMemExecutor2(func(sql string) (executor.Result, error) {
return sqlExecutor.Exec(context.Background(), sql, executor.Options{})
}, txnOperator)

s.asyncUpgradeTenantTask(ctx)
require.True(t, taskReady.Load())
require.True(t, finalized.Load())
require.Equal(t, uint64(1), h.callHandleTenantUpgrade.Load())
require.True(t, tenantVersionUpdated.Load())
},
)
}

func Test_asyncUpgradeTenantTask_AutoCompletesDeletedTenantTasks(t *testing.T) {
sid := ""
runtime.RunTest(
Expand Down
52 changes: 52 additions & 0 deletions pkg/bootstrap/versions/v4_0_6/tenant_upgrade_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
package v4_0_6

import (
"fmt"

"github.com/matrixorigin/matrixone/pkg/bootstrap/versions"
"github.com/matrixorigin/matrixone/pkg/catalog"
"github.com/matrixorigin/matrixone/pkg/sql/mongodb"
Expand All @@ -24,9 +26,27 @@ import (
var tenantUpgEntries = []versions.UpgradeEntry{
newMongoDBCatalogTable(mongodb.TableConnections, mongodb.ConnectionsDDL),
newMongoDBCatalogTable(mongodb.TableMappings, mongodb.MappingsDDL),
addForeignKeyMetadataColumn("referenced_index_name", "varchar(5000) not null default ''", "on_update"),
addForeignKeyMetadataColumn("on_delete_origin", "varchar(64) not null default 'ACTION_ORIGIN_LEGACY_AMBIGUOUS'", "referenced_index_name"),
addForeignKeyMetadataColumn("on_update_origin", "varchar(64) not null default 'ACTION_ORIGIN_LEGACY_AMBIGUOUS'", "on_delete_origin"),
upgradeInformationSchemaKeyColumnUsage(),
upgradeInformationSchemaReferentialConstraints(),
populateInformationSchemaCharacterSets(),
}

func addForeignKeyMetadataColumn(column, definition, after string) versions.UpgradeEntry {
return versions.UpgradeEntry{
Schema: catalog.MO_CATALOG,
TableName: catalog.MOForeignKeys,
UpgType: versions.ADD_COLUMN,
UpgSql: fmt.Sprintf("alter table %s.%s add column %s %s after %s", catalog.MO_CATALOG, catalog.MOForeignKeys, column, definition, after),
CheckFunc: func(txn executor.TxnExecutor, accountID uint32) (bool, error) {
columnInfo, err := versions.CheckTableColumn(txn, accountID, catalog.MO_CATALOG, catalog.MOForeignKeys, column)
return columnInfo.IsExits, err
},
}
}

func populateInformationSchemaCharacterSets() versions.UpgradeEntry {
return versions.UpgradeEntry{
Schema: sysview.InformationDBConst,
Expand Down Expand Up @@ -59,3 +79,35 @@ func newMongoDBCatalogTable(name, ddl string) versions.UpgradeEntry {
},
}
}

func upgradeInformationSchemaKeyColumnUsage() versions.UpgradeEntry {
return versions.UpgradeEntry{
Schema: sysview.InformationDBConst,
TableName: "KEY_COLUMN_USAGE",
UpgType: versions.CREATE_VIEW,
UpgSql: sysview.InformationSchemaKeyColumnUsageDDL,
CheckFunc: checkViewDefinition("KEY_COLUMN_USAGE", sysview.InformationSchemaKeyColumnUsageDDL),
PreSql: fmt.Sprintf("DROP TABLE IF EXISTS %s.%s;", sysview.InformationDBConst, "KEY_COLUMN_USAGE"),
}
}

func upgradeInformationSchemaReferentialConstraints() versions.UpgradeEntry {
return versions.UpgradeEntry{
Schema: sysview.InformationDBConst,
TableName: "REFERENTIAL_CONSTRAINTS",
UpgType: versions.MODIFY_VIEW,
UpgSql: sysview.InformationSchemaReferentialConstraintsDDL,
CheckFunc: checkViewDefinition("REFERENTIAL_CONSTRAINTS", sysview.InformationSchemaReferentialConstraintsDDL),
PreSql: fmt.Sprintf("DROP VIEW IF EXISTS %s.%s;", sysview.InformationDBConst, "REFERENTIAL_CONSTRAINTS"),
}
}

func checkViewDefinition(viewName, definition string) func(executor.TxnExecutor, uint32) (bool, error) {
return func(txn executor.TxnExecutor, accountID uint32) (bool, error) {
exists, viewDef, err := versions.CheckViewDefinition(txn, accountID, sysview.InformationDBConst, viewName)
if err != nil {
return false, err
}
return exists && viewDef == definition, nil
}
}
Loading
Loading