tidb schema 代码
文件路径:/expression/schema.go
/ Copyright 2016 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 expression
import (
"strings"
)
/ KeyInfo stores the columns of one unique key or primary key.
type KeyInfo []*Column
/ Clone copies the entire UniqueKey.
func (ki KeyInfo) Clone() KeyInfo {
result := make([]*Column, 0, len(ki))
for _, col := range ki {
result = append(result, col.Clone().(*Column))
}
return result
}
/ String implements fmt.Stringer interface.
func (ki KeyInfo) String() string {
ukColStrs := make([]string, 0, len(ki))
for _, col := range ki {
ukColStrs = append(ukColStrs, col.String())
}
return "[" + strings.Join(ukColStrs, ",") + "]"
}
/ Schema stands for the row schema and unique key information get from input.
type Schema struct {
Columns []*Column
Keys []KeyInfo
/ UniqueKeys stores those unique indexes that allow null values, but Keys does not allow null values.
/ since equivalence conditions can filter out null values, in this case a unique index with null values can be a Key.
UniqueKeys []KeyInfo
}
/ String implements fmt.Stringer interface.
func (s *Schema) String() string {
colStrs := make([]string, 0, len(s.Columns))
for _, col := range s.Columns {
colStrs = append(colStrs, col.String())
}
ukStrs := make([]string, 0, len(s.Keys))
for _, key := range s.Keys {
ukStrs = append(ukStrs, key.String())
}
return "Column: [" + strings.Join(colStrs, ",") + "] Unique key: [" + strings.Join(ukStrs, ",") + "]"
}
/ Clone copies the total schema.
func (s *Schema) Clone() *Schema {
cols := make([]*Column, 0, s.Len())
keys := make([]KeyInfo, 0, len(s.Keys))
for _, col := range s.Columns {
cols = append(cols, col.Clone().(*Column))
}
for _, key := range s.Keys {
keys = append(keys, key.Clone())
}
schema := NewSchema(cols...)
schema.SetUniqueKeys(keys)
return schema
}
/ ExprFromSchema checks if all columns of this expression are from the same schema.
func ExprFromSchema(expr Expression, schema *Schema) bool {
switch v := expr.(type) {
case *Column:
return schema.Contains(v)
case *ScalarFunction:
for _, arg := range v.GetArgs() {
if !ExprFromSchema(arg, schema) {
return false
}
}
return true
case *CorrelatedColumn, *Constant:
return true
}
return false
}
/ RetrieveColumn retrieves column in expression from the columns in schema.
func (s *Schema) RetrieveColumn(col *Column) *Column {
index := s.ColumnIndex(col)
if index != -1 {
return s.Columns[index]
}
return nil
}
/ IsUniqueKey checks if this column is a unique key.
func (s *Schema) IsUniqueKey(col *Column) bool {
for _, key := range s.Keys {
if len(key) == 1 && key[0].Equal(nil, col) {
return true
}
}
return false
}
/ IsUnique checks if this column is a unique key which may contain duplicate nulls .
func (s *Schema) IsUnique(col *Column) bool {
for _, key := range s.UniqueKeys {
if len(key) == 1 && key[0].Equal(nil, col) {
return true
}
}
return false
}
/ ColumnIndex finds the index for a column.
func (s *Schema) ColumnIndex(col *Column) int {
backupIdx := -1
for i, c := range s.Columns {
if c.UniqueID == col.UniqueID {
backupIdx = i
if c.IsPrefix {
/ instead of returning a prefix column
/ prefer to find a full column
/ only clustered index table can meet this:
/ same column `c1` maybe appear in both primary key and secondary index
/ so secondary index itself can have two `c1` column one for indexKey and one for handle
continue
}
return i
}
}
return backupIdx
}
/ Contains checks if the schema contains the column.
func (s *Schema) Contains(col *Column) bool {
return s.ColumnIndex(col) != -1
}
/ Len returns the number of columns in schema.
func (s *Schema) Len() int {
return len(s.Columns)
}
/ Append append new column to the columns stored in schema.
func (s *Schema) Append(col ...*Column) {
s.Columns = append(s.Columns, col...)
}
/ SetUniqueKeys will set the value of Schema.Keys.
func (s *Schema) SetUniqueKeys(keys []KeyInfo) {
s.Keys = keys
}
/ ColumnsIndices will return a slice which contains the position of each column in schema.
/ If there is one column that doesn't match, nil will be returned.
func (s *Schema) ColumnsIndices(cols []*Column) (ret []int) {
ret = make([]int, 0, len(cols))
for _, col := range cols {
pos := s.ColumnIndex(col)
if pos != -1 {
ret = append(ret, pos)
} else {
return nil
}
}
return
}
/ ColumnsByIndices returns columns by multiple offsets.
/ Callers should guarantee that all the offsets provided should be valid, which means offset should:
/ 1. not smaller than 0, and
/ 2. not exceed len(s.Columns)
func (s *Schema) ColumnsByIndices(offsets []int) []*Column {
cols := make([]*Column, 0, len(offsets))
for _, offset := range offsets {
cols = append(cols, s.Columns[offset])
}
return cols
}
/ ExtractColGroups checks if column groups are from current schema, and returns
/ offsets of those satisfied column groups.
func (s *Schema) ExtractColGroups(colGroups [][]*Column) ([][]int, []int) {
if len(colGroups) == 0 {
return nil, nil
}
extracted := make([][]int, 0, len(colGroups))
offsets := make([]int, 0, len(colGroups))
for i, g := range colGroups {
if j := s.ColumnsIndices(g); j != nil {
extracted = append(extracted, j)
offsets = append(offsets, i)
}
}
return extracted, offsets
}
/ MergeSchema will merge two schema into one schema. We shouldn't need to consider unique keys.
/ That will be processed in build_key_info.go.
func MergeSchema(lSchema, rSchema *Schema) *Schema {
if lSchema == nil && rSchema == nil {
return nil
}
if lSchema == nil {
return rSchema.Clone()
}
if rSchema == nil {
return lSchema.Clone()
}
tmpL := lSchema.Clone()
tmpR := rSchema.Clone()
ret := NewSchema(append(tmpL.Columns, tmpR.Columns...)...)
return ret
}
/ GetUsedList shows whether each column in schema is contained in usedCols.
func GetUsedList(usedCols []*Column, schema *Schema) []bool {
tmpSchema := NewSchema(usedCols...)
used := make([]bool, schema.Len())
for i, col := range schema.Columns {
if !used[i] {
used[i] = tmpSchema.Contains(col)
/ When cols are a generated expression col, compare them in terms of virtual expr.
if expr, ok := col.VirtualExpr.(*ScalarFunction); ok && used[i] {
for j, colToCompare := range schema.Columns {
if !used[j] && j != i && (expr).Equal(nil, colToCompare.VirtualExpr) && col.RetType.Equal(colToCompare.RetType) {
used[j] = true
}
}
}
}
}
return used
}
/ NewSchema returns a schema made by its parameter.
func NewSchema(cols ...*Column) *Schema {
return &Schema{Columns: cols}
}
相关信息
相关文章
tidb builtin_arithmetic_vec 源码