Skip to content

Commit

Permalink
Add support for external symbols to boltz stores. Fixes #76
Browse files Browse the repository at this point in the history
  • Loading branch information
plorenz committed Jul 12, 2024
1 parent 007260d commit cc29b37
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 11 deletions.
1 change: 1 addition & 0 deletions boltz/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ type ConfigurableStore interface {
AddPublicSetSymbol(name string, nodeType ast.NodeType) EntitySetSymbol
AddFkSetSymbol(name string, linkedType Store) EntitySetSymbol
NewEntitySymbol(name string, nodeType ast.NodeType) EntitySymbol
AddEntitySymbol(symbol EntitySymbol)

AddExtEntitySymbols()
MakeSymbolPublic(name string)
Expand Down
72 changes: 72 additions & 0 deletions boltz/external_symbol.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package boltz

import (
"github.com/openziti/storage/ast"
"go.etcd.io/bbolt"
)

type ExternalSymbol struct {
store Store
name string
nodeType ast.NodeType
impl func(tx *bbolt.Tx, rowId []byte) (FieldType, []byte)
}

func (self *ExternalSymbol) GetStore() Store {
return self.store
}

func (self *ExternalSymbol) GetLinkedType() Store {
return nil
}

func (self *ExternalSymbol) GetPath() []string {
return nil
}

func (self *ExternalSymbol) GetType() ast.NodeType {
return self.nodeType
}

func (self *ExternalSymbol) GetName() string {
return self.name
}

func (self *ExternalSymbol) IsSet() bool {
return false
}

func (self *ExternalSymbol) Eval(tx *bbolt.Tx, rowId []byte) (FieldType, []byte) {
return self.impl(tx, rowId)
}

func NewBoolFuncSymbol(store Store, name string, f func(id string) bool) EntitySymbol {
return &ExternalSymbol{
store: store,
name: name,
nodeType: ast.NodeTypeBool,
impl: func(tx *bbolt.Tx, rowId []byte) (FieldType, []byte) {
result := f(string(rowId))
buf := make([]byte, 1)
if result {
buf[0] = 1
}
return TypeBool, buf
},
}
}

func NewStringFuncSymbol(store Store, name string, f func(id string) *string) EntitySymbol {
return &ExternalSymbol{
store: store,
name: name,
nodeType: ast.NodeTypeString,
impl: func(tx *bbolt.Tx, rowId []byte) (FieldType, []byte) {
result := f(string(rowId))
if result == nil {
return TypeString, nil
}
return TypeString, []byte(*result)
},
}
}
3 changes: 1 addition & 2 deletions boltz/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ func NewBaseStore[E Entity](definition StoreDefinition[E]) *BaseStore[E] {
entityStrategy: definition.EntityStrategy,
parent: definition.Parent,
parentMapper: definition.ParentMapper,
symbols: map[string]EntitySymbol{},
mapSymbols: map[string]*entityMapSymbol{},
publicSymbols: map[string]struct{}{},
Indexer: *NewIndexer(append(indexPath, IndexesBucket)...),
Expand Down Expand Up @@ -204,7 +203,7 @@ type BaseStore[E Entity] struct {
parentMapper func(childEntity Entity) Entity
entityType string
entityPath []string
symbols map[string]EntitySymbol
symbols concurrenz.CopyOnWriteMap[string, EntitySymbol]
publicSymbols map[string]struct{}
mapSymbols map[string]*entityMapSymbol
isExtended bool
Expand Down
22 changes: 13 additions & 9 deletions boltz/store_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func (store *BaseStore[E]) GetSymbol(name string) EntitySymbol {
4. Composite multi-value symbols (employee.directReports.phoneNumbers)
5. Maps (employee.tags.location, employee.manager.tags.location, employee.directReports.tags.location)
*/
if result := store.symbols[name]; result != nil {
if result := store.symbols.Get(name); result != nil {
// If it's a set symbol, make a runtime copy so we don't share cursor data. If we ever have a case where we
// are evaluating the same symbol in multiple context, this will still break, but since currently any given
// expression only involves a single symbol, this should not be a problem
Expand Down Expand Up @@ -178,7 +178,7 @@ func (store *BaseStore[E]) createCompositeEntitySymbol(name string, first linked
}

func (store *BaseStore[E]) addSymbol(name string, public bool, symbol EntitySymbol) EntitySymbol {
store.symbols[name] = symbol
store.symbols.Put(name, symbol)
if public {
store.publicSymbols[name] = struct{}{}
}
Expand All @@ -190,7 +190,7 @@ func (store *BaseStore[E]) inheritMapSymbol(symbol *entityMapSymbol) {
}

func (store *BaseStore[E]) GrantSymbols(child ConfigurableStore) {
for name, value := range store.symbols {
for name, value := range store.symbols.AsMap() {
child.addSymbol(name, store.IsPublicSymbol(name), value)
}
for name, value := range store.mapSymbols {
Expand All @@ -210,11 +210,11 @@ func (store *BaseStore[E]) AddIdSymbol(name string, nodeType ast.NodeType) Entit
}

func (store *BaseStore[E]) MapSymbol(name string, mapper SymbolMapper) {
if symbol, found := store.symbols[name]; found {
store.symbols[name] = &symbolMapWrapper{
if symbol := store.symbols.Get(name); symbol != nil {
store.symbols.Put(name, &symbolMapWrapper{
EntitySymbol: symbol,
SymbolMapper: mapper,
}
})
}
}

Expand Down Expand Up @@ -242,6 +242,10 @@ func (store *BaseStore[E]) AddMapSymbol(name string, nodeType ast.NodeType, key
}
}

func (store *BaseStore[E]) AddEntitySymbol(symbol EntitySymbol) {
store.symbols.Put(symbol.GetName(), symbol)
}

func (store *BaseStore[E]) NewEntitySymbol(name string, nodeType ast.NodeType) EntitySymbol {
return store.newEntitySymbol(name, nodeType, name, nil)
}
Expand Down Expand Up @@ -297,7 +301,7 @@ func (store *BaseStore[E]) addSetSymbol(name string, nodeType ast.NodeType, list
result := &entitySetSymbolImpl{
entitySymbol: entitySymbol,
}
store.symbols[name] = result
store.symbols.Put(name, result)
return result
}

Expand Down Expand Up @@ -331,9 +335,9 @@ func (store *BaseStore[E]) newRowComparator(sort []ast.SortField) (RowComparator

var symbolsComparators []symbolComparator
for _, sortField := range sort {
symbol, found := store.symbols[sortField.Symbol()]
symbol := store.symbols.Get(sortField.Symbol())
forward := sortField.IsAscending()
if !found {
if symbol == nil {
return nil, errors.Errorf("no such sort field: %v", sortField.Symbol())
}
if symbol.IsSet() {
Expand Down

0 comments on commit cc29b37

Please sign in to comment.