mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-08-01 02:11:15 -04:00
query.Normalize resolves field names (query.ResolveField, from the derived index + a small alias overlay) and expands media-type restrictions (mimetype.Expand) once, between parse and backend compilation.
74 lines
2.1 KiB
Go
74 lines
2.1 KiB
Go
package query
|
|
|
|
import (
|
|
"reflect"
|
|
|
|
"github.com/opencloud-eu/opencloud/pkg/ast"
|
|
"github.com/opencloud-eu/opencloud/services/search/pkg/query/mimetype"
|
|
)
|
|
|
|
// Normalize is the shared KQL lowering pass between parse and compile: it
|
|
// resolves keys to real field names (via resolve) and expands media-type
|
|
// restrictions, so the backends compile a plain field:value AST.
|
|
func Normalize(a *ast.Ast, resolve func(string) string) *ast.Ast {
|
|
a.Nodes = normalizeNodes(a.Nodes, resolve, "")
|
|
return a
|
|
}
|
|
|
|
// normalizeNodes rewrites nodes in place. defaultKey is what a bare restriction
|
|
// inherits: its enclosing group's key, or "" at the top level.
|
|
func normalizeNodes(nodes []ast.Node, resolve func(string) string, defaultKey string) []ast.Node {
|
|
resolveKey := func(key string) string {
|
|
if key == "" && defaultKey != "" {
|
|
return defaultKey // bare child inherits the group key
|
|
}
|
|
return resolve(key)
|
|
}
|
|
|
|
out := make([]ast.Node, 0, len(nodes))
|
|
for _, n := range nodes {
|
|
n = toPointer(n) // ensure a pointer so in-place key rewrites persist
|
|
switch node := n.(type) {
|
|
case *ast.StringNode:
|
|
node.Key = resolveKey(node.Key)
|
|
if exp := mimetype.Expand(node.Key, node.Value); exp != nil {
|
|
out = append(out, normalizeNodes(exp, resolve, defaultKey)...)
|
|
continue
|
|
}
|
|
out = append(out, node)
|
|
case *ast.DateTimeNode:
|
|
node.Key = resolveKey(node.Key)
|
|
out = append(out, node)
|
|
case *ast.BooleanNode:
|
|
node.Key = resolveKey(node.Key)
|
|
out = append(out, node)
|
|
case *ast.GroupNode:
|
|
groupKey := defaultKey
|
|
if node.Key != "" {
|
|
node.Key = resolve(node.Key)
|
|
groupKey = node.Key
|
|
}
|
|
node.Nodes = normalizeNodes(node.Nodes, resolve, groupKey)
|
|
out = append(out, node)
|
|
default:
|
|
out = append(out, n)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
// toPointer returns n as a pointer; the parser emits some nodes by value and the
|
|
// in-place key rewrites would be lost on those.
|
|
func toPointer(n ast.Node) ast.Node {
|
|
rv := reflect.ValueOf(n)
|
|
if rv.Kind() == reflect.Ptr {
|
|
return n
|
|
}
|
|
ptr := reflect.New(rv.Type())
|
|
ptr.Elem().Set(rv)
|
|
if pn, ok := ptr.Interface().(ast.Node); ok {
|
|
return pn
|
|
}
|
|
return n
|
|
}
|