github.com/dolthub/go-mysql-server@v0.18.0/sql/mysql_db/procs_priv.go (about)

     1  // Copyright 2023 Dolthub, Inc.
     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 mysql_db
    16  
    17  import (
    18  	"strings"
    19  	"sync"
    20  	"time"
    21  
    22  	"github.com/dolthub/vitess/go/sqltypes"
    23  
    24  	"github.com/dolthub/go-mysql-server/sql"
    25  	"github.com/dolthub/go-mysql-server/sql/expression"
    26  	"github.com/dolthub/go-mysql-server/sql/in_mem_table"
    27  	"github.com/dolthub/go-mysql-server/sql/types"
    28  )
    29  
    30  const procsPrivTblName = "procs_priv"
    31  
    32  var procsPrivTblSchema = buildProcsPrivSchema()
    33  
    34  func NewUserProcsIndexedSetTable(set in_mem_table.IndexedSet[*User], lock, rlock sync.Locker) *in_mem_table.MultiIndexedSetTable[*User] {
    35  	table := in_mem_table.NewMultiIndexedSetTable[*User](
    36  		procsPrivTblName,
    37  		procsPrivTblSchema,
    38  		sql.Collation_utf8mb3_bin,
    39  		set,
    40  		in_mem_table.MultiValueOps[*User]{
    41  			ToRows:    UserToProcsPrivRows,
    42  			FromRow:   UserFromProcsPrivRow,
    43  			AddRow:    UserAddProcsPrivRow,
    44  			DeleteRow: UserRemoveProcsPrivRow,
    45  		},
    46  		lock,
    47  		rlock,
    48  	)
    49  	return table
    50  }
    51  
    52  func newEmptyRow(ctx *sql.Context) sql.Row {
    53  	row := make(sql.Row, len(procsPrivTblSchema))
    54  	var err error
    55  	for i, col := range procsPrivTblSchema {
    56  		row[i], err = col.Default.Eval(ctx, nil)
    57  		if err != nil {
    58  			panic(err) // Schema is static. New rows should never fail.
    59  		}
    60  	}
    61  	return row
    62  }
    63  
    64  func UserToProcsPrivRows(ctx *sql.Context, user *User) ([]sql.Row, error) {
    65  
    66  	var ans []sql.Row
    67  	for _, dbSet := range user.PrivilegeSet.GetDatabases() {
    68  		for _, routineSet := range dbSet.GetRoutines() {
    69  			if routineSet.Count() == 0 {
    70  				continue
    71  			}
    72  			row := newEmptyRow(ctx)
    73  
    74  			row[procsPrivTblColIndex_Host] = user.Host
    75  			row[procsPrivTblColIndex_Db] = dbSet.Name()
    76  			row[procsPrivTblColIndex_User] = user.User
    77  			row[procsPrivTblColIndex_RoutineName] = routineSet.RoutineName()
    78  			row[procsPrivTblColIndex_RoutineType] = routineSet.RoutineType()
    79  
    80  			var privs []string
    81  			for _, priv := range routineSet.ToSlice() {
    82  				switch priv {
    83  				case sql.PrivilegeType_Execute:
    84  					privs = append(privs, "Execute")
    85  				case sql.PrivilegeType_GrantOption:
    86  					privs = append(privs, "Grant") // MySQL prints just "Grant", and not "Grant Option"
    87  				case sql.PrivilegeType_AlterRoutine:
    88  					privs = append(privs, "Alter Routine")
    89  				}
    90  			}
    91  			privsStr := strings.Join(privs, ",")
    92  			row[procsPrivTblColIndex_ProcPriv] = privsStr
    93  
    94  			ans = append(ans, row)
    95  		}
    96  	}
    97  
    98  	return ans, nil
    99  }
   100  
   101  func UserFromProcsPrivRow(ctx *sql.Context, row sql.Row) (*User, error) {
   102  	panic("implement me") // Currently inaccessible code path.
   103  }
   104  
   105  func UserAddProcsPrivRow(ctx *sql.Context, row sql.Row, user *User) (*User, error) {
   106  	panic("implement me") // Currently inaccessible code path.
   107  }
   108  
   109  func UserRemoveProcsPrivRow(ctx *sql.Context, row sql.Row, user *User) (*User, error) {
   110  	panic("implement me") // Currently inaccessible code path.
   111  }
   112  
   113  // buildProcsPrivSchema builds the schema for the "procs_priv" Grant Table.
   114  // MySQL Table for reference:
   115  //
   116  // mysql> show create table mysql.procs_priv:
   117  //
   118  // CREATE TABLE `procs_priv` (
   119  //
   120  //	 `Host` char(255) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT '',
   121  //	 `Db` char(64) COLLATE utf8mb3_bin NOT NULL DEFAULT '',
   122  //	 `User` char(32) COLLATE utf8mb3_bin NOT NULL DEFAULT '',
   123  //	 `Routine_name` char(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '',
   124  //	 `Routine_type` enum('FUNCTION','PROCEDURE') COLLATE utf8mb3_bin NOT NULL,
   125  //	 `Grantor` varchar(288) COLLATE utf8mb3_bin NOT NULL DEFAULT '',
   126  //	 `Proc_priv` set('Execute','Alter Routine','Grant') CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '',
   127  //	 `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
   128  //	 PRIMARY KEY (`Host`,`User`,`Db`,`Routine_name`,`Routine_type`),
   129  //	 KEY `Grantor` (`Grantor`
   130  //	)
   131  func buildProcsPrivSchema() sql.Schema {
   132  	len255_asciii := types.MustCreateString(sqltypes.Char, 255, sql.Collation_ascii_general_ci)
   133  	len64_utf8_bin := types.MustCreateString(sqltypes.Char, 64, sql.Collation_utf8_bin)
   134  	len64_utf8_gen := types.MustCreateString(sqltypes.Char, 64, sql.Collation_utf8_general_ci)
   135  	len32_utf8 := types.MustCreateString(sqltypes.Char, 32, sql.Collation_utf8_bin)
   136  	routine_types_enum := types.MustCreateEnumType([]string{"FUNCTION", "PROCEDURE"}, sql.Collation_utf8_bin)
   137  	varchar288_utf8 := types.MustCreateString(sqltypes.VarChar, 288, sql.Collation_utf8_bin)
   138  	set_privs := types.MustCreateSetType([]string{"Execute", "Alter Routine", "Grant"}, sql.Collation_utf8_general_ci)
   139  
   140  	return sql.Schema{
   141  		columnTemplate("Host", procsPrivTblName, true, &sql.Column{
   142  			Type:     len255_asciii,
   143  			Default:  mustDefault(expression.NewLiteral("", len255_asciii), len255_asciii, true, false),
   144  			Nullable: false}),
   145  		columnTemplate("Db", procsPrivTblName, true, &sql.Column{
   146  			Type:     len64_utf8_bin,
   147  			Default:  mustDefault(expression.NewLiteral("", len64_utf8_bin), len64_utf8_bin, true, false),
   148  			Nullable: false}),
   149  		columnTemplate("User", procsPrivTblName, true, &sql.Column{
   150  			Type:     len32_utf8,
   151  			Default:  mustDefault(expression.NewLiteral("", len32_utf8), len32_utf8, true, false),
   152  			Nullable: false}),
   153  		columnTemplate("Routine_name", procsPrivTblName, true, &sql.Column{
   154  			Type:     len64_utf8_gen,
   155  			Default:  mustDefault(expression.NewLiteral("", len64_utf8_gen), len64_utf8_gen, true, false),
   156  			Nullable: false}),
   157  		columnTemplate("Routine_type", procsPrivTblName, true, &sql.Column{
   158  			Type:     routine_types_enum,
   159  			Default:  mustDefault(expression.NewLiteral("PROCEDURE", routine_types_enum), routine_types_enum, true, false),
   160  			Nullable: false}),
   161  		columnTemplate("Grantor", procsPrivTblName, false, &sql.Column{
   162  			Type:     varchar288_utf8,
   163  			Default:  mustDefault(expression.NewLiteral("", varchar288_utf8), varchar288_utf8, true, false),
   164  			Nullable: false}),
   165  		columnTemplate("Proc_priv", procsPrivTblName, false, &sql.Column{
   166  			Type:     set_privs,
   167  			Default:  mustDefault(expression.NewLiteral("", set_privs), set_privs, true, false),
   168  			Nullable: false}),
   169  		columnTemplate("Timestamp", tablesPrivTblName, false, &sql.Column{
   170  			Type:     types.Timestamp,
   171  			Default:  mustDefault(expression.NewLiteral(time.Unix(1, 0).UTC(), types.Timestamp), types.Timestamp, true, false),
   172  			Nullable: false}),
   173  	}
   174  }
   175  
   176  // The column indexes of the "procs_priv" Grant Table.
   177  // https://dev.mysql.com/doc/refman/8.0/en/grant-tables.html#grant-tables-procs-priv
   178  // https://mariadb.com/kb/en/mysqlprocs_priv-table/
   179  const (
   180  	procsPrivTblColIndex_Host int = iota
   181  	procsPrivTblColIndex_Db
   182  	procsPrivTblColIndex_User
   183  	procsPrivTblColIndex_RoutineName
   184  	procsPrivTblColIndex_RoutineType
   185  	procsPrivTblColIndex_Grantor
   186  	procsPrivTblColIndex_ProcPriv
   187  	procsPrivTblColIndex_Timestamp
   188  )