123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- /*
- * EliasDB
- *
- * Copyright 2016 Matthias Ladkau. All rights reserved.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
- package interpreter
- import (
- "devt.de/krotik/eliasdb/eql/parser"
- "devt.de/krotik/eliasdb/graph"
- )
- // Runtime provider for LOOKUP queries
- // ===================================
- /*
- Instance function for LOOKUP query components
- */
- type lookupInst func(*LookupRuntimeProvider, *parser.ASTNode) parser.Runtime
- /*
- Runtime map for LOOKUP query specific components
- */
- var lookupProviderMap = map[string]lookupInst{
- parser.NodeLOOKUP: lookupRuntimeInst,
- }
- /*
- LookupRuntimeProvider data structure
- */
- type LookupRuntimeProvider struct {
- *eqlRuntimeProvider
- }
- /*
- NewLookupRuntimeProvider creates a new LookupRuntimeProvider object. This provider
- can interpret LOOKUP queries.
- */
- func NewLookupRuntimeProvider(name string, part string, gm *graph.Manager, ni NodeInfo) *LookupRuntimeProvider {
- return &LookupRuntimeProvider{&eqlRuntimeProvider{name, part, gm, ni, "", false, nil, "",
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil}}
- }
- /*
- Runtime returns a runtime component for a given ASTNode.
- */
- func (rtp *LookupRuntimeProvider) Runtime(node *parser.ASTNode) parser.Runtime {
- if pinst, ok := generalProviderMap[node.Name]; ok {
- return pinst(rtp.eqlRuntimeProvider, node)
- } else if pinst, ok := lookupProviderMap[node.Name]; ok {
- return pinst(rtp, node)
- }
- return invalidRuntimeInst(rtp.eqlRuntimeProvider, node)
- }
- // LOOKUP Runtime
- // ==============
- type lookupRuntime struct {
- *getRuntime
- rtp *LookupRuntimeProvider
- node *parser.ASTNode
- }
- func lookupRuntimeInst(rtp *LookupRuntimeProvider, node *parser.ASTNode) parser.Runtime {
- return &lookupRuntime{&getRuntime{&GetRuntimeProvider{rtp.eqlRuntimeProvider}, node}, rtp, node}
- }
- /*
- Validate and reset this runtime component and all its child components.
- */
- func (rt *lookupRuntime) Validate() error {
- // First child is always the first node kind to query
- // (validation of this value was done during lexing)
- startKind := rt.node.Children[0].Token.Val
- // Check how many keys were given
- var keys []string
- // Assume initially that only keys where given
- initIndex := len(rt.node.Children) - 1
- for i, child := range rt.node.Children[1:] {
- if child.Token.ID != parser.TokenVALUE {
- // We have a first non-id child
- initIndex = i
- break
- } else {
- // Collect all given keys
- keys = append(keys, child.Token.Val)
- }
- }
- // Initialise the runtime provider
- initErr := rt.rtp.init(startKind, rt.node.Children[initIndex+1:])
- if rt.rtp.groupScope == "" {
- nodePtr := len(keys)
- if nodePtr > 0 {
- // Iterate over all traversed nodes
- rt.rtp.nextStartKey = func() (string, error) {
- nodePtr--
- if nodePtr >= 0 {
- return keys[nodePtr], nil
- }
- return "", nil
- }
- }
- } else {
- // Build a map of keys
- keyMap := make(map[string]string)
- for _, key := range keys {
- keyMap[key] = ""
- }
- // Try to lookup group node
- nodes, _, err := rt.rtp.gm.TraverseMulti(rt.rtp.part, rt.rtp.groupScope,
- GroupNodeKind, ":::"+startKind, false)
- if err != nil {
- return err
- }
- nodePtr := len(nodes)
- // Iterate over all traversed nodes
- rt.rtp.nextStartKey = func() (string, error) {
- nodePtr--
- if nodePtr >= 0 {
- nodeKey := nodes[nodePtr].Key()
- if _, ok := keyMap[nodeKey]; ok {
- return nodeKey, nil
- }
- return rt.rtp.nextStartKey()
- }
- return "", nil
- }
- }
- return initErr
- }
- /*
- Eval evaluate this runtime component.
- */
- func (rt *lookupRuntime) Eval() (interface{}, error) {
- if err := rt.Validate(); err != nil {
- return nil, err
- }
- return rt.getRuntime.gaterResult(rt.node)
- }
|