Hi,
Recently, we found out some of our documents were deleted when this should not have been the case!
Digging deeper, we arrived to the conclusion that it was because of a mismatch between a N1QL query and its response, leading us to retrieve the wrong document id for our query, and later on deleting the “wrong” document based on the N1QL query returned data.
We added a clientContextId for every query we make and compare it with the one returned in the response and we have some time a mismatch detected!
Error querying from datastore with query [SELECT
myField
FROMmyBucket
WHEREmyField
LIKE ‘prefix:%’ ANDmyOtherField
IS VALUED ORDER BYmyField
LIMIT 1] with context id [n1ql-7446786d-d8a8-457e-9fb5-f073f6f8d390] - Response context id [n1ql-cc3d4da1-499e-4c69-8136-10587baad8ba]
At the same time we are having similar queries happening, all returning only the myField
therefore, before adding the clientContextId were not able to detect the mismatch:
SELECT
myField
FROMmyBucket
WHEREmyField
LIKE ‘prefix1:%’ ANDmyOtherField
IS VALUED ORDER BYmyField
LIMIT 1
SELECTmyField
FROMmyBucket
WHEREmyField
LIKE ‘prefix2:%:suffix2’ ANDmyOtherField
IS VALUED
We are using Couchbase 4.5 and Java SDK client 2.3.1.
We are not using prepared statement and the snipper of code below shows how we use the SDK to query:
`
public List executeSimpleQuery(String statement) {
return executeQuery(N1qlQuery.simple(statement, N1qlParams.build().consistency(ScanConsistency.REQUEST_PLUS)));
}
public List<N1qlQueryRow> executeParameterisedQuery(String statement, JsonObject placeholderValues) {
N1qlQuery query = N1qlQuery.parameterized(statement, placeholderValues, N1qlParams.build().consistency(ScanConsistency.REQUEST_PLUS));
return executeQuery(query);
}
private List<N1qlQueryRow> executeQuery(N1qlQuery query) {
// Generate a client context id for sanity check on response
String clientContextId = generateN1QLClientContextId();
query.params().withContextId(clientContextId);
// Do the query
N1qlQueryResult queryResult = bucket.query(query);
// Check response match query
if (!clientContextId.equals(queryResult.clientContextId())) {
throw new RuntimeException(
String.format("Error querying from datastore with query [%s] with context id [%s]" +
" - Response context id [%s] does not match",
query.statement().toString(), clientContextId, queryResult.clientContextId()));
}
// Check response success
if (!queryResult.parseSuccess() || !queryResult.finalSuccess()) {
throw new RuntimeException(
String.format("Error querying from datastore with query [%s] - Errors are [%s]",
query.statement().toString(), queryResult.errors().toString()));
}
return queryResult.allRows();
}`
Also to be mentioned, if I use the query tab in the UI to retrieve the list of completed_requests with select * from system:completed_requests order by Time desc
, not all the queries shows the clientContextId!
Is there something we are doing wrong in our query code?
Has anyone encountered this issue of mismatch between query and response before?
Any help will be really appreciated!
Thanks.