mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-09-07 09:05:55 +00:00
Switch timestamp field to use epoch instead of min/max
This commit is contained in:
parent
6616b0d6f0
commit
ea01f7e37c
5 changed files with 23 additions and 46 deletions
|
|
@ -454,7 +454,7 @@ func TestAPI_ImportValue(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("creating index: %v", err)
|
||||
}
|
||||
_, err = m1.API.CreateField(ctx, index, field, pilosa.OptFieldTypeTimestamp(pilosa.MinTimestamp, pilosa.MaxTimestamp, pilosa.TimeUnitSeconds))
|
||||
_, err = m1.API.CreateField(ctx, index, field, pilosa.OptFieldTypeTimestamp(pilosa.DefaultEpoch, pilosa.TimeUnitSeconds))
|
||||
if err != nil {
|
||||
t.Fatalf("creating field: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1005,7 +1005,7 @@ func TestExecutor_Execute_SetValue(t *testing.T) {
|
|||
|
||||
// Create fields.
|
||||
index := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
|
||||
if _, err := index.CreateFieldIfNotExists("f", pilosa.OptFieldTypeTimestamp(pilosa.MinTimestamp, pilosa.MaxTimestamp, pilosa.TimeUnitSeconds)); err != nil {
|
||||
if _, err := index.CreateFieldIfNotExists("f", pilosa.OptFieldTypeTimestamp(pilosa.DefaultEpoch, pilosa.TimeUnitSeconds)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if _, err := index.CreateFieldIfNotExists("xxx", pilosa.OptFieldTypeDefault()); err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
@ -1798,20 +1798,18 @@ func TestExecutor_Execute_MinMax(t *testing.T) {
|
|||
}
|
||||
|
||||
tests := []struct {
|
||||
min time.Time
|
||||
max time.Time
|
||||
set time.Time
|
||||
epoch time.Time
|
||||
set time.Time
|
||||
}{
|
||||
{
|
||||
time.Date(2000, time.January, 10, 0, 0, 0, 0, time.UTC),
|
||||
time.Date(2000, time.January, 20, 0, 0, 0, 0, time.UTC),
|
||||
time.Date(2000, time.January, 11, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
}
|
||||
for i, test := range tests {
|
||||
fld := fmt.Sprintf("f%d", i)
|
||||
t.Run("MinMaxField_"+fld, func(t *testing.T) {
|
||||
if _, err := idx.CreateField(fld, pilosa.OptFieldTypeTimestamp(test.min, test.max, pilosa.TimeUnitSeconds)); err != nil {
|
||||
if _, err := idx.CreateField(fld, pilosa.OptFieldTypeTimestamp(test.epoch, pilosa.TimeUnitSeconds)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if _, err := c.GetNode(0).API.Query(context.Background(), &pilosa.QueryRequest{Index: "i", Query: fmt.Sprintf(`Set(10, %s="%s")`, fld, test.set.Format(time.RFC3339))}); err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
@ -4883,7 +4881,7 @@ func TestExecutor_Execute_Extract(t *testing.T) {
|
|||
Set(3, bsidecimal=-1.01)
|
||||
`)
|
||||
|
||||
c.CreateField(t, "i", pilosa.IndexOptions{TrackExistence: true}, "timestamp", pilosa.OptFieldTypeTimestamp(pilosa.MinTimestamp, pilosa.MaxTimestamp, pilosa.TimeUnitSeconds))
|
||||
c.CreateField(t, "i", pilosa.IndexOptions{TrackExistence: true}, "timestamp", pilosa.OptFieldTypeTimestamp(pilosa.DefaultEpoch, pilosa.TimeUnitSeconds))
|
||||
c.Query(t, "i", `
|
||||
Set(0, timestamp='2000-01-01T00:00:00Z')
|
||||
Set(1, timestamp='2000-01-01T00:00:01Z')
|
||||
|
|
|
|||
36
field.go
36
field.go
|
|
@ -208,10 +208,9 @@ func OptFieldTypeInt(min, max int64) FieldOption {
|
|||
// OptFieldTypeTimestamp is a functional option on FieldOptions
|
||||
// used to specify the field as being type `timestamp` and to
|
||||
// provide any respective configuration values.
|
||||
func OptFieldTypeTimestamp(min, max time.Time, timeUnit string) FieldOption {
|
||||
func OptFieldTypeTimestamp(epoch time.Time, timeUnit string) FieldOption {
|
||||
return func(fo *FieldOptions) error {
|
||||
minValue := min.UnixNano() / TimeUnitNanos(timeUnit)
|
||||
maxValue := max.UnixNano() / TimeUnitNanos(timeUnit)
|
||||
epochValue := epoch.UnixNano() / TimeUnitNanos(timeUnit)
|
||||
if fo.Type != "" {
|
||||
return errors.Errorf("field type is already set to: %s", fo.Type)
|
||||
}
|
||||
|
|
@ -220,18 +219,11 @@ func OptFieldTypeTimestamp(min, max time.Time, timeUnit string) FieldOption {
|
|||
} else if !IsValidTimeUnit(timeUnit) {
|
||||
return errors.Errorf("invalid time unit: %q", fo.TimeUnit)
|
||||
}
|
||||
if min.Before(MinTimestamp) {
|
||||
return errors.New("timestamp field min is too low")
|
||||
} else if max.After(MaxTimestamp) {
|
||||
return errors.New("timestamp field max is too high")
|
||||
} else if min.After(max) {
|
||||
return errors.New("timestamp field min cannot be greater than max")
|
||||
}
|
||||
fo.Type = FieldTypeTimestamp
|
||||
fo.TimeUnit = timeUnit
|
||||
fo.Min = pql.NewDecimal(minValue, 0)
|
||||
fo.Max = pql.NewDecimal(maxValue, 0)
|
||||
fo.Base = bsiBase(minValue, maxValue)
|
||||
fo.Min = pql.NewDecimal(MinTimestamp.UnixNano()/TimeUnitNanos(timeUnit), 0)
|
||||
fo.Max = pql.NewDecimal(MaxTimestamp.UnixNano()/TimeUnitNanos(timeUnit), 0)
|
||||
fo.Base = epochValue
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
@ -1925,23 +1917,15 @@ func (o *FieldOptions) MarshalJSON() ([]byte, error) {
|
|||
})
|
||||
case FieldTypeTimestamp:
|
||||
return json.Marshal(struct {
|
||||
Type string `json:"type"`
|
||||
BaseTimestamp time.Time `json:"baseTimestamp"`
|
||||
BitDepth uint64 `json:"bitDepth"`
|
||||
MinTimestamp time.Time `json:"minTimestamp"`
|
||||
MaxTimestamp time.Time `json:"maxTimestamp"`
|
||||
Keys bool `json:"keys"`
|
||||
TimeUnit string `json:"timeUnit"`
|
||||
ForeignIndex string `json:"foreignIndex"`
|
||||
Type string `json:"type"`
|
||||
Epoch time.Time `json:"epoch"`
|
||||
BitDepth uint64 `json:"bitDepth"`
|
||||
TimeUnit string `json:"timeUnit"`
|
||||
}{
|
||||
o.Type,
|
||||
time.Unix(0, o.Base*TimeUnitNanos(o.TimeUnit)).UTC(),
|
||||
o.BitDepth,
|
||||
time.Unix(0, o.Min.Value*TimeUnitNanos(o.TimeUnit)).UTC(),
|
||||
time.Unix(0, o.Max.Value*TimeUnitNanos(o.TimeUnit)).UTC(),
|
||||
o.Keys,
|
||||
o.TimeUnit,
|
||||
o.ForeignIndex,
|
||||
})
|
||||
case FieldTypeTime:
|
||||
return json.Marshal(struct {
|
||||
|
|
@ -2154,6 +2138,8 @@ func (f *Field) persistView(ctx context.Context, cvm *CreateViewMessage) error {
|
|||
|
||||
// Timestamp field range.
|
||||
var (
|
||||
DefaultEpoch = time.Unix(0, 0).UTC() // 1970-01-01T00:00:00Z
|
||||
|
||||
MinTimestamp = time.Unix(-1<<32, 0).UTC() // 1833-11-24T17:31:44Z
|
||||
MaxTimestamp = time.Unix(1<<32, 0).UTC() // 2106-02-07T06:28:16Z
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1341,19 +1341,11 @@ func (h *Handler) handlePostField(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
fos = append(fos, pilosa.OptFieldTypeDecimal(scale, minmax...))
|
||||
case pilosa.FieldTypeTimestamp:
|
||||
if req.Options.Min == nil {
|
||||
min := pql.NewDecimal(pilosa.MinTimestamp.UnixNano()/pilosa.TimeUnitNanos(*req.Options.TimeUnit), 0)
|
||||
req.Options.Min = &min
|
||||
if req.Options.Epoch == nil {
|
||||
epoch := pilosa.DefaultEpoch
|
||||
req.Options.Epoch = &epoch
|
||||
}
|
||||
if req.Options.Max == nil {
|
||||
max := pql.NewDecimal(pilosa.MaxTimestamp.UnixNano()/pilosa.TimeUnitNanos(*req.Options.TimeUnit), 0)
|
||||
req.Options.Max = &max
|
||||
}
|
||||
fos = append(fos, pilosa.OptFieldTypeTimestamp(
|
||||
time.Unix(0, req.Options.Min.ToInt64(0)*pilosa.TimeUnitNanos(*req.Options.TimeUnit)).UTC(),
|
||||
time.Unix(0, req.Options.Max.ToInt64(0)*pilosa.TimeUnitNanos(*req.Options.TimeUnit)).UTC(),
|
||||
*req.Options.TimeUnit,
|
||||
))
|
||||
fos = append(fos, pilosa.OptFieldTypeTimestamp(req.Options.Epoch.UTC(), *req.Options.TimeUnit))
|
||||
case pilosa.FieldTypeTime:
|
||||
fos = append(fos, pilosa.OptFieldTypeTime(*req.Options.TimeQuantum, req.Options.NoStandardView))
|
||||
case pilosa.FieldTypeMutex:
|
||||
|
|
@ -1398,6 +1390,7 @@ type fieldOptions struct {
|
|||
Min *pql.Decimal `json:"min,omitempty"`
|
||||
Max *pql.Decimal `json:"max,omitempty"`
|
||||
Scale *int64 `json:"scale,omitempty"`
|
||||
Epoch *time.Time `json:"epoch,omitempty"`
|
||||
TimeUnit *string `json:"timeUnit,omitempty"`
|
||||
TimeQuantum *pilosa.TimeQuantum `json:"timeQuantum,omitempty"`
|
||||
Keys *bool `json:"keys,omitempty"`
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ func TestIndex_CreateField(t *testing.T) {
|
|||
defer index.Close()
|
||||
|
||||
// Create field with schema and verify it exists.
|
||||
if f, err := index.CreateField("f", pilosa.OptFieldTypeTimestamp(pilosa.MinTimestamp, pilosa.MaxTimestamp, pilosa.TimeUnitSeconds)); err != nil {
|
||||
if f, err := index.CreateField("f", pilosa.OptFieldTypeTimestamp(pilosa.DefaultEpoch, pilosa.TimeUnitSeconds)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !reflect.DeepEqual(f.Type(), pilosa.FieldTypeTimestamp) {
|
||||
t.Fatalf("unexpected type: %#v", f.Type())
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue