dbgate-tools
Version:
Auxiliary tools for other DbGate packages.
247 lines (246 loc) • 9.3 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SqlGenerator = void 0;
const flatten_1 = __importDefault(require("lodash/flatten"));
const uniqBy_1 = __importDefault(require("lodash/uniqBy"));
const getLogger_1 = require("./getLogger");
const structureTools_1 = require("./structureTools");
const stringTools_1 = require("./stringTools");
const logger = (0, getLogger_1.getLogger)('sqlGenerator');
class SqlGenerator {
constructor(dbinfo, options, objects, dmp, driver, pool) {
this.options = options;
this.objects = objects;
this.dmp = dmp;
this.driver = driver;
this.pool = pool;
this.isTruncated = false;
this.isUnhandledException = false;
this.handleException = error => {
logger.error((0, stringTools_1.extractErrorLogData)(error), 'DBGM-00186 Unhandled error');
this.isUnhandledException = true;
};
this.dbinfo = (0, structureTools_1.extendDatabaseInfo)(dbinfo);
this.tables = this.extract('tables');
this.views = this.extract('views');
this.matviews = this.extract('matviews');
this.procedures = this.extract('procedures');
this.functions = this.extract('functions');
this.triggers = this.extract('triggers');
this.schedulerEvents = this.extract('schedulerEvents');
}
async dump() {
try {
process.on('uncaughtException', this.handleException);
this.dropObjects(this.procedures, 'Procedure');
if (this.checkDumper())
return;
this.dropObjects(this.functions, 'Function');
if (this.checkDumper())
return;
this.dropObjects(this.views, 'View');
if (this.checkDumper())
return;
this.dropObjects(this.matviews, 'Matview');
if (this.checkDumper())
return;
this.dropObjects(this.triggers, 'Trigger');
if (this.checkDumper())
return;
this.dropObjects(this.schedulerEvents, 'SchedulerEvent');
if (this.checkDumper())
return;
this.dropTables();
if (this.checkDumper())
return;
this.createTables();
if (this.checkDumper())
return;
this.truncateTables();
if (this.checkDumper())
return;
await this.insertData();
if (this.checkDumper())
return;
this.createForeignKeys();
if (this.checkDumper())
return;
this.createObjects(this.procedures, 'Procedure');
if (this.checkDumper())
return;
this.createObjects(this.functions, 'Function');
if (this.checkDumper())
return;
this.createObjects(this.views, 'View');
if (this.checkDumper())
return;
this.createObjects(this.matviews, 'Matview');
if (this.checkDumper())
return;
this.createObjects(this.triggers, 'Trigger');
if (this.checkDumper())
return;
this.createObjects(this.schedulerEvents, 'SchedulerEvent');
if (this.checkDumper())
return;
}
finally {
process.off('uncaughtException', this.handleException);
}
}
createForeignKeys() {
const fks = [];
if (this.options.createForeignKeys)
fks.push(...(0, flatten_1.default)(this.tables.map(x => x.foreignKeys || [])));
if (this.options.createReferences)
fks.push(...(0, flatten_1.default)(this.tables.map(x => x.dependencies || [])));
for (const fk of (0, uniqBy_1.default)(fks, 'constraintName')) {
this.dmp.createForeignKey(fk);
if (this.checkDumper())
return;
}
}
truncateTables() {
if (this.options.truncate) {
for (const table of this.tables) {
this.dmp.truncateTable(table);
if (this.checkDumper())
return;
}
}
}
createTables() {
if (this.options.createTables) {
for (const table of this.tables) {
this.dmp.createTable({
...table,
foreignKeys: [],
dependencies: [],
indexes: [],
});
if (this.checkDumper())
return;
}
}
if (this.options.createIndexes) {
for (const index of (0, flatten_1.default)(this.tables.map(x => x.indexes || []))) {
this.dmp.createIndex(index);
}
}
}
async insertData() {
if (!this.options.insert)
return;
this.enableConstraints(false);
for (const table of this.tables) {
await this.insertTableData(table);
if (this.checkDumper())
return;
}
this.enableConstraints(true);
}
checkDumper() {
if (this.dmp.s.length > 4000000) {
if (!this.isTruncated) {
this.dmp.putRaw('\n');
this.dmp.comment(' *************** SQL is truncated ******************');
this.dmp.putRaw('\n');
}
this.isTruncated = true;
return true;
}
return false;
}
dropObjects(list, name) {
if (this.options[`drop${name}s`]) {
for (const item of list) {
this.dmp[`drop${name}`](item, { testIfExists: this.options[`checkIf${name}Exists`] });
if (this.checkDumper())
return;
}
}
}
createObjects(list, name) {
if (this.options[`create${name}s`]) {
for (const item of list) {
this.dmp[`create${name}`](item);
if (this.checkDumper())
return;
}
}
}
dropTables() {
if (this.options.dropReferences) {
for (const fk of (0, flatten_1.default)(this.tables.map(x => x.dependencies || []))) {
this.dmp.dropForeignKey(fk);
}
}
if (this.options.dropTables) {
for (const table of this.tables) {
this.dmp.dropTable(table, { testIfExists: this.options.checkIfTableExists });
}
}
}
async insertTableData(table) {
const dmpLocal = this.driver.createDumper();
dmpLocal.put('^select * ^from %f', table);
const autoinc = table.columns.find(x => x.autoIncrement);
if (autoinc && !this.options.skipAutoincrementColumn) {
this.dmp.allowIdentityInsert(table, true);
}
const readable = await this.driver.readQuery(this.pool, dmpLocal.s, table);
await this.processReadable(table, readable);
if (autoinc && !this.options.skipAutoincrementColumn) {
this.dmp.allowIdentityInsert(table, false);
}
}
processReadable(table, readable) {
const columnsFiltered = this.options.skipAutoincrementColumn
? table.columns.filter(x => !x.autoIncrement)
: table.columns;
const columnNames = columnsFiltered.map(x => x.columnName);
let isClosed = false;
let isHeaderRead = false;
return new Promise(resolve => {
readable.on('data', chunk => {
if (isClosed)
return;
if (!isHeaderRead) {
isHeaderRead = true;
return;
}
if (this.checkDumper()) {
isClosed = true;
resolve(undefined);
readable.destroy();
return;
}
const columnNamesCopy = this.options.omitNulls ? columnNames.filter(col => chunk[col] != null) : columnNames;
this.dmp.put('^insert ^into %f (%,i) ^values (%,v);&n', table, columnNamesCopy, columnNamesCopy.map(col => chunk[col]));
});
readable.on('end', () => {
resolve(undefined);
});
});
}
extract(objectTypeField) {
var _a, _b;
return ((_b = (_a = this.dbinfo[objectTypeField]) === null || _a === void 0 ? void 0 : _a.filter(x => this.objects.find(y => x.pureName == y.pureName && x.schemaName == y.schemaName && y.objectTypeField == objectTypeField))) !== null && _b !== void 0 ? _b : []);
}
enableConstraints(enabled) {
if (this.options.disableConstraints) {
if (this.driver.dialect.enableConstraintsPerTable) {
for (const table of this.tables) {
this.dmp.enableConstraints(table, enabled);
}
}
else {
this.dmp.enableConstraints(null, enabled);
}
}
}
}
exports.SqlGenerator = SqlGenerator;