MOBILE-4304 core: Return database records rowId

main
Noel De Martin 2024-01-17 12:19:18 +01:00
parent b6f32dfddd
commit 869f08eee7
18 changed files with 219 additions and 101 deletions

View File

@ -18,7 +18,9 @@ import { CoreSiteSchema } from '@services/sites';
* Database variables for AddonModScormOfflineProvider. * Database variables for AddonModScormOfflineProvider.
*/ */
export const ATTEMPTS_TABLE_NAME = 'addon_mod_scorm_offline_attempts'; export const ATTEMPTS_TABLE_NAME = 'addon_mod_scorm_offline_attempts';
export const ATTEMPTS_TABLE_PRIMARY_KEYS = ['scormid', 'userid', 'attempt'] as const;
export const TRACKS_TABLE_NAME = 'addon_mod_scorm_offline_scos_tracks'; export const TRACKS_TABLE_NAME = 'addon_mod_scorm_offline_scos_tracks';
export const TRACKS_TABLE_PRIMARY_KEYS = ['scormid', 'userid', 'attempt', 'scoid', 'element'] as const;
export const OFFLINE_SITE_SCHEMA: CoreSiteSchema = { export const OFFLINE_SITE_SCHEMA: CoreSiteSchema = {
name: 'AddonModScormOfflineProvider', name: 'AddonModScormOfflineProvider',
version: 1, version: 1,
@ -58,7 +60,7 @@ export const OFFLINE_SITE_SCHEMA: CoreSiteSchema = {
type: 'TEXT', type: 'TEXT',
}, },
], ],
primaryKeys: ['scormid', 'userid', 'attempt'], primaryKeys: [...ATTEMPTS_TABLE_PRIMARY_KEYS],
}, },
{ {
name: TRACKS_TABLE_NAME, name: TRACKS_TABLE_NAME,
@ -101,7 +103,7 @@ export const OFFLINE_SITE_SCHEMA: CoreSiteSchema = {
type: 'INTEGER', type: 'INTEGER',
}, },
], ],
primaryKeys: ['scormid', 'userid', 'attempt', 'scoid', 'element'], primaryKeys: [...TRACKS_TABLE_PRIMARY_KEYS],
}, },
], ],
}; };
@ -125,6 +127,8 @@ export type AddonModScormAttemptDBRecord = AddonModScormOfflineDBCommonData & {
snapshot?: string | null; snapshot?: string | null;
}; };
export type AddonModScormAttemptDBPrimaryKeys = typeof ATTEMPTS_TABLE_PRIMARY_KEYS[number];
/** /**
* SCORM track data. * SCORM track data.
*/ */
@ -135,3 +139,5 @@ export type AddonModScormTrackDBRecord = AddonModScormOfflineDBCommonData & {
timemodified: number; timemodified: number;
synced: number; synced: number;
}; };
export type AddonModScormTrackDBPrimaryKeys = typeof TRACKS_TABLE_PRIMARY_KEYS[number];

View File

