Merge pull request #1563 from 54mir/timestamp-in-orm

Replicate timefield functionality in pilosaclient
This commit is contained in:
Samir Patel 2021-04-09 13:36:39 -05:00 committed by GitHub
commit da749cc757
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 107 additions and 3 deletions

View file

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

View file

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