import type { BulkWriteRow, RxDocumentData, RxJsonSchema } from 'nxdb-old/src/types'; import type { DocWithIndexString, MemoryStorageInternals, MemoryStorageInternalsByIndex } from 'nxdb-old/src/plugins/storage-memory/memory-types'; import type { RxStorageInstanceMemory } from 'nxdb-old/src/plugins/storage-memory/rx-storage-instance-memory'; import { pushAtSortPosition } from 'array-push-at-sort-position'; import { newRxError } from 'nxdb-old/src/rx-error'; import { boundEQ } from 'nxdb-old/src/plugins/storage-memory/binary-search-bounds'; export function getMemoryCollectionKey( databaseName: string, collectionName: string, schemaVersion: number ): string { return [ databaseName, collectionName, schemaVersion ].join('--memory--'); } export function ensureNotRemoved( instance: RxStorageInstanceMemory ) { if (instance.internals.removed) { throw new Error('removed'); } } export function attachmentMapKey(documentId: string, attachmentId: string): string { return documentId + '||' + attachmentId; } function sortByIndexStringComparator(a: DocWithIndexString, b: DocWithIndexString) { if (a.indexString < b.indexString) { return -1; } else { return 1; } } /** * @hotPath */ export function putWriteRowToState( docId: string, state: MemoryStorageInternals, stateByIndex: MemoryStorageInternalsByIndex[], row: BulkWriteRow, docInState?: RxDocumentData ) { state.documents.set(docId, row.document as any); for (let i = 0; i < stateByIndex.length; ++i) { const byIndex = stateByIndex[i]; const docsWithIndex = byIndex.docsWithIndex; const newIndexString = byIndex.getIndexableString(row.document as any); const insertPosition = pushAtSortPosition( docsWithIndex, { id: docId, doc: row.document, indexString: newIndexString }, sortByIndexStringComparator, 0 ); /** * Remove previous if it was in the state */ if (docInState) { const previousIndexString = byIndex.getIndexableString(docInState); if (previousIndexString === newIndexString) { /** * Performance shortcut. * If index was not changed -> The old doc must be before or after the new one. */ const prev = docsWithIndex[insertPosition - 1]; if (prev && prev.id === docId) { docsWithIndex.splice(insertPosition - 1, 1); } else { const next = docsWithIndex[insertPosition + 1]; if (next.id === docId) { docsWithIndex.splice(insertPosition + 1, 1); } else { throw newRxError('SNH', { args: { row, byIndex } }); } } } else { /** * Index changed, we must search for the old one and remove it. */ const indexBefore = boundEQ( docsWithIndex, { indexString: previousIndexString } as any, compareDocsWithIndex ); docsWithIndex.splice(indexBefore, 1); } } } } export function removeDocFromState( primaryPath: string, schema: RxJsonSchema>, state: MemoryStorageInternals, doc: RxDocumentData ) { const docId: string = (doc as any)[primaryPath]; state.documents.delete(docId); Object.values(state.byIndex).forEach(byIndex => { const docsWithIndex = byIndex.docsWithIndex; const indexString = byIndex.getIndexableString(doc); const positionInIndex = boundEQ( docsWithIndex, { indexString } as any, compareDocsWithIndex ); docsWithIndex.splice(positionInIndex, 1); }); } export function compareDocsWithIndex( a: DocWithIndexString, b: DocWithIndexString ): 1 | 0 | -1 { if (a.indexString < b.indexString) { return -1; } else if (a.indexString === b.indexString) { return 0; } else { return 1; } }