UNPKG

@bazilio-san/af-stream

Version:
121 lines (99 loc) 3.97 kB
/* eslint-disable class-methods-use-this */ import { IDbConstructorOptions, IEmPortionOfDataCount, IEmPortionOfDataSql, TDbRecord } from '../interfaces'; import { DEBUG_SQL } from '../constants'; export class DbBase { public readonly options: IDbConstructorOptions; public dbInfo: string; public fieldsList: string; public schemaAndTable: string; public fieldsArray: string[]; public tsField: string; public idFields: string[] | any[]; public sortBy: string; private ld: string; private rd: string; private noLock: string = ''; private readonly recordsetPropName: string; constructor (options: IDbConstructorOptions) { this.options = options; const { streamConfig, dbConfig } = options; let host; if (dbConfig.dialect === 'mssql') { this.ld = '['; this.rd = ']'; this.recordsetPropName = 'recordset'; this.noLock = ' WITH(NOLOCK) '; host = dbConfig.server; } else { this.ld = '"'; this.rd = '"'; this.recordsetPropName = 'rows'; ({ host } = dbConfig); } const { ld, rd } = this; this.dbInfo = `${dbConfig.user}@${ld}${host}:${dbConfig.port}${rd}.${ld}${dbConfig.database}${rd}`; const { fields, src } = streamConfig; const { schema, table, tsField, idFields } = src; if (Array.isArray(fields)) { this.fieldsArray = [...fields]; } else { this.fieldsArray = Object.keys(fields); } this.fieldsList = this.fieldsArray.map((fName) => `${ld}${fName}${rd}`).join(', '); this.schemaAndTable = `${ld}${schema}${rd}.${ld}${table}${rd}`; this.tsField = tsField; this.idFields = idFields; this.sortBy = [tsField, ...idFields].map((f) => `${ld}${f}${rd}`).join(','); } async getPool (): Promise<any> { return null; } async close (): Promise<boolean> { return true; } // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-unused-vars async query (strSQL: string): Promise<any> { return null; } async _getColumnsNames (): Promise<string[]> { return []; } async init (): Promise<void> { const { schemaAndTable, options: { exitOnError, streamConfig: { streamId } }, fieldsArray } = this; const columnsNames = await this._getColumnsNames(); const unknownFields = fieldsArray.filter((name) => !columnsNames.includes(name)); if (unknownFields.length) { exitOnError(`Table ${schemaAndTable} is missing fields specified in the ${streamId} stream configuration:\n\t${unknownFields.join('\n\t')} `); } } // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars limitIt (strSQL: string, limit: number): string { return strSQL; } getPortionSQL ({ startTs, endTs, limit }: { startTs: number, endTs: number, limit: number }): string { const { tsField, ld, rd, options: { millis2dbFn } } = this; let sql = `SELECT ${this.fieldsList} FROM ${this.schemaAndTable} WHERE ${ld}${tsField}${rd} >= ${millis2dbFn(startTs)} AND ${ld}${tsField}${rd} <= ${millis2dbFn(endTs)} ORDER BY ${this.sortBy}`; if (limit) { sql = this.limitIt(sql, limit); } return sql; } async getPortionOfData ({ startTs, endTs, limit }: { startTs: number, endTs: number, limit: number }): Promise<TDbRecord[]> { const { options: { eventEmitter, streamConfig: { streamId } }, dbInfo } = this; const sql = this.getPortionSQL({ startTs, endTs, limit }); if (DEBUG_SQL) { const payload: IEmPortionOfDataSql = { streamId, sql, startTs, endTs, limit, dbInfo }; eventEmitter.emit('get-portion-of-data-sql', payload); } const result = await this.query(sql); if (DEBUG_SQL) { const payload: IEmPortionOfDataCount = { streamId, sql, count: result?.[this.recordsetPropName]?.length }; eventEmitter.emit('get-portion-of-data-count', payload); } return result?.[this.recordsetPropName] || []; } }