Exemple #1
0
func builtinNow(args []types.Datum, _ context.Context) (d types.Datum, err error) {
	// TODO: if NOW is used in stored function or trigger, NOW will return the beginning time
	// of the execution.
	fsp := 0
	if len(args) == 1 && args[0].Kind() != types.KindNull {
		if fsp, err = checkFsp(args[0]); err != nil {
			d.SetNull()
			return d, errors.Trace(err)
		}
	}

	t := mysql.Time{
		Time: time.Now(),
		Type: mysql.TypeDatetime,
		// set unspecified for later round
		Fsp: mysql.UnspecifiedFsp,
	}

	tr, err := t.RoundFrac(int(fsp))
	if err != nil {
		d.SetNull()
		return d, errors.Trace(err)
	}
	d.SetMysqlTime(tr)
	return d, nil
}
Exemple #2
0
func unflatten(datum types.Datum, tp *types.FieldType) (types.Datum, error) {
	if datum.IsNull() {
		return datum, nil
	}
	switch tp.Tp {
	case mysql.TypeFloat:
		datum.SetFloat32(float32(datum.GetFloat64()))
		return datum, nil
	case mysql.TypeTiny, mysql.TypeShort, mysql.TypeYear, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong,
		mysql.TypeDouble, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeBlob, mysql.TypeLongBlob,
		mysql.TypeVarchar, mysql.TypeString:
		return datum, nil
	case mysql.TypeDate, mysql.TypeDatetime, mysql.TypeTimestamp:
		var t mysql.Time
		t.Type = tp.Tp
		t.Fsp = tp.Decimal
		err := t.Unmarshal(datum.GetBytes())
		if err != nil {
			return datum, errors.Trace(err)
		}
		datum.SetValue(t)
		return datum, nil
	case mysql.TypeDuration:
		dur := mysql.Duration{Duration: time.Duration(datum.GetInt64())}
		datum.SetValue(dur)
		return datum, nil
	case mysql.TypeNewDecimal, mysql.TypeDecimal:
		dec, err := mysql.ParseDecimal(datum.GetString())
		if err != nil {
			return datum, errors.Trace(err)
		}
		if tp.Decimal >= 0 {
			dec = dec.Truncate(int32(tp.Decimal))
		}
		datum.SetValue(dec)
		return datum, nil
	case mysql.TypeEnum:
		enum, err := mysql.ParseEnumValue(tp.Elems, datum.GetUint64())
		if err != nil {
			return datum, errors.Trace(err)
		}
		datum.SetValue(enum)
		return datum, nil
	case mysql.TypeSet:
		set, err := mysql.ParseSetValue(tp.Elems, datum.GetUint64())
		if err != nil {
			return datum, errors.Trace(err)
		}
		datum.SetValue(set)
		return datum, nil
	case mysql.TypeBit:
		bit := mysql.Bit{Value: datum.GetUint64(), Width: tp.Flen}
		datum.SetValue(bit)
		return datum, nil
	}
	log.Error(tp.Tp, datum)
	return datum, nil
}
Exemple #3
0
// Unflatten converts a raw datum to a column datum.
func Unflatten(datum types.Datum, ft *types.FieldType, inIndex bool) (types.Datum, error) {
	if datum.IsNull() {
		return datum, nil
	}
	switch ft.Tp {
	case mysql.TypeFloat:
		datum.SetFloat32(float32(datum.GetFloat64()))
		return datum, nil
	case mysql.TypeTiny, mysql.TypeShort, mysql.TypeYear, mysql.TypeInt24,
		mysql.TypeLong, mysql.TypeLonglong, mysql.TypeDouble, mysql.TypeTinyBlob,
		mysql.TypeMediumBlob, mysql.TypeBlob, mysql.TypeLongBlob, mysql.TypeVarchar,
		mysql.TypeString:
		return datum, nil
	case mysql.TypeDate, mysql.TypeDatetime, mysql.TypeTimestamp:
		var t mysql.Time
		t.Type = ft.Tp
		t.Fsp = ft.Decimal
		var err error
		err = t.FromPackedUint(datum.GetUint64())
		if err != nil {
			return datum, errors.Trace(err)
		}
		datum.SetMysqlTime(t)
		return datum, nil
	case mysql.TypeDuration:
		dur := mysql.Duration{Duration: time.Duration(datum.GetInt64())}
		datum.SetValue(dur)
		return datum, nil
	case mysql.TypeEnum:
		enum, err := mysql.ParseEnumValue(ft.Elems, datum.GetUint64())
		if err != nil {
			return datum, errors.Trace(err)
		}
		datum.SetValue(enum)
		return datum, nil
	case mysql.TypeSet:
		set, err := mysql.ParseSetValue(ft.Elems, datum.GetUint64())
		if err != nil {
			return datum, errors.Trace(err)
		}
		datum.SetValue(set)
		return datum, nil
	case mysql.TypeBit:
		bit := mysql.Bit{Value: datum.GetUint64(), Width: ft.Flen}
		datum.SetValue(bit)
		return datum, nil
	}
	return datum, nil
}
Exemple #4
0
func (s *testCodecSuite) TestTime(c *C) {
	defer testleak.AfterTest(c)()
	tbl := []string{
		"2011-01-01 00:00:00",
		"2011-01-01 00:00:00",
		"0001-01-01 00:00:00",
	}

	for _, t := range tbl {
		m := types.NewDatum(parseTime(c, t))

		b, err := EncodeKey(nil, m)
		c.Assert(err, IsNil)
		v, err := Decode(b)
		c.Assert(err, IsNil)
		var t mysql.Time
		t.Type = mysql.TypeDatetime
		t.FromPackedUint(v[0].GetUint64())
		c.Assert(types.NewDatum(t), DeepEquals, m)
	}

	tblCmp := []struct {
		Arg1 string
		Arg2 string
		Ret  int
	}{
		{"2011-10-10 00:00:00", "2000-12-12 11:11:11", 1},
		{"2000-10-10 00:00:00", "2001-10-10 00:00:00", -1},
		{"2000-10-10 00:00:00", "2000-10-10 00:00:00", 0},
	}

	for _, t := range tblCmp {
		m1 := types.NewDatum(parseTime(c, t.Arg1))
		m2 := types.NewDatum(parseTime(c, t.Arg2))

		b1, err := EncodeKey(nil, m1)
		c.Assert(err, IsNil)
		b2, err := EncodeKey(nil, m2)
		c.Assert(err, IsNil)

		ret := bytes.Compare(b1, b2)
		c.Assert(ret, Equals, t.Ret)
	}
}
Exemple #5
0
func builtinNow(args []interface{}, ctx map[interface{}]interface{}) (interface{}, error) {
	// TODO: if NOW is used in stored function or trigger, NOW will return the beginning time
	// of the execution.
	fsp := 0
	if len(args) == 1 {
		var err error
		if fsp, err = checkFsp(args[0]); err != nil {
			return nil, errors.Trace(err)
		}
	}

	t := mysql.Time{
		Time: time.Now(),
		Type: mysql.TypeDatetime,
		// set unspecified for later round
		Fsp: mysql.UnspecifiedFsp,
	}

	return t.RoundFrac(int(fsp))
}
Exemple #6
0
func (d *Datum) compareMysqlTime(time mysql.Time) (int, error) {
	switch d.k {
	case KindString, KindBytes:
		dt, err := mysql.ParseDatetime(d.GetString())
		return dt.Compare(time), err
	case KindMysqlTime:
		return d.GetMysqlTime().Compare(time), nil
	default:
		fVal, _ := time.ToNumber().ToFloat64()
		return d.compareFloat64(fVal)
	}
}
Exemple #7
0
func dumpBinaryDateTime(t mysql.Time, loc *time.Location) (data []byte) {
	if t.Type == mysql.TypeTimestamp && loc != nil {
		t.Time = t.In(loc)
	}

	year, mon, day := t.Year(), t.Month(), t.Day()
	if t.IsZero() {
		year, mon, day = 1, time.January, 1
	}
	switch t.Type {
	case mysql.TypeTimestamp, mysql.TypeDatetime:
		data = append(data, 11)
		data = append(data, dumpUint16(uint16(year))...)
		data = append(data, byte(mon), byte(day), byte(t.Hour()), byte(t.Minute()), byte(t.Second()))
		data = append(data, dumpUint32(uint32((t.Nanosecond() / 1000)))...)
	case mysql.TypeDate, mysql.TypeNewDate:
		data = append(data, 4)
		data = append(data, dumpUint16(uint16(year))...) //year
		data = append(data, byte(mon), byte(day))
	}
	return
}
Exemple #8
0
func getTimeValue(ctx context.Context, v interface{}, tp byte, fsp int) (interface{}, error) {
	value := mysql.Time{
		Type: tp,
		Fsp:  fsp,
	}

	defaultTime, err := getSystemTimestamp(ctx)
	if err != nil {
		return nil, errors.Trace(err)
	}

	switch x := v.(type) {
	case string:
		if x == CurrentTimestamp {
			value.Time = defaultTime
		} else if x == ZeroTimestamp {
			value, _ = mysql.ParseTimeFromNum(0, tp, fsp)
		} else {
			value, err = mysql.ParseTime(x, tp, fsp)
			if err != nil {
				return nil, errors.Trace(err)
			}
		}
	case Value:
		x.Val = types.RawData(x.Val)
		switch xval := x.Val.(type) {
		case string:
			value, err = mysql.ParseTime(xval, tp, fsp)
			if err != nil {
				return nil, errors.Trace(err)
			}
		case int64:
			value, err = mysql.ParseTimeFromNum(int64(xval), tp, fsp)
			if err != nil {
				return nil, errors.Trace(err)
			}
		case nil:
			return nil, nil
		default:
			return nil, errors.Trace(errDefaultValue)
		}
	case *Ident:
		if x.Equal(CurrentTimeExpr) {
			return CurrentTimestamp, nil
		}

		return nil, errors.Trace(errDefaultValue)
	case *UnaryOperation:
		// support some expression, like `-1`
		m := map[interface{}]interface{}{}
		v := Eval(x, nil, m)
		ft := types.NewFieldType(mysql.TypeLonglong)
		xval, err := types.Convert(v, ft)
		if err != nil {
			return nil, errors.Trace(err)
		}

		value, err = mysql.ParseTimeFromNum(xval.(int64), tp, fsp)
		if err != nil {
			return nil, errors.Trace(err)
		}
	default:
		return nil, nil
	}

	return value, nil
}
Exemple #9
0
// Cast casts val to certain types and does not return error.
func Cast(val interface{}, target *FieldType) (v interface{}) {
	tp := target.Tp
	switch tp {
	case mysql.TypeString:
		x, _ := ToString(val)
		// TODO: consider target.Charset/Collate
		x = truncateStr(x, target.Flen)
		if target.Charset == charset.CharsetBin {
			return []byte(x)
		}
		return x
	case mysql.TypeDuration:
		var dur mysql.Duration
		fsp := mysql.DefaultFsp
		if target.Decimal != UnspecifiedLength {
			fsp = target.Decimal
		}
		switch x := val.(type) {
		case mysql.Duration:
			dur, _ = x.RoundFrac(fsp)
		case mysql.Time:
			dur, _ = x.ConvertToDuration()
			dur, _ = dur.RoundFrac(fsp)
		case string:
			dur, _ = mysql.ParseDuration(x, fsp)
		case *DataItem:
			return Cast(x.Data, target)
		}
		return dur
	case mysql.TypeDatetime, mysql.TypeDate:
		fsp := mysql.DefaultFsp
		if target.Decimal != UnspecifiedLength {
			fsp = target.Decimal
		}
		var t mysql.Time
		t.Type = tp
		switch x := val.(type) {
		case mysql.Time:
			t, _ = x.Convert(tp)
			t, _ = t.RoundFrac(fsp)
		case mysql.Duration:
			t, _ = x.ConvertToTime(tp)
			t, _ = t.RoundFrac(fsp)
		case string:
			t, _ = mysql.ParseTime(x, tp, fsp)
		case int64:
			t, _ = mysql.ParseTimeFromNum(x, tp, fsp)
		case *DataItem:
			return Cast(x.Data, target)
		}
		return t
	case mysql.TypeLonglong:
		if mysql.HasUnsignedFlag(target.Flag) {
			v, _ = ToUint64(val)
		} else {
			v, _ = ToInt64(val)
		}
		return
	case mysql.TypeNewDecimal:
		x, _ := ToDecimal(val)
		if target.Decimal != UnspecifiedLength {
			x = x.Round(int32(target.Decimal))
		}
		// TODO: check Flen
		return x
	default:
		panic("should never happen")
	}
}
Exemple #10
0
func getTimeValue(ctx context.Context, v interface{}, tp byte, fsp int) (d types.Datum, err error) {
	value := mysql.Time{
		Type: tp,
		Fsp:  fsp,
	}

	defaultTime, err := getSystemTimestamp(ctx)
	if err != nil {
		return d, errors.Trace(err)
	}

	switch x := v.(type) {
	case string:
		upperX := strings.ToUpper(x)
		if upperX == CurrentTimestamp {
			value.Time = defaultTime
		} else if upperX == ZeroTimestamp {
			value, _ = mysql.ParseTimeFromNum(0, tp, fsp)
		} else {
			value, err = mysql.ParseTime(x, tp, fsp)
			if err != nil {
				return d, errors.Trace(err)
			}
		}
	case *ast.ValueExpr:
		switch x.Kind() {
		case types.KindString:
			value, err = mysql.ParseTime(x.GetString(), tp, fsp)
			if err != nil {
				return d, errors.Trace(err)
			}
		case types.KindInt64:
			value, err = mysql.ParseTimeFromNum(x.GetInt64(), tp, fsp)
			if err != nil {
				return d, errors.Trace(err)
			}
		case types.KindNull:
			return d, nil
		default:
			return d, errors.Trace(errDefaultValue)
		}
	case *ast.FuncCallExpr:
		if x.FnName.L == currentTimestampL {
			d.SetString(CurrentTimestamp)
			return d, nil
		}
		return d, errors.Trace(errDefaultValue)
	case *ast.UnaryOperationExpr:
		// support some expression, like `-1`
		v, err := Eval(ctx, x)
		if err != nil {
			return d, errors.Trace(err)
		}
		ft := types.NewFieldType(mysql.TypeLonglong)
		xval, err := v.ConvertTo(ft)
		if err != nil {
			return d, errors.Trace(err)
		}

		value, err = mysql.ParseTimeFromNum(xval.GetInt64(), tp, fsp)
		if err != nil {
			return d, errors.Trace(err)
		}
	default:
		return d, nil
	}

	d.SetMysqlTime(value)
	return d, nil
}