github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/dbs/dagger/dagger.go (about)

     1  // Copyright 2020 WHTCORPS INC, 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  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package dagger
    15  
    16  import (
    17  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    18  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    19  	"github.com/whtcorpsinc/milevadb/schemareplicant"
    20  	"github.com/whtcorpsinc/milevadb/stochastikctx"
    21  	"github.com/whtcorpsinc/milevadb/causet"
    22  	"github.com/whtcorpsinc/milevadb/soliton"
    23  )
    24  
    25  // Checker uses to check blocks dagger.
    26  type Checker struct {
    27  	ctx stochastikctx.Context
    28  	is  schemareplicant.SchemaReplicant
    29  }
    30  
    31  // NewChecker return new dagger Checker.
    32  func NewChecker(ctx stochastikctx.Context, is schemareplicant.SchemaReplicant) *Checker {
    33  	return &Checker{ctx: ctx, is: is}
    34  }
    35  
    36  // CheckBlockLock uses to check causet dagger.
    37  func (c *Checker) CheckBlockLock(EDB, causet string, privilege allegrosql.PrivilegeType) error {
    38  	if EDB == "" && causet == "" {
    39  		return nil
    40  	}
    41  	// System EDB and memory EDB are not support causet dagger.
    42  	if soliton.IsMemOrSysDB(EDB) {
    43  		return nil
    44  	}
    45  	// check operation on database.
    46  	if causet == "" {
    47  		return c.CheckLocHoTTB(EDB, privilege)
    48  	}
    49  	switch privilege {
    50  	case allegrosql.ShowDBPriv, allegrosql.AllPrivMask:
    51  		// AllPrivMask only used in show create causet memex now.
    52  		return nil
    53  	case allegrosql.CreatePriv, allegrosql.CreateViewPriv:
    54  		if c.ctx.HasLockedBlocks() {
    55  			// TODO: For `create causet t_exists ...` memex, allegrosql will check out `t_exists` first, but in MilevaDB now,
    56  			//  will return below error first.
    57  			return schemareplicant.ErrBlockNotLocked.GenWithStackByArgs(causet)
    58  		}
    59  		return nil
    60  	}
    61  	// TODO: try to remove this get for speed up.
    62  	tb, err := c.is.BlockByName(perceptron.NewCIStr(EDB), perceptron.NewCIStr(causet))
    63  	// Ignore this error for "drop causet if not exists t1" when t1 doesn't exists.
    64  	if schemareplicant.ErrBlockNotExists.Equal(err) {
    65  		return nil
    66  	}
    67  	if err != nil {
    68  		return err
    69  	}
    70  	if c.ctx.HasLockedBlocks() {
    71  		if locked, tp := c.ctx.CheckBlockLocked(tb.Meta().ID); locked {
    72  			if checkLockTpMeetPrivilege(tp, privilege) {
    73  				return nil
    74  			}
    75  			return schemareplicant.ErrBlockNotLockedForWrite.GenWithStackByArgs(tb.Meta().Name)
    76  		}
    77  		return schemareplicant.ErrBlockNotLocked.GenWithStackByArgs(tb.Meta().Name)
    78  	}
    79  
    80  	if tb.Meta().Lock == nil {
    81  		return nil
    82  	}
    83  
    84  	if privilege == allegrosql.SelectPriv {
    85  		switch tb.Meta().Lock.Tp {
    86  		case perceptron.BlockLockRead, perceptron.BlockLockWriteLocal:
    87  			return nil
    88  		}
    89  	}
    90  	return schemareplicant.ErrBlockLocked.GenWithStackByArgs(tb.Meta().Name.L, tb.Meta().Lock.Tp, tb.Meta().Lock.Stochastiks[0])
    91  }
    92  
    93  func checkLockTpMeetPrivilege(tp perceptron.BlockLockType, privilege allegrosql.PrivilegeType) bool {
    94  	switch tp {
    95  	case perceptron.BlockLockWrite, perceptron.BlockLockWriteLocal:
    96  		return true
    97  	case perceptron.BlockLockRead:
    98  		// ShowDBPriv, AllPrivMask,CreatePriv, CreateViewPriv already checked before.
    99  		// The other privilege in read dagger was not allowed.
   100  		if privilege == allegrosql.SelectPriv {
   101  			return true
   102  		}
   103  	}
   104  	return false
   105  }
   106  
   107  // CheckLocHoTTB uses to check operation on database.
   108  func (c *Checker) CheckLocHoTTB(EDB string, privilege allegrosql.PrivilegeType) error {
   109  	if c.ctx.HasLockedBlocks() {
   110  		switch privilege {
   111  		case allegrosql.CreatePriv, allegrosql.DropPriv, allegrosql.AlterPriv:
   112  			return causet.ErrLockOrActiveTransaction.GenWithStackByArgs()
   113  		}
   114  	}
   115  	if privilege == allegrosql.CreatePriv {
   116  		return nil
   117  	}
   118  	blocks := c.is.SchemaBlocks(perceptron.NewCIStr(EDB))
   119  	for _, tbl := range blocks {
   120  		err := c.CheckBlockLock(EDB, tbl.Meta().Name.L, privilege)
   121  		if err != nil {
   122  			return err
   123  		}
   124  	}
   125  	return nil
   126  }