util.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package eql
  2. import (
  3. "fmt"
  4. "sort"
  5. "strings"
  6. "devt.de/krotik/common/stringutil"
  7. "devt.de/krotik/eliasdb/eql/parser"
  8. )
  9. /*
  10. RefineQueryByResultRows tries to construct a query which will only
  11. show certain rows of a given query result. Might fail if no primary
  12. node per row can be identified or if the "primary" keyword is used.
  13. */
  14. func RefineQueryByResultRows(res SearchResult, rows []int) (string, error) {
  15. var col = -1
  16. var ret = ""
  17. // Search for column which gives the root node key and kind
  18. err := fmt.Errorf("Could not determine root nodes")
  19. rowCount := res.RowCount()
  20. if rowCount > 0 {
  21. for i, d := range res.Header().Data() {
  22. if ds := strings.Split(d, ":"); ds[0] == "1" && ds[1] == "n" {
  23. col = i
  24. err = nil
  25. }
  26. }
  27. }
  28. if err == nil {
  29. var ast *parser.ASTNode
  30. // Get the AST
  31. if ast, err = ParseQuery("Refine query", res.Query()); err == nil {
  32. var qtail []*parser.ASTNode
  33. // Get the children of the AST which do not produce the root nodes
  34. for i, c := range ast.Children {
  35. if c.Name != parser.NodeVALUE {
  36. qtail = ast.Children[i:]
  37. break
  38. }
  39. }
  40. // Now collect the keys which should be the new root nodes
  41. keys := make([]string, 0, len(rows))
  42. kind := ""
  43. for _, r := range rows {
  44. if r < rowCount {
  45. src := strings.Split(res.RowSource(r)[col], ":")
  46. keys = append(keys, src[2])
  47. if kind == "" {
  48. kind = src[1]
  49. }
  50. }
  51. }
  52. sort.Strings(keys)
  53. err = fmt.Errorf("Could not find requested row%v", stringutil.Plural(len(rows)))
  54. if len(keys) > 0 {
  55. // Assemble the query
  56. ast, _ = ParseQuery("", fmt.Sprintf("lookup %v '%v'", kind, strings.Join(keys, "', '")))
  57. ast.Children = append(ast.Children, qtail...)
  58. ret, err = parser.PrettyPrint(ast)
  59. }
  60. }
  61. }
  62. return ret, err
  63. }