Files
tidb/pkg/planner/util/misc.go

185 lines
5.1 KiB
Go

// Copyright 2022 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 util
import (
"encoding/binary"
"fmt"
"time"
"unsafe"
"github.com/pingcap/tidb/pkg/expression"
"github.com/pingcap/tidb/pkg/parser/model"
"github.com/pingcap/tidb/pkg/planner/property"
"github.com/pingcap/tidb/pkg/types"
"github.com/pingcap/tidb/pkg/util/ranger"
)
// CloneFieldNames uses types.FieldName.Clone to clone a slice of types.FieldName.
func CloneFieldNames(names []*types.FieldName) []*types.FieldName {
if names == nil {
return nil
}
cloned := make([]*types.FieldName, len(names))
for i, name := range names {
*cloned[i] = *name
}
return cloned
}
// CloneCIStrs uses model.CIStr.Clone to clone a slice of model.CIStr.
func CloneCIStrs(strs []model.CIStr) []model.CIStr {
if strs == nil {
return nil
}
cloned := make([]model.CIStr, 0, len(strs))
cloned = append(cloned, strs...)
return cloned
}
// CloneExprs uses Expression.Clone to clone a slice of Expression.
func CloneExprs(exprs []expression.Expression) []expression.Expression {
if exprs == nil {
return nil
}
cloned := make([]expression.Expression, 0, len(exprs))
for _, e := range exprs {
cloned = append(cloned, e.Clone())
}
return cloned
}
// CloneScalarFunctions uses (*ScalarFunction).Clone to clone a slice of *ScalarFunction.
func CloneScalarFunctions(scalarFuncs []*expression.ScalarFunction) []*expression.ScalarFunction {
if scalarFuncs == nil {
return nil
}
cloned := make([]*expression.ScalarFunction, 0, len(scalarFuncs))
for _, f := range scalarFuncs {
cloned = append(cloned, f.Clone().(*expression.ScalarFunction))
}
return cloned
}
// CloneCols uses (*Column).Clone to clone a slice of *Column.
func CloneCols(cols []*expression.Column) []*expression.Column {
if cols == nil {
return nil
}
cloned := make([]*expression.Column, 0, len(cols))
for _, c := range cols {
if c == nil {
cloned = append(cloned, nil)
continue
}
cloned = append(cloned, c.Clone().(*expression.Column))
}
return cloned
}
// CloneColInfos uses (*ColumnInfo).Clone to clone a slice of *ColumnInfo.
func CloneColInfos(cols []*model.ColumnInfo) []*model.ColumnInfo {
if cols == nil {
return nil
}
cloned := make([]*model.ColumnInfo, 0, len(cols))
for _, c := range cols {
cloned = append(cloned, c.Clone())
}
return cloned
}
// CloneRanges uses (*Range).Clone to clone a slice of *Range.
func CloneRanges(ranges []*ranger.Range) []*ranger.Range {
if ranges == nil {
return nil
}
cloned := make([]*ranger.Range, 0, len(ranges))
for _, r := range ranges {
cloned = append(cloned, r.Clone())
}
return cloned
}
// CloneByItems uses (*ByItems).Clone to clone a slice of *ByItems.
func CloneByItems(byItems []*ByItems) []*ByItems {
if byItems == nil {
return nil
}
cloned := make([]*ByItems, 0, len(byItems))
for _, item := range byItems {
cloned = append(cloned, item.Clone())
}
return cloned
}
// CloneSortItem uses SortItem.Clone to clone a slice of SortItem.
func CloneSortItem(items []property.SortItem) []property.SortItem {
if items == nil {
return nil
}
cloned := make([]property.SortItem, 0, len(items))
for _, item := range items {
cloned = append(cloned, item.Clone())
}
return cloned
}
// QueryTimeRange represents a time range specified by TIME_RANGE hint
type QueryTimeRange struct {
From time.Time
To time.Time
}
// Condition returns a WHERE clause base on it's value
func (tr *QueryTimeRange) Condition() string {
return fmt.Sprintf("where time>='%s' and time<='%s'",
tr.From.Format(MetricTableTimeFormat), tr.To.Format(MetricTableTimeFormat))
}
// MetricTableTimeFormat is the time format for metric table explain and format.
const MetricTableTimeFormat = "2006-01-02 15:04:05.999"
const emptyQueryTimeRangeSize = int64(unsafe.Sizeof(QueryTimeRange{}))
// MemoryUsage return the memory usage of QueryTimeRange
func (tr *QueryTimeRange) MemoryUsage() (sum int64) {
if tr == nil {
return
}
return emptyQueryTimeRangeSize
}
// EncodeIntAsUint32 is used for LogicalPlan Interface
func EncodeIntAsUint32(result []byte, value int) []byte {
var buf [4]byte
binary.BigEndian.PutUint32(buf[:], uint32(value))
return append(result, buf[:]...)
}
// GetMaxSortPrefix returns the prefix offset of sortCols in allCols.
func GetMaxSortPrefix(sortCols, allCols []*expression.Column) []int {
tmpSchema := expression.NewSchema(allCols...)
sortColOffsets := make([]int, 0, len(sortCols))
for _, sortCol := range sortCols {
offset := tmpSchema.ColumnIndex(sortCol)
if offset == -1 {
return sortColOffsets
}
sortColOffsets = append(sortColOffsets, offset)
}
return sortColOffsets
}