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

     1  // Copyright 2022 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  	"fmt"
    19  	"strings"
    20  	"sync"
    21  	"time"
    22  
    23  	"github.com/dolthub/vitess/go/sqltypes"
    24  
    25  	"github.com/dolthub/go-mysql-server/sql"
    26  	"github.com/dolthub/go-mysql-server/sql/expression"
    27  	"github.com/dolthub/go-mysql-server/sql/in_mem_table"
    28  	"github.com/dolthub/go-mysql-server/sql/types"
    29  )
    30  
    31  const tablesPrivTblName = "tables_priv"
    32  
    33  var (
    34  	errTablesPrivEntry = fmt.Errorf("the converter for the `tables_priv` table was given an unknown entry")
    35  	errTablesPrivRow   = fmt.Errorf("the converter for the `tables_priv` table was given a row belonging to an unknown schema")
    36  
    37  	tablesPrivTblSchema sql.Schema
    38  )
    39  
    40  func UserAddTablesRow(ctx *sql.Context, row sql.Row, user *User) (*User, error) {
    41  	if len(row) != len(tablesPrivTblSchema) {
    42  		return nil, errTablesPrivRow
    43  	}
    44  
    45  	dbName, ok := row[tablesPrivTblColIndex_Db].(string)
    46  	if !ok {
    47  		return nil, errTablesPrivRow
    48  	}
    49  	tblName, ok := row[tablesPrivTblColIndex_Table_name].(string)
    50  	if !ok {
    51  		return nil, errTablesPrivRow
    52  	}
    53  	tablePrivs, ok := row[tablesPrivTblColIndex_Table_priv].(uint64)
    54  	if !ok {
    55  		return nil, errTablesPrivRow
    56  	}
    57  	tablePrivStrs, err := tablesPrivTblSchema[tablesPrivTblColIndex_Table_priv].Type.(sql.SetType).BitsToString(tablePrivs)
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  
    62  	user = UserCopy(user)
    63  
    64  	var privs []sql.PrivilegeType
    65  	for _, val := range strings.Split(tablePrivStrs, ",") {
    66  		switch val {
    67  		case "Select":
    68  			privs = append(privs, sql.PrivilegeType_Select)
    69  		case "Insert":
    70  			privs = append(privs, sql.PrivilegeType_Insert)
    71  		case "Update":
    72  			privs = append(privs, sql.PrivilegeType_Update)
    73  		case "Delete":
    74  			privs = append(privs, sql.PrivilegeType_Delete)
    75  		case "Create":
    76  			privs = append(privs, sql.PrivilegeType_Create)
    77  		case "Drop":
    78  			privs = append(privs, sql.PrivilegeType_Drop)
    79  		case "Grant":
    80  			privs = append(privs, sql.PrivilegeType_GrantOption)
    81  		case "References":
    82  			privs = append(privs, sql.PrivilegeType_References)
    83  		case "Index":
    84  			privs = append(privs, sql.PrivilegeType_Index)
    85  		case "Alter":
    86  			privs = append(privs, sql.PrivilegeType_Alter)
    87  		case "Create View":
    88  			privs = append(privs, sql.PrivilegeType_CreateView)
    89  		case "Show view":
    90  			privs = append(privs, sql.PrivilegeType_ShowView)
    91  		case "Trigger":
    92  			privs = append(privs, sql.PrivilegeType_Trigger)
    93  		case "":
    94  		default:
    95  			return nil, errTablesPrivRow
    96  		}
    97  	}
    98  	user.PrivilegeSet.AddTable(dbName, tblName, privs...)
    99  	return user, nil
   100  }
   101  
   102  func UserRemoveTablesRow(ctx *sql.Context, row sql.Row, user *User) (*User, error) {
   103  	if len(row) != len(tablesPrivTblSchema) {
   104  		return nil, errTablesPrivRow
   105  	}
   106  
   107  	db, ok := row[tablesPrivTblColIndex_Db].(string)
   108  	if !ok {
   109  		return nil, errTablesPrivRow
   110  	}
   111  	tbl, ok := row[tablesPrivTblColIndex_Table_name].(string)
   112  	if !ok {
   113  		return nil, errTablesPrivRow
   114  	}
   115  
   116  	user = UserCopy(user)
   117  	user.PrivilegeSet.ClearTable(db, tbl)
   118  	return user, nil
   119  }
   120  
   121  func UserFromTablesRow(ctx *sql.Context, row sql.Row) (*User, error) {
   122  	if len(row) != len(tablesPrivTblSchema) {
   123  		return nil, errTablesPrivRow
   124  	}
   125  	host, ok := row[tablesPrivTblColIndex_Host].(string)
   126  	if !ok {
   127  		return nil, errTablesPrivRow
   128  	}
   129  	user, ok := row[tablesPrivTblColIndex_User].(string)
   130  	if !ok {
   131  		return nil, errTablesPrivRow
   132  	}
   133  	return &User{
   134  		Host: host,
   135  		User: user,
   136  	}, nil
   137  }
   138  
   139  func UserToTablesRows(ctx *sql.Context, user *User) ([]sql.Row, error) {
   140  	newRow := func() (sql.Row, error) {
   141  		row := make(sql.Row, len(tablesPrivTblSchema))
   142  		var err error
   143  		for i, col := range tablesPrivTblSchema {
   144  			row[i], err = col.Default.Eval(ctx, nil)
   145  			if err != nil {
   146  				return nil, err // Should never happen, schema is static
   147  			}
   148  		}
   149  		return row, nil
   150  	}
   151  
   152  	var rows []sql.Row
   153  	for _, dbSet := range user.PrivilegeSet.GetDatabases() {
   154  		for _, tblSet := range dbSet.GetTables() {
   155  			if tblSet.Count() == 0 {
   156  				continue
   157  			}
   158  			row, err := newRow()
   159  			if err != nil {
   160  				return nil, err
   161  			}
   162  
   163  			row[tablesPrivTblColIndex_User] = user.User
   164  			row[tablesPrivTblColIndex_Host] = user.Host
   165  			row[tablesPrivTblColIndex_Db] = dbSet.Name()
   166  			row[tablesPrivTblColIndex_Table_name] = tblSet.Name()
   167  
   168  			var privs []string
   169  			for _, priv := range tblSet.ToSlice() {
   170  				switch priv {
   171  				case sql.PrivilegeType_Select:
   172  					privs = append(privs, "Select")
   173  				case sql.PrivilegeType_Insert:
   174  					privs = append(privs, "Insert")
   175  				case sql.PrivilegeType_Update:
   176  					privs = append(privs, "Update")
   177  				case sql.PrivilegeType_Delete:
   178  					privs = append(privs, "Delete")
   179  				case sql.PrivilegeType_Create:
   180  					privs = append(privs, "Create")
   181  				case sql.PrivilegeType_Drop:
   182  					privs = append(privs, "Drop")
   183  				case sql.PrivilegeType_GrantOption:
   184  					privs = append(privs, "Grant")
   185  				case sql.PrivilegeType_References:
   186  					privs = append(privs, "References")
   187  				case sql.PrivilegeType_Index:
   188  					privs = append(privs, "Index")
   189  				case sql.PrivilegeType_Alter:
   190  					privs = append(privs, "Alter")
   191  				case sql.PrivilegeType_CreateView:
   192  					privs = append(privs, "Create View")
   193  				case sql.PrivilegeType_ShowView:
   194  					privs = append(privs, "Show view")
   195  				case sql.PrivilegeType_Trigger:
   196  					privs = append(privs, "Trigger")
   197  				}
   198  			}
   199  			formattedSet, _, err := tablesPrivTblSchema[tablesPrivTblColIndex_Table_priv].Type.Convert(strings.Join(privs, ","))
   200  			if err != nil {
   201  				return nil, err
   202  			}
   203  			row[tablesPrivTblColIndex_Table_priv] = formattedSet.(uint64)
   204  			rows = append(rows, row)
   205  		}
   206  	}
   207  
   208  	return rows, nil
   209  }
   210  
   211  func NewUserTablesIndexedSetTable(set in_mem_table.IndexedSet[*User], lock, rlock sync.Locker) *in_mem_table.MultiIndexedSetTable[*User] {
   212  	table := in_mem_table.NewMultiIndexedSetTable[*User](
   213  		tablesPrivTblName,
   214  		tablesPrivTblSchema,
   215  		sql.Collation_utf8mb3_bin,
   216  		set,
   217  		in_mem_table.MultiValueOps[*User]{
   218  			ToRows:    UserToTablesRows,
   219  			FromRow:   UserFromTablesRow,
   220  			AddRow:    UserAddTablesRow,
   221  			DeleteRow: UserRemoveTablesRow,
   222  		},
   223  		lock,
   224  		rlock,
   225  	)
   226  	return table
   227  }
   228  
   229  // init creates the schema for the "tables_priv" Grant Table.
   230  func init() {
   231  	// Types
   232  	char32_utf8_bin := types.MustCreateString(sqltypes.Char, 32, sql.Collation_utf8_bin)
   233  	char64_utf8_bin := types.MustCreateString(sqltypes.Char, 64, sql.Collation_utf8_bin)
   234  	char255_ascii_general_ci := types.MustCreateString(sqltypes.Char, 255, sql.Collation_ascii_general_ci)
   235  	set_ColumnPrivs_utf8_general_ci := types.MustCreateSetType([]string{"Select", "Insert", "Update", "References"}, sql.Collation_utf8_general_ci)
   236  	set_TablePrivs_utf8_general_ci := types.MustCreateSetType([]string{
   237  		"Select", "Insert", "Update", "Delete", "Create", "Drop", "Grant",
   238  		"References", "Index", "Alter", "Create View", "Show view", "Trigger"}, sql.Collation_utf8_general_ci)
   239  	varchar288_utf8_bin := types.MustCreateString(sqltypes.VarChar, 288, sql.Collation_utf8_bin)
   240  
   241  	// Column Templates
   242  	char32_utf8_bin_not_null_default_empty := &sql.Column{
   243  		Type:     char32_utf8_bin,
   244  		Default:  mustDefault(expression.NewLiteral("", char32_utf8_bin), char32_utf8_bin, true, false),
   245  		Nullable: false,
   246  	}
   247  	char64_utf8_bin_not_null_default_empty := &sql.Column{
   248  		Type:     char64_utf8_bin,
   249  		Default:  mustDefault(expression.NewLiteral("", char64_utf8_bin), char64_utf8_bin, true, false),
   250  		Nullable: false,
   251  	}
   252  	char255_ascii_general_ci_not_null_default_empty := &sql.Column{
   253  		Type:     char255_ascii_general_ci,
   254  		Default:  mustDefault(expression.NewLiteral("", char255_ascii_general_ci), char255_ascii_general_ci, true, false),
   255  		Nullable: false,
   256  	}
   257  	set_ColumnPrivs_utf8_general_ci_not_null_default_empty := &sql.Column{
   258  		Type:     set_ColumnPrivs_utf8_general_ci,
   259  		Default:  mustDefault(expression.NewLiteral("", set_ColumnPrivs_utf8_general_ci), set_ColumnPrivs_utf8_general_ci, true, false),
   260  		Nullable: false,
   261  	}
   262  	set_TablePrivs_utf8_general_ci_not_null_default_empty := &sql.Column{
   263  		Type:     set_TablePrivs_utf8_general_ci,
   264  		Default:  mustDefault(expression.NewLiteral("", set_TablePrivs_utf8_general_ci), set_TablePrivs_utf8_general_ci, true, false),
   265  		Nullable: false,
   266  	}
   267  	timestamp_not_null_default_epoch := &sql.Column{
   268  		Type:     types.Timestamp,
   269  		Default:  mustDefault(expression.NewLiteral(time.Unix(1, 0).UTC(), types.Timestamp), types.Timestamp, true, false),
   270  		Nullable: false,
   271  	}
   272  	varchar288_utf8_bin_not_null_default_empty := &sql.Column{
   273  		Type:     varchar288_utf8_bin,
   274  		Default:  mustDefault(expression.NewLiteral("", varchar288_utf8_bin), varchar288_utf8_bin, true, false),
   275  		Nullable: false,
   276  	}
   277  
   278  	tablesPrivTblSchema = sql.Schema{
   279  		columnTemplate("Host", tablesPrivTblName, true, char255_ascii_general_ci_not_null_default_empty),
   280  		columnTemplate("Db", tablesPrivTblName, true, char64_utf8_bin_not_null_default_empty),
   281  		columnTemplate("User", tablesPrivTblName, true, char32_utf8_bin_not_null_default_empty),
   282  		columnTemplate("Table_name", tablesPrivTblName, true, char64_utf8_bin_not_null_default_empty),
   283  		columnTemplate("Grantor", tablesPrivTblName, false, varchar288_utf8_bin_not_null_default_empty),
   284  		columnTemplate("Timestamp", tablesPrivTblName, false, timestamp_not_null_default_epoch),
   285  		columnTemplate("Table_priv", tablesPrivTblName, false, set_TablePrivs_utf8_general_ci_not_null_default_empty),
   286  		columnTemplate("Column_priv", tablesPrivTblName, false, set_ColumnPrivs_utf8_general_ci_not_null_default_empty),
   287  	}
   288  }
   289  
   290  // These represent the column indexes of the "tables_priv" Grant Table.
   291  const (
   292  	tablesPrivTblColIndex_Host int = iota
   293  	tablesPrivTblColIndex_Db
   294  	tablesPrivTblColIndex_User
   295  	tablesPrivTblColIndex_Table_name
   296  	tablesPrivTblColIndex_Grantor
   297  	tablesPrivTblColIndex_Timestamp
   298  	tablesPrivTblColIndex_Table_priv
   299  	tablesPrivTblColIndex_Column_priv
   300  )