From 0b3e16b6bb356b8d593679c77e822a641ee82880 Mon Sep 17 00:00:00 2001 From: qingxinhome <758355272@qq.com> Date: Mon, 30 Dec 2024 09:56:14 +0800 Subject: [PATCH 1/7] add Permission authentication resource statistics --- pkg/frontend/authenticate.go | 245 +++++++++++------- pkg/frontend/mysql_cmd_executor.go | 81 +++--- .../impl/motrace/statistic/stats_array.go | 8 + 3 files changed, 206 insertions(+), 128 deletions(-) diff --git a/pkg/frontend/authenticate.go b/pkg/frontend/authenticate.go index c2f9db14ce95c..efae44abdc5ac 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 { @@ -6057,36 +6058,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 @@ -6112,14 +6117,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 @@ -6132,11 +6137,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. @@ -6183,19 +6188,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) { @@ -6210,23 +6215,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 ( @@ -6371,16 +6376,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;") @@ -6388,15 +6398,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. @@ -6460,17 +6470,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() { @@ -6480,13 +6494,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 } } @@ -6494,12 +6508,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. @@ -6512,60 +6528,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 @@ -6574,46 +6596,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() @@ -6621,27 +6645,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 @@ -6650,38 +6677,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 @@ -6690,27 +6717,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. @@ -6904,12 +6936,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 @@ -6935,26 +6972,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) { @@ -6973,7 +7010,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) { @@ -6995,7 +7032,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) { @@ -7090,21 +7127,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) } @@ -7137,45 +7180,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/mysql_cmd_executor.go b/pkg/frontend/mysql_cmd_executor.go index eb38d9cc43cf2..78b4d0409dfc1 100644 --- a/pkg/frontend/mysql_cmd_executor.go +++ b/pkg/frontend/mysql_cmd_executor.go @@ -2056,10 +2056,11 @@ 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) + authStats, err := authenticateCanExecuteStatementAndPlan(reqCtx, ses.(*Session), stmt, ret) if err != nil { return nil, err } + stats.PermissionAuth.Add(&authStats) } return ret, err } @@ -2085,10 +2086,11 @@ 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) + authStats, err := authenticateCanExecuteStatementAndPlan(reqCtx, ses.(*Session), stmt, ret) if err != nil { return nil, err } + stats.PermissionAuth.Add(&authStats) } } return ret, err @@ -2225,91 +2227,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 @@ -3107,11 +3125,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) } /* diff --git a/pkg/util/trace/impl/motrace/statistic/stats_array.go b/pkg/util/trace/impl/motrace/statistic/stats_array.go index 39ad628a5c747..1f9c28f1fbd50 100644 --- a/pkg/util/trace/impl/motrace/statistic/stats_array.go +++ b/pkg/util/trace/impl/motrace/statistic/stats_array.go @@ -339,6 +339,8 @@ type StatsInfo struct { TxnIncrStatementS3 S3Request `json:"TxnIncrStatementS3"` } + PermissionAuth StatsArray + // FileService(S3 or localFS) Read Data time Consumption IOAccessTimeConsumption int64 // S3 FileService Prefetch File IOMerge time Consumption @@ -370,6 +372,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 From 9aa45b3d64229d83a0fb6c196b7bfdb4209d3109 Mon Sep 17 00:00:00 2001 From: qingxinhome <758355272@qq.com> Date: Mon, 30 Dec 2024 20:30:03 +0800 Subject: [PATCH 2/7] append code --- pkg/frontend/back_exec.go | 3 +- pkg/frontend/buildPlan.go | 163 ++++++++++++++++++ pkg/frontend/computation_wrapper.go | 48 ++++-- pkg/frontend/mysql_cmd_executor.go | 3 +- pkg/frontend/query_result.go | 23 ++- pkg/frontend/self_handle.go | 4 +- .../impl/motrace/statistic/stats_array.go | 6 +- 7 files changed, 226 insertions(+), 24 deletions(-) create mode 100644 pkg/frontend/buildPlan.go 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/buildPlan.go b/pkg/frontend/buildPlan.go new file mode 100644 index 0000000000000..188a9fcef7c0b --- /dev/null +++ b/pkg/frontend/buildPlan.go @@ -0,0 +1,163 @@ +// Copyright 2024 Matrix Origin +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package frontend + +import ( + "context" + "strings" + "time" + + "github.com/matrixorigin/matrixone/pkg/defines" + "github.com/matrixorigin/matrixone/pkg/perfcounter" + "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" + plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan" + "github.com/matrixorigin/matrixone/pkg/txn/client" + txnTrace "github.com/matrixorigin/matrixone/pkg/txn/trace" + v2 "github.com/matrixorigin/matrixone/pkg/util/metric/v2" + "github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace/statistic" +) + +func buildPlanV1(reqCtx context.Context, ses FeSession, ctx plan2.CompilerContext, stmt tree.Statement) (*plan2.Plan, error) { + var ret *plan2.Plan + var err error + + txnOp := ctx.GetProcess().GetTxnOperator() + start := time.Now() + seq := uint64(0) + if txnOp != nil { + seq = txnOp.NextSequence() + txnTrace.GetService(ses.GetService()).AddTxnDurationAction( + txnOp, + client.BuildPlanEvent, + seq, + 0, + 0, + err) + } + + defer func() { + cost := time.Since(start) + if txnOp != nil { + txnTrace.GetService(ses.GetService()).AddTxnDurationAction( + txnOp, + client.BuildPlanEvent, + seq, + 0, + cost, + err) + } + v2.TxnStatementBuildPlanDurationHistogram.Observe(cost.Seconds()) + }() + + // NOTE: The context used by buildPlan comes from the CompilerContext object + planContext := ctx.GetContext() + stats := statistic.StatsInfoFromContext(planContext) + stats.PlanStart() + + crs := new(perfcounter.CounterSet) + planContext = perfcounter.AttachBuildPlanMarkKey(planContext, crs) + ctx.SetContext(planContext) + defer func() { + stats.AddBuildPlanS3Request(statistic.S3Request{ + List: crs.FileService.S3.List.Load(), + Head: crs.FileService.S3.Head.Load(), + Put: crs.FileService.S3.Put.Load(), + Get: crs.FileService.S3.Get.Load(), + Delete: crs.FileService.S3.Delete.Load(), + DeleteMul: crs.FileService.S3.DeleteMulti.Load(), + }) + stats.PlanEnd() + }() + + isPrepareStmt := false + if ses != nil { + 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) + if err != nil { + return nil, err + } + } + } + + // After building the plan, handle other types of statements + if ret != nil { + ret.IsPrepare = isPrepareStmt + 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.ExplainStmt, *tree.ExplainAnalyze, *tree.ExplainPhyPlan: + opt := plan2.NewBaseOptimizer(ctx) + optimized, err := opt.Optimize(stmt, isPrepareStmt) // isPrepareStmt = false + if err != nil { + return nil, err + } + + ret = &plan2.Plan{ + Plan: &plan2.Plan_Query{ + Query: optimized, + }, + } + default: + ret, err = plan2.BuildPlan(ctx, stmt, isPrepareStmt) + } + + if ret != nil { + ret.IsPrepare = isPrepareStmt + } + return ret, err +} + +// buildPlanWithAuthorization wraps the buildPlan function to perform permission checks +// after the plan has been successfully built. +func buildPlanWithAuthorizationV1(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 := buildPlanV1(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 +} diff --git a/pkg/frontend/computation_wrapper.go b/pkg/frontend/computation_wrapper.go index d7333178d7a42..157f0d385e3e7 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 = buildPlanWithAuthorizationV1(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 diff --git a/pkg/frontend/mysql_cmd_executor.go b/pkg/frontend/mysql_cmd_executor.go index 78b4d0409dfc1..b3ce9d019456e 100644 --- a/pkg/frontend/mysql_cmd_executor.go +++ b/pkg/frontend/mysql_cmd_executor.go @@ -3040,7 +3040,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) diff --git a/pkg/frontend/query_result.go b/pkg/frontend/query_result.go index e7e8132b7fe56..5bd196e0caca0 100644 --- a/pkg/frontend/query_result.go +++ b/pkg/frontend/query_result.go @@ -38,6 +38,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/engine/tae/blockio" "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 := blockio.NewFileReader(sid, 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/util/trace/impl/motrace/statistic/stats_array.go b/pkg/util/trace/impl/motrace/statistic/stats_array.go index 1f9c28f1fbd50..bfda85a4bff23 100644 --- a/pkg/util/trace/impl/motrace/statistic/stats_array.go +++ b/pkg/util/trace/impl/motrace/statistic/stats_array.go @@ -338,8 +338,9 @@ type StatsInfo struct { OtherStage struct { TxnIncrStatementS3 S3Request `json:"TxnIncrStatementS3"` } - - PermissionAuth StatsArray + // 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 @@ -662,6 +663,7 @@ func (stats *StatsInfo) Reset() { return } *stats = StatsInfo{} + stats.PermissionAuth.Reset() } func ContextWithStatsInfo(requestCtx context.Context, stats *StatsInfo) context.Context { From 2e82fc4e1b5bb154f508641c86c462ad90aee910 Mon Sep 17 00:00:00 2001 From: qingxinhome <758355272@qq.com> Date: Tue, 31 Dec 2024 12:15:29 +0800 Subject: [PATCH 3/7] Additional permission authentication SQL resource statistics --- pkg/frontend/authenticate_test.go | 123 +++++++++++++++-------------- pkg/frontend/mysql_cmd_executor.go | 2 + pkg/frontend/session_test.go | 4 +- pkg/sql/compile/analyze_module.go | 1 + pkg/sql/models/show_phyplan.go | 1 + 5 files changed, 70 insertions(+), 61 deletions(-) diff --git a/pkg/frontend/authenticate_test.go b/pkg/frontend/authenticate_test.go index b3aef63ec8023..f909998b20e94 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) } @@ -7505,6 +7505,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 } @@ -8485,7 +8490,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) }) @@ -8533,7 +8538,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) }) @@ -8575,7 +8580,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) }) @@ -8619,7 +8624,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) }) @@ -8668,7 +8673,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) }) @@ -8710,7 +8715,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/mysql_cmd_executor.go b/pkg/frontend/mysql_cmd_executor.go index b3ce9d019456e..ea8fcbe45c12d 100644 --- a/pkg/frontend/mysql_cmd_executor.go +++ b/pkg/frontend/mysql_cmd_executor.go @@ -3831,6 +3831,8 @@ func (h *marshalPlanHandler) Stats(ctx context.Context, ses FeSession) (statsByt statsByte.WithS3IOListCount(totalS3List) statsByte.WithS3IODeleteCount(totalS3Delete) } + // Additional permission authentication SQL statistics + statsByte.Add(&statsInfo.PermissionAuth) return } diff --git a/pkg/frontend/session_test.go b/pkg/frontend/session_test.go index b6156c68da8d5..c1d2f3dc81973 100644 --- a/pkg/frontend/session_test.go +++ b/pkg/frontend/session_test.go @@ -651,7 +651,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 @@ -659,7 +659,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/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 { From f1c38b914df13a38db9c9ae1f29b60770e386e93 Mon Sep 17 00:00:00 2001 From: qingxinhome <758355272@qq.com> Date: Tue, 31 Dec 2024 14:30:18 +0800 Subject: [PATCH 4/7] update ut test case --- pkg/sql/plan/function/func_mo_explain_phy_test.go | 2 ++ test/distributed/cases/function/func_make_date.result | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) 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/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 ( From 018d5e14595febdc0fdcfe84c2d01109725fa372 Mon Sep 17 00:00:00 2001 From: qingxinhome <758355272@qq.com> Date: Tue, 31 Dec 2024 15:46:34 +0800 Subject: [PATCH 5/7] imporve code --- pkg/frontend/buildPlan.go | 163 ---------------------------- pkg/frontend/computation_wrapper.go | 3 +- pkg/frontend/connector.go | 3 +- pkg/frontend/mysql_cmd_executor.go | 63 +++++++---- 4 files changed, 45 insertions(+), 187 deletions(-) delete mode 100644 pkg/frontend/buildPlan.go diff --git a/pkg/frontend/buildPlan.go b/pkg/frontend/buildPlan.go deleted file mode 100644 index 188a9fcef7c0b..0000000000000 --- a/pkg/frontend/buildPlan.go +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2024 Matrix Origin -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package frontend - -import ( - "context" - "strings" - "time" - - "github.com/matrixorigin/matrixone/pkg/defines" - "github.com/matrixorigin/matrixone/pkg/perfcounter" - "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" - plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan" - "github.com/matrixorigin/matrixone/pkg/txn/client" - txnTrace "github.com/matrixorigin/matrixone/pkg/txn/trace" - v2 "github.com/matrixorigin/matrixone/pkg/util/metric/v2" - "github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace/statistic" -) - -func buildPlanV1(reqCtx context.Context, ses FeSession, ctx plan2.CompilerContext, stmt tree.Statement) (*plan2.Plan, error) { - var ret *plan2.Plan - var err error - - txnOp := ctx.GetProcess().GetTxnOperator() - start := time.Now() - seq := uint64(0) - if txnOp != nil { - seq = txnOp.NextSequence() - txnTrace.GetService(ses.GetService()).AddTxnDurationAction( - txnOp, - client.BuildPlanEvent, - seq, - 0, - 0, - err) - } - - defer func() { - cost := time.Since(start) - if txnOp != nil { - txnTrace.GetService(ses.GetService()).AddTxnDurationAction( - txnOp, - client.BuildPlanEvent, - seq, - 0, - cost, - err) - } - v2.TxnStatementBuildPlanDurationHistogram.Observe(cost.Seconds()) - }() - - // NOTE: The context used by buildPlan comes from the CompilerContext object - planContext := ctx.GetContext() - stats := statistic.StatsInfoFromContext(planContext) - stats.PlanStart() - - crs := new(perfcounter.CounterSet) - planContext = perfcounter.AttachBuildPlanMarkKey(planContext, crs) - ctx.SetContext(planContext) - defer func() { - stats.AddBuildPlanS3Request(statistic.S3Request{ - List: crs.FileService.S3.List.Load(), - Head: crs.FileService.S3.Head.Load(), - Put: crs.FileService.S3.Put.Load(), - Get: crs.FileService.S3.Get.Load(), - Delete: crs.FileService.S3.Delete.Load(), - DeleteMul: crs.FileService.S3.DeleteMulti.Load(), - }) - stats.PlanEnd() - }() - - isPrepareStmt := false - if ses != nil { - 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) - if err != nil { - return nil, err - } - } - } - - // After building the plan, handle other types of statements - if ret != nil { - ret.IsPrepare = isPrepareStmt - 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.ExplainStmt, *tree.ExplainAnalyze, *tree.ExplainPhyPlan: - opt := plan2.NewBaseOptimizer(ctx) - optimized, err := opt.Optimize(stmt, isPrepareStmt) // isPrepareStmt = false - if err != nil { - return nil, err - } - - ret = &plan2.Plan{ - Plan: &plan2.Plan_Query{ - Query: optimized, - }, - } - default: - ret, err = plan2.BuildPlan(ctx, stmt, isPrepareStmt) - } - - if ret != nil { - ret.IsPrepare = isPrepareStmt - } - return ret, err -} - -// buildPlanWithAuthorization wraps the buildPlan function to perform permission checks -// after the plan has been successfully built. -func buildPlanWithAuthorizationV1(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 := buildPlanV1(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 -} diff --git a/pkg/frontend/computation_wrapper.go b/pkg/frontend/computation_wrapper.go index 157f0d385e3e7..e601b6d552b0b 100644 --- a/pkg/frontend/computation_wrapper.go +++ b/pkg/frontend/computation_wrapper.go @@ -206,7 +206,7 @@ func (cwft *TxnComputationWrapper) Compile(any any, fill func(*batch.Batch, *per cacheHit := cwft.plan != nil if !cacheHit { - cwft.plan, err = buildPlanWithAuthorizationV1(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 } @@ -538,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 ea8fcbe45c12d..b6726954385e9 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,28 +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() { - authStats, err := authenticateCanExecuteStatementAndPlan(reqCtx, ses.(*Session), stmt, ret) - if err != nil { - return nil, err - } - stats.PermissionAuth.Add(&authStats) - } 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, @@ -2083,19 +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() { - authStats, err := authenticateCanExecuteStatementAndPlan(reqCtx, ses.(*Session), stmt, ret) - if err != nil { - return nil, err - } - stats.PermissionAuth.Add(&authStats) - } } 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 From d5b2445dbe2dc11bb931ec98318dabcec45744ae Mon Sep 17 00:00:00 2001 From: qingxinhome <758355272@qq.com> Date: Tue, 31 Dec 2024 17:53:54 +0800 Subject: [PATCH 6/7] add code --- pkg/perfcounter/update.go | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) 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) + } } } From 701bda43e76d6de0ee068f8ee00cd972fd8e0616 Mon Sep 17 00:00:00 2001 From: qingxinhome <758355272@qq.com> Date: Wed, 8 Jan 2025 16:00:46 +0800 Subject: [PATCH 7/7] update code --- pkg/frontend/mysql_cmd_executor.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/frontend/mysql_cmd_executor.go b/pkg/frontend/mysql_cmd_executor.go index 1081c3e462fa1..4057d239ffd1e 100644 --- a/pkg/frontend/mysql_cmd_executor.go +++ b/pkg/frontend/mysql_cmd_executor.go @@ -3849,9 +3849,10 @@ 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) } - // Additional permission authentication SQL statistics - statsByte.Add(&statsInfo.PermissionAuth) return }