Skip to content

Commit

Permalink
feat(alpha): support RDF response via http query request (#8004) (#8639)
Browse files Browse the repository at this point in the history
Fixes #8529
Closes: DGRAPHCORE-223

inspired from #8004

Co-authored-by: Aman Mangal <aman@dgraph.io>
  • Loading branch information
all-seeing-code and mangalaman93 committed Jul 31, 2023
1 parent 75ff9c3 commit 48b1d5f
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 12 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ GOPATH ?= $(shell go env GOPATH)
######################
DGRAPH_VERSION ?= local

.PHONY: all
.PHONY: all
all: dgraph

.PHONY: dgraph
Expand Down
24 changes: 23 additions & 1 deletion dgraph/cmd/alpha/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,18 @@ func queryHandler(w http.ResponseWriter, r *http.Request) {
}
}

// If rdf is set true, then response will be in rdf format.
respFormat := r.URL.Query().Get("respFormat")
switch respFormat {
case "", "json":
req.RespFormat = api.Request_JSON
case "rdf":
req.RespFormat = api.Request_RDF
default:
x.SetStatus(w, x.ErrorInvalidRequest, fmt.Sprintf("invalid value [%v] for parameter respFormat", respFormat))
return
}

// Core processing happens here.
resp, err := (&edgraph.Server{}).QueryNoGrpc(ctx, &req)
if err != nil {
Expand Down Expand Up @@ -273,7 +285,17 @@ func queryHandler(w http.ResponseWriter, r *http.Request) {
x.Check2(out.Write(js))
}
x.Check2(out.WriteRune('{'))
writeEntry("data", resp.Json)
if respFormat == "rdf" {
// In Json, []byte marshals into a base64 data. We instead Marshal it as a string.
// json.Marshal is therefore necessary here. We also do not want to escape <,>.
var buf bytes.Buffer
encoder := json.NewEncoder(&buf)
encoder.SetEscapeHTML(false)
x.Check(encoder.Encode(string(resp.Rdf)))
writeEntry("data", buf.Bytes())
} else {
writeEntry("data", resp.Json)
}
x.Check2(out.WriteRune(','))
writeEntry("extensions", js)
x.Check2(out.WriteRune('}'))
Expand Down
72 changes: 62 additions & 10 deletions dgraph/cmd/alpha/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,12 @@ func queryWithGz(queryText, contentType, debug, timeout string, gzReq, gzResp bo
}

type queryInp struct {
body string
typ string
debug string
ts uint64
hash string
body string
typ string
debug string
ts uint64
hash string
respFmt string
}

type tsInfo struct {
Expand All @@ -191,6 +192,9 @@ func queryWithTsForResp(inp queryInp) (string, *tsInfo, *http.Response, error) {
params = append(params, fmt.Sprintf("startTs=%v", strconv.FormatUint(inp.ts, 10)))
params = append(params, fmt.Sprintf("hash=%s", inp.hash))
}
if inp.respFmt != "" {
params = append(params, fmt.Sprintf("respFormat=%s", inp.respFmt))
}
url := addr + "/query?" + strings.Join(params, "&")

_, body, resp, err := runWithRetriesForResp("POST", inp.typ, url, inp.body)
Expand All @@ -205,12 +209,9 @@ func queryWithTsForResp(inp queryInp) (string, *tsInfo, *http.Response, error) {
startTs := r.Extensions.Txn.StartTs
hash := r.Extensions.Txn.Hash

// Remove the extensions.
r2 := res{
Data: r.Data,
}
// Remove the extensions
r2 := res{Data: r.Data}
output, err := json.Marshal(r2)

return string(output), &tsInfo{ts: startTs, hash: hash}, resp, err
}

Expand Down Expand Up @@ -985,3 +986,54 @@ func TestQueryBackwardCompatibleWithGraphqlPlusMinusHeader(t *testing.T) {
require.NoError(t, err)
require.Equal(t, "2", resp.Header.Get(x.DgraphCostHeader))
}

func TestQueryRdfData(t *testing.T) {
require.NoError(t, dropAll())
require.NoError(t, alterSchema(`name: string @index(term) .`))

// empty RDF response
q1 := `
{
balances(func: anyofterms(name, "Alice Bob")) {
name
balance
}
}`
resp, _, err := queryWithTs(queryInp{body: q1, typ: "application/dql", respFmt: "rdf"})
require.NoError(t, err)
require.Equal(t, `{"data":""}`, resp)

m1 := `
{
set {
_:bob <name> "Bob \"<the builder>\"" .
_:bob <balance> "110" .
_:alice <balance> "60" .
}
}`
_, err = mutationWithTs(mutationInp{body: m1, typ: "application/rdf", commitNow: true})
require.NoError(t, err)

// json query
resp, _, err = queryWithTs(queryInp{body: q1, typ: "application/dql"})
require.NoError(t, err)
require.Equal(t, `{"data":{"balances":[{"name":"Bob \"\u003cthe builder\u003e\"","balance":"110"}]}}`, resp)

// rdf query
resp, _, err = queryWithTs(queryInp{body: q1, typ: "application/dql", respFmt: "rdf"})
require.NoError(t, err)
var r2 struct {
Data string `json:"data"`
}
require.NoError(t, json.Unmarshal([]byte(resp), &r2))

// we apply the same RDF mutation and it should work
require.NoError(t, dropAll())
require.NoError(t, alterSchema(`name: string @index(term) .`))
_, err = mutationWithTs(mutationInp{body: `{set {` + r2.Data + `}}`, typ: "application/rdf", commitNow: true})
require.NoError(t, err)

resp, _, err = queryWithTs(queryInp{body: q1, typ: "application/dql"})
require.NoError(t, err)
require.Equal(t, `{"data":{"balances":[{"name":"Bob \"\u003cthe builder\u003e\"","balance":"110"}]}}`, resp)
}

0 comments on commit 48b1d5f

Please sign in to comment.