(Node SDK) N1qlQuery CAS invalid for document update

n1ql
query

#1

Hello,

I’m having an issue where I’m using a N1qlQuery to return a list of objects, and then selecting one of those objects, modifying its data, and then attempting to update it with conditional update (using CAS)…

The CAS returned by a query appears to be invalid for an update. Consider this code:

var payload = {"new":"item"};
bucket.insert(guid(), payload, function(err, result) {
    // Wait 3 seconds to validate that the query will return the inserted object.
	setTimeout(function() {
		bucket.query(queryBuilder.fromString("SELECT *,meta() AS `path` FROM `default` WHERE new=\"item\""), function(err, result) {
			var doc = result[0];
			bucket.replace(doc.path.id, doc, {cas: doc.path.cas}, function(err,result) {
				if(err) {
					console.log("An error occurred: ");
					console.log(err);
				} else {
					console.log(result);
				}
				bucket.disconnect();
			});
			
		});
	}, 3000);
});

This will output:

TypeError: cas option needs to be a CAS object or string.
    at Bucket._checkCasOption (/Users/mattpryor/projects/xtranet-api/node_modules/couchbase/lib/bucket.js:1147:13)
    at Bucket._store (/Users/mattpryor/projects/xtranet-api/node_modules/couchbase/lib/bucket.js:1555:8)
    at Bucket.replace (/Users/mattpryor/projects/xtranet-api/node_modules/couchbase/lib/bucket.js:1642:8)

If I instead cast the returned CAS to a string, using {cas: doc.path.cas.toString}, I will get a different error:

CouchbaseError: The key already exists in the server. If you have supplied a CAS then the key exists with a CAS value different than specified

I would expect that the CAS returned from the Query would match the CAS returned from a GET, but it seems that is not the case as well, consider the following code:

var payload = {"new":"item"};
var id = guid();
bucket.insert(id, payload, function(err, result) {
	setTimeout(function() {
		bucket.get(id, function(err, result) {
			console.log("GET cas: " + result.cas);
		});
		bucket.query(queryBuilder.fromString("SELECT *,meta() AS `path` FROM `default` WHERE new=\"item\""), function(err, result) {
			console.log("QUERY cas: " + result[0].path.cas);
		});
	}, 3000);
});

This will output something like the following:

GET cas: CouchbaseCas<103571374997504>
QUERY cas: 5047431593984

I had expected that these 2 values would match.

If I do a get, then the replace using the retrieved CAS, then everything works.

Is there something I am missing, or is this a bug?

Thanks,
Matthew Pryor


I’m using Couchbase Server Enterprise 4.5.0, and the Node SDK version: 2.2.1 on OSX El Capitan


#2

This looks very similar to Different CAS value for the same document obtained via Java SDK and N1QL