github.com/matrixorigin/matrixone@v0.7.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/container/batch" 19 "github.com/matrixorigin/matrixone/pkg/container/nulls" 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.NewWithSize(0) 35 bat.Zs = []int64{1} 36 return &ConstantFold{ 37 bat: bat, 38 isPrepared: isPrepared, 39 } 40 } 41 42 func (r *ConstantFold) GetBatch() *batch.Batch { 43 return r.bat 44 } 45 46 // Match always true 47 func (r *ConstantFold) Match(n *plan.Node) bool { 48 return true 49 } 50 51 func (r *ConstantFold) Apply(n *plan.Node, _ *plan.Query, proc *process.Process) { 52 if n.Limit != nil { 53 n.Limit = r.constantFold(n.Limit, proc) 54 } 55 if n.Offset != nil { 56 n.Offset = r.constantFold(n.Offset, proc) 57 } 58 if len(n.OnList) > 0 { 59 for i := range n.OnList { 60 n.OnList[i] = r.constantFold(n.OnList[i], proc) 61 } 62 } 63 if len(n.FilterList) > 0 { 64 for i := range n.FilterList { 65 n.FilterList[i] = r.constantFold(n.FilterList[i], proc) 66 } 67 } 68 if len(n.ProjectList) > 0 { 69 for i := range n.ProjectList { 70 n.ProjectList[i] = r.constantFold(n.ProjectList[i], proc) 71 } 72 } 73 } 74 75 func (r *ConstantFold) constantFold(e *plan.Expr, proc *process.Process) *plan.Expr { 76 ef, ok := e.Expr.(*plan.Expr_F) 77 if !ok { 78 if el, ok := e.Expr.(*plan.Expr_List); ok { 79 lenList := len(el.List.List) 80 for i := 0; i < lenList; i++ { 81 el.List.List[i] = r.constantFold(el.List.List[i], proc) 82 } 83 } 84 return e 85 } 86 overloadID := ef.F.Func.GetObj() 87 f, exists := function.GetFunctionByIDWithoutError(overloadID) 88 if !exists { 89 return e 90 } 91 if f.Volatile { // function cannot be fold 92 return e 93 } 94 if f.RealTimeRelated && r.isPrepared { 95 return e 96 } 97 for i := range ef.F.Args { 98 ef.F.Args[i] = r.constantFold(ef.F.Args[i], proc) 99 } 100 if !IsConstant(e) { 101 return e 102 } 103 vec, err := colexec.EvalExpr(r.bat, proc, e) 104 if err != nil { 105 return e 106 } 107 c := GetConstantValue(vec, false) 108 if c == nil { 109 return e 110 } 111 112 if f.RealTimeRelated { 113 c.Src = &plan.Expr{ 114 Typ: &plan.Type{ 115 Id: e.Typ.Id, 116 NotNullable: e.Typ.NotNullable, 117 Width: e.Typ.Width, 118 Precision: e.Typ.Precision, 119 Size: e.Typ.Size, 120 Scale: e.Typ.Scale, 121 AutoIncr: e.Typ.AutoIncr, 122 Table: e.Typ.Table, 123 }, 124 Expr: &plan.Expr_F{ 125 F: &plan.Function{ 126 Func: &plan.ObjectRef{ 127 Server: ef.F.Func.GetServer(), 128 Db: ef.F.Func.GetDb(), 129 Schema: ef.F.Func.GetSchema(), 130 Obj: ef.F.Func.GetObj(), 131 ServerName: ef.F.Func.GetServerName(), 132 DbName: ef.F.Func.GetDbName(), 133 SchemaName: ef.F.Func.GetSchemaName(), 134 ObjName: ef.F.Func.GetObjName(), 135 }, 136 Args: make([]*plan.Expr, 0), 137 }, 138 }, 139 } 140 } else { 141 existRealTimeFunc := false 142 for i, expr := range ef.F.Args { 143 if ac, cok := expr.Expr.(*plan.Expr_C); cok && ac.C.Src != nil { 144 if _, pok := ac.C.Src.Expr.(*plan.Expr_V); !pok { 145 ef.F.Args[i] = ac.C.Src 146 existRealTimeFunc = true 147 } 148 } 149 } 150 if existRealTimeFunc { 151 c.Src = &plan.Expr{ 152 Typ: &plan.Type{ 153 Id: e.Typ.Id, 154 NotNullable: e.Typ.NotNullable, 155 Width: e.Typ.Width, 156 Precision: e.Typ.Precision, 157 Size: e.Typ.Size, 158 Scale: e.Typ.Scale, 159 AutoIncr: e.Typ.AutoIncr, 160 Table: e.Typ.Table, 161 }, 162 Expr: ef, 163 } 164 } 165 } 166 167 ec := &plan.Expr_C{ 168 C: c, 169 } 170 e.Typ = &plan.Type{Id: int32(vec.Typ.Oid), Precision: vec.Typ.Precision, Scale: vec.Typ.Scale, Width: vec.Typ.Width, Size: vec.Typ.Size} 171 e.Expr = ec 172 return e 173 } 174 175 func GetConstantValue(vec *vector.Vector, transAll bool) *plan.Const { 176 if nulls.Any(vec.Nsp) { 177 return &plan.Const{Isnull: true} 178 } 179 switch vec.Typ.Oid { 180 case types.T_bool: 181 return &plan.Const{ 182 Value: &plan.Const_Bval{ 183 Bval: vec.Col.([]bool)[0], 184 }, 185 } 186 case types.T_int8: 187 return &plan.Const{ 188 Value: &plan.Const_I8Val{ 189 I8Val: int32(vec.Col.([]int8)[0]), 190 }, 191 } 192 case types.T_int16: 193 return &plan.Const{ 194 Value: &plan.Const_I16Val{ 195 I16Val: int32(vec.Col.([]int16)[0]), 196 }, 197 } 198 case types.T_int32: 199 return &plan.Const{ 200 Value: &plan.Const_I32Val{ 201 I32Val: vec.Col.([]int32)[0], 202 }, 203 } 204 case types.T_int64: 205 return &plan.Const{ 206 Value: &plan.Const_I64Val{ 207 I64Val: vec.Col.([]int64)[0], 208 }, 209 } 210 case types.T_uint8: 211 return &plan.Const{ 212 Value: &plan.Const_U8Val{ 213 U8Val: uint32(vec.Col.([]uint8)[0]), 214 }, 215 } 216 case types.T_uint16: 217 return &plan.Const{ 218 Value: &plan.Const_U16Val{ 219 U16Val: uint32(vec.Col.([]uint16)[0]), 220 }, 221 } 222 case types.T_uint32: 223 return &plan.Const{ 224 Value: &plan.Const_U32Val{ 225 U32Val: vec.Col.([]uint32)[0], 226 }, 227 } 228 case types.T_uint64: 229 return &plan.Const{ 230 Value: &plan.Const_U64Val{ 231 U64Val: vec.Col.([]uint64)[0], 232 }, 233 } 234 case types.T_float32: 235 return &plan.Const{ 236 Value: &plan.Const_Fval{ 237 Fval: vec.Col.([]float32)[0], 238 }, 239 } 240 case types.T_float64: 241 return &plan.Const{ 242 Value: &plan.Const_Dval{ 243 Dval: vec.Col.([]float64)[0], 244 }, 245 } 246 case types.T_varchar, types.T_char, types.T_text, types.T_blob: 247 return &plan.Const{ 248 Value: &plan.Const_Sval{ 249 Sval: vec.GetString(0), 250 }, 251 } 252 case types.T_json: 253 if !transAll { 254 return nil 255 } 256 return &plan.Const{ 257 Value: &plan.Const_Sval{ 258 Sval: vec.GetString(0), 259 }, 260 } 261 case types.T_timestamp: 262 return &plan.Const{ 263 Value: &plan.Const_Timestampval{ 264 Timestampval: int64(vector.MustTCols[types.Timestamp](vec)[0]), 265 }, 266 } 267 case types.T_date: 268 return &plan.Const{ 269 Value: &plan.Const_Dateval{ 270 Dateval: int32(vector.MustTCols[types.Date](vec)[0]), 271 }, 272 } 273 case types.T_time: 274 if !transAll { 275 return nil 276 } 277 return &plan.Const{ 278 Value: &plan.Const_Timeval{ 279 Timeval: int64(vector.MustTCols[types.Time](vec)[0]), 280 }, 281 } 282 case types.T_datetime: 283 if !transAll { 284 return nil 285 } 286 return &plan.Const{ 287 Value: &plan.Const_Datetimeval{ 288 Datetimeval: int64(vector.MustTCols[types.Datetime](vec)[0]), 289 }, 290 } 291 case types.T_decimal64: 292 if !transAll { 293 return nil 294 } 295 return &plan.Const{ 296 Value: &plan.Const_Decimal64Val{ 297 Decimal64Val: &plan.Decimal64{A: types.Decimal64ToInt64Raw(vector.MustTCols[types.Decimal64](vec)[0])}, 298 }, 299 } 300 case types.T_decimal128: 301 if !transAll { 302 return nil 303 } 304 decimalValue := &plan.Decimal128{} 305 decimalValue.A, decimalValue.B = types.Decimal128ToInt64Raw(vector.MustTCols[types.Decimal128](vec)[0]) 306 return &plan.Const{Value: &plan.Const_Decimal128Val{Decimal128Val: decimalValue}} 307 default: 308 return nil 309 } 310 } 311 312 func IsConstant(e *plan.Expr) bool { 313 switch ef := e.Expr.(type) { 314 case *plan.Expr_C, *plan.Expr_T: 315 return true 316 case *plan.Expr_F: 317 overloadID := ef.F.Func.GetObj() 318 f, exists := function.GetFunctionByIDWithoutError(overloadID) 319 if !exists { 320 return false 321 } 322 if f.Volatile { // function cannot be fold 323 return false 324 } 325 for i := range ef.F.Args { 326 if !IsConstant(ef.F.Args[i]) { 327 return false 328 } 329 } 330 return true 331 default: 332 return false 333 } 334 }