Skip to content

Commit

Permalink
FakeDynamo accounts for GSIs with no range keys
Browse files Browse the repository at this point in the history
  • Loading branch information
eduardoramirez committed Feb 28, 2018
1 parent e574195 commit fc86a09
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 7 deletions.
19 changes: 12 additions & 7 deletions lib/FakeDynamo.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ FakeTable.prototype.setRangeKey = function(name, type) {
/**
* Set GSI definitions for this table.
*
* @param {Array.<{hash:({name:(string), type:(string)}), range:({name:(string), type:(string)})}>} gsiDefinitions
* @param {Array.<{hash:({name:(string), type:(string)}), ?range:({name:(string), type:(string)})}>} gsiDefinitions
* @return {FakeTable} the current FakeTable instance
*/
FakeTable.prototype.setGsiDefinitions = function(gsiDefinitions) {
Expand Down Expand Up @@ -240,16 +240,21 @@ FakeTable.prototype.query = function(data) {
FakeTable.prototype._queryGlobalSecondaryIndex = function(data) {
var indexParts = data.IndexName.split('-')
var gsis = this.gsiDefinitions.filter(function (gsi) {
return indexParts.indexOf(gsi.hash.name) >= 0 &&
indexParts.indexOf(gsi.range.name) >= 0
if (gsi.range) {
return indexParts.indexOf(gsi.hash.name) >= 0 &&
indexParts.indexOf(gsi.range.name) >= 0
}
return indexParts.indexOf(gsi.hash.name) >= 0
})

if (gsis.length == 0) {
throw new Error('No gsi found for ' + data.IndexName)
}

// We should only find 1 gsi, so use the first one
this._validateFilterKeys(data, gsis[0].hash.name, gsis[0].range.name)
var hashKey = gsis[0].hash.name
var rangeKey = gsis[0].range && gsis[0].range.name
this._validateFilterKeys(data, hashKey, rangeKey)

// store keys, values, and conditions from data for easy access in scan
var keyConditionFn = getKeyConditionFn(data)
Expand Down Expand Up @@ -542,11 +547,11 @@ FakeTable.prototype._validateKeySize = function (key) {
*
* @param {Object} data
* @param {string} partitionKey
* @param {string} sortKey
* @param {?string} opt_sortKey
*/
FakeTable.prototype._validateFilterKeys = function (data, partitionKey, sortKey) {
FakeTable.prototype._validateFilterKeys = function (data, partitionKey, opt_sortKey) {
forEachFilterCondition(data, function (condition, key) {
if (key === partitionKey || key === sortKey) {
if (key === partitionKey || key === opt_sortKey) {
throw new DynamoError(
'ValidationException',
'Filter Expression can only contain non-primary key attributes: Primary key attribute: ' + key
Expand Down
35 changes: 35 additions & 0 deletions test/testFakeDynamo.js
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,41 @@ builder.add(function testQueryFilterOnGsiIndexThrowsError(test) {
})
})

builder.add(function testQueryFilterOnGsiWithNoRangeWorks(test) {
db.getTable('cookie').setGsiDefinitions([
{
hash: {
name: 'cookieType',
type: 'S'
}
}
])

db.getTable('cookie').setData({
'cookieA': {
1: {cookieId: 'cookieA', column: '1', createdAt: 1, orderedAt: 27, cookieType: 'Oreo'},
2: {cookieId: 'cookieA', column: '2', createdAt: 2, orderedAt: 29, cookieType: 'Oreo'}
},
'cookieB': {
1: {cookieId: 'cookieB', column: '1', createdAt: 2, orderedAt: 12, cookieType: 'Snickerdoodle'},
2: {cookieId: 'cookieB', column: '2', createdAt: 1, orderedAt: 14, cookieType: 'Snickerdoodle'}
}
})

var filter = client.newConditionBuilder()
.filterAttributeLessThan('orderedAt', 28)

return client.newQueryBuilder('cookie')
.setHashKey('cookieType', 'Oreo')
.setIndexName('index-cookieType-gsi')
.withFilter(filter)
.execute()
.then(function (data) {
test.equal(data.result.length, 1)
test.deepEqual(data.result[0], {cookieId: 'cookieA', column: '1', createdAt: 1, orderedAt: 27, cookieType: 'Oreo'})
})
})

builder.add(function testQueryFilterWithRangeWithIndexDoesNotThrowsError(test) {
var filter = client.newConditionBuilder()
.filterAttributeLessThan('createdAt', 30)
Expand Down

0 comments on commit fc86a09

Please sign in to comment.