github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/interlock/aggfuncs/func_value.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 aggfuncs
    15  
    16  import (
    17  	"unsafe"
    18  
    19  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    20  	"github.com/whtcorpsinc/milevadb/memex"
    21  	"github.com/whtcorpsinc/milevadb/stochastikctx"
    22  	"github.com/whtcorpsinc/milevadb/types"
    23  	"github.com/whtcorpsinc/milevadb/types/json"
    24  	"github.com/whtcorpsinc/milevadb/soliton/chunk"
    25  )
    26  
    27  const (
    28  	// DefPartialResult4FirstValueSize is the size of partialResult4FirstValue
    29  	DefPartialResult4FirstValueSize = int64(unsafe.Sizeof(partialResult4FirstValue{}))
    30  	// DefPartialResult4LastValueSize is the size of partialResult4LastValue
    31  	DefPartialResult4LastValueSize = int64(unsafe.Sizeof(partialResult4LastValue{}))
    32  	// DefPartialResult4NthValueSize is the size of partialResult4NthValue
    33  	DefPartialResult4NthValueSize = int64(unsafe.Sizeof(partialResult4NthValue{}))
    34  
    35  	// DefValue4IntSize is the size of value4Int
    36  	DefValue4IntSize = int64(unsafe.Sizeof(value4Int{}))
    37  	// DefValue4Float32Size is the size of value4Float32
    38  	DefValue4Float32Size = int64(unsafe.Sizeof(value4Float32{}))
    39  	// DefValue4Float64Size is the size of value4Float64
    40  	DefValue4Float64Size = int64(unsafe.Sizeof(value4Float64{}))
    41  	// DefValue4DecimalSize is the size of value4Decimal
    42  	DefValue4DecimalSize = int64(unsafe.Sizeof(value4Decimal{}))
    43  	// DefValue4TimeSize is the size of value4Time
    44  	DefValue4TimeSize = int64(unsafe.Sizeof(value4Time{}))
    45  	// DefValue4DurationSize is the size of value4Duration
    46  	DefValue4DurationSize = int64(unsafe.Sizeof(value4Duration{}))
    47  	// DefValue4StringSize is the size of value4String
    48  	DefValue4StringSize = int64(unsafe.Sizeof(value4String{}))
    49  	// DefValue4JSONSize is the size of value4JSON
    50  	DefValue4JSONSize = int64(unsafe.Sizeof(value4JSON{}))
    51  )
    52  
    53  // valueEvaluator is used to evaluate values for `first_value`, `last_value`, `nth_value`,
    54  // `lead` and `lag`.
    55  type valueEvaluator interface {
    56  	// evaluateEvent evaluates the memex using event and stores the result inside.
    57  	evaluateEvent(ctx stochastikctx.Context, expr memex.Expression, event chunk.Event) (memDelta int64, err error)
    58  	// appendResult appends the result to chunk.
    59  	appendResult(chk *chunk.Chunk, defCausIdx int)
    60  }
    61  
    62  type value4Int struct {
    63  	val    int64
    64  	isNull bool
    65  }
    66  
    67  func (v *value4Int) evaluateEvent(ctx stochastikctx.Context, expr memex.Expression, event chunk.Event) (memDelta int64, err error) {
    68  	v.val, v.isNull, err = expr.EvalInt(ctx, event)
    69  	return 0, err
    70  }
    71  
    72  func (v *value4Int) appendResult(chk *chunk.Chunk, defCausIdx int) {
    73  	if v.isNull {
    74  		chk.AppendNull(defCausIdx)
    75  	} else {
    76  		chk.AppendInt64(defCausIdx, v.val)
    77  	}
    78  }
    79  
    80  type value4Float32 struct {
    81  	val    float32
    82  	isNull bool
    83  }
    84  
    85  func (v *value4Float32) evaluateEvent(ctx stochastikctx.Context, expr memex.Expression, event chunk.Event) (memDelta int64, err error) {
    86  	var val float64
    87  	val, v.isNull, err = expr.EvalReal(ctx, event)
    88  	v.val = float32(val)
    89  	return 0, err
    90  }
    91  
    92  func (v *value4Float32) appendResult(chk *chunk.Chunk, defCausIdx int) {
    93  	if v.isNull {
    94  		chk.AppendNull(defCausIdx)
    95  	} else {
    96  		chk.AppendFloat32(defCausIdx, v.val)
    97  	}
    98  }
    99  
   100  type value4Decimal struct {
   101  	val    *types.MyDecimal
   102  	isNull bool
   103  }
   104  
   105  func (v *value4Decimal) evaluateEvent(ctx stochastikctx.Context, expr memex.Expression, event chunk.Event) (memDelta int64, err error) {
   106  	v.val, v.isNull, err = expr.EvalDecimal(ctx, event)
   107  	return 0, err
   108  }
   109  
   110  func (v *value4Decimal) appendResult(chk *chunk.Chunk, defCausIdx int) {
   111  	if v.isNull {
   112  		chk.AppendNull(defCausIdx)
   113  	} else {
   114  		chk.AppendMyDecimal(defCausIdx, v.val)
   115  	}
   116  }
   117  
   118  type value4Float64 struct {
   119  	val    float64
   120  	isNull bool
   121  }
   122  
   123  func (v *value4Float64) evaluateEvent(ctx stochastikctx.Context, expr memex.Expression, event chunk.Event) (memDelta int64, err error) {
   124  	v.val, v.isNull, err = expr.EvalReal(ctx, event)
   125  	return 0, err
   126  }
   127  
   128  func (v *value4Float64) appendResult(chk *chunk.Chunk, defCausIdx int) {
   129  	if v.isNull {
   130  		chk.AppendNull(defCausIdx)
   131  	} else {
   132  		chk.AppendFloat64(defCausIdx, v.val)
   133  	}
   134  }
   135  
   136  type value4String struct {
   137  	val    string
   138  	isNull bool
   139  }
   140  
   141  func (v *value4String) evaluateEvent(ctx stochastikctx.Context, expr memex.Expression, event chunk.Event) (memDelta int64, err error) {
   142  	originalLength := len(v.val)
   143  	v.val, v.isNull, err = expr.EvalString(ctx, event)
   144  	return int64(len(v.val) - originalLength), err
   145  }
   146  
   147  func (v *value4String) appendResult(chk *chunk.Chunk, defCausIdx int) {
   148  	if v.isNull {
   149  		chk.AppendNull(defCausIdx)
   150  	} else {
   151  		chk.AppendString(defCausIdx, v.val)
   152  	}
   153  }
   154  
   155  type value4Time struct {
   156  	val    types.Time
   157  	isNull bool
   158  }
   159  
   160  func (v *value4Time) evaluateEvent(ctx stochastikctx.Context, expr memex.Expression, event chunk.Event) (memDelta int64, err error) {
   161  	v.val, v.isNull, err = expr.EvalTime(ctx, event)
   162  	return 0, err
   163  }
   164  
   165  func (v *value4Time) appendResult(chk *chunk.Chunk, defCausIdx int) {
   166  	if v.isNull {
   167  		chk.AppendNull(defCausIdx)
   168  	} else {
   169  		chk.AppendTime(defCausIdx, v.val)
   170  	}
   171  }
   172  
   173  type value4Duration struct {
   174  	val    types.Duration
   175  	isNull bool
   176  }
   177  
   178  func (v *value4Duration) evaluateEvent(ctx stochastikctx.Context, expr memex.Expression, event chunk.Event) (memDelta int64, err error) {
   179  	v.val, v.isNull, err = expr.EvalDuration(ctx, event)
   180  	return 0, err
   181  }
   182  
   183  func (v *value4Duration) appendResult(chk *chunk.Chunk, defCausIdx int) {
   184  	if v.isNull {
   185  		chk.AppendNull(defCausIdx)
   186  	} else {
   187  		chk.AppendDuration(defCausIdx, v.val)
   188  	}
   189  }
   190  
   191  type value4JSON struct {
   192  	val    json.BinaryJSON
   193  	isNull bool
   194  }
   195  
   196  func (v *value4JSON) evaluateEvent(ctx stochastikctx.Context, expr memex.Expression, event chunk.Event) (memDelta int64, err error) {
   197  	originalLength := len(v.val.Value)
   198  	v.val, v.isNull, err = expr.EvalJSON(ctx, event)
   199  	v.val = v.val.Copy() // deep copy to avoid content change.
   200  	return int64(len(v.val.Value) - originalLength), err
   201  }
   202  
   203  func (v *value4JSON) appendResult(chk *chunk.Chunk, defCausIdx int) {
   204  	if v.isNull {
   205  		chk.AppendNull(defCausIdx)
   206  	} else {
   207  		chk.AppendJSON(defCausIdx, v.val)
   208  	}
   209  }
   210  
   211  func buildValueEvaluator(tp *types.FieldType) (ve valueEvaluator, memDelta int64) {
   212  	evalType := tp.EvalType()
   213  	if tp.Tp == allegrosql.TypeBit {
   214  		evalType = types.ETString
   215  	}
   216  	switch evalType {
   217  	case types.ETInt:
   218  		return &value4Int{}, DefValue4IntSize
   219  	case types.ETReal:
   220  		switch tp.Tp {
   221  		case allegrosql.TypeFloat:
   222  			return &value4Float32{}, DefValue4Float32Size
   223  		case allegrosql.TypeDouble:
   224  			return &value4Float64{}, DefValue4Float64Size
   225  		}
   226  	case types.ETDecimal:
   227  		return &value4Decimal{}, DefValue4DecimalSize
   228  	case types.ETDatetime, types.ETTimestamp:
   229  		return &value4Time{}, DefValue4TimeSize
   230  	case types.ETDuration:
   231  		return &value4Duration{}, DefValue4DurationSize
   232  	case types.ETString:
   233  		return &value4String{}, DefValue4StringSize
   234  	case types.ETJson:
   235  		return &value4JSON{}, DefValue4JSONSize
   236  	}
   237  	return nil, 0
   238  }
   239  
   240  type firstValue struct {
   241  	baseAggFunc
   242  
   243  	tp *types.FieldType
   244  }
   245  
   246  type partialResult4FirstValue struct {
   247  	gotFirstValue bool
   248  	evaluator     valueEvaluator
   249  }
   250  
   251  func (v *firstValue) AllocPartialResult() (pr PartialResult, memDelta int64) {
   252  	ve, veMemDelta := buildValueEvaluator(v.tp)
   253  	p := &partialResult4FirstValue{evaluator: ve}
   254  	return PartialResult(p), DefPartialResult4FirstValueSize + veMemDelta
   255  }
   256  
   257  func (v *firstValue) ResetPartialResult(pr PartialResult) {
   258  	p := (*partialResult4FirstValue)(pr)
   259  	p.gotFirstValue = false
   260  }
   261  
   262  func (v *firstValue) UFIDelatePartialResult(sctx stochastikctx.Context, rowsInGroup []chunk.Event, pr PartialResult) (memDelta int64, err error) {
   263  	p := (*partialResult4FirstValue)(pr)
   264  	if p.gotFirstValue {
   265  		return 0, nil
   266  	}
   267  	if len(rowsInGroup) > 0 {
   268  		p.gotFirstValue = true
   269  		memDelta, err = p.evaluator.evaluateEvent(sctx, v.args[0], rowsInGroup[0])
   270  		if err != nil {
   271  			return 0, err
   272  		}
   273  	}
   274  	return memDelta, nil
   275  }
   276  
   277  func (v *firstValue) AppendFinalResult2Chunk(sctx stochastikctx.Context, pr PartialResult, chk *chunk.Chunk) error {
   278  	p := (*partialResult4FirstValue)(pr)
   279  	if !p.gotFirstValue {
   280  		chk.AppendNull(v.ordinal)
   281  	} else {
   282  		p.evaluator.appendResult(chk, v.ordinal)
   283  	}
   284  	return nil
   285  }
   286  
   287  type lastValue struct {
   288  	baseAggFunc
   289  
   290  	tp *types.FieldType
   291  }
   292  
   293  type partialResult4LastValue struct {
   294  	gotLastValue bool
   295  	evaluator    valueEvaluator
   296  }
   297  
   298  func (v *lastValue) AllocPartialResult() (pr PartialResult, memDelta int64) {
   299  	ve, veMemDelta := buildValueEvaluator(v.tp)
   300  	p := &partialResult4FirstValue{evaluator: ve}
   301  	return PartialResult(p), DefPartialResult4LastValueSize + veMemDelta
   302  }
   303  
   304  func (v *lastValue) ResetPartialResult(pr PartialResult) {
   305  	p := (*partialResult4LastValue)(pr)
   306  	p.gotLastValue = false
   307  }
   308  
   309  func (v *lastValue) UFIDelatePartialResult(sctx stochastikctx.Context, rowsInGroup []chunk.Event, pr PartialResult) (memDelta int64, err error) {
   310  	p := (*partialResult4LastValue)(pr)
   311  	if len(rowsInGroup) > 0 {
   312  		p.gotLastValue = true
   313  		memDelta, err = p.evaluator.evaluateEvent(sctx, v.args[0], rowsInGroup[len(rowsInGroup)-1])
   314  		if err != nil {
   315  			return 0, err
   316  		}
   317  	}
   318  	return memDelta, nil
   319  }
   320  
   321  func (v *lastValue) AppendFinalResult2Chunk(sctx stochastikctx.Context, pr PartialResult, chk *chunk.Chunk) error {
   322  	p := (*partialResult4LastValue)(pr)
   323  	if !p.gotLastValue {
   324  		chk.AppendNull(v.ordinal)
   325  	} else {
   326  		p.evaluator.appendResult(chk, v.ordinal)
   327  	}
   328  	return nil
   329  }
   330  
   331  type nthValue struct {
   332  	baseAggFunc
   333  
   334  	tp  *types.FieldType
   335  	nth uint64
   336  }
   337  
   338  type partialResult4NthValue struct {
   339  	seenEvents  uint64
   340  	evaluator valueEvaluator
   341  }
   342  
   343  func (v *nthValue) AllocPartialResult() (pr PartialResult, memDelta int64) {
   344  	ve, veMemDelta := buildValueEvaluator(v.tp)
   345  	p := &partialResult4FirstValue{evaluator: ve}
   346  	return PartialResult(p), DefPartialResult4NthValueSize + veMemDelta
   347  }
   348  
   349  func (v *nthValue) ResetPartialResult(pr PartialResult) {
   350  	p := (*partialResult4NthValue)(pr)
   351  	p.seenEvents = 0
   352  }
   353  
   354  func (v *nthValue) UFIDelatePartialResult(sctx stochastikctx.Context, rowsInGroup []chunk.Event, pr PartialResult) (memDelta int64, err error) {
   355  	if v.nth == 0 {
   356  		return 0, nil
   357  	}
   358  	p := (*partialResult4NthValue)(pr)
   359  	numEvents := uint64(len(rowsInGroup))
   360  	if v.nth > p.seenEvents && v.nth-p.seenEvents <= numEvents {
   361  		memDelta, err = p.evaluator.evaluateEvent(sctx, v.args[0], rowsInGroup[v.nth-p.seenEvents-1])
   362  		if err != nil {
   363  			return 0, err
   364  		}
   365  	}
   366  	p.seenEvents += numEvents
   367  	return memDelta, nil
   368  }
   369  
   370  func (v *nthValue) AppendFinalResult2Chunk(sctx stochastikctx.Context, pr PartialResult, chk *chunk.Chunk) error {
   371  	p := (*partialResult4NthValue)(pr)
   372  	if v.nth == 0 || p.seenEvents < v.nth {
   373  		chk.AppendNull(v.ordinal)
   374  	} else {
   375  		p.evaluator.appendResult(chk, v.ordinal)
   376  	}
   377  	return nil
   378  }