1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/hanchuanchuan-goInception

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Это зеркальный репозиторий, синхронизируется ежедневно с исходного репозитория.
Клонировать/Скачать
builtin_control.go 24 КБ
Копировать Редактировать Исходные данные Просмотреть построчно История
hanchuanchuan Отправлено 6 лет назад 27f3c5a
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
package expression
import (
"github.com/cznic/mathutil"
"github.com/hanchuanchuan/goInception/mysql"
"github.com/hanchuanchuan/goInception/sessionctx"
"github.com/hanchuanchuan/goInception/types"
"github.com/hanchuanchuan/goInception/types/json"
"github.com/hanchuanchuan/goInception/util/charset"
"github.com/hanchuanchuan/goInception/util/chunk"
"github.com/pingcap/errors"
"github.com/pingcap/tipb/go-tipb"
)
var (
_ functionClass = &caseWhenFunctionClass{}
_ functionClass = &ifFunctionClass{}
_ functionClass = &ifNullFunctionClass{}
)
var (
_ builtinFunc = &builtinCaseWhenIntSig{}
_ builtinFunc = &builtinCaseWhenRealSig{}
_ builtinFunc = &builtinCaseWhenDecimalSig{}
_ builtinFunc = &builtinCaseWhenStringSig{}
_ builtinFunc = &builtinCaseWhenTimeSig{}
_ builtinFunc = &builtinCaseWhenDurationSig{}
_ builtinFunc = &builtinIfNullIntSig{}
_ builtinFunc = &builtinIfNullRealSig{}
_ builtinFunc = &builtinIfNullDecimalSig{}
_ builtinFunc = &builtinIfNullStringSig{}
_ builtinFunc = &builtinIfNullTimeSig{}
_ builtinFunc = &builtinIfNullDurationSig{}
_ builtinFunc = &builtinIfNullJSONSig{}
_ builtinFunc = &builtinIfIntSig{}
_ builtinFunc = &builtinIfRealSig{}
_ builtinFunc = &builtinIfDecimalSig{}
_ builtinFunc = &builtinIfStringSig{}
_ builtinFunc = &builtinIfTimeSig{}
_ builtinFunc = &builtinIfDurationSig{}
_ builtinFunc = &builtinIfJSONSig{}
)
// inferType4ControlFuncs infer result type for builtin IF, IFNULL && NULLIF.
func inferType4ControlFuncs(lhs, rhs *types.FieldType) *types.FieldType {
resultFieldType := &types.FieldType{}
if lhs.Tp == mysql.TypeNull {
*resultFieldType = *rhs
// If both arguments are NULL, make resulting type BINARY(0).
if rhs.Tp == mysql.TypeNull {
resultFieldType.Tp = mysql.TypeString
resultFieldType.Flen, resultFieldType.Decimal = 0, 0
types.SetBinChsClnFlag(resultFieldType)
}
} else if rhs.Tp == mysql.TypeNull {
*resultFieldType = *lhs
} else {
var unsignedFlag uint
evalType := types.AggregateEvalType([]*types.FieldType{lhs, rhs}, &unsignedFlag)
resultFieldType = types.AggFieldType([]*types.FieldType{lhs, rhs})
if evalType == types.ETInt {
resultFieldType.Decimal = 0
} else {
if lhs.Decimal == types.UnspecifiedLength || rhs.Decimal == types.UnspecifiedLength {
resultFieldType.Decimal = types.UnspecifiedLength
} else {
resultFieldType.Decimal = mathutil.Max(lhs.Decimal, rhs.Decimal)
}
}
if types.IsNonBinaryStr(lhs) && !types.IsBinaryStr(rhs) {
resultFieldType.Charset, resultFieldType.Collate, resultFieldType.Flag = charset.CharsetUTF8, charset.CollationUTF8, 0
if mysql.HasBinaryFlag(lhs.Flag) || !types.IsNonBinaryStr(rhs) {
resultFieldType.Flag |= mysql.BinaryFlag
}
} else if types.IsNonBinaryStr(rhs) && !types.IsBinaryStr(lhs) {
resultFieldType.Charset, resultFieldType.Collate, resultFieldType.Flag = charset.CharsetUTF8, charset.CollationUTF8, 0
if mysql.HasBinaryFlag(rhs.Flag) || !types.IsNonBinaryStr(lhs) {
resultFieldType.Flag |= mysql.BinaryFlag
}
} else if types.IsBinaryStr(lhs) || types.IsBinaryStr(rhs) || !evalType.IsStringKind() {
types.SetBinChsClnFlag(resultFieldType)
} else {
resultFieldType.Charset, resultFieldType.Collate, resultFieldType.Flag = charset.CharsetUTF8, charset.CollationUTF8, 0
}
if evalType == types.ETDecimal || evalType == types.ETInt {
lhsUnsignedFlag, rhsUnsignedFlag := mysql.HasUnsignedFlag(lhs.Flag), mysql.HasUnsignedFlag(rhs.Flag)
lhsFlagLen, rhsFlagLen := 0, 0
if !lhsUnsignedFlag {
lhsFlagLen = 1
}
if !rhsUnsignedFlag {
rhsFlagLen = 1
}
lhsFlen := lhs.Flen - lhsFlagLen
rhsFlen := rhs.Flen - rhsFlagLen
if lhs.Decimal != types.UnspecifiedLength {
lhsFlen -= lhs.Decimal
}
if lhs.Decimal != types.UnspecifiedLength {
rhsFlen -= rhs.Decimal
}
resultFieldType.Flen = mathutil.Max(lhsFlen, rhsFlen) + resultFieldType.Decimal + 1
} else {
resultFieldType.Flen = mathutil.Max(lhs.Flen, rhs.Flen)
}
}
// Fix decimal for int and string.
resultEvalType := resultFieldType.EvalType()
if resultEvalType == types.ETInt {
resultFieldType.Decimal = 0
} else if resultEvalType == types.ETString {
if lhs.Tp != mysql.TypeNull || rhs.Tp != mysql.TypeNull {
resultFieldType.Decimal = types.UnspecifiedLength
}
}
return resultFieldType
}
type caseWhenFunctionClass struct {
baseFunctionClass
}
func (c *caseWhenFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (sig builtinFunc, err error) {
if err = c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
l := len(args)
// Fill in each 'THEN' clause parameter type.
fieldTps := make([]*types.FieldType, 0, (l+1)/2)
decimal, flen, isBinaryStr, isBinaryFlag := args[1].GetType().Decimal, 0, false, false
for i := 1; i < l; i += 2 {
fieldTps = append(fieldTps, args[i].GetType())
decimal = mathutil.Max(decimal, args[i].GetType().Decimal)
flen = mathutil.Max(flen, args[i].GetType().Flen)
isBinaryStr = isBinaryStr || types.IsBinaryStr(args[i].GetType())
isBinaryFlag = isBinaryFlag || !types.IsNonBinaryStr(args[i].GetType())
}
if l%2 == 1 {
fieldTps = append(fieldTps, args[l-1].GetType())
decimal = mathutil.Max(decimal, args[l-1].GetType().Decimal)
flen = mathutil.Max(flen, args[l-1].GetType().Flen)
isBinaryStr = isBinaryStr || types.IsBinaryStr(args[l-1].GetType())
isBinaryFlag = isBinaryFlag || !types.IsNonBinaryStr(args[l-1].GetType())
}
fieldTp := types.AggFieldType(fieldTps)
tp := fieldTp.EvalType()
if tp == types.ETInt {
decimal = 0
}
fieldTp.Decimal, fieldTp.Flen = decimal, flen
if fieldTp.EvalType().IsStringKind() && !isBinaryStr {
fieldTp.Charset, fieldTp.Collate = mysql.DefaultCharset, mysql.DefaultCollationName
}
if isBinaryFlag {
fieldTp.Flag |= mysql.BinaryFlag
}
// Set retType to BINARY(0) if all arguments are of type NULL.
if fieldTp.Tp == mysql.TypeNull {
fieldTp.Flen, fieldTp.Decimal = 0, -1
types.SetBinChsClnFlag(fieldTp)
}
argTps := make([]types.EvalType, 0, l)
for i := 0; i < l-1; i += 2 {
argTps = append(argTps, types.ETInt, tp)
}
if l%2 == 1 {
argTps = append(argTps, tp)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, tp, argTps...)
bf.tp = fieldTp
switch tp {
case types.ETInt:
bf.tp.Decimal = 0
sig = &builtinCaseWhenIntSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_CaseWhenInt)
case types.ETReal:
sig = &builtinCaseWhenRealSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_CaseWhenReal)
case types.ETDecimal:
sig = &builtinCaseWhenDecimalSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_CaseWhenDecimal)
case types.ETString:
bf.tp.Decimal = types.UnspecifiedLength
sig = &builtinCaseWhenStringSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_CaseWhenString)
case types.ETDatetime, types.ETTimestamp:
sig = &builtinCaseWhenTimeSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_CaseWhenTime)
case types.ETDuration:
sig = &builtinCaseWhenDurationSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_CaseWhenDuration)
}
return sig, nil
}
type builtinCaseWhenIntSig struct {
baseBuiltinFunc
}
func (b *builtinCaseWhenIntSig) Clone() builtinFunc {
newSig := &builtinCaseWhenIntSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalInt evals a builtinCaseWhenIntSig.
// See https://dev.mysql.com/doc/refman/5.7/en/case.html
func (b *builtinCaseWhenIntSig) evalInt(row chunk.Row) (ret int64, isNull bool, err error) {
var condition int64
args, l := b.getArgs(), len(b.getArgs())
for i := 0; i < l-1; i += 2 {
condition, isNull, err = args[i].EvalInt(b.ctx, row)
if err != nil {
return 0, isNull, errors.Trace(err)
}
if isNull || condition == 0 {
continue
}
ret, isNull, err = args[i+1].EvalInt(b.ctx, row)
return ret, isNull, errors.Trace(err)
}
// when clause(condition, result) -> args[i], args[i+1]; (i >= 0 && i+1 < l-1)
// else clause -> args[l-1]
// If case clause has else clause, l%2 == 1.
if l%2 == 1 {
ret, isNull, err = args[l-1].EvalInt(b.ctx, row)
return ret, isNull, errors.Trace(err)
}
return ret, true, nil
}
type builtinCaseWhenRealSig struct {
baseBuiltinFunc
}
func (b *builtinCaseWhenRealSig) Clone() builtinFunc {
newSig := &builtinCaseWhenRealSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals a builtinCaseWhenRealSig.
// See https://dev.mysql.com/doc/refman/5.7/en/case.html
func (b *builtinCaseWhenRealSig) evalReal(row chunk.Row) (ret float64, isNull bool, err error) {
var condition int64
args, l := b.getArgs(), len(b.getArgs())
for i := 0; i < l-1; i += 2 {
condition, isNull, err = args[i].EvalInt(b.ctx, row)
if err != nil {
return 0, isNull, errors.Trace(err)
}
if isNull || condition == 0 {
continue
}
ret, isNull, err = args[i+1].EvalReal(b.ctx, row)
return ret, isNull, errors.Trace(err)
}
// when clause(condition, result) -> args[i], args[i+1]; (i >= 0 && i+1 < l-1)
// else clause -> args[l-1]
// If case clause has else clause, l%2 == 1.
if l%2 == 1 {
ret, isNull, err = args[l-1].EvalReal(b.ctx, row)
return ret, isNull, errors.Trace(err)
}
return ret, true, nil
}
type builtinCaseWhenDecimalSig struct {
baseBuiltinFunc
}
func (b *builtinCaseWhenDecimalSig) Clone() builtinFunc {
newSig := &builtinCaseWhenDecimalSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalDecimal evals a builtinCaseWhenDecimalSig.
// See https://dev.mysql.com/doc/refman/5.7/en/case.html
func (b *builtinCaseWhenDecimalSig) evalDecimal(row chunk.Row) (ret *types.MyDecimal, isNull bool, err error) {
var condition int64
args, l := b.getArgs(), len(b.getArgs())
for i := 0; i < l-1; i += 2 {
condition, isNull, err = args[i].EvalInt(b.ctx, row)
if err != nil {
return nil, isNull, errors.Trace(err)
}
if isNull || condition == 0 {
continue
}
ret, isNull, err = args[i+1].EvalDecimal(b.ctx, row)
return ret, isNull, errors.Trace(err)
}
// when clause(condition, result) -> args[i], args[i+1]; (i >= 0 && i+1 < l-1)
// else clause -> args[l-1]
// If case clause has else clause, l%2 == 1.
if l%2 == 1 {
ret, isNull, err = args[l-1].EvalDecimal(b.ctx, row)
return ret, isNull, errors.Trace(err)
}
return ret, true, nil
}
type builtinCaseWhenStringSig struct {
baseBuiltinFunc
}
func (b *builtinCaseWhenStringSig) Clone() builtinFunc {
newSig := &builtinCaseWhenStringSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalString evals a builtinCaseWhenStringSig.
// See https://dev.mysql.com/doc/refman/5.7/en/case.html
func (b *builtinCaseWhenStringSig) evalString(row chunk.Row) (ret string, isNull bool, err error) {
var condition int64
args, l := b.getArgs(), len(b.getArgs())
for i := 0; i < l-1; i += 2 {
condition, isNull, err = args[i].EvalInt(b.ctx, row)
if err != nil {
return "", isNull, errors.Trace(err)
}
if isNull || condition == 0 {
continue
}
ret, isNull, err = args[i+1].EvalString(b.ctx, row)
return ret, isNull, errors.Trace(err)
}
// when clause(condition, result) -> args[i], args[i+1]; (i >= 0 && i+1 < l-1)
// else clause -> args[l-1]
// If case clause has else clause, l%2 == 1.
if l%2 == 1 {
ret, isNull, err = args[l-1].EvalString(b.ctx, row)
return ret, isNull, errors.Trace(err)
}
return ret, true, nil
}
type builtinCaseWhenTimeSig struct {
baseBuiltinFunc
}
func (b *builtinCaseWhenTimeSig) Clone() builtinFunc {
newSig := &builtinCaseWhenTimeSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalTime evals a builtinCaseWhenTimeSig.
// See https://dev.mysql.com/doc/refman/5.7/en/case.html
func (b *builtinCaseWhenTimeSig) evalTime(row chunk.Row) (ret types.Time, isNull bool, err error) {
var condition int64
args, l := b.getArgs(), len(b.getArgs())
for i := 0; i < l-1; i += 2 {
condition, isNull, err = args[i].EvalInt(b.ctx, row)
if err != nil {
return ret, isNull, errors.Trace(err)
}
if isNull || condition == 0 {
continue
}
ret, isNull, err = args[i+1].EvalTime(b.ctx, row)
return ret, isNull, errors.Trace(err)
}
// when clause(condition, result) -> args[i], args[i+1]; (i >= 0 && i+1 < l-1)
// else clause -> args[l-1]
// If case clause has else clause, l%2 == 1.
if l%2 == 1 {
ret, isNull, err = args[l-1].EvalTime(b.ctx, row)
return ret, isNull, errors.Trace(err)
}
return ret, true, nil
}
type builtinCaseWhenDurationSig struct {
baseBuiltinFunc
}
func (b *builtinCaseWhenDurationSig) Clone() builtinFunc {
newSig := &builtinCaseWhenDurationSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalDuration evals a builtinCaseWhenDurationSig.
// See https://dev.mysql.com/doc/refman/5.7/en/case.html
func (b *builtinCaseWhenDurationSig) evalDuration(row chunk.Row) (ret types.Duration, isNull bool, err error) {
var condition int64
args, l := b.getArgs(), len(b.getArgs())
for i := 0; i < l-1; i += 2 {
condition, isNull, err = args[i].EvalInt(b.ctx, row)
if err != nil {
return ret, true, errors.Trace(err)
}
if isNull || condition == 0 {
continue
}
ret, isNull, err = args[i+1].EvalDuration(b.ctx, row)
return ret, isNull, errors.Trace(err)
}
// when clause(condition, result) -> args[i], args[i+1]; (i >= 0 && i+1 < l-1)
// else clause -> args[l-1]
// If case clause has else clause, l%2 == 1.
if l%2 == 1 {
ret, isNull, err = args[l-1].EvalDuration(b.ctx, row)
return ret, isNull, errors.Trace(err)
}
return ret, true, nil
}
type ifFunctionClass struct {
baseFunctionClass
}
// getFunction see https://dev.mysql.com/doc/refman/5.7/en/control-flow-functions.html#function_if
func (c *ifFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (sig builtinFunc, err error) {
if err = c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
retTp := inferType4ControlFuncs(args[1].GetType(), args[2].GetType())
evalTps := retTp.EvalType()
bf := newBaseBuiltinFuncWithTp(ctx, args, evalTps, types.ETInt, evalTps, evalTps)
retTp.Flag |= bf.tp.Flag
bf.tp = retTp
switch evalTps {
case types.ETInt:
sig = &builtinIfIntSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_IfInt)
case types.ETReal:
sig = &builtinIfRealSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_IfReal)
case types.ETDecimal:
sig = &builtinIfDecimalSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_IfDecimal)
case types.ETString:
sig = &builtinIfStringSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_IfString)
case types.ETDatetime, types.ETTimestamp:
sig = &builtinIfTimeSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_IfTime)
case types.ETDuration:
sig = &builtinIfDurationSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_IfDuration)
case types.ETJson:
sig = &builtinIfJSONSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_IfJson)
}
return sig, nil
}
type builtinIfIntSig struct {
baseBuiltinFunc
}
func (b *builtinIfIntSig) Clone() builtinFunc {
newSig := &builtinIfIntSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (b *builtinIfIntSig) evalInt(row chunk.Row) (ret int64, isNull bool, err error) {
arg0, isNull0, err := b.args[0].EvalInt(b.ctx, row)
if err != nil {
return 0, true, errors.Trace(err)
}
arg1, isNull1, err := b.args[1].EvalInt(b.ctx, row)
if (!isNull0 && arg0 != 0) || err != nil {
return arg1, isNull1, errors.Trace(err)
}
arg2, isNull2, err := b.args[2].EvalInt(b.ctx, row)
return arg2, isNull2, errors.Trace(err)
}
type builtinIfRealSig struct {
baseBuiltinFunc
}
func (b *builtinIfRealSig) Clone() builtinFunc {
newSig := &builtinIfRealSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (b *builtinIfRealSig) evalReal(row chunk.Row) (ret float64, isNull bool, err error) {
arg0, isNull0, err := b.args[0].EvalInt(b.ctx, row)
if err != nil {
return 0, true, errors.Trace(err)
}
arg1, isNull1, err := b.args[1].EvalReal(b.ctx, row)
if (!isNull0 && arg0 != 0) || err != nil {
return arg1, isNull1, errors.Trace(err)
}
arg2, isNull2, err := b.args[2].EvalReal(b.ctx, row)
return arg2, isNull2, errors.Trace(err)
}
type builtinIfDecimalSig struct {
baseBuiltinFunc
}
func (b *builtinIfDecimalSig) Clone() builtinFunc {
newSig := &builtinIfDecimalSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (b *builtinIfDecimalSig) evalDecimal(row chunk.Row) (ret *types.MyDecimal, isNull bool, err error) {
arg0, isNull0, err := b.args[0].EvalInt(b.ctx, row)
if err != nil {
return nil, true, errors.Trace(err)
}
arg1, isNull1, err := b.args[1].EvalDecimal(b.ctx, row)
if (!isNull0 && arg0 != 0) || err != nil {
return arg1, isNull1, errors.Trace(err)
}
arg2, isNull2, err := b.args[2].EvalDecimal(b.ctx, row)
return arg2, isNull2, errors.Trace(err)
}
type builtinIfStringSig struct {
baseBuiltinFunc
}
func (b *builtinIfStringSig) Clone() builtinFunc {
newSig := &builtinIfStringSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (b *builtinIfStringSig) evalString(row chunk.Row) (ret string, isNull bool, err error) {
arg0, isNull0, err := b.args[0].EvalInt(b.ctx, row)
if err != nil {
return "", true, errors.Trace(err)
}
arg1, isNull1, err := b.args[1].EvalString(b.ctx, row)
if (!isNull0 && arg0 != 0) || err != nil {
return arg1, isNull1, errors.Trace(err)
}
arg2, isNull2, err := b.args[2].EvalString(b.ctx, row)
return arg2, isNull2, errors.Trace(err)
}
type builtinIfTimeSig struct {
baseBuiltinFunc
}
func (b *builtinIfTimeSig) Clone() builtinFunc {
newSig := &builtinIfTimeSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (b *builtinIfTimeSig) evalTime(row chunk.Row) (ret types.Time, isNull bool, err error) {
arg0, isNull0, err := b.args[0].EvalInt(b.ctx, row)
if err != nil {
return ret, true, errors.Trace(err)
}
arg1, isNull1, err := b.args[1].EvalTime(b.ctx, row)
if (!isNull0 && arg0 != 0) || err != nil {
return arg1, isNull1, errors.Trace(err)
}
arg2, isNull2, err := b.args[2].EvalTime(b.ctx, row)
return arg2, isNull2, errors.Trace(err)
}
type builtinIfDurationSig struct {
baseBuiltinFunc
}
func (b *builtinIfDurationSig) Clone() builtinFunc {
newSig := &builtinIfDurationSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (b *builtinIfDurationSig) evalDuration(row chunk.Row) (ret types.Duration, isNull bool, err error) {
arg0, isNull0, err := b.args[0].EvalInt(b.ctx, row)
if err != nil {
return ret, true, errors.Trace(err)
}
arg1, isNull1, err := b.args[1].EvalDuration(b.ctx, row)
if (!isNull0 && arg0 != 0) || err != nil {
return arg1, isNull1, errors.Trace(err)
}
arg2, isNull2, err := b.args[2].EvalDuration(b.ctx, row)
return arg2, isNull2, errors.Trace(err)
}
type builtinIfJSONSig struct {
baseBuiltinFunc
}
func (b *builtinIfJSONSig) Clone() builtinFunc {
newSig := &builtinIfJSONSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (b *builtinIfJSONSig) evalJSON(row chunk.Row) (ret json.BinaryJSON, isNull bool, err error) {
arg0, isNull0, err := b.args[0].EvalInt(b.ctx, row)
if err != nil {
return ret, true, errors.Trace(err)
}
arg1, isNull1, err := b.args[1].EvalJSON(b.ctx, row)
if err != nil {
return ret, true, errors.Trace(err)
}
arg2, isNull2, err := b.args[2].EvalJSON(b.ctx, row)
if err != nil {
return ret, true, errors.Trace(err)
}
switch {
case isNull0 || arg0 == 0:
ret, isNull = arg2, isNull2
case arg0 != 0:
ret, isNull = arg1, isNull1
}
return
}
type ifNullFunctionClass struct {
baseFunctionClass
}
func (c *ifNullFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (sig builtinFunc, err error) {
if err = errors.Trace(c.verifyArgs(args)); err != nil {
return nil, errors.Trace(err)
}
lhs, rhs := args[0].GetType(), args[1].GetType()
retTp := inferType4ControlFuncs(lhs, rhs)
retTp.Flag |= (lhs.Flag & mysql.NotNullFlag) | (rhs.Flag & mysql.NotNullFlag)
if lhs.Tp == mysql.TypeNull && rhs.Tp == mysql.TypeNull {
retTp.Tp = mysql.TypeNull
retTp.Flen, retTp.Decimal = 0, -1
types.SetBinChsClnFlag(retTp)
}
evalTps := retTp.EvalType()
bf := newBaseBuiltinFuncWithTp(ctx, args, evalTps, evalTps, evalTps)
bf.tp = retTp
switch evalTps {
case types.ETInt:
sig = &builtinIfNullIntSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_IfNullInt)
case types.ETReal:
sig = &builtinIfNullRealSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_IfNullReal)
case types.ETDecimal:
sig = &builtinIfNullDecimalSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_IfNullDecimal)
case types.ETString:
sig = &builtinIfNullStringSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_IfNullString)
case types.ETDatetime, types.ETTimestamp:
sig = &builtinIfNullTimeSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_IfNullTime)
case types.ETDuration:
sig = &builtinIfNullDurationSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_IfNullDuration)
case types.ETJson:
sig = &builtinIfNullJSONSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_IfNullJson)
}
return sig, nil
}
type builtinIfNullIntSig struct {
baseBuiltinFunc
}
func (b *builtinIfNullIntSig) Clone() builtinFunc {
newSig := &builtinIfNullIntSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (b *builtinIfNullIntSig) evalInt(row chunk.Row) (int64, bool, error) {
arg0, isNull, err := b.args[0].EvalInt(b.ctx, row)
if !isNull || err != nil {
return arg0, err != nil, errors.Trace(err)
}
arg1, isNull, err := b.args[1].EvalInt(b.ctx, row)
return arg1, isNull || err != nil, errors.Trace(err)
}
type builtinIfNullRealSig struct {
baseBuiltinFunc
}
func (b *builtinIfNullRealSig) Clone() builtinFunc {
newSig := &builtinIfNullRealSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (b *builtinIfNullRealSig) evalReal(row chunk.Row) (float64, bool, error) {
arg0, isNull, err := b.args[0].EvalReal(b.ctx, row)
if !isNull || err != nil {
return arg0, err != nil, errors.Trace(err)
}
arg1, isNull, err := b.args[1].EvalReal(b.ctx, row)
return arg1, isNull || err != nil, errors.Trace(err)
}
type builtinIfNullDecimalSig struct {
baseBuiltinFunc
}
func (b *builtinIfNullDecimalSig) Clone() builtinFunc {
newSig := &builtinIfNullDecimalSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (b *builtinIfNullDecimalSig) evalDecimal(row chunk.Row) (*types.MyDecimal, bool, error) {
arg0, isNull, err := b.args[0].EvalDecimal(b.ctx, row)
if !isNull || err != nil {
return arg0, err != nil, errors.Trace(err)
}
arg1, isNull, err := b.args[1].EvalDecimal(b.ctx, row)
return arg1, isNull || err != nil, errors.Trace(err)
}
type builtinIfNullStringSig struct {
baseBuiltinFunc
}
func (b *builtinIfNullStringSig) Clone() builtinFunc {
newSig := &builtinIfNullStringSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (b *builtinIfNullStringSig) evalString(row chunk.Row) (string, bool, error) {
arg0, isNull, err := b.args[0].EvalString(b.ctx, row)
if !isNull || err != nil {
return arg0, err != nil, errors.Trace(err)
}
arg1, isNull, err := b.args[1].EvalString(b.ctx, row)
return arg1, isNull || err != nil, errors.Trace(err)
}
type builtinIfNullTimeSig struct {
baseBuiltinFunc
}
func (b *builtinIfNullTimeSig) Clone() builtinFunc {
newSig := &builtinIfNullTimeSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (b *builtinIfNullTimeSig) evalTime(row chunk.Row) (types.Time, bool, error) {
arg0, isNull, err := b.args[0].EvalTime(b.ctx, row)
if !isNull || err != nil {
return arg0, err != nil, errors.Trace(err)
}
arg1, isNull, err := b.args[1].EvalTime(b.ctx, row)
return arg1, isNull || err != nil, errors.Trace(err)
}
type builtinIfNullDurationSig struct {
baseBuiltinFunc
}
func (b *builtinIfNullDurationSig) Clone() builtinFunc {
newSig := &builtinIfNullDurationSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (b *builtinIfNullDurationSig) evalDuration(row chunk.Row) (types.Duration, bool, error) {
arg0, isNull, err := b.args[0].EvalDuration(b.ctx, row)
if !isNull || err != nil {
return arg0, err != nil, errors.Trace(err)
}
arg1, isNull, err := b.args[1].EvalDuration(b.ctx, row)
return arg1, isNull || err != nil, errors.Trace(err)
}
type builtinIfNullJSONSig struct {
baseBuiltinFunc
}
func (b *builtinIfNullJSONSig) Clone() builtinFunc {
newSig := &builtinIfNullJSONSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
func (b *builtinIfNullJSONSig) evalJSON(row chunk.Row) (json.BinaryJSON, bool, error) {
arg0, isNull, err := b.args[0].EvalJSON(b.ctx, row)
if !isNull {
return arg0, err != nil, errors.Trace(err)
}
arg1, isNull, err := b.args[1].EvalJSON(b.ctx, row)
return arg1, isNull || err != nil, errors.Trace(err)
}

Комментарий ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://gitlife.ru/oschina-mirror/hanchuanchuan-goInception.git
git@gitlife.ru:oschina-mirror/hanchuanchuan-goInception.git
oschina-mirror
hanchuanchuan-goInception
hanchuanchuan-goInception
v1.2.4