query.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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 graphql contains the main API for GraphQL.
  12. Example GraphQL query:
  13. {
  14. Person @withValue(name : "Marvin") {
  15. key
  16. kind
  17. name
  18. }
  19. }
  20. */
  21. package graphql
  22. import (
  23. "fmt"
  24. "devt.de/krotik/common/lang/graphql/parser"
  25. "devt.de/krotik/eliasdb/graph"
  26. "devt.de/krotik/eliasdb/graphql/interpreter"
  27. )
  28. /*
  29. RunQuery runs a GraphQL query against a given graph database. The query parameter
  30. needs to have the following fields:
  31. operationName - Operation to Execute (string)
  32. query - Query document (string)
  33. variables - Variables map (map[string]interface{})
  34. Set the readOnly flag if the query should only be allowed to do read operations.
  35. */
  36. func RunQuery(name string, part string, query map[string]interface{},
  37. gm *graph.Manager, callbackHandler interpreter.SubscriptionCallbackHandler,
  38. readOnly bool) (map[string]interface{}, error) {
  39. var ok bool
  40. var vars map[string]interface{}
  41. // Make sure all info is present on the query object
  42. for _, op := range []string{"operationName", "query", "variables"} {
  43. if _, ok := query[op]; !ok {
  44. return nil, fmt.Errorf("Mandatory field '%s' missing from query object", op)
  45. }
  46. }
  47. // Nil pointer become empty strings
  48. if query["operationName"] == nil {
  49. query["operationName"] = ""
  50. }
  51. if query["query"] == nil {
  52. query["query"] = ""
  53. }
  54. if vars, ok = query["variables"].(map[string]interface{}); !ok {
  55. vars = make(map[string]interface{})
  56. }
  57. // Create runtime provider
  58. rtp := interpreter.NewGraphQLRuntimeProvider(name, part, gm,
  59. fmt.Sprint(query["operationName"]), vars, callbackHandler, readOnly)
  60. // Parse the query and annotate the AST with runtime components
  61. ast, err := parser.ParseWithRuntime(name, fmt.Sprint(query["query"]), rtp)
  62. if err == nil {
  63. if err = ast.Runtime.Validate(); err == nil {
  64. // Evaluate the query
  65. return ast.Runtime.Eval()
  66. }
  67. }
  68. return nil, err
  69. }
  70. /*
  71. ParseQuery parses a GraphQL query and return its Abstract Syntax Tree.
  72. */
  73. func ParseQuery(name string, query string) (*parser.ASTNode, error) {
  74. ast, err := parser.ParseWithRuntime(name, query, nil)
  75. if err != nil {
  76. return nil, err
  77. }
  78. return ast, nil
  79. }