Comparing version 0.3.5 to 0.4.0
@@ -6,2 +6,5 @@ var common = require('./common') | ||
// TODO(nick): Add an iterative API. | ||
/** @const */ | ||
@@ -68,3 +71,3 @@ var BATCH_LIMIT = 100 | ||
// Divde all the items to fetch into braches, BATCH_LIMIT (100) items each. | ||
// Divide the items into batches, BATCH_LIMIT (100) items each. | ||
for (var tableName in this._tableKeys) { | ||
@@ -165,4 +168,4 @@ var keys = this._tableKeys[tableName] | ||
.then(function (moreData) { | ||
builder._mergeTwoBatches(data, moreData) | ||
data.UnprocessedKeys = {} | ||
builder._mergeTwoBatches(data, moreData) | ||
return data | ||
@@ -180,2 +183,2 @@ }) | ||
module.exports = BatchGetItemBuilder | ||
module.exports = BatchGetItemBuilder |
@@ -5,2 +5,4 @@ var util = require('util') | ||
var typeUtil = require('./typeUtil') | ||
var DynamoResponse = require('./DynamoResponse') | ||
function Builder(options) { | ||
@@ -48,2 +50,6 @@ this._options = options || {} | ||
Builder.prototype.getPrefix = function () { | ||
return this._tablePrefix | ||
} | ||
Builder.prototype.setPrefix = function (prefix) { | ||
@@ -131,37 +137,3 @@ this._tablePrefix = prefix | ||
Builder.prototype.prepareOutput = function (output) { | ||
var data = {} | ||
if (output.ConsumedCapacityUnits) data.ConsumedCapacityUnits = output.ConsumedCapacityUnits | ||
if (output.ConsumedCapacityUnits !== undefined) data.ConsumedCapacityUnits = output.ConsumedCapacityUnits | ||
if (output.LastEvaluatedKey) data.LastEvaluatedKey = output.LastEvaluatedKey | ||
if (output.Count !== undefined) data.Count = output.Count | ||
// For batchGet | ||
if (output.UnprocessedKeys) { | ||
var unprocessed = {} | ||
for (var table in output.UnprocessedKeys) { | ||
unprocessed[table] = typeUtil.unpackObjects(output.UnprocessedKeys[table].Keys) | ||
} | ||
data.UnprocessedKeys = unprocessed | ||
} | ||
if (output.ConsumedCapacity) { | ||
var capacity = {} | ||
for (var i = 0; i < output.ConsumedCapacity.length; i++) { | ||
capacity[output.ConsumedCapacity[i].TableName] = output.ConsumedCapacity[i].CapacityUnits | ||
} | ||
data.ConsumedCapacity = capacity | ||
} | ||
if (output.Items) data.result = typeUtil.unpackObjects(output.Items) | ||
else if (output.Item) data.result = typeUtil.unpackObjects([output.Item])[0] | ||
else if (output.Attributes) data.result = typeUtil.unpackObjects([output.Attributes])[0] | ||
else if (output.Responses) { | ||
var result = {} | ||
for (var table in output.Responses) { | ||
var origTableName = this._tablePrefix ? table.substr(this._tablePrefix.length) : table | ||
result[origTableName] = typeUtil.unpackObjects(output.Responses[table]) | ||
} | ||
data.result = result | ||
} | ||
return data | ||
return new DynamoResponse(this._tablePrefix, output, null) | ||
} | ||
@@ -168,0 +140,0 @@ |
var ConditionBuilder = require('./ConditionBuilder') | ||
var assert = require('assert') | ||
var typeUtil = require('./typeUtil') | ||
@@ -24,3 +25,3 @@ function DynamoRequest(options) { | ||
for (var key in item) { | ||
this.data.Item[key] = valueToObject(item[key]) | ||
this.data.Item[key] = typeUtil.valueToObject(item[key]) | ||
} | ||
@@ -45,3 +46,3 @@ } | ||
for (var j = 0; j < keyCondition.attributes.length; j++) { | ||
conditionData.AttributeValueList.push(valueToObject(keyCondition.attributes[j])) | ||
conditionData.AttributeValueList.push(typeUtil.valueToObject(keyCondition.attributes[j])) | ||
} | ||
@@ -60,8 +61,8 @@ } | ||
} else { | ||
this.data.AttributeUpdates[key] = {Value: valueToObject(updates[key].del), Action: 'DELETE'} | ||
this.data.AttributeUpdates[key] = {Value: typeUtil.valueToObject(updates[key].del), Action: 'DELETE'} | ||
} | ||
} else if (typeof updates[key].increment !== 'undefined') { | ||
this.data.AttributeUpdates[key] = {Value: valueToObject(updates[key].increment), Action: 'ADD'} | ||
this.data.AttributeUpdates[key] = {Value: typeUtil.valueToObject(updates[key].increment), Action: 'ADD'} | ||
} else { | ||
this.data.AttributeUpdates[key] = {Value: valueToObject(updates[key].val), Action: 'PUT'} | ||
this.data.AttributeUpdates[key] = {Value: typeUtil.valueToObject(updates[key].val), Action: 'PUT'} | ||
} | ||
@@ -84,13 +85,24 @@ } | ||
for (var key in filter) { | ||
if (filter[key][0] === 'BETWEEN') { | ||
this.data.ScanFilter[key] = {AttributeValueList:[valueToObject(filter[key][1]), valueToObject(filter[key][2])], ComparisonOperator: filter[key][0]} | ||
} else if (filter[key][0] === 'IN') { | ||
var values = [] | ||
var op = filter[key][0] | ||
var attrList = null | ||
if (op === 'BETWEEN') { | ||
attrList = [typeUtil.valueToObject(filter[key][1]), typeUtil.valueToObject(filter[key][2])] | ||
} else if (op === 'IN') { | ||
attrList = [] | ||
for (var i = 1; i < filter[key].length; i += 1) { | ||
values.push(valueToObject(filter[key][i])) | ||
attrList.push(typeUtil.valueToObject(filter[key][i])) | ||
} | ||
this.data.ScanFilter[key] = {AttributeValueList: values, ComparisonOperator: filter[key][0]} | ||
} else if (op === 'NULL' || op === 'NOT_NULL') { | ||
attrList = null | ||
} else { | ||
this.data.ScanFilter[key] = {AttributeValueList:[valueToObject(filter[key][1])], ComparisonOperator: filter[key][0]} | ||
// All other ops have 1 argument. | ||
attrList = [typeUtil.valueToObject(filter[key][1])] | ||
} | ||
this.data.ScanFilter[key] = { | ||
ComparisonOperator: op | ||
} | ||
if (attrList) { | ||
this.data.ScanFilter[key].AttributeValueList = attrList | ||
} | ||
} | ||
@@ -116,3 +128,3 @@ } | ||
} else { | ||
this.data.Expected[key] = {Value: valueToObject(attr.val)} | ||
this.data.Expected[key] = {Value: typeUtil.valueToObject(attr.val)} | ||
} | ||
@@ -141,3 +153,3 @@ } | ||
this.data.Key[key.name] = valueToObject(key.val) | ||
this.data.Key[key.name] = typeUtil.valueToObject(key.val) | ||
@@ -151,3 +163,3 @@ return this | ||
this.data.Key[key.name] = valueToObject(key.val) | ||
this.data.Key[key.name] = typeUtil.valueToObject(key.val) | ||
@@ -159,3 +171,3 @@ return this | ||
if (key) { | ||
this.data.ExclusiveStartKey = key | ||
this.data.ExclusiveStartKey = typeUtil.packObjectOrArray(key) | ||
} | ||
@@ -225,3 +237,3 @@ return this | ||
var dynamoKeys = {} | ||
for (var key in keys) dynamoKeys[key] = valueToObject(keys[key]) | ||
for (var key in keys) dynamoKeys[key] = typeUtil.valueToObject(keys[key]) | ||
this.data.RequestItems[tableNameWithPrefix].Keys.push(dynamoKeys) | ||
@@ -248,50 +260,2 @@ } | ||
/** | ||
* @param {number|string|Array} value | ||
*/ | ||
function valueToObject(value) { | ||
var type = typeof value | ||
if (Array.isArray(value)) { | ||
var firstItemType = typeof value[0] | ||
// check that all of the items are of the same type; that of the first element's | ||
for (var i = 0; i < value.length; i++) { | ||
if (typeof value[i] !== firstItemType) { | ||
throw new Error('Inconsistent types in set! Expecting all types to be the same as the first element\'s: ' + firstItemType) | ||
} | ||
} | ||
if (firstItemType === 'string') { | ||
return {SS: value} | ||
} else { | ||
if (firstItemType !== 'number') { | ||
throw new Error('Invalid dynamo set value. Type: ' + firstItemType + ', Value: ' + value[0]) | ||
} | ||
var numArray = [] | ||
for (var i = 0; i < value.length; i++) { | ||
numArray.push(String(value[i])) | ||
} | ||
return {NS: numArray} | ||
} | ||
} else if (type === 'string') { | ||
return {S: value} | ||
} else { | ||
if (type !== 'number') { | ||
// TODO(nick): I'm pretty sure this should be an error. But there is a bunch | ||
// of code relying on this behavior, so just log the error for now and | ||
// we'll track down the problems in the logs. | ||
// | ||
// Xiao: Nick, agreed. Examples of places that depend on this behavior: | ||
// (1) ScanBuilder.filterAttributeNull | ||
// (2) ScanBuilder.filterAttributeNotNull | ||
console.error('Invalid dynamo value. Type: ' + type + ', Value: ' + value) | ||
} | ||
return {N: String(value)} | ||
} | ||
} | ||
module.exports = DynamoRequest |
@@ -196,3 +196,3 @@ var Q = require('kew') | ||
var attributes = this._getAttributesFromData(queryData) | ||
ret.Items = typeUtil.packObjects(filteredResults, attributes) | ||
ret.Items = typeUtil.packObjectOrArray(filteredResults, attributes) | ||
return Q.resolve(ret) | ||
@@ -211,3 +211,3 @@ } | ||
var exclusiveStartKey = queryData.ExclusiveStartKey ? | ||
typeUtil.unpackObjects(queryData.ExclusiveStartKey) : undefined | ||
typeUtil.unpackObjectOrArray(queryData.ExclusiveStartKey) : undefined | ||
@@ -238,3 +238,3 @@ // TODO(nick): Fix this to work for backward queries/scans. | ||
primaryKeyAttribute[this.primaryKey.range.name] = true | ||
return typeUtil.packObjects(item, primaryKeyAttribute) | ||
return typeUtil.packObjectOrArray(item, primaryKeyAttribute) | ||
} | ||
@@ -395,3 +395,3 @@ | ||
return Q.resolve({ | ||
Attributes: typeUtil.packObjects(item), | ||
Attributes: typeUtil.packObjectOrArray(item), | ||
ConsumedCapacity: 1 | ||
@@ -438,3 +438,3 @@ }) | ||
return Q.resolve({ | ||
Item: typeUtil.packObjects(item, attributes), | ||
Item: typeUtil.packObjectOrArray(item, attributes), | ||
ConsumedCapacity: 1 | ||
@@ -441,0 +441,0 @@ }) |
@@ -21,3 +21,3 @@ var common = require('./common') | ||
return this.request("getItem", queryData) | ||
.then(this.prepareOutput) | ||
.then(this.prepareOutput.bind(this)) | ||
.fail(this.emptyResult) | ||
@@ -29,2 +29,2 @@ .setContext({data: queryData, isWrite: false}) | ||
module.exports = GetItemBuilder | ||
module.exports = GetItemBuilder |
var common = require('./common') | ||
var typ = require('typ') | ||
var DynamoRequest = require('./DynamoRequest') | ||
var DynamoResponse = require('./DynamoResponse') | ||
var Builder = require('./Builder') | ||
@@ -100,2 +101,17 @@ | ||
/** @override */ | ||
QueryBuilder.prototype.prepareOutput = function (output) { | ||
return new DynamoResponse( | ||
this.getPrefix(), output, this._repeatWithStartKey.bind(this)) | ||
} | ||
/** | ||
* @param {Object} key | ||
* @return {Q.<DynamoResponse>} | ||
* @private | ||
*/ | ||
QueryBuilder.prototype._repeatWithStartKey = function (nextKey) { | ||
return this.setStartKey(nextKey).execute() | ||
} | ||
QueryBuilder.prototype.execute = function () { | ||
@@ -122,3 +138,3 @@ var query = new DynamoRequest(this.getOptions()) | ||
return this.request("query", queryData) | ||
.then(this.prepareOutput) | ||
.then(this.prepareOutput.bind(this)) | ||
.fail(this.emptyResults) | ||
@@ -125,0 +141,0 @@ .setContext({attributes: queryData, isWrite: false}) |
var common = require('./common') | ||
var typ = require('typ') | ||
var DynamoRequest = require('./DynamoRequest') | ||
var DynamoResponse = require('./DynamoResponse') | ||
var Builder = require('./Builder') | ||
@@ -107,2 +108,17 @@ | ||
/** @override */ | ||
ScanBuilder.prototype.prepareOutput = function (output) { | ||
return new DynamoResponse( | ||
this.getPrefix(), output, this._repeatWithStartKey.bind(this)) | ||
} | ||
/** | ||
* @param {Object} key | ||
* @return {Q.<DynamoResponse>} | ||
* @private | ||
*/ | ||
ScanBuilder.prototype._repeatWithStartKey = function (nextKey) { | ||
return this.setStartKey(nextKey).execute() | ||
} | ||
ScanBuilder.prototype.execute = function () { | ||
@@ -119,3 +135,3 @@ var queryData = new DynamoRequest(this.getOptions()) | ||
return this.request("scan", queryData) | ||
.then(this.prepareOutput) | ||
.then(this.prepareOutput.bind(this)) | ||
.fail(this.emptyResults) | ||
@@ -127,2 +143,2 @@ .setContext({data: queryData, isWrite: false}) | ||
module.exports = ScanBuilder | ||
module.exports = ScanBuilder |
@@ -17,5 +17,5 @@ // Copyright 2013 The Obvious Corporation | ||
*/ | ||
function unpackObjects(object) { | ||
function unpackObjectOrArray(object) { | ||
if (typ.isNullish(object)) return object | ||
if (Array.isArray(object)) return object.map(unpackObjects) | ||
if (Array.isArray(object)) return object.map(unpackObjectOrArray) | ||
@@ -36,8 +36,6 @@ var item = {} | ||
*/ | ||
function packObjects(object, attributes) { | ||
function packObjectOrArray(object, attributes) { | ||
if (typ.isNullish(object)) return object | ||
if (Array.isArray(object)) { | ||
var ret = [] | ||
object.forEach(function (obj) { ret.push(packObjects(obj, attributes)) }) | ||
return ret | ||
return object.map(function (obj) { return packObjectOrArray(obj, attributes) }) | ||
} | ||
@@ -48,37 +46,49 @@ | ||
if (attributes && !attributes[key]) continue | ||
newObj[key] = valueToObject(object[key]) | ||
} | ||
return newObj | ||
} | ||
if (Array.isArray(object[key])) { | ||
// array field | ||
var firstType = typeof object[key][0] | ||
var consistentType = firstType | ||
object[key].map(function (attr) { | ||
if ((typeof attr) !== firstType) throw new Error('Array types must all be the same') | ||
}) | ||
/** | ||
* @param {number|string|Array} value | ||
*/ | ||
function valueToObject(value) { | ||
var type = typeof value | ||
if (firstType === 'string') { | ||
newObj[key] = { | ||
SS: object[key] | ||
} | ||
} else if (firstType === 'number') { | ||
newObj[key] = { | ||
NS: object[key] | ||
} | ||
} else { | ||
throw new Error('Only arrays of strings and numbers are allowed. Unknown type: ' + firstType) | ||
if (Array.isArray(value)) { | ||
var firstItemType = typeof value[0] | ||
// check that all of the items are of the same type; that of the first element's | ||
for (var i = 0; i < value.length; i++) { | ||
if (typeof value[i] !== firstItemType) { | ||
throw new Error('Inconsistent types in set! Expecting all types to be the same as the first element\'s: ' + firstItemType) | ||
} | ||
} else if (typeof object[key] === 'string') { | ||
// string field | ||
newObj[key] = { | ||
S: object[key] | ||
} | ||
if (firstItemType === 'string') { | ||
return {SS: value} | ||
} else { | ||
if (firstItemType !== 'number') { | ||
throw new Error('Invalid dynamo set value. Type: ' + firstItemType + ', Value: ' + value[0]) | ||
} | ||
} else if (typeof object[key] === 'number') { | ||
// number field | ||
newObj[key] = { | ||
N: object[key] | ||
var numArray = [] | ||
for (var i = 0; i < value.length; i++) { | ||
numArray.push(String(value[i])) | ||
} | ||
} else { | ||
throw new Error('Unknown object type at ' + key) | ||
return {NS: numArray} | ||
} | ||
} else if (type === 'string') { | ||
return {S: value} | ||
} else { | ||
if (type !== 'number') { | ||
// TODO(nick): I'm pretty sure this should be an error. But there is a bunch | ||
// of code relying on this behavior, so just log the error for now and | ||
// we'll track down the problems in the logs. | ||
console.error('Invalid dynamo value. Type: ' + type + ', Value: ' + value, new Error().stack) | ||
} | ||
return {N: String(value)} | ||
} | ||
return newObj | ||
} | ||
@@ -107,4 +117,5 @@ | ||
module.exports = { | ||
unpackObjects: unpackObjects, | ||
packObjects: packObjects | ||
unpackObjectOrArray: unpackObjectOrArray, | ||
packObjectOrArray: packObjectOrArray, | ||
valueToObject: valueToObject | ||
} |
@@ -62,3 +62,3 @@ var common = require('./common') | ||
return this.request("updateItem", queryData) | ||
.then(this.prepareOutput) | ||
.then(this.prepareOutput.bind(this)) | ||
.setContext({data: queryData, isWrite: true}) | ||
@@ -69,2 +69,2 @@ .fail(this.convertErrors) | ||
module.exports = UpdateBuilder | ||
module.exports = UpdateBuilder |
{ | ||
"name": "dynamite", | ||
"description": "promise-based DynamoDB client", | ||
"version": "0.3.5", | ||
"version": "0.4.0", | ||
"homepage": "https://github.com/Obvious/dynamite", | ||
@@ -6,0 +6,0 @@ "licenses" : [ |
@@ -309,4 +309,16 @@ # Dynamite | ||
There exist a variety of methods that refine and restrict the returned set of results that operate on the indexed range key, which in our sample case is `column`. | ||
The result of the query will be a DynamoResult object with a `result` property for the result set. | ||
DynamoResult also has two methods: | ||
+ hasNext(): boolean | ||
Returns whether there are remaining results for this query. | ||
+ next(): Promise.<DynamoResult> | ||
Executes a new query that fetches the next page of results. | ||
There are also a variety of methods that refine and restrict the returned set of results that operate on the indexed range key, which in our sample case is `column`. | ||
#### getCount() | ||
@@ -334,2 +346,4 @@ | ||
In general, calling setStartKey directly is discouraged in favor of using the `next()` method described above. | ||
#### setLimit(max) | ||
@@ -336,0 +350,0 @@ |
@@ -33,3 +33,3 @@ // Copyright 2013 The Obvious Corporation. | ||
var muchoData = [] | ||
var junk = new Array(100000).join('.') | ||
var junk = new Array(62000).join('.') | ||
for (var i = 0; i < 101; i++) { | ||
@@ -39,4 +39,2 @@ muchoData.push({'hashKey': 'id' + i, 'column': '@', 'data': junk}) | ||
// basic setup for the tests, creating record userA with range key @ | ||
@@ -90,8 +88,4 @@ exports.setUp = function (done) { | ||
.then(function (data) { | ||
test.equal(data.ConsumedCapacity.user, 1) | ||
test.equal(data.ConsumedCapacity.phones, 1) | ||
var ages = data.result.user.map(function (user) { return user.age }) | ||
test.deepEqual(ages, ['29', '44']) | ||
var phones = data.result.phones.map(function (phone) { return phone.number }) | ||
@@ -98,0 +92,0 @@ test.deepEqual(phones, ['415-662-1234', '550-555-5555']) |
@@ -6,2 +6,3 @@ // Copyright 2013 The Obvious Corporation. | ||
var typ = require('typ') | ||
var errors = require('../lib/errors') | ||
var nodeunitq = require('nodeunitq') | ||
@@ -117,5 +118,3 @@ var builder = new nodeunitq.Builder(exports) | ||
}) | ||
.fail(function (e) { | ||
test.equal(e.message.indexOf('conditional') !== -1, true, "Conditional request should fail") | ||
}) | ||
.fail(this.client.throwUnlessConditionalError) | ||
}) | ||
@@ -138,5 +137,3 @@ | ||
}) | ||
.fail(function (e) { | ||
test.equal(e.message.indexOf('conditional') !== -1, true, "Conditional request should fail") | ||
}) | ||
.fail(this.client.throwUnlessConditionalError) | ||
}) | ||
@@ -159,5 +156,3 @@ | ||
}) | ||
.fail(function (e) { | ||
test.equal(e.message.indexOf('conditional') !== -1, true, "Conditional request should fail") | ||
}) | ||
.fail(this.client.throwUnlessConditionalError) | ||
}) | ||
@@ -164,0 +159,0 @@ |
@@ -131,3 +131,3 @@ // Copyright 2013 The Obvious Corporation | ||
test.deepEqual(result[1], {userId: 'userA', column: '2', age: '28'}) | ||
test.deepEqual(data.LastEvaluatedKey, typeUtil.packObjects({userId: 'userA', column: '2'})) | ||
test.deepEqual(data.LastEvaluatedKey, {userId: 'userA', column: '2'}) | ||
}) | ||
@@ -148,3 +148,3 @@ }) | ||
return client.newScanBuilder('user') | ||
.setStartKey(typeUtil.packObjects({userId: 'userA', column: '2'})) | ||
.setStartKey({userId: 'userA', column: '2'}) | ||
.execute() | ||
@@ -260,3 +260,3 @@ .then(function (data) { | ||
test.equal(data.result.length, 2) | ||
test.deepEqual(data.LastEvaluatedKey, {userId: {S: 'userA'}, column: {S: '3'}}) | ||
test.deepEqual(data.LastEvaluatedKey, {userId: 'userA', column: '3'}) | ||
@@ -296,4 +296,4 @@ return client.newQueryBuilder('user') | ||
test.equal(data.result.length, 1) | ||
test.deepEqual(data.LastEvaluatedKey, {userId: {S: 'userA'}, column: {S: '2'}}) | ||
test.deepEqual(data.LastEvaluatedKey, {userId: 'userA', column: '2'}) | ||
}) | ||
}) |
@@ -7,2 +7,3 @@ // Copyright 2013 The Obvious Corporation. | ||
var builder = new nodeunitq.Builder(exports) | ||
var errors = require('../lib/errors') | ||
@@ -151,5 +152,3 @@ var onError = console.error.bind(console) | ||
}) | ||
.fail(function (e) { | ||
test.equal(e.message.indexOf('conditional') !== -1, true, "Conditional request should fail") | ||
}) | ||
.fail(this.client.throwUnlessConditionalError) | ||
}) | ||
@@ -174,5 +173,3 @@ | ||
}) | ||
.fail(function (e) { | ||
test.equal(e.message.indexOf('conditional') !== -1, true, "Conditional request should fail") | ||
}) | ||
.fail(this.client.throwUnlessConditionalError) | ||
}) | ||
@@ -197,5 +194,3 @@ | ||
}) | ||
.fail(function (e) { | ||
test.equal(e.message.indexOf('conditional') !== -1, true, "Conditional request should fail") | ||
}) | ||
.fail(this.client.throwUnlessConditionalError) | ||
}) |
var utils = require('./utils/testUtils.js') | ||
var dynamite = require('../dynamite') | ||
var errors = require('../lib/errors') | ||
var nodeunitq = require('nodeunitq') | ||
@@ -205,5 +206,3 @@ var builder = new nodeunitq.Builder(exports) | ||
}) | ||
.fail(function (e) { | ||
test.equal(e.message.indexOf('conditional') !== -1, true, "Conditional request should fail") | ||
}) | ||
.fail(this.client.throwUnlessConditionalError) | ||
}) | ||
@@ -231,5 +230,3 @@ | ||
}) | ||
.fail(function (e) { | ||
test.equal(e.message.indexOf('conditional') !== -1, true, "Conditional request should fail") | ||
}) | ||
.fail(this.client.throwUnlessConditionalError) | ||
}) | ||
@@ -257,5 +254,3 @@ | ||
}) | ||
.fail(function (e) { | ||
test.equal(e.message.indexOf('conditional') !== -1, true, "Conditional request should fail") | ||
}) | ||
.fail(this.client.throwUnlessConditionalError) | ||
}) |
@@ -271,1 +271,25 @@ // Copyright 2013 The Obvious Corporation. | ||
}) | ||
builder.add(function testNext(test) { | ||
return this.client.newQueryBuilder('comments') | ||
.setHashKey('postId', 'post1') | ||
.indexBetween('column', '/comment/', '/comment/timestamp/999999') | ||
.setLimit(3) | ||
.execute() | ||
.then(function (data) { | ||
test.equal(3, data.Count) | ||
test.ok(data.hasNext()) | ||
return data.next() | ||
}) | ||
.then(function (data) { | ||
test.equal(1, data.Count) | ||
test.ok(!data.hasNext()) | ||
return data.next() | ||
}) | ||
.then(function (data) { | ||
test.fail('Expected error') | ||
}) | ||
.fail(function (e) { | ||
if (e.message !== 'No more results') throw e | ||
}) | ||
}) |
@@ -11,5 +11,5 @@ // Copyright 2013 The Obvious Corporation. | ||
var tableName = "user" | ||
var rawData = [{"userId": "c", "column": "@", "post": "3", "email": "1@medium.com"}, | ||
var rawData = [{"userId": "a", "column": "@", "post": "3", "email": "1@medium.com"}, | ||
{"userId": "b", "column": "@", "post": "0", "address": "800 Market St. SF, CA"}, | ||
{"userId": "a", "column": "@", "post": "5", "email": "3@medium"}, | ||
{"userId": "c", "column": "@", "post": "5", "email": "3@medium"}, | ||
{"userId": "d", "column": "@", "post": "2", "twitter": "haha"}, | ||
@@ -52,4 +52,5 @@ {"userId": "e", "column": "@", "post": "2", "twitter": "hoho"}, | ||
test.equal(data.result.length, expect.length, expect.length + " records should be returned") | ||
data.result.sort(function(a, b) {return (a.userId < b.userId) ? -1 : ((a.userId > b.userId) ? 1 : 0)}) | ||
for (var i = 0; i < data.result.length; i++) { | ||
test.deepEqual(data.result[i], rawData[expect[i]], "Row should be retrieved in the correct order") | ||
test.deepEqual(data.result[i], rawData[expect[i]], "Some records are wrong") | ||
} | ||
@@ -62,3 +63,3 @@ }) | ||
var scan = this.client.newScanBuilder(tableName) | ||
return scanAndCheck(scan, [2, 1, 0, 3, 4, 5, 6], test) | ||
return scanAndCheck(scan, [0, 1, 2, 3, 4, 5, 6], test) | ||
}) | ||
@@ -77,3 +78,3 @@ | ||
.filterAttributeNotEquals("post", 2) | ||
return scanAndCheck(scan, [2, 1, 0, 5, 6], test) | ||
return scanAndCheck(scan, [0, 1, 2, 5, 6], test) | ||
}) | ||
@@ -99,3 +100,3 @@ | ||
.filterAttributeGreaterThanEqual("post", 2) | ||
return scanAndCheck(scan, [2, 0, 3, 4, 5, 6], test) | ||
return scanAndCheck(scan, [0, 2, 3, 4, 5, 6], test) | ||
}) | ||
@@ -107,3 +108,3 @@ | ||
.filterAttributeGreaterThan("post", 2) | ||
return scanAndCheck(scan, [2, 0, 5, 6], test) | ||
return scanAndCheck(scan, [0, 2, 5, 6], test) | ||
}) | ||
@@ -115,6 +116,6 @@ | ||
.filterAttributeNotNull("post") | ||
return scanAndCheck(scan, [2, 1, 0, 3, 4, 5, 6], test) | ||
return scanAndCheck(scan, [0, 1, 2, 3, 4, 5, 6], test) | ||
scan = this.client.newScanBuilder(tableName) | ||
.filterAttributeNotNull("email") | ||
return scanAndCheck(scan, [2, 0, 5], test) | ||
return scanAndCheck(scan, [0, 2, 5], test) | ||
}) | ||
@@ -126,3 +127,3 @@ | ||
.filterAttributeContains("email", "medium") | ||
return scanAndCheck(scan, [2, 0], test) | ||
return scanAndCheck(scan, [0, 2], test) | ||
}) | ||
@@ -171,1 +172,28 @@ | ||
}) | ||
builder.add(function testNext(test) { | ||
var numInFirstScan = 0 | ||
return this.client.newScanBuilder(tableName) | ||
.filterAttributeGreaterThan("post", 2) | ||
// The limit is *not* the number of records to return; instead it is | ||
// the number of records to scan. So the actual number of records returned | ||
// is not specified when a filter is given. | ||
.setLimit(4) | ||
.execute() | ||
.then(function (data) { | ||
numInFirstScan = data.Count | ||
test.ok(data.hasNext()) | ||
return data.next() | ||
}) | ||
.then(function (data) { | ||
test.equal(4, numInFirstScan + data.Count, 'Scan should return 4 records in total') | ||
test.ok(!data.hasNext()) | ||
return data.next() | ||
}) | ||
.then(function (data) { | ||
test.fail('Expected error') | ||
}) | ||
.fail(function (e) { | ||
if (e.message !== 'No more results') throw e | ||
}) | ||
}) |
@@ -5,2 +5,3 @@ // Copyright 2013 The Obvious Corporation. | ||
var dynamite = require('../dynamite') | ||
var errors = require('../lib/errors') | ||
var nodeunitq = require('nodeunitq') | ||
@@ -78,3 +79,3 @@ var builder = new nodeunitq.Builder(exports) | ||
//test putting attributes with empty and null values | ||
//test putting attributes with empty would succeed | ||
builder.add(function testPutAttributeEmpty(test) { | ||
@@ -306,5 +307,3 @@ var self = this | ||
}) | ||
.fail(function (e) { | ||
test.equal(e.message.indexOf('conditional') !== -1, true, "Conditional request should fail") | ||
}) | ||
.fail(this.client.throwUnlessConditionalError) | ||
}) | ||
@@ -329,5 +328,3 @@ | ||
}) | ||
.fail(function (e) { | ||
test.equal(e.message.indexOf('conditional') !== -1, true, "Conditional request should fail") | ||
}) | ||
.fail(this.client.throwUnlessConditionalError) | ||
}) | ||
@@ -352,5 +349,3 @@ | ||
}) | ||
.fail(function (e) { | ||
test.equal(e.message.indexOf('conditional') !== -1, true, "Conditional request should fail") | ||
}) | ||
.fail(this.client.throwUnlessConditionalError) | ||
}) | ||
@@ -357,0 +352,0 @@ |
@@ -68,3 +68,3 @@ /** | ||
RangeKeyElement: {AttributeName: rangeKey, AttributeType: "S"}}, | ||
ProvisionedThroughput: {ReadCapacityUnits: 0, WriteCapacityUnits: 0} | ||
ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1} | ||
}, | ||
@@ -80,3 +80,3 @@ defer.makeNodeResolver() | ||
{AttributeName: rangeKey, KeyType: "RANGE"}], | ||
ProvisionedThroughput: {ReadCapacityUnits: 0, WriteCapacityUnits: 0} | ||
ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1} | ||
}, | ||
@@ -137,5 +137,3 @@ defer.makeNodeResolver() | ||
db.putItem( | ||
{TableName: tableName, | ||
Item: convert(record) | ||
}, | ||
{TableName: tableName, Item: convert(record)}, | ||
defer.makeNodeResolver() | ||
@@ -154,13 +152,7 @@ ) | ||
var db = context.db | ||
var p = null | ||
var helper = function (i) { | ||
return function (e) { | ||
return putOneRecord(db, context.tableName, context.data[i]) | ||
}; | ||
var promises = [] | ||
for (var i = 0; i < context.data.length; i += 1) { | ||
promises.push(putOneRecord(db, context.tableName, context.data[i])) | ||
} | ||
p = putOneRecord(db, context.tableName, context.data[0]); | ||
for (var i = 1; i < context.data.length; i += 1) { | ||
p = p.then(helper(i)) | ||
} | ||
return p | ||
return Q.all(promises) | ||
} | ||
@@ -167,0 +159,0 @@ |
168009
35
4087
471