sparqlupdate.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package gold
  2. import (
  3. "bytes"
  4. "errors"
  5. "io"
  6. "io/ioutil"
  7. "strings"
  8. "text/scanner"
  9. )
  10. // SPARQLUpdateQuery contains a verb, the body of the query and the graph
  11. type SPARQLUpdateQuery struct {
  12. verb string
  13. body string
  14. graph AnyGraph
  15. }
  16. // SPARQLUpdate contains the base URI and a list of queries
  17. type SPARQLUpdate struct {
  18. baseURI string
  19. queries []SPARQLUpdateQuery
  20. }
  21. // NewSPARQLUpdate creates a new SPARQL object
  22. func NewSPARQLUpdate(baseURI string) *SPARQLUpdate {
  23. return &SPARQLUpdate{
  24. baseURI: baseURI,
  25. queries: []SPARQLUpdateQuery{},
  26. }
  27. }
  28. // Parse parses a SPARQL query from the reader
  29. func (sparql *SPARQLUpdate) Parse(src io.Reader) error {
  30. b, _ := ioutil.ReadAll(src)
  31. s := new(scanner.Scanner).Init(bytes.NewReader(b))
  32. s.Mode = scanner.ScanIdents | scanner.ScanStrings
  33. start := 0
  34. level := 0
  35. verb := ""
  36. tok := s.Scan()
  37. for tok != scanner.EOF {
  38. switch tok {
  39. case -2:
  40. if level == 0 {
  41. if len(verb) > 0 {
  42. verb += " "
  43. }
  44. verb += s.TokenText()
  45. }
  46. case 123: // {
  47. if level == 0 {
  48. start = s.Position.Offset
  49. }
  50. level++
  51. case 125: // }
  52. level--
  53. if level == 0 {
  54. query := SPARQLUpdateQuery{
  55. body: string(b[start+1 : s.Position.Offset]),
  56. graph: NewGraph(sparql.baseURI),
  57. verb: verb,
  58. }
  59. query.graph.Parse(strings.NewReader(query.body), "text/turtle")
  60. sparql.queries = append(sparql.queries, query)
  61. }
  62. case 59: // ;
  63. if level == 0 {
  64. verb = ""
  65. }
  66. }
  67. tok = s.Scan()
  68. }
  69. return nil
  70. }
  71. // SPARQLUpdate is used to update a graph from a SPARQL query
  72. // Ugly, needs to be improved
  73. func (g *Graph) SPARQLUpdate(sparql *SPARQLUpdate) (int, error) {
  74. for _, query := range sparql.queries {
  75. if query.verb == "DELETE" || query.verb == "DELETE DATA" {
  76. for pattern := range query.graph.IterTriples() {
  77. found := false
  78. for _, triple := range g.All(pattern.Subject, pattern.Predicate, nil) {
  79. switch triple.Object.(type) {
  80. case *BlankNode:
  81. return 500, errors.New("bnodes are not supported!")
  82. default:
  83. if pattern.Object.Equal(triple.Object) {
  84. g.Remove(triple)
  85. found = true
  86. }
  87. }
  88. }
  89. if !found {
  90. return 409, errors.New("no matching triple found in graph!")
  91. }
  92. }
  93. }
  94. }
  95. for _, query := range sparql.queries {
  96. if query.verb == "INSERT" || query.verb == "INSERT DATA" {
  97. for triple := range query.graph.IterTriples() {
  98. g.Add(triple)
  99. }
  100. }
  101. }
  102. return 200, nil
  103. }