github.com/matrixorigin/matrixone@v1.2.0/pkg/frontend/system_initialize.go (about) 1 // Copyright 2024 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package frontend 16 17 import ( 18 "context" 19 "fmt" 20 "os" 21 "time" 22 23 "github.com/matrixorigin/matrixone/pkg/catalog" 24 "github.com/matrixorigin/matrixone/pkg/common/moerr" 25 "github.com/matrixorigin/matrixone/pkg/config" 26 "github.com/matrixorigin/matrixone/pkg/container/types" 27 "github.com/matrixorigin/matrixone/pkg/container/vector" 28 "github.com/matrixorigin/matrixone/pkg/util/executor" 29 ) 30 31 // InitSysTenant initializes the tenant SYS before any tenants and accepting any requests 32 // during the system is booting. 33 func InitSysTenant(ctx context.Context, txn executor.TxnExecutor, finalVersion string) (err error) { 34 txn.Use(catalog.MO_CATALOG) 35 res, err := txn.Exec(createDbInformationSchemaSql, executor.StatementOption{}) 36 if err != nil { 37 return err 38 } 39 res.Close() 40 41 exists, err := checkSysExistsOrNotWithTxn(ctx, txn) 42 if err != nil { 43 return err 44 } 45 46 if !exists { 47 if err = createTablesInMoCatalog(ctx, txn, finalVersion); err != nil { 48 return err 49 } 50 } 51 return err 52 } 53 54 // createTablesInMoCatalog creates catalog tables in the database mo_catalog. 55 func createTablesInMoCatalog(ctx context.Context, txn executor.TxnExecutor, finalVersion string) error { 56 var initMoAccount string 57 var initDataSqls []string 58 59 addSqlIntoSet := func(sql string) { 60 initDataSqls = append(initDataSqls, sql) 61 } 62 63 //create tables for the tenant 64 for _, sql := range createSqls { 65 addSqlIntoSet(sql) 66 } 67 68 //initialize the default data of tables for the tenant 69 //step 1: add new tenant entry to the mo_account 70 initMoAccount = fmt.Sprintf(initMoAccountFormat, sysAccountID, sysAccountName, rootName, sysAccountStatus, types.CurrentTimestamp().String2(time.UTC, 0), sysAccountComments, finalVersion) 71 addSqlIntoSet(initMoAccount) 72 73 //step 2:add new role entries to the mo_role 74 75 initMoRole1 := fmt.Sprintf(initMoRoleFormat, moAdminRoleID, moAdminRoleName, rootID, moAdminRoleID, types.CurrentTimestamp().String2(time.UTC, 0), "") 76 initMoRole2 := fmt.Sprintf(initMoRoleFormat, publicRoleID, publicRoleName, rootID, moAdminRoleID, types.CurrentTimestamp().String2(time.UTC, 0), "") 77 addSqlIntoSet(initMoRole1) 78 addSqlIntoSet(initMoRole2) 79 80 //step 3:add new user entry to the mo_user 81 defaultPassword := rootPassword 82 if d := os.Getenv(defaultPasswordEnv); d != "" { 83 defaultPassword = d 84 } 85 86 //encryption the password 87 encryption := HashPassWord(defaultPassword) 88 89 initMoUser1 := fmt.Sprintf(initMoUserFormat, rootID, rootHost, rootName, encryption, rootStatus, types.CurrentTimestamp().String2(time.UTC, 0), rootExpiredTime, rootLoginType, rootCreatorID, rootOwnerRoleID, rootDefaultRoleID) 90 initMoUser2 := fmt.Sprintf(initMoUserFormat, dumpID, dumpHost, dumpName, encryption, dumpStatus, types.CurrentTimestamp().String2(time.UTC, 0), dumpExpiredTime, dumpLoginType, dumpCreatorID, dumpOwnerRoleID, dumpDefaultRoleID) 91 addSqlIntoSet(initMoUser1) 92 addSqlIntoSet(initMoUser2) 93 94 //step4: add new entries to the mo_role_privs 95 //moadmin role 96 for _, t := range entriesOfMoAdminForMoRolePrivsFor { 97 entry := privilegeEntriesMap[t] 98 initMoRolePriv := fmt.Sprintf(initMoRolePrivFormat, 99 moAdminRoleID, moAdminRoleName, 100 entry.objType, entry.objId, 101 entry.privilegeId, entry.privilegeId.String(), entry.privilegeLevel, 102 rootID, types.CurrentTimestamp().String2(time.UTC, 0), 103 entry.withGrantOption) 104 addSqlIntoSet(initMoRolePriv) 105 } 106 107 //public role 108 for _, t := range entriesOfPublicForMoRolePrivsFor { 109 entry := privilegeEntriesMap[t] 110 initMoRolePriv := fmt.Sprintf(initMoRolePrivFormat, 111 publicRoleID, publicRoleName, 112 entry.objType, entry.objId, 113 entry.privilegeId, entry.privilegeId.String(), entry.privilegeLevel, 114 rootID, types.CurrentTimestamp().String2(time.UTC, 0), 115 entry.withGrantOption) 116 addSqlIntoSet(initMoRolePriv) 117 } 118 119 //step5: add new entries to the mo_user_grant 120 121 initMoUserGrant1 := fmt.Sprintf(initMoUserGrantFormat, moAdminRoleID, rootID, types.CurrentTimestamp().String2(time.UTC, 0), false) 122 initMoUserGrant2 := fmt.Sprintf(initMoUserGrantFormat, publicRoleID, rootID, types.CurrentTimestamp().String2(time.UTC, 0), false) 123 addSqlIntoSet(initMoUserGrant1) 124 addSqlIntoSet(initMoUserGrant2) 125 initMoUserGrant4 := fmt.Sprintf(initMoUserGrantFormat, moAdminRoleID, dumpID, types.CurrentTimestamp().String2(time.UTC, 0), false) 126 initMoUserGrant5 := fmt.Sprintf(initMoUserGrantFormat, publicRoleID, dumpID, types.CurrentTimestamp().String2(time.UTC, 0), false) 127 addSqlIntoSet(initMoUserGrant4) 128 addSqlIntoSet(initMoUserGrant5) 129 130 //setp6: add new entries to the mo_mysql_compatibility_mode 131 pu := config.GetParameterUnit(ctx) 132 for _, variable := range gSysVarsDefs { 133 if _, ok := configInitVariables[variable.Name]; ok { 134 addsql := addInitSystemVariablesSql(sysAccountID, sysAccountName, variable.Name, pu) 135 if len(addsql) != 0 { 136 addSqlIntoSet(addsql) 137 } 138 } else { 139 initMoMysqlCompatibilityMode := fmt.Sprintf(initMoMysqlCompatbilityModeWithoutDataBaseFormat, sysAccountID, sysAccountName, variable.Name, getVariableValue(variable.Default), true) 140 addSqlIntoSet(initMoMysqlCompatibilityMode) 141 } 142 } 143 144 //fill the mo_account, mo_role, mo_user, mo_role_privs, mo_user_grant, mo_mysql_compatibility_mode 145 for _, sql := range initDataSqls { 146 res, err := txn.Exec(sql, executor.StatementOption{}) 147 if err != nil { 148 return err 149 } 150 res.Close() 151 } 152 return nil 153 } 154 155 // checkSysExistsOrNot checks the SYS tenant exists or not. 156 func checkSysExistsOrNotWithTxn(ctx context.Context, txn executor.TxnExecutor) (bool, error) { 157 if res, err := txn.Exec("show databases;", executor.StatementOption{}); err != nil { 158 return false, err 159 } else { 160 count := 0 161 res.ReadRows(func(rows int, cols []*vector.Vector) bool { 162 count += rows 163 return true 164 }) 165 res.Close() 166 167 if count == 0 { 168 return false, moerr.NewInternalError(ctx, "it must have result set") 169 } 170 } 171 172 if res, err := txn.Exec("show tables from mo_catalog;", executor.StatementOption{}); err != nil { 173 return false, err 174 } else { 175 count := 0 176 sysTenantExists := false 177 res.ReadRows(func(rows int, cols []*vector.Vector) bool { 178 for i := 0; i < rows; i++ { 179 count += i 180 tableName := cols[0].GetStringAt(i) 181 // if there is at least one catalog table, it denotes the sys tenant exists. 182 if _, ok := sysWantedTables[tableName]; ok { 183 sysTenantExists = true 184 } 185 } 186 return true 187 }) 188 res.Close() 189 190 if count == 0 { 191 return false, moerr.NewInternalError(ctx, "it must have result set") 192 } 193 194 if sysTenantExists { 195 return true, nil 196 } 197 } 198 return false, nil 199 } 200 201 // GenSQLForInsertUpgradeAccountPrivilege generates SQL statements for inserting upgrade account permissions 202 func GenSQLForInsertUpgradeAccountPrivilege() string { 203 entry := privilegeEntry{ 204 privilegeId: PrivilegeTypeUpgradeAccount, 205 privilegeLevel: privilegeLevelStar, 206 objType: objectTypeAccount, 207 objId: objectIDAll, 208 withGrantOption: false, 209 databaseName: "", 210 tableName: "", 211 privilegeEntryTyp: privilegeEntryTypeGeneral, 212 compound: nil, 213 } 214 return fmt.Sprintf(initMoRolePrivFormat, 215 moAdminRoleID, moAdminRoleName, 216 entry.objType, entry.objId, 217 entry.privilegeId, entry.privilegeId.String(), entry.privilegeLevel, 218 rootID, types.CurrentTimestamp().String2(time.UTC, 0), 219 entry.withGrantOption) 220 } 221 222 // GenSQLForCheckUpgradeAccountPrivilegeExist generates an SQL statement to check for the existence of upgrade account permissions. 223 func GenSQLForCheckUpgradeAccountPrivilegeExist() string { 224 entry := privilegeEntry{ 225 privilegeId: PrivilegeTypeUpgradeAccount, 226 privilegeLevel: privilegeLevelStar, 227 objType: objectTypeAccount, 228 objId: objectIDAll, 229 withGrantOption: false, 230 databaseName: "", 231 tableName: "", 232 privilegeEntryTyp: privilegeEntryTypeGeneral, 233 compound: nil, 234 } 235 236 sql := fmt.Sprintf("select * from mo_catalog.mo_role_privs where role_id = %d and obj_type = '%s' and obj_id = %d and privilege_id = %d and privilege_level = '%s'", 237 moAdminRoleID, entry.objType, entry.objId, entry.privilegeId, entry.privilegeLevel) 238 return sql 239 }