<!
doctype html>
<
meta charset=
"utf-8">
<
title>
IndexedDB: scoping for database /
object store / index names, and index keys
</
title>
<
link rel=
"help" href=
"https://w3c.github.io/IndexedDB/#constructs">
<
link rel=
"author" href=
"pwnall@chromium.org" title=
"Victor Costan">
<
script src=
"/resources/testharness.js"></
script>
<
script src=
"/resources/testharnessreport.js"></
script>
<
script src=
"resources/support-promises.js"></
script>
<
script>
'use strict';
// Creates the structure inside a test database.
//
// The structure includes two stores with identical indexes and nearly-similar
// records. The records differ in the
"path" attribute values, which are used to
// verify that IndexedDB returns the correct records when queried.
//
// databaseName appears redundant, but we don
't want to rely on database.name.
const buildStores = (database, databaseName, useUniqueKeys) => {
for (let storeName of [
'x',
'y']) {
const store = database.createObjectStore(
storeName, { keyPath:
'pKey', autoIncrement: true });
for (let indexName of [
'x',
'y']) {
store.createIndex(
indexName, `${indexName}Key`, { unique: useUniqueKeys });
}
for (let xKeyRoot of [
'x',
'y']) {
for (let yKeyRoot of [
'x',
'y']) {
let xKey, yKey;
if (useUniqueKeys) {
xKey = `${xKeyRoot}${yKeyRoot}`;
yKey = `${yKeyRoot}${xKeyRoot}`;
} else {
xKey = xKeyRoot;
yKey = yKeyRoot;
}
const path = `${databaseName}-${storeName}-${xKeyRoot}-${yKeyRoot}`;
store.put({ xKey: xKey, yKey: yKey, path: path });
}
}
}
};
// Creates two databases with identical structures.
const buildDatabases = (testCase, useUniqueKeys) => {
return createNamedDatabase(
testCase,
'x', database => buildStores(database,
'x', useUniqueKeys))
.then(database => database.close())
.then(() => createNamedDatabase(
testCase,
'y', database => buildStores(database,
'y', useUniqueKeys)))
.then(database => database.close());
};
// Reads all the store
's values using an index.
//
// Returns a Promise that resolves with an array of values.
const readIndex = (testCase, index) => {
return new Promise((resolve, reject) => {
const results = [];
const request = index.openCursor(IDBKeyRange.bound(
'a',
'z'),
'next');
request.onsuccess = () => {
const cursor = request.result;
if (cursor) {
results.push(cursor.value);
cursor.continue();
} else {
resolve(results);
}
}
});
}
// Verifies that a database contains the expected records.
const checkDatabaseContent =
(testCase, database, databaseName, usedUniqueKeys) => {
const promises = [];
const transaction = database.transaction([
'x',
'y'],
'readonly');
for (let storeName of [
'x',
'y']) {
const store = transaction.objectStore(storeName);
for (let indexName of [
'x',
'y']) {
const index = store.index(indexName);
const promise = readIndex(testCase, index).then((results) => {
assert_array_equals(
results.
map(result => `${result.path}:${result.pKey}`).sort(),
[`${databaseName}-${storeName}-x-x:1`,
`${databaseName}-${storeName}-x-y:2`,
`${databaseName}-${storeName}-y-x:3`,
`${databaseName}-${storeName}-y-y:4`],
'The results should include all records put into the store');
let expectedKeys = (usedUniqueKeys) ?
[
'xx:xx',
'xy:yx',
'yx:xy',
'yy:yy'] : [
'x:x',
'x:y',
'y:x',
'y:y'];
assert_array_equals(
results.
map(result => `${result.xKey}:${result.yKey}`).sort(),
expectedKeys,
'The results should include all the index keys put in the store');
assert_array_equals(
results.
map(result => result[`${indexName}Key`]),
results.
map(result => result[`${indexName}Key`]).sort(),
'The results should be sorted by the index key');
});
promises.push(promise);
}
}
return Promise.all(promises).then(() => database);
}
promise_test(testCase => {
return buildDatabases(testCase, false)
.then(() => openNamedDatabase(testCase,
'x', 1))
.then(database => checkDatabaseContent(testCase, database,
'x', false))
.then(database => database.close())
.then(() => openNamedDatabase(testCase,
'y', 1))
.then(database => checkDatabaseContent(testCase, database,
'y', false))
.then(database => database.close());
},
'Non-unique index keys');
promise_test(testCase => {
return buildDatabases(testCase, true)
.then(() => openNamedDatabase(testCase,
'x', 1))
.then(database => checkDatabaseContent(testCase, database,
'x', true))
.then(database => database.close())
.then(() => openNamedDatabase(testCase,
'y', 1))
.then(database => checkDatabaseContent(testCase, database,
'y', true))
.then(database => database.close());
},
'Unique index keys');
</
script>