github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/plan/rule/constant_fold.go (about)

     1  // Copyright 2021 - 2022 Matrix Origin
     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  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package rule
    16  
    17  import (
    18  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    19  	"github.com/matrixorigin/matrixone/pkg/container/batch"
    20  	"github.com/matrixorigin/matrixone/pkg/container/types"
    21  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    22  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    23  	"github.com/matrixorigin/matrixone/pkg/sql/colexec"
    24  	"github.com/matrixorigin/matrixone/pkg/sql/plan/function"
    25  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    26  )
    27  
    28  type ConstantFold struct {
    29  	bat        *batch.Batch
    30  	isPrepared bool
    31  }
    32  
    33  func NewConstantFold(isPrepared bool) *ConstantFold {
    34  	bat := batch.EmptyForConstFoldBatch
    35  	return &ConstantFold{
    36  		bat:        bat,
    37  		isPrepared: isPrepared,
    38  	}
    39  }
    40  
    41  func (r *ConstantFold) GetBatch() *batch.Batch {
    42  	return r.bat
    43  }
    44  
    45  // Match always true
    46  func (r *ConstantFold) Match(n *plan.Node) bool {
    47  	return true
    48  }
    49  
    50  func (r *ConstantFold) Apply(n *plan.Node, _ *plan.Query, proc *process.Process) {
    51  	if n.Limit != nil {
    52  		n.Limit = r.constantFold(n.Limit, proc)
    53  	}
    54  	if n.Offset != nil {
    55  		n.Offset = r.constantFold(n.Offset, proc)
    56  	}
    57  	if len(n.OnList) > 0 {
    58  		for i := range n.OnList {
    59  			n.OnList[i] = r.constantFold(n.OnList[i], proc)
    60  		}
    61  	}
    62  	if len(n.FilterList) > 0 {
    63  		for i := range n.FilterList {
    64  			n.FilterList[i] = r.constantFold(n.FilterList[i], proc)
    65  		}
    66  	}
    67  	if len(n.BlockFilterList) > 0 {
    68  		for i := range n.BlockFilterList {
    69  			n.BlockFilterList[i] = r.constantFold(n.BlockFilterList[i], proc)
    70  		}
    71  	}
    72  
    73  	if len(n.ProjectList) > 0 {
    74  		for i := range n.ProjectList {
    75  			n.ProjectList[i] = r.constantFold(n.ProjectList[i], proc)
    76  		}
    77  	}
    78  }
    79  
    80  func (r *ConstantFold) constantFold(expr *plan.Expr, proc *process.Process) *plan.Expr {
    81  	if expr.Typ.Id == int32(types.T_interval) {
    82  		panic(moerr.NewInternalError(proc.Ctx, "not supported type INTERVAL"))
    83  	}
    84  
    85  	fn := expr.GetF()
    86  	if fn == nil {
    87  		if elist := expr.GetList(); elist != nil {
    88  			exprList := elist.List
    89  			for i := range exprList {
    90  				exprList[i] = r.constantFold(exprList[i], proc)
    91  			}
    92  
    93  			vec, err := colexec.GenerateConstListExpressionExecutor(proc, exprList)
    94  			if err != nil {
    95  				return expr
    96  			}
    97  			defer vec.Free(proc.Mp())
    98  
    99  			vec.InplaceSortAndCompact()
   100  
   101  			data, err := vec.MarshalBinary()
   102  			if err != nil {
   103  				return expr
   104  			}
   105  
   106  			return &plan.Expr{
   107  				Typ: expr.Typ,
   108  				Expr: &plan.Expr_Vec{
   109  					Vec: &plan.LiteralVec{
   110  						Len:  int32(vec.Length()),
   111  						Data: data,
   112  					},
   113  				},
   114  			}
   115  		}
   116  
   117  		return expr
   118  	}
   119  	overloadID := fn.Func.GetObj()
   120  	f, exists := function.GetFunctionByIdWithoutError(overloadID)
   121  	if !exists {
   122  		return expr
   123  	}
   124  	if f.CannotFold() { // function cannot be fold
   125  		return expr
   126  	}
   127  	if f.IsRealTimeRelated() && r.isPrepared {
   128  		return expr
   129  	}
   130  	isVec := false
   131  	for i := range fn.Args {
   132  		fn.Args[i] = r.constantFold(fn.Args[i], proc)
   133  		isVec = isVec || fn.Args[i].GetVec() != nil
   134  	}
   135  	if !IsConstant(expr, false) {
   136  		return expr
   137  	}
   138  
   139  	vec, err := colexec.EvalExpressionOnce(proc, expr, []*batch.Batch{r.bat})
   140  	if err != nil {
   141  		return expr
   142  	}
   143  	defer vec.Free(proc.Mp())
   144  
   145  	if isVec {
   146  		data, err := vec.MarshalBinary()
   147  		if err != nil {
   148  			return expr
   149  		}
   150  
   151  		return &plan.Expr{
   152  			Typ: expr.Typ,
   153  			Expr: &plan.Expr_Vec{
   154  				Vec: &plan.LiteralVec{
   155  					Len:  int32(vec.Length()),
   156  					Data: data,
   157  				},
   158  			},
   159  		}
   160  	}
   161  
   162  	c := GetConstantValue(vec, false, 0)
   163  	if c == nil {
   164  		return expr
   165  	}
   166  
   167  	if f.IsRealTimeRelated() {
   168  		c.Src = &plan.Expr{
   169  			Typ: plan.Type{
   170  				Id:          expr.Typ.Id,
   171  				NotNullable: expr.Typ.NotNullable,
   172  				Width:       expr.Typ.Width,
   173  				Scale:       expr.Typ.Scale,
   174  				AutoIncr:    expr.Typ.AutoIncr,
   175  				Table:       expr.Typ.Table,
   176  			},
   177  			Expr: &plan.Expr_F{
   178  				F: &plan.Function{
   179  					Func: &plan.ObjectRef{
   180  						Server:     fn.Func.GetServer(),
   181  						Db:         fn.Func.GetDb(),
   182  						Schema:     fn.Func.GetSchema(),
   183  						Obj:        fn.Func.GetObj(),
   184  						ServerName: fn.Func.GetServerName(),
   185  						DbName:     fn.Func.GetDbName(),
   186  						SchemaName: fn.Func.GetSchemaName(),
   187  						ObjName:    fn.Func.GetObjName(),
   188  					},
   189  					Args: make([]*plan.Expr, 0),
   190  				},
   191  			},
   192  		}
   193  	} else {
   194  		existRealTimeFunc := false
   195  		for i, expr := range fn.Args {
   196  			if ac, cok := expr.Expr.(*plan.Expr_Lit); cok && ac.Lit.Src != nil {
   197  				if _, pok := ac.Lit.Src.Expr.(*plan.Expr_V); !pok {
   198  					fn.Args[i] = ac.Lit.Src
   199  					existRealTimeFunc = true
   200  				}
   201  			}
   202  		}
   203  		if existRealTimeFunc {
   204  			c.Src = &plan.Expr{
   205  				Typ: plan.Type{
   206  					Id:          expr.Typ.Id,
   207  					NotNullable: expr.Typ.NotNullable,
   208  					Width:       expr.Typ.Width,
   209  					Scale:       expr.Typ.Scale,
   210  					AutoIncr:    expr.Typ.AutoIncr,
   211  					Table:       expr.Typ.Table,
   212  				},
   213  				Expr: &plan.Expr_F{
   214  					F: fn,
   215  				},
   216  			}
   217  		}
   218  	}
   219  
   220  	ec := &plan.Expr_Lit{
   221  		Lit: c,
   222  	}
   223  	expr.Typ = plan.Type{Id: int32(vec.GetType().Oid), Scale: vec.GetType().Scale, Width: vec.GetType().Width}
   224  	expr.Expr = ec
   225  
   226  	return expr
   227  }
   228  
   229  func GetConstantValue(vec *vector.Vector, transAll bool, row uint64) *plan.Literal {
   230  	if vec.IsConstNull() || vec.GetNulls().Contains(row) {
   231  		return &plan.Literal{Isnull: true}
   232  	}
   233  	switch vec.GetType().Oid {
   234  	case types.T_bool:
   235  		return &plan.Literal{
   236  			Value: &plan.Literal_Bval{
   237  				Bval: vector.MustFixedCol[bool](vec)[row],
   238  			},
   239  		}
   240  	case types.T_bit:
   241  		return &plan.Literal{
   242  			Value: &plan.Literal_U64Val{
   243  				U64Val: vector.MustFixedCol[uint64](vec)[row],
   244  			},
   245  		}
   246  	case types.T_int8:
   247  		return &plan.Literal{
   248  			Value: &plan.Literal_I8Val{
   249  				I8Val: int32(vector.MustFixedCol[int8](vec)[row]),
   250  			},
   251  		}
   252  	case types.T_int16:
   253  		return &plan.Literal{
   254  			Value: &plan.Literal_I16Val{
   255  				I16Val: int32(vector.MustFixedCol[int16](vec)[row]),
   256  			},
   257  		}
   258  	case types.T_int32:
   259  		return &plan.Literal{
   260  			Value: &plan.Literal_I32Val{
   261  				I32Val: vector.MustFixedCol[int32](vec)[row],
   262  			},
   263  		}
   264  	case types.T_int64:
   265  		return &plan.Literal{
   266  			Value: &plan.Literal_I64Val{
   267  				I64Val: vector.MustFixedCol[int64](vec)[row],
   268  			},
   269  		}
   270  	case types.T_uint8:
   271  		return &plan.Literal{
   272  			Value: &plan.Literal_U8Val{
   273  				U8Val: uint32(vector.MustFixedCol[uint8](vec)[row]),
   274  			},
   275  		}
   276  	case types.T_uint16:
   277  		return &plan.Literal{
   278  			Value: &plan.Literal_U16Val{
   279  				U16Val: uint32(vector.MustFixedCol[uint16](vec)[row]),
   280  			},
   281  		}
   282  	case types.T_uint32:
   283  		return &plan.Literal{
   284  			Value: &plan.Literal_U32Val{
   285  				U32Val: vector.MustFixedCol[uint32](vec)[row],
   286  			},
   287  		}
   288  	case types.T_uint64:
   289  		return &plan.Literal{
   290  			Value: &plan.Literal_U64Val{
   291  				U64Val: vector.MustFixedCol[uint64](vec)[row],
   292  			},
   293  		}
   294  	case types.T_float32:
   295  		return &plan.Literal{
   296  			Value: &plan.Literal_Fval{
   297  				Fval: vector.MustFixedCol[float32](vec)[row],
   298  			},
   299  		}
   300  	case types.T_float64:
   301  		return &plan.Literal{
   302  			Value: &plan.Literal_Dval{
   303  				Dval: vector.MustFixedCol[float64](vec)[row],
   304  			},
   305  		}
   306  	case types.T_varchar, types.T_char,
   307  		types.T_binary, types.T_varbinary, types.T_text, types.T_blob:
   308  		return &plan.Literal{
   309  			Value: &plan.Literal_Sval{
   310  				Sval: vec.GetStringAt(int(row)),
   311  			},
   312  		}
   313  	case types.T_json:
   314  		if !transAll {
   315  			return nil
   316  		}
   317  		return &plan.Literal{
   318  			Value: &plan.Literal_Sval{
   319  				Sval: vec.GetStringAt(0),
   320  			},
   321  		}
   322  	case types.T_timestamp:
   323  		return &plan.Literal{
   324  			Value: &plan.Literal_Timestampval{
   325  				Timestampval: int64(vector.MustFixedCol[types.Timestamp](vec)[row]),
   326  			},
   327  		}
   328  	case types.T_date:
   329  		return &plan.Literal{
   330  			Value: &plan.Literal_Dateval{
   331  				Dateval: int32(vector.MustFixedCol[types.Date](vec)[row]),
   332  			},
   333  		}
   334  	case types.T_time:
   335  		return &plan.Literal{
   336  			Value: &plan.Literal_Timeval{
   337  				Timeval: int64(vector.MustFixedCol[types.Time](vec)[row]),
   338  			},
   339  		}
   340  	case types.T_datetime:
   341  		return &plan.Literal{
   342  			Value: &plan.Literal_Datetimeval{
   343  				Datetimeval: int64(vector.MustFixedCol[types.Datetime](vec)[row]),
   344  			},
   345  		}
   346  	case types.T_enum:
   347  		if !transAll {
   348  			return nil
   349  		}
   350  		return &plan.Literal{
   351  			Value: &plan.Literal_EnumVal{
   352  				EnumVal: uint32(vector.MustFixedCol[types.Enum](vec)[row]),
   353  			},
   354  		}
   355  	case types.T_decimal64:
   356  		return &plan.Literal{
   357  			Value: &plan.Literal_Decimal64Val{
   358  				Decimal64Val: &plan.Decimal64{A: int64(vector.MustFixedCol[types.Decimal64](vec)[row])},
   359  			},
   360  		}
   361  	case types.T_decimal128:
   362  		decimalValue := &plan.Decimal128{}
   363  		decimalValue.A = int64(vector.MustFixedCol[types.Decimal128](vec)[row].B0_63)
   364  		decimalValue.B = int64(vector.MustFixedCol[types.Decimal128](vec)[row].B64_127)
   365  		return &plan.Literal{Value: &plan.Literal_Decimal128Val{Decimal128Val: decimalValue}}
   366  	default:
   367  		return nil
   368  	}
   369  }
   370  
   371  func IsConstant(e *plan.Expr, varAndParamIsConst bool) bool {
   372  	switch ef := e.Expr.(type) {
   373  	case *plan.Expr_Lit, *plan.Expr_T, *plan.Expr_Vec:
   374  		return true
   375  	case *plan.Expr_F:
   376  		overloadID := ef.F.Func.GetObj()
   377  		f, exists := function.GetFunctionByIdWithoutError(overloadID)
   378  		if !exists {
   379  			return false
   380  		}
   381  		if f.CannotFold() { // function cannot be fold
   382  			return false
   383  		}
   384  		for i := range ef.F.Args {
   385  			if !IsConstant(ef.F.Args[i], varAndParamIsConst) {
   386  				return false
   387  			}
   388  		}
   389  		return true
   390  	case *plan.Expr_List:
   391  		for _, arg := range ef.List.List {
   392  			if !IsConstant(arg, varAndParamIsConst) {
   393  				return false
   394  			}
   395  		}
   396  		return true
   397  	case *plan.Expr_P:
   398  		return varAndParamIsConst
   399  	case *plan.Expr_V:
   400  		return varAndParamIsConst
   401  	default:
   402  		return false
   403  	}
   404  }