Skip to content

Commit

Permalink
datastore: scope Key creation to include NS. fixes googleapis#116.
Browse files Browse the repository at this point in the history
  • Loading branch information
stephenplusplus committed Aug 20, 2014
1 parent 6207a6d commit 8c8ab55
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 65 deletions.
35 changes: 26 additions & 9 deletions lib/datastore/dataset.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,32 +54,49 @@ var SCOPES = [
* @constructor
* @alias module:datastore/dataset
*
* @param {object} options
* @param {string} options.id - Dataset ID. This is your project ID from the
* Google Developers Console.
* @param {object=} options
* @param {string} options.projectId - Dataset ID. This is your project ID from
* the Google Developers Console.
* @param {string} options.keyFileName - Full path to the JSON key downloaded
* from the Google Developers Console.
* @param {string} options.namespace - Namespace to isolate transactions to.
*
* @example
* ```js
* var dataset = new Dataset({
* id: 'my-project',
* projectId: 'my-project',
* keyFileName: '/path/to/keyfile.json'
* });
* ```
*/
function Dataset(opts) {
opts = opts || {};
var id = opts.projectId;
function Dataset(options) {
options = options || {};

this.connection = new conn.Connection({
keyFilename: opts.keyFilename,
keyFilename: options.keyFilename,
scopes: SCOPES
});
this.id = id;
this.id = options.projectId;
this.ns = options.namespace;
this.transaction = this.createTransaction_();
}

/**
* Helper to create a Key object, scoped to the namespace if present.
*
* @example
* ```js
* var key = dataset.key('Company', 123);
* ```
*/
Dataset.prototype.key = function() {
return new entity.Key({
namespace: this.ns,
path: [].slice.call(arguments)
});
};


/**
* Create a query from the current dataset to query the specified kinds.
*
Expand Down
39 changes: 19 additions & 20 deletions lib/datastore/entity.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,18 +89,22 @@ var SIGN_TO_ORDER = {
* Build a Datastore Key object.
*
* @constructor
* @param {...*} - Key descriptors.
* @param {object} - Configuration object.
* @param {...*} options.path - Key path.
* @param {string=} options.namespace - Optional namespace.
*
* @example
* ```js
* var key = new Key('Company', 123);
* ```
*/
function Key() {
if (arguments.length > 1) {
this.path_ = [].slice.call(arguments);
function Key(options) {
this.namespace_ = options.namespace;

if (options.path.length > 1) {
this.path_ = [].slice.call(options.path);
} else {
this.path_ = arguments[0];
this.path_ = options.path[0];
}
}

Expand Down Expand Up @@ -220,15 +224,17 @@ module.exports.entityFromEntityProto = entityFromEntityProto;
* ```
*/
function keyFromKeyProto(proto) {
var keyPath = [];
var keyOptions = {
path: []
};
if (proto.partition_id && proto.partition_id.namespace) {
keyPath.push(proto.partition_id.namespace);
keyOptions.namespace = proto.partition_id.namespace;
}
proto.path_element.forEach(function(path) {
keyPath.push(path.kind);
keyPath.push(Number(path.id) || path.name || null);
keyOptions.path.push(path.kind);
keyOptions.path.push(Number(path.id) || path.name || null);
});
return new Key(keyPath);
return new Key(keyOptions);
}

module.exports.keyFromKeyProto = keyFromKeyProto;
Expand Down Expand Up @@ -261,15 +267,8 @@ function keyToKeyProto(key) {
if (keyPath.length < 2) {
throw new Error('A key should contain at least a kind and an identifier.');
}
var namespace = null;
var start = 0;
if (keyPath.length % 2 === 1) {
// the first item is the namespace
namespace = keyPath[0];
start = 1;
}
var path = [];
for (var i = start; i < (keyPath.length - start); i += 2) {
for (var i = 0; i < keyPath.length; i += 2) {
var p = { kind: keyPath[i] };
var val = keyPath[i+1];
if (val) {
Expand All @@ -285,9 +284,9 @@ function keyToKeyProto(key) {
var proto = {
path_element: path
};
if (namespace) {
if (key.namespace_) {
proto.partition_id = {
namespace: namespace
namespace: key.namespace_
};
}
return proto;
Expand Down
12 changes: 0 additions & 12 deletions lib/datastore/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,6 @@ var datastore = {};
*/
datastore.Dataset = require('./dataset');

/**
* @borrows {module:datastore/entity~Key} as key
*
* @example
* ```js
* var key = dataset.key('Company', 123);
* ```
*/
datastore.key = function() {
return new entity.Key([].slice.call(arguments));
};

/**
* @borrows {module:datastore/entity~Int} as int
*
Expand Down
22 changes: 11 additions & 11 deletions test/datastore/dataset.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('Dataset', function() {
assert.equal(proto.key.length, 1);
callback(null, mockRespGet);
};
ds.get(datastore.key('Kind', 123), function(err, entity) {
ds.get(ds.key('Kind', 123), function(err, entity) {
var data = entity.data;
assert.deepEqual(entity.key.path_, ['Kind', 5732568548769792]);
assert.strictEqual(data.author, 'Silvano');
Expand All @@ -49,7 +49,7 @@ describe('Dataset', function() {
assert.equal(proto.key.length, 1);
callback(null, mockRespGet);
};
var key = datastore.key('Kind', 5732568548769792);
var key = ds.key('Kind', 5732568548769792);
ds.get([key], function(err, entities) {
var entity = entities[0];
var data = entity.data;
Expand All @@ -68,7 +68,7 @@ describe('Dataset', function() {
assert.equal(!!proto.mutation.delete, true);
callback();
};
ds.delete(datastore.key('Kind', 123), done);
ds.delete(ds.key('Kind', 123), done);
});

it('should multi delete by keys', function(done) {
Expand All @@ -79,8 +79,8 @@ describe('Dataset', function() {
callback();
};
ds.delete([
datastore.key('Kind', 123),
datastore.key('Kind', 345)
ds.key('Kind', 123),
ds.key('Kind', 345)
], done);
});

Expand All @@ -91,7 +91,7 @@ describe('Dataset', function() {
assert.equal(proto.mutation.insert_auto_id.length, 1);
callback();
};
var key = datastore.key('Kind', null);
var key = ds.key('Kind', null);
ds.save({ key: key, data: {} }, done);
});

Expand All @@ -106,8 +106,8 @@ describe('Dataset', function() {
callback();
};
ds.save([
{ key: datastore.key('Kind', 123), data: { k: 'v' } },
{ key: datastore.key('Kind', 456), data: { k: 'v' } }
{ key: ds.key('Kind', 123), data: { k: 'v' } },
{ key: ds.key('Kind', 456), data: { k: 'v' } }
], done);
});

Expand All @@ -126,16 +126,16 @@ describe('Dataset', function() {
]
});
};
ds.allocateIds(datastore.key('Kind', null), 1, function(err, ids) {
assert.deepEqual(ids[0], datastore.key('Kind', 123));
ds.allocateIds(ds.key('Kind', null), 1, function(err, ids) {
assert.deepEqual(ids[0], ds.key('Kind', 123));
done();
});
});

it('should throw if trying to allocate IDs with complete keys', function() {
var ds = new datastore.Dataset({ projectId: 'test' });
assert.throws(function() {
ds.allocateIds(datastore.key('Kind', 123));
ds.allocateIds(ds.key('Kind', 123));
});
});

Expand Down
46 changes: 33 additions & 13 deletions test/datastore/entity.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,26 +159,32 @@ describe('keyFromKeyProto', function() {

it('should handle keys hierarchically', function(done) {
var key = entity.keyFromKeyProto(protoH);
assert.deepEqual(key, datastore.key('Test', 'Kind', 111, 'Kind2', 'name'));
assert.deepEqual(key, new entity.Key({
namespace: 'Test',
path: [ 'Kind', 111, 'Kind2', 'name' ]
}));
done();
});

it('should handle incomplete keys hierarchically', function(done) {
var key = entity.keyFromKeyProto(protoHIncomplete);
assert.deepEqual(key, datastore.key('Test', 'Kind', null, 'Kind2', null));
assert.deepEqual(key, new entity.Key({
namespace: 'Test',
path: [ 'Kind', null, 'Kind2', null ]
}));
done();
});

it('should not set namespace if default', function(done) {
var key = entity.keyFromKeyProto(proto);
assert.deepEqual(key, datastore.key('Kind', 'Name'));
assert.deepEqual(key, new entity.Key({ path: [ 'Kind', 'Name' ] }));
done();
});
});

describe('keyToKeyProto', function() {
it('should handle hierarchical key definitions', function(done) {
var key = datastore.key('Kind1', 1, 'Kind2', 'name');
var key = new entity.Key({ path: [ 'Kind1', 1, 'Kind2', 'name' ] });
var proto = entity.keyToKeyProto(key);
assert.strictEqual(proto.partition_id, undefined);
assert.strictEqual(proto.path_element[0].kind, 'Kind1');
Expand All @@ -191,7 +197,10 @@ describe('keyToKeyProto', function() {
});

it('should detect the namespace of the hierarchical keys', function(done) {
var key = datastore.key('Namespace', 'Kind1', 1, 'Kind2', 'name');
var key = new entity.Key({
namespace: 'Namespace',
path: [ 'Kind1', 1, 'Kind2', 'name' ]
});
var proto = entity.keyToKeyProto(key);
assert.strictEqual(proto.partition_id.namespace, 'Namespace');
assert.strictEqual(proto.path_element[0].kind, 'Kind1');
Expand All @@ -204,8 +213,11 @@ describe('keyToKeyProto', function() {
});

it('should handle incomplete keys with & without namespaces', function(done) {
var key = datastore.key('Kind1', null);
var keyWithNS = datastore.key('Namespace', 'Kind1', null);
var key = new entity.Key({ path: [ 'Kind1', null ] });
var keyWithNS = new entity.Key({
namespace: 'Namespace',
path: [ 'Kind1', null ]
});

var proto = entity.keyToKeyProto(key);
var protoWithNS = entity.keyToKeyProto(keyWithNS);
Expand All @@ -232,10 +244,16 @@ describe('keyToKeyProto', function() {
describe('isKeyComplete', function() {
it('should ret true if kind and an identifier have !0 vals', function(done) {
[
{ key: datastore.key('Kind1', null), expected: false },
{ key: datastore.key('Kind1', 3), expected: true },
{ key: datastore.key('Namespace', 'Kind1', null), expected: false },
{ key: datastore.key('Namespace', 'Kind1', 'name'), expected: true }
{ key: new entity.Key({ path: [ 'Kind1', null ] }), expected: false },
{ key: new entity.Key({ path: [ 'Kind1', 3 ] }), expected: true },
{ key: new entity.Key({
namespace: 'Namespace',
path: [ 'Kind1', null ]
}), expected: false },
{ key: new entity.Key({
namespace: 'Namespace',
path: [ 'Kind1', 'name' ]
}), expected: true }
].forEach(function(test) {
assert.strictEqual(entity.isKeyComplete(test.key), test.expected);
});
Expand All @@ -247,7 +265,9 @@ describe('entityFromEntityProto', function() {
it('should support boolean, integer, double, string, entity and list values',
function(done) {
var obj = entity.entityFromEntityProto(entityProto);
assert.deepEqual(obj.linkedTo, datastore.key('Kind', 'another'));
assert.deepEqual(obj.linkedTo, new entity.Key({
path: [ 'Kind', 'another' ]
}));
assert.strictEqual(obj.name, 'Some name');
assert.strictEqual(obj.flagged, false);
assert.strictEqual(obj.count, 5);
Expand Down Expand Up @@ -305,7 +325,7 @@ describe('queryToQueryProto', function() {
var ds = new datastore.Dataset({ projectId: 'project-id' });
var q = ds.createQuery('Kind1')
.filter('name =', 'John')
.hasAncestor(datastore.key('Kind2', 'somename'));
.hasAncestor(new entity.Key({ path: [ 'Kind2', 'somename' ] }));
var proto = entity.queryToQueryProto(q);
assert.deepEqual(proto, queryFilterProto);
done();
Expand Down

0 comments on commit 8c8ab55

Please sign in to comment.