UNPKG

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
(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(); }); }); }); }); })();