Select/Construct query does not work on the TransactionalRepositoryClient
Closed this issue · 5 comments
Library version [3.0.1]
Node.js version [18]
Describe the bug
Select/Construct query does not work on transactional-repository-client.
To Reproduce
Simply start a transaction and send any construct query.
const client: TransactionalRepositoryClient = await repository.beginTransaction();
client.registerParser(new JsonLDParser());
const query = `construct where {?s ?p ?o.} limit 1 `
const payload = new GetQueryPayload()
.setQuery(query)
.setQueryType(QueryType.CONSTRUCT)
.setResponseType(RDFMimeType.JSON_LD)
.setInference(inference)
const stream = await repository.query(payload);
stream.on('data', (bindings) => {
// the bindings stream converted to data objects with the registered parser
});
stream.on('end', () => {
// handle end of the stream
});
await client.commit();
Expected behavior
Execute the query without any error.
Additional context
TransactionalRepositoryClient.query(...)
is not implemented correctly.
The following code fixes this:
query(payload) {
const serviceRequest = this.queryService.query(payload);
// The body should be the plain query and the 'content-type' header should be 'application/sparql-query'.
serviceRequest.getHttpRequestBuilder().setData(payload.payload.query)
serviceRequest.getHttpRequestBuilder().setHeaders({...serviceRequest.getHttpRequestBuilder().getHeaders(), 'Content-Type': 'application/sparql-query'})
this.decorateServiceRequest(serviceRequest, 'QUERY');
return serviceRequest.execute();
}
The fix is also implemented here.
Thank you @LesterLyu. We will investigate and fix the issue.
Hi @LesterLyu,
This is not a bug.
The GetQueryPayload
has a default ContentType set in it's constructor. It is the QueryContentType.X_WWW_FORM_URLENCODED
.
If you content is a query string, you must set the content type of the GetQueryPayload
object to QueryContentType.SPARQL_QUERY
using the setContentType
method.
So your code should be:
const client = getRepositoryClient();
const transactionClient = await client.beginTransaction();
transactionClient.registerParser(new JsonLDParser());
const query = `construct where {?s ?p ?o.} limit 1 `
const payload = new GetQueryPayload()
.setQuery(query)
.setQueryType(QueryType.CONSTRUCT)
.setResponseType(RDFMimeType.JSON_LD)
.setInference(true)
.setContentType(QueryContentType.SPARQL_QUERY);
const result = [];
const stream = await client.query(payload);
stream.on('data', (bindings) => {
result.push(bindings);
});
stream.on('end', () => {
res.send(Buffer.concat(result).toString('utf8').trim());
});
await transactionClient.commit();
In the docs about the GetQueryPayload
:
Content type parameter which is used for setting the Content-Type http header is optional and by default application/x-www-form-urlencoded type is set.
In the fix you have made, you hardcode it to `application/sparql-query` for every request.
I will close the issue. Please try the above way of making the transactional query and if you experience any difficulty we will reopen it.
I found another issue, setInference(false)
does not work when it is used in a transactionClient
Hello @LesterLyu. Thank you for reporting this issue. If you don't mind I'll split it as a separate issue so we can track it more easily.