antares/src/main/libs/exporters/sql/SqlExporter.ts

189 lines
5.7 KiB
TypeScript
Raw Normal View History

2022-04-15 23:13:23 +02:00
import * as moment from 'moment';
2022-04-15 23:13:23 +02:00
import { MySQLClient } from '../../clients/MySQLClient';
import { PostgreSQLClient } from '../../clients/PostgreSQLClient';
2021-10-29 12:58:37 +02:00
import { BaseExporter } from '../BaseExporter';
export class SqlExporter extends BaseExporter {
2022-04-15 23:13:23 +02:00
protected _client: MySQLClient | PostgreSQLClient;
protected _commentChar = '--'
protected _postTablesSql = ''
2021-10-29 12:58:37 +02:00
get schemaName () {
return this._options.schema;
}
get host () {
return this._client._params.host;
}
async getServerVersion () {
const version = await this._client.getVersion();
return `${version.name} ${version.number}`;
}
async dump () {
const { includes } = this._options;
2022-04-15 23:13:23 +02:00
const extraItems = Object.keys(includes).filter((key: 'functions' | 'views' | 'triggers' | 'routines' | 'schedulers') => includes[key]);
const totalTableToProcess = this._tables.filter(
t => t.includeStructure || t.includeContent || t.includeDropStatement
).length;
const processingItemCount = totalTableToProcess + extraItems.length;
2021-10-29 12:58:37 +02:00
const exportState = {
totalItems: processingItemCount,
2021-10-29 12:58:37 +02:00
currentItemIndex: 0,
currentItem: '',
op: ''
};
const header = await this.getSqlHeader();
this.writeString(header);
this.writeString('\n\n\n');
for (const item of this._tables) {
2021-10-29 12:58:37 +02:00
// user abort operation
if (this.isCancelled) return;
2021-10-29 12:58:37 +02:00
// skip item if not set to output any detail for them
if (
!item.includeStructure &&
!item.includeContent &&
!item.includeDropStatement
)
2021-10-29 12:58:37 +02:00
continue;
exportState.currentItemIndex++;
exportState.currentItem = item.table;
exportState.op = 'FETCH';
2021-10-29 12:58:37 +02:00
this.emitUpdate(exportState);
const tableHeader = this.buildComment(
`Dump of table ${item.table}\n------------------------------------------------------------`
);
2021-10-29 12:58:37 +02:00
this.writeString(tableHeader);
this.writeString('\n\n');
if (item.includeDropStatement) {
const dropTableSyntax = this.getDropTable(item.table);
this.writeString(dropTableSyntax);
this.writeString('\n\n');
}
if (item.includeStructure) {
const createTableSyntax = await this.getCreateTable(item.table);
this.writeString(createTableSyntax);
this.writeString('\n\n');
}
if (item.includeContent) {
exportState.op = 'WRITE';
this.emitUpdate(exportState);
for await (const sqlStr of this.getTableInsert(item.table)) {
if (this.isCancelled) return;
this.writeString(sqlStr);
}
2021-10-29 12:58:37 +02:00
this.writeString('\n\n');
}
this.writeString('\n\n');
}
2022-03-27 11:41:35 +02:00
// SQL to execute after tables creation
if (this._postTablesSql) {
this.writeString(this._postTablesSql);
2021-10-29 12:58:37 +02:00
this.writeString('\n\n');
}
for (const item of extraItems) {
2022-04-15 23:13:23 +02:00
type exporterMethods = 'getViews' | 'getTriggers' | 'getSchedulers' | 'getFunctions' | 'getRoutines'
const processingMethod = `get${item.charAt(0).toUpperCase() + item.slice(1)}` as exporterMethods;
exportState.currentItemIndex++;
exportState.currentItem = item;
exportState.op = 'PROCESSING';
this.emitUpdate(exportState);
if (this[processingMethod]) {
2022-04-15 23:13:23 +02:00
const data = await this[processingMethod]() as unknown as string;
if (data !== '') {
const header =
this.buildComment(
`Dump of ${item}\n------------------------------------------------------------`
) + '\n\n';
this.writeString(header);
this.writeString(data);
this.writeString('\n\n');
}
}
}
2021-10-29 12:58:37 +02:00
const footer = await this.getFooter();
this.writeString(footer);
}
2022-04-15 23:13:23 +02:00
buildComment (text: string) {
return text
.split('\n')
.map(txt => `${this._commentChar} ${txt}`)
.join('\n');
2021-10-29 12:58:37 +02:00
}
async getSqlHeader () {
const serverVersion = await this.getServerVersion();
const header = `************************************************************
Antares - SQL Client
2022-02-16 12:58:24 +01:00
Version ${process.env.PACKAGE_VERSION}
2021-10-29 12:58:37 +02:00
https://antares-sql.app/
2022-03-31 16:04:47 +02:00
https://github.com/antares-sql/antares
2021-10-29 12:58:37 +02:00
Host: ${this.host} (${serverVersion})
Database: ${this.schemaName}
Generation time: ${moment().format()}
************************************************************`;
return this.buildComment(header);
}
async getFooter () {
return this.buildComment(`Dump completed on ${moment().format()}`);
2021-10-29 12:58:37 +02:00
}
2022-04-15 23:13:23 +02:00
/* eslint-disable @typescript-eslint/no-unused-vars */
getCreateTable (_tableName: string): Promise<string> {
throw new Error('Sql Exporter must implement the "getCreateTable" method');
2021-10-29 12:58:37 +02:00
}
2022-04-15 23:13:23 +02:00
getDropTable (_tableName: string): string {
2021-10-29 12:58:37 +02:00
throw new Error('Sql Exporter must implement the "getDropTable" method');
}
2022-04-15 23:13:23 +02:00
getTableInsert (_tableName: string): AsyncGenerator<string> {
throw new Error('Sql Exporter must implement the "getTableInsert" method');
}
getViews () {
throw new Error('Method "getViews" not implemented');
}
getTriggers () {
throw new Error('Method "getTriggers" not implemented');
}
getSchedulers () {
throw new Error('Method "getSchedulers" not implemented');
}
getFunctions () {
throw new Error('Method "getFunctions" not implemented');
}
getRoutines () {
throw new Error('Method "getRoutines" not implemented');
2021-10-29 12:58:37 +02:00
}
2022-04-15 23:13:23 +02:00
/* eslint-enable @typescript-eslint/no-unused-vars */
2021-10-29 12:58:37 +02:00
}