github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/dbs/memristed/memex/util.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 memex
    15  
    16  import (
    17  	"math"
    18  	"strconv"
    19  	"strings"
    20  	"time"
    21  	"unicode"
    22  
    23  	"github.com/whtcorpsinc/errors"
    24  	"github.com/whtcorpsinc/BerolinaSQL/ast"
    25  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    26  	"github.com/whtcorpsinc/BerolinaSQL/opcode"
    27  	"github.com/whtcorpsinc/BerolinaSQL/terror"
    28  	"github.com/whtcorpsinc/milevadb/stochastikctx"
    29  	"github.com/whtcorpsinc/milevadb/types"
    30  	"github.com/whtcorpsinc/milevadb/types/BerolinaSQL_driver"
    31  	"github.com/whtcorpsinc/milevadb/soliton/chunk"
    32  	"github.com/whtcorpsinc/milevadb/soliton/defCauslate"
    33  	"github.com/whtcorpsinc/milevadb/soliton/logutil"
    34  	"go.uber.org/zap"
    35  	"golang.org/x/tools/container/intsets"
    36  )
    37  
    38  // cowExprRef is a copy-on-write slice ref soliton using in `DeferredCausetSubstitute`
    39  // to reduce unnecessary allocation for Expression arguments array
    40  type cowExprRef struct {
    41  	ref []Expression
    42  	new []Expression
    43  }
    44  
    45  // Set will allocate new array if changed flag true
    46  func (c *cowExprRef) Set(i int, changed bool, val Expression) {
    47  	if c.new != nil {
    48  		c.new[i] = val
    49  		return
    50  	}
    51  	if !changed {
    52  		return
    53  	}
    54  	c.new = make([]Expression, len(c.ref))
    55  	copy(c.new, c.ref[:i])
    56  	c.new[i] = val
    57  }
    58  
    59  // Result return the final reference
    60  func (c *cowExprRef) Result() []Expression {
    61  	if c.new != nil {
    62  		return c.new
    63  	}
    64  	return c.ref
    65  }
    66  
    67  // Filter the input memexs, append the results to result.
    68  func Filter(result []Expression, input []Expression, filter func(Expression) bool) []Expression {
    69  	for _, e := range input {
    70  		if filter(e) {
    71  			result = append(result, e)
    72  		}
    73  	}
    74  	return result
    75  }
    76  
    77  // FilterOutInPlace do the filtering out in place.
    78  // The remained are the ones who doesn't match the filter, storing in the original slice.
    79  // The filteredOut are the ones match the filter, storing in a new slice.
    80  func FilterOutInPlace(input []Expression, filter func(Expression) bool) (remained, filteredOut []Expression) {
    81  	for i := len(input) - 1; i >= 0; i-- {
    82  		if filter(input[i]) {
    83  			filteredOut = append(filteredOut, input[i])
    84  			input = append(input[:i], input[i+1:]...)
    85  		}
    86  	}
    87  	return input, filteredOut
    88  }
    89  
    90  // ExtractDependentDeferredCausets extracts all dependent defCausumns from a virtual defCausumn.
    91  func ExtractDependentDeferredCausets(expr Expression) []*DeferredCauset {
    92  	// Pre-allocate a slice to reduce allocation, 8 doesn't have special meaning.
    93  	result := make([]*DeferredCauset, 0, 8)
    94  	return extractDependentDeferredCausets(result, expr)
    95  }
    96  
    97  func extractDependentDeferredCausets(result []*DeferredCauset, expr Expression) []*DeferredCauset {
    98  	switch v := expr.(type) {
    99  	case *DeferredCauset:
   100  		result = append(result, v)
   101  		if v.VirtualExpr != nil {
   102  			result = extractDependentDeferredCausets(result, v.VirtualExpr)
   103  		}
   104  	case *ScalarFunction:
   105  		for _, arg := range v.GetArgs() {
   106  			result = extractDependentDeferredCausets(result, arg)
   107  		}
   108  	}
   109  	return result
   110  }
   111  
   112  // ExtractDeferredCausets extracts all defCausumns from an memex.
   113  func ExtractDeferredCausets(expr Expression) []*DeferredCauset {
   114  	// Pre-allocate a slice to reduce allocation, 8 doesn't have special meaning.
   115  	result := make([]*DeferredCauset, 0, 8)
   116  	return extractDeferredCausets(result, expr, nil)
   117  }
   118  
   119  // ExtractCorDeferredCausets extracts correlated defCausumn from given memex.
   120  func ExtractCorDeferredCausets(expr Expression) (defcaus []*CorrelatedDeferredCauset) {
   121  	switch v := expr.(type) {
   122  	case *CorrelatedDeferredCauset:
   123  		return []*CorrelatedDeferredCauset{v}
   124  	case *ScalarFunction:
   125  		for _, arg := range v.GetArgs() {
   126  			defcaus = append(defcaus, ExtractCorDeferredCausets(arg)...)
   127  		}
   128  	}
   129  	return
   130  }
   131  
   132  // ExtractDeferredCausetsFromExpressions is a more efficient version of ExtractDeferredCausets for batch operation.
   133  // filter can be nil, or a function to filter the result defCausumn.
   134  // It's often observed that the pattern of the caller like this:
   135  //
   136  // defcaus := ExtractDeferredCausets(...)
   137  // for _, defCaus := range defcaus {
   138  //     if xxx(defCaus) {...}
   139  // }
   140  //
   141  // Provide an additional filter argument, this can be done in one step.
   142  // To avoid allocation for defcaus that not need.
   143  func ExtractDeferredCausetsFromExpressions(result []*DeferredCauset, exprs []Expression, filter func(*DeferredCauset) bool) []*DeferredCauset {
   144  	for _, expr := range exprs {
   145  		result = extractDeferredCausets(result, expr, filter)
   146  	}
   147  	return result
   148  }
   149  
   150  func extractDeferredCausets(result []*DeferredCauset, expr Expression, filter func(*DeferredCauset) bool) []*DeferredCauset {
   151  	switch v := expr.(type) {
   152  	case *DeferredCauset:
   153  		if filter == nil || filter(v) {
   154  			result = append(result, v)
   155  		}
   156  	case *ScalarFunction:
   157  		for _, arg := range v.GetArgs() {
   158  			result = extractDeferredCausets(result, arg, filter)
   159  		}
   160  	}
   161  	return result
   162  }
   163  
   164  // ExtractDeferredCausetSet extracts the different values of `UniqueId` for defCausumns in memexs.
   165  func ExtractDeferredCausetSet(exprs []Expression) *intsets.Sparse {
   166  	set := &intsets.Sparse{}
   167  	for _, expr := range exprs {
   168  		extractDeferredCausetSet(expr, set)
   169  	}
   170  	return set
   171  }
   172  
   173  func extractDeferredCausetSet(expr Expression, set *intsets.Sparse) {
   174  	switch v := expr.(type) {
   175  	case *DeferredCauset:
   176  		set.Insert(int(v.UniqueID))
   177  	case *ScalarFunction:
   178  		for _, arg := range v.GetArgs() {
   179  			extractDeferredCausetSet(arg, set)
   180  		}
   181  	}
   182  }
   183  
   184  func setExprDeferredCausetInOperand(expr Expression) Expression {
   185  	switch v := expr.(type) {
   186  	case *DeferredCauset:
   187  		defCaus := v.Clone().(*DeferredCauset)
   188  		defCaus.InOperand = true
   189  		return defCaus
   190  	case *ScalarFunction:
   191  		args := v.GetArgs()
   192  		for i, arg := range args {
   193  			args[i] = setExprDeferredCausetInOperand(arg)
   194  		}
   195  	}
   196  	return expr
   197  }
   198  
   199  // DeferredCausetSubstitute substitutes the defCausumns in filter to memexs in select fields.
   200  // e.g. select * from (select b as a from t) k where a < 10 => select * from (select b as a from t where b < 10) k.
   201  func DeferredCausetSubstitute(expr Expression, schemaReplicant *Schema, newExprs []Expression) Expression {
   202  	_, resExpr := DeferredCausetSubstituteImpl(expr, schemaReplicant, newExprs)
   203  	return resExpr
   204  }
   205  
   206  // DeferredCausetSubstituteImpl tries to substitute defCausumn expr using newExprs,
   207  // the newFunctionInternal is only called if its child is substituted
   208  func DeferredCausetSubstituteImpl(expr Expression, schemaReplicant *Schema, newExprs []Expression) (bool, Expression) {
   209  	switch v := expr.(type) {
   210  	case *DeferredCauset:
   211  		id := schemaReplicant.DeferredCausetIndex(v)
   212  		if id == -1 {
   213  			return false, v
   214  		}
   215  		newExpr := newExprs[id]
   216  		if v.InOperand {
   217  			newExpr = setExprDeferredCausetInOperand(newExpr)
   218  		}
   219  		newExpr.SetCoercibility(v.Coercibility())
   220  		return true, newExpr
   221  	case *ScalarFunction:
   222  		if v.FuncName.L == ast.Cast {
   223  			newFunc := v.Clone().(*ScalarFunction)
   224  			_, newFunc.GetArgs()[0] = DeferredCausetSubstituteImpl(newFunc.GetArgs()[0], schemaReplicant, newExprs)
   225  			return true, newFunc
   226  		}
   227  		// cowExprRef is a copy-on-write soliton, args array allocation happens only
   228  		// when expr in args is changed
   229  		refExprArr := cowExprRef{v.GetArgs(), nil}
   230  		substituted := false
   231  		_, defCausl := DeriveDefCauslationFromExprs(v.GetCtx(), v.GetArgs()...)
   232  		for idx, arg := range v.GetArgs() {
   233  			changed, newFuncExpr := DeferredCausetSubstituteImpl(arg, schemaReplicant, newExprs)
   234  			if defCauslate.NewDefCauslationEnabled() {
   235  				// Make sure the defCauslation used by the ScalarFunction isn't changed and its result defCauslation is not weaker than the defCauslation used by the ScalarFunction.
   236  				if changed {
   237  					changed = false
   238  					tmpArgs := make([]Expression, 0, len(v.GetArgs()))
   239  					_ = append(append(append(tmpArgs, refExprArr.Result()[0:idx]...), refExprArr.Result()[idx+1:]...), newFuncExpr)
   240  					_, newDefCausl := DeriveDefCauslationFromExprs(v.GetCtx(), append(v.GetArgs(), newFuncExpr)...)
   241  					if defCausl == newDefCausl {
   242  						changed = checkDefCauslationStrictness(defCausl, newFuncExpr.GetType().DefCauslate)
   243  					}
   244  				}
   245  			}
   246  			refExprArr.Set(idx, changed, newFuncExpr)
   247  			if changed {
   248  				substituted = true
   249  			}
   250  		}
   251  		if substituted {
   252  			return true, NewFunctionInternal(v.GetCtx(), v.FuncName.L, v.RetType, refExprArr.Result()...)
   253  		}
   254  	}
   255  	return false, expr
   256  }
   257  
   258  // checkDefCauslationStrictness check defCauslation strictness-ship between `defCausl` and `newFuncDefCausl`
   259  // return true iff `newFuncDefCausl` is not weaker than `defCausl`
   260  func checkDefCauslationStrictness(defCausl, newFuncDefCausl string) bool {
   261  	defCauslGroupID, ok1 := DefCauslationStrictnessGroup[defCausl]
   262  	newFuncDefCauslGroupID, ok2 := DefCauslationStrictnessGroup[newFuncDefCausl]
   263  
   264  	if ok1 && ok2 {
   265  		if defCauslGroupID == newFuncDefCauslGroupID {
   266  			return true
   267  		}
   268  
   269  		for _, id := range DefCauslationStrictness[defCauslGroupID] {
   270  			if newFuncDefCauslGroupID == id {
   271  				return true
   272  			}
   273  		}
   274  	}
   275  
   276  	return false
   277  }
   278  
   279  // getValidPrefix gets a prefix of string which can parsed to a number with base. the minimum base is 2 and the maximum is 36.
   280  func getValidPrefix(s string, base int64) string {
   281  	var (
   282  		validLen int
   283  		upper    rune
   284  	)
   285  	switch {
   286  	case base >= 2 && base <= 9:
   287  		upper = rune('0' + base)
   288  	case base <= 36:
   289  		upper = rune('A' + base - 10)
   290  	default:
   291  		return ""
   292  	}
   293  Loop:
   294  	for i := 0; i < len(s); i++ {
   295  		c := rune(s[i])
   296  		switch {
   297  		case unicode.IsDigit(c) || unicode.IsLower(c) || unicode.IsUpper(c):
   298  			c = unicode.ToUpper(c)
   299  			if c < upper {
   300  				validLen = i + 1
   301  			} else {
   302  				break Loop
   303  			}
   304  		case c == '+' || c == '-':
   305  			if i != 0 {
   306  				break Loop
   307  			}
   308  		default:
   309  			break Loop
   310  		}
   311  	}
   312  	if validLen > 1 && s[0] == '+' {
   313  		return s[1:validLen]
   314  	}
   315  	return s[:validLen]
   316  }
   317  
   318  // SubstituteCorDefCaus2Constant will substitute correlated defCausumn to constant value which it contains.
   319  // If the args of one scalar function are all constant, we will substitute it to constant.
   320  func SubstituteCorDefCaus2Constant(expr Expression) (Expression, error) {
   321  	switch x := expr.(type) {
   322  	case *ScalarFunction:
   323  		allConstant := true
   324  		newArgs := make([]Expression, 0, len(x.GetArgs()))
   325  		for _, arg := range x.GetArgs() {
   326  			newArg, err := SubstituteCorDefCaus2Constant(arg)
   327  			if err != nil {
   328  				return nil, err
   329  			}
   330  			_, ok := newArg.(*Constant)
   331  			newArgs = append(newArgs, newArg)
   332  			allConstant = allConstant && ok
   333  		}
   334  		if allConstant {
   335  			val, err := x.Eval(chunk.Event{})
   336  			if err != nil {
   337  				return nil, err
   338  			}
   339  			return &Constant{Value: val, RetType: x.GetType()}, nil
   340  		}
   341  		var newSf Expression
   342  		if x.FuncName.L == ast.Cast {
   343  			newSf = BuildCastFunction(x.GetCtx(), newArgs[0], x.RetType)
   344  		} else {
   345  			newSf = NewFunctionInternal(x.GetCtx(), x.FuncName.L, x.GetType(), newArgs...)
   346  		}
   347  		return newSf, nil
   348  	case *CorrelatedDeferredCauset:
   349  		return &Constant{Value: *x.Data, RetType: x.GetType()}, nil
   350  	case *Constant:
   351  		if x.DeferredExpr != nil {
   352  			newExpr := FoldConstant(x)
   353  			return &Constant{Value: newExpr.(*Constant).Value, RetType: x.GetType()}, nil
   354  		}
   355  	}
   356  	return expr, nil
   357  }
   358  
   359  // timeZone2Duration converts timezone whose format should satisfy the regular condition
   360  // `(^(+|-)(0?[0-9]|1[0-2]):[0-5]?\d$)|(^+13:00$)` to time.Duration.
   361  func timeZone2Duration(tz string) time.Duration {
   362  	sign := 1
   363  	if strings.HasPrefix(tz, "-") {
   364  		sign = -1
   365  	}
   366  
   367  	i := strings.Index(tz, ":")
   368  	h, err := strconv.Atoi(tz[1:i])
   369  	terror.Log(err)
   370  	m, err := strconv.Atoi(tz[i+1:])
   371  	terror.Log(err)
   372  	return time.Duration(sign) * (time.Duration(h)*time.Hour + time.Duration(m)*time.Minute)
   373  }
   374  
   375  var logicalOps = map[string]struct{}{
   376  	ast.LT:                 {},
   377  	ast.GE:                 {},
   378  	ast.GT:                 {},
   379  	ast.LE:                 {},
   380  	ast.EQ:                 {},
   381  	ast.NE:                 {},
   382  	ast.UnaryNot:           {},
   383  	ast.LogicAnd:           {},
   384  	ast.LogicOr:            {},
   385  	ast.LogicXor:           {},
   386  	ast.In:                 {},
   387  	ast.IsNull:             {},
   388  	ast.IsTruthWithoutNull: {},
   389  	ast.IsFalsity:          {},
   390  	ast.Like:               {},
   391  }
   392  
   393  var oppositeOp = map[string]string{
   394  	ast.LT:       ast.GE,
   395  	ast.GE:       ast.LT,
   396  	ast.GT:       ast.LE,
   397  	ast.LE:       ast.GT,
   398  	ast.EQ:       ast.NE,
   399  	ast.NE:       ast.EQ,
   400  	ast.LogicOr:  ast.LogicAnd,
   401  	ast.LogicAnd: ast.LogicOr,
   402  }
   403  
   404  // a op b is equal to b symmetricOp a
   405  var symmetricOp = map[opcode.Op]opcode.Op{
   406  	opcode.LT:     opcode.GT,
   407  	opcode.GE:     opcode.LE,
   408  	opcode.GT:     opcode.LT,
   409  	opcode.LE:     opcode.GE,
   410  	opcode.EQ:     opcode.EQ,
   411  	opcode.NE:     opcode.NE,
   412  	opcode.NullEQ: opcode.NullEQ,
   413  }
   414  
   415  func pushNotAcrossArgs(ctx stochastikctx.Context, exprs []Expression, not bool) ([]Expression, bool) {
   416  	newExprs := make([]Expression, 0, len(exprs))
   417  	flag := false
   418  	for _, expr := range exprs {
   419  		newExpr, changed := pushNotAcrossExpr(ctx, expr, not)
   420  		flag = changed || flag
   421  		newExprs = append(newExprs, newExpr)
   422  	}
   423  	return newExprs, flag
   424  }
   425  
   426  // pushNotAcrossExpr try to eliminate the NOT expr in memex tree.
   427  // Input `not` indicates whether there's a `NOT` be pushed down.
   428  // Output `changed` indicates whether the output memex differs from the
   429  // input `expr` because of the pushed-down-not.
   430  func pushNotAcrossExpr(ctx stochastikctx.Context, expr Expression, not bool) (_ Expression, changed bool) {
   431  	if f, ok := expr.(*ScalarFunction); ok {
   432  		switch f.FuncName.L {
   433  		case ast.UnaryNot:
   434  			child, err := wrapWithIsTrue(ctx, true, f.GetArgs()[0], true)
   435  			if err != nil {
   436  				return expr, false
   437  			}
   438  			var childExpr Expression
   439  			childExpr, changed = pushNotAcrossExpr(f.GetCtx(), child, !not)
   440  			if !changed && !not {
   441  				return expr, false
   442  			}
   443  			return childExpr, true
   444  		case ast.LT, ast.GE, ast.GT, ast.LE, ast.EQ, ast.NE:
   445  			if not {
   446  				return NewFunctionInternal(f.GetCtx(), oppositeOp[f.FuncName.L], f.GetType(), f.GetArgs()...), true
   447  			}
   448  			newArgs, changed := pushNotAcrossArgs(f.GetCtx(), f.GetArgs(), false)
   449  			if !changed {
   450  				return f, false
   451  			}
   452  			return NewFunctionInternal(f.GetCtx(), f.FuncName.L, f.GetType(), newArgs...), true
   453  		case ast.LogicAnd, ast.LogicOr:
   454  			var (
   455  				newArgs []Expression
   456  				changed bool
   457  			)
   458  			funcName := f.FuncName.L
   459  			if not {
   460  				newArgs, _ = pushNotAcrossArgs(f.GetCtx(), f.GetArgs(), true)
   461  				funcName = oppositeOp[f.FuncName.L]
   462  				changed = true
   463  			} else {
   464  				newArgs, changed = pushNotAcrossArgs(f.GetCtx(), f.GetArgs(), false)
   465  			}
   466  			if !changed {
   467  				return f, false
   468  			}
   469  			return NewFunctionInternal(f.GetCtx(), funcName, f.GetType(), newArgs...), true
   470  		}
   471  	}
   472  	if not {
   473  		expr = NewFunctionInternal(ctx, ast.UnaryNot, types.NewFieldType(allegrosql.TypeTiny), expr)
   474  	}
   475  	return expr, not
   476  }
   477  
   478  // PushDownNot pushes the `not` function down to the memex's arguments.
   479  func PushDownNot(ctx stochastikctx.Context, expr Expression) Expression {
   480  	newExpr, _ := pushNotAcrossExpr(ctx, expr, false)
   481  	return newExpr
   482  }
   483  
   484  // Contains tests if `exprs` contains `e`.
   485  func Contains(exprs []Expression, e Expression) bool {
   486  	for _, expr := range exprs {
   487  		if e == expr {
   488  			return true
   489  		}
   490  	}
   491  	return false
   492  }
   493  
   494  // ExtractFiltersFromDNFs checks whether the cond is DNF. If so, it will get the extracted part and the remained part.
   495  // The original DNF will be replaced by the remained part or just be deleted if remained part is nil.
   496  // And the extracted part will be appended to the end of the orignal slice.
   497  func ExtractFiltersFromDNFs(ctx stochastikctx.Context, conditions []Expression) []Expression {
   498  	var allExtracted []Expression
   499  	for i := len(conditions) - 1; i >= 0; i-- {
   500  		if sf, ok := conditions[i].(*ScalarFunction); ok && sf.FuncName.L == ast.LogicOr {
   501  			extracted, remained := extractFiltersFromDNF(ctx, sf)
   502  			allExtracted = append(allExtracted, extracted...)
   503  			if remained == nil {
   504  				conditions = append(conditions[:i], conditions[i+1:]...)
   505  			} else {
   506  				conditions[i] = remained
   507  			}
   508  		}
   509  	}
   510  	return append(conditions, allExtracted...)
   511  }
   512  
   513  // extractFiltersFromDNF extracts the same condition that occurs in every DNF item and remove them from dnf leaves.
   514  func extractFiltersFromDNF(ctx stochastikctx.Context, dnfFunc *ScalarFunction) ([]Expression, Expression) {
   515  	dnfItems := FlattenDNFConditions(dnfFunc)
   516  	sc := ctx.GetStochastikVars().StmtCtx
   517  	codeMap := make(map[string]int)
   518  	hashcode2Expr := make(map[string]Expression)
   519  	for i, dnfItem := range dnfItems {
   520  		innerMap := make(map[string]struct{})
   521  		cnfItems := SplitCNFItems(dnfItem)
   522  		for _, cnfItem := range cnfItems {
   523  			code := cnfItem.HashCode(sc)
   524  			if i == 0 {
   525  				codeMap[string(code)] = 1
   526  				hashcode2Expr[string(code)] = cnfItem
   527  			} else if _, ok := codeMap[string(code)]; ok {
   528  				// We need this check because there may be the case like `select * from t, t1 where (t.a=t1.a and t.a=t1.a) or (something).
   529  				// We should make sure that the two `t.a=t1.a` contributes only once.
   530  				// TODO: do this out of this function.
   531  				if _, ok = innerMap[string(code)]; !ok {
   532  					codeMap[string(code)]++
   533  					innerMap[string(code)] = struct{}{}
   534  				}
   535  			}
   536  		}
   537  	}
   538  	// We should make sure that this item occurs in every DNF item.
   539  	for hashcode, cnt := range codeMap {
   540  		if cnt < len(dnfItems) {
   541  			delete(hashcode2Expr, hashcode)
   542  		}
   543  	}
   544  	if len(hashcode2Expr) == 0 {
   545  		return nil, dnfFunc
   546  	}
   547  	newDNFItems := make([]Expression, 0, len(dnfItems))
   548  	onlyNeedExtracted := false
   549  	for _, dnfItem := range dnfItems {
   550  		cnfItems := SplitCNFItems(dnfItem)
   551  		newCNFItems := make([]Expression, 0, len(cnfItems))
   552  		for _, cnfItem := range cnfItems {
   553  			code := cnfItem.HashCode(sc)
   554  			_, ok := hashcode2Expr[string(code)]
   555  			if !ok {
   556  				newCNFItems = append(newCNFItems, cnfItem)
   557  			}
   558  		}
   559  		// If the extracted part is just one leaf of the DNF memex. Then the value of the total DNF memex is
   560  		// always the same with the value of the extracted part.
   561  		if len(newCNFItems) == 0 {
   562  			onlyNeedExtracted = true
   563  			break
   564  		}
   565  		newDNFItems = append(newDNFItems, ComposeCNFCondition(ctx, newCNFItems...))
   566  	}
   567  	extractedExpr := make([]Expression, 0, len(hashcode2Expr))
   568  	for _, expr := range hashcode2Expr {
   569  		extractedExpr = append(extractedExpr, expr)
   570  	}
   571  	if onlyNeedExtracted {
   572  		return extractedExpr, nil
   573  	}
   574  	return extractedExpr, ComposeDNFCondition(ctx, newDNFItems...)
   575  }
   576  
   577  // DeriveRelaxedFiltersFromDNF given a DNF memex, derive a relaxed DNF memex which only contains defCausumns
   578  // in specified schemaReplicant; the derived memex is a superset of original memex, i.e, any tuple satisfying
   579  // the original memex must satisfy the derived memex. Return nil when the derived memex is universal set.
   580  // A running example is: for schemaReplicant of t1, `(t1.a=1 and t2.a=1) or (t1.a=2 and t2.a=2)` would be derived as
   581  // `t1.a=1 or t1.a=2`, while `t1.a=1 or t2.a=1` would get nil.
   582  func DeriveRelaxedFiltersFromDNF(expr Expression, schemaReplicant *Schema) Expression {
   583  	sf, ok := expr.(*ScalarFunction)
   584  	if !ok || sf.FuncName.L != ast.LogicOr {
   585  		return nil
   586  	}
   587  	ctx := sf.GetCtx()
   588  	dnfItems := FlattenDNFConditions(sf)
   589  	newDNFItems := make([]Expression, 0, len(dnfItems))
   590  	for _, dnfItem := range dnfItems {
   591  		cnfItems := SplitCNFItems(dnfItem)
   592  		newCNFItems := make([]Expression, 0, len(cnfItems))
   593  		for _, cnfItem := range cnfItems {
   594  			if itemSF, ok := cnfItem.(*ScalarFunction); ok && itemSF.FuncName.L == ast.LogicOr {
   595  				relaxedCNFItem := DeriveRelaxedFiltersFromDNF(cnfItem, schemaReplicant)
   596  				if relaxedCNFItem != nil {
   597  					newCNFItems = append(newCNFItems, relaxedCNFItem)
   598  				}
   599  				// If relaxed memex for embedded DNF is universal set, just drop this CNF item
   600  				continue
   601  			}
   602  			// This cnfItem must be simple memex now
   603  			// If it cannot be fully covered by schemaReplicant, just drop this CNF item
   604  			if ExprFromSchema(cnfItem, schemaReplicant) {
   605  				newCNFItems = append(newCNFItems, cnfItem)
   606  			}
   607  		}
   608  		// If this DNF item involves no defCausumn of specified schemaReplicant, the relaxed memex must be universal set
   609  		if len(newCNFItems) == 0 {
   610  			return nil
   611  		}
   612  		newDNFItems = append(newDNFItems, ComposeCNFCondition(ctx, newCNFItems...))
   613  	}
   614  	return ComposeDNFCondition(ctx, newDNFItems...)
   615  }
   616  
   617  // GetEventLen gets the length if the func is event, returns 1 if not event.
   618  func GetEventLen(e Expression) int {
   619  	if f, ok := e.(*ScalarFunction); ok && f.FuncName.L == ast.EventFunc {
   620  		return len(f.GetArgs())
   621  	}
   622  	return 1
   623  }
   624  
   625  // CheckArgsNotMultiDeferredCausetEvent checks the args are not multi-defCausumn event.
   626  func CheckArgsNotMultiDeferredCausetEvent(args ...Expression) error {
   627  	for _, arg := range args {
   628  		if GetEventLen(arg) != 1 {
   629  			return ErrOperandDeferredCausets.GenWithStackByArgs(1)
   630  		}
   631  	}
   632  	return nil
   633  }
   634  
   635  // GetFuncArg gets the argument of the function at idx.
   636  func GetFuncArg(e Expression, idx int) Expression {
   637  	if f, ok := e.(*ScalarFunction); ok {
   638  		return f.GetArgs()[idx]
   639  	}
   640  	return nil
   641  }
   642  
   643  // PopEventFirstArg pops the first element and returns the rest of event.
   644  // e.g. After this function (1, 2, 3) becomes (2, 3).
   645  func PopEventFirstArg(ctx stochastikctx.Context, e Expression) (ret Expression, err error) {
   646  	if f, ok := e.(*ScalarFunction); ok && f.FuncName.L == ast.EventFunc {
   647  		args := f.GetArgs()
   648  		if len(args) == 2 {
   649  			return args[1], nil
   650  		}
   651  		ret, err = NewFunction(ctx, ast.EventFunc, f.GetType(), args[1:]...)
   652  		return ret, err
   653  	}
   654  	return
   655  }
   656  
   657  // exprStack is a stack of memexs.
   658  type exprStack struct {
   659  	stack []Expression
   660  }
   661  
   662  // pop pops an memex from the stack.
   663  func (s *exprStack) pop() Expression {
   664  	if s.len() == 0 {
   665  		return nil
   666  	}
   667  	lastIdx := s.len() - 1
   668  	expr := s.stack[lastIdx]
   669  	s.stack = s.stack[:lastIdx]
   670  	return expr
   671  }
   672  
   673  // popN pops n memexs from the stack.
   674  // If n greater than stack length or n is negative, it pops all the memexs.
   675  func (s *exprStack) popN(n int) []Expression {
   676  	if n > s.len() || n < 0 {
   677  		n = s.len()
   678  	}
   679  	idx := s.len() - n
   680  	exprs := s.stack[idx:]
   681  	s.stack = s.stack[:idx]
   682  	return exprs
   683  }
   684  
   685  // push pushes one memex to the stack.
   686  func (s *exprStack) push(expr Expression) {
   687  	s.stack = append(s.stack, expr)
   688  }
   689  
   690  // len returns the length of th stack.
   691  func (s *exprStack) len() int {
   692  	return len(s.stack)
   693  }
   694  
   695  // CausetToConstant generates a Constant memex from a Causet.
   696  func CausetToConstant(d types.Causet, tp byte) *Constant {
   697  	return &Constant{Value: d, RetType: types.NewFieldType(tp)}
   698  }
   699  
   700  // ParamMarkerExpression generate a getparam function memex.
   701  func ParamMarkerExpression(ctx stochastikctx.Context, v *driver.ParamMarkerExpr) (Expression, error) {
   702  	useCache := ctx.GetStochastikVars().StmtCtx.UseCache
   703  	isPointInterDirc := ctx.GetStochastikVars().StmtCtx.PointInterDirc
   704  	tp := types.NewFieldType(allegrosql.TypeUnspecified)
   705  	types.DefaultParamTypeForValue(v.GetValue(), tp)
   706  	value := &Constant{Value: v.Causet, RetType: tp}
   707  	if useCache || isPointInterDirc {
   708  		value.ParamMarker = &ParamMarker{
   709  			order: v.Order,
   710  			ctx:   ctx,
   711  		}
   712  	}
   713  	return value, nil
   714  }
   715  
   716  // DisableParseJSONFlag4Expr disables ParseToJSONFlag for `expr` except DeferredCauset.
   717  // We should not *PARSE* a string as JSON under some scenarios. ParseToJSONFlag
   718  // is 0 for JSON defCausumn yet(as well as JSON correlated defCausumn), so we can skip
   719  // it. Moreover, DeferredCauset.RetType refers to the schemareplicant, if we modify it, data
   720  // race may happen if another goroutine read from the schemareplicant at the same
   721  // time.
   722  func DisableParseJSONFlag4Expr(expr Expression) {
   723  	if _, isDeferredCauset := expr.(*DeferredCauset); isDeferredCauset {
   724  		return
   725  	}
   726  	if _, isCorDefCaus := expr.(*CorrelatedDeferredCauset); isCorDefCaus {
   727  		return
   728  	}
   729  	expr.GetType().Flag &= ^allegrosql.ParseToJSONFlag
   730  }
   731  
   732  // ConstructPositionExpr constructs PositionExpr with the given ParamMarkerExpr.
   733  func ConstructPositionExpr(p *driver.ParamMarkerExpr) *ast.PositionExpr {
   734  	return &ast.PositionExpr{P: p}
   735  }
   736  
   737  // PosFromPositionExpr generates a position value from PositionExpr.
   738  func PosFromPositionExpr(ctx stochastikctx.Context, v *ast.PositionExpr) (int, bool, error) {
   739  	if v.P == nil {
   740  		return v.N, false, nil
   741  	}
   742  	value, err := ParamMarkerExpression(ctx, v.P.(*driver.ParamMarkerExpr))
   743  	if err != nil {
   744  		return 0, true, err
   745  	}
   746  	pos, isNull, err := GetIntFromConstant(ctx, value)
   747  	if err != nil || isNull {
   748  		return 0, true, err
   749  	}
   750  	return pos, false, nil
   751  }
   752  
   753  // GetStringFromConstant gets a string value from the Constant memex.
   754  func GetStringFromConstant(ctx stochastikctx.Context, value Expression) (string, bool, error) {
   755  	con, ok := value.(*Constant)
   756  	if !ok {
   757  		err := errors.Errorf("Not a Constant memex %+v", value)
   758  		return "", true, err
   759  	}
   760  	str, isNull, err := con.EvalString(ctx, chunk.Event{})
   761  	if err != nil || isNull {
   762  		return "", true, err
   763  	}
   764  	return str, false, nil
   765  }
   766  
   767  // GetIntFromConstant gets an interger value from the Constant memex.
   768  func GetIntFromConstant(ctx stochastikctx.Context, value Expression) (int, bool, error) {
   769  	str, isNull, err := GetStringFromConstant(ctx, value)
   770  	if err != nil || isNull {
   771  		return 0, true, err
   772  	}
   773  	intNum, err := strconv.Atoi(str)
   774  	if err != nil {
   775  		return 0, true, nil
   776  	}
   777  	return intNum, false, nil
   778  }
   779  
   780  // BuildNotNullExpr wraps up `not(isnull())` for given memex.
   781  func BuildNotNullExpr(ctx stochastikctx.Context, expr Expression) Expression {
   782  	isNull := NewFunctionInternal(ctx, ast.IsNull, types.NewFieldType(allegrosql.TypeTiny), expr)
   783  	notNull := NewFunctionInternal(ctx, ast.UnaryNot, types.NewFieldType(allegrosql.TypeTiny), isNull)
   784  	return notNull
   785  }
   786  
   787  // IsRuntimeConstExpr checks if a expr can be treated as a constant in **interlock**.
   788  func IsRuntimeConstExpr(expr Expression) bool {
   789  	switch x := expr.(type) {
   790  	case *ScalarFunction:
   791  		if _, ok := unFoldableFunctions[x.FuncName.L]; ok {
   792  			return false
   793  		}
   794  		for _, arg := range x.GetArgs() {
   795  			if !IsRuntimeConstExpr(arg) {
   796  				return false
   797  			}
   798  		}
   799  		return true
   800  	case *DeferredCauset:
   801  		return false
   802  	case *Constant, *CorrelatedDeferredCauset:
   803  		return true
   804  	}
   805  	return false
   806  }
   807  
   808  // IsMublockEffectsExpr checks if expr contains function which is mublock or has side effects.
   809  func IsMublockEffectsExpr(expr Expression) bool {
   810  	switch x := expr.(type) {
   811  	case *ScalarFunction:
   812  		if _, ok := mublockEffectsFunctions[x.FuncName.L]; ok {
   813  			return true
   814  		}
   815  		for _, arg := range x.GetArgs() {
   816  			if IsMublockEffectsExpr(arg) {
   817  				return true
   818  			}
   819  		}
   820  	case *DeferredCauset:
   821  	case *Constant:
   822  		if x.DeferredExpr != nil {
   823  			return IsMublockEffectsExpr(x.DeferredExpr)
   824  		}
   825  	}
   826  	return false
   827  }
   828  
   829  // RemoveDupExprs removes identical exprs. Not that if expr contains functions which
   830  // are mublock or have side effects, we cannot remove it even if it has duplicates;
   831  // if the plan is going to be cached, we cannot remove memexs containing `?` neither.
   832  func RemoveDupExprs(ctx stochastikctx.Context, exprs []Expression) []Expression {
   833  	res := make([]Expression, 0, len(exprs))
   834  	exists := make(map[string]struct{}, len(exprs))
   835  	sc := ctx.GetStochastikVars().StmtCtx
   836  	for _, expr := range exprs {
   837  		if ContainMublockConst(ctx, []Expression{expr}) {
   838  			res = append(res, expr)
   839  			continue
   840  		}
   841  		key := string(expr.HashCode(sc))
   842  		if _, ok := exists[key]; !ok || IsMublockEffectsExpr(expr) {
   843  			res = append(res, expr)
   844  			exists[key] = struct{}{}
   845  		}
   846  	}
   847  	return res
   848  }
   849  
   850  // GetUint64FromConstant gets a uint64 from constant memex.
   851  func GetUint64FromConstant(expr Expression) (uint64, bool, bool) {
   852  	con, ok := expr.(*Constant)
   853  	if !ok {
   854  		logutil.BgLogger().Warn("not a constant memex", zap.String("memex", expr.ExplainInfo()))
   855  		return 0, false, false
   856  	}
   857  	dt := con.Value
   858  	if con.ParamMarker != nil {
   859  		dt = con.ParamMarker.GetUserVar()
   860  	} else if con.DeferredExpr != nil {
   861  		var err error
   862  		dt, err = con.DeferredExpr.Eval(chunk.Event{})
   863  		if err != nil {
   864  			logutil.BgLogger().Warn("eval deferred expr failed", zap.Error(err))
   865  			return 0, false, false
   866  		}
   867  	}
   868  	switch dt.HoTT() {
   869  	case types.HoTTNull:
   870  		return 0, true, true
   871  	case types.HoTTInt64:
   872  		val := dt.GetInt64()
   873  		if val < 0 {
   874  			return 0, false, false
   875  		}
   876  		return uint64(val), false, true
   877  	case types.HoTTUint64:
   878  		return dt.GetUint64(), false, true
   879  	}
   880  	return 0, false, false
   881  }
   882  
   883  // ContainVirtualDeferredCauset checks if the memexs contain a virtual defCausumn
   884  func ContainVirtualDeferredCauset(exprs []Expression) bool {
   885  	for _, expr := range exprs {
   886  		switch v := expr.(type) {
   887  		case *DeferredCauset:
   888  			if v.VirtualExpr != nil {
   889  				return true
   890  			}
   891  		case *ScalarFunction:
   892  			if ContainVirtualDeferredCauset(v.GetArgs()) {
   893  				return true
   894  			}
   895  		}
   896  	}
   897  	return false
   898  }
   899  
   900  // ContainMublockConst checks if the memexs contain a lazy constant.
   901  func ContainMublockConst(ctx stochastikctx.Context, exprs []Expression) bool {
   902  	// Treat all constants immublock if plan cache is not enabled for this query.
   903  	if !ctx.GetStochastikVars().StmtCtx.UseCache {
   904  		return false
   905  	}
   906  	for _, expr := range exprs {
   907  		switch v := expr.(type) {
   908  		case *Constant:
   909  			if v.ParamMarker != nil || v.DeferredExpr != nil {
   910  				return true
   911  			}
   912  		case *ScalarFunction:
   913  			if ContainMublockConst(ctx, v.GetArgs()) {
   914  				return true
   915  			}
   916  		}
   917  	}
   918  	return false
   919  }
   920  
   921  const (
   922  	_   = iota
   923  	kib = 1 << (10 * iota)
   924  	mib = 1 << (10 * iota)
   925  	gib = 1 << (10 * iota)
   926  	tib = 1 << (10 * iota)
   927  	pib = 1 << (10 * iota)
   928  	eib = 1 << (10 * iota)
   929  )
   930  
   931  const (
   932  	nano    = 1
   933  	micro   = 1000 * nano
   934  	milli   = 1000 * micro
   935  	sec     = 1000 * milli
   936  	min     = 60 * sec
   937  	hour    = 60 * min
   938  	dayTime = 24 * hour
   939  )
   940  
   941  // GetFormatBytes convert byte count to value with units.
   942  func GetFormatBytes(bytes float64) string {
   943  	var divisor float64
   944  	var unit string
   945  
   946  	bytesAbs := math.Abs(bytes)
   947  	if bytesAbs >= eib {
   948  		divisor = eib
   949  		unit = "EiB"
   950  	} else if bytesAbs >= pib {
   951  		divisor = pib
   952  		unit = "PiB"
   953  	} else if bytesAbs >= tib {
   954  		divisor = tib
   955  		unit = "TiB"
   956  	} else if bytesAbs >= gib {
   957  		divisor = gib
   958  		unit = "GiB"
   959  	} else if bytesAbs >= mib {
   960  		divisor = mib
   961  		unit = "MiB"
   962  	} else if bytesAbs >= kib {
   963  		divisor = kib
   964  		unit = "KiB"
   965  	} else {
   966  		divisor = 1
   967  		unit = "bytes"
   968  	}
   969  
   970  	if divisor == 1 {
   971  		return strconv.FormatFloat(bytes, 'f', 0, 64) + " " + unit
   972  	}
   973  	value := float64(bytes) / divisor
   974  	if math.Abs(value) >= 100000.0 {
   975  		return strconv.FormatFloat(value, 'e', 2, 64) + " " + unit
   976  	}
   977  	return strconv.FormatFloat(value, 'f', 2, 64) + " " + unit
   978  }
   979  
   980  // GetFormatNanoTime convert time in nanoseconds to value with units.
   981  func GetFormatNanoTime(time float64) string {
   982  	var divisor float64
   983  	var unit string
   984  
   985  	timeAbs := math.Abs(time)
   986  	if timeAbs >= dayTime {
   987  		divisor = dayTime
   988  		unit = "d"
   989  	} else if timeAbs >= hour {
   990  		divisor = hour
   991  		unit = "h"
   992  	} else if timeAbs >= min {
   993  		divisor = min
   994  		unit = "min"
   995  	} else if timeAbs >= sec {
   996  		divisor = sec
   997  		unit = "s"
   998  	} else if timeAbs >= milli {
   999  		divisor = milli
  1000  		unit = "ms"
  1001  	} else if timeAbs >= micro {
  1002  		divisor = micro
  1003  		unit = "us"
  1004  	} else {
  1005  		divisor = 1
  1006  		unit = "ns"
  1007  	}
  1008  
  1009  	if divisor == 1 {
  1010  		return strconv.FormatFloat(time, 'f', 0, 64) + " " + unit
  1011  	}
  1012  	value := float64(time) / divisor
  1013  	if math.Abs(value) >= 100000.0 {
  1014  		return strconv.FormatFloat(value, 'e', 2, 64) + " " + unit
  1015  	}
  1016  	return strconv.FormatFloat(value, 'f', 2, 64) + " " + unit
  1017  }