mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-09-06 00:25:55 +00:00
Merge pull request #1563 from 54mir/timestamp-in-orm
Replicate timefield functionality in pilosaclient
This commit is contained in:
commit
da749cc757
2 changed files with 107 additions and 3 deletions
|
|
@ -793,6 +793,7 @@ type FieldOptions struct {
|
|||
keys bool
|
||||
noStandardView bool
|
||||
foreignIndex string
|
||||
timeUnit string
|
||||
}
|
||||
|
||||
// Type returns the type of the field. Currently "set", "int", or "time".
|
||||
|
|
@ -841,6 +842,10 @@ func (fo FieldOptions) ForeignIndex() string {
|
|||
return fo.foreignIndex
|
||||
}
|
||||
|
||||
func (fo FieldOptions) TimeUnit() string {
|
||||
return fo.timeUnit
|
||||
}
|
||||
|
||||
// NoStandardView suppresses creating the standard view for supported field types (currently, time)
|
||||
func (fo FieldOptions) NoStandardView() bool {
|
||||
return fo.noStandardView
|
||||
|
|
@ -877,6 +882,10 @@ func (fo FieldOptions) String() string {
|
|||
case FieldTypeTime:
|
||||
mopt["timeQuantum"] = string(fo.timeQuantum)
|
||||
mopt["noStandardView"] = fo.noStandardView
|
||||
case FieldTypeTimestamp:
|
||||
mopt["min"] = fo.min
|
||||
mopt["max"] = fo.max
|
||||
mopt["timeUnit"] = fo.timeUnit
|
||||
}
|
||||
|
||||
if fo.fieldType != FieldTypeDefault {
|
||||
|
|
@ -900,6 +909,16 @@ func (fo *FieldOptions) addOptions(options ...FieldOption) {
|
|||
}
|
||||
}
|
||||
|
||||
// MinTimestamp returns the minimum value for a timestamp field.
|
||||
func (o FieldOptions) MinTimestamp() time.Time {
|
||||
return time.Unix(0, o.min.ToInt64(0)*int64(TimeUnitNano(o.TimeUnit())))
|
||||
}
|
||||
|
||||
// MaxTimestamp returns the maxnimum value for a timestamp field.
|
||||
func (o FieldOptions) MaxTimestamp() time.Time {
|
||||
return time.Unix(0, o.max.ToInt64(0)*int64(TimeUnitNano(o.TimeUnit())))
|
||||
}
|
||||
|
||||
// FieldOption is used to pass an option to index.Field function.
|
||||
type FieldOption func(options *FieldOptions)
|
||||
|
||||
|
|
@ -950,6 +969,18 @@ func OptFieldTypeTime(quantum TimeQuantum, opts ...bool) FieldOption {
|
|||
}
|
||||
}
|
||||
|
||||
func OptFieldTypeTimestamp(min, max time.Time, timeUnit string) FieldOption {
|
||||
return func(fo *FieldOptions) {
|
||||
minNano := min.UnixNano()
|
||||
maxNano := max.UnixNano()
|
||||
fo.fieldType = FieldTypeTimestamp
|
||||
fo.timeUnit = timeUnit
|
||||
fo.min = pql.NewDecimal(minNano, 0)
|
||||
fo.max = pql.NewDecimal(maxNano, 0)
|
||||
// fo.Base = bsiBase(minNano, maxNano)
|
||||
}
|
||||
}
|
||||
|
||||
// OptFieldTypeMutex adds a mutex field.
|
||||
func OptFieldTypeMutex(cacheType CacheType, cacheSize int) FieldOption {
|
||||
return func(options *FieldOptions) {
|
||||
|
|
@ -1287,7 +1318,8 @@ const (
|
|||
// FieldTypeDecimal can store floating point numbers as integers
|
||||
// with a scale factor. This field type is only available in
|
||||
// Molecula's Pilosa with enterprise extensions.
|
||||
FieldTypeDecimal FieldType = "decimal"
|
||||
FieldTypeDecimal FieldType = "decimal"
|
||||
FieldTypeTimestamp FieldType = "timestamp"
|
||||
)
|
||||
|
||||
// TimeQuantum type represents valid time quantum values time fields.
|
||||
|
|
@ -1308,6 +1340,28 @@ const (
|
|||
TimeQuantumYearMonthDayHour TimeQuantum = "YMDH"
|
||||
)
|
||||
|
||||
// List of time units.
|
||||
const (
|
||||
TimeUnitSeconds = "s"
|
||||
TimeUnitMilliseconds = "ms"
|
||||
TimeUnitMicroseconds = "µs"
|
||||
TimeUnitNanoseconds = "ns"
|
||||
)
|
||||
|
||||
// TimeUnitNano returns the number of nanoseconds in unit.
|
||||
func TimeUnitNano(unit string) int64 {
|
||||
switch unit {
|
||||
case TimeUnitSeconds:
|
||||
return int64(time.Second)
|
||||
case TimeUnitMilliseconds:
|
||||
return int64(time.Millisecond)
|
||||
case TimeUnitMicroseconds:
|
||||
return int64(time.Microsecond)
|
||||
default:
|
||||
return int64(time.Nanosecond)
|
||||
}
|
||||
}
|
||||
|
||||
// CacheType represents cache type for a field
|
||||
type CacheType string
|
||||
|
||||
|
|
|
|||
|
|
@ -1022,6 +1022,7 @@ func TestORM(t *testing.T) {
|
|||
9999,
|
||||
pql.NewDecimal(0, 0),
|
||||
pql.NewDecimal(0, 0),
|
||||
"",
|
||||
"")
|
||||
})
|
||||
|
||||
|
|
@ -1040,6 +1041,7 @@ func TestORM(t *testing.T) {
|
|||
0,
|
||||
pql.NewDecimal(-10, 0),
|
||||
pql.NewDecimal(100, 0),
|
||||
"",
|
||||
"")
|
||||
|
||||
field = sampleIndex.Field("int-field2", OptFieldTypeInt(-10))
|
||||
|
|
@ -1057,6 +1059,7 @@ func TestORM(t *testing.T) {
|
|||
0,
|
||||
pql.NewDecimal(-10, 0),
|
||||
pql.NewDecimal(math.MaxInt64, 0),
|
||||
"",
|
||||
"")
|
||||
field = sampleIndex.Field("int-field3", OptFieldTypeInt())
|
||||
jsonString = field.options.String()
|
||||
|
|
@ -1072,6 +1075,7 @@ func TestORM(t *testing.T) {
|
|||
0,
|
||||
pql.NewDecimal(math.MinInt64, 0),
|
||||
pql.NewDecimal(math.MaxInt64, 0),
|
||||
"",
|
||||
"")
|
||||
|
||||
field = sampleIndex.Field("int-field4", OptFieldTypeInt(), OptFieldForeignIndex("blerg"))
|
||||
|
|
@ -1088,7 +1092,8 @@ func TestORM(t *testing.T) {
|
|||
0,
|
||||
pql.NewDecimal(math.MinInt64, 0),
|
||||
pql.NewDecimal(math.MaxInt64, 0),
|
||||
"blerg")
|
||||
"blerg",
|
||||
"")
|
||||
})
|
||||
|
||||
t.Run("TimeFieldOptions", func(t *testing.T) {
|
||||
|
|
@ -1109,6 +1114,7 @@ func TestORM(t *testing.T) {
|
|||
0,
|
||||
pql.NewDecimal(0, 0),
|
||||
pql.NewDecimal(0, 0),
|
||||
"",
|
||||
"")
|
||||
})
|
||||
|
||||
|
|
@ -1127,6 +1133,7 @@ func TestORM(t *testing.T) {
|
|||
9999,
|
||||
pql.NewDecimal(0, 0),
|
||||
pql.NewDecimal(0, 0),
|
||||
"",
|
||||
"")
|
||||
})
|
||||
|
||||
|
|
@ -1145,6 +1152,7 @@ func TestORM(t *testing.T) {
|
|||
0,
|
||||
pql.NewDecimal(0, 0),
|
||||
pql.NewDecimal(0, 0),
|
||||
"",
|
||||
"")
|
||||
})
|
||||
|
||||
|
|
@ -1163,9 +1171,48 @@ func TestORM(t *testing.T) {
|
|||
0,
|
||||
pql.NewDecimal(7, 3),
|
||||
pql.NewDecimal(999, 3),
|
||||
"",
|
||||
"")
|
||||
})
|
||||
|
||||
t.Run("DecimalFieldOptions", func(t *testing.T) {
|
||||
field := sampleIndex.Field("decimal-field", OptFieldTypeDecimal(3, pql.NewDecimal(7, 3), pql.NewDecimal(999, 3)))
|
||||
jsonString := field.options.String()
|
||||
targetString := `{"options":{"type":"decimal","scale":3,"max":0.999,"min":0.007}}`
|
||||
if sortedString(targetString) != sortedString(jsonString) {
|
||||
t.Fatalf("`%s` != `%s`", targetString, jsonString)
|
||||
}
|
||||
compareFieldOptions(t,
|
||||
field.Options(),
|
||||
FieldTypeDecimal,
|
||||
TimeQuantumNone,
|
||||
CacheTypeDefault,
|
||||
0,
|
||||
pql.NewDecimal(7, 3),
|
||||
pql.NewDecimal(999, 3),
|
||||
"",
|
||||
"")
|
||||
})
|
||||
|
||||
t.Run("TimestampFieldOptions", func(t *testing.T) {
|
||||
field := sampleIndex.Field("timestamp-field", OptFieldTypeTimestamp(time.Unix(0, 2), time.Unix(0, 5000), "s"))
|
||||
jsonString := field.options.String()
|
||||
targetString := `{"options":{"type":"timestamp","timeUnit":"s","max":5000,"min":2}}`
|
||||
if sortedString(targetString) != sortedString(jsonString) {
|
||||
t.Fatalf("`%s` != `%s`", targetString, jsonString)
|
||||
}
|
||||
compareFieldOptions(t,
|
||||
field.Options(),
|
||||
FieldTypeTimestamp,
|
||||
TimeQuantumNone,
|
||||
CacheTypeDefault,
|
||||
0,
|
||||
pql.NewDecimal(2, 0),
|
||||
pql.NewDecimal(5000, 0),
|
||||
"",
|
||||
"s")
|
||||
})
|
||||
|
||||
t.Run("EncodeMapPanicsOnMarshalFailure", func(t *testing.T) {
|
||||
defer func() {
|
||||
_ = recover()
|
||||
|
|
@ -1211,7 +1258,7 @@ func comparePQL(t *testing.T, target string, q PQLQuery) {
|
|||
}
|
||||
}
|
||||
|
||||
func compareFieldOptions(t *testing.T, opts *FieldOptions, fieldType FieldType, timeQuantum TimeQuantum, cacheType CacheType, cacheSize int, min pql.Decimal, max pql.Decimal, foreignIndex string) {
|
||||
func compareFieldOptions(t *testing.T, opts *FieldOptions, fieldType FieldType, timeQuantum TimeQuantum, cacheType CacheType, cacheSize int, min pql.Decimal, max pql.Decimal, foreignIndex string, timeUnit string) {
|
||||
if fieldType != opts.Type() {
|
||||
t.Fatalf("%s != %s", fieldType, opts.Type())
|
||||
}
|
||||
|
|
@ -1233,6 +1280,9 @@ func compareFieldOptions(t *testing.T, opts *FieldOptions, fieldType FieldType,
|
|||
if foreignIndex != opts.ForeignIndex() {
|
||||
t.Fatalf("%s != %s", foreignIndex, opts.ForeignIndex())
|
||||
}
|
||||
if timeUnit != opts.TimeUnit() {
|
||||
t.Fatalf("%s != %s", timeUnit, opts.TimeUnit())
|
||||
}
|
||||
}
|
||||
|
||||
func sortedString(s string) string {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue