diff --git a/pkg/frontend/authenticate.go b/pkg/frontend/authenticate.go index 20215916ce4ab..1d2c27f4b63e9 100644 --- a/pkg/frontend/authenticate.go +++ b/pkg/frontend/authenticate.go @@ -63,6 +63,7 @@ import ( "github.com/matrixorigin/matrixone/pkg/util/sysview" "github.com/matrixorigin/matrixone/pkg/util/trace" "github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace" + "github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace/statistic" ) type TenantInfo struct { @@ -6117,36 +6118,40 @@ func determineRoleSetHasPrivilegeSet(ctx context.Context, bh BackgroundExec, ses // determineUserHasPrivilegeSet decides the privileges of user can satisfy the requirement of the privilege set // The algorithm 1. -func determineUserHasPrivilegeSet(ctx context.Context, ses *Session, priv *privilege) (ret bool, err error) { +func determineUserHasPrivilegeSet(ctx context.Context, ses *Session, priv *privilege) (ret bool, stats statistic.StatsArray, err error) { var erArray []ExecResult var yes bool var roleB int64 var ok bool var grantedIds *btree.Set[int64] var enableCache bool + stats.Reset() //check privilege cache first if len(priv.entries) == 0 { - return false, nil + return false, stats, nil } enableCache, err = privilegeCacheIsEnabled(ctx, ses) if err != nil { - return false, err + return false, stats, err } if enableCache { yes, err = checkPrivilegeInCache(ctx, ses, priv, enableCache) if err != nil { - return false, err + return false, stats, err } if yes { - return true, nil + return true, stats, nil } } tenant := ses.GetTenantInfo() bh := ses.GetBackgroundExec(ctx) - defer bh.Close() + defer func() { + stats = bh.GetExecStatsArray() + bh.Close() + }() if ses.tStmt != nil { // for reset frontend query's txn-id @@ -6172,14 +6177,14 @@ func determineUserHasPrivilegeSet(ctx context.Context, ses *Session, priv *privi err = finishTxn(ctx, bh, err) }() if err != nil { - return false, err + return false, stats, err } //step 2: The Set R2 {the roleid granted to the userid} //If the user uses the all secondary roles, the secondary roles needed to be loaded err = loadAllSecondaryRoles(ctx, bh, tenant, roleSetOfKthIteration) if err != nil { - return false, err + return false, stats, err } //init RVisited = Rk @@ -6192,11 +6197,11 @@ func determineUserHasPrivilegeSet(ctx context.Context, ses *Session, priv *privi //If the result of the algorithm 2 is true, Then return true; yes, err = determineRoleSetHasPrivilegeSet(ctx, bh, ses, roleSetOfKthIteration, priv, enableCache) if err != nil { - return false, err + return false, stats, err } if yes { ret = true - return ret, err + return ret, stats, err } /* step 3: !!!NOTE all roleid in Rk has been processed by the algorithm 2. @@ -6243,19 +6248,19 @@ func determineUserHasPrivilegeSet(ctx context.Context, ses *Session, priv *privi bh.ClearExecResultSet() err = bh.Exec(ctx, sqlForInheritedRoleIdOfRoleId) if err != nil { - return false, moerr.NewInternalErrorf(ctx, "get inherited role id of the role id. error:%v", err) + return false, stats, moerr.NewInternalErrorf(ctx, "get inherited role id of the role id. error:%v", err) } erArray, err = getResultSet(ctx, bh) if err != nil { - return false, err + return false, stats, err } if execResultArrayHasData(erArray) { for i := uint64(0); i < erArray[0].GetRowCount(); i++ { roleB, err = erArray[0].GetInt64(ctx, i, 0) if err != nil { - return false, err + return false, stats, err } if !roleSetOfVisited.Contains(roleB) { @@ -6270,23 +6275,23 @@ func determineUserHasPrivilegeSet(ctx context.Context, ses *Session, priv *privi //no more roleB, it is done if roleSetOfKPlusOneThIteration.Len() == 0 { ret = false - return ret, err + return ret, stats, err } //Call the algorithm 2. //If the result of the algorithm 2 is true, Then return true; yes, err = determineRoleSetHasPrivilegeSet(ctx, bh, ses, roleSetOfKPlusOneThIteration, priv, enableCache) if err != nil { - return false, err + return false, stats, err } if yes { ret = true - return ret, err + return ret, stats, err } roleSetOfKthIteration, roleSetOfKPlusOneThIteration = roleSetOfKPlusOneThIteration, roleSetOfKthIteration } - return ret, err + return ret, stats, err } const ( @@ -6431,16 +6436,21 @@ func determineUserCanGrantRolesToOthersInternal(ctx context.Context, bh Backgrou // determineUserCanGrantRoleToOtherUsers decides if the user can grant roles to other users or roles // the same as the grant/revoke privilege, role. -func determineUserCanGrantRolesToOthers(ctx context.Context, ses *Session, fromRoles []*tree.Role) (ret bool, err error) { +func determineUserCanGrantRolesToOthers(ctx context.Context, ses *Session, fromRoles []*tree.Role) (ret bool, stats statistic.StatsArray, err error) { + stats.Reset() + //step1: normalize the names of roles and users err = normalizeNamesOfRoles(ctx, fromRoles) if err != nil { - return false, err + return false, stats, err } //step2: decide the current user bh := ses.GetBackgroundExec(ctx) - defer bh.Close() + defer func() { + stats = bh.GetExecStatsArray() + bh.Close() + }() //put it into the single transaction err = bh.Exec(ctx, "begin;") @@ -6448,15 +6458,15 @@ func determineUserCanGrantRolesToOthers(ctx context.Context, ses *Session, fromR err = finishTxn(ctx, bh, err) }() if err != nil { - return false, err + return false, stats, err } ret, err = determineUserCanGrantRolesToOthersInternal(ctx, bh, ses, fromRoles) if err != nil { - return false, err + return false, stats, err } - return ret, err + return ret, stats, err } // isRoleGrantedToUserWGO verifies the role has been granted to the user with with_grant_option = true. @@ -6520,17 +6530,21 @@ func getRoleSetThatRoleGrantedToWGO(ctx context.Context, bh BackgroundExec, role } // authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase decides the user has the privilege of executing the statement with object type account -func authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ctx context.Context, ses *Session, stmt tree.Statement) (bool, error) { +func authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ctx context.Context, ses *Session, stmt tree.Statement) (bool, statistic.StatsArray, error) { var err error var ok, yes bool + var stats statistic.StatsArray + stats.Reset() + priv := ses.GetPrivilege() if priv.objectType() != objectTypeAccount && priv.objectType() != objectTypeDatabase { //do nothing - return true, nil + return true, stats, nil } - ok, err = determineUserHasPrivilegeSet(ctx, ses, priv) + ok, delta, err := determineUserHasPrivilegeSet(ctx, ses, priv) if err != nil { - return false, err + return false, stats, err } + stats.Add(&delta) //double check privilege of drop table if !ok && ses.GetFromRealUser() && ses.GetTenantInfo() != nil && ses.GetTenantInfo().IsSysTenant() { @@ -6540,13 +6554,13 @@ func authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ctx con if len(dbName) == 0 { dbName = ses.GetDatabaseName() } - return isClusterTable(dbName, string(st.Names[0].ObjectName)), nil + return isClusterTable(dbName, string(st.Names[0].ObjectName)), stats, nil case *tree.AlterTable: dbName := string(st.Table.SchemaName) if len(dbName) == 0 { dbName = ses.GetDatabaseName() } - return isClusterTable(dbName, string(st.Table.ObjectName)), nil + return isClusterTable(dbName, string(st.Table.ObjectName)), stats, nil } } @@ -6554,12 +6568,14 @@ func authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ctx con if !ok && priv.kind == privilegeKindInherit { grant := stmt.(*tree.Grant) grantRole := grant.GrantRole - yes, err = determineUserCanGrantRolesToOthers(ctx, ses, grantRole.Roles) + yes, delta, err = determineUserCanGrantRolesToOthers(ctx, ses, grantRole.Roles) if err != nil { - return false, err + return false, stats, err } + stats.Add(&delta) + if yes { - return true, nil + return true, stats, nil } } //for Create User statement with default role. @@ -6572,60 +6588,66 @@ func authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ctx con // get the databasename dbName := string(st.Name) if _, inSet := sysDatabases[dbName]; inSet { - return ok, nil + return ok, stats, nil } return checkRoleWhetherDatabaseOwner(ctx, ses, dbName, ok) case *tree.DropTable: // get the databasename and tablename if len(st.Names) != 1 { - return ok, nil + return ok, stats, nil } dbName := string(st.Names[0].SchemaName) if len(dbName) == 0 { dbName = ses.GetDatabaseName() } if _, inSet := sysDatabases[dbName]; inSet { - return ok, nil + return ok, stats, nil } tbName := string(st.Names[0].ObjectName) return checkRoleWhetherTableOwner(ctx, ses, dbName, tbName, ok) } } - return ok, nil + return ok, stats, nil } -func checkRoleWhetherTableOwner(ctx context.Context, ses *Session, dbName, tbName string, ok bool) (bool, error) { +func checkRoleWhetherTableOwner(ctx context.Context, ses *Session, dbName, tbName string, ok bool) (bool, statistic.StatsArray, error) { var owner int64 var err error var erArray []ExecResult var sql string + var stats statistic.StatsArray + stats.Reset() + roles := make([]int64, 0) tenantInfo := ses.GetTenantInfo() // current user currentUser := tenantInfo.GetUserID() bh := ses.GetBackgroundExec(ctx) - defer bh.Close() + defer func() { + stats = bh.GetExecStatsArray() + bh.Close() + }() // getOwner of the table sql = getSqlForGetOwnerOfTable(dbName, tbName) bh.ClearExecResultSet() err = bh.Exec(ctx, sql) if err != nil { - return ok, nil + return ok, stats, nil } erArray, err = getResultSet(ctx, bh) if err != nil { - return ok, nil + return ok, stats, nil } if execResultArrayHasData(erArray) { owner, err = erArray[0].GetInt64(ctx, 0, 0) if err != nil { - return ok, nil + return ok, stats, nil } } else { - return ok, nil + return ok, stats, nil } // check role @@ -6634,46 +6656,48 @@ func checkRoleWhetherTableOwner(ctx context.Context, ses *Session, dbName, tbNam bh.ClearExecResultSet() err = bh.Exec(ctx, sql) if err != nil { - return ok, nil + return ok, stats, nil } erArray, err = getResultSet(ctx, bh) if err != nil { - return ok, nil + return ok, stats, nil } if execResultArrayHasData(erArray) { for i := uint64(0); i < erArray[0].GetRowCount(); i++ { role, err := erArray[0].GetInt64(ctx, i, 0) if err != nil { - return ok, nil + return ok, stats, nil } roles = append(roles, role) } } else { - return ok, nil + return ok, stats, nil } // check the role whether the table's owner for _, role := range roles { if role == owner { - return true, nil + return true, stats, nil } } } else { currentRole := tenantInfo.GetDefaultRoleID() if owner == int64(currentRole) { - return true, nil + return true, stats, nil } } - return ok, nil + return ok, stats, nil } -func checkRoleWhetherDatabaseOwner(ctx context.Context, ses *Session, dbName string, ok bool) (bool, error) { +func checkRoleWhetherDatabaseOwner(ctx context.Context, ses *Session, dbName string, ok bool) (bool, statistic.StatsArray, error) { var owner int64 var err error var erArray []ExecResult var sql string + var stats statistic.StatsArray + stats.Reset() roles := make([]int64, 0) tenantInfo := ses.GetTenantInfo() @@ -6681,27 +6705,30 @@ func checkRoleWhetherDatabaseOwner(ctx context.Context, ses *Session, dbName str currentUser := tenantInfo.GetUserID() bh := ses.GetBackgroundExec(ctx) - defer bh.Close() + defer func() { + stats = bh.GetExecStatsArray() + bh.Close() + }() // getOwner of the database sql = getSqlForGetOwnerOfDatabase(dbName) bh.ClearExecResultSet() err = bh.Exec(ctx, sql) if err != nil { - return ok, nil + return ok, stats, nil } erArray, err = getResultSet(ctx, bh) if err != nil { - return ok, nil + return ok, stats, nil } if execResultArrayHasData(erArray) { owner, err = erArray[0].GetInt64(ctx, 0, 0) if err != nil { - return ok, nil + return ok, stats, nil } } else { - return ok, nil + return ok, stats, nil } // check role @@ -6710,38 +6737,38 @@ func checkRoleWhetherDatabaseOwner(ctx context.Context, ses *Session, dbName str bh.ClearExecResultSet() err = bh.Exec(ctx, sql) if err != nil { - return ok, nil + return ok, stats, nil } erArray, err = getResultSet(ctx, bh) if err != nil { - return ok, nil + return ok, stats, nil } if execResultArrayHasData(erArray) { for i := uint64(0); i < erArray[0].GetRowCount(); i++ { role, err := erArray[0].GetInt64(ctx, i, 0) if err != nil { - return ok, nil + return ok, stats, nil } roles = append(roles, role) } } else { - return ok, nil + return ok, stats, nil } // check the role whether the database's owner for _, role := range roles { if role == owner { - return true, nil + return true, stats, nil } } } else { currentRole := tenantInfo.GetDefaultRoleID() if owner == int64(currentRole) { - return true, nil + return true, stats, nil } } - return ok, nil + return ok, stats, nil } // authenticateUserCanExecuteStatementWithObjectTypeDatabaseAndTable @@ -6750,27 +6777,32 @@ func checkRoleWhetherDatabaseOwner(ctx context.Context, ses *Session, dbName str func authenticateUserCanExecuteStatementWithObjectTypeDatabaseAndTable(ctx context.Context, ses *Session, stmt tree.Statement, - p *plan2.Plan) (bool, error) { + p *plan2.Plan) (bool, statistic.StatsArray, error) { + var stats statistic.StatsArray + stats.Reset() + priv := determinePrivilegeSetOfStatement(stmt) if priv.objectType() == objectTypeTable { //only sys account, moadmin role can exec mo_ctrl if hasMoCtrl(p) { if !verifyAccountCanExecMoCtrl(ses.GetTenantInfo()) { - return false, moerr.NewInternalError(ctx, "do not have privilege to execute the statement") + return false, stats, moerr.NewInternalError(ctx, "do not have privilege to execute the statement") } } arr := extractPrivilegeTipsFromPlan(p) if len(arr) == 0 { - return true, nil + return true, stats, nil } convertPrivilegeTipsToPrivilege(priv, arr) - ok, err := determineUserHasPrivilegeSet(ctx, ses, priv) + ok, delta, err := determineUserHasPrivilegeSet(ctx, ses, priv) if err != nil { - return false, err + return false, stats, err } - return ok, nil + stats.Add(&delta) + + return ok, stats, nil } - return true, nil + return true, stats, nil } // formSqlFromGrantPrivilege makes the sql for querying the database. @@ -6964,12 +6996,17 @@ func setIsIntersected(A, B *btree.Set[int64]) bool { } // determineUserCanGrantPrivilegesToOthers decides the privileges can be granted to others. -func determineUserCanGrantPrivilegesToOthers(ctx context.Context, ses *Session, gp *tree.GrantPrivilege) (ret bool, err error) { +func determineUserCanGrantPrivilegesToOthers(ctx context.Context, ses *Session, gp *tree.GrantPrivilege) (ret bool, stats statistic.StatsArray, err error) { + stats.Reset() + //step1: normalize the names of roles and users //step2: decide the current user account := ses.GetTenantInfo() bh := ses.GetBackgroundExec(ctx) - defer bh.Close() + defer func() { + stats = bh.GetExecStatsArray() + bh.Close() + }() //step3: check the link: roleX -> roleA -> .... -> roleZ -> the current user. Every link has the with_grant_option. ret = true @@ -6995,26 +7032,26 @@ func determineUserCanGrantPrivilegesToOthers(ctx context.Context, ses *Session, err = finishTxn(ctx, bh, err) }() if err != nil { - return false, err + return false, stats, err } //step 2: The Set R2 {the roleid granted to the userid} //If the user uses the all secondary roles, the secondary roles needed to be loaded err = loadAllSecondaryRoles(ctx, bh, account, roleSetOfCurrentUser) if err != nil { - return false, err + return false, stats, err } for _, priv := range gp.Privileges { privType, err = convertAstPrivilegeTypeToPrivilegeType(ctx, priv.Type, gp.ObjType) if err != nil { - return false, err + return false, stats, err } //call the algorithm 3. roleSetOfPrivilegeGrantedToWGO, err = getRoleSetThatPrivilegeGrantedToWGO(ctx, bh, privType) if err != nil { - return false, err + return false, stats, err } if setIsIntersected(roleSetOfPrivilegeGrantedToWGO, roleSetOfCurrentUser) { @@ -7033,7 +7070,7 @@ func determineUserCanGrantPrivilegesToOthers(ctx context.Context, ses *Session, for _, ri := range roleSetOfKthIteration.Keys() { tempRoleSet, err = getRoleSetThatRoleGrantedToWGO(ctx, bh, ri, roleSetOfVisited, roleSetOfKPlusOneThIteration) if err != nil { - return false, err + return false, stats, err } if setIsIntersected(tempRoleSet, roleSetOfCurrentUser) { @@ -7055,7 +7092,7 @@ func determineUserCanGrantPrivilegesToOthers(ctx context.Context, ses *Session, break } } - return ret, err + return ret, stats, err } func convertAstPrivilegeTypeToPrivilegeType(ctx context.Context, priv tree.PrivilegeType, ot tree.ObjectType) (PrivilegeType, error) { @@ -7150,21 +7187,27 @@ func convertAstPrivilegeTypeToPrivilegeType(ctx context.Context, priv tree.Privi } // authenticateUserCanExecuteStatementWithObjectTypeNone decides the user has the privilege of executing the statement with object type none -func authenticateUserCanExecuteStatementWithObjectTypeNone(ctx context.Context, ses *Session, stmt tree.Statement) (bool, error) { +func authenticateUserCanExecuteStatementWithObjectTypeNone(ctx context.Context, ses *Session, stmt tree.Statement) (bool, statistic.StatsArray, error) { + var stats statistic.StatsArray + stats.Reset() + priv := ses.GetPrivilege() if priv.objectType() != objectTypeNone { //do nothing - return true, nil + return true, stats, nil } tenant := ses.GetTenantInfo() if priv.privilegeKind() == privilegeKindNone { // do nothing - return true, nil + return true, stats, nil } else if priv.privilegeKind() == privilegeKindSpecial { //GrantPrivilege, RevokePrivilege - checkGrantPrivilege := func(g *tree.GrantPrivilege) (bool, error) { + checkGrantPrivilege := func(g *tree.GrantPrivilege) (bool, statistic.StatsArray, error) { + var temp statistic.StatsArray + temp.Reset() + //in the version 0.6, only the moAdmin and accountAdmin can grant the privilege. if tenant.IsAdminRole() { - return true, nil + return true, temp, nil } return determineUserCanGrantPrivilegesToOthers(ctx, ses, g) } @@ -7197,45 +7240,53 @@ func authenticateUserCanExecuteStatementWithObjectTypeNone(ctx context.Context, switch gp := stmt.(type) { case *tree.Grant: if gp.Typ == tree.GrantTypePrivilege { - yes, err := checkGrantPrivilege(&gp.GrantPrivilege) + yes, delta, err := checkGrantPrivilege(&gp.GrantPrivilege) + stats.Add(&delta) if err != nil { - return yes, err + return yes, stats, err } if yes { - return yes, nil + return yes, stats, nil } } case *tree.Revoke: if gp.Typ == tree.RevokeTypePrivilege { - return checkRevokePrivilege() + yes, err := checkRevokePrivilege() + return yes, stats, err } case *tree.GrantPrivilege: - yes, err := checkGrantPrivilege(gp) + yes, delta, err := checkGrantPrivilege(gp) + stats.Add(&delta) if err != nil { - return yes, err + return yes, stats, err } if yes { - return yes, nil + return yes, stats, nil } case *tree.RevokePrivilege: - return checkRevokePrivilege() + yes, err := checkRevokePrivilege() + return yes, stats, err case *tree.ShowAccounts: - return checkShowAccountsPrivilege() + yes, err := checkShowAccountsPrivilege() + return yes, stats, err case *tree.ShowAccountUpgrade: - return tenant.IsMoAdminRole(), nil + return tenant.IsMoAdminRole(), stats, nil case *tree.ShowLogserviceReplicas, *tree.ShowLogserviceStores, *tree.ShowLogserviceSettings, *tree.SetLogserviceSettings: - return checkShowLogservicePrivilege() + yes, err := checkShowLogservicePrivilege() + return yes, stats, err case *tree.UpgradeStatement: - return tenant.IsMoAdminRole(), nil + return tenant.IsMoAdminRole(), stats, nil case *tree.BackupStart: - return checkBackUpStartPrivilege() + yes, err := checkBackUpStartPrivilege() + return yes, stats, err case *tree.CreateCDC, *tree.ShowCDC, *tree.PauseCDC, *tree.DropCDC, *tree.ResumeCDC, *tree.RestartCDC: - return checkCdcTaskPrivilege() + yes, err := checkCdcTaskPrivilege() + return yes, stats, err } } - return false, nil + return false, stats, nil } func checkTenantExistsOrNot(ctx context.Context, bh BackgroundExec, userName string) (bool, error) { diff --git a/pkg/frontend/authenticate_test.go b/pkg/frontend/authenticate_test.go index 5d3c2ee70aaf4..d8c76a7870795 100644 --- a/pkg/frontend/authenticate_test.go +++ b/pkg/frontend/authenticate_test.go @@ -587,7 +587,7 @@ func Test_determineCreateAccount(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -621,7 +621,7 @@ func Test_determineCreateAccount(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeFalse) }) @@ -658,7 +658,7 @@ func Test_determineCreateUser(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -703,7 +703,7 @@ func Test_determineCreateUser(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -755,7 +755,7 @@ func Test_determineCreateUser(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeFalse) }) @@ -793,7 +793,7 @@ func Test_determineDropUser(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -838,7 +838,7 @@ func Test_determineDropUser(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -890,7 +890,7 @@ func Test_determineDropUser(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeFalse) }) @@ -927,7 +927,7 @@ func Test_determineCreateRole(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -972,7 +972,7 @@ func Test_determineCreateRole(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -1024,7 +1024,7 @@ func Test_determineCreateRole(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeFalse) }) @@ -1061,7 +1061,7 @@ func Test_determineDropRole(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -1106,7 +1106,7 @@ func Test_determineDropRole(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -1158,7 +1158,7 @@ func Test_determineDropRole(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeFalse) }) @@ -1197,7 +1197,7 @@ func Test_determineGrantRole(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -1244,7 +1244,7 @@ func Test_determineGrantRole(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -1346,7 +1346,7 @@ func Test_determineGrantRole(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, g) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, g) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -1448,7 +1448,7 @@ func Test_determineGrantRole(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, g) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, g) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -1547,7 +1547,7 @@ func Test_determineGrantRole(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, g) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, g) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeFalse) }) @@ -1647,7 +1647,7 @@ func Test_determineGrantRole(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, g) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, g) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeFalse) }) @@ -1684,7 +1684,7 @@ func Test_determineRevokeRole(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -1730,7 +1730,7 @@ func Test_determineRevokeRole(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -1783,7 +1783,7 @@ func Test_determineRevokeRole(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeFalse) }) @@ -1829,7 +1829,7 @@ func Test_determineGrantPrivilege(t *testing.T) { ses := newSes(priv, ctrl) ses.SetDatabaseName("db") - ok, err := authenticateUserCanExecuteStatementWithObjectTypeNone(ses.GetTxnHandler().GetTxnCtx(), ses, stmt) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeNone(ses.GetTxnHandler().GetTxnCtx(), ses, stmt) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) } @@ -1931,7 +1931,7 @@ func Test_determineGrantPrivilege(t *testing.T) { bh.sql2result[sql] = newMrsForPrivilegeWGO(rows) } - ok, err := authenticateUserCanExecuteStatementWithObjectTypeNone(ses.GetTxnHandler().GetTxnCtx(), ses, stmt) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeNone(ses.GetTxnHandler().GetTxnCtx(), ses, stmt) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) } @@ -2042,7 +2042,7 @@ func Test_determineGrantPrivilege(t *testing.T) { bh.sql2result[sql] = newMrsForPrivilegeWGO(rows) } - ok, err := authenticateUserCanExecuteStatementWithObjectTypeNone(ses.GetTxnHandler().GetTxnCtx(), ses, stmt) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeNone(ses.GetTxnHandler().GetTxnCtx(), ses, stmt) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeFalse) } @@ -2124,7 +2124,7 @@ func Test_determineGrantPrivilege(t *testing.T) { bh.sql2result[sql] = newMrsForPrivilegeWGO(rows) } - ok, err := authenticateUserCanExecuteStatementWithObjectTypeNone(ses.GetTxnHandler().GetTxnCtx(), ses, stmt) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeNone(ses.GetTxnHandler().GetTxnCtx(), ses, stmt) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) } @@ -2216,7 +2216,7 @@ func Test_determineGrantPrivilege(t *testing.T) { bh.sql2result[sql] = newMrsForPrivilegeWGO(rows) } - ok, err := authenticateUserCanExecuteStatementWithObjectTypeNone(ses.GetTxnHandler().GetTxnCtx(), ses, stmt) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeNone(ses.GetTxnHandler().GetTxnCtx(), ses, stmt) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeFalse) } @@ -2277,7 +2277,7 @@ func Test_determineGrantPrivilege(t *testing.T) { bh.sql2result[sql] = newMrsForPrivilegeWGO(rows) } - ok, err := authenticateUserCanExecuteStatementWithObjectTypeNone(ses.GetTxnHandler().GetTxnCtx(), ses, stmt) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeNone(ses.GetTxnHandler().GetTxnCtx(), ses, stmt) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) } @@ -2349,7 +2349,7 @@ func Test_determineGrantPrivilege(t *testing.T) { bh.sql2result[sql] = newMrsForPrivilegeWGO(rows) } - ok, err := authenticateUserCanExecuteStatementWithObjectTypeNone(ses.GetTxnHandler().GetTxnCtx(), ses, stmt) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeNone(ses.GetTxnHandler().GetTxnCtx(), ses, stmt) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeFalse) } @@ -2416,7 +2416,7 @@ func TestBackUpStatementPrivilege(t *testing.T) { } ses.SetTenantInfo(tenant) - ok, err := authenticateUserCanExecuteStatementWithObjectTypeNone(ses.GetTxnHandler().GetTxnCtx(), ses, stmt) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeNone(ses.GetTxnHandler().GetTxnCtx(), ses, stmt) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -2437,7 +2437,7 @@ func TestBackUpStatementPrivilege(t *testing.T) { } ses.SetTenantInfo(tenant) - ok, err := authenticateUserCanExecuteStatementWithObjectTypeNone(ses.GetTxnHandler().GetTxnCtx(), ses, stmt) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeNone(ses.GetTxnHandler().GetTxnCtx(), ses, stmt) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeFalse) }) @@ -2474,7 +2474,7 @@ func Test_determineCreateDatabase(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -2519,7 +2519,7 @@ func Test_determineCreateDatabase(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -2571,7 +2571,7 @@ func Test_determineCreateDatabase(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeFalse) }) @@ -2609,7 +2609,7 @@ func Test_determineDropDatabase(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -2653,7 +2653,7 @@ func Test_determineDropDatabase(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -2704,7 +2704,7 @@ func Test_determineDropDatabase(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeFalse) }) @@ -2742,7 +2742,7 @@ func Test_determineShowDatabase(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -2787,7 +2787,7 @@ func Test_determineShowDatabase(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -2839,7 +2839,7 @@ func Test_determineShowDatabase(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeFalse) }) @@ -2879,7 +2879,7 @@ func Test_determineUseDatabase(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -2926,7 +2926,7 @@ func Test_determineUseDatabase(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -2980,7 +2980,7 @@ func Test_determineUseDatabase(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeFalse) }) @@ -3045,7 +3045,7 @@ func Test_determineCreateTable(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -3119,7 +3119,7 @@ func Test_determineCreateTable(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -3198,7 +3198,7 @@ func Test_determineCreateTable(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeFalse) }) @@ -3259,7 +3259,7 @@ func Test_determineDropTable(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -3333,7 +3333,7 @@ func Test_determineDropTable(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -3412,7 +3412,7 @@ func Test_determineDropTable(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(ses.GetTxnHandler().GetTxnCtx(), ses, nil) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeFalse) }) @@ -3553,7 +3553,7 @@ func Test_determineDML(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeDatabaseAndTable(ses.GetTxnHandler().GetTxnCtx(), ses, a.stmt, a.p) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeDatabaseAndTable(ses.GetTxnHandler().GetTxnCtx(), ses, a.stmt, a.p) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) } @@ -3651,7 +3651,7 @@ func Test_determineDML(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeDatabaseAndTable(ses.GetTxnHandler().GetTxnCtx(), ses, a.stmt, a.p) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeDatabaseAndTable(ses.GetTxnHandler().GetTxnCtx(), ses, a.stmt, a.p) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) } @@ -3741,7 +3741,7 @@ func Test_determineDML(t *testing.T) { bhStub := gostub.StubFunc(&NewBackgroundExec, bh) defer bhStub.Reset() - ok, err := authenticateUserCanExecuteStatementWithObjectTypeDatabaseAndTable(ses.GetTxnHandler().GetTxnCtx(), ses, a.stmt, a.p) + ok, _, err := authenticateUserCanExecuteStatementWithObjectTypeDatabaseAndTable(ses.GetTxnHandler().GetTxnCtx(), ses, a.stmt, a.p) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeFalse) } @@ -7507,6 +7507,11 @@ func newBh(ctrl *gomock.Controller, sql2result map[string]ExecResult) Background bh.EXPECT().GetExecResultSet().DoAndReturn(func() []interface{} { return []interface{}{sql2result[currentSql]} }).AnyTimes() + bh.EXPECT().GetExecStatsArray().DoAndReturn(func() statistic.StatsArray { + var stats statistic.StatsArray + stats.Reset() + return stats + }).AnyTimes() return bh } @@ -8487,7 +8492,7 @@ func TestCheckRoleWhetherTableOwner(t *testing.T) { }) bh.sql2result[sql] = mrs - _, err := checkRoleWhetherTableOwner(ses.GetTxnHandler().GetTxnCtx(), ses, "db1", "t1", true) + _, _, err := checkRoleWhetherTableOwner(ses.GetTxnHandler().GetTxnCtx(), ses, "db1", "t1", true) convey.So(err, convey.ShouldBeNil) }) @@ -8535,7 +8540,7 @@ func TestCheckRoleWhetherTableOwner(t *testing.T) { }) bh.sql2result[sql] = mrs - ok, err := checkRoleWhetherTableOwner(ses.GetTxnHandler().GetTxnCtx(), ses, "db1", "t1", true) + ok, _, err := checkRoleWhetherTableOwner(ses.GetTxnHandler().GetTxnCtx(), ses, "db1", "t1", true) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -8577,7 +8582,7 @@ func TestCheckRoleWhetherTableOwner(t *testing.T) { }) bh.sql2result[sql] = mrs - ok, err := checkRoleWhetherTableOwner(ses.GetTxnHandler().GetTxnCtx(), ses, "db1", "t1", false) + ok, _, err := checkRoleWhetherTableOwner(ses.GetTxnHandler().GetTxnCtx(), ses, "db1", "t1", false) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeFalse) }) @@ -8621,7 +8626,7 @@ func TestCheckRoleWhetherDatabaseOwner(t *testing.T) { }) bh.sql2result[sql] = mrs - ok, err := checkRoleWhetherDatabaseOwner(ses.GetTxnHandler().GetTxnCtx(), ses, "db1", true) + ok, _, err := checkRoleWhetherDatabaseOwner(ses.GetTxnHandler().GetTxnCtx(), ses, "db1", true) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -8670,7 +8675,7 @@ func TestCheckRoleWhetherDatabaseOwner(t *testing.T) { }) bh.sql2result[sql] = mrs - ok, err := checkRoleWhetherDatabaseOwner(ses.GetTxnHandler().GetTxnCtx(), ses, "db1", true) + ok, _, err := checkRoleWhetherDatabaseOwner(ses.GetTxnHandler().GetTxnCtx(), ses, "db1", true) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeTrue) }) @@ -8712,7 +8717,7 @@ func TestCheckRoleWhetherDatabaseOwner(t *testing.T) { }) bh.sql2result[sql] = mrs - ok, err := checkRoleWhetherDatabaseOwner(ses.GetTxnHandler().GetTxnCtx(), ses, "db1", false) + ok, _, err := checkRoleWhetherDatabaseOwner(ses.GetTxnHandler().GetTxnCtx(), ses, "db1", false) convey.So(err, convey.ShouldBeNil) convey.So(ok, convey.ShouldBeFalse) }) diff --git a/pkg/frontend/back_exec.go b/pkg/frontend/back_exec.go index 9397fb2008b6d..6460b1a254308 100644 --- a/pkg/frontend/back_exec.go +++ b/pkg/frontend/back_exec.go @@ -354,7 +354,8 @@ func doComQueryInBack( defer span.End() // Instantiate StatsInfo to track SQL resource statistics - statsInfo := new(statistic.StatsInfo) + //statsInfo := new(statistic.StatsInfo) + statsInfo := statistic.NewStatsInfo() statsInfo.ParseStage.ParseStartTime = beginInstant execCtx.reqCtx = statistic.ContextWithStatsInfo(execCtx.reqCtx, statsInfo) execCtx.input = input diff --git a/pkg/frontend/computation_wrapper.go b/pkg/frontend/computation_wrapper.go index d7333178d7a42..e601b6d552b0b 100644 --- a/pkg/frontend/computation_wrapper.go +++ b/pkg/frontend/computation_wrapper.go @@ -175,11 +175,14 @@ func (cwft *TxnComputationWrapper) GetServerStatus() uint16 { return uint16(cwft.ses.GetTxnHandler().GetServerStatus()) } -func checkResultQueryPrivilege(proc *process.Process, p *plan.Plan, reqCtx context.Context, sid string, ses *Session) error { +func checkResultQueryPrivilege(proc *process.Process, p *plan.Plan, reqCtx context.Context, sid string, ses *Session) (statistic.StatsArray, error) { var ids []string var err error + var stats statistic.StatsArray + stats.Reset() + if ids, err = isResultQuery(proc, p); err != nil || ids == nil { - return err + return stats, err } return checkPrivilege(sid, ids, reqCtx, ses) } @@ -188,20 +191,26 @@ func checkResultQueryPrivilege(proc *process.Process, p *plan.Plan, reqCtx conte func (cwft *TxnComputationWrapper) Compile(any any, fill func(*batch.Batch, *perfcounter.CounterSet) error) (interface{}, error) { var originSQL string var span trace.Span + var err error + execCtx := any.(*ExecCtx) execCtx.reqCtx, span = trace.Start(execCtx.reqCtx, "TxnComputationWrapper.Compile", trace.WithKind(trace.SpanKindStatement)) defer span.End(trace.WithStatementExtra(cwft.ses.GetTxnId(), cwft.ses.GetStmtId(), cwft.ses.GetSqlOfStmt())) - var err error defer RecordStatementTxnID(execCtx.reqCtx, cwft.ses) if cwft.ses.GetTxnHandler().HasTempEngine() { updateTempStorageInCtx(execCtx, cwft.proc, cwft.ses.GetTxnHandler().GetTempStorage()) } + stats := statistic.StatsInfoFromContext(execCtx.reqCtx) cacheHit := cwft.plan != nil if !cacheHit { - cwft.plan, err = buildPlan(execCtx.reqCtx, cwft.ses, cwft.ses.GetTxnCompileCtx(), cwft.stmt) + cwft.plan, err = buildPlanWithAuthorization(execCtx.reqCtx, cwft.ses, cwft.ses.GetTxnCompileCtx(), cwft.stmt) + if err != nil { + return nil, err + } + //cwft.plan, err = buildPlan(execCtx.reqCtx, cwft.ses, cwft.ses.GetTxnCompileCtx(), cwft.stmt) } else if cwft.ses != nil && cwft.ses.GetTenantInfo() != nil && !cwft.ses.IsBackgroundSession() { var accId uint32 accId, err = defines.GetAccountId(execCtx.reqCtx) @@ -209,16 +218,29 @@ func (cwft *TxnComputationWrapper) Compile(any any, fill func(*batch.Batch, *per return nil, err } cwft.ses.SetAccountId(accId) - err = authenticateCanExecuteStatementAndPlan(execCtx.reqCtx, cwft.ses.(*Session), cwft.stmt, cwft.plan) - } - if err != nil { - return nil, err + + //err = authenticateCanExecuteStatementAndPlan(execCtx.reqCtx, cwft.ses.(*Session), cwft.stmt, cwft.plan) + authStats, err := authenticateCanExecuteStatementAndPlan(execCtx.reqCtx, cwft.ses.(*Session), cwft.stmt, cwft.plan) + if err != nil { + return nil, err + } + // record permission statistics. + stats.PermissionAuth.Add(&authStats) } + //if err != nil { + // return nil, err + //} if !cwft.ses.IsBackgroundSession() { cwft.ses.SetPlan(cwft.plan) - if err := checkResultQueryPrivilege(cwft.proc, cwft.plan, execCtx.reqCtx, cwft.ses.GetService(), cwft.ses.(*Session)); err != nil { + //if err := checkResultQueryPrivilege(cwft.proc, cwft.plan, execCtx.reqCtx, cwft.ses.GetService(), cwft.ses.(*Session)); err != nil { + // return nil, err + //} + + authStats, err := checkResultQueryPrivilege(cwft.proc, cwft.plan, execCtx.reqCtx, cwft.ses.GetService(), cwft.ses.(*Session)) + if err != nil { return nil, err } + stats.PermissionAuth.Add(&authStats) } if _, isTextProtExecute := cwft.stmt.(*tree.Execute); isTextProtExecute || execCtx.input.isBinaryProtExecute { @@ -232,9 +254,15 @@ func (cwft *TxnComputationWrapper) Compile(any any, fill func(*batch.Batch, *per if err != nil { return nil, err } - if err := checkResultQueryPrivilege(cwft.proc, plan, execCtx.reqCtx, cwft.ses.GetService(), cwft.ses.(*Session)); err != nil { + //if err := checkResultQueryPrivilege(cwft.proc, plan, execCtx.reqCtx, cwft.ses.GetService(), cwft.ses.(*Session)); err != nil { + // return nil, err + //} + authStats, err := checkResultQueryPrivilege(cwft.proc, plan, execCtx.reqCtx, cwft.ses.GetService(), cwft.ses.(*Session)) + if err != nil { return nil, err } + stats.PermissionAuth.Add(&authStats) + cwft.plan = plan cwft.stmt.Free() // reset plan & stmt @@ -510,6 +538,7 @@ func createCompile( ) retCompile.SetIsPrepare(isPrepare) retCompile.SetBuildPlanFunc(func(ctx context.Context) (*plan2.Plan, error) { + // No permission verification is required when retry execute buildPlan plan, err := buildPlan(ctx, ses, ses.GetTxnCompileCtx(), stmt) if err != nil { return nil, err diff --git a/pkg/frontend/connector.go b/pkg/frontend/connector.go index 27cb603358a5c..07cc16a556cdb 100644 --- a/pkg/frontend/connector.go +++ b/pkg/frontend/connector.go @@ -61,7 +61,8 @@ func handleCreateDynamicTable(ctx context.Context, ses *Session, st *tree.Create } } - generatedPlan, err := buildPlan(ctx, ses, ses.GetTxnCompileCtx(), st.AsSource) + generatedPlan, err := buildPlanWithAuthorization(ctx, ses, ses.GetTxnCompileCtx(), st.AsSource) + //generatedPlan, err := buildPlan(ctx, ses, ses.GetTxnCompileCtx(), st.AsSource) if err != nil { return err } diff --git a/pkg/frontend/mysql_cmd_executor.go b/pkg/frontend/mysql_cmd_executor.go index be73d974a91fe..4057d239ffd1e 100644 --- a/pkg/frontend/mysql_cmd_executor.go +++ b/pkg/frontend/mysql_cmd_executor.go @@ -1036,7 +1036,8 @@ func doExplainStmt(reqCtx context.Context, ses *Session, stmt *tree.ExplainStmt) } //get query optimizer and execute Optimize - exPlan, err := buildPlan(reqCtx, ses, ses.GetTxnCompileCtx(), stmt.Statement) + //exPlan, err := buildPlan(reqCtx, ses, ses.GetTxnCompileCtx(), stmt.Statement) + exPlan, err := buildPlanWithAuthorization(reqCtx, ses, ses.GetTxnCompileCtx(), stmt.Statement) if err != nil { return err } @@ -1153,7 +1154,8 @@ func createPrepareStmt( stmt tree.Statement, saveStmt tree.Statement) (*PrepareStmt, error) { - preparePlan, err := buildPlan(execCtx.reqCtx, ses, ses.GetTxnCompileCtx(), stmt) + //preparePlan, err := buildPlan(execCtx.reqCtx, ses, ses.GetTxnCompileCtx(), stmt) + preparePlan, err := buildPlanWithAuthorization(execCtx.reqCtx, ses, ses.GetTxnCompileCtx(), stmt) if err != nil { return nil, err } @@ -1200,7 +1202,8 @@ func createPrepareStmt( } func doDeallocate(ses *Session, execCtx *ExecCtx, st *tree.Deallocate) error { - deallocatePlan, err := buildPlan(execCtx.reqCtx, ses, ses.GetTxnCompileCtx(), st) + deallocatePlan, err := buildPlanWithAuthorization(execCtx.reqCtx, ses, ses.GetTxnCompileCtx(), st) + //deallocatePlan, err := buildPlan(execCtx.reqCtx, ses, ses.GetTxnCompileCtx(), st) if err != nil { return err } @@ -2000,7 +2003,6 @@ func buildPlan(reqCtx context.Context, ses FeSession, ctx plan2.CompilerContext, defer func() { cost := time.Since(start) - if txnOp != nil { txnTrace.GetService(ses.GetService()).AddTxnDurationAction( txnOp, @@ -2017,6 +2019,7 @@ func buildPlan(reqCtx context.Context, ses FeSession, ctx plan2.CompilerContext, planContext := ctx.GetContext() stats := statistic.StatsInfoFromContext(planContext) stats.PlanStart() + crs := new(perfcounter.CounterSet) planContext = perfcounter.AttachBuildPlanMarkKey(planContext, crs) ctx.SetContext(planContext) @@ -2034,17 +2037,18 @@ func buildPlan(reqCtx context.Context, ses FeSession, ctx plan2.CompilerContext, isPrepareStmt := false if ses != nil { - var accId uint32 - accId, err = defines.GetAccountId(reqCtx) + accId, err := defines.GetAccountId(reqCtx) if err != nil { return nil, err } ses.SetAccountId(accId) + if len(ses.GetSql()) > 8 { prefix := strings.ToLower(ses.GetSql()[:8]) isPrepareStmt = prefix == "execute " || prefix == "prepare " } } + // Handle specific statement types if s, ok := stmt.(*tree.Insert); ok { if _, ok := s.Rows.Select.(*tree.ValuesClause); ok { ret, err = plan2.BuildPlan(ctx, stmt, isPrepareStmt) @@ -2053,27 +2057,25 @@ func buildPlan(reqCtx context.Context, ses FeSession, ctx plan2.CompilerContext, } } } + if ret != nil { ret.IsPrepare = isPrepareStmt - if ses != nil && ses.GetTenantInfo() != nil && !ses.IsBackgroundSession() { - err = authenticateCanExecuteStatementAndPlan(reqCtx, ses.(*Session), stmt, ret) - if err != nil { - return nil, err - } - } return ret, err } + + // Default handling of various statements switch stmt := stmt.(type) { case *tree.Select, *tree.ParenSelect, *tree.ValuesStatement, *tree.Update, *tree.Delete, *tree.Insert, - *tree.ShowDatabases, *tree.ShowTables, *tree.ShowSequences, *tree.ShowColumns, *tree.ShowColumnNumber, *tree.ShowTableNumber, - *tree.ShowCreateDatabase, *tree.ShowCreateTable, *tree.ShowIndex, + *tree.ShowDatabases, *tree.ShowTables, *tree.ShowSequences, *tree.ShowColumns, *tree.ShowColumnNumber, + *tree.ShowTableNumber, *tree.ShowCreateDatabase, *tree.ShowCreateTable, *tree.ShowIndex, *tree.ExplainStmt, *tree.ExplainAnalyze, *tree.ExplainPhyPlan: opt := plan2.NewBaseOptimizer(ctx) optimized, err := opt.Optimize(stmt, isPrepareStmt) if err != nil { return nil, err } + ret = &plan2.Plan{ Plan: &plan2.Plan_Query{ Query: optimized, @@ -2082,18 +2084,37 @@ func buildPlan(reqCtx context.Context, ses FeSession, ctx plan2.CompilerContext, default: ret, err = plan2.BuildPlan(ctx, stmt, isPrepareStmt) } + if ret != nil { ret.IsPrepare = isPrepareStmt - if ses != nil && ses.GetTenantInfo() != nil && !ses.IsBackgroundSession() { - err = authenticateCanExecuteStatementAndPlan(reqCtx, ses.(*Session), stmt, ret) - if err != nil { - return nil, err - } - } } return ret, err } +// buildPlanWithAuthorization wraps the buildPlan function to perform permission checks +// after the plan has been successfully built. +func buildPlanWithAuthorization(reqCtx context.Context, ses FeSession, ctx plan2.CompilerContext, stmt tree.Statement) (*plan2.Plan, error) { + planContext := ctx.GetContext() + stats := statistic.StatsInfoFromContext(planContext) + + // Step 1: Call buildPlan to construct the execution plan + plan, err := buildPlan(reqCtx, ses, ctx, stmt) + if err != nil { + return nil, err + } + + // Step 2: Perform permission check after the plan is built + if ses != nil && ses.GetTenantInfo() != nil && !ses.IsBackgroundSession() { + authStats, err := authenticateCanExecuteStatementAndPlan(reqCtx, ses.(*Session), stmt, plan) + if err != nil { + return nil, err + } + // record permission statistics. + stats.PermissionAuth.Add(&authStats) + } + return plan, nil +} + func checkModify(plan0 *plan.Plan, ses FeSession) bool { if plan0 == nil { return true @@ -2225,91 +2246,107 @@ func incStatementErrorsCounter(tenant string, stmt tree.Statement) { } // authenticateUserCanExecuteStatement checks the user can execute the statement -func authenticateUserCanExecuteStatement(reqCtx context.Context, ses *Session, stmt tree.Statement) error { +func authenticateUserCanExecuteStatement(reqCtx context.Context, ses *Session, stmt tree.Statement) (statistic.StatsArray, error) { + var stats statistic.StatsArray + stats.Reset() + reqCtx, span := trace.Debug(reqCtx, "authenticateUserCanExecuteStatement") defer span.End() if getPu(ses.GetService()).SV.SkipCheckPrivilege { - return nil + return stats, nil } if ses.skipAuthForSpecialUser() { - return nil + return stats, nil } - var havePrivilege bool - var err error + //var havePrivilege bool + //var err error if ses.GetTenantInfo() != nil { ses.SetPrivilege(determinePrivilegeSetOfStatement(stmt)) // can or not execute in retricted status if ses.getRoutine() != nil && ses.getRoutine().isRestricted() && !ses.GetPrivilege().canExecInRestricted { - return moerr.NewInternalError(reqCtx, "do not have enough storage to execute the statement") + return stats, moerr.NewInternalError(reqCtx, "do not have enough storage to execute the statement") } // can or not execute in password expired status if ses.getRoutine() != nil && ses.getRoutine().isExpired() && !ses.GetPrivilege().canExecInPasswordExpired { - return moerr.NewInternalError(reqCtx, "password has expired, please change the password") + return stats, moerr.NewInternalError(reqCtx, "password has expired, please change the password") } - havePrivilege, err = authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(reqCtx, ses, stmt) + havePrivilege, delta, err := authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(reqCtx, ses, stmt) if err != nil { - return err + return stats, err } + stats.Add(&delta) if !havePrivilege { err = moerr.NewInternalError(reqCtx, "do not have privilege to execute the statement") - return err + return stats, err } - havePrivilege, err = authenticateUserCanExecuteStatementWithObjectTypeNone(reqCtx, ses, stmt) + havePrivilege, delta, err = authenticateUserCanExecuteStatementWithObjectTypeNone(reqCtx, ses, stmt) if err != nil { - return err + return stats, err } + stats.Add(&delta) if !havePrivilege { err = moerr.NewInternalError(reqCtx, "do not have privilege to execute the statement") - return err + return stats, err } } - return err + return stats, nil } // authenticateCanExecuteStatementAndPlan checks the user can execute the statement and its plan -func authenticateCanExecuteStatementAndPlan(reqCtx context.Context, ses *Session, stmt tree.Statement, p *plan.Plan) error { +func authenticateCanExecuteStatementAndPlan(reqCtx context.Context, ses *Session, stmt tree.Statement, p *plan.Plan) (statistic.StatsArray, error) { + var stats statistic.StatsArray + stats.Reset() + _, task := gotrace.NewTask(reqCtx, "frontend.authenticateCanExecuteStatementAndPlan") defer task.End() if getPu(ses.GetService()).SV.SkipCheckPrivilege { - return nil + return stats, nil } if ses.skipAuthForSpecialUser() { - return nil + return stats, nil } - yes, err := authenticateUserCanExecuteStatementWithObjectTypeDatabaseAndTable(reqCtx, ses, stmt, p) + yes, delta, err := authenticateUserCanExecuteStatementWithObjectTypeDatabaseAndTable(reqCtx, ses, stmt, p) if err != nil { - return err + return stats, err } + stats.Add(&delta) + if !yes { - return moerr.NewInternalError(reqCtx, "do not have privilege to execute the statement") + return stats, moerr.NewInternalError(reqCtx, "do not have privilege to execute the statement") } - return nil + return stats, nil } // authenticatePrivilegeOfPrepareAndExecute checks the user can execute the Prepare or Execute statement -func authenticateUserCanExecutePrepareOrExecute(reqCtx context.Context, ses *Session, stmt tree.Statement, p *plan.Plan) error { +func authenticateUserCanExecutePrepareOrExecute(reqCtx context.Context, ses *Session, stmt tree.Statement, p *plan.Plan) (statistic.StatsArray, error) { + var stats statistic.StatsArray + stats.Reset() + _, task := gotrace.NewTask(reqCtx, "frontend.authenticateUserCanExecutePrepareOrExecute") defer task.End() if getPu(ses.GetService()).SV.SkipCheckPrivilege { - return nil + return stats, nil } - err := authenticateUserCanExecuteStatement(reqCtx, ses, stmt) + delta, err := authenticateUserCanExecuteStatement(reqCtx, ses, stmt) if err != nil { - return err + return stats, err } - err = authenticateCanExecuteStatementAndPlan(reqCtx, ses, stmt, p) + stats.Add(&delta) + + delta, err = authenticateCanExecuteStatementAndPlan(reqCtx, ses, stmt, p) if err != nil { - return err + return stats, err } - return err + stats.Add(&delta) + return stats, err } // canExecuteStatementInUncommittedTxn checks the user can execute the statement in an uncommitted transaction @@ -3022,7 +3059,8 @@ func doComQuery(ses *Session, execCtx *ExecCtx, input *UserInput) (retErr error) proc.Base.SessionInfo.User = userNameOnly proc.Base.SessionInfo.QueryId = ses.getQueryId(input.isInternal()) - statsInfo := new(statistic.StatsInfo) + //statsInfo := new(statistic.StatsInfo) + statsInfo := statistic.NewStatsInfo() statsInfo.ParseStage.ParseStartTime = beginInstant execCtx.reqCtx = statistic.ContextWithStatsInfo(execCtx.reqCtx, statsInfo) @@ -3107,11 +3145,12 @@ func doComQuery(ses *Session, execCtx *ExecCtx, input *UserInput) (retErr error) tenant := ses.GetTenantNameWithStmt(stmt) //skip PREPARE statement here if ses.GetTenantInfo() != nil && !IsPrepareStatement(stmt) { - err = authenticateUserCanExecuteStatement(execCtx.reqCtx, ses, stmt) + authStats, err := authenticateUserCanExecuteStatement(execCtx.reqCtx, ses, stmt) if err != nil { logStatementStatus(execCtx.reqCtx, ses, stmt, fail, err) return err } + statsInfo.PermissionAuth.Add(&authStats) } /* @@ -3810,6 +3849,9 @@ func (h *marshalPlanHandler) Stats(ctx context.Context, ses FeSession) (statsByt statsByte.WithS3IOOutputCount(totalS3Output) statsByte.WithS3IOListCount(totalS3List) statsByte.WithS3IODeleteCount(totalS3Delete) + + // Additional permission authentication SQL statistics + statsByte.Add(&statsInfo.PermissionAuth) } return } diff --git a/pkg/frontend/query_result.go b/pkg/frontend/query_result.go index 1a7c9b3f1f8fb..c2eb8a835fa00 100644 --- a/pkg/frontend/query_result.go +++ b/pkg/frontend/query_result.go @@ -39,6 +39,7 @@ import ( "github.com/matrixorigin/matrixone/pkg/perfcounter" "github.com/matrixorigin/matrixone/pkg/sql/colexec" "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" + "github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace/statistic" "github.com/matrixorigin/matrixone/pkg/vm/process" ) @@ -357,19 +358,22 @@ func isResultQuery(proc *process.Process, p *plan.Plan) ([]string, error) { return uuids, nil } -func checkPrivilege(sid string, uuids []string, reqCtx context.Context, ses *Session) error { +func checkPrivilege(sid string, uuids []string, reqCtx context.Context, ses *Session) (statistic.StatsArray, error) { + var stats statistic.StatsArray + stats.Reset() + f := getPu(ses.GetService()).FileService for _, id := range uuids { // var size int64 = -1 path := catalog.BuildQueryResultMetaPath(ses.GetTenantInfo().GetTenant(), id) reader, err := ioutil.NewFileReader(f, path) if err != nil { - return err + return stats, err } idxs := []uint16{catalog.PLAN_IDX, catalog.AST_IDX} bats, closeCB, err := reader.LoadAllColumns(reqCtx, idxs, ses.GetMemPool()) if err != nil { - return err + return stats, err } defer func() { if closeCB != nil { @@ -380,18 +384,21 @@ func checkPrivilege(sid string, uuids []string, reqCtx context.Context, ses *Ses p := bat.Vecs[0].UnsafeGetStringAt(0) pn := &plan.Plan{} if err = pn.Unmarshal([]byte(p)); err != nil { - return err + return stats, err } a := bat.Vecs[1].UnsafeGetStringAt(0) var ast tree.Statement if ast, err = simpleAstUnmarshal([]byte(a)); err != nil { - return err + return stats, err } - if err = authenticateCanExecuteStatementAndPlan(reqCtx, ses, ast, pn); err != nil { - return err + + delta, err := authenticateCanExecuteStatementAndPlan(reqCtx, ses, ast, pn) + if err != nil { + return stats, err } + stats.Add(&delta) } - return nil + return stats, nil } type simpleAst struct { diff --git a/pkg/frontend/self_handle.go b/pkg/frontend/self_handle.go index e21a36cbbe495..f8b19ed67c7e2 100644 --- a/pkg/frontend/self_handle.go +++ b/pkg/frontend/self_handle.go @@ -65,7 +65,7 @@ func execInFrontend(ses *Session, execCtx *ExecCtx) (stats statistic.StatsArray, if err != nil { return } - err = authenticateUserCanExecutePrepareOrExecute(execCtx.reqCtx, ses, execCtx.prepareStmt.PrepareStmt, execCtx.prepareStmt.PreparePlan.GetDcl().GetPrepare().GetPlan()) + _, err = authenticateUserCanExecutePrepareOrExecute(execCtx.reqCtx, ses, execCtx.prepareStmt.PrepareStmt, execCtx.prepareStmt.PreparePlan.GetDcl().GetPrepare().GetPlan()) if err != nil { ses.RemovePrepareStmt(execCtx.prepareStmt.Name) return @@ -77,7 +77,7 @@ func execInFrontend(ses *Session, execCtx *ExecCtx) (stats statistic.StatsArray, if err != nil { return } - err = authenticateUserCanExecutePrepareOrExecute(execCtx.reqCtx, ses, execCtx.prepareStmt.PrepareStmt, execCtx.prepareStmt.PreparePlan.GetDcl().GetPrepare().GetPlan()) + _, err = authenticateUserCanExecutePrepareOrExecute(execCtx.reqCtx, ses, execCtx.prepareStmt.PrepareStmt, execCtx.prepareStmt.PreparePlan.GetDcl().GetPrepare().GetPlan()) if err != nil { ses.RemovePrepareStmt(execCtx.prepareStmt.Name) return diff --git a/pkg/frontend/session_test.go b/pkg/frontend/session_test.go index ec7211a98d8db..e6e38a1143795 100644 --- a/pkg/frontend/session_test.go +++ b/pkg/frontend/session_test.go @@ -679,7 +679,7 @@ func TestCheckPasswordExpired(t *testing.T) { rp, err := mysql.Parse(ctx, sql, 1) defer rp[0].Free() assert.NoError(t, err) - err = authenticateUserCanExecuteStatement(ctx, ses, rp[0]) + _, err = authenticateUserCanExecuteStatement(ctx, ses, rp[0]) assert.Error(t, err) // exexpir can execute stmt @@ -687,7 +687,7 @@ func TestCheckPasswordExpired(t *testing.T) { rp, err = mysql.Parse(ctx, sql, 1) defer rp[0].Free() assert.NoError(t, err) - err = authenticateUserCanExecuteStatement(ctx, ses, rp[0]) + _, err = authenticateUserCanExecuteStatement(ctx, ses, rp[0]) assert.Error(t, err) // getPasswordLifetime error diff --git a/pkg/perfcounter/update.go b/pkg/perfcounter/update.go index 02e436e2a1fe3..0cd5accc72ead 100644 --- a/pkg/perfcounter/update.go +++ b/pkg/perfcounter/update.go @@ -24,18 +24,25 @@ func Update(ctx context.Context, fn func(*CounterSet), extraCounterSets ...*Coun // Check if InternalExecutorKey is present in the context. // No action is taken when InternalExecutorKey is present. if ctx.Value(TxnExecutorKey{}) == nil { - // If the InternalExecutorKey does not exist, it means that you are using a generic executor. - if counter1, ok := ctx.Value(ExecPipelineMarkKey{}).(*CounterSet); ok && counter1 != nil { - // No code here; At this stage, independent functions are used to statistically analyze S3 requests - } else if counter2, ok := ctx.Value(CompilePlanMarkKey{}).(*CounterSet); ok && counter2 != nil { - fn(counter2) - } else if counter3, ok := ctx.Value(BuildPlanMarkKey{}).(*CounterSet); ok && counter3 != nil { - fn(counter3) - } + if ctx.Value(BackgroundExecutorKey{}) != nil { + // Handling the usage of S3 resources when calling a function + if counter, ok := ctx.Value(S3RequestKey{}).(*CounterSet); ok && counter != nil { + fn(counter) + } + } else { + // If the InternalExecutorKey does not exist, it means that you are using a generic executor. + if counter1, ok := ctx.Value(ExecPipelineMarkKey{}).(*CounterSet); ok && counter1 != nil { + // No code here; At this stage, independent functions are used to statistically analyze S3 requests + } else if counter2, ok := ctx.Value(CompilePlanMarkKey{}).(*CounterSet); ok && counter2 != nil { + fn(counter2) + } else if counter3, ok := ctx.Value(BuildPlanMarkKey{}).(*CounterSet); ok && counter3 != nil { + fn(counter3) + } - // Handling the usage of S3 resources when calling a function - if counter, ok := ctx.Value(S3RequestKey{}).(*CounterSet); ok && counter != nil { - fn(counter) + // Handling the usage of S3 resources when calling a function + if counter, ok := ctx.Value(S3RequestKey{}).(*CounterSet); ok && counter != nil { + fn(counter) + } } } diff --git a/pkg/sql/compile/analyze_module.go b/pkg/sql/compile/analyze_module.go index 721714902871a..5d18b5e8fb2a7 100644 --- a/pkg/sql/compile/analyze_module.go +++ b/pkg/sql/compile/analyze_module.go @@ -526,6 +526,7 @@ func explainResourceOverview(queryResult *util.RunResult, statsInfo *statistic.S statsInfo.PlanStage.BuildPlanStatsIOConsumption, statsInfo.IOAccessTimeConsumption, statsInfo.S3FSPrefetchFileIOMergerTimeConsumption)) + buffer.WriteString(fmt.Sprintf("\t\t- Permission Authentication Stats Array: %v \n", statsInfo.PermissionAuth)) //------------------------------------------------------------------------------------------------------- if option.Analyze { diff --git a/pkg/sql/models/show_phyplan.go b/pkg/sql/models/show_phyplan.go index 4ae57b193ff28..c70884c3c5ad5 100644 --- a/pkg/sql/models/show_phyplan.go +++ b/pkg/sql/models/show_phyplan.go @@ -103,6 +103,7 @@ func explainResourceOverview(phy *PhyPlan, statsInfo *statistic.StatsInfo, optio statsInfo.PlanStage.BuildPlanStatsIOConsumption, statsInfo.IOAccessTimeConsumption, statsInfo.S3FSPrefetchFileIOMergerTimeConsumption)) + buffer.WriteString(fmt.Sprintf("\t\t- Permission Authentication Stats Array: %v \n", statsInfo.PermissionAuth)) //------------------------------------------------------------------------------------------------------- if option == AnalyzeOption { diff --git a/pkg/sql/plan/function/func_mo_explain_phy_test.go b/pkg/sql/plan/function/func_mo_explain_phy_test.go index 9dc1b06d053a7..23f5496ef3e48 100644 --- a/pkg/sql/plan/function/func_mo_explain_phy_test.go +++ b/pkg/sql/plan/function/func_mo_explain_phy_test.go @@ -922,6 +922,7 @@ Scope 1 (Magic: Merge, mcpu: 1, Receiver: [0]) CPU Usage: - Total CPU Time: 91033157ns - CPU Time Detail: Parse(162026)+BuildPlan(649910)+Compile(299370)+PhyExec(304651393)+PrepareRun(178265)-PreRunWaitLock(0)-PlanStatsIO(0)-IOAccess(214917833)-IOMerge(0) + - Permission Authentication Stats Array: [0 0 0 0 0 0 0 0 0 0 0] Physical Plan Deployment: LOCAL SCOPES: Scope 1 (Magic: Merge, mcpu: 1, Receiver: [0]) @@ -979,6 +980,7 @@ Scope 1 (Magic: Merge, mcpu: 1, Receiver: [0]) CPU Usage: - Total CPU Time: 91033157ns - CPU Time Detail: Parse(162026)+BuildPlan(649910)+Compile(299370)+PhyExec(304651393)+PrepareRun(178265)-PreRunWaitLock(0)-PlanStatsIO(0)-IOAccess(214917833)-IOMerge(0) + - Permission Authentication Stats Array: [0 0 0 0 0 0 0 0 0 0 0] Query Build Plan Stage: - CPU Time: 649910ns - S3List:0, S3Head:0, S3Put:0, S3Get:0, S3Delete:0, S3DeleteMul:0 diff --git a/pkg/util/trace/impl/motrace/statistic/stats_array.go b/pkg/util/trace/impl/motrace/statistic/stats_array.go index 39ad628a5c747..bfda85a4bff23 100644 --- a/pkg/util/trace/impl/motrace/statistic/stats_array.go +++ b/pkg/util/trace/impl/motrace/statistic/stats_array.go @@ -338,6 +338,9 @@ type StatsInfo struct { OtherStage struct { TxnIncrStatementS3 S3Request `json:"TxnIncrStatementS3"` } + // stats: [5,241837539,5622976.000,0,0,149,0,1,8.4507,0,0] + // stats: [5,241837539,5622976.000,0,0,149,0,1,8.4507,0,0] + PermissionAuth StatsArray `json:"PermissionAuth"` // FileService(S3 or localFS) Read Data time Consumption IOAccessTimeConsumption int64 @@ -370,6 +373,12 @@ func (s S3Request) CountPUT() int64 { return s.Put } func (s S3Request) CountGET() int64 { return s.Head + s.Get } func (s S3Request) CountDELETE() int64 { return s.Delete + s.DeleteMul } +func NewStatsInfo() *StatsInfo { + s := new(StatsInfo) + s.PermissionAuth.Reset() + return s +} + func (stats *StatsInfo) CompileStart() { if stats == nil { return @@ -654,6 +663,7 @@ func (stats *StatsInfo) Reset() { return } *stats = StatsInfo{} + stats.PermissionAuth.Reset() } func ContextWithStatsInfo(requestCtx context.Context, stats *StatsInfo) context.Context { diff --git a/test/distributed/cases/function/func_make_date.result b/test/distributed/cases/function/func_make_date.result index 35ac691140fee..4bcbd6a989c89 100644 --- a/test/distributed/cases/function/func_make_date.result +++ b/test/distributed/cases/function/func_make_date.result @@ -24,7 +24,7 @@ years_passed 0 SELECT IF(MAKEDATE(YEAR(NOW()), 366) < NOW(), '闰年', '平年') AS leap_year_status; leap_year_status -平年 +闰年 create database abc; use abc; CREATE TABLE employees (