selectionset.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  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. "fmt"
  13. "regexp"
  14. "strconv"
  15. "strings"
  16. "devt.de/krotik/common/lang/graphql/parser"
  17. "devt.de/krotik/common/stringutil"
  18. "devt.de/krotik/eliasdb/graph"
  19. "devt.de/krotik/eliasdb/graph/data"
  20. )
  21. // SelectionSet Runtime
  22. // ====================
  23. /*
  24. Runtime for SelectionSets.
  25. */
  26. type selectionSetRuntime struct {
  27. *invalidRuntime
  28. rtp *GraphQLRuntimeProvider
  29. node *parser.ASTNode
  30. }
  31. /*
  32. selectionSetRuntimeInst returns a new runtime component instance.
  33. */
  34. func selectionSetRuntimeInst(rtp *GraphQLRuntimeProvider, node *parser.ASTNode) parser.Runtime {
  35. return &selectionSetRuntime{&invalidRuntime{rtp, node}, rtp, node}
  36. }
  37. /*
  38. Eval evaluate this runtime component.
  39. */
  40. func (rt *selectionSetRuntime) Eval() (map[string]interface{}, error) {
  41. var err error
  42. // Build result data
  43. res := make(map[string]interface{})
  44. for _, c := range rt.node.Children {
  45. // Lookup nodes
  46. if c.Name == parser.NodeField {
  47. field := c.Runtime.(*fieldRuntime)
  48. if field.Name() == "__schema" {
  49. // We have an introspection query - handle this one in a special way
  50. res[field.Alias()] = field.SelectionSetRuntime().ProcessIntrospection()
  51. } else if field.SelectionSetRuntime() != nil {
  52. nodes := field.SelectionSetRuntime().ProcessNodes([]string{field.Alias()},
  53. field.Name(), field.Arguments(), nil)
  54. res[field.Alias()] = nodes
  55. }
  56. }
  57. }
  58. return res, err
  59. }
  60. /*
  61. nodeIterator is an object which can iterate over nodes.
  62. */
  63. type nodeIterator interface {
  64. Next() (string, string)
  65. HasNext() bool
  66. Error() error
  67. }
  68. /*
  69. nodeKeyIteratorWrapper wraps around a normal node key iterator.
  70. */
  71. type nodeKeyIteratorWrapper struct {
  72. kind string
  73. *graph.NodeKeyIterator
  74. }
  75. func (ni *nodeKeyIteratorWrapper) Next() (string, string) {
  76. return ni.NodeKeyIterator.Next(), ni.kind
  77. }
  78. /*
  79. traversalIterator contains a traversal result.
  80. */
  81. type traversalIterator struct {
  82. index int
  83. nodeList []data.Node
  84. }
  85. func (ti *traversalIterator) Next() (string, string) {
  86. next := ti.nodeList[ti.index]
  87. ti.index++
  88. return next.Key(), next.Kind()
  89. }
  90. func (ti *traversalIterator) HasNext() bool {
  91. return ti.index < len(ti.nodeList)
  92. }
  93. func (ti *traversalIterator) Error() error {
  94. return nil
  95. }
  96. func (rt *selectionSetRuntime) checkArgs(path []string, args map[string]interface{}) {
  97. knownArgs := []string{"key", "matches", "traverse", "storeNode",
  98. "storeEdge", "removeNode", "removeEdge", "ascending", "descending",
  99. "from", "items", "last"}
  100. for arg := range args {
  101. if stringutil.IndexOf(arg, knownArgs) == -1 {
  102. rt.rtp.handleRuntimeError(fmt.Errorf("Unknown argument: %s", arg),
  103. path, rt.node)
  104. }
  105. }
  106. }
  107. /*
  108. ProcessNodes uses the selection set to lookup/store nodes. Kind is not set during a
  109. traversal.
  110. */
  111. func (rt *selectionSetRuntime) ProcessNodes(path []string, kind string,
  112. args map[string]interface{}, it nodeIterator) []map[string]interface{} {
  113. var from, items, last int
  114. var ascending, descending string
  115. var err error
  116. res := make([]map[string]interface{}, 0)
  117. // Get only the attributes which were specified
  118. attrs, aliasMap, traversalMap := rt.GetPlainFieldsAndAliases(path, kind)
  119. addToRes := func(node data.Node) error {
  120. var err error
  121. r := make(map[string]interface{})
  122. for alias, attr := range aliasMap {
  123. if err == nil {
  124. if traversal, ok := traversalMap[alias]; ok {
  125. nodes, _, err := rt.rtp.gm.TraverseMulti(rt.rtp.part,
  126. node.Key(), node.Kind(), traversal.spec, false)
  127. if err == nil {
  128. data.NodeSort(nodes)
  129. r[alias] = traversal.selectionSetRuntime.ProcessNodes(
  130. append(path, traversal.spec), "", traversal.args,
  131. &traversalIterator{0, nodes})
  132. }
  133. } else {
  134. r[alias] = node.Attr(attr)
  135. }
  136. }
  137. }
  138. if err == nil {
  139. res = append(res, r)
  140. }
  141. return err
  142. }
  143. // Check arguments
  144. rt.checkArgs(path, args)
  145. if it == nil {
  146. err = rt.handleMutationArgs(path, args, kind)
  147. }
  148. if err == nil {
  149. ascending, descending, from, items, last, err = rt.handleOutputArgs(args)
  150. if err == nil {
  151. if key, ok := args["key"]; ok && it == nil {
  152. var node data.Node
  153. // Lookup a single node
  154. if node, err = rt.rtp.FetchNode(rt.rtp.part, fmt.Sprint(key), kind); err == nil && node != nil {
  155. addToRes(node)
  156. }
  157. } else {
  158. matchesRegexMap := make(map[string]*regexp.Regexp)
  159. matchAttrs := make([]string, 0)
  160. // Handle matches expression
  161. matches, matchesOk := args["matches"]
  162. matchesMap, matchesMapOk := matches.(map[string]interface{})
  163. if matchesOk {
  164. if matchesMapOk {
  165. for k, v := range matchesMap {
  166. matchAttrs = append(matchAttrs, k)
  167. if re, rerr := regexp.Compile(fmt.Sprint(v)); rerr == nil {
  168. matchesRegexMap[k] = re
  169. } else {
  170. rt.rtp.handleRuntimeError(fmt.Errorf("Regex %s did not compile: %s", v, rerr.Error()),
  171. path, rt.node)
  172. }
  173. }
  174. } else {
  175. rt.rtp.handleRuntimeError(fmt.Errorf("Matches expression is not a map"),
  176. path, rt.node)
  177. }
  178. }
  179. // Lookup a list of nodes
  180. if it == nil {
  181. var kit *graph.NodeKeyIterator
  182. kit, err = rt.rtp.gm.NodeKeyIterator(rt.rtp.part, kind)
  183. if kit != nil {
  184. it = &nodeKeyIteratorWrapper{kind, kit}
  185. }
  186. }
  187. if it != nil && err == nil {
  188. for err == nil && it.HasNext() {
  189. var node data.Node
  190. if err = it.Error(); err == nil {
  191. nkey, nkind := it.Next()
  192. if kind == "" {
  193. // If the kind is not fixed we need to reevaluate the attributes
  194. // to query for every node
  195. attrs, aliasMap, traversalMap = rt.GetPlainFieldsAndAliases(path, nkind)
  196. }
  197. if node, err = rt.rtp.FetchNodePart(rt.rtp.part, nkey,
  198. nkind, append(attrs, matchAttrs...)); err == nil && node != nil {
  199. if matchesOk && !rt.matchNode(node, matchesRegexMap) {
  200. continue
  201. }
  202. err = addToRes(node)
  203. }
  204. }
  205. }
  206. }
  207. }
  208. // Check if the result should be sorted
  209. if err == nil {
  210. if _, aok := args["ascending"]; aok {
  211. dataSort(res, ascending, true)
  212. } else if _, dok := args["descending"]; dok {
  213. dataSort(res, descending, false)
  214. }
  215. }
  216. // Check if the result should be truncated
  217. if last > 0 && last < len(res) {
  218. res = res[len(res)-last:]
  219. }
  220. if from > 0 || items > 0 {
  221. if from >= len(res) {
  222. from = 0
  223. }
  224. if from+items > len(res) {
  225. res = res[from:]
  226. } else {
  227. res = res[from : from+items]
  228. }
  229. }
  230. }
  231. }
  232. rt.rtp.handleRuntimeError(err, path, rt.node)
  233. return res
  234. }
  235. /*
  236. handleOutputModifyingArgs handles arguments which modify the output presentation.
  237. */
  238. func (rt *selectionSetRuntime) handleOutputArgs(args map[string]interface{}) (string, string, int, int, int, error) {
  239. var from, items, last int
  240. var ascending, descending string
  241. var err error
  242. ascendingData, aok := args["ascending"]
  243. descendingData, dok := args["descending"]
  244. if aok && dok {
  245. err = fmt.Errorf("Cannot specify ascending and descending sorting")
  246. } else if aok {
  247. ascending = fmt.Sprint(ascendingData)
  248. } else {
  249. descending = fmt.Sprint(descendingData)
  250. }
  251. if err == nil {
  252. if lastText, ok := args["last"]; ok {
  253. last, err = strconv.Atoi(fmt.Sprint(lastText))
  254. }
  255. }
  256. if err == nil {
  257. if fromText, ok := args["from"]; ok {
  258. from, err = strconv.Atoi(fmt.Sprint(fromText))
  259. }
  260. }
  261. if err == nil {
  262. if itemsText, ok := args["items"]; ok {
  263. items, err = strconv.Atoi(fmt.Sprint(itemsText))
  264. }
  265. }
  266. return ascending, descending, from, items, last, err
  267. }
  268. /*
  269. handleMutationArgs handles node and edge insertion and removal.
  270. */
  271. func (rt *selectionSetRuntime) handleMutationArgs(path []string, args map[string]interface{}, kind string) error {
  272. var err error
  273. if toStore, ok := args["storeNode"]; ok && rt.rtp.CheckWritePermission(path, rt.node) {
  274. toStoreMap, ok := toStore.(map[string]interface{})
  275. if ok {
  276. // Handle mutations of nodes
  277. node := data.NewGraphNodeFromMap(toStoreMap)
  278. if node.Kind() == "" {
  279. node.SetAttr("kind", kind)
  280. }
  281. err = rt.rtp.gm.StoreNode(rt.rtp.part, node)
  282. } else {
  283. rt.rtp.handleRuntimeError(fmt.Errorf("Object required for node attributes and values"),
  284. path, rt.node)
  285. }
  286. }
  287. if toRemove, ok := args["removeNode"]; ok && rt.rtp.CheckWritePermission(path, rt.node) {
  288. toRemoveMap, ok := toRemove.(map[string]interface{})
  289. if ok {
  290. // Handle removal of nodes
  291. node := data.NewGraphNodeFromMap(toRemoveMap)
  292. if node.Kind() == "" {
  293. node.SetAttr("kind", kind)
  294. }
  295. _, err = rt.rtp.gm.RemoveNode(rt.rtp.part, node.Key(), node.Kind())
  296. } else {
  297. rt.rtp.handleRuntimeError(fmt.Errorf("Object required for node key and kind"),
  298. path, rt.node)
  299. }
  300. }
  301. if toStore, ok := args["storeEdge"]; err == nil && ok && rt.rtp.CheckWritePermission(path, rt.node) {
  302. toStoreMap, ok := toStore.(map[string]interface{})
  303. if ok {
  304. // Handle mutations of edges
  305. node := data.NewGraphEdgeFromNode(data.NewGraphNodeFromMap(toStoreMap))
  306. err = rt.rtp.gm.StoreEdge(rt.rtp.part, node)
  307. } else {
  308. rt.rtp.handleRuntimeError(fmt.Errorf("Object required for edge attributes and values"),
  309. path, rt.node)
  310. }
  311. }
  312. if toRemove, ok := args["removeEdge"]; err == nil && ok && rt.rtp.CheckWritePermission(path, rt.node) {
  313. toRemoveMap, ok := toRemove.(map[string]interface{})
  314. if ok {
  315. // Handle mutations of edges
  316. node := data.NewGraphEdgeFromNode(data.NewGraphNodeFromMap(toRemoveMap))
  317. _, err = rt.rtp.gm.RemoveEdge(rt.rtp.part, node.Key(), node.Kind())
  318. } else {
  319. rt.rtp.handleRuntimeError(fmt.Errorf("Object required for edge key and kind"),
  320. path, rt.node)
  321. }
  322. }
  323. return err
  324. }
  325. /*
  326. matchNode matches a given node against a given node template. Returns true if
  327. the template matches, false otherwise.
  328. */
  329. func (rt *selectionSetRuntime) matchNode(node data.Node, nodeTemplate map[string]*regexp.Regexp) bool {
  330. nodeData := node.Data()
  331. for k, v := range nodeTemplate {
  332. // Check if the match query should be negated
  333. negate := false
  334. if strings.HasPrefix(k, "not_") {
  335. k = k[4:]
  336. negate = true
  337. }
  338. mapAttr, ok := nodeData[k]
  339. if !ok {
  340. return false // Attribute does not exist
  341. }
  342. if negate {
  343. if v.MatchString(fmt.Sprint(mapAttr)) {
  344. return false // Attribute is the same
  345. }
  346. } else {
  347. if !v.MatchString(fmt.Sprint(mapAttr)) {
  348. return false // Attribute is not the same
  349. }
  350. }
  351. }
  352. return true
  353. }
  354. /*
  355. traversal captures all required data for a traversal during node lookup.
  356. */
  357. type traversal struct {
  358. spec string
  359. args map[string]interface{}
  360. selectionSetRuntime *selectionSetRuntime
  361. }
  362. /*
  363. fragmentRuntime is the common interface for all fragment runtimes.
  364. */
  365. type fragmentRuntime interface {
  366. TypeCondition() string
  367. SelectionSet() *parser.ASTNode
  368. }
  369. /*
  370. GetPlainFieldsAndAliases returns all fields as a list of node attributes, a map of
  371. aliases to names and a map from aliases to traversals.
  372. */
  373. func (rt *selectionSetRuntime) GetPlainFieldsAndAliases(path []string, kind string) (
  374. []string, map[string]string, map[string]*traversal) {
  375. errMultiFields := make([]string, 0)
  376. resList := []string{"key", "kind"}
  377. resMap := make(map[string]string)
  378. traversalMap := make(map[string]*traversal)
  379. fieldList := append(rt.node.Children[:0:0], rt.node.Children...) // Copy into new slice
  380. for i := 0; i < len(fieldList); i++ {
  381. var lastChild *parser.ASTNode
  382. c := fieldList[i]
  383. if len(c.Children) > 0 {
  384. lastChild = c.Children[len(c.Children)-1]
  385. }
  386. // Check for skip and include directive
  387. if rt.skipField(path, c) {
  388. continue
  389. }
  390. if c.Name == parser.NodeField {
  391. // Handle simple fields
  392. field := c.Runtime.(*fieldRuntime)
  393. if _, ok := resMap[field.Alias()]; ok {
  394. // Alias was used before
  395. if stringutil.IndexOf(field.Alias(), errMultiFields) == -1 {
  396. errMultiFields = append(errMultiFields, field.Alias())
  397. }
  398. continue
  399. }
  400. // Map alias to name and process the field
  401. resMap[field.Alias()] = field.Name()
  402. if lastChild.Name == parser.NodeSelectionSet {
  403. args := field.Arguments()
  404. // Handle traversals
  405. if spec, ok := args["traverse"]; ok {
  406. traversalMap[field.Alias()] = &traversal{
  407. spec: fmt.Sprint(spec),
  408. args: args,
  409. selectionSetRuntime: field.SelectionSetRuntime(),
  410. }
  411. } else {
  412. rt.rtp.handleRuntimeError(fmt.Errorf(
  413. "Traversal argument is missing"), path, c)
  414. }
  415. } else if stringutil.IndexOf(field.Name(), resList) == -1 {
  416. // Handle normal attribute lookup
  417. resList = append(resList, field.Name())
  418. }
  419. } else if c.Name == parser.NodeFragmentSpread || c.Name == parser.NodeInlineFragment {
  420. var fd fragmentRuntime
  421. if c.Name == parser.NodeFragmentSpread {
  422. // Lookup fragment spreads
  423. fd = rt.rtp.fragments[c.Token.Val]
  424. } else {
  425. // Construct inline fragments
  426. fd = c.Runtime.(*inlineFragmentDefinitionRuntime)
  427. }
  428. if fd.TypeCondition() != kind {
  429. // Type condition was not met - just skip the fragment
  430. continue
  431. }
  432. ss := fd.SelectionSet()
  433. fieldList = append(fieldList, ss.Children...)
  434. }
  435. }
  436. if len(errMultiFields) > 0 {
  437. for _, name := range errMultiFields {
  438. rt.rtp.handleRuntimeError(fmt.Errorf(
  439. "Field identifier %s used multiple times", name),
  440. path, rt.node)
  441. }
  442. }
  443. return resList, resMap, traversalMap
  444. }
  445. /*
  446. skipField checks if a given field has a skip or include directive and returns
  447. if the directive excludes the field.
  448. */
  449. func (rt *selectionSetRuntime) skipField(path []string, node *parser.ASTNode) bool {
  450. for _, c := range node.Children {
  451. if c.Name == parser.NodeDirectives {
  452. for _, directive := range c.Children {
  453. rt := directive.Runtime.(*argumentExpressionRuntime)
  454. name := rt.Name()
  455. args := rt.Arguments()
  456. if name == "skip" || name == "include" {
  457. if cond, ok := args["if"]; ok {
  458. if name == "skip" {
  459. skip, _ := strconv.ParseBool(fmt.Sprint(cond))
  460. return skip
  461. }
  462. include, _ := strconv.ParseBool(fmt.Sprint(cond))
  463. return !include
  464. }
  465. rt.rtp.handleRuntimeError(fmt.Errorf(
  466. "Directive %s is missing the 'if' argument", name), path, c)
  467. }
  468. }
  469. }
  470. }
  471. return false
  472. }
  473. // ArgumentExpression Runtime
  474. // ==========================
  475. /*
  476. Runtime for expressions with arguments.
  477. */
  478. type argumentExpressionRuntime struct {
  479. *invalidRuntime
  480. rtp *GraphQLRuntimeProvider
  481. node *parser.ASTNode
  482. }
  483. /*
  484. argumentExpressionRuntimeInst returns a new runtime component instance.
  485. */
  486. func argumentExpressionRuntimeInst(rtp *GraphQLRuntimeProvider, node *parser.ASTNode) parser.Runtime {
  487. return &argumentExpressionRuntime{&invalidRuntime{rtp, node}, rtp, node}
  488. }
  489. /*
  490. Name returns the name of this field.
  491. */
  492. func (rt *argumentExpressionRuntime) Name() string {
  493. if rt.node.Children[0].Name == parser.NodeAlias {
  494. return rt.node.Children[1].Token.Val
  495. }
  496. return rt.node.Children[0].Token.Val
  497. }
  498. /*
  499. Arguments returns all arguments of the field as a map.
  500. */
  501. func (rt *argumentExpressionRuntime) Arguments() map[string]interface{} {
  502. res := make(map[string]interface{})
  503. for _, c := range rt.node.Children {
  504. if c.Name == parser.NodeArguments {
  505. for _, a := range c.Children {
  506. res[a.Children[0].Token.Val] = a.Children[1].Runtime.(*valueRuntime).Value()
  507. }
  508. }
  509. }
  510. return res
  511. }
  512. // Field Runtime
  513. // =============
  514. /*
  515. Runtime for Fields.
  516. */
  517. type fieldRuntime struct {
  518. *argumentExpressionRuntime
  519. rtp *GraphQLRuntimeProvider
  520. node *parser.ASTNode
  521. }
  522. /*
  523. fieldRuntimeInst returns a new runtime component instance.
  524. */
  525. func fieldRuntimeInst(rtp *GraphQLRuntimeProvider, node *parser.ASTNode) parser.Runtime {
  526. return &fieldRuntime{&argumentExpressionRuntime{&invalidRuntime{rtp, node},
  527. rtp, node}, rtp, node}
  528. }
  529. /*
  530. Alias returns the alias of this field.
  531. */
  532. func (rt *fieldRuntime) Alias() string {
  533. return rt.node.Children[0].Token.Val
  534. }
  535. /*
  536. SelectionSetRuntime returns the SelectionSet runtime of this field.
  537. */
  538. func (rt *fieldRuntime) SelectionSetRuntime() *selectionSetRuntime {
  539. res, _ := rt.node.Children[len(rt.node.Children)-1].Runtime.(*selectionSetRuntime)
  540. return res
  541. }