mirror of
				https://github.com/chaisql/chai.git
				synced 2025-10-31 10:56:22 +08:00 
			
		
		
		
	Drop duration type
This commit is contained in:
		| @@ -4,7 +4,6 @@ import ( | ||||
| 	"encoding/base64" | ||||
| 	"fmt" | ||||
| 	"strconv" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| // CastAs casts v as the selected type when possible. | ||||
| @@ -25,8 +24,6 @@ func (v Value) CastAs(t ValueType) (Value, error) { | ||||
| 		return v.CastAsInteger() | ||||
| 	case DoubleValue: | ||||
| 		return v.CastAsDouble() | ||||
| 	case DurationValue: | ||||
| 		return v.CastAsDuration() | ||||
| 	case BlobValue: | ||||
| 		return v.CastAsBlob() | ||||
| 	case TextValue: | ||||
| @@ -65,7 +62,6 @@ func (v Value) CastAsBool() (Value, error) { | ||||
| // CastAsInteger casts according to the following rules: | ||||
| // Bool: returns 1 if true, 0 if false. | ||||
| // Double: cuts off the decimal and remaining numbers. | ||||
| // Duration: returns the number of nanoseconds in the duration. | ||||
| // Text: uses strconv.ParseInt to determine the integer value, | ||||
| // then casts it to an integer. If it fails uses strconv.ParseFloat | ||||
| // to determine the double value, then casts it to an integer | ||||
| @@ -82,8 +78,6 @@ func (v Value) CastAsInteger() (Value, error) { | ||||
| 		return NewIntegerValue(0), nil | ||||
| 	case DoubleValue: | ||||
| 		return NewIntegerValue(int64(v.V.(float64))), nil | ||||
| 	case DurationValue: | ||||
| 		return NewIntegerValue(int64(v.V.(time.Duration))), nil | ||||
| 	case TextValue: | ||||
| 		i, err := strconv.ParseInt(v.V.(string), 10, 64) | ||||
| 		if err != nil { | ||||
| @@ -122,26 +116,6 @@ func (v Value) CastAsDouble() (Value, error) { | ||||
| 	return Value{}, fmt.Errorf("cannot cast %s as double", v.Type) | ||||
| } | ||||
|  | ||||
| // CastAsDuration casts according to the following rules: | ||||
| // Text: decodes using time.ParseDuration, otherwise fails. | ||||
| // Any other type is considered an invalid cast. | ||||
| func (v Value) CastAsDuration() (Value, error) { | ||||
| 	if v.Type == DurationValue { | ||||
| 		return v, nil | ||||
| 	} | ||||
|  | ||||
| 	if v.Type == TextValue { | ||||
| 		d, err := time.ParseDuration(v.V.(string)) | ||||
| 		if err != nil { | ||||
| 			return Value{}, fmt.Errorf(`cannot cast %q as duration: %w`, v.V, err) | ||||
| 		} | ||||
|  | ||||
| 		return NewDurationValue(d), nil | ||||
| 	} | ||||
|  | ||||
| 	return Value{}, fmt.Errorf("cannot cast %s as duration", v.Type) | ||||
| } | ||||
|  | ||||
| // CastAsText returns a JSON representation of v. | ||||
| // If the representation is a string, it gets unquoted. | ||||
| func (v Value) CastAsText() (Value, error) { | ||||
| @@ -156,7 +130,7 @@ func (v Value) CastAsText() (Value, error) { | ||||
|  | ||||
| 	s := string(d) | ||||
|  | ||||
| 	if v.Type == DurationValue || v.Type == BlobValue { | ||||
| 	if v.Type == BlobValue { | ||||
| 		s, err = strconv.Unquote(s) | ||||
| 		if err != nil { | ||||
| 			return Value{}, err | ||||
|   | ||||
| @@ -2,7 +2,6 @@ package document | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/stretchr/testify/require" | ||||
| ) | ||||
| @@ -15,7 +14,6 @@ func TestCastAs(t *testing.T) { | ||||
|  | ||||
| 	boolV := NewBoolValue(true) | ||||
| 	integerV := NewIntegerValue(10) | ||||
| 	durationV := NewDurationValue(3 * time.Second) | ||||
| 	doubleV := NewDoubleValue(10.5) | ||||
| 	textV := NewTextValue("foo") | ||||
| 	blobV := NewBlobValue([]byte("abc")) | ||||
| @@ -45,7 +43,6 @@ func TestCastAs(t *testing.T) { | ||||
| 			{boolV, boolV, false}, | ||||
| 			{integerV, boolV, false}, | ||||
| 			{NewIntegerValue(0), NewBoolValue(false), false}, | ||||
| 			{durationV, Value{}, true}, | ||||
| 			{doubleV, Value{}, true}, | ||||
| 			{textV, Value{}, true}, | ||||
| 			{NewTextValue("true"), boolV, false}, | ||||
| @@ -61,7 +58,6 @@ func TestCastAs(t *testing.T) { | ||||
| 			{boolV, NewIntegerValue(1), false}, | ||||
| 			{NewBoolValue(false), NewIntegerValue(0), false}, | ||||
| 			{integerV, integerV, false}, | ||||
| 			{durationV, NewIntegerValue(int64(3 * time.Second)), false}, | ||||
| 			{doubleV, integerV, false}, | ||||
| 			{textV, Value{}, true}, | ||||
| 			{NewTextValue("10"), integerV, false}, | ||||
| @@ -76,7 +72,6 @@ func TestCastAs(t *testing.T) { | ||||
| 		check(t, DoubleValue, []test{ | ||||
| 			{boolV, Value{}, true}, | ||||
| 			{integerV, NewDoubleValue(10), false}, | ||||
| 			{durationV, Value{}, true}, | ||||
| 			{doubleV, doubleV, false}, | ||||
| 			{textV, Value{}, true}, | ||||
| 			{NewTextValue("10"), NewDoubleValue(10), false}, | ||||
| @@ -87,26 +82,10 @@ func TestCastAs(t *testing.T) { | ||||
| 		}) | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("duration", func(t *testing.T) { | ||||
| 		check(t, DurationValue, []test{ | ||||
| 			{boolV, Value{}, true}, | ||||
| 			{integerV, Value{}, true}, | ||||
| 			{durationV, durationV, false}, | ||||
| 			{doubleV, Value{}, true}, | ||||
| 			{textV, Value{}, true}, | ||||
| 			{NewTextValue("3s"), durationV, false}, | ||||
| 			{NewTextValue("10.5"), Value{}, true}, | ||||
| 			{blobV, Value{}, true}, | ||||
| 			{arrayV, Value{}, true}, | ||||
| 			{docV, Value{}, true}, | ||||
| 		}) | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("text", func(t *testing.T) { | ||||
| 		check(t, TextValue, []test{ | ||||
| 			{boolV, NewTextValue("true"), false}, | ||||
| 			{integerV, NewTextValue("10"), false}, | ||||
| 			{durationV, NewTextValue("3s"), false}, | ||||
| 			{doubleV, NewTextValue("10.5"), false}, | ||||
| 			{textV, textV, false}, | ||||
| 			{blobV, NewTextValue("YWJj"), false}, | ||||
| @@ -121,7 +100,6 @@ func TestCastAs(t *testing.T) { | ||||
| 		check(t, BlobValue, []test{ | ||||
| 			{boolV, Value{}, true}, | ||||
| 			{integerV, Value{}, true}, | ||||
| 			{durationV, Value{}, true}, | ||||
| 			{doubleV, Value{}, true}, | ||||
| 			{NewTextValue("YWJj"), blobV, false}, | ||||
| 			{NewTextValue("   dww  "), Value{}, true}, | ||||
| @@ -135,7 +113,6 @@ func TestCastAs(t *testing.T) { | ||||
| 		check(t, ArrayValue, []test{ | ||||
| 			{boolV, Value{}, true}, | ||||
| 			{integerV, Value{}, true}, | ||||
| 			{durationV, Value{}, true}, | ||||
| 			{doubleV, Value{}, true}, | ||||
| 			{NewTextValue(`["bar", 10]`), arrayV, false}, | ||||
| 			{NewTextValue("abc"), Value{}, true}, | ||||
| @@ -149,7 +126,6 @@ func TestCastAs(t *testing.T) { | ||||
| 		check(t, DocumentValue, []test{ | ||||
| 			{boolV, Value{}, true}, | ||||
| 			{integerV, Value{}, true}, | ||||
| 			{durationV, Value{}, true}, | ||||
| 			{doubleV, Value{}, true}, | ||||
| 			{NewTextValue(`{"a": 10, "b": "foo"}`), docV, false}, | ||||
| 			{NewTextValue("abc"), Value{}, true}, | ||||
|   | ||||
| @@ -3,7 +3,6 @@ package document | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| type operator uint8 | ||||
| @@ -94,10 +93,6 @@ func compare(op operator, l, r Value, compareDifferentTypes bool) (bool, error) | ||||
| 	case l.Type.IsNumber() && r.Type.IsNumber(): | ||||
| 		return compareNumbers(op, l, r) | ||||
|  | ||||
| 	// compare durations together | ||||
| 	case l.Type == DurationValue && r.Type == DurationValue: | ||||
| 		return compareIntegers(op, int64(l.V.(time.Duration)), int64(r.V.(time.Duration))), nil | ||||
|  | ||||
| 	// compare arrays together | ||||
| 	case l.Type == ArrayValue && r.Type == ArrayValue: | ||||
| 		return compareArrays(op, l.V.(Array), r.V.(Array)) | ||||
|   | ||||
| @@ -4,7 +4,6 @@ import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"testing" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/genjidb/genji/document" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| @@ -34,14 +33,6 @@ func jsonToBoolean(t testing.TB, x string) document.Value { | ||||
| 	return document.NewBoolValue(b) | ||||
| } | ||||
|  | ||||
| func jsonToDuration(t testing.TB, x string) document.Value { | ||||
| 	var d time.Duration | ||||
| 	err := json.Unmarshal([]byte(x), &d) | ||||
| 	require.NoError(t, err) | ||||
|  | ||||
| 	return document.NewDurationValue(d) | ||||
| } | ||||
|  | ||||
| func toText(t testing.TB, x string) document.Value { | ||||
| 	return document.NewTextValue(x) | ||||
| } | ||||
| @@ -127,24 +118,6 @@ func TestCompare(t *testing.T) { | ||||
| 		{"<=", "1", "2", true, jsonToDouble}, | ||||
| 		{"<=", "2", "2", true, jsonToDouble}, | ||||
|  | ||||
| 		// duration | ||||
| 		{"=", "2", "1", false, jsonToDuration}, | ||||
| 		{"=", "2", "2", true, jsonToDuration}, | ||||
| 		{"!=", "2", "1", true, jsonToDuration}, | ||||
| 		{"!=", "2", "2", false, jsonToDuration}, | ||||
| 		{">", "2", "1", true, jsonToDuration}, | ||||
| 		{">", "1", "2", false, jsonToDuration}, | ||||
| 		{">", "2", "2", false, jsonToDuration}, | ||||
| 		{">=", "2", "1", true, jsonToDuration}, | ||||
| 		{">=", "1", "2", false, jsonToDuration}, | ||||
| 		{">=", "2", "2", true, jsonToDuration}, | ||||
| 		{"<", "2", "1", false, jsonToDuration}, | ||||
| 		{"<", "1", "2", true, jsonToDuration}, | ||||
| 		{"<", "2", "2", false, jsonToDuration}, | ||||
| 		{"<=", "2", "1", false, jsonToDuration}, | ||||
| 		{"<=", "1", "2", true, jsonToDuration}, | ||||
| 		{"<=", "2", "2", true, jsonToDuration}, | ||||
|  | ||||
| 		// text | ||||
| 		{"=", "b", "a", false, toText}, | ||||
| 		{"=", "b", "b", true, toText}, | ||||
|   | ||||
| @@ -165,8 +165,6 @@ func (s structDocument) MarshalJSON() ([]byte, error) { | ||||
| func NewValue(x interface{}) (Value, error) { | ||||
| 	// Attempt exact matches first: | ||||
| 	switch v := x.(type) { | ||||
| 	case time.Duration: | ||||
| 		return NewDurationValue(v), nil | ||||
| 	case time.Time: | ||||
| 		return NewTextValue(v.Format(time.RFC3339Nano)), nil | ||||
| 	case nil: | ||||
|   | ||||
| @@ -5,7 +5,6 @@ import ( | ||||
| 	"encoding/binary" | ||||
| 	"errors" | ||||
| 	"io" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/genjidb/genji/document" | ||||
| 	"github.com/genjidb/genji/document/encoding" | ||||
| @@ -128,8 +127,6 @@ func EncodeValue(v document.Value) ([]byte, error) { | ||||
| 		return encodeInt64(v.V.(int64)), nil | ||||
| 	case document.DoubleValue: | ||||
| 		key.AppendFloat64(nil, v.V.(float64)) | ||||
| 	case document.DurationValue: | ||||
| 		return encodeInt64(int64(v.V.(time.Duration))), nil | ||||
| 	case document.NullValue: | ||||
| 		return nil, nil | ||||
| 	} | ||||
| @@ -331,9 +328,6 @@ func DecodeValue(t document.ValueType, data []byte) (document.Value, error) { | ||||
| 			return document.Value{}, err | ||||
| 		} | ||||
| 		return document.NewDoubleValue(x), nil | ||||
| 	case document.DurationValue: | ||||
| 		x, _ := binary.Varint(data) | ||||
| 		return document.NewDurationValue(time.Duration(x)), nil | ||||
| 	case document.NullValue: | ||||
| 		return document.NewNullValue(), nil | ||||
| 	} | ||||
|   | ||||
| @@ -4,7 +4,6 @@ package encodingtest | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"testing" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/genjidb/genji/document" | ||||
| 	"github.com/genjidb/genji/document/encoding" | ||||
| @@ -97,8 +96,7 @@ func testArrayGetByIndex(t *testing.T, codecBuilder func() encoding.Codec) { | ||||
| 	arr := document.NewValueBuffer(). | ||||
| 		Append(document.NewIntegerValue(10)). | ||||
| 		Append(document.NewNullValue()). | ||||
| 		Append(document.NewTextValue("john")). | ||||
| 		Append(document.NewDurationValue(10 * time.Nanosecond)) | ||||
| 		Append(document.NewTextValue("john")) | ||||
|  | ||||
| 	var buf bytes.Buffer | ||||
|  | ||||
|   | ||||
| @@ -3,7 +3,6 @@ package msgpack | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/genjidb/genji/document" | ||||
| 	"github.com/genjidb/genji/document/encoding" | ||||
| @@ -11,11 +10,6 @@ import ( | ||||
| 	"github.com/vmihailenco/msgpack/v5/codes" | ||||
| ) | ||||
|  | ||||
| // List of custom types | ||||
| const ( | ||||
| 	DurationType int8 = 0x1 | ||||
| ) | ||||
|  | ||||
| // A Codec is a MessagePack implementation of an encoding.Codec. | ||||
| type Codec struct{} | ||||
|  | ||||
| @@ -115,7 +109,6 @@ func (e *Encoder) EncodeArray(a document.Array) error { | ||||
| // - int32 -> int32 | ||||
| // - int64 -> int64 | ||||
| // - float64 -> float64 | ||||
| // - duration -> custom type with code 0x1 and size 8 | ||||
| func (e *Encoder) EncodeValue(v document.Value) error { | ||||
| 	switch v.Type { | ||||
| 	case document.DocumentValue: | ||||
| @@ -134,32 +127,6 @@ func (e *Encoder) EncodeValue(v document.Value) error { | ||||
| 		return e.enc.EncodeInt64(v.V.(int64)) | ||||
| 	case document.DoubleValue: | ||||
| 		return e.enc.EncodeFloat64(v.V.(float64)) | ||||
| 	case document.DurationValue: | ||||
| 		// because messagepack doesn't have a duration type | ||||
| 		// vmihailenco/msgpack EncodeDuration method | ||||
| 		// encodes durations as int64 values. | ||||
| 		// this means that the duration is lost during | ||||
| 		// encoding and there is no way of knowing that | ||||
| 		// an int64 is a duration during decoding. | ||||
| 		// to avoid that, we create a custom duration type. | ||||
| 		err := e.enc.EncodeExtHeader(DurationType, 8) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		d := uint64(v.V.(time.Duration)) | ||||
| 		var buf [8]byte | ||||
| 		buf[0] = byte(d >> 56) | ||||
| 		buf[1] = byte(d >> 48) | ||||
| 		buf[2] = byte(d >> 40) | ||||
| 		buf[3] = byte(d >> 32) | ||||
| 		buf[4] = byte(d >> 24) | ||||
| 		buf[5] = byte(d >> 16) | ||||
| 		buf[6] = byte(d >> 8) | ||||
| 		buf[7] = byte(d) | ||||
|  | ||||
| 		_, err = e.enc.Writer().Write(buf[:]) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return e.enc.Encode(v.V) | ||||
| @@ -228,36 +195,6 @@ func (d *Decoder) DecodeValue() (v document.Value, err error) { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// decode custom codes | ||||
| 	if codes.IsExt(c) { | ||||
| 		var tp int8 | ||||
| 		tp, _, err = d.dec.DecodeExtHeader() | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		if tp != DurationType { | ||||
| 			panic(fmt.Sprintf("unknown custom code %d", tp)) | ||||
| 		} | ||||
|  | ||||
| 		var buf [8]byte | ||||
| 		err = d.dec.ReadFull(buf[:]) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		n := (uint64(buf[0]) << 56) | | ||||
| 			(uint64(buf[1]) << 48) | | ||||
| 			(uint64(buf[2]) << 40) | | ||||
| 			(uint64(buf[3]) << 32) | | ||||
| 			(uint64(buf[4]) << 24) | | ||||
| 			(uint64(buf[5]) << 16) | | ||||
| 			(uint64(buf[6]) << 8) | | ||||
| 			uint64(buf[7]) | ||||
| 		v.V = time.Duration(n) | ||||
| 		v.Type = document.DurationValue | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// decode the rest | ||||
| 	switch c { | ||||
| 	case codes.Nil: | ||||
|   | ||||
| @@ -65,7 +65,6 @@ func TestScan(t *testing.T) { | ||||
| 				Add("foo", document.NewTextValue("foo")). | ||||
| 				Add("bar", document.NewTextValue("bar")), | ||||
| 		)). | ||||
| 		Add("o", document.NewDurationValue(10*time.Nanosecond)). | ||||
| 		Add("p", document.NewTextValue(now.Format(time.RFC3339Nano))). | ||||
| 		Add("r", document.NewDocumentValue(codec.NewDocument(buf.Bytes()))) | ||||
|  | ||||
| @@ -89,11 +88,10 @@ func TestScan(t *testing.T) { | ||||
| 	var l *foo = new(foo) | ||||
| 	var m *foo | ||||
| 	var n map[string]string | ||||
| 	var o time.Duration | ||||
| 	var p time.Time | ||||
| 	var r map[string]interface{} | ||||
|  | ||||
| 	err = document.Scan(doc, &a, &b, &c, &d, &e, &f, &g, &h, &i, &j, &k, &l, &m, &n, &o, &p, &r) | ||||
| 	err = document.Scan(doc, &a, &b, &c, &d, &e, &f, &g, &h, &i, &j, &k, &l, &m, &n, &p, &r) | ||||
| 	require.NoError(t, err) | ||||
| 	require.Equal(t, a, []byte("foo")) | ||||
| 	require.Equal(t, b, "bar") | ||||
| @@ -110,7 +108,6 @@ func TestScan(t *testing.T) { | ||||
| 	require.Equal(t, &foo{Foo: "foo", Pub: &bar}, l) | ||||
| 	require.Equal(t, &foo{Foo: "foo", Pub: &bar}, m) | ||||
| 	require.Equal(t, map[string]string{"foo": "foo", "bar": "bar"}, n) | ||||
| 	require.Equal(t, 10*time.Nanosecond, o) | ||||
| 	require.Equal(t, now.Format(time.RFC3339Nano), p.Format(time.RFC3339Nano)) | ||||
| 	require.Equal(t, map[string]interface{}{ | ||||
| 		"foo": map[string]interface{}{ | ||||
| @@ -136,14 +133,14 @@ func TestScan(t *testing.T) { | ||||
| 		m := make(map[string]interface{}) | ||||
| 		err := document.MapScan(doc, m) | ||||
| 		require.NoError(t, err) | ||||
| 		require.Len(t, m, 17) | ||||
| 		require.Len(t, m, 16) | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("MapPtr", func(t *testing.T) { | ||||
| 		var m map[string]interface{} | ||||
| 		err := document.MapScan(doc, &m) | ||||
| 		require.NoError(t, err) | ||||
| 		require.Len(t, m, 17) | ||||
| 		require.Len(t, m, 16) | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("Small Slice", func(t *testing.T) { | ||||
|   | ||||
| @@ -7,7 +7,6 @@ import ( | ||||
| 	"fmt" | ||||
| 	"math" | ||||
| 	"strconv" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/buger/jsonparser" | ||||
| ) | ||||
| @@ -16,7 +15,6 @@ var ( | ||||
| 	boolZeroValue     = NewZeroValue(BoolValue) | ||||
| 	integerZeroValue  = NewZeroValue(IntegerValue) | ||||
| 	doubleZeroValue   = NewZeroValue(DoubleValue) | ||||
| 	durationZeroValue = NewZeroValue(DurationValue) | ||||
| 	blobZeroValue     = NewZeroValue(BlobValue) | ||||
| 	textZeroValue     = NewZeroValue(TextValue) | ||||
| 	arrayZeroValue    = NewZeroValue(ArrayValue) | ||||
| @@ -50,9 +48,6 @@ const ( | ||||
| 	// double family: 0xA0 to 0xAF | ||||
| 	DoubleValue ValueType = 0xA0 | ||||
|  | ||||
| 	// time family: 0xB0 to 0xBF | ||||
| 	DurationValue ValueType = 0xB0 | ||||
|  | ||||
| 	// string family: 0xC0 to 0xCF | ||||
| 	TextValue ValueType = 0xC0 | ||||
|  | ||||
| @@ -76,8 +71,6 @@ func (t ValueType) String() string { | ||||
| 		return "integer" | ||||
| 	case DoubleValue: | ||||
| 		return "double" | ||||
| 	case DurationValue: | ||||
| 		return "duration" | ||||
| 	case BlobValue: | ||||
| 		return "blob" | ||||
| 	case TextValue: | ||||
| @@ -134,14 +127,6 @@ func NewDoubleValue(x float64) Value { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // NewDurationValue returns a value of type Duration. | ||||
| func NewDurationValue(d time.Duration) Value { | ||||
| 	return Value{ | ||||
| 		Type: DurationValue, | ||||
| 		V:    d, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // NewBlobValue encodes x and returns a value. | ||||
| func NewBlobValue(x []byte) Value { | ||||
| 	return Value{ | ||||
| @@ -186,8 +171,6 @@ func NewZeroValue(t ValueType) Value { | ||||
| 		return NewIntegerValue(0) | ||||
| 	case DoubleValue: | ||||
| 		return NewDoubleValue(0) | ||||
| 	case DurationValue: | ||||
| 		return NewDurationValue(0) | ||||
| 	case BlobValue: | ||||
| 		return NewBlobValue(nil) | ||||
| 	case TextValue: | ||||
| @@ -221,8 +204,6 @@ func (v Value) IsZeroValue() (bool, error) { | ||||
| 		return v.V == integerZeroValue.V, nil | ||||
| 	case DoubleValue: | ||||
| 		return v.V == doubleZeroValue.V, nil | ||||
| 	case DurationValue: | ||||
| 		return v.V == durationZeroValue.V, nil | ||||
| 	case BlobValue: | ||||
| 		return bytes.Compare(v.V.([]byte), blobZeroValue.V.([]byte)) == 0, nil | ||||
| 	case TextValue: | ||||
| @@ -278,8 +259,6 @@ func (v Value) MarshalJSON() ([]byte, error) { | ||||
| 		} | ||||
|  | ||||
| 		return strconv.AppendFloat(nil, v.V.(float64), fmt, -1, 64), nil | ||||
| 	case DurationValue: | ||||
| 		return []byte(strconv.Quote(v.V.(time.Duration).String())), nil | ||||
| 	case TextValue: | ||||
| 		return []byte(strconv.Quote(v.V.(string))), nil | ||||
| 	case BlobValue: | ||||
| @@ -305,7 +284,7 @@ func (v Value) String() string { | ||||
| 		return "NULL" | ||||
| 	case TextValue: | ||||
| 		return strconv.Quote(v.V.(string)) | ||||
| 	case BlobValue, DurationValue: | ||||
| 	case BlobValue: | ||||
| 		return fmt.Sprintf("%v", v.V) | ||||
| 	} | ||||
|  | ||||
| @@ -375,18 +354,6 @@ func calculateValues(a, b Value, operator byte) (res Value, err error) { | ||||
| 		return NewNullValue(), nil | ||||
| 	} | ||||
|  | ||||
| 	if a.Type == DurationValue && b.Type == DurationValue { | ||||
| 		res, err = calculateIntegers(a, b, operator) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		if operator != '&' && operator != '|' && operator != '^' { | ||||
| 			return NewDurationValue(time.Duration(res.V.(int64))), nil | ||||
| 		} | ||||
|  | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if a.Type.IsNumber() && b.Type.IsNumber() { | ||||
| 		if a.Type == DoubleValue || b.Type == DoubleValue { | ||||
| 			return calculateFloats(a, b, operator) | ||||
| @@ -415,8 +382,6 @@ func convertNumberToInt64(v Value) (int64, error) { | ||||
| 			return 0, errors.New(`cannot convert "double" value to "integer" without loss of precision`) | ||||
| 		} | ||||
| 		i = int64(f) | ||||
| 	case DurationValue: | ||||
| 		return int64(v.V.(time.Duration)), nil | ||||
| 	} | ||||
|  | ||||
| 	return i, nil | ||||
|   | ||||
| @@ -23,7 +23,6 @@ func TestValueString(t *testing.T) { | ||||
| 		{"double", document.NewDoubleValue(10.1), "10.1"}, | ||||
| 		{"document", document.NewDocumentValue(document.NewFieldBuffer().Add("a", document.NewIntegerValue(10))), "{\"a\": 10}"}, | ||||
| 		{"array", document.NewArrayValue(document.NewValueBuffer(document.NewIntegerValue(10))), "[10]"}, | ||||
| 		{"duration", document.NewDurationValue(10 * time.Nanosecond), "10ns"}, | ||||
| 	} | ||||
|  | ||||
| 	for _, test := range tests { | ||||
| @@ -74,7 +73,6 @@ func TestNewValue(t *testing.T) { | ||||
| 		{"null", nil, nil}, | ||||
| 		{"document", document.NewFieldBuffer().Add("a", document.NewIntegerValue(10)), document.NewFieldBuffer().Add("a", document.NewIntegerValue(10))}, | ||||
| 		{"array", document.NewValueBuffer(document.NewIntegerValue(10)), document.NewValueBuffer(document.NewIntegerValue(10))}, | ||||
| 		{"duration", 10 * time.Nanosecond, 10 * time.Nanosecond}, | ||||
| 		{"time", now, now.Format(time.RFC3339Nano)}, | ||||
| 		{"bytes", myBytes("bar"), []byte("bar")}, | ||||
| 		{"string", myString("bar"), "bar"}, | ||||
| @@ -119,7 +117,6 @@ func TestValueAdd(t *testing.T) { | ||||
| 		{"text('120')+text('120')", document.NewTextValue("120"), document.NewTextValue("120"), document.NewNullValue(), false}, | ||||
| 		{"document+document", document.NewDocumentValue(document.NewFieldBuffer().Add("a", document.NewIntegerValue(10))), document.NewDocumentValue(document.NewFieldBuffer().Add("a", document.NewIntegerValue(10))), document.NewNullValue(), false}, | ||||
| 		{"array+array", document.NewArrayValue(document.NewValueBuffer(document.NewIntegerValue(10))), document.NewArrayValue(document.NewValueBuffer(document.NewIntegerValue(10))), document.NewNullValue(), false}, | ||||
| 		{"duration(1ns)+duration(1ms)", document.NewDurationValue(time.Nanosecond), document.NewDurationValue(time.Millisecond), document.NewDurationValue(time.Nanosecond + time.Millisecond), false}, | ||||
| 	} | ||||
|  | ||||
| 	for _, test := range tests { | ||||
| @@ -156,7 +153,6 @@ func TestValueSub(t *testing.T) { | ||||
| 		{"text('120')-text('120')", document.NewTextValue("120"), document.NewTextValue("120"), document.NewNullValue(), false}, | ||||
| 		{"document-document", document.NewDocumentValue(document.NewFieldBuffer().Add("a", document.NewIntegerValue(10))), document.NewDocumentValue(document.NewFieldBuffer().Add("a", document.NewIntegerValue(10))), document.NewNullValue(), false}, | ||||
| 		{"array-array", document.NewArrayValue(document.NewValueBuffer(document.NewIntegerValue(10))), document.NewArrayValue(document.NewValueBuffer(document.NewIntegerValue(10))), document.NewNullValue(), false}, | ||||
| 		{"duration(1ns)-duration(1ms)", document.NewDurationValue(time.Nanosecond), document.NewDurationValue(time.Millisecond), document.NewDurationValue(time.Nanosecond - time.Millisecond), false}, | ||||
| 	} | ||||
|  | ||||
| 	for _, test := range tests { | ||||
| @@ -191,7 +187,6 @@ func TestValueMult(t *testing.T) { | ||||
| 		{"text('120')*text('120')", document.NewTextValue("120"), document.NewTextValue("120"), document.NewNullValue(), false}, | ||||
| 		{"document*document", document.NewDocumentValue(document.NewFieldBuffer().Add("a", document.NewIntegerValue(10))), document.NewDocumentValue(document.NewFieldBuffer().Add("a", document.NewIntegerValue(10))), document.NewNullValue(), false}, | ||||
| 		{"array*array", document.NewArrayValue(document.NewValueBuffer(document.NewIntegerValue(10))), document.NewArrayValue(document.NewValueBuffer(document.NewIntegerValue(10))), document.NewNullValue(), false}, | ||||
| 		{"duration(10ns)*duration(1ms)", document.NewDurationValue(10 * time.Nanosecond), document.NewDurationValue(time.Millisecond), document.NewDurationValue(10 * time.Nanosecond * time.Millisecond), false}, | ||||
| 	} | ||||
|  | ||||
| 	for _, test := range tests { | ||||
| @@ -227,7 +222,6 @@ func TestValueDiv(t *testing.T) { | ||||
| 		{"text('120')/text('120')", document.NewTextValue("120"), document.NewTextValue("120"), document.NewNullValue(), false}, | ||||
| 		{"document/document", document.NewDocumentValue(document.NewFieldBuffer().Add("a", document.NewIntegerValue(10))), document.NewDocumentValue(document.NewFieldBuffer().Add("a", document.NewIntegerValue(10))), document.NewNullValue(), false}, | ||||
| 		{"array/array", document.NewArrayValue(document.NewValueBuffer(document.NewIntegerValue(10))), document.NewArrayValue(document.NewValueBuffer(document.NewIntegerValue(10))), document.NewNullValue(), false}, | ||||
| 		{"duration(10ns)/duration(1ms)", document.NewDurationValue(10 * time.Nanosecond), document.NewDurationValue(time.Millisecond), document.NewDurationValue(10 * time.Nanosecond / time.Millisecond), false}, | ||||
| 	} | ||||
|  | ||||
| 	for _, test := range tests { | ||||
| @@ -265,7 +259,6 @@ func TestValueMod(t *testing.T) { | ||||
| 		{"text('120')%text('120')", document.NewTextValue("120"), document.NewTextValue("120"), document.NewNullValue(), false}, | ||||
| 		{"document%document", document.NewDocumentValue(document.NewFieldBuffer().Add("a", document.NewIntegerValue(10))), document.NewDocumentValue(document.NewFieldBuffer().Add("a", document.NewIntegerValue(10))), document.NewNullValue(), false}, | ||||
| 		{"array%array", document.NewArrayValue(document.NewValueBuffer(document.NewIntegerValue(10))), document.NewArrayValue(document.NewValueBuffer(document.NewIntegerValue(10))), document.NewNullValue(), false}, | ||||
| 		{"duration(10ns)%duration(1ms)", document.NewDurationValue(10 * time.Nanosecond), document.NewDurationValue(time.Millisecond), document.NewDurationValue(10 * time.Nanosecond % time.Millisecond), false}, | ||||
| 	} | ||||
|  | ||||
| 	for _, test := range tests { | ||||
| @@ -300,7 +293,6 @@ func TestValueBitwiseAnd(t *testing.T) { | ||||
| 		{"text('120')&text('120')", document.NewTextValue("120"), document.NewTextValue("120"), document.NewNullValue(), false}, | ||||
| 		{"document&document", document.NewDocumentValue(document.NewFieldBuffer().Add("a", document.NewIntegerValue(10))), document.NewDocumentValue(document.NewFieldBuffer().Add("a", document.NewIntegerValue(10))), document.NewNullValue(), false}, | ||||
| 		{"array&array", document.NewArrayValue(document.NewValueBuffer(document.NewIntegerValue(10))), document.NewArrayValue(document.NewValueBuffer(document.NewIntegerValue(10))), document.NewNullValue(), false}, | ||||
| 		{"duration(10ns)&duration(1ms)", document.NewDurationValue(10 * time.Nanosecond), document.NewDurationValue(time.Microsecond), document.NewIntegerValue(8), false}, | ||||
| 	} | ||||
|  | ||||
| 	for _, test := range tests { | ||||
| @@ -334,7 +326,6 @@ func TestValueBitwiseOr(t *testing.T) { | ||||
| 		{"text('120')|text('120')", document.NewTextValue("120"), document.NewTextValue("120"), document.NewNullValue(), false}, | ||||
| 		{"document|document", document.NewDocumentValue(document.NewFieldBuffer().Add("a", document.NewIntegerValue(10))), document.NewDocumentValue(document.NewFieldBuffer().Add("a", document.NewIntegerValue(10))), document.NewNullValue(), false}, | ||||
| 		{"array|array", document.NewArrayValue(document.NewValueBuffer(document.NewIntegerValue(10))), document.NewArrayValue(document.NewValueBuffer(document.NewIntegerValue(10))), document.NewNullValue(), false}, | ||||
| 		{"duration(10ns)|duration(1ms)", document.NewDurationValue(10 * time.Nanosecond), document.NewDurationValue(time.Microsecond), document.NewIntegerValue(1002), false}, | ||||
| 	} | ||||
|  | ||||
| 	for _, test := range tests { | ||||
| @@ -367,7 +358,6 @@ func TestValueBitwiseXor(t *testing.T) { | ||||
| 		{"text('120')^text('120')", document.NewTextValue("120"), document.NewTextValue("120"), document.NewNullValue(), false}, | ||||
| 		{"document^document", document.NewDocumentValue(document.NewFieldBuffer().Add("a", document.NewIntegerValue(10))), document.NewDocumentValue(document.NewFieldBuffer().Add("a", document.NewIntegerValue(10))), document.NewNullValue(), false}, | ||||
| 		{"array^array", document.NewArrayValue(document.NewValueBuffer(document.NewIntegerValue(10))), document.NewArrayValue(document.NewValueBuffer(document.NewIntegerValue(10))), document.NewNullValue(), false}, | ||||
| 		{"duration(10ns)^duration(1ms)", document.NewDurationValue(10 * time.Nanosecond), document.NewDurationValue(time.Microsecond), document.NewIntegerValue(994), false}, | ||||
| 	} | ||||
|  | ||||
| 	for _, test := range tests { | ||||
|   | ||||
| @@ -1,14 +1,8 @@ | ||||
| package document | ||||
|  | ||||
| import ( | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| // NewValue creates a value from x. It only supports a few type and doesn't rely on reflection. | ||||
| func NewValue(x interface{}) (Value, error) { | ||||
| 	switch v := x.(type) { | ||||
| 	case time.Duration: | ||||
| 		return NewDurationValue(v), nil | ||||
| 	case nil: | ||||
| 		return NewNullValue(), nil | ||||
| 	case Document: | ||||
|   | ||||
| @@ -20,7 +20,6 @@ var valueTypes = []document.ValueType{ | ||||
| 	document.NullValue, | ||||
| 	document.BoolValue, | ||||
| 	document.DoubleValue, | ||||
| 	document.DurationValue, | ||||
| 	document.TextValue, | ||||
| 	document.BlobValue, | ||||
| 	document.ArrayValue, | ||||
|   | ||||
| @@ -13,7 +13,6 @@ import ( | ||||
| 	"encoding/binary" | ||||
| 	"errors" | ||||
| 	"math" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/genjidb/genji/document" | ||||
| ) | ||||
| @@ -196,8 +195,6 @@ func decodeValue(data []byte, delim, end byte) (document.Value, int, error) { | ||||
| 		i++ | ||||
| 	case document.DoubleValue: | ||||
| 		i += 16 | ||||
| 	case document.DurationValue: | ||||
| 		i += 8 | ||||
| 	case document.BlobValue, document.TextValue: | ||||
| 		for i < len(data) && data[i] != delim && data[i] != end { | ||||
| 			i++ | ||||
| @@ -352,8 +349,6 @@ func AppendValue(buf []byte, v document.Value) ([]byte, error) { | ||||
| 		return AppendBool(buf, v.V.(bool)), nil | ||||
| 	case document.IntegerValue, document.DoubleValue: | ||||
| 		return AppendNumber(buf, v) | ||||
| 	case document.DurationValue: | ||||
| 		return AppendInt64(buf, int64(v.V.(time.Duration))), nil | ||||
| 	case document.NullValue: | ||||
| 		return buf, nil | ||||
| 	case document.ArrayValue: | ||||
| @@ -398,12 +393,6 @@ func DecodeValue(data []byte) (document.Value, error) { | ||||
| 			return document.Value{}, err | ||||
| 		} | ||||
| 		return document.NewDoubleValue(x), nil | ||||
| 	case document.DurationValue: | ||||
| 		x, err := DecodeInt64(data) | ||||
| 		if err != nil { | ||||
| 			return document.Value{}, err | ||||
| 		} | ||||
| 		return document.NewDurationValue(time.Duration(x)), nil | ||||
| 	case document.NullValue: | ||||
| 		return document.NewNullValue(), nil | ||||
| 	case document.ArrayValue: | ||||
| @@ -437,8 +426,6 @@ func Append(buf []byte, t document.ValueType, v interface{}) ([]byte, error) { | ||||
| 		return AppendInt64(buf, v.(int64)), nil | ||||
| 	case document.DoubleValue: | ||||
| 		return AppendFloat64(buf, v.(float64)), nil | ||||
| 	case document.DurationValue: | ||||
| 		return AppendInt64(buf, int64(v.(time.Duration))), nil | ||||
| 	case document.NullValue: | ||||
| 		return buf, nil | ||||
| 	case document.ArrayValue: | ||||
| @@ -472,12 +459,6 @@ func Decode(t document.ValueType, data []byte) (document.Value, error) { | ||||
| 			return document.Value{}, err | ||||
| 		} | ||||
| 		return document.NewDoubleValue(x), nil | ||||
| 	case document.DurationValue: | ||||
| 		x, err := DecodeInt64(data) | ||||
| 		if err != nil { | ||||
| 			return document.Value{}, err | ||||
| 		} | ||||
| 		return document.NewDurationValue(time.Duration(x)), nil | ||||
| 	case document.NullValue: | ||||
| 		return document.NewNullValue(), nil | ||||
| 	case document.ArrayValue: | ||||
|   | ||||
| @@ -5,7 +5,6 @@ import ( | ||||
| 	"math" | ||||
| 	"sort" | ||||
| 	"testing" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/genjidb/genji/document" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| @@ -22,7 +21,6 @@ func TestAppendDecode(t *testing.T) { | ||||
| 		{"double", document.NewDoubleValue(-3.14)}, | ||||
| 		{"text", document.NewTextValue("foo")}, | ||||
| 		{"blob", document.NewBlobValue([]byte("bar"))}, | ||||
| 		{"duration", document.NewDurationValue(10 * time.Second)}, | ||||
| 		{"array", document.NewArrayValue(document.NewValueBuffer( | ||||
| 			document.NewBoolValue(true), | ||||
| 			document.NewIntegerValue(55), | ||||
| @@ -89,7 +87,6 @@ func TestAppendValueDecodeValue(t *testing.T) { | ||||
| 		{"double", document.NewDoubleValue(-3.14)}, | ||||
| 		{"text", document.NewTextValue("foo")}, | ||||
| 		{"blob", document.NewBlobValue([]byte("bar"))}, | ||||
| 		{"duration", document.NewDurationValue(10 * time.Second)}, | ||||
| 		{"array", document.NewArrayValue(document.NewValueBuffer( | ||||
| 			document.NewBoolValue(true), | ||||
| 			document.NewIntegerValue(55), | ||||
|   | ||||
| @@ -101,13 +101,12 @@ func TestParserCreateTable(t *testing.T) { | ||||
| 				}, | ||||
| 			}, false}, | ||||
| 		{"With all supported variable size data types", | ||||
| 			"CREATE TABLE test(i integer, du duration, b blob, byt bytes, t text, a array, d document)", | ||||
| 			"CREATE TABLE test(i integer, b blob, byt bytes, t text, a array, d document)", | ||||
| 			query.CreateTableStmt{ | ||||
| 				TableName: "test", | ||||
| 				Info: database.TableInfo{ | ||||
| 					FieldConstraints: []database.FieldConstraint{ | ||||
| 						{Path: parsePath(t, "i"), Type: document.IntegerValue}, | ||||
| 						{Path: parsePath(t, "du"), Type: document.DurationValue}, | ||||
| 						{Path: parsePath(t, "b"), Type: document.BlobValue}, | ||||
| 						{Path: parsePath(t, "byt"), Type: document.BlobValue}, | ||||
| 						{Path: parsePath(t, "t"), Type: document.TextValue}, | ||||
|   | ||||
| @@ -5,7 +5,6 @@ import ( | ||||
| 	"fmt" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/genjidb/genji/document" | ||||
| 	"github.com/genjidb/genji/sql/query/expr" | ||||
| @@ -195,12 +194,6 @@ func (p *Parser) parseUnaryExpr() (expr.Expr, error) { | ||||
| 		return expr.BoolValue(tok == scanner.TRUE), nil | ||||
| 	case scanner.NULL: | ||||
| 		return expr.NullValue(), nil | ||||
| 	case scanner.DURATION: | ||||
| 		d, err := time.ParseDuration(lit) | ||||
| 		if err != nil { | ||||
| 			return nil, &ParseError{Message: "unable to parse duration", Pos: pos} | ||||
| 		} | ||||
| 		return expr.DurationValue(d), nil | ||||
| 	case scanner.LBRACKET: | ||||
| 		p.Unscan() | ||||
| 		e, err := p.parseDocument() | ||||
| @@ -293,8 +286,6 @@ func (p *Parser) parseType() document.ValueType { | ||||
| 		return document.BlobValue | ||||
| 	case scanner.TYPEDOCUMENT: | ||||
| 		return document.DocumentValue | ||||
| 	case scanner.TYPEDURATION: | ||||
| 		return document.DurationValue | ||||
| 	case scanner.TYPEDOUBLE: | ||||
| 		return document.DoubleValue | ||||
| 	case scanner.TYPEINTEGER: | ||||
|   | ||||
| @@ -3,7 +3,6 @@ package parser | ||||
| import ( | ||||
| 	"strings" | ||||
| 	"testing" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/genjidb/genji/document" | ||||
| 	"github.com/genjidb/genji/sql/query/expr" | ||||
| @@ -42,11 +41,6 @@ func TestParserExpr(t *testing.T) { | ||||
| 		{"+float64", "10.0", expr.DoubleValue(10), false}, | ||||
| 		{"-float64", "-10.0", expr.DoubleValue(-10), false}, | ||||
|  | ||||
| 		// durations | ||||
| 		{"+duration", "150ms", expr.DurationValue(150 * time.Millisecond), false}, | ||||
| 		{"-duration", "-150ms", expr.DurationValue(-150 * time.Millisecond), false}, | ||||
| 		{"bad duration", "-150xs", expr.DurationValue(0), true}, | ||||
|  | ||||
| 		// strings | ||||
| 		{"double quoted string", `"10.0"`, expr.TextValue("10.0"), false}, | ||||
| 		{"single quoted string", "'-10.0'", expr.TextValue("-10.0"), false}, | ||||
|   | ||||
| @@ -85,8 +85,7 @@ func TestCreateTable(t *testing.T) { | ||||
| 		t.Run("with variable size data types", func(t *testing.T) { | ||||
| 			err = db.Exec(` | ||||
| 				CREATE TABLE test1( | ||||
| 					foo.bar[1].hello bytes PRIMARY KEY, foo.a[1][2] TEXT NOT NULL, bar[4][0].bat integer, | ||||
| 				 	du duration, b blob, t text, a array, d document | ||||
| 					foo.bar[1].hello bytes PRIMARY KEY, foo.a[1][2] TEXT NOT NULL, bar[4][0].bat integer, b blob, t text, a array, d document | ||||
| 				) | ||||
| 			`) | ||||
| 			require.NoError(t, err) | ||||
| @@ -105,7 +104,6 @@ func TestCreateTable(t *testing.T) { | ||||
| 					{Path: parsePath(t, "foo.bar[1].hello"), Type: document.BlobValue, IsPrimaryKey: true}, | ||||
| 					{Path: parsePath(t, "foo.a[1][2]"), Type: document.TextValue, IsNotNull: true}, | ||||
| 					{Path: parsePath(t, "bar[4][0].bat"), Type: document.IntegerValue}, | ||||
| 					{Path: parsePath(t, "du"), Type: document.DurationValue}, | ||||
| 					{Path: parsePath(t, "b"), Type: document.BlobValue}, | ||||
| 					{Path: parsePath(t, "t"), Type: document.TextValue}, | ||||
| 					{Path: parsePath(t, "a"), Type: document.ArrayValue}, | ||||
|   | ||||
| @@ -3,7 +3,6 @@ package expr | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/genjidb/genji/document" | ||||
| ) | ||||
| @@ -52,11 +51,6 @@ func DoubleValue(v float64) LiteralValue { | ||||
| 	return LiteralValue(document.NewDoubleValue(v)) | ||||
| } | ||||
|  | ||||
| // DurationValue creates a litteral value of type Duration. | ||||
| func DurationValue(v time.Duration) LiteralValue { | ||||
| 	return LiteralValue(document.NewDurationValue(v)) | ||||
| } | ||||
|  | ||||
| // NullValue creates a litteral value of type Null. | ||||
| func NullValue() LiteralValue { | ||||
| 	return LiteralValue(document.NewNullValue()) | ||||
|   | ||||
| @@ -141,7 +141,7 @@ func TestInsertStmt(t *testing.T) { | ||||
|  | ||||
| 		err = db.Exec(`CREATE TABLE test( | ||||
| 			b bool, db double, | ||||
| 			i integer, du duration, bb blob, byt bytes, | ||||
| 			i integer, bb blob, byt bytes, | ||||
| 			t text, a array, d document | ||||
| 		)`) | ||||
| 		require.NoError(t, err) | ||||
| @@ -150,7 +150,7 @@ func TestInsertStmt(t *testing.T) { | ||||
| 			INSERT INTO test | ||||
| 			VALUES { | ||||
| 				i: 10000000000, db: 21.21, b: true, | ||||
| 				du: 127ns, bb: "YmxvYlZhbHVlCg==", byt: "Ynl0ZXNWYWx1ZQ==", | ||||
| 				bb: "YmxvYlZhbHVlCg==", byt: "Ynl0ZXNWYWx1ZQ==", | ||||
| 				t: "text", a: [1, "foo", true], d: {"foo": "bar"} | ||||
| 			}`) | ||||
| 		require.NoError(t, err) | ||||
| @@ -166,7 +166,6 @@ func TestInsertStmt(t *testing.T) { | ||||
| 			"i": 10000000000, | ||||
| 			"db": 21.21, | ||||
| 			"b": true, | ||||
| 			"du": "127ns", | ||||
| 			"bb": "YmxvYlZhbHVlCg==", | ||||
| 			"byt": "Ynl0ZXNWYWx1ZQ==", | ||||
| 			"t": "text", | ||||
| @@ -200,10 +199,6 @@ func TestInsertStmt(t *testing.T) { | ||||
| 			{"document / not null with type constraint", "DOCUMENT NOT NULL", `{}`}, | ||||
| 			{"document / not null with non-respected type constraint ", "DOCUMENT NOT NULL", `{a: false}`}, | ||||
|  | ||||
| 			{"duration", "DURATION", `{a: "foo"}`}, | ||||
| 			{"duration / not null with type constraint", "DURATION NOT NULL", `{}`}, | ||||
| 			{"duration / not null with non-respected type constraint ", "DURATION NOT NULL", `{a: [1,2,3]}`}, | ||||
|  | ||||
| 			{"double", "DOUBLE", `{a: "foo"}`}, | ||||
| 			{"double / not null with type constraint", "DOUBLE NOT NULL", `{}`}, | ||||
| 			{"double / not null with non-respected type constraint ", "DOUBLE NOT NULL", `{a: [1,2,3]}`}, | ||||
|   | ||||
| @@ -50,7 +50,7 @@ func (s *Scanner) unbuffer() string { | ||||
| } | ||||
|  | ||||
| // Scan returns the next token and position from the underlying reader. | ||||
| // Also returns the literal text read for strings, numbers, and duration tokens | ||||
| // Also returns the literal text read for strings, and number tokens | ||||
| // since these token types can have different literal representations. | ||||
| func (s *Scanner) Scan() TokenInfo { | ||||
| 	// Read next code point. | ||||
| @@ -354,32 +354,7 @@ func (s *Scanner) scanNumber() TokenInfo { | ||||
| 		s.unread() | ||||
| 	} | ||||
|  | ||||
| 	// Read as a duration or integer if it doesn't have a fractional part. | ||||
| 	if !isDecimal { | ||||
| 		// If the next rune is a letter then this is a duration token. | ||||
| 		if ch0, _ := s.read(); isLetter(ch0) || ch0 == 'µ' { | ||||
| 			_, _ = buf.WriteRune(ch0) | ||||
| 			for { | ||||
| 				ch1, _ := s.read() | ||||
| 				if !isLetter(ch1) && ch1 != 'µ' { | ||||
| 					s.unread() | ||||
| 					break | ||||
| 				} | ||||
| 				_, _ = buf.WriteRune(ch1) | ||||
| 			} | ||||
|  | ||||
| 			// Continue reading digits and letters as part of this token. | ||||
| 			for { | ||||
| 				if ch0, _ := s.read(); isLetter(ch0) || ch0 == 'µ' || isDigit(ch0) { | ||||
| 					_, _ = buf.WriteRune(ch0) | ||||
| 				} else { | ||||
| 					s.unread() | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
| 			return TokenInfo{DURATION, pos, buf.String(), s.unbuffer()} | ||||
| 		} | ||||
| 		s.unread() | ||||
| 		return TokenInfo{INTEGER, pos, buf.String(), s.unbuffer()} | ||||
| 	} | ||||
| 	return TokenInfo{NUMBER, pos, buf.String(), s.unbuffer()} | ||||
|   | ||||
| @@ -115,17 +115,6 @@ func TestScanner_Scan(t *testing.T) { | ||||
| 		{s: `10.3s`, tok: scanner.NUMBER, lit: `10.3`, raw: `10.3`}, | ||||
| 		{s: `-10.3`, tok: scanner.NUMBER, lit: `-10.3`, raw: `-10.3`}, | ||||
|  | ||||
| 		// Durations | ||||
| 		{s: `10u`, tok: scanner.DURATION, lit: `10u`, raw: `10u`}, | ||||
| 		{s: `10µ`, tok: scanner.DURATION, lit: `10µ`, raw: `10µ`}, | ||||
| 		{s: `10ms`, tok: scanner.DURATION, lit: `10ms`, raw: `10ms`}, | ||||
| 		{s: `1s`, tok: scanner.DURATION, lit: `1s`, raw: `1s`}, | ||||
| 		{s: `10m`, tok: scanner.DURATION, lit: `10m`, raw: `10m`}, | ||||
| 		{s: `10h`, tok: scanner.DURATION, lit: `10h`, raw: `10h`}, | ||||
| 		{s: `10d`, tok: scanner.DURATION, lit: `10d`, raw: `10d`}, | ||||
| 		{s: `10w`, tok: scanner.DURATION, lit: `10w`, raw: `10w`}, | ||||
| 		{s: `10x`, tok: scanner.DURATION, lit: `10x`, raw: `10x`}, // non-duration unit, but scanned as a duration value | ||||
|  | ||||
| 		// Keywords | ||||
| 		{s: `ALTER`, tok: scanner.ALTER, raw: `ALTER`}, | ||||
| 		{s: `AS`, tok: scanner.AS, raw: `AS`}, | ||||
|   | ||||
| @@ -22,7 +22,6 @@ const ( | ||||
| 	POSITIONALPARAM // ? | ||||
| 	NUMBER          // 12345.67 | ||||
| 	INTEGER         // 12345 | ||||
| 	DURATION        // 13h | ||||
| 	STRING          // "abc" | ||||
| 	BADSTRING       // "abc | ||||
| 	BADESCAPE       // \q | ||||
| @@ -122,7 +121,6 @@ const ( | ||||
| 	TYPEBYTES | ||||
| 	TYPEDOCUMENT | ||||
| 	TYPEDOUBLE | ||||
| 	TYPEDURATION | ||||
| 	TYPEINTEGER | ||||
| 	TYPETEXT | ||||
|  | ||||
| @@ -137,7 +135,6 @@ var tokens = [...]string{ | ||||
| 	IDENT:           "IDENT", | ||||
| 	POSITIONALPARAM: "?", | ||||
| 	NUMBER:          "NUMBER", | ||||
| 	DURATION:        "DURATIONVAL", | ||||
| 	STRING:          "STRING", | ||||
| 	BADSTRING:       "BADSTRING", | ||||
| 	BADESCAPE:       "BADESCAPE", | ||||
| @@ -230,7 +227,6 @@ var tokens = [...]string{ | ||||
| 	TYPEBYTES:    "BYTES", | ||||
| 	TYPEDOCUMENT: "DOCUMENT", | ||||
| 	TYPEDOUBLE:   "DOUBLE", | ||||
| 	TYPEDURATION: "DURATION", | ||||
| 	TYPEINTEGER:  "INTEGER", | ||||
| 	TYPETEXT:     "TEXT", | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Asdine El Hrychy
					Asdine El Hrychy