get.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /*
  2. * EliasDB
  3. *
  4. * Copyright 2016 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the Mozilla Public
  7. * License, v. 2.0. If a copy of the MPL was not distributed with this
  8. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. */
  10. package interpreter
  11. import (
  12. "devt.de/krotik/eliasdb/eql/parser"
  13. "devt.de/krotik/eliasdb/graph"
  14. )
  15. // Runtime provider for GET queries
  16. // ================================
  17. /*
  18. Instance function for GET query components
  19. */
  20. type getInst func(*GetRuntimeProvider, *parser.ASTNode) parser.Runtime
  21. /*
  22. Runtime map for GET query specific components
  23. */
  24. var getProviderMap = map[string]getInst{
  25. parser.NodeGET: getRuntimeInst,
  26. }
  27. /*
  28. GetRuntimeProvider data structure
  29. */
  30. type GetRuntimeProvider struct {
  31. *eqlRuntimeProvider
  32. }
  33. /*
  34. NewGetRuntimeProvider creates a new GetRuntimeProvider object. This provider
  35. can interpret GET queries.
  36. */
  37. func NewGetRuntimeProvider(name string, part string, gm *graph.Manager, ni NodeInfo) *GetRuntimeProvider {
  38. return &GetRuntimeProvider{&eqlRuntimeProvider{name, part, gm, ni, "", false, nil, "",
  39. nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil}}
  40. }
  41. /*
  42. Runtime returns a runtime component for a given ASTNode.
  43. */
  44. func (rtp *GetRuntimeProvider) Runtime(node *parser.ASTNode) parser.Runtime {
  45. if pinst, ok := generalProviderMap[node.Name]; ok {
  46. return pinst(rtp.eqlRuntimeProvider, node)
  47. } else if pinst, ok := getProviderMap[node.Name]; ok {
  48. return pinst(rtp, node)
  49. }
  50. return invalidRuntimeInst(rtp.eqlRuntimeProvider, node)
  51. }
  52. // GET Runtime
  53. // ===========
  54. type getRuntime struct {
  55. rtp *GetRuntimeProvider
  56. node *parser.ASTNode
  57. }
  58. func getRuntimeInst(rtp *GetRuntimeProvider, node *parser.ASTNode) parser.Runtime {
  59. return &getRuntime{rtp, node}
  60. }
  61. /*
  62. Validate and reset this runtime component and all its child components.
  63. */
  64. func (rt *getRuntime) Validate() error {
  65. // First child is always the first node kind to query
  66. // (validation of this value was done during lexing)
  67. startKind := rt.node.Children[0].Token.Val
  68. initErr := rt.rtp.init(startKind, rt.node.Children[1:])
  69. if rt.rtp.groupScope == "" {
  70. // Start keys can be provided by a simple node key iterator
  71. startKeyIterator, err := rt.rtp.gm.NodeKeyIterator(rt.rtp.part, startKind)
  72. if err != nil {
  73. return err
  74. } else if startKeyIterator == nil {
  75. return rt.rtp.newRuntimeError(ErrUnknownNodeKind, startKind, rt.node.Children[0])
  76. }
  77. rt.rtp.nextStartKey = func() (string, error) {
  78. nextKey := startKeyIterator.Next()
  79. if startKeyIterator.LastError != nil {
  80. return "", startKeyIterator.LastError
  81. }
  82. return nextKey, nil
  83. }
  84. } else {
  85. // Try to lookup group node
  86. nodes, _, err := rt.rtp.gm.TraverseMulti(rt.rtp.part, rt.rtp.groupScope,
  87. GroupNodeKind, ":::"+startKind, false)
  88. if err != nil {
  89. return err
  90. }
  91. nodePtr := len(nodes)
  92. // Iterate over all traversed nodes
  93. rt.rtp.nextStartKey = func() (string, error) {
  94. nodePtr--
  95. if nodePtr >= 0 {
  96. return nodes[nodePtr].Key(), nil
  97. }
  98. return "", nil
  99. }
  100. }
  101. return initErr
  102. }
  103. /*
  104. Eval evaluate this runtime component.
  105. */
  106. func (rt *getRuntime) Eval() (interface{}, error) {
  107. // First validate the query and reset the runtime provider datastructures
  108. if rt.rtp.specs == nil || !allowMultiEval {
  109. if err := rt.Validate(); err != nil {
  110. return nil, err
  111. }
  112. }
  113. return rt.gaterResult(rt.node)
  114. }
  115. func (rt *getRuntime) gaterResult(topNode *parser.ASTNode) (interface{}, error) {
  116. // Generate query
  117. query, err := parser.PrettyPrint(topNode)
  118. // Create result object
  119. res := newSearchResult(rt.rtp.eqlRuntimeProvider, query)
  120. if err == nil {
  121. var more bool
  122. // Go through all rows
  123. more, err = rt.rtp.next()
  124. for more && err == nil {
  125. // Add row to the result
  126. if err := res.addRow(rt.rtp.rowNode, rt.rtp.rowEdge); err != nil {
  127. return nil, err
  128. }
  129. // More on to the next row
  130. more, err = rt.rtp.next()
  131. }
  132. // Finish the result
  133. res.finish()
  134. }
  135. return res, err
  136. }