UNPKG

ddl-manager

Version:

store postgres procedures and triggers in files

271 lines (229 loc) 8.37 kB
import { Expression, Select } from "../../lib/ast"; import { IDatabaseDriver, MinMax } from "../../lib/database/interface"; import { Database } from "../../lib/database/schema/Database"; import { Table } from "../../lib/database/schema/Table"; import { DatabaseFunction } from "../../lib/database/schema/DatabaseFunction"; import { DatabaseTrigger } from "../../lib/database/schema/DatabaseTrigger"; import { Column } from "../../lib/database/schema/Column"; import { IFileContent } from "../../lib/fs/File"; import { Index } from "../../lib/database/schema/Index"; import { TableID } from "../../lib/database/schema/TableID"; import { CacheUpdate } from "../../lib/Comparator/graph/CacheUpdate"; export class FakeDatabaseDriver implements IDatabaseDriver { readonly state: IFileContent; readonly columns: { [tableAndColumn: string]: { name: string; type: string; default: string | null; }; }; readonly indexes: {[table: string]: Index[]}; private rowsCountByTable: {[table: string]: number}; private updatedByLimit: {[table: string]: { limit: number; }[]}; private tablesIds: {[table: string]: MinMax}; private updatedByMinMax: {[table: string]: string[]}; private columnsDrops: {[tableColumn: string]: boolean}; constructor(state?: IFileContent) { this.state = state || { functions: [], triggers: [], cache: [] }; this.columns = {}; this.rowsCountByTable = {}; this.updatedByLimit = {}; this.updatedByMinMax = {}; this.tablesIds = {}; this.columnsDrops = {}; this.indexes = {}; } async load() { const database = new Database([]); database.addFunctions(this.state.functions); for (const trigger of this.state.triggers) { const table = new Table( trigger.table.schema, trigger.table.name ); database.setTable(table); database.addTrigger( trigger ); } return database; } async query(sql: string) { return {rows: []} } async queryWithTimeout(sql: string, timeout: number) { return {rows: []} } async enableTrigger(onTable: TableID, triggerName: string): Promise<void> { } async disableTrigger(onTable: TableID, triggerName: string): Promise<void> { } async createOrReplaceFunction(func: DatabaseFunction): Promise<void> { const existentFuncIndex = this.state.functions.findIndex(someFunc => someFunc.getSignature() === func.getSignature() ); if ( existentFuncIndex !== -1 ) { this.state.functions[ existentFuncIndex ] = func; } else { this.state.functions.push( func ); } } async createOrReplaceLogFunction(func: DatabaseFunction): Promise<void> { const existentFuncIndex = this.state.functions.findIndex(someFunc => someFunc.getSignature() === func.getSignature() ); if ( existentFuncIndex !== -1 ) { this.state.functions[ existentFuncIndex ] = func; } else { this.state.functions.push( func ); } } async dropFunction(func: DatabaseFunction): Promise<void> { const existentFuncIndex = this.state.functions.findIndex(someFunc => someFunc.getSignature() === func.getSignature() ); if ( existentFuncIndex !== -1 ) { this.state.functions.splice(existentFuncIndex, 1); } } async createOrReplaceTrigger(trigger: DatabaseTrigger): Promise<void> { const existentTriggerIndex = this.state.triggers.findIndex(someTrigger => someTrigger.getSignature() === trigger.getSignature() ); if ( existentTriggerIndex !== -1 ) { this.state.triggers[ existentTriggerIndex ] = trigger; } else { this.state.triggers.push( trigger ); } } async dropTrigger(trigger: DatabaseTrigger): Promise<void> { const existentTriggerIndex = this.state.triggers.findIndex(someFunc => someFunc.getSignature() === trigger.getSignature() ); if ( existentTriggerIndex !== -1 ) { this.state.triggers.splice(existentTriggerIndex, 1); } } async getType(expression: Expression): Promise<string> { return ""; } async commentColumn(column: Column): Promise<void> { } async createOrReplaceColumn(column: Column): Promise<void> { this.columns[ column.getSignature() ] = { name: column.name, type: column.type.value, "default": column.default }; } async dropColumn(column: Column): Promise<void> { delete this.columns[ column.getSignature() ]; this.columnsDrops[ column.getSignature() ] = true; } async selectMinMax(tableId: TableID): Promise<MinMax> { const table = tableId.toString(); const minMax = this.tablesIds[ table ] || {min: null, max: null}; return minMax; } async selectNextIds( table: TableID, maxId: number, limit: number ): Promise<number[]> { const minMax = this.tablesIds[ table.toString() ] || {}; const outputIds: number[] = []; while ( outputIds.length < limit ) { maxId--; if ( maxId < (minMax.min ?? 1) ) { break; } outputIds.push(maxId); } return outputIds.reverse(); } async updateCacheForRows( update: CacheUpdate, minId: number, maxId: number ): Promise<void> { const table = update.table.table.toString(); const updated = (this.updatedByMinMax[ table ] || []).slice(); updated.push(`${minId} - ${maxId}`); this.updatedByMinMax[ table ] = updated; } async updateCacheLimitedPackage( update: CacheUpdate, limit: number ): Promise<number[]> { const table = update.table.table.toString(); const alreadyUpdatedPackages = (this.updatedByLimit[table] || []).slice(); const updateRowsCount = alreadyUpdatedPackages.reduce((total, updated) => total + updated.limit, 0 ); const totalTableRowsCount = this.rowsCountByTable[ table ] || 0; const remainder = totalTableRowsCount - updateRowsCount; alreadyUpdatedPackages.push({ limit }); this.updatedByLimit[table] = alreadyUpdatedPackages; const updatedCount = Math.min(remainder, limit); const outputIds: number[] = []; for (let i = 1; i < updatedCount; i++) { outputIds.push(i); } return outputIds; } unfreezeAll(dbState: Database): Promise<void> { throw new Error("Method not implemented."); } async dropIndex(index: Index) { const table = index.table.toString(); const tableIndexes = this.indexes[ table ] || []; const i = tableIndexes.findIndex(someIndex => someIndex.getSignature() === index.getSignature() ); if ( i !== -1 ) { tableIndexes.splice(i, 1); } this.indexes[ table ] = tableIndexes; } async createOrReplaceIndex(index: Index) { const table = index.table.toString(); const tableIndexes = this.indexes[ table ] || []; tableIndexes.push(index); this.indexes[ table ] = tableIndexes; } end() { // } async terminateActiveCacheUpdates() { // } // test methods setRowsCount(table: string, rowsCount: number) { this.rowsCountByTable[ table ] = rowsCount; } getUpdatedPackages(table: string) { return this.updatedByLimit[table]; } wasDroppedColumn(table: string, columnName: string): boolean { return !!this.columnsDrops[ table + "." + columnName ]; } setTableMinMax(table: TableID, min: number, max: number): void { this.tablesIds[ table.toString() ] = {min, max}; } getUpdates(table: TableID) { const updatedIds = (this.updatedByMinMax[ table.toString() ] || []).slice(); return updatedIds; } }