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