@ -22,11 +22,15 @@ import { CoreUtils } from '@services/utils/utils';
import { makeSingleton } from '@singletons'; import { makeSingleton } from '@singletons';
import { CoreLogger } from '@singletons/logger'; import { CoreLogger } from '@singletons/logger';
import { import {
AddonModScormAttemptDBPrimaryKeys,
AddonModScormAttemptDBRecord, AddonModScormAttemptDBRecord,
AddonModScormOfflineDBCommonData, AddonModScormOfflineDBCommonData,
AddonModScormTrackDBPrimaryKeys,
AddonModScormTrackDBRecord, AddonModScormTrackDBRecord,
ATTEMPTS_TABLE_NAME, ATTEMPTS_TABLE_NAME,
ATTEMPTS_TABLE_PRIMARY_KEYS,
TRACKS_TABLE_NAME, TRACKS_TABLE_NAME,
TRACKS_TABLE_PRIMARY_KEYS,
} from './database/scorm'; } from './database/scorm';
import { import {
AddonModScormDataEntry, AddonModScormDataEntry,
@ -51,33 +55,41 @@ export class AddonModScormOfflineProvider {
protected logger: CoreLogger; protected logger: CoreLogger;
protected tracksTables: LazyMap< protected tracksTables: LazyMap<
AsyncInstance<CoreDatabaseTable<AddonModScormTrackDBRecord, 'scormid' | 'userid' | 'attempt' | 'scoid' | 'element'>> AsyncInstance<CoreDatabaseTable<AddonModScormTrackDBRecord, AddonModScormTrackDBPrimaryKeys, never>>
>; >;
protected attemptsTables: LazyMap< protected attemptsTables: LazyMap<
AsyncInstance<CoreDatabaseTable<AddonModScormAttemptDBRecord, 'scormid' | 'userid' | 'attempt'>> AsyncInstance<CoreDatabaseTable<AddonModScormAttemptDBRecord, AddonModScormAttemptDBPrimaryKeys, never>>
>; >;
constructor() { constructor() {
this.logger = CoreLogger.getInstance('AddonModScormOfflineProvider'); this.logger = CoreLogger.getInstance('AddonModScormOfflineProvider');
this.tracksTables = lazyMap( this.tracksTables = lazyMap(
siteId => asyncInstance( siteId => asyncInstance(
() => CoreSites.getSiteTable(TRACKS_TABLE_NAME, { () => CoreSites.getSiteTable<AddonModScormTrackDBRecord, AddonModScormTrackDBPrimaryKeys, never>(
siteId, TRACKS_TABLE_NAME,
primaryKeyColumns: ['scormid', 'userid', 'attempt', 'scoid', 'element'], {
config: { cachingStrategy: CoreDatabaseCachingStrategy.None }, siteId,
onDestroy: () => delete this.tracksTables[siteId], primaryKeyColumns: [...TRACKS_TABLE_PRIMARY_KEYS],
}), rowIdColumn: null,
config: { cachingStrategy: CoreDatabaseCachingStrategy.None },
onDestroy: () => delete this.tracksTables[siteId],
},
),
), ),
); );
this.attemptsTables = lazyMap( this.attemptsTables = lazyMap(
siteId => asyncInstance( siteId => asyncInstance(
() => CoreSites.getSiteTable(ATTEMPTS_TABLE_NAME, { () => CoreSites.getSiteTable<AddonModScormAttemptDBRecord, AddonModScormAttemptDBPrimaryKeys, never>(
siteId, ATTEMPTS_TABLE_NAME,
primaryKeyColumns: ['scormid', 'userid', 'attempt'], {
config: { cachingStrategy: CoreDatabaseCachingStrategy.None }, siteId,
onDestroy: () => delete this.tracksTables[siteId], primaryKeyColumns: [...ATTEMPTS_TABLE_PRIMARY_KEYS],
}), rowIdColumn: null,
config: { cachingStrategy: CoreDatabaseCachingStrategy.None },
onDestroy: () => delete this.tracksTables[siteId],
},
),
), ),
); );
} }

View File

@ -38,16 +38,17 @@ import { CoreLazyDatabaseTable } from './lazy-database-table';
export class CoreDatabaseTableProxy< export class CoreDatabaseTableProxy<
DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues, DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues,
PrimaryKeyColumn extends keyof DBRecord = 'id', PrimaryKeyColumn extends keyof DBRecord = 'id',
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> RowIdColumn extends PrimaryKeyColumn = PrimaryKeyColumn,
> extends CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey> { PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>,
> extends CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn, PrimaryKey> {
protected readonly DEFAULT_CACHING_STRATEGY = CoreDatabaseCachingStrategy.None; protected readonly DEFAULT_CACHING_STRATEGY = CoreDatabaseCachingStrategy.None;
protected target = asyncInstance<CoreDatabaseTable<DBRecord, PrimaryKeyColumn>>(); protected target = asyncInstance<CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn>>();
protected environmentObserver?: CoreEventObserver; protected environmentObserver?: CoreEventObserver;
protected targetConstructors: Record< protected targetConstructors: Record<
CoreDatabaseCachingStrategy, CoreDatabaseCachingStrategy,
CoreDatabaseTableConstructor<DBRecord, PrimaryKeyColumn, PrimaryKey> CoreDatabaseTableConstructor<DBRecord, PrimaryKeyColumn, RowIdColumn>
> = { > = {
[CoreDatabaseCachingStrategy.Eager]: CoreEagerDatabaseTable, [CoreDatabaseCachingStrategy.Eager]: CoreEagerDatabaseTable,
[CoreDatabaseCachingStrategy.Lazy]: CoreLazyDatabaseTable, [CoreDatabaseCachingStrategy.Lazy]: CoreLazyDatabaseTable,
@ -154,7 +155,7 @@ export class CoreDatabaseTableProxy<
/** /**
* @inheritdoc * @inheritdoc
*/ */
async insert(record: DBRecord): Promise<void> { async insert(record: Omit<DBRecord, RowIdColumn> & Partial<Pick<DBRecord, RowIdColumn>>): Promise<number> {
return this.target.insert(record); return this.target.insert(record);
} }
@ -239,7 +240,7 @@ export class CoreDatabaseTableProxy<
* *
* @returns Target instance. * @returns Target instance.
*/ */
protected async createTarget(): Promise<CoreDatabaseTable<DBRecord, PrimaryKeyColumn>> { protected async createTarget(): Promise<CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn>> {
const config = await this.getRuntimeConfig(); const config = await this.getRuntimeConfig();
const table = this.createTable(config); const table = this.createTable(config);
@ -252,7 +253,7 @@ export class CoreDatabaseTableProxy<
* @param config Database configuration. * @param config Database configuration.
* @returns Database table. * @returns Database table.
*/ */
protected createTable(config: Partial<CoreDatabaseConfiguration>): CoreDatabaseTable<DBRecord, PrimaryKeyColumn> { protected createTable(config: Partial<CoreDatabaseConfiguration>): CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn> {
const DatabaseTable = this.targetConstructors[config.cachingStrategy ?? this.DEFAULT_CACHING_STRATEGY]; const DatabaseTable = this.targetConstructors[config.cachingStrategy ?? this.DEFAULT_CACHING_STRATEGY];
return new DatabaseTable(config, this.database, this.tableName, this.primaryKeyColumns); return new DatabaseTable(config, this.database, this.tableName, this.primaryKeyColumns);

View File

@ -21,13 +21,15 @@ import { SQLiteDB, SQLiteDBRecordValue, SQLiteDBRecordValues } from '@classes/sq
export class CoreDatabaseTable< export class CoreDatabaseTable<
DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues, DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues,
PrimaryKeyColumn extends keyof DBRecord = 'id', PrimaryKeyColumn extends keyof DBRecord = 'id',
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> RowIdColumn extends PrimaryKeyColumn = PrimaryKeyColumn,
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>,
> { > {
protected config: Partial<CoreDatabaseConfiguration>; protected config: Partial<CoreDatabaseConfiguration>;
protected database: SQLiteDB; protected database: SQLiteDB;
protected tableName: string; protected tableName: string;
protected primaryKeyColumns: PrimaryKeyColumn[]; protected primaryKeyColumns: PrimaryKeyColumn[];
protected rowIdColumn: RowIdColumn | null;
protected listeners: CoreDatabaseTableListener[] = []; protected listeners: CoreDatabaseTableListener[] = [];
constructor( constructor(
@ -35,11 +37,13 @@ export class CoreDatabaseTable<
database: SQLiteDB, database: SQLiteDB,
tableName: string, tableName: string,
primaryKeyColumns?: PrimaryKeyColumn[], primaryKeyColumns?: PrimaryKeyColumn[],
rowIdColumn?: RowIdColumn | null,
) { ) {
this.config = config; this.config = config;
this.database = database; this.database = database;
this.tableName = tableName; this.tableName = tableName;
this.primaryKeyColumns = primaryKeyColumns ?? ['id'] as PrimaryKeyColumn[]; this.primaryKeyColumns = primaryKeyColumns ?? ['id'] as PrimaryKeyColumn[];
this.rowIdColumn = rowIdColumn === null ? null : (rowIdColumn ?? 'id') as RowIdColumn;
} }
/** /**
@ -253,9 +257,12 @@ export class CoreDatabaseTable<
* Insert a new record. * Insert a new record.
* *
* @param record Database record. * @param record Database record.
* @returns New record row id.
*/ */
async insert(record: DBRecord): Promise<void> { async insert(record: Omit<DBRecord, RowIdColumn> & Partial<Pick<DBRecord, RowIdColumn>>): Promise<number> {
await this.database.insertRecord(this.tableName, record); const rowId = await this.database.insertRecord(this.tableName, record);
return rowId;
} }
/** /**
@ -263,7 +270,7 @@ export class CoreDatabaseTable<
* *
* @param record Database record. * @param record Database record.
*/ */
syncInsert(record: DBRecord): void { syncInsert(record: Omit<DBRecord, RowIdColumn> & Partial<Pick<DBRecord, RowIdColumn>>): void {
// The current database architecture does not support synchronous operations, // The current database architecture does not support synchronous operations,
// so calling this method will mean that errors will be silenced. Because of that, // so calling this method will mean that errors will be silenced. Because of that,
// this should only be called if using the asynchronous alternatives is not possible. // this should only be called if using the asynchronous alternatives is not possible.
@ -423,15 +430,17 @@ export interface CoreDatabaseTableListener {
export type CoreDatabaseTableConstructor< export type CoreDatabaseTableConstructor<
DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues, DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues,
PrimaryKeyColumn extends keyof DBRecord = 'id', PrimaryKeyColumn extends keyof DBRecord = 'id',
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> RowIdColumn extends PrimaryKeyColumn = PrimaryKeyColumn,
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>,
> = { > = {
new ( new (
config: Partial<CoreDatabaseConfiguration>, config: Partial<CoreDatabaseConfiguration>,
database: SQLiteDB, database: SQLiteDB,
tableName: string, tableName: string,
primaryKeyColumns?: PrimaryKeyColumn[] primaryKeyColumns?: PrimaryKeyColumn[],
): CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey>; rowIdColumn?: RowIdColumn | null,
): CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn, PrimaryKey>;
}; };

View File

@ -30,13 +30,14 @@ import {
export class CoreDebugDatabaseTable< export class CoreDebugDatabaseTable<
DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues, DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues,
PrimaryKeyColumn extends keyof DBRecord = 'id', PrimaryKeyColumn extends keyof DBRecord = 'id',
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> RowIdColumn extends PrimaryKeyColumn = PrimaryKeyColumn,
> extends CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey> { PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>,
> extends CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn, PrimaryKey> {
protected target: CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey>; protected target: CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn, PrimaryKey>;
protected logger: CoreLogger; protected logger: CoreLogger;
constructor(target: CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey>) { constructor(target: CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn, PrimaryKey>) {
super(target.getConfig(), target.getDatabase(), target.getTableName(), target.getPrimaryKeyColumns()); super(target.getConfig(), target.getDatabase(), target.getTableName(), target.getPrimaryKeyColumns());
this.target = target; this.target = target;
@ -48,7 +49,7 @@ export class CoreDebugDatabaseTable<
* *
* @returns Table instance. * @returns Table instance.
*/ */
getTarget(): CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey> { getTarget(): CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn, PrimaryKey> {
return this.target; return this.target;
} }
@ -152,7 +153,7 @@ export class CoreDebugDatabaseTable<
/** /**
* @inheritdoc * @inheritdoc
*/ */
insert(record: DBRecord): Promise<void> { insert(record: Omit<DBRecord, RowIdColumn> & Partial<Pick<DBRecord, RowIdColumn>>): Promise<number> {
this.logger.log('insert', record); this.logger.log('insert', record);
return this.target.insert(record); return this.target.insert(record);

View File

@ -31,8 +31,9 @@ import {
export class CoreEagerDatabaseTable< export class CoreEagerDatabaseTable<
DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues, DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues,
PrimaryKeyColumn extends keyof DBRecord = 'id', PrimaryKeyColumn extends keyof DBRecord = 'id',
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> RowIdColumn extends PrimaryKeyColumn = PrimaryKeyColumn,
> extends CoreInMemoryDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey> { PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>,
> extends CoreInMemoryDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn, PrimaryKey> {
protected records: Record<string, DBRecord> = {}; protected records: Record<string, DBRecord> = {};
@ -153,12 +154,10 @@ export class CoreEagerDatabaseTable<
/** /**
* @inheritdoc * @inheritdoc
*/ */
async insert(record: DBRecord): Promise<void> { async insert(record: Omit<DBRecord, RowIdColumn> & Partial<Pick<DBRecord, RowIdColumn>>): Promise<number> {
await super.insert(record); const rowId = await this.insertAndRemember(record, this.records);
const primaryKey = this.serializePrimaryKey(this.getPrimaryKeyFromRecord(record)); return rowId;
this.records[primaryKey] = record;
} }
/** /**

View File

@ -26,8 +26,9 @@ import { CoreDatabaseTable, GetDBRecordPrimaryKey } from './database-table';
export abstract class CoreInMemoryDatabaseTable< export abstract class CoreInMemoryDatabaseTable<
DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues, DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues,
PrimaryKeyColumn extends keyof DBRecord = 'id', PrimaryKeyColumn extends keyof DBRecord = 'id',
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> RowIdColumn extends PrimaryKeyColumn = PrimaryKeyColumn,
> extends CoreDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey> { PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>,
> extends CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn, PrimaryKey> {
private static readonly ACTIVE_TABLES: WeakMap<SQLiteDB, Set<string>> = new WeakMap(); private static readonly ACTIVE_TABLES: WeakMap<SQLiteDB, Set<string>> = new WeakMap();
private static readonly LOGGER: CoreLogger = CoreLogger.getInstance('CoreInMemoryDatabaseTable'); private static readonly LOGGER: CoreLogger = CoreLogger.getInstance('CoreInMemoryDatabaseTable');
@ -70,4 +71,28 @@ export abstract class CoreInMemoryDatabaseTable<
} }
} }
/**
* Insert a new record and store it in the given object.
*
* @param record Database record.
* @param records Records object.
* @returns New record row id.
*/
protected async insertAndRemember(
record: Omit<DBRecord, RowIdColumn> & Partial<Pick<DBRecord, RowIdColumn>>,
records: Record<string, DBRecord | null>,
): Promise<number> {
const rowId = await super.insert(record);
const completeRecord = (this.rowIdColumn && !(this.rowIdColumn in record))
? Object.assign({ [this.rowIdColumn]: rowId }, record) as DBRecord
: record as DBRecord;
const primaryKey = this.serializePrimaryKey(this.getPrimaryKeyFromRecord(completeRecord));
records[primaryKey] = completeRecord;
return rowId;
}
} }

View File

@ -31,8 +31,9 @@ import {
export class CoreLazyDatabaseTable< export class CoreLazyDatabaseTable<
DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues, DBRecord extends SQLiteDBRecordValues = SQLiteDBRecordValues,
PrimaryKeyColumn extends keyof DBRecord = 'id', PrimaryKeyColumn extends keyof DBRecord = 'id',
PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> RowIdColumn extends PrimaryKeyColumn = PrimaryKeyColumn,
> extends CoreInMemoryDatabaseTable<DBRecord, PrimaryKeyColumn, PrimaryKey> { PrimaryKey extends GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn> = GetDBRecordPrimaryKey<DBRecord, PrimaryKeyColumn>,
> extends CoreInMemoryDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn, PrimaryKey> {
protected readonly DEFAULT_CACHE_LIFETIME = 60000; protected readonly DEFAULT_CACHE_LIFETIME = 60000;
@ -137,10 +138,10 @@ export class CoreLazyDatabaseTable<
/** /**
* @inheritdoc * @inheritdoc
*/ */
async insert(record: DBRecord): Promise<void> { async insert(record: Omit<DBRecord, RowIdColumn> & Partial<Pick<DBRecord, RowIdColumn>>): Promise<number> {
await super.insert(record); const rowId = await this.insertAndRemember(record, this.records);
this.records[this.serializePrimaryKey(this.getPrimaryKeyFromRecord(record))] = record; return rowId;
} }
/** /**

View File

@ -42,8 +42,10 @@ import { CoreDatabaseCachingStrategy } from '../database/database-table-proxy';
import { import {
CONFIG_TABLE, CONFIG_TABLE,
CoreSiteConfigDBRecord, CoreSiteConfigDBRecord,
CoreSiteLastViewedDBPrimaryKeys,
CoreSiteLastViewedDBRecord, CoreSiteLastViewedDBRecord,
CoreSiteWSCacheRecord, CoreSiteWSCacheRecord,
LAST_VIEWED_PRIMARY_KEYS,
LAST_VIEWED_TABLE, LAST_VIEWED_TABLE,
WS_CACHE_TABLE, WS_CACHE_TABLE,
} from '@services/database/sites'; } from '@services/database/sites';
@ -65,8 +67,8 @@ export class CoreSite extends CoreAuthenticatedSite {
protected db!: SQLiteDB; protected db!: SQLiteDB;
protected cacheTable: AsyncInstance<CoreDatabaseTable<CoreSiteWSCacheRecord>>; protected cacheTable: AsyncInstance<CoreDatabaseTable<CoreSiteWSCacheRecord>>;
protected configTable: AsyncInstance<CoreDatabaseTable<CoreSiteConfigDBRecord, 'name'>>; protected configTable: AsyncInstance<CoreDatabaseTable<CoreSiteConfigDBRecord, 'name', never>>;
protected lastViewedTable: AsyncInstance<CoreDatabaseTable<CoreSiteLastViewedDBRecord, 'component' | 'id'>>; protected lastViewedTable: AsyncInstance<CoreDatabaseTable<CoreSiteLastViewedDBRecord, CoreSiteLastViewedDBPrimaryKeys>>;
protected lastAutoLogin = 0; protected lastAutoLogin = 0;
protected tokenPluginFileWorks?: boolean; protected tokenPluginFileWorks?: boolean;
protected tokenPluginFileWorksPromise?: Promise<boolean>; protected tokenPluginFileWorksPromise?: Promise<boolean>;
@ -99,18 +101,19 @@ export class CoreSite extends CoreAuthenticatedSite {
config: { cachingStrategy: CoreDatabaseCachingStrategy.None }, config: { cachingStrategy: CoreDatabaseCachingStrategy.None },
})); }));
this.configTable = asyncInstance(() => CoreSites.getSiteTable(CONFIG_TABLE, { this.configTable = asyncInstance(() => CoreSites.getSiteTable<CoreSiteConfigDBRecord, 'name', never>(CONFIG_TABLE, {
siteId: this.getId(), siteId: this.getId(),
database: this.getDb(), database: this.getDb(),
config: { cachingStrategy: CoreDatabaseCachingStrategy.Eager }, config: { cachingStrategy: CoreDatabaseCachingStrategy.Eager },
primaryKeyColumns: ['name'], primaryKeyColumns: ['name'],
rowIdColumn: null,
})); }));
this.lastViewedTable = asyncInstance(() => CoreSites.getSiteTable(LAST_VIEWED_TABLE, { this.lastViewedTable = asyncInstance(() => CoreSites.getSiteTable(LAST_VIEWED_TABLE, {
siteId: this.getId(), siteId: this.getId(),
database: this.getDb(), database: this.getDb(),
config: { cachingStrategy: CoreDatabaseCachingStrategy.Eager }, config: { cachingStrategy: CoreDatabaseCachingStrategy.Eager },
primaryKeyColumns: ['component', 'id'], primaryKeyColumns: [...LAST_VIEWED_PRIMARY_KEYS],
})); }));
this.setInfo(otherData.info); this.setInfo(otherData.info);
this.calculateOfflineDisabled(); this.calculateOfflineDisabled();

View File

@ -27,7 +27,12 @@ import { makeSingleton, Translate } from '@singletons';
import { CoreStatusWithWarningsWSResponse, CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws'; import { CoreStatusWithWarningsWSResponse, CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
import { import {
CoreCourseStatusDBRecord, CoreCourseViewedModulesDBRecord, COURSE_STATUS_TABLE, COURSE_VIEWED_MODULES_TABLE , CoreCourseStatusDBRecord,
CoreCourseViewedModulesDBPrimaryKeys,
CoreCourseViewedModulesDBRecord,
COURSE_STATUS_TABLE,
COURSE_VIEWED_MODULES_PRIMARY_KEYS,
COURSE_VIEWED_MODULES_TABLE,
} from './database/course'; } from './database/course';
import { CoreCourseOffline } from './course-offline'; import { CoreCourseOffline } from './course-offline';
import { CoreError } from '@classes/errors/error'; import { CoreError } from '@classes/errors/error';
@ -121,7 +126,9 @@ export class CoreCourseProvider {
protected logger: CoreLogger; protected logger: CoreLogger;
protected statusTables: LazyMap<AsyncInstance<CoreDatabaseTable<CoreCourseStatusDBRecord>>>; protected statusTables: LazyMap<AsyncInstance<CoreDatabaseTable<CoreCourseStatusDBRecord>>>;
protected viewedModulesTables: LazyMap<AsyncInstance<CoreDatabaseTable<CoreCourseViewedModulesDBRecord, 'courseId' | 'cmId'>>>; protected viewedModulesTables: LazyMap<
AsyncInstance<CoreDatabaseTable<CoreCourseViewedModulesDBRecord, CoreCourseViewedModulesDBPrimaryKeys, never>>
>;
constructor() { constructor() {
this.logger = CoreLogger.getInstance('CoreCourseProvider'); this.logger = CoreLogger.getInstance('CoreCourseProvider');
@ -137,12 +144,16 @@ export class CoreCourseProvider {
this.viewedModulesTables = lazyMap( this.viewedModulesTables = lazyMap(
siteId => asyncInstance( siteId => asyncInstance(
() => CoreSites.getSiteTable(COURSE_VIEWED_MODULES_TABLE, { () => CoreSites.getSiteTable<CoreCourseViewedModulesDBRecord, CoreCourseViewedModulesDBPrimaryKeys, never>(
siteId, COURSE_VIEWED_MODULES_TABLE,
config: { cachingStrategy: CoreDatabaseCachingStrategy.None }, {
primaryKeyColumns: ['courseId', 'cmId'], siteId,
onDestroy: () => delete this.viewedModulesTables[siteId], config: { cachingStrategy: CoreDatabaseCachingStrategy.None },
}), primaryKeyColumns: [...COURSE_VIEWED_MODULES_PRIMARY_KEYS],
rowIdColumn: null,
onDestroy: () => delete this.viewedModulesTables[siteId],
},
),
), ),
); );
} }

View File

@ -19,6 +19,7 @@ import { CoreSiteSchema } from '@services/sites';
*/ */
export const COURSE_STATUS_TABLE = 'course_status'; export const COURSE_STATUS_TABLE = 'course_status';
export const COURSE_VIEWED_MODULES_TABLE = 'course_viewed_modules'; export const COURSE_VIEWED_MODULES_TABLE = 'course_viewed_modules';
export const COURSE_VIEWED_MODULES_PRIMARY_KEYS = ['courseId', 'cmId'] as const;
export const SITE_SCHEMA: CoreSiteSchema = { export const SITE_SCHEMA: CoreSiteSchema = {
name: 'CoreCourseProvider', name: 'CoreCourseProvider',
version: 2, version: 2,
@ -75,7 +76,7 @@ export const SITE_SCHEMA: CoreSiteSchema = {
type: 'INTEGER', type: 'INTEGER',
}, },
], ],
primaryKeys: ['courseId', 'cmId'], primaryKeys: [...COURSE_VIEWED_MODULES_PRIMARY_KEYS],
}, },
], ],
}; };
@ -133,6 +134,8 @@ export type CoreCourseViewedModulesDBRecord = {
sectionId?: number; sectionId?: number;
}; };
export type CoreCourseViewedModulesDBPrimaryKeys = typeof COURSE_VIEWED_MODULES_PRIMARY_KEYS[number];
export type CoreCourseManualCompletionDBRecord = { export type CoreCourseManualCompletionDBRecord = {
cmid: number; cmid: number;
completed: number; completed: number;

View File

@ -21,8 +21,10 @@ import { CoreSiteSchema } from '@services/sites';
* Keep "addon" in some names for backwards compatibility. * Keep "addon" in some names for backwards compatibility.
*/ */
export const BADGE_TABLE_NAME = 'addon_pushnotifications_badge'; export const BADGE_TABLE_NAME = 'addon_pushnotifications_badge';
export const BADGE_TABLE_PRIMARY_KEYS = ['siteid', 'addon'] as const;
export const PENDING_UNREGISTER_TABLE_NAME = 'addon_pushnotifications_pending_unregister'; export const PENDING_UNREGISTER_TABLE_NAME = 'addon_pushnotifications_pending_unregister';
export const REGISTERED_DEVICES_TABLE_NAME = 'addon_pushnotifications_registered_devices_2'; export const REGISTERED_DEVICES_TABLE_NAME = 'addon_pushnotifications_registered_devices_2';
export const REGISTERED_DEVICES_TABLE_PRIMARY_KEYS = ['appid', 'uuid'] as const;
export const APP_SCHEMA: CoreAppSchema = { export const APP_SCHEMA: CoreAppSchema = {
name: 'CorePushNotificationsProvider', name: 'CorePushNotificationsProvider',
version: 1, version: 1,
@ -43,7 +45,7 @@ export const APP_SCHEMA: CoreAppSchema = {
type: 'INTEGER', type: 'INTEGER',
}, },
], ],
primaryKeys: ['siteid', 'addon'], primaryKeys: [...BADGE_TABLE_PRIMARY_KEYS],
}, },
{ {
name: PENDING_UNREGISTER_TABLE_NAME, name: PENDING_UNREGISTER_TABLE_NAME,
@ -109,7 +111,7 @@ export const SITE_SCHEMA: CoreSiteSchema = {
type: 'TEXT', type: 'TEXT',
}, },
], ],
primaryKeys: ['appid', 'uuid'], primaryKeys: [...REGISTERED_DEVICES_TABLE_PRIMARY_KEYS],
}, },
], ],
async migrate(db: SQLiteDB, oldVersion: number): Promise<void> { async migrate(db: SQLiteDB, oldVersion: number): Promise<void> {
@ -129,6 +131,8 @@ export type CorePushNotificationsBadgeDBRecord = {
number: number; // eslint-disable-line id-blacklist number: number; // eslint-disable-line id-blacklist
}; };
export type CorePushNotificationsBadgeDBPrimaryKeys = typeof BADGE_TABLE_PRIMARY_KEYS[number];
/** /**
* Data stored in DB for pending unregisters. * Data stored in DB for pending unregisters.
*/ */
@ -152,3 +156,5 @@ export type CorePushNotificationsRegisteredDeviceDBRecord = {
pushid: string; // Push ID. pushid: string; // Push ID.
publickey?: string; // Public key. publickey?: string; // Public key.
}; };
export type CorePushNotificationsRegisteredDeviceDBPrimaryKeys = typeof REGISTERED_DEVICES_TABLE_PRIMARY_KEYS[number];

View File

@ -36,6 +36,10 @@ import {
CorePushNotificationsPendingUnregisterDBRecord, CorePushNotificationsPendingUnregisterDBRecord,
CorePushNotificationsRegisteredDeviceDBRecord, CorePushNotificationsRegisteredDeviceDBRecord,
CorePushNotificationsBadgeDBRecord, CorePushNotificationsBadgeDBRecord,
REGISTERED_DEVICES_TABLE_PRIMARY_KEYS,
CorePushNotificationsRegisteredDeviceDBPrimaryKeys,
CorePushNotificationsBadgeDBPrimaryKeys,
BADGE_TABLE_PRIMARY_KEYS,
} from './database/pushnotifications'; } from './database/pushnotifications';
import { CoreError } from '@classes/errors/error'; import { CoreError } from '@classes/errors/error';
import { CoreWSExternalWarning } from '@services/ws'; import { CoreWSExternalWarning } from '@services/ws';
@ -61,23 +65,38 @@ export class CorePushNotificationsProvider {
protected logger: CoreLogger; protected logger: CoreLogger;
protected pushID?: string; protected pushID?: string;
protected badgesTable = asyncInstance<CoreDatabaseTable<CorePushNotificationsBadgeDBRecord, 'siteid' | 'addon'>>(); protected badgesTable =
asyncInstance<CoreDatabaseTable<CorePushNotificationsBadgeDBRecord, CorePushNotificationsBadgeDBPrimaryKeys>>();
protected pendingUnregistersTable = protected pendingUnregistersTable =
asyncInstance<CoreDatabaseTable<CorePushNotificationsPendingUnregisterDBRecord, 'siteid'>>(); asyncInstance<CoreDatabaseTable<CorePushNotificationsPendingUnregisterDBRecord, 'siteid'>>();
protected registeredDevicesTables: protected registeredDevicesTables:
LazyMap<AsyncInstance<CoreDatabaseTable<CorePushNotificationsRegisteredDeviceDBRecord, 'appid' | 'uuid'>>>; LazyMap<
AsyncInstance<
CoreDatabaseTable<
CorePushNotificationsRegisteredDeviceDBRecord,
CorePushNotificationsRegisteredDeviceDBPrimaryKeys,
never
>
>
>;
constructor() { constructor() {
this.logger = CoreLogger.getInstance('CorePushNotificationsProvider'); this.logger = CoreLogger.getInstance('CorePushNotificationsProvider');
this.registeredDevicesTables = lazyMap( this.registeredDevicesTables = lazyMap(
siteId => asyncInstance( siteId => asyncInstance(
() => CoreSites.getSiteTable( () => CoreSites.getSiteTable<
CorePushNotificationsRegisteredDeviceDBRecord,
CorePushNotificationsRegisteredDeviceDBPrimaryKeys,
never
>(
REGISTERED_DEVICES_TABLE_NAME, REGISTERED_DEVICES_TABLE_NAME,
{ {
siteId, siteId,
config: { cachingStrategy: CoreDatabaseCachingStrategy.None }, config: { cachingStrategy: CoreDatabaseCachingStrategy.None },
primaryKeyColumns: ['appid', 'uuid'], primaryKeyColumns: [...REGISTERED_DEVICES_TABLE_PRIMARY_KEYS],
rowIdColumn: null,
onDestroy: () => delete this.registeredDevicesTables[siteId], onDestroy: () => delete this.registeredDevicesTables[siteId],
}, },
), ),
@ -190,11 +209,11 @@ export class CorePushNotificationsProvider {
} }
const database = CoreApp.getDB(); const database = CoreApp.getDB();
const badgesTable = new CoreDatabaseTableProxy<CorePushNotificationsBadgeDBRecord, 'siteid' | 'addon'>( const badgesTable = new CoreDatabaseTableProxy<CorePushNotificationsBadgeDBRecord, CorePushNotificationsBadgeDBPrimaryKeys>(
{ cachingStrategy: CoreDatabaseCachingStrategy.Eager }, { cachingStrategy: CoreDatabaseCachingStrategy.Eager },
database, database,
BADGE_TABLE_NAME, BADGE_TABLE_NAME,
['siteid', 'addon'], [...BADGE_TABLE_PRIMARY_KEYS],
); );
const pendingUnregistersTable = new CoreDatabaseTableProxy<CorePushNotificationsPendingUnregisterDBRecord, 'siteid'>( const pendingUnregistersTable = new CoreDatabaseTableProxy<CorePushNotificationsPendingUnregisterDBRecord, 'siteid'>(
{ cachingStrategy: CoreDatabaseCachingStrategy.Eager }, { cachingStrategy: CoreDatabaseCachingStrategy.Eager },

View File

@ -49,7 +49,6 @@ export class CoreUserToursService {
{ cachingStrategy: CoreDatabaseCachingStrategy.Eager }, { cachingStrategy: CoreDatabaseCachingStrategy.Eager },
CoreApp.getDB(), CoreApp.getDB(),
USER_TOURS_TABLE_NAME, USER_TOURS_TABLE_NAME,
['id'],
); );
await table.initialize(); await table.initialize();

View File

@ -19,8 +19,10 @@ import { CoreSiteSchema } from '@services/sites';
* Database variables for CoreFilepool service. * Database variables for CoreFilepool service.
*/ */
export const QUEUE_TABLE_NAME = 'filepool_files_queue'; // Queue of files to download. export const QUEUE_TABLE_NAME = 'filepool_files_queue'; // Queue of files to download.
export const QUEUE_TABLE_PRIMARY_KEYS = ['siteId', 'fileId'] as const;
export const FILES_TABLE_NAME = 'filepool_files'; // Downloaded files. export const FILES_TABLE_NAME = 'filepool_files'; // Downloaded files.
export const LINKS_TABLE_NAME = 'filepool_files_links'; // Links between downloaded files and components. export const LINKS_TABLE_NAME = 'filepool_files_links'; // Links between downloaded files and components.
export const LINKS_TABLE_PRIMARY_KEYS = ['fileId', 'component', 'componentId'] as const;
export const PACKAGES_TABLE_NAME = 'filepool_packages'; // Downloaded packages (sets of files). export const PACKAGES_TABLE_NAME = 'filepool_packages'; // Downloaded packages (sets of files).
export const APP_SCHEMA: CoreAppSchema = { export const APP_SCHEMA: CoreAppSchema = {
name: 'CoreFilepoolProvider', name: 'CoreFilepoolProvider',
@ -74,7 +76,7 @@ export const APP_SCHEMA: CoreAppSchema = {
type: 'TEXT', type: 'TEXT',
}, },
], ],
primaryKeys: ['siteId', 'fileId'], primaryKeys: [...QUEUE_TABLE_PRIMARY_KEYS],
}, },
], ],
}; };
@ -146,7 +148,7 @@ export const SITE_SCHEMA: CoreSiteSchema = {
type: 'TEXT', type: 'TEXT',
}, },
], ],
primaryKeys: ['fileId', 'component', 'componentId'], primaryKeys: [...LINKS_TABLE_PRIMARY_KEYS],
}, },
{ {
name: PACKAGES_TABLE_NAME, name: PACKAGES_TABLE_NAME,
@ -241,7 +243,7 @@ export type CoreFilepoolFileEntry = CoreFilepoolFileOptions & {
/** /**
* DB data for entry from file's queue. * DB data for entry from file's queue.
*/ */
export type CoreFilepoolQueueDBEntry = CoreFilepoolFileOptions & { export type CoreFilepoolQueueDBRecord = CoreFilepoolFileOptions & {
/** /**
* The site the file belongs to. * The site the file belongs to.
*/ */
@ -278,10 +280,12 @@ export type CoreFilepoolQueueDBEntry = CoreFilepoolFileOptions & {
links: string; links: string;
}; };
export type CoreFilepoolQueueDBPrimaryKeys = typeof QUEUE_TABLE_PRIMARY_KEYS[number];
/** /**
* Entry from the file's queue. * Entry from the file's queue.
*/ */
export type CoreFilepoolQueueEntry = CoreFilepoolQueueDBEntry & { export type CoreFilepoolQueueEntry = CoreFilepoolQueueDBRecord & {
/** /**
* File links (to link the file to components and componentIds). * File links (to link the file to components and componentIds).
*/ */
@ -356,8 +360,10 @@ export type CoreFilepoolComponentLink = {
/** /**
* Links table record type. * Links table record type.
*/ */
export type CoreFilepoolLinksRecord = { export type CoreFilepoolLinksDBRecord = {
fileId: string; // File Id. fileId: string; // File Id.
component: string; // Component name. component: string; // Component name.
componentId: number | string; // Component Id. componentId: number | string; // Component Id.
}; };
export type CoreFilepoolLinksDBPrimaryKeys = typeof LINKS_TABLE_PRIMARY_KEYS[number];

View File

@ -28,6 +28,7 @@ export const SCHEMA_VERSIONS_TABLE_NAME = 'schema_versions';
export const WS_CACHE_TABLE = 'wscache_2'; export const WS_CACHE_TABLE = 'wscache_2';
export const CONFIG_TABLE = 'core_site_config'; export const CONFIG_TABLE = 'core_site_config';
export const LAST_VIEWED_TABLE = 'core_site_last_viewed'; export const LAST_VIEWED_TABLE = 'core_site_last_viewed';
export const LAST_VIEWED_PRIMARY_KEYS = ['component', 'id'] as const;
// Schema to register in App DB. // Schema to register in App DB.
export const APP_SCHEMA: CoreAppSchema = { export const APP_SCHEMA: CoreAppSchema = {
@ -156,7 +157,7 @@ export const SITE_SCHEMA: CoreSiteSchema = {
type: 'INTEGER', type: 'INTEGER',
}, },
], ],
primaryKeys: ['component', 'id'], primaryKeys: [...LAST_VIEWED_PRIMARY_KEYS],
}, },
], ],
}; };
@ -214,3 +215,5 @@ export type CoreSiteLastViewedDBRecord = {
timeaccess: number; timeaccess: number;
data?: string; data?: string;
}; };
export type CoreSiteLastViewedDBPrimaryKeys = typeof LAST_VIEWED_PRIMARY_KEYS[number];

View File

@ -42,10 +42,14 @@ import {
CoreFilepoolFileEntry, CoreFilepoolFileEntry,
CoreFilepoolComponentLink, CoreFilepoolComponentLink,
CoreFilepoolFileOptions, CoreFilepoolFileOptions,
CoreFilepoolLinksRecord, CoreFilepoolLinksDBRecord,
CoreFilepoolPackageEntry, CoreFilepoolPackageEntry,
CoreFilepoolQueueEntry, CoreFilepoolQueueEntry,
CoreFilepoolQueueDBEntry, CoreFilepoolQueueDBRecord,
CoreFilepoolLinksDBPrimaryKeys,
LINKS_TABLE_PRIMARY_KEYS,
CoreFilepoolQueueDBPrimaryKeys,
QUEUE_TABLE_PRIMARY_KEYS,
} from '@services/database/filepool'; } from '@services/database/filepool';
import { CoreFileHelper } from './file-helper'; import { CoreFileHelper } from './file-helper';
import { CoreUrl } from '@singletons/url'; import { CoreUrl } from '@singletons/url';
@ -102,33 +106,39 @@ export class CoreFilepoolProvider {
// Variables to prevent downloading packages/files twice at the same time. // Variables to prevent downloading packages/files twice at the same time.
protected packagesPromises: { [s: string]: { [s: string]: Promise<void> } } = {}; protected packagesPromises: { [s: string]: { [s: string]: Promise<void> } } = {};
protected filePromises: { [s: string]: { [s: string]: Promise<string> } } = {}; protected filePromises: { [s: string]: { [s: string]: Promise<string> } } = {};
protected filesTables: LazyMap<AsyncInstance<CoreDatabaseTable<CoreFilepoolFileEntry, 'fileId'>>>; protected filesTables: LazyMap<AsyncInstance<CoreDatabaseTable<CoreFilepoolFileEntry, 'fileId', never>>>;
protected linksTables: protected linksTables: LazyMap<
LazyMap<AsyncInstance<CoreDatabaseTable<CoreFilepoolLinksRecord, 'fileId' | 'component' | 'componentId'>>>; AsyncInstance<CoreDatabaseTable<CoreFilepoolLinksDBRecord, CoreFilepoolLinksDBPrimaryKeys, never>>
>;
protected packagesTables: LazyMap<AsyncInstance<CoreDatabaseTable<CoreFilepoolPackageEntry>>>; protected packagesTables: LazyMap<AsyncInstance<CoreDatabaseTable<CoreFilepoolPackageEntry>>>;
protected queueTable = asyncInstance<CoreDatabaseTable<CoreFilepoolQueueDBEntry, 'siteId' | 'fileId'>>(); protected queueTable = asyncInstance<CoreDatabaseTable<CoreFilepoolQueueDBRecord, CoreFilepoolQueueDBPrimaryKeys>>();
constructor() { constructor() {
this.logger = CoreLogger.getInstance('CoreFilepoolProvider'); this.logger = CoreLogger.getInstance('CoreFilepoolProvider');
this.filesTables = lazyMap( this.filesTables = lazyMap(
siteId => asyncInstance( siteId => asyncInstance(
() => CoreSites.getSiteTable(FILES_TABLE_NAME, { () => CoreSites.getSiteTable<CoreFilepoolFileEntry, 'fileId', never>(FILES_TABLE_NAME, {
siteId, siteId,
config: { cachingStrategy: CoreDatabaseCachingStrategy.Lazy }, config: { cachingStrategy: CoreDatabaseCachingStrategy.Lazy },
primaryKeyColumns: ['fileId'], primaryKeyColumns: ['fileId'],
rowIdColumn: null,
onDestroy: () => delete this.filesTables[siteId], onDestroy: () => delete this.filesTables[siteId],
}), }),
), ),
); );
this.linksTables = lazyMap( this.linksTables = lazyMap(
siteId => asyncInstance( siteId => asyncInstance(
() => CoreSites.getSiteTable(LINKS_TABLE_NAME, { () => CoreSites.getSiteTable<CoreFilepoolLinksDBRecord, CoreFilepoolLinksDBPrimaryKeys, never>(
siteId, LINKS_TABLE_NAME,
config: { cachingStrategy: CoreDatabaseCachingStrategy.Lazy }, {
primaryKeyColumns: ['fileId', 'component', 'componentId'], siteId,
onDestroy: () => delete this.linksTables[siteId], config: { cachingStrategy: CoreDatabaseCachingStrategy.Lazy },
}), primaryKeyColumns: [...LINKS_TABLE_PRIMARY_KEYS],
rowIdColumn: null,
onDestroy: () => delete this.linksTables[siteId],
},
),
), ),
); );
this.packagesTables = lazyMap( this.packagesTables = lazyMap(
@ -168,11 +178,11 @@ export class CoreFilepoolProvider {
// Ignore errors. // Ignore errors.
} }
const queueTable = new CoreDatabaseTableProxy<CoreFilepoolQueueDBEntry, 'siteId' | 'fileId'>( const queueTable = new CoreDatabaseTableProxy<CoreFilepoolQueueDBRecord, CoreFilepoolQueueDBPrimaryKeys>(
{ cachingStrategy: CoreDatabaseCachingStrategy.Lazy }, { cachingStrategy: CoreDatabaseCachingStrategy.Lazy },
CoreApp.getDB(), CoreApp.getDB(),
QUEUE_TABLE_NAME, QUEUE_TABLE_NAME,
['siteId','fileId'], [...QUEUE_TABLE_PRIMARY_KEYS],
); );
await queueTable.initialize(); await queueTable.initialize();
@ -406,7 +416,7 @@ export class CoreFilepoolProvider {
return this.addToQueue(siteId, fileId, fileUrl, priority, revision, timemodified, filePath, onProgress, options, link); return this.addToQueue(siteId, fileId, fileUrl, priority, revision, timemodified, filePath, onProgress, options, link);
} }
const newData: Partial<CoreFilepoolQueueDBEntry> = {}; const newData: Partial<CoreFilepoolQueueDBRecord> = {};
let foundLink = false; let foundLink = false;
// We already have the file in queue, we update the priority and links. // We already have the file in queue, we update the priority and links.
@ -1245,7 +1255,7 @@ export class CoreFilepoolProvider {
siteId: string | undefined, siteId: string | undefined,
component: string, component: string,
componentId?: string | number, componentId?: string | number,
): Promise<CoreFilepoolLinksRecord[]> { ): Promise<CoreFilepoolLinksDBRecord[]> {
siteId = siteId ?? CoreSites.getCurrentSiteId(); siteId = siteId ?? CoreSites.getCurrentSiteId();
const conditions = { const conditions = {
component, component,
@ -1364,7 +1374,7 @@ export class CoreFilepoolProvider {
* @param fileId The file ID. * @param fileId The file ID.
* @returns Promise resolved with the links. * @returns Promise resolved with the links.
*/ */
protected async getFileLinks(siteId: string, fileId: string): Promise<CoreFilepoolLinksRecord[]> { protected async getFileLinks(siteId: string, fileId: string): Promise<CoreFilepoolLinksDBRecord[]> {
const items = await this.linksTables[siteId].getMany({ fileId }); const items = await this.linksTables[siteId].getMany({ fileId });
items.forEach((item) => { items.forEach((item) => {

View File

@ -93,7 +93,7 @@ export class CoreSitesProvider {
protected siteSchemas: { [name: string]: CoreRegisteredSiteSchema } = {}; protected siteSchemas: { [name: string]: CoreRegisteredSiteSchema } = {};
protected pluginsSiteSchemas: { [name: string]: CoreRegisteredSiteSchema } = {}; protected pluginsSiteSchemas: { [name: string]: CoreRegisteredSiteSchema } = {};
protected siteTables: Record<string, Record<string, CorePromisedValue<CoreDatabaseTable>>> = {}; protected siteTables: Record<string, Record<string, CorePromisedValue<CoreDatabaseTable>>> = {};
protected schemasTables: Record<string, AsyncInstance<CoreDatabaseTable<SchemaVersionsDBEntry, 'name'>>> = {}; protected schemasTables: Record<string, AsyncInstance<CoreDatabaseTable<SchemaVersionsDBEntry, 'name', never>>> = {};
protected sitesTable = asyncInstance<CoreDatabaseTable<SiteDBEntry>>(); protected sitesTable = asyncInstance<CoreDatabaseTable<SiteDBEntry>>();
constructor(@Optional() @Inject(CORE_SITE_SCHEMAS) siteSchemas: CoreSiteSchema[][] | null) { constructor(@Optional() @Inject(CORE_SITE_SCHEMAS) siteSchemas: CoreSiteSchema[][] | null) {
@ -211,7 +211,8 @@ export class CoreSitesProvider {
*/ */
async getSiteTable< async getSiteTable<
DBRecord extends SQLiteDBRecordValues, DBRecord extends SQLiteDBRecordValues,
PrimaryKeyColumn extends keyof DBRecord PrimaryKeyColumn extends keyof DBRecord,
RowIdColumn extends PrimaryKeyColumn,
>( >(
tableName: string, tableName: string,
options: Partial<{ options: Partial<{
@ -219,9 +220,10 @@ export class CoreSitesProvider {
config: Partial<CoreDatabaseConfiguration>; config: Partial<CoreDatabaseConfiguration>;
database: SQLiteDB; database: SQLiteDB;
primaryKeyColumns: PrimaryKeyColumn[]; primaryKeyColumns: PrimaryKeyColumn[];
rowIdColumn: RowIdColumn | null;
onDestroy(): void; onDestroy(): void;
}> = {}, }> = {},
): Promise<CoreDatabaseTable<DBRecord, PrimaryKeyColumn>> { ): Promise<CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn>> {
const siteId = options.siteId ?? this.getCurrentSiteId(); const siteId = options.siteId ?? this.getCurrentSiteId();
if (!(siteId in this.siteTables)) { if (!(siteId in this.siteTables)) {
@ -231,11 +233,12 @@ export class CoreSitesProvider {
if (!(tableName in this.siteTables[siteId])) { if (!(tableName in this.siteTables[siteId])) {
const promisedTable = this.siteTables[siteId][tableName] = new CorePromisedValue(); const promisedTable = this.siteTables[siteId][tableName] = new CorePromisedValue();
const database = options.database ?? await this.getSiteDb(siteId); const database = options.database ?? await this.getSiteDb(siteId);
const table = new CoreDatabaseTableProxy<DBRecord, PrimaryKeyColumn>( const table = new CoreDatabaseTableProxy<DBRecord, PrimaryKeyColumn, RowIdColumn>(
options.config ?? {}, options.config ?? {},
database, database,
tableName, tableName,
options.primaryKeyColumns, options.primaryKeyColumns,
options.rowIdColumn,
); );
options.onDestroy && table.addListener({ onDestroy: options.onDestroy }); options.onDestroy && table.addListener({ onDestroy: options.onDestroy });
@ -245,7 +248,7 @@ export class CoreSitesProvider {
promisedTable.resolve(table as unknown as CoreDatabaseTable); promisedTable.resolve(table as unknown as CoreDatabaseTable);
} }
return this.siteTables[siteId][tableName] as unknown as Promise<CoreDatabaseTable<DBRecord, PrimaryKeyColumn>>; return this.siteTables[siteId][tableName] as unknown as Promise<CoreDatabaseTable<DBRecord, PrimaryKeyColumn, RowIdColumn>>;
} }
/** /**
@ -2033,6 +2036,7 @@ export class CoreSitesProvider {
database: site.getDb(), database: site.getDb(),
config: { cachingStrategy: CoreDatabaseCachingStrategy.Eager }, config: { cachingStrategy: CoreDatabaseCachingStrategy.Eager },
primaryKeyColumns: ['name'], primaryKeyColumns: ['name'],
rowIdColumn: null,
onDestroy: () => delete this.schemasTables[siteId], onDestroy: () => delete this.schemasTables[siteId],
}), }),
); );