// evalInt evals a UNIX_TIMESTAMP().
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_unix-timestamp
354391
func (b *builtinUnixTimestampCurrentSig) evalInt(row chunk.Row) (int64, bool, error) {
	var nowTs = &b.ctx.GetSessionVars().StmtCtx.NowTs
	if nowTs.Equal(time.Time{}) {
		*nowTs = time.Now()
	}
	dec, err := goTimeToMysqlUnixTimestamp(*nowTs, 1)
	if err != nil {
		return 0, true, err
	}
	intVal, err := dec.ToInt()
	terror.Log(err)
	return intVal, false, nil
}
946406
func (b *builtinUTCDateSig) evalTime(row chunk.Row) (types.Time, bool, error) {
	var nowTs = &b.ctx.GetSessionVars().StmtCtx.NowTs
	if nowTs.Equal(time.Time{}) {
		*nowTs = time.Now()
	}
	year, month, day := nowTs.UTC().Date()
	result := types.Time{
		Time: types.FromGoTime(time.Date(year, month, day, 0, 0, 0, 0, time.UTC)),
		Type: mysql.TypeDate,
		Fsp:  types.UnspecifiedFsp}
	return result, false, nil
}
1151692
func (b *builtinUTCTimestampWithoutArgSig) evalTime(row chunk.Row) (types.Time, bool, error) {
	result, isNull, err := evalUTCTimestampWithFsp(b.ctx, 0)
	return result, isNull, err
}
460570
func (b *builtinAbsUIntSig) evalInt(row chunk.Row) (int64, bool, error) {
	return b.args[0].EvalInt(b.ctx, row)
}
600408
func (b *builtinTimeFormatSig) evalString(row chunk.Row) (string, bool, error) {
	dur, isNull, err := b.args[0].EvalDuration(b.ctx, row)
	// if err != nil, then dur is ZeroDuration, outputs 00:00:00 in this case which follows the behavior of mysql.
	if err != nil {
		logutil.Logger(context.Background()).Warn("time_format.args[0].EvalDuration failed", zap.Error(err))
	}
	if isNull {
		return "", isNull, err
	}
	formatMask, isNull, err := b.args[1].EvalString(b.ctx, row)
	if err != nil || isNull {
		return "", isNull, err
	}
	res, err := b.formatTime(b.ctx, dur, formatMask)
	return res, isNull, err
}
465386
func (r Rule) Eval(ctx context.Context, e *scheduler.Event, err error, ch Chain) (context.Context, *scheduler.Event, error) {
	if r != nil {
		return r(ctx, e, err, ch)
	}
	return ch(ctx, e, err)
}
466156
func (b *builtinDateSig) evalTime(row chunk.Row) (types.Time, bool, error) {
	expr, isNull, err := b.args[0].EvalTime(b.ctx, row)
	if isNull || err != nil {
		return types.Time{}, true, handleInvalidTimeError(b.ctx, err)
	}

	if expr.IsZero() {
		return types.Time{}, true, handleInvalidTimeError(b.ctx, types.ErrIncorrectDatetimeValue.GenWithStackByArgs(expr.String()))
	}

	expr.Time = types.FromDate(expr.Time.Year(), expr.Time.Month(), expr.Time.Day(), 0, 0, 0, 0)
	expr.Type = mysql.TypeDate
	return expr, false, nil
}
467442
func (b *builtinLocate2ArgsSig) evalInt(row chunk.Row) (int64, bool, error) {
	subStr, isNull, err := b.args[0].EvalString(b.ctx, row)
	if isNull || err != nil {
		return 0, isNull, err
	}
	str, isNull, err := b.args[1].EvalString(b.ctx, row)
	if isNull || err != nil {
		return 0, isNull, err
	}
	if int64(len([]rune(subStr))) == 0 {
		return 1, false, nil
	}
	slice := string([]rune(strings.ToLower(str)))
	ret, idx := 0, strings.Index(slice, strings.ToLower(subStr))
	if idx != -1 {
		ret = utf8.RuneCountInString(slice[:idx]) + 1
	}
	return int64(ret), false, nil
}
1132257
func (b *builtinFromDaysSig) evalTime(row chunk.Row) (types.Time, bool, error) {
	n, isNull, err := b.args[0].EvalInt(b.ctx, row)
	if isNull || err != nil {
		return types.Time{}, true, err
	}

	return types.TimeFromDays(n), false, nil
}
758492
func (b *builtinConvertTzSig) evalTime(row chunk.Row) (types.Time, bool, error) {
	dt, isNull, err := b.args[0].EvalTime(b.ctx, row)
	if isNull || err != nil {
		return types.Time{}, true, err
	}

	fromTzStr, isNull, err := b.args[1].EvalString(b.ctx, row)
	if isNull || err != nil {
		return types.Time{}, true, err
	}

	toTzStr, isNull, err := b.args[2].EvalString(b.ctx, row)
	if isNull || err != nil {
		return types.Time{}, true, err
	}

	fromTzMatched := b.timezoneRegex.MatchString(fromTzStr)
	toTzMatched := b.timezoneRegex.MatchString(toTzStr)

	if !fromTzMatched && !toTzMatched {
		fromTz, err := time.LoadLocation(fromTzStr)
		if err != nil {
			return types.Time{}, true, err
		}

		toTz, err := time.LoadLocation(toTzStr)
		if err != nil {
			return types.Time{}, true, err
		}

		t, err := dt.Time.GoTime(fromTz)
		if err != nil {
			return types.Time{}, true, err
		}

		return types.Time{
			Time: types.FromGoTime(t.In(toTz)),
			Type: mysql.TypeDatetime,
			Fsp:  b.tp.Decimal,
		}, false, nil
	}
	if fromTzMatched && toTzMatched {
		t, err := dt.Time.GoTime(time.Local)
		if err != nil {
			return types.Time{}, true, err
		}

		return types.Time{
			Time: types.FromGoTime(t.Add(timeZone2Duration(toTzStr) - timeZone2Duration(fromTzStr))),
			Type: mysql.TypeDatetime,
			Fsp:  b.tp.Decimal,
		}, false, nil
	}
	return types.Time{}, true, nil
}
1319191
func (b *builtinLockSig) evalInt(_ chunk.Row) (int64, bool, error) {
	return 1, false, nil
}
1260867
func (b *builtinCeilDecToIntSig) evalInt(row chunk.Row) (int64, bool, error) {
	val, isNull, err := b.args[0].EvalDecimal(b.ctx, row)
	if isNull || err != nil {
		return 0, isNull, err
	}
	// err here will only be ErrOverFlow(will never happen) or ErrTruncate(can be ignored).
	res, err := val.ToInt()
	if err == types.ErrTruncated {
		err = nil
		if !val.IsNegative() {
			res = res + 1
		}
	}
	return res, false, err
}
139992
func (b *builtinLocateBinary3ArgsSig) evalInt(row chunk.Row) (int64, bool, error) {
	subStr, isNull, err := b.args[0].EvalString(b.ctx, row)
	if isNull || err != nil {
		return 0, isNull, err
	}
	str, isNull, err := b.args[1].EvalString(b.ctx, row)
	if isNull || err != nil {
		return 0, isNull, err
	}
	pos, isNull, err := b.args[2].EvalInt(b.ctx, row)
	// Transfer the argument which starts from 1 to real index which starts from 0.
	pos--
	if isNull || err != nil {
		return 0, isNull, err
	}
	subStrLen := len(subStr)
	if pos < 0 || pos > int64(len(str)-subStrLen) {
		return 0, false, nil
	} else if subStrLen == 0 {
		return pos + 1, false, nil
	}
	slice := str[pos:]
	idx := strings.Index(slice, subStr)
	if idx != -1 {
		return pos + int64(idx) + 1, false, nil
	}
	return 0, false, nil
}
147390
func (c *Constant) EvalJSON(ctx sessionctx.Context, _ chunk.Row) (json.BinaryJSON, bool, error) {
	if c.DeferredExpr != nil {
		dt, err := c.DeferredExpr.Eval(chunk.Row{})
		if err != nil {
			return json.BinaryJSON{}, true, err
		}
		if dt.IsNull() {
			return json.BinaryJSON{}, true, nil
		}
		val, err := dt.ConvertTo(ctx.GetSessionVars().StmtCtx, types.NewFieldType(mysql.TypeJSON))
		if err != nil {
			return json.BinaryJSON{}, true, err
		}
		fmt.Println("const eval json", val.GetMysqlJSON().String())
		c.Value.SetMysqlJSON(val.GetMysqlJSON())
		c.GetType().Tp = mysql.TypeJSON
	} else {
		if c.GetType().Tp == mysql.TypeNull || c.Value.IsNull() {
			return json.BinaryJSON{}, true, nil
		}
	}
	return c.Value.GetMysqlJSON(), false, nil
}
1269177
func (b *builtinDayOfMonthSig) evalInt(row chunk.Row) (int64, bool, error) {
	arg, isNull, err := b.args[0].EvalTime(b.ctx, row)
	if isNull || err != nil {
		return 0, true, handleInvalidTimeError(b.ctx, err)
	}
	if arg.IsZero() {
		if b.ctx.GetSessionVars().SQLMode.HasNoZeroDateMode() {
			return 0, true, handleInvalidTimeError(b.ctx, types.ErrIncorrectDatetimeValue.GenWithStackByArgs(arg.String()))
		}
		return 0, false, nil
	}
	return int64(arg.Time.Day()), false, nil
}
237853
func (col *Column) EvalTime(ctx sessionctx.Context, row chunk.Row) (types.Time, bool, error) {
	if row.IsNull(col.Index) {
		return types.Time{}, true, nil
	}
	return row.GetTime(col.Index), false, nil
}
644806
func (b *builtinAddTimeDateTimeNullSig) evalTime(row chunk.Row) (types.Time, bool, error) {
	return types.ZeroDatetime, true, nil
}