selectionset.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  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. if node.Key() == "" {
  296. var it *graph.NodeKeyIterator
  297. if it, err = rt.rtp.gm.NodeKeyIterator(rt.rtp.part, node.Kind()); err == nil {
  298. var keys []string
  299. for it.HasNext() && err == nil {
  300. keys = append(keys, it.Next())
  301. err = it.Error()
  302. }
  303. if err == nil {
  304. for _, key := range keys {
  305. if err == nil {
  306. _, err = rt.rtp.gm.RemoveNode(rt.rtp.part, key, node.Kind())
  307. }
  308. }
  309. }
  310. }
  311. } else {
  312. _, err = rt.rtp.gm.RemoveNode(rt.rtp.part, node.Key(), node.Kind())
  313. }
  314. } else {
  315. rt.rtp.handleRuntimeError(fmt.Errorf("Object required for node key and kind"),
  316. path, rt.node)
  317. }
  318. }
  319. if toStore, ok := args["storeEdge"]; err == nil && ok && rt.rtp.CheckWritePermission(path, rt.node) {
  320. toStoreMap, ok := toStore.(map[string]interface{})
  321. if ok {
  322. // Handle mutations of edges
  323. node := data.NewGraphEdgeFromNode(data.NewGraphNodeFromMap(toStoreMap))
  324. err = rt.rtp.gm.StoreEdge(rt.rtp.part, node)
  325. } else {
  326. rt.rtp.handleRuntimeError(fmt.Errorf("Object required for edge attributes and values"),
  327. path, rt.node)
  328. }
  329. }
  330. if toRemove, ok := args["removeEdge"]; err == nil && ok && rt.rtp.CheckWritePermission(path, rt.node) {
  331. toRemoveMap, ok := toRemove.(map[string]interface{})
  332. if ok {
  333. // Handle mutations of edges
  334. node := data.NewGraphEdgeFromNode(data.NewGraphNodeFromMap(toRemoveMap))
  335. _, err = rt.rtp.gm.RemoveEdge(rt.rtp.part, node.Key(), node.Kind())
  336. } else {
  337. rt.rtp.handleRuntimeError(fmt.Errorf("Object required for edge key and kind"),
  338. path, rt.node)
  339. }
  340. }
  341. return err
  342. }
  343. /*
  344. matchNode matches a given node against a given node template. Returns true if
  345. the template matches, false otherwise.
  346. */
  347. func (rt *selectionSetRuntime) matchNode(node data.Node, nodeTemplate map[string]*regexp.Regexp) bool {
  348. nodeData := node.Data()
  349. for k, v := range nodeTemplate {
  350. // Check if the match query should be negated
  351. negate := false
  352. if strings.HasPrefix(k, "not_") {
  353. k = k[4:]
  354. negate = true
  355. }
  356. mapAttr, ok := nodeData[k]
  357. if !ok {
  358. return false // Attribute does not exist
  359. }
  360. if negate {
  361. if v.MatchString(fmt.Sprint(mapAttr)) {
  362. return false // Attribute is the same
  363. }
  364. } else {
  365. if !v.MatchString(fmt.Sprint(mapAttr)) {
  366. return false // Attribute is not the same
  367. }
  368. }
  369. }
  370. return true
  371. }
  372. /*
  373. traversal captures all required data for a traversal during node lookup.
  374. */
  375. type traversal struct {
  376. spec string
  377. args map[string]interface{}
  378. selectionSetRuntime *selectionSetRuntime
  379. }
  380. /*
  381. fragmentRuntime is the common interface for all fragment runtimes.
  382. */
  383. type fragmentRuntime interface {
  384. TypeCondition() string
  385. SelectionSet() *parser.ASTNode
  386. }
  387. /*
  388. GetPlainFieldsAndAliases returns all fields as a list of node attributes, a map of
  389. aliases to names and a map from aliases to traversals.
  390. */
  391. func (rt *selectionSetRuntime) GetPlainFieldsAndAliases(path []string, kind string) (
  392. []string, map[string]string, map[string]*traversal) {
  393. errMultiFields := make([]string, 0)
  394. resList := []string{"key", "kind"}
  395. resMap := make(map[string]string)
  396. traversalMap := make(map[string]*traversal)
  397. fieldList := append(rt.node.Children[:0:0], rt.node.Children...) // Copy into new slice
  398. for i := 0; i < len(fieldList); i++ {
  399. var lastChild *parser.ASTNode
  400. c := fieldList[i]
  401. if len(c.Children) > 0 {
  402. lastChild = c.Children[len(c.Children)-1]
  403. }
  404. // Check for skip and include directive
  405. if rt.skipField(path, c) {
  406. continue
  407. }
  408. if c.Name == parser.NodeField {
  409. // Handle simple fields
  410. field := c.Runtime.(*fieldRuntime)
  411. if _, ok := resMap[field.Alias()]; ok {
  412. // Alias was used before
  413. if stringutil.IndexOf(field.Alias(), errMultiFields) == -1 {
  414. errMultiFields = append(errMultiFields, field.Alias())
  415. }
  416. continue
  417. }
  418. // Map alias to name and process the field
  419. resMap[field.Alias()] = field.Name()
  420. if lastChild.Name == parser.NodeSelectionSet {
  421. args := field.Arguments()
  422. // Handle traversals
  423. if spec, ok := args["traverse"]; ok {
  424. traversalMap[field.Alias()] = &traversal{
  425. spec: fmt.Sprint(spec),
  426. args: args,
  427. selectionSetRuntime: field.SelectionSetRuntime(),
  428. }
  429. } else {
  430. rt.rtp.handleRuntimeError(fmt.Errorf(
  431. "Traversal argument is missing"), path, c)
  432. }
  433. } else if stringutil.IndexOf(field.Name(), resList) == -1 {
  434. // Handle normal attribute lookup
  435. resList = append(resList, field.Name())
  436. }
  437. } else if c.Name == parser.NodeFragmentSpread || c.Name == parser.NodeInlineFragment {
  438. var fd fragmentRuntime
  439. if c.Name == parser.NodeFragmentSpread {
  440. // Lookup fragment spreads
  441. fd = rt.rtp.fragments[c.Token.Val]
  442. } else {
  443. // Construct inline fragments
  444. fd = c.Runtime.(*inlineFragmentDefinitionRuntime)
  445. }
  446. if fd.TypeCondition() != kind {
  447. // Type condition was not met - just skip the fragment
  448. continue
  449. }
  450. ss := fd.SelectionSet()
  451. fieldList = append(fieldList, ss.Children...)
  452. }
  453. }
  454. if len(errMultiFields) > 0 {
  455. for _, name := range errMultiFields {
  456. rt.rtp.handleRuntimeError(fmt.Errorf(
  457. "Field identifier %s used multiple times", name),
  458. path, rt.node)
  459. }
  460. }
  461. return resList, resMap, traversalMap
  462. }
  463. /*
  464. skipField checks if a given field has a skip or include directive and returns
  465. if the directive excludes the field.
  466. */
  467. func (rt *selectionSetRuntime) skipField(path []string, node *parser.ASTNode) bool {
  468. for _, c := range node.Children {
  469. if c.Name == parser.NodeDirectives {
  470. for _, directive := range c.Children {
  471. rt := directive.Runtime.(*argumentExpressionRuntime)
  472. name := rt.Name()
  473. args := rt.Arguments()
  474. if name == "skip" || name == "include" {
  475. if cond, ok := args["if"]; ok {
  476. if name == "skip" {
  477. skip, _ := strconv.ParseBool(fmt.Sprint(cond))
  478. return skip
  479. }
  480. include, _ := strconv.ParseBool(fmt.Sprint(cond))
  481. return !include
  482. }
  483. rt.rtp.handleRuntimeError(fmt.Errorf(
  484. "Directive %s is missing the 'if' argument", name), path, c)
  485. }
  486. }
  487. }
  488. }
  489. return false
  490. }
  491. // ArgumentExpression Runtime
  492. // ==========================
  493. /*
  494. Runtime for expressions with arguments.
  495. */
  496. type argumentExpressionRuntime struct {
  497. *invalidRuntime
  498. rtp *GraphQLRuntimeProvider
  499. node *parser.ASTNode
  500. }
  501. /*
  502. argumentExpressionRuntimeInst returns a new runtime component instance.
  503. */
  504. func argumentExpressionRuntimeInst(rtp *GraphQLRuntimeProvider, node *parser.ASTNode) parser.Runtime {
  505. return &argumentExpressionRuntime{&invalidRuntime{rtp, node}, rtp, node}
  506. }
  507. /*
  508. Name returns the name of this field.
  509. */
  510. func (rt *argumentExpressionRuntime) Name() string {
  511. if rt.node.Children[0].Name == parser.NodeAlias {
  512. return rt.node.Children[1].Token.Val
  513. }
  514. return rt.node.Children[0].Token.Val
  515. }
  516. /*
  517. Arguments returns all arguments of the field as a map.
  518. */
  519. func (rt *argumentExpressionRuntime) Arguments() map[string]interface{} {
  520. res := make(map[string]interface{})
  521. for _, c := range rt.node.Children {
  522. if c.Name == parser.NodeArguments {
  523. for _, a := range c.Children {
  524. res[a.Children[0].Token.Val] = a.Children[1].Runtime.(*valueRuntime).Value()
  525. }
  526. }
  527. }
  528. return res
  529. }
  530. // Field Runtime
  531. // =============
  532. /*
  533. Runtime for Fields.
  534. */
  535. type fieldRuntime struct {
  536. *argumentExpressionRuntime
  537. rtp *GraphQLRuntimeProvider
  538. node *parser.ASTNode
  539. }
  540. /*
  541. fieldRuntimeInst returns a new runtime component instance.
  542. */
  543. func fieldRuntimeInst(rtp *GraphQLRuntimeProvider, node *parser.ASTNode) parser.Runtime {
  544. return &fieldRuntime{&argumentExpressionRuntime{&invalidRuntime{rtp, node},
  545. rtp, node}, rtp, node}
  546. }
  547. /*
  548. Alias returns the alias of this field.
  549. */
  550. func (rt *fieldRuntime) Alias() string {
  551. return rt.node.Children[0].Token.Val
  552. }
  553. /*
  554. SelectionSetRuntime returns the SelectionSet runtime of this field.
  555. */
  556. func (rt *fieldRuntime) SelectionSetRuntime() *selectionSetRuntime {
  557. res, _ := rt.node.Children[len(rt.node.Children)-1].Runtime.(*selectionSetRuntime)
  558. return res
  559. }