ydn.db
Version:
Javascript database library for IndexedDB, WebDatabase (WebSQL) and WebStorage (localStorage) storage mechanisms supporting version migration, advanced query and transaction workflow.
701 lines (588 loc) • 18.9 kB
JavaScript
(function() {
var db_name = 'test_query_count';
var store_inline = 'ts'; // in-line key store
var store_inline_index = 'ts6'; // in-line key store
var schema_1 = {
stores: [
{
name: store_inline,
keyPath: 'id'
},
{
name: store_inline_index,
keyPath: 'id',
type: 'NUMERIC',
indexes: [
{name: 'name', type: 'TEXT'},
{name: 'value', type: 'NUMERIC'},
{name: 'name, value', keyPath: ['name', 'value']}
]
}
]
};
var db_r;
var df = $.Deferred();
// persist store data.
(function() {
var _db = new ydn.db.Storage(db_name, schema_1, options);
_db.clear(store_inline_index);
_db.put(store_inline_index, [
{id: 1, value: 2, name: 'a' + Math.random()},
{id: 2, value: 2, name: 'b' + Math.random()},
{id: 3, value: 2, name: 'b' + Math.random()},
{id: 4, value: 3, name: 'c' + Math.random()}
]);
_db.clear(store_inline);
_db.put(store_inline, [
{id: 1, value: 'v' + Math.random()},
{id: 2, value: 'v' + Math.random()},
{id: 3, value: 'v' + Math.random()},
{id: 4, value: 'v' + Math.random()}
]);
_db.count(store_inline_index).always(function() {
_db.close();
setTimeout(function() {
df.resolve();
}, 100);
});
})();
var test_count = 0;
var test_env = {
setup: function() {
db_r = new ydn.db.Storage(db_name, schema_1, options);
},
teardown: function() {
db_r.close();
test_count++;
if (test_count == 2) {
var type = db_r.getType();
ydn.db.deleteDatabase(db_name, type);
}
}
};
module('query,count', test_env);
reporter.createTestSuite('query');
asyncTest('primary key', 2, function() {
df.always(function() {
var q = db_r.from(store_inline);
q.count().always(function(x) {
equal(x, 4, 'all records');
});
q = db_r.from(store_inline, '>', 1, '<=', 3);
q.count().always(function(x) {
equal(x, 2, 'number of records in a bounded range');
start();
});
});
});
asyncTest('by index iterator', 3, function() {
df.always(function() {
var value_iter = db_r.from(store_inline_index)
.where('value', '>', 2, '<=', 3);
value_iter.count().always(function(x) {
//console.log('count value')
equal(x, 1, 'number of values in the range');
});
var name_iter = db_r.from(store_inline_index).where('name', '^', 'b');
name_iter.count().always(function(x) {
equal(x, 2, 'number of name in the range');
});
var iter = db_r.from(store_inline_index).select('value').unique(true);
iter.count().always(function(x) {
equal(x, 2, 'unique count');
start();
});
});
});
})();
(function() {
var db_name = 'test_query_to_list-1';
var store_inline_index = 'ts6'; // in-line key store
var schema_1 = {
stores: [
{
name: store_inline_index,
keyPath: 'id'
}
]
};
var test_count = 0;
var df = $.Deferred();
var objs = [
{test: 't' + Math.random(), value: 4, id: 0, name: 'a', tags: ['a', 'b']},
{test: 't' + Math.random(), value: 10, id: 1, name: 'a', tags: ['x']},
{test: 't' + Math.random(), value: 0, id: 2, name: 'a', tags: ['z']},
{test: 't' + Math.random(), value: 2, id: 3, name: 'bc',
tags: ['a', 'd', 'c']},
{test: 't' + Math.random(), value: 2, id: 4, name: 'bc', tags: ['e', 'c']},
{test: 't' + Math.random(), value: 8, id: 5, name: 'c', tags: ['b']},
{test: 't' + Math.random(), value: 2, id: 6, name: 'c', tags: ['a']}
];
// persist store data.
(function() {
var _db = new ydn.db.Storage(db_name, schema_1, options);
_db.clear(store_inline_index);
_db.put(store_inline_index, objs).always(function() {
_db.close();
setTimeout(function() {
df.resolve();
}, 100);
});
})();
var db;
var test_env = {
setup: function() {
db = new ydn.db.Storage(db_name, schema_1, options);
},
teardown: function() {
var type = db.getType();
db.close();
ydn.db.deleteDatabase(db_name, type);
}
};
module('query,list', test_env);
reporter.createTestSuite('query');
asyncTest('by primary key range', 3, function() {
df.always(function() {
var q = db.from(store_inline_index, '>=', 1, '<=', 3);
q.list().always(function(x) {
//console.log(q)
deepEqual(x, objs.slice(1, 4), 'closed bound');
});
q.copy().reverse().list().always(function(x) {
var exp = objs.slice(1, 4).reverse();
deepEqual(x, exp, 'closed bound reverse');
});
q.copy().list(1).always(function(x) {
deepEqual(x, objs.slice(1, 2), 'closed bound limit');
start();
});
});
});
})();
(function() {
var store_inline_index = 'ts6'; // in-line key store
var schema_1 = {
stores: [
{
name: store_inline_index,
keyPath: 'id',
indexes: [{
name: 'value'
}]
}
]
};
var test_count = 0;
var objs = [
{test: 't' + Math.random(), value: 14, id: 0, name: 'a', tags: ['a', 'b']},
{test: 't' + Math.random(), value: 10, id: 1, name: 'a', tags: ['x']},
{test: 't' + Math.random(), value: 0, id: 2, name: 'a', tags: ['z']},
{test: 't' + Math.random(), value: 13, id: 3, name: 'bc',
tags: ['a', 'd', 'c']},
{test: 't' + Math.random(), value: 13, id: 4, name: 'bc', tags: ['e', 'c']},
{test: 't' + Math.random(), value: 18, id: 5, name: 'c', tags: ['b']},
{test: 't' + Math.random(), value: 12, id: 6, name: 'c', tags: ['a']}
];
var db;
var test_env = {
setup: function() {
var db_name = 'test_query_to_list-' + Math.random();
db = new ydn.db.Storage(db_name, schema_1, options);
db.put(store_inline_index, objs).always(function() {
});
},
teardown: function() {
ydn.db.deleteDatabase(db.getName(), db.getType());
db.close();
}
};
module('query,list-key', test_env);
reporter.createTestSuite('query');
var keys = objs.map(function(x) {
return x.id;
});
asyncTest('primary keys by key range', 3, function() {
var q = db.from(store_inline_index, '>=', 1, '<=', 3);
q.select('id').list().always(function(x) {
// console.log(x, keys.slice(1, 4))
deepEqual(x, keys.slice(1, 4), 'closed bound');
});
q.copy().reverse().select('id').list().always(function(x) {
var exp = keys.slice(1, 4).reverse();
deepEqual(x, exp, 'closed bound reverse');
});
q.copy().select('id').list(1).always(function(x) {
deepEqual(x, keys.slice(1, 2), 'closed bound limit');
start();
});
});
var values = objs.map(function(x) {
return x.values;
}).sort();
asyncTest('index keys by key range', 2, function() {
var q = db.from(store_inline_index).where('value', '>=', 13, '<=', 14);
q.select('value').list().always(function(x) {
// console.log(x, keys.slice(1, 4))
deepEqual(x, [13, 13, 14], 'closed bound - index');
});
q.select('id').list().always(function(x) {
// console.log(x, keys.slice(1, 4))
deepEqual(x, [3, 4, 0], 'closed bound - primary');
start();
});
});
})();
(function() {
var db_name = 'test_query_to_list-order-4';
var store_inline_index = 'ts6'; // in-line key store
var schema_1 = {
stores: [
{
name: store_inline_index,
keyPath: 'id',
type: 'NUMERIC',
indexes: [
{name: 'name', type: 'TEXT'},
{name: 'value', type: 'NUMERIC'},
{name: 'name, value', keyPath: ['name', 'value']}
]
}
]
};
var test_count = 0;
var objs = [
{test: 't' + Math.random(), value: 4, id: 0, name: 'a', tags: ['a', 'b']},
{test: 't' + Math.random(), value: 10, id: 1, name: 'a', tags: ['x']},
{test: 't' + Math.random(), value: 0, id: 2, name: 'a', tags: ['z']},
{test: 't' + Math.random(), value: 2, id: 3, name: 'bc',
tags: ['a', 'd', 'c']},
{test: 't' + Math.random(), value: 2, id: 4, name: 'bc', tags: ['e', 'c']},
{test: 't' + Math.random(), value: 8, id: 5, name: 'c', tags: ['b']},
{test: 't' + Math.random(), value: 2, id: 6, name: 'c', tags: ['a']}
];
var cmp_value = function(a, b) {
return a.value > b.value ? 1 : a.value < b.value ? -1 :
a.id > b.id ? 1 : a.id < b.id ? -1 : 0;
};
var df = $.Deferred();
var db = new ydn.db.Storage(db_name, schema_1, options);
db.clear(store_inline_index);
db.put(store_inline_index, objs).always(function() {
df.resolve();
});
var test_env = {
setup: function() {
},
teardown: function() {
test_count++;
if (test_count == 4) {
db.close();
var type = db.getType();
ydn.db.deleteDatabase(db_name, type);
}
}
};
module('query,list-index', test_env);
reporter.createTestSuite('query,list', 'list');
var sorted_objs = objs.slice().sort(function(a, b) {
return a.value > b.value ? 1 : -1;
});
var keys = objs.map(function(x) {
return x.id;
});
asyncTest('by index key range', 4, function() {
df.always(function() {
var q;
q = db.from(store_inline_index).where('value', '>=', 2, '<=', 4);
q.list().always(function(x) {
//console.log(q)
var result = objs.filter(function(x) {
return x.value >= 2 && x.value <= 4;
}).sort(cmp_value);
deepEqual(x, result, 'closed bound');
});
q = db.from(store_inline_index).where('value', '<', 4);
q.list().always(function(x) {
//console.log(q)
var result = objs.filter(function(x) {
return x.value < 4;
}).sort(cmp_value);
deepEqual(x, result, 'open upperBound');
});
q = db.from(store_inline_index).where('value', '>=', 2, '<=', 4);
var result_limit = objs.filter(function(x) {
return x.value >= 2 && x.value <= 4;
}).sort(cmp_value);
q.list(2).always(function(x) {
//console.log(q)
deepEqual(x, result_limit.slice(0, 2), 'first limit');
q.list().always(function(x) {
//console.log(q)
deepEqual(x, result_limit.slice(2), 'last limit');
start();
});
});
});
});
asyncTest('natural ordering', 2, function() {
df.always(function() {
var q = db.from(store_inline_index);
q.list().always(function(x) {
deepEqual(x, objs, 'natural order');
});
var q2 = db.from(store_inline_index).reverse();
q2.list().always(function(x) {
deepEqual(x, objs.reverse(), 'natural order reverse');
start();
});
});
});
asyncTest('index ordering', 2, function() {
df.always(function() {
var q = db.from(store_inline_index).order('value');
q.list().always(function(x) {
deepEqual(x, sorted_objs, 'simple index order');
});
var q2 = db.from(store_inline_index).order('value').reverse();
q2.list().always(function(x) {
deepEqual(x, sorted_objs.reverse(), 'reverse index order');
start();
});
});
});
asyncTest('ordering with key range', 1, function() {
df.always(function() {
var q = db.from(store_inline_index).where('value', '>=', 2, '<=', 4);
// q = q.order('value');
q.list().always(function(x) {
//console.log(q)
var result = objs.filter(function(x) {
return x.value >= 2 && x.value <= 4;
}).sort(function(a, b) {
return a.value > b.value ? 1 : a.value < b.value ? -1 :
a.id > b.id ? 1 : a.id < b.id ? -1 : 0;
});
deepEqual(x, result, 'closed bound');
start()
});
/* TODO: make this test work
q = db.from(store_inline_index).where('name', '>', 'a');
throws(function() {
q = q.order('value');
}, Error, 'impossible ordering'
);
*/
/* TODO: make this test work
q = db.from(store_inline_index).where('name', '=', 'a');
q = q.order('value');
q.list().always(function(x) {
//console.log(q)
deepEqual(x, [objs[2], objs[0], objs[1]], 'compound order');
start();
});
*/
});
});
})();
(function() {
var store_inline_index = 'ts6'; // in-line key store
var schema_1 = {
stores: [
{
name: store_inline_index,
keyPath: 'id',
type: 'NUMERIC',
indexes: [
{name: 'tags', type: 'TEXT', multiEntry: true}
]
}
]
};
var df = $.Deferred();
var objs = [
{test: 't' + Math.random(), value: 4, id: 0, name: 'a', tags: ['a', 'b']},
{test: 't' + Math.random(), value: 10, id: 1, name: 'a', tags: ['b']},
{test: 't' + Math.random(), value: 0, id: 2, name: 'a', tags: ['a']},
{test: 't' + Math.random(), value: 2, id: 3, name: 'bc',
tags: ['a', 'b', 'c']},
{test: 't' + Math.random(), value: 2, id: 4, name: 'bc', tags: ['a', 'c']},
{test: 't' + Math.random(), value: 8, id: 5, name: 'c', tags: ['b']},
{test: 't' + Math.random(), value: 2, id: 6, name: 'c', tags: ['a']}
];
var cmp_value = function(a, b) {
return a.value > b.value ? 1 : a.value < b.value ? -1 :
a.id > b.id ? 1 : a.id < b.id ? -1 : 0;
};
var db;
module('query,query-unique', {
setup: function() {
var db_name = 'test_query_to_list-' + Math.random();
var _db = new ydn.db.Storage(db_name, schema_1, options);
_db.clear(store_inline_index);
_db.put(store_inline_index, objs).always(function() {
_db.close();
db = new ydn.db.Storage(db_name, schema_1, options);
df.resolve();
});
},
teardown: function() {
var type = db.getType();
db.close();
ydn.db.deleteDatabase(db.getName(), type);
}
});
reporter.createTestSuite('query');
asyncTest('unique index', 2, function() {
df.always(function() {
var q = db.from(store_inline_index).select('tags').unique(true);
q.list().always(function(x) {
//console.log(q)
deepEqual(x, ['a', 'b', 'c'], 'unique index keys');
});
q = db.from(store_inline_index).select('tags').unique(false);
q.list().always(function(x) {
//console.log(q)
deepEqual(x, ["a",
"a",
"a",
"a",
"a",
"b",
"b",
"b",
"b",
"c",
"c"], 'non unique index keys');
start();
});
});
});
})();
(function() {
var db_name = 'test_query_patch';
var store_inline = 'ts'; // in-line key store
var store_inline_index = 'ts6'; // in-line key store
var schema_1 = {
stores: [
{
name: store_inline,
keyPath: 'id'},
{
name: store_inline_index,
keyPath: 'id',
type: 'NUMERIC',
indexes: [
{name: 'name', type: 'TEXT'},
{name: 'value', type: 'NUMERIC'},
{name: 'name, value', keyPath: ['name', 'value']},
{name: 'tags', type: 'TEXT', multiEntry: true}
]
}
]
};
var test_count = 0;
var df = $.Deferred();
var objs = [
{test: 't' + Math.random(), value: 4, id: 0, name: 'a', tags: ['a', 'f']},
{test: 't' + Math.random(), value: 10, id: 1, name: 'a', tags: ['f']},
{test: 't' + Math.random(), value: 0, id: 2, name: 'a', tags: ['a']},
{test: 't' + Math.random(), value: 2, id: 3, name: 'bc',
tags: ['a', 'b', 'c']},
{test: 't' + Math.random(), value: 2, id: 4, name: 'bc', tags: ['a', 'c']},
{test: 't' + Math.random(), value: 8, id: 5, name: 'c', tags: ['b']},
{test: 't' + Math.random(), value: 2, id: 6, name: 'c', tags: ['a']}
];
var cmp_value = function(a, b) {
return a.value > b.value ? 1 : a.value < b.value ? -1 :
a.id > b.id ? 1 : a.id < b.id ? -1 : 0;
};
// persist store data.
(function() {
var _db = new ydn.db.Storage(db_name, schema_1, options);
_db.clear(store_inline_index);
_db.put(store_inline_index, objs);
_db.count(store_inline_index).always(function() {
_db.close();
setTimeout(function() {
df.resolve();
}, 100);
});
})();
var db;
module('query,patch', {
setup: function() {
db = new ydn.db.Storage(db_name, schema_1, options);
},
teardown: function() {
var type = db.getType();
test_count++;
db.close();
if (test_count == 2) {
ydn.db.deleteDatabase(db_name, type);
}
}
});
var sorted_objs = objs.slice().sort(function(a, b) {
return a.value > b.value ? 1 : -1;
});
var keys = objs.map(function(x) {
return x.id;
});
asyncTest('single', 3, function() {
var new_val = 'new-' + Math.random();
var createPatch = function(id) {
var new_obj = JSON.parse(JSON.stringify(objs[id]));
new_obj.test = new_val;
return new_obj;
};
df.always(function() {
var q = db.from(store_inline_index, '=', 0);
q.patch({test: new_val}).always(function() {
db.get(store_inline_index, 0).always(function(x) {
deepEqual(x, createPatch(0), 'by object');
});
});
q = db.from(store_inline_index, '=', 1);
q.patch('test', new_val).always(function() {
db.get(store_inline_index, 1).always(function(x) {
deepEqual(x, createPatch(1), 'by single field');
});
});
q = db.from(store_inline_index, '=', 2);
q.patch(['test', 'name'], [new_val, 'name']).always(function() {
db.get(store_inline_index, 2).always(function(x) {
var obj = createPatch(2);
obj.name = 'name';
deepEqual(x, obj, 'by fields');
start();
});
});
});
});
asyncTest('multiple', 2, function() {
var new_val = 'new-' + Math.random();
var createPatch = function(id) {
var new_obj = JSON.parse(JSON.stringify(objs[id]));
new_obj.test = new_val;
return new_obj;
};
var exp = [createPatch(3), createPatch(4), createPatch(6)];
var exp2 = [createPatch(0), createPatch(1)];
df.always(function() {
var q = db.from(store_inline_index).where('value', '=', 2);
q.patch({test: new_val}).always(function() {
db.values(store_inline_index, 'value', ydn.db.KeyRange.only(2)).always(function(x) {
deepEqual(x, exp, 'by object');
});
});
q = db.from(store_inline_index).where('tags', '=', 'f');
q.patch('test', new_val).always(function() {
db.values(store_inline_index, 'tags', ydn.db.KeyRange.only('f')).always(function(x) {
deepEqual(x, exp2, 'by field');
start();
});
});
});
});
})();