Drop duration type

This commit is contained in:
Asdine El Hrychy
2020-09-28 22:32:06 +04:00
parent e146328321
commit dfdbc16b18
24 changed files with 11 additions and 312 deletions

View File

@@ -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

View File

@@ -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},

View File

@@ -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))

View File

@@ -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},

View File

@@ -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:

View File

@@ -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
} }

View File

@@ -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

View File

@@ -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:

View File

@@ -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) {

View File

@@ -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

View File

@@ -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 {

View File

@@ -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:

View File

@@ -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,

View File

@@ -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:

View File

@@ -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),

View File

@@ -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},

View File

@@ -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:

View File

@@ -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},

View File

@@ -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},

View File

@@ -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())

View File

@@ -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]}`},

View File

@@ -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()}

View File

@@ -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`},

View File

@@ -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",
} }