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  }