UNPKG

3.82 kBJavaScriptView Raw
1var once = require('once'),
2 db = require('../db')
3
4module.exports = function scan(store, data, cb) {
5 cb = once(cb)
6
7 store.getTable(data.TableName, function(err, table) {
8 if (err) return cb(err)
9
10 var keySchema = table.KeySchema, startKeyNames = keySchema.map(function(key) { return key.AttributeName }),
11 fetchFromItemDb = false, isLocal
12
13 if (data.IndexName) {
14 var index = db.traverseIndexes(table, function(attr, type, index, isGlobal) {
15 if (index.IndexName == data.IndexName) {
16 isLocal = !isGlobal
17 return index
18 }
19 })
20 if (index == null) {
21 return cb(db.validationError('The table does not have the specified index: ' + data.IndexName))
22 }
23 if (!isLocal && data.ConsistentRead) {
24 return cb(db.validationError('Consistent reads are not supported on global secondary indexes'))
25 }
26 keySchema = index.KeySchema
27 fetchFromItemDb = data.Select == 'ALL_ATTRIBUTES' && index.Projection.ProjectionType != 'ALL'
28 keySchema.forEach(function(key) { if (!~startKeyNames.indexOf(key.AttributeName)) startKeyNames.push(key.AttributeName) })
29 }
30
31 if (data.ExclusiveStartKey && Object.keys(data.ExclusiveStartKey).length != startKeyNames.length) {
32 return data.IndexName ? cb(db.validationError('The provided starting key is invalid')) :
33 cb(db.validationError('The provided starting key is invalid: The provided key element does not match the schema'))
34 }
35
36 if (data.IndexName && data.ExclusiveStartKey) {
37 err = db.traverseKey(table, keySchema, function(attr, type, isHash) {
38 if (!data.ExclusiveStartKey[attr]) {
39 return db.validationError('The provided starting key is invalid')
40 }
41 return db.validateKeyPiece(data.ExclusiveStartKey, attr, type, isHash)
42 })
43 if (err) return cb(err)
44 }
45
46 if (fetchFromItemDb && !isLocal) {
47 return cb(db.validationError('One or more parameter values were invalid: ' +
48 'Select type ALL_ATTRIBUTES is not supported for global secondary index ' +
49 data.IndexName + ' because its projection type is not ALL'))
50 }
51
52 if (data.ExclusiveStartKey) {
53 var tableStartKey = table.KeySchema.reduce(function(obj, attr) {
54 obj[attr.AttributeName] = data.ExclusiveStartKey[attr.AttributeName]
55 return obj
56 }, {})
57 if ((err = db.validateKey(tableStartKey, table)) != null) {
58 return cb(db.validationError('The provided starting key is invalid: ' + err.message))
59 }
60 }
61
62 if (data.TotalSegments > 1) {
63 if (data.Segment > 0)
64 var hashStart = ('00' + Math.ceil(4096 * data.Segment / data.TotalSegments).toString(16)).slice(-3)
65 var hashEnd = ('00' + (Math.ceil(4096 * (data.Segment + 1) / data.TotalSegments) - 1).toString(16)).slice(-3) + '~'
66 }
67
68 if (data.ExclusiveStartKey) {
69 var startKey = db.createIndexKey(data.ExclusiveStartKey, table, keySchema)
70
71 if (data.TotalSegments > 1 && (startKey < hashStart || startKey > hashEnd)) {
72 return cb(db.validationError('The provided starting key is invalid: Invalid ExclusiveStartKey. ' +
73 'Please use ExclusiveStartKey with correct Segment. ' +
74 'TotalSegments: ' + data.TotalSegments + ' Segment: ' + data.Segment))
75 }
76
77 hashStart = startKey
78 }
79
80 if ((err = db.validateKeyPaths((data._projection || {}).nestedPaths, table)) != null) return cb(err)
81
82 if ((err = db.validateKeyPaths((data._filter || {}).nestedPaths, table)) != null) return cb(err)
83
84 var opts = {limit: data.Limit ? data.Limit + 1 : -1}
85
86 if (hashStart != null) {
87 opts.gt = hashStart
88 }
89 if (hashEnd != null) {
90 opts.lt = hashEnd
91 }
92
93 db.queryTable(store, table, data, opts, isLocal, fetchFromItemDb, startKeyNames, cb)
94 })
95}