// Copyright 2024 PingCAP, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package exprctx import ( "fmt" "log" "unsafe" "github.com/pingcap/tidb/pkg/util/intest" ) func init() { // Ensure the count of optional properties is less than the bits of OptionalEvalProps. if maxCnt := int64(unsafe.Sizeof(*new(OptionalEvalPropKeySet))) * 8; int64(OptPropsCnt) > maxCnt { log.Fatalf( "The count optional properties should less than the bits of OptionalEvalProps, but %d > %d", OptPropsCnt, maxCnt, ) } // check optionalPropertyDescList are valid if len(optionalPropertyDescList) != OptPropsCnt { log.Fatalf( "The lenghth of OptionalPropertieDescs should be %d, but got %d", OptPropsCnt, len(optionalPropertyDescList), ) } for i := range OptPropsCnt { if key := optionalPropertyDescList[i].Key(); key != OptionalEvalPropKey(i) { log.Fatalf( "Invalid optionalPropertyDescList[%d].Key, unexpected index: %d", i, key, ) } } } // OptionalEvalPropKey is the key for optional evaluation properties in EvalContext. type OptionalEvalPropKey int // AsPropKeySet returns the set only contains the property key. func (k OptionalEvalPropKey) AsPropKeySet() OptionalEvalPropKeySet { return 1 << k } // Desc returns the description for the property key. func (k OptionalEvalPropKey) Desc() *OptionalEvalPropDesc { return &optionalPropertyDescList[k] } // String implements fmt.Stringer interface. func (k OptionalEvalPropKey) String() string { if k < optPropsCnt { return k.Desc().str } return fmt.Sprintf("UnknownOptionalEvalPropKey(%d)", k) } const ( // OptPropCurrentUser indicates to provide the current user property. OptPropCurrentUser OptionalEvalPropKey = iota // OptPropSessionVars indicates to provide `variable.SessionVariable`. OptPropSessionVars // OptPropInfoSchema indicates to provide the information schema. OptPropInfoSchema // OptPropKVStore indicates to provide the kv store. OptPropKVStore // OptPropSQLExecutor indicates to provide executors to execute sql. OptPropSQLExecutor // OptPropSequenceOperator indicates to provide sequence operators for sequences. OptPropSequenceOperator // OptPropAdvisoryLock indicates to provide advisory lock operations. OptPropAdvisoryLock // OptPropDDLOwnerInfo indicates to provide DDL owner information. OptPropDDLOwnerInfo // OptPropPrivilegeChecker indicates to provide the privilege checker. OptPropPrivilegeChecker // optPropsCnt is the count of optional properties. DO NOT use it as a property key. optPropsCnt ) const allOptPropsMask = (1 << optPropsCnt) - 1 // OptPropsCnt is the count of optional properties. const OptPropsCnt = int(optPropsCnt) // OptionalEvalPropDesc is the description for optional evaluation properties in EvalContext. type OptionalEvalPropDesc struct { key OptionalEvalPropKey str string // TODO: add more fields if needed } // Key returns the property key. func (desc *OptionalEvalPropDesc) Key() OptionalEvalPropKey { return desc.key } // OptionalEvalPropProvider is the interface to provide optional properties in EvalContext. type OptionalEvalPropProvider interface { Desc() *OptionalEvalPropDesc } // optionalPropertyDescList contains all optional property descriptions in EvalContext. var optionalPropertyDescList = []OptionalEvalPropDesc{ { key: OptPropCurrentUser, str: "OptPropCurrentUser", }, { key: OptPropSessionVars, str: "OptPropSessionVars", }, { key: OptPropInfoSchema, str: "OptPropInfoSchema", }, { key: OptPropKVStore, str: "OptPropKVStore", }, { key: OptPropSQLExecutor, str: "OptPropSQLExecutor", }, { key: OptPropSequenceOperator, str: "OptPropDDLOwnerInfo", }, { key: OptPropAdvisoryLock, str: "OptPropAdvisoryLock", }, { key: OptPropDDLOwnerInfo, str: "OptPropDDLOwnerInfo", }, { key: OptPropPrivilegeChecker, str: "OptPropPrivilegeChecker", }, } // OptionalEvalPropKeySet is a bit map for optional evaluation properties in EvalContext // to indicate whether some properties are set. type OptionalEvalPropKeySet uint64 // Add adds the property key to the set func (b OptionalEvalPropKeySet) Add(key OptionalEvalPropKey) OptionalEvalPropKeySet { intest.Assert(key < optPropsCnt) if key >= optPropsCnt { return b } return b | key.AsPropKeySet() } // Remove removes the property key from the set func (b OptionalEvalPropKeySet) Remove(key OptionalEvalPropKey) OptionalEvalPropKeySet { intest.Assert(key < optPropsCnt) if key >= optPropsCnt { return b } return b &^ key.AsPropKeySet() } // Contains checks whether the set contains the property func (b OptionalEvalPropKeySet) Contains(key OptionalEvalPropKey) bool { intest.Assert(key < optPropsCnt) if key >= optPropsCnt { return false } return b&key.AsPropKeySet() != 0 } // IsEmpty checks whether the bit map is empty. func (b OptionalEvalPropKeySet) IsEmpty() bool { return b&allOptPropsMask == 0 } // IsFull checks whether all optional properties are contained in the bit map. func (b OptionalEvalPropKeySet) IsFull() bool { return b&allOptPropsMask == allOptPropsMask }