-
Notifications
You must be signed in to change notification settings - Fork 560
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
It's now possible to do: SCAN fleet WHERE "properties.speed < 25 || properties.speed > 50" Uses javascript-like syntax using the https://github.com/tidwall/expr package. Automatically reference fields and GeoJSON properties: SET fleet truck1 FIELD speed 65 POINT -112 33 Can be queried: SCAN fleet WHERE "speed > 50" SCAN fleet WHERE "id == 'truck1'" SCAN fleet WHERE "speed > 50 && id == 'truck1'"
- Loading branch information
Showing
8 changed files
with
227 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
package server | ||
|
||
import ( | ||
"sync" | ||
|
||
"github.com/tidwall/expr" | ||
"github.com/tidwall/geojson" | ||
"github.com/tidwall/gjson" | ||
"github.com/tidwall/tile38/internal/field" | ||
"github.com/tidwall/tile38/internal/object" | ||
) | ||
|
||
type exprPool struct { | ||
pool *sync.Pool | ||
} | ||
|
||
func typeForObject(o *object.Object) expr.Value { | ||
switch o.Geo().(type) { | ||
case *geojson.Point, *geojson.SimplePoint: | ||
return expr.String("Point") | ||
case *geojson.LineString: | ||
return expr.String("LineString") | ||
case *geojson.Polygon, *geojson.Circle, *geojson.Rect: | ||
return expr.String("Polygon") | ||
case *geojson.MultiPoint: | ||
return expr.String("MultiPoint") | ||
case *geojson.MultiLineString: | ||
return expr.String("MultiLineString") | ||
case *geojson.MultiPolygon: | ||
return expr.String("MultiPolygon") | ||
case *geojson.GeometryCollection: | ||
return expr.String("GeometryCollection") | ||
case *geojson.Feature: | ||
return expr.String("Feature") | ||
case *geojson.FeatureCollection: | ||
return expr.String("FeatureCollection") | ||
default: | ||
return expr.Undefined | ||
} | ||
} | ||
|
||
func resultToValue(r gjson.Result) expr.Value { | ||
if !r.Exists() { | ||
return expr.Undefined | ||
} | ||
switch r.Type { | ||
case gjson.String: | ||
return expr.String(r.String()) | ||
case gjson.False: | ||
return expr.Bool(false) | ||
case gjson.True: | ||
return expr.Bool(true) | ||
case gjson.Number: | ||
return expr.Number(r.Float()) | ||
case gjson.JSON: | ||
return expr.String(r.String()) | ||
default: | ||
return expr.Null | ||
} | ||
} | ||
|
||
func newExprPool(s *Server) *exprPool { | ||
ext := expr.NewExtender( | ||
// ref | ||
func(info expr.RefInfo, ctx *expr.Context) (expr.Value, error) { | ||
o := ctx.UserData.(*object.Object) | ||
if !info.Chain { | ||
// root | ||
if r := gjson.Get(o.Geo().Members(), info.Ident); r.Exists() { | ||
return resultToValue(r), nil | ||
} | ||
switch info.Ident { | ||
case "id": | ||
return expr.String(o.ID()), nil | ||
case "type": | ||
return typeForObject(o), nil | ||
default: | ||
var rf field.Field | ||
var ok bool | ||
o.Fields().Scan(func(f field.Field) bool { | ||
if f.Name() == info.Ident { | ||
rf = f | ||
ok = true | ||
return false | ||
} | ||
return true | ||
}) | ||
if ok { | ||
r := gjson.Parse(rf.Value().JSON()) | ||
return resultToValue(r), nil | ||
} | ||
} | ||
} else { | ||
switch info.Value.Value().(type) { | ||
case string: | ||
r := gjson.Get(info.Value.String(), info.Ident) | ||
return resultToValue(r), nil | ||
} | ||
} | ||
return expr.Undefined, nil | ||
}, | ||
// call | ||
func(info expr.CallInfo, ctx *expr.Context) (expr.Value, error) { | ||
// No custom calls | ||
return expr.Undefined, nil | ||
}, | ||
// op | ||
func(info expr.OpInfo, ctx *expr.Context) (expr.Value, error) { | ||
// No custom operations | ||
return expr.Undefined, nil | ||
}, | ||
) | ||
return &exprPool{ | ||
pool: &sync.Pool{ | ||
New: func() any { | ||
ctx := &expr.Context{ | ||
Extender: ext, | ||
} | ||
return ctx | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func (p *exprPool) Get(o *object.Object) *expr.Context { | ||
ctx := p.pool.Get().(*expr.Context) | ||
ctx.UserData = o | ||
return ctx | ||
} | ||
|
||
func (p *exprPool) Put(ctx *expr.Context) { | ||
p.pool.Put(ctx) | ||
} | ||
|
||
func (where whereT) matchExpr(s *Server, o *object.Object) bool { | ||
ctx := s.epool.Get(o) | ||
res, _ := expr.Eval(where.name, ctx) | ||
s.epool.Put(ctx) | ||
return res.Bool() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters