idb: don't create duplicate index entries
This commit is contained in:
parent
e2b7441e73
commit
6cea1f7c5b
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "idb-bridge",
|
"name": "idb-bridge",
|
||||||
"version": "0.0.7",
|
"version": "0.0.8",
|
||||||
"description": "IndexedDB implementation that uses SQLite3 as storage",
|
"description": "IndexedDB implementation that uses SQLite3 as storage",
|
||||||
"main": "./build/index.js",
|
"main": "./build/index.js",
|
||||||
"types": "./build/index.d.ts",
|
"types": "./build/index.d.ts",
|
||||||
@ -12,7 +12,7 @@
|
|||||||
"build": "tsc"
|
"build": "tsc"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"ava": "2.1.0",
|
"ava": "2.3.0",
|
||||||
"typescript": "^3.4.5"
|
"typescript": "^3.4.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,8 +261,11 @@ export class MemoryBackend implements Backend {
|
|||||||
throw Error("DB dump corrupt");
|
throw Error("DB dump corrupt");
|
||||||
}
|
}
|
||||||
const objectStores: { [name: string]: ObjectStore } = {};
|
const objectStores: { [name: string]: ObjectStore } = {};
|
||||||
for (const objectStoreName of Object.keys(data.databases[dbName].objectStores)) {
|
for (const objectStoreName of Object.keys(
|
||||||
const dumpedObjectStore = data.databases[dbName].objectStores[objectStoreName];
|
data.databases[dbName].objectStores,
|
||||||
|
)) {
|
||||||
|
const dumpedObjectStore =
|
||||||
|
data.databases[dbName].objectStores[objectStoreName];
|
||||||
|
|
||||||
const indexes: { [name: string]: Index } = {};
|
const indexes: { [name: string]: Index } = {};
|
||||||
for (const indexName of Object.keys(dumpedObjectStore.indexes)) {
|
for (const indexName of Object.keys(dumpedObjectStore.indexes)) {
|
||||||
@ -270,21 +273,27 @@ export class MemoryBackend implements Backend {
|
|||||||
const pairs = dumpedIndex.records.map((r: any) => {
|
const pairs = dumpedIndex.records.map((r: any) => {
|
||||||
return structuredClone([r.indexKey, r]);
|
return structuredClone([r.indexKey, r]);
|
||||||
});
|
});
|
||||||
const indexData: ISortedMapF<Key, IndexRecord> = new BTree(pairs, compareKeys);
|
const indexData: ISortedMapF<Key, IndexRecord> = new BTree(
|
||||||
|
pairs,
|
||||||
|
compareKeys,
|
||||||
|
);
|
||||||
const index: Index = {
|
const index: Index = {
|
||||||
deleted: false,
|
deleted: false,
|
||||||
modifiedData: undefined,
|
modifiedData: undefined,
|
||||||
modifiedName: undefined,
|
modifiedName: undefined,
|
||||||
originalName: indexName,
|
originalName: indexName,
|
||||||
originalData: indexData,
|
originalData: indexData,
|
||||||
}
|
};
|
||||||
indexes[indexName] = index;
|
indexes[indexName] = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pairs = dumpedObjectStore.records.map((r: any) => {
|
const pairs = dumpedObjectStore.records.map((r: any) => {
|
||||||
return structuredClone([r.primaryKey, r]);
|
return structuredClone([r.primaryKey, r]);
|
||||||
});
|
});
|
||||||
const objectStoreData: ISortedMapF<Key, ObjectStoreRecord> = new BTree(pairs, compareKeys);
|
const objectStoreData: ISortedMapF<Key, ObjectStoreRecord> = new BTree(
|
||||||
|
pairs,
|
||||||
|
compareKeys,
|
||||||
|
);
|
||||||
const objectStore: ObjectStore = {
|
const objectStore: ObjectStore = {
|
||||||
deleted: false,
|
deleted: false,
|
||||||
modifiedData: undefined,
|
modifiedData: undefined,
|
||||||
@ -295,7 +304,7 @@ export class MemoryBackend implements Backend {
|
|||||||
originalKeyGenerator: dumpedObjectStore.keyGenerator,
|
originalKeyGenerator: dumpedObjectStore.keyGenerator,
|
||||||
committedIndexes: indexes,
|
committedIndexes: indexes,
|
||||||
modifiedIndexes: {},
|
modifiedIndexes: {},
|
||||||
}
|
};
|
||||||
objectStores[objectStoreName] = objectStore;
|
objectStores[objectStoreName] = objectStore;
|
||||||
}
|
}
|
||||||
const db: Database = {
|
const db: Database = {
|
||||||
@ -310,13 +319,15 @@ export class MemoryBackend implements Backend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private makeObjectStoreMap(database: Database): { [currentName: string]: ObjectStoreMapEntry } {
|
private makeObjectStoreMap(
|
||||||
let map: { [currentName: string]: ObjectStoreMapEntry } = {}
|
database: Database,
|
||||||
|
): { [currentName: string]: ObjectStoreMapEntry } {
|
||||||
|
let map: { [currentName: string]: ObjectStoreMapEntry } = {};
|
||||||
for (let objectStoreName in database.committedObjectStores) {
|
for (let objectStoreName in database.committedObjectStores) {
|
||||||
const store = database.committedObjectStores[objectStoreName];
|
const store = database.committedObjectStores[objectStoreName];
|
||||||
const entry: ObjectStoreMapEntry = {
|
const entry: ObjectStoreMapEntry = {
|
||||||
store,
|
store,
|
||||||
indexMap: Object.assign({}, store.committedIndexes)
|
indexMap: Object.assign({}, store.committedIndexes),
|
||||||
};
|
};
|
||||||
map[objectStoreName] = entry;
|
map[objectStoreName] = entry;
|
||||||
}
|
}
|
||||||
@ -581,7 +592,8 @@ export class MemoryBackend implements Backend {
|
|||||||
if (!indexesSchema) {
|
if (!indexesSchema) {
|
||||||
throw new Error("new index name already used");
|
throw new Error("new index name already used");
|
||||||
}
|
}
|
||||||
const index: Index = myConn.objectStoreMap[objectStoreName].indexMap[oldName];
|
const index: Index =
|
||||||
|
myConn.objectStoreMap[objectStoreName].indexMap[oldName];
|
||||||
if (!index) {
|
if (!index) {
|
||||||
throw Error("old index missing in connection's index map");
|
throw Error("old index missing in connection's index map");
|
||||||
}
|
}
|
||||||
@ -592,7 +604,11 @@ export class MemoryBackend implements Backend {
|
|||||||
index.modifiedName = newName;
|
index.modifiedName = newName;
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteIndex(btx: DatabaseTransaction, objectStoreName: string, indexName: string): void {
|
deleteIndex(
|
||||||
|
btx: DatabaseTransaction,
|
||||||
|
objectStoreName: string,
|
||||||
|
indexName: string,
|
||||||
|
): void {
|
||||||
if (this.enableTracing) {
|
if (this.enableTracing) {
|
||||||
console.log(`TRACING: deleteIndex(${indexName})`);
|
console.log(`TRACING: deleteIndex(${indexName})`);
|
||||||
}
|
}
|
||||||
@ -614,7 +630,8 @@ export class MemoryBackend implements Backend {
|
|||||||
if (!schema.objectStores[objectStoreName].indexes[indexName]) {
|
if (!schema.objectStores[objectStoreName].indexes[indexName]) {
|
||||||
throw new Error("index does not exist");
|
throw new Error("index does not exist");
|
||||||
}
|
}
|
||||||
const index: Index = myConn.objectStoreMap[objectStoreName].indexMap[indexName];
|
const index: Index =
|
||||||
|
myConn.objectStoreMap[objectStoreName].indexMap[indexName];
|
||||||
if (!index) {
|
if (!index) {
|
||||||
throw Error("old index missing in connection's index map");
|
throw Error("old index missing in connection's index map");
|
||||||
}
|
}
|
||||||
@ -782,7 +799,9 @@ export class MemoryBackend implements Backend {
|
|||||||
originalName: indexName,
|
originalName: indexName,
|
||||||
};
|
};
|
||||||
myConn.objectStoreMap[objectStoreName].indexMap[indexName] = newIndex;
|
myConn.objectStoreMap[objectStoreName].indexMap[indexName] = newIndex;
|
||||||
db.modifiedObjectStores[objectStoreName].modifiedIndexes[indexName] = newIndex;
|
db.modifiedObjectStores[objectStoreName].modifiedIndexes[
|
||||||
|
indexName
|
||||||
|
] = newIndex;
|
||||||
const schema = myConn.modifiedSchema;
|
const schema = myConn.modifiedSchema;
|
||||||
if (!schema) {
|
if (!schema) {
|
||||||
throw Error("no schema in versionchange tx");
|
throw Error("no schema in versionchange tx");
|
||||||
@ -798,7 +817,9 @@ export class MemoryBackend implements Backend {
|
|||||||
throw Error("object store does not exist");
|
throw Error("object store does not exist");
|
||||||
}
|
}
|
||||||
|
|
||||||
const storeData = objectStoreMapEntry.store.modifiedData || objectStoreMapEntry.store.originalData;
|
const storeData =
|
||||||
|
objectStoreMapEntry.store.modifiedData ||
|
||||||
|
objectStoreMapEntry.store.originalData;
|
||||||
|
|
||||||
storeData.forEach((v, k) => {
|
storeData.forEach((v, k) => {
|
||||||
this.insertIntoIndex(newIndex, k, v.value, indexProperties);
|
this.insertIntoIndex(newIndex, k, v.value, indexProperties);
|
||||||
@ -837,7 +858,8 @@ export class MemoryBackend implements Backend {
|
|||||||
const objectStoreMapEntry = myConn.objectStoreMap[objectStoreName];
|
const objectStoreMapEntry = myConn.objectStoreMap[objectStoreName];
|
||||||
|
|
||||||
if (!objectStoreMapEntry.store.modifiedData) {
|
if (!objectStoreMapEntry.store.modifiedData) {
|
||||||
objectStoreMapEntry.store.modifiedData = objectStoreMapEntry.store.originalData;
|
objectStoreMapEntry.store.modifiedData =
|
||||||
|
objectStoreMapEntry.store.originalData;
|
||||||
}
|
}
|
||||||
|
|
||||||
let modifiedData = objectStoreMapEntry.store.modifiedData;
|
let modifiedData = objectStoreMapEntry.store.modifiedData;
|
||||||
@ -877,13 +899,20 @@ export class MemoryBackend implements Backend {
|
|||||||
throw Error("assertion failed");
|
throw Error("assertion failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const indexName of Object.keys(schema.objectStores[objectStoreName].indexes)) {
|
for (const indexName of Object.keys(
|
||||||
const index = myConn.objectStoreMap[objectStoreName].indexMap[indexName];
|
schema.objectStores[objectStoreName].indexes,
|
||||||
|
)) {
|
||||||
|
const index =
|
||||||
|
myConn.objectStoreMap[objectStoreName].indexMap[indexName];
|
||||||
if (!index) {
|
if (!index) {
|
||||||
throw Error("index referenced by object store does not exist");
|
throw Error("index referenced by object store does not exist");
|
||||||
}
|
}
|
||||||
this.enableTracing && console.log(`deleting from index ${indexName} for object store ${objectStoreName}`);
|
this.enableTracing &&
|
||||||
const indexProperties = schema.objectStores[objectStoreName].indexes[indexName];
|
console.log(
|
||||||
|
`deleting from index ${indexName} for object store ${objectStoreName}`,
|
||||||
|
);
|
||||||
|
const indexProperties =
|
||||||
|
schema.objectStores[objectStoreName].indexes[indexName];
|
||||||
this.deleteFromIndex(
|
this.deleteFromIndex(
|
||||||
index,
|
index,
|
||||||
storeEntry.primaryKey,
|
storeEntry.primaryKey,
|
||||||
@ -993,12 +1022,15 @@ export class MemoryBackend implements Backend {
|
|||||||
const unique: boolean =
|
const unique: boolean =
|
||||||
req.direction === "prevunique" || req.direction === "nextunique";
|
req.direction === "prevunique" || req.direction === "nextunique";
|
||||||
|
|
||||||
const storeData = objectStoreMapEntry.store.modifiedData || objectStoreMapEntry.store.originalData;
|
const storeData =
|
||||||
|
objectStoreMapEntry.store.modifiedData ||
|
||||||
|
objectStoreMapEntry.store.originalData;
|
||||||
|
|
||||||
const haveIndex = req.indexName !== undefined;
|
const haveIndex = req.indexName !== undefined;
|
||||||
|
|
||||||
if (haveIndex) {
|
if (haveIndex) {
|
||||||
const index = myConn.objectStoreMap[req.objectStoreName].indexMap[req.indexName!];
|
const index =
|
||||||
|
myConn.objectStoreMap[req.objectStoreName].indexMap[req.indexName!];
|
||||||
const indexData = index.modifiedData || index.originalData;
|
const indexData = index.modifiedData || index.originalData;
|
||||||
let indexPos = req.lastIndexPosition;
|
let indexPos = req.lastIndexPosition;
|
||||||
|
|
||||||
@ -1275,7 +1307,8 @@ export class MemoryBackend implements Backend {
|
|||||||
const objectStoreMapEntry = myConn.objectStoreMap[storeReq.objectStoreName];
|
const objectStoreMapEntry = myConn.objectStoreMap[storeReq.objectStoreName];
|
||||||
|
|
||||||
if (!objectStoreMapEntry.store.modifiedData) {
|
if (!objectStoreMapEntry.store.modifiedData) {
|
||||||
objectStoreMapEntry.store.modifiedData = objectStoreMapEntry.store.originalData;
|
objectStoreMapEntry.store.modifiedData =
|
||||||
|
objectStoreMapEntry.store.originalData;
|
||||||
}
|
}
|
||||||
const modifiedData = objectStoreMapEntry.store.modifiedData;
|
const modifiedData = objectStoreMapEntry.store.modifiedData;
|
||||||
|
|
||||||
@ -1296,13 +1329,15 @@ export class MemoryBackend implements Backend {
|
|||||||
const storeKeyResult: StoreKeyResult = makeStoreKeyValue(
|
const storeKeyResult: StoreKeyResult = makeStoreKeyValue(
|
||||||
storeReq.value,
|
storeReq.value,
|
||||||
storeReq.key,
|
storeReq.key,
|
||||||
objectStoreMapEntry.store.modifiedKeyGenerator || objectStoreMapEntry.store.originalKeyGenerator,
|
objectStoreMapEntry.store.modifiedKeyGenerator ||
|
||||||
|
objectStoreMapEntry.store.originalKeyGenerator,
|
||||||
schema.objectStores[storeReq.objectStoreName].autoIncrement,
|
schema.objectStores[storeReq.objectStoreName].autoIncrement,
|
||||||
schema.objectStores[storeReq.objectStoreName].keyPath,
|
schema.objectStores[storeReq.objectStoreName].keyPath,
|
||||||
);
|
);
|
||||||
key = storeKeyResult.key;
|
key = storeKeyResult.key;
|
||||||
value = storeKeyResult.value;
|
value = storeKeyResult.value;
|
||||||
objectStoreMapEntry.store.modifiedKeyGenerator = storeKeyResult.updatedKeyGenerator;
|
objectStoreMapEntry.store.modifiedKeyGenerator =
|
||||||
|
storeKeyResult.updatedKeyGenerator;
|
||||||
const hasKey = modifiedData.has(key);
|
const hasKey = modifiedData.has(key);
|
||||||
|
|
||||||
if (hasKey && storeReq.storeLevel !== StoreLevel.AllowOverwrite) {
|
if (hasKey && storeReq.storeLevel !== StoreLevel.AllowOverwrite) {
|
||||||
@ -1315,15 +1350,22 @@ export class MemoryBackend implements Backend {
|
|||||||
value: structuredClone(value),
|
value: structuredClone(value),
|
||||||
};
|
};
|
||||||
|
|
||||||
objectStoreMapEntry.store.modifiedData = modifiedData.with(key, objectStoreRecord, true);
|
objectStoreMapEntry.store.modifiedData = modifiedData.with(
|
||||||
|
key,
|
||||||
|
objectStoreRecord,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
for (const indexName of Object.keys(schema.objectStores[storeReq.objectStoreName]
|
for (const indexName of Object.keys(
|
||||||
.indexes)) {
|
schema.objectStores[storeReq.objectStoreName].indexes,
|
||||||
const index = myConn.objectStoreMap[storeReq.objectStoreName] .indexMap[indexName];
|
)) {
|
||||||
|
const index =
|
||||||
|
myConn.objectStoreMap[storeReq.objectStoreName].indexMap[indexName];
|
||||||
if (!index) {
|
if (!index) {
|
||||||
throw Error("index referenced by object store does not exist");
|
throw Error("index referenced by object store does not exist");
|
||||||
}
|
}
|
||||||
const indexProperties = schema.objectStores[storeReq.objectStoreName].indexes[indexName];
|
const indexProperties =
|
||||||
|
schema.objectStores[storeReq.objectStoreName].indexes[indexName];
|
||||||
this.insertIntoIndex(index, key, value, indexProperties);
|
this.insertIntoIndex(index, key, value, indexProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1353,13 +1395,16 @@ export class MemoryBackend implements Backend {
|
|||||||
if (indexProperties.unique) {
|
if (indexProperties.unique) {
|
||||||
throw new ConstraintError();
|
throw new ConstraintError();
|
||||||
} else {
|
} else {
|
||||||
const newIndexRecord = {
|
const pred = (x: Key) => compareKeys(x, primaryKey) === 0;
|
||||||
indexKey: indexKey,
|
if (existingRecord.primaryKeys.findIndex(pred) === -1) {
|
||||||
primaryKeys: [primaryKey]
|
const newIndexRecord = {
|
||||||
.concat(existingRecord.primaryKeys)
|
indexKey: indexKey,
|
||||||
.sort(compareKeys),
|
primaryKeys: [...existingRecord.primaryKeys, primaryKey].sort(
|
||||||
};
|
compareKeys,
|
||||||
index.modifiedData = indexData.with(indexKey, newIndexRecord, true);
|
),
|
||||||
|
};
|
||||||
|
index.modifiedData = indexData.with(indexKey, newIndexRecord, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const newIndexRecord: IndexRecord = {
|
const newIndexRecord: IndexRecord = {
|
||||||
@ -1396,9 +1441,11 @@ export class MemoryBackend implements Backend {
|
|||||||
objectStore.modifiedData = undefined;
|
objectStore.modifiedData = undefined;
|
||||||
objectStore.modifiedName = undefined;
|
objectStore.modifiedName = undefined;
|
||||||
objectStore.modifiedKeyGenerator = undefined;
|
objectStore.modifiedKeyGenerator = undefined;
|
||||||
objectStore.modifiedIndexes = {}
|
objectStore.modifiedIndexes = {};
|
||||||
|
|
||||||
for (const indexName in Object.keys(db.committedSchema.objectStores[objectStoreName].indexes)) {
|
for (const indexName in Object.keys(
|
||||||
|
db.committedSchema.objectStores[objectStoreName].indexes,
|
||||||
|
)) {
|
||||||
const index = objectStore.committedIndexes[indexName];
|
const index = objectStore.committedIndexes[indexName];
|
||||||
index.deleted = false;
|
index.deleted = false;
|
||||||
index.modifiedData = undefined;
|
index.modifiedData = undefined;
|
||||||
@ -1451,7 +1498,6 @@ export class MemoryBackend implements Backend {
|
|||||||
index.originalName = index.modifiedName || index.originalName;
|
index.originalName = index.modifiedName || index.originalName;
|
||||||
store.committedIndexes[indexName] = index;
|
store.committedIndexes[indexName] = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
myConn.objectStoreMap = this.makeObjectStoreMap(db);
|
myConn.objectStoreMap = this.makeObjectStoreMap(db);
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user