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 }