185 lines
5.1 KiB
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
|
|
}
|