javascript/syncbase: Allowing methods that take
RowRange/PrefixRange to also accept strings.
When a string is used, it is interpreted
as 'prefix'.
scan and deleteRange accept string in addition
to RowRange. When a string is used, it is assumed
to be a prefix rather than a single row key.
This is a reasonable assumption since deleteRange
has the sister method delete(string key) that can
be used for deleting single rows and scanning for
a single row is equivalent to doing a get.
Now we are also removing PrefixRange completely
since prefix is now just a string for scan,
deleteRange and setPermission.
PrefixPermission also now has the prefix property
as string instead of PrefixRange.
Closes https://github.com/vanadium/issues/issues/677
Change-Id: If1c611ef6f5d0bc88ad8c2b45df2784d32ecf276
diff --git a/src/nosql/rowrange.js b/src/nosql/rowrange.js
index 98ed55a..c85c9ad 100644
--- a/src/nosql/rowrange.js
+++ b/src/nosql/rowrange.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-var inherits = require('inherits');
-
var util = require('../util');
/**
@@ -16,7 +14,8 @@
module.exports = {
range: range,
singleRow: singleRow,
- prefix: prefix
+ prefix: prefix,
+ RowRange: RowRange
};
/**
@@ -37,11 +36,14 @@
/**
* Creates a range that only matches items of the given prefix.
* @param {string} prefix Prefix.
- * @return {module:syncbase.nosql~PrefixRange} A PrefixRange object. PrefixRange
+ * @return {module:syncbase.nosql~Range} A Range object covering the prefix.
* inherits from {@link module:syncbase.nosql~RowRange}
*/
function prefix(p) {
- return new PrefixRange(p);
+ var startBytes = util.stringToUTF8Bytes(p);
+ var limitBytes = util.stringToUTF8Bytes(p);
+ util.prefixRangeLimit(limitBytes);
+ return new RowRange(startBytes, limitBytes);
}
var ASCII_NULL = '\x00';
@@ -93,37 +95,3 @@
enumerable: true
});
}
-
-/*
- * @summary
- * PrefixRange is a sub type of {@link module:syncbase.nosql.rowrange~RowRange}
- * that indicates all ranges matching a prefix.
- * Private constructor, use {@link module:syncbase.nosql.rowrange#prefix} to
- * create an instance.
- * @inherits module:syncbase.nosql.rowrange~RowRange
- * @inner
- * @constructor
- * @memberof {module:syncbase.nosql.rowrange}
- */
-function PrefixRange(prefix) {
- if (!(this instanceof PrefixRange)) {
- return new PrefixRange(prefix);
- }
-
- var startBytes = util.stringToUTF8Bytes(prefix);
- var limitBytes = util.stringToUTF8Bytes(prefix);
- util.prefixRangeLimit(limitBytes);
-
- /**
- * Prefix
- * @type {string}
- */
- Object.defineProperty(this, 'prefix', {
- value: prefix,
- writable: false,
- enumerable: true
- });
-
- RowRange.call(this, startBytes, limitBytes);
-}
-inherits(PrefixRange, RowRange);
diff --git a/src/nosql/table.js b/src/nosql/table.js
index 81037b1..9f83221 100644
--- a/src/nosql/table.js
+++ b/src/nosql/table.js
@@ -6,8 +6,10 @@
var vanadium = require('vanadium');
var nosqlVdl = require('../gen-vdl/v.io/v23/services/syncbase/nosql');
-var prefix = require('./rowrange').prefix;
var Row = require('./row');
+var RowRange = require('./rowrange');
+
+var prefix = RowRange.prefix;
module.exports = Table;
@@ -147,10 +149,13 @@
* deleteRange deletes all rows in the given half-open range [start, limit). If
* limit is "", all rows with keys >= start are included.
* @param {module:vanadium.context.Context} ctx Vanadium context.
- * @param {module:syncbase.nosql.rowrange.RowRange} range Row ranges to delete.
+ * @param {module:syncbase.nosql.rowrange.RowRange|string} range Row range
+ * to delete. If a string value is provided for the range, it is assumed to be
+ * a prefix.
* @param {function} cb Callback.
*/
Table.prototype.deleteRange = function(ctx, range, cb) {
+ range = normalizeRangeParam(range);
this._wire(ctx).deleteRange(
ctx, this.schemaVersion, range.start, range.limit, cb);
};
@@ -162,11 +167,14 @@
* time of the RPC, and will not reflect subsequent writes to keys not yet
* reached by the stream.
* @param {module:vanadium.context.Context} ctx Vanadium context.
- * @param {module:syncbase.nosql.rowrange.RowRange} range Row ranges to scan.
+ * @param {module:syncbase.nosql.rowrange.RowRange|string} range Row range to
+ * scan. If a string value is provided for the range, it is assumed to be
+ * a prefix.
* @param {function} cb Callback.
* @returns {stream} Stream of row objects.
*/
Table.prototype.scan = function(ctx, range, cb) {
+ range = normalizeRangeParam(range);
var vomStreamDecoder = through2({
objectMode: true
}, function(row, enc, cb) {
@@ -201,19 +209,16 @@
* SetPermissions will fail if called with a prefix that does not match any
* rows.
* @param {module:vanadium.context.Context} ctx Vanadium context.
- * @param {module:syncbase.nosql.rowrange.PrefixRange|string} prefix Prefix or
- * PrefixRange.
+ * @param {string} prefix Prefix.
* @param @param {module:vanadium.security.access.Permissions} perms Permissions
* for the rows matching the prefix.
* @param {function} cb Callback.
*/
Table.prototype.setPermissions = function(ctx, prefix, perms, cb) {
this._wire(ctx).setPermissions(
- ctx, this.schemaVersion, stringifyPrefix(prefix), perms, cb);
+ ctx, this.schemaVersion, prefix, perms, cb);
};
-
-
/**
* GetPermissions returns an array of (prefix, perms) pairs. The array is
* sorted from longest prefix to shortest, so element zero is the one that
@@ -225,80 +230,35 @@
* @param {function} cb Callback.
*/
Table.prototype.getPermissions = function(ctx, key, cb) {
- // There are two PrefixPermission types, one is the wire type which has
- // Prefix as a string and then there is the client type where prefix is a
- // PrefixRange, therefore we convert between the wire and client types.
- this._wire(ctx).getPermissions(ctx, this.schemaVersion, key,
- function(err, wirePerms) {
- if (err) {
- return cb(err);
- }
-
- var perms = wirePerms.map(function(v) {
- return new PrefixPermissions(
- prefix(v.prefix),
- v.perms
- );
- });
-
- cb(null, perms);
- }
- );
+ this._wire(ctx).getPermissions(ctx, this.schemaVersion, key, cb);
};
/**
* DeletePermissions deletes the permissions for the specified prefix. Any
* rows covered by this prefix will use the next longest prefix's permissions.
* @param {module:vanadium.context.Context} ctx Vanadium context.
- * @param {module:syncbase.nosql.rowrane.PrefixRange|string} prefix Prefix or
- * PrefixRange.
+ * @param {string} prefix Prefix.
* @param {function} cb Callback.
*/
Table.prototype.deletePermissions = function(ctx, prefix, cb) {
- //TODO(aghassemi): Why is prefix a PrefixRange in Go?
this._wire(ctx).deletePermissions(
- ctx, this.schemaVersion, stringifyPrefix(prefix), cb);
+ ctx, this.schemaVersion, prefix, cb);
};
-function stringifyPrefix(prefix) {
- var prefixStr = prefix;
- if (typeof prefix === 'object') {
- // assume it is a PrefixRange
- prefixStr = prefix.prefix;
- }
- return prefixStr;
-}
-
/**
- * @summary
- * Represents a pair of {@link module:syncbase.nosql~PrefixRange} and
- * {@link module:vanadium.security.access.Permissions}.
- * @constructor
- * @inner
- * @memberof {module:syncbase.nosql}
+ * Ensures range is either a string or a RowRange object.
+ * If a string, it returns a prefix RowRange object.
+ * If not a string or RowRange object, it throws a type error.
+ * @private
*/
-function PrefixPermissions(prefixRange, perms) {
- if (!(this instanceof PrefixPermissions)) {
- return new PrefixPermissions(prefixRange, perms);
+function normalizeRangeParam(range) {
+ if (typeof range === 'string') {
+ range = prefix(range);
+ } else if(!(range instanceof RowRange.RowRange)) {
+ var rangeType = (range.constructor ? range.constructor.name : typeof range);
+ throw new TypeError('range must be of type string or RowRange. got ' +
+ range + ' with type ' + rangeType);
}
- /**
- * Prefix
- * @type {module:syncbase.nosql~PrefixRange}
- */
- Object.defineProperty(this, 'prefix', {
- value: prefixRange,
- writable: false,
- enumerable: true
- });
-
- /**
- * Permissions
- * @type {module:vanadium.security.access.Permissions}
- */
- Object.defineProperty(this, 'perms', {
- value: perms,
- writable: false,
- enumerable: true
- });
+ return range;
}
diff --git a/test/integration/test-table.js b/test/integration/test-table.js
index 3e24c89..86b2fdd 100644
--- a/test/integration/test-table.js
+++ b/test/integration/test-table.js
@@ -241,7 +241,16 @@
});
});
-test('Scanning table by a prefix range', function(t) {
+test('Scanning table by a prefix range passed as string', function(t) {
+ testScanningTableByPrefix(t, ROW_KEY);
+});
+
+test('Scanning table by a prefix range passed as RowRange', function(t) {
+ var range = syncbase.nosql.rowrange.prefix(ROW_KEY);
+ testScanningTableByPrefix(t, range);
+});
+
+function testScanningTableByPrefix(t, range) {
setupTable(t, function(err, o) {
if (err) {
return t.end(err);
@@ -275,23 +284,30 @@
return o.teardown(t.end);
}
- var range = syncbase.nosql.rowrange.prefix(ROW_KEY);
assertScanRows(o.ctx, table, range, prefixedRows, function(err) {
t.error(err);
o.teardown(t.end);
});
}
});
+}
+
+test('Deleting rows by a prefix range passed as string', function(t) {
+ testDeletingRowsByPrefix(t, ROW_KEY);
});
-test('Deleting rows by a prefix range', function(t) {
+test('Deleting rows by a prefix range passed as RowRange', function(t) {
+ var range = syncbase.nosql.rowrange.prefix(ROW_KEY);
+ testDeletingRowsByPrefix(t, range);
+});
+
+function testDeletingRowsByPrefix(t, range) {
setupTable(t, function(err, o) {
if (err) {
return t.end(err);
}
var table = o.table;
- var range = syncbase.nosql.rowrange.prefix(ROW_KEY);
// create multiple rows all with ROW_KEY as prefix
var rows = [{
@@ -328,7 +344,7 @@
});
}
});
-});
+}
//TODO(aghassemi) Skipped test.
//Set permission for prefix != "" is not implemented.