From 1fef4e3dd0a134c44c4e9c2e50ab11dc3b41b64a Mon Sep 17 00:00:00 2001 From: aptend Date: Mon, 18 Nov 2024 15:17:27 +0800 Subject: [PATCH] fix --- pkg/frontend/test/engine_mock.go | 15 +++++++ pkg/testutil/testengine/testengine_test.go | 19 +++++++++ pkg/vm/engine/disttae/txn_database.go | 40 +++++++++++++++---- .../disttae/txn_table_sharding_handle.go | 5 ++- pkg/vm/engine/memoryengine/database.go | 11 +++++ pkg/vm/engine/test/disttae_engine_test.go | 31 ++++++++++++++ pkg/vm/engine/types.go | 1 + 7 files changed, 113 insertions(+), 9 deletions(-) diff --git a/pkg/frontend/test/engine_mock.go b/pkg/frontend/test/engine_mock.go index ab74c9d444460..2bf6ae424714d 100644 --- a/pkg/frontend/test/engine_mock.go +++ b/pkg/frontend/test/engine_mock.go @@ -1733,6 +1733,21 @@ func (mr *MockDatabaseMockRecorder) Relation(arg0, arg1, arg2 interface{}) *gomo return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Relation", reflect.TypeOf((*MockDatabase)(nil).Relation), arg0, arg1, arg2) } +// RelationExists mocks base method. +func (m *MockDatabase) RelationExists(arg0 context.Context, arg1 string, arg2 any) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RelationExists", arg0, arg1, arg2) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RelationExists indicates an expected call of RelationExists. +func (mr *MockDatabaseMockRecorder) RelationExists(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RelationExists", reflect.TypeOf((*MockDatabase)(nil).RelationExists), arg0, arg1, arg2) +} + // Relations mocks base method. func (m *MockDatabase) Relations(arg0 context.Context) ([]string, error) { m.ctrl.T.Helper() diff --git a/pkg/testutil/testengine/testengine_test.go b/pkg/testutil/testengine/testengine_test.go index a37ba8b27e8f5..2e0e9351d5cf6 100644 --- a/pkg/testutil/testengine/testengine_test.go +++ b/pkg/testutil/testengine/testengine_test.go @@ -20,6 +20,8 @@ import ( "github.com/matrixorigin/matrixone/pkg/catalog" "github.com/matrixorigin/matrixone/pkg/common/runtime" + "github.com/matrixorigin/matrixone/pkg/defines" + "github.com/stretchr/testify/require" ) func TestTestEngine(t *testing.T) { @@ -40,3 +42,20 @@ func BenchmarkNew(b *testing.B) { New(context.Background()) } } + +func TestRelationExists(t *testing.T) { + catalog.SetupDefines("") + ctx := context.Background() + ctx = defines.AttachAccountId(ctx, 0) + eng, _, _ := New(ctx) + db, err := eng.Database(ctx, "test", nil) + require.NoError(t, err) + + exist, err := db.RelationExists(ctx, "NotExist", nil) + require.NoError(t, err) + require.False(t, exist) + + exist, err = db.RelationExists(ctx, "r", nil) + require.NoError(t, err) + require.True(t, exist) +} diff --git a/pkg/vm/engine/disttae/txn_database.go b/pkg/vm/engine/disttae/txn_database.go index 325aba5e75b5b..16496b178236f 100644 --- a/pkg/vm/engine/disttae/txn_database.go +++ b/pkg/vm/engine/disttae/txn_database.go @@ -87,7 +87,7 @@ func (db *txnDatabase) Relations(ctx context.Context) ([]string, error) { return rels, nil } -func (db *txnDatabase) Relation(ctx context.Context, name string, proc any) (engine.Relation, error) { +func (db *txnDatabase) relation(ctx context.Context, name string, proc any) (engine.Relation, error) { common.DoIfDebugEnabled(func() { logutil.Debug( "Transaction.Relation", @@ -118,7 +118,8 @@ func (db *txnDatabase) Relation(ctx context.Context, name string, proc any) (eng // check the table is deleted or not if !openSys && txn.tableOps.existAndDeleted(key) { - return nil, moerr.NewParseErrorf(ctx, "table %q does not exist", name) + logutil.Info("[relation] deleted in txn", zap.String("table", name)) + return nil, nil } // get relation from the txn created tables cache: created by this txn @@ -144,10 +145,13 @@ func (db *txnDatabase) Relation(ctx context.Context, name string, proc any) (eng if err != nil { return nil, err } + if item == nil { + return nil, nil + } tbl, err := newTxnTable( db, - item, + *item, p, shardservice.GetService(p.GetService()), txn.engine, @@ -160,6 +164,25 @@ func (db *txnDatabase) Relation(ctx context.Context, name string, proc any) (eng return tbl, nil } +func (db *txnDatabase) Relation(ctx context.Context, name string, proc any) (engine.Relation, error) { + rel, err := db.relation(ctx, name, proc) + if err != nil { + return nil, err + } + if rel == nil { + return nil, moerr.NewParseErrorf(ctx, "table %q does not exist", name) + } + return rel, nil +} + +func (db *txnDatabase) RelationExists(ctx context.Context, name string, proc any) (bool, error) { + rel, err := db.relation(ctx, name, proc) + if err != nil { + return false, err + } + return rel != nil, nil +} + func (db *txnDatabase) Delete(ctx context.Context, name string) error { _, err := db.deleteTable(ctx, name, false, false) return err @@ -596,7 +619,7 @@ func (db *txnDatabase) getTableItem( accountID uint32, name string, engine *Engine, -) (cache.TableItem, error) { +) (*cache.TableItem, error) { item := cache.TableItem{ Name: name, DatabaseId: db.databaseId, @@ -608,14 +631,15 @@ func (db *txnDatabase) getTableItem( if ok := c.GetTable(&item); !ok { var tableitem *cache.TableItem if !c.CanServe(types.TimestampToTS(db.op.SnapshotTS())) { + logutil.Info("FIND_TABLE getTableItem cache cannot serve", zap.String("table", name), zap.Uint32("accountID", accountID), zap.String("timestamp", db.op.SnapshotTS().DebugString())) if tableitem, err = db.loadTableFromStorage(ctx, accountID, name); err != nil { - return cache.TableItem{}, err + return nil, err } } if tableitem == nil { - return cache.TableItem{}, moerr.NewParseErrorf(ctx, "table %q does not exist", name) + return nil, nil } - return *tableitem, nil + return tableitem, nil } - return item, nil + return &item, nil } diff --git a/pkg/vm/engine/disttae/txn_table_sharding_handle.go b/pkg/vm/engine/disttae/txn_table_sharding_handle.go index a3c12a135048b..009b886db602c 100644 --- a/pkg/vm/engine/disttae/txn_table_sharding_handle.go +++ b/pkg/vm/engine/disttae/txn_table_sharding_handle.go @@ -681,10 +681,13 @@ func getTxnTable( if err != nil { return nil, err } + if item == nil { + return nil, moerr.NewParseErrorf(ctx, "table %q does not exist", param.TxnTable.TableName) + } tbl := newTxnTableWithItem( db, - item, + *item, proc, engine.(*Engine), ) diff --git a/pkg/vm/engine/memoryengine/database.go b/pkg/vm/engine/memoryengine/database.go index 8b4b5a0456dd6..012e9d98b4094 100644 --- a/pkg/vm/engine/memoryengine/database.go +++ b/pkg/vm/engine/memoryengine/database.go @@ -165,6 +165,17 @@ func (d *Database) Relation(ctx context.Context, relName string, _ any) (engine. } } +func (d *Database) RelationExists(ctx context.Context, relName string, _ any) (bool, error) { + rel, err := d.Relation(ctx, relName, nil) + if err != nil { + if moerr.IsMoErrCode(err, moerr.ErrNoSuchTable) { + return false, nil + } else { + return false, err + } + } + return rel != nil, nil +} func (d *Database) Relations(ctx context.Context) ([]string, error) { diff --git a/pkg/vm/engine/test/disttae_engine_test.go b/pkg/vm/engine/test/disttae_engine_test.go index b2dabcc474ed0..acc36b4288d35 100644 --- a/pkg/vm/engine/test/disttae_engine_test.go +++ b/pkg/vm/engine/test/disttae_engine_test.go @@ -1215,3 +1215,34 @@ func TestCache3Tables(t *testing.T) { require.Equal(t, catalog.MO_COLUMNS, tname) require.NotNil(t, rel) } + +func TestRelationExists(t *testing.T) { + opts := config.WithLongScanAndCKPOpts(nil) + p := testutil.InitEnginePack(testutil.TestOptions{TaeEngineOptions: opts}, t) + defer p.Close() + txnop := p.StartCNTxn() + schema := catalog2.MockSchemaAll(2, 0) + schema.Name = "test" + p.CreateDBAndTable(txnop, "db", schema) + + db, err := p.D.Engine.Database(p.Ctx, "db", txnop) + require.NoError(t, err) + + exist, err := db.RelationExists(p.Ctx, "test", nil) + require.NoError(t, err) + require.True(t, exist) + + exist, err = db.RelationExists(p.Ctx, "testxx", nil) + require.NoError(t, err) + require.False(t, exist) + + // craft no-account-id error + ctx := context.WithValue(p.Ctx, defines.TenantIDKey{}, nil) + exist, err = db.RelationExists(ctx, "testxx", nil) + require.Error(t, err) + require.False(t, exist) + + rel, err := db.Relation(ctx, "test", nil) + require.Error(t, err) + require.Nil(t, rel) +} diff --git a/pkg/vm/engine/types.go b/pkg/vm/engine/types.go index 4019cc745dde0..1f494cb1ab7c3 100644 --- a/pkg/vm/engine/types.go +++ b/pkg/vm/engine/types.go @@ -931,6 +931,7 @@ type Reader interface { type Database interface { Relations(context.Context) ([]string, error) Relation(context.Context, string, any) (Relation, error) + RelationExists(context.Context, string, any) (bool, error) Delete(context.Context, string) error Create(context.Context, string, []TableDef) error // Create Table - (name, table define)