query.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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. /*
  11. Package eql contains the main API for EQL.
  12. Example EQL query:
  13. GET Person where name = "Marvin"
  14. */
  15. package eql
  16. import (
  17. "strings"
  18. "devt.de/krotik/eliasdb/eql/interpreter"
  19. "devt.de/krotik/eliasdb/eql/parser"
  20. "devt.de/krotik/eliasdb/graph"
  21. )
  22. /*
  23. GroupNodeKind is a special node kind representing groups
  24. */
  25. const GroupNodeKind = interpreter.GroupNodeKind
  26. /*
  27. RunQuery runs a search query against a given graph database.
  28. */
  29. func RunQuery(name string, part string, query string, gm *graph.Manager) (SearchResult, error) {
  30. return RunQueryWithNodeInfo(name, part, query, gm, interpreter.NewDefaultNodeInfo(gm))
  31. }
  32. /*
  33. RunQueryWithNodeInfo runs a search query against a given graph database. Using
  34. a given NodeInfo object to retrieve rendering information.
  35. */
  36. func RunQueryWithNodeInfo(name string, part string, query string, gm *graph.Manager, ni interpreter.NodeInfo) (SearchResult, error) {
  37. var rtp parser.RuntimeProvider
  38. word := strings.ToLower(parser.FirstWord(query))
  39. if word == "get" {
  40. rtp = interpreter.NewGetRuntimeProvider(name, part, gm, ni)
  41. } else if word == "lookup" {
  42. rtp = interpreter.NewLookupRuntimeProvider(name, part, gm, ni)
  43. } else {
  44. return nil, &interpreter.RuntimeError{
  45. Source: name,
  46. Type: interpreter.ErrInvalidConstruct,
  47. Detail: "Unknown query type: " + word,
  48. Node: nil,
  49. Line: 1,
  50. Pos: 1,
  51. }
  52. }
  53. ast, err := parser.ParseWithRuntime(name, query, rtp)
  54. if err != nil {
  55. return nil, err
  56. }
  57. res, err := ast.Runtime.Eval()
  58. if err != nil {
  59. return nil, err
  60. }
  61. return &queryResult{res.(*interpreter.SearchResult)}, nil
  62. }
  63. /*
  64. ParseQuery parses a search query and return its Abstract Syntax Tree.
  65. */
  66. func ParseQuery(name string, query string) (*parser.ASTNode, error) {
  67. ast, err := parser.Parse(name, query)
  68. if err != nil {
  69. return nil, err
  70. }
  71. return ast, nil
  72. }
  73. /*
  74. queryResult datastructure to hide implementation details.
  75. */
  76. type queryResult struct {
  77. *interpreter.SearchResult
  78. }
  79. /*
  80. Header returns a data structure describing the result header.
  81. */
  82. func (qr *queryResult) Header() SearchResultHeader {
  83. return qr.SearchResult.Header()
  84. }