all files / handlers/ MysqlHandler.js

100% Statements 74/74
100% Branches 10/10
100% Functions 33/33
100% Lines 70/70
3 statements, 3 branches Ignored     
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161                                                                                      10×                                 19× 19× 19×   19×                                                              
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var mysql = require("mysql");
var utils_1 = require("../commons/utils/utils");
var BaseHandler_1 = require("./BaseHandler");
/**
 * MySql Handler.
 *
 * @export
 * @class MysqlHandler
 * @extends {BaseHandler}
 */
var MysqlHandler = (function (_super) {
    tslib_1.__extends(MysqlHandler, _super);
    /**
     * Constructor for the MySqlHandler.
     *
     * @param {mysq.IConnectionConfig} options Connection parameters.
     */
    function MysqlHandler(options) {
        var _this = _super.call(this, 'mysql') || this;
        _this.options = options;
        _this.connection = mysql.createConnection({
            host: _this.options.host,
            port: _this.options.port,
            user: _this.options.user,
            password: _this.options.password,
            database: 'information_schema',
        });
        return _this;
    }
    /**
     * Connect to MySql based on the connection data.
     */
    MysqlHandler.prototype.connect = function () {
        this.connection.connect();
    };
    /**
     * Reads the database schema, processes it and returns a normalized version of it.
     *
     * @returns {Promise<Schema>} database schema
     */
    MysqlHandler.prototype.readSchema = function () {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var _this = this;
            return tslib_1.__generator(this, function (_a) {
                return [2 /*return*/, new Promise(function (resolve, reject) {
                        _this.getTables().then(function (tablesNames) {
                            var tables = tablesNames.map(function (tableName) { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) {
                                return [2 /*return*/, this.getTableSchema(tableName)];
                            }); }); });
                            Promise.all(tables).then(function (schema) {
                                resolve(_this.normalizeRelations(schema));
                            }).catch(reject);
                        }).catch(reject);
                    })];
            });
        });
    };
    /**
     * Reads the information schema and returns an array of tables.
     *
     * @returns {Promise<string[]>} array of table names.
     */
    MysqlHandler.prototype.getTables = function () {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var _this = this;
            return tslib_1.__generator(this, function (_a) {
                return [2 /*return*/, new Promise(function (resolve, reject) {
                        _this.connection.query("SELECT TABLE_NAME FROM TABLES WHERE TABLE_SCHEMA = '" + _this.options.database + "';", function (err, results) {
                            /* istanbul ignore next */
                            Iif (err) {
                                return reject(err);
                            }
                            var tables = results.map(function (result) { return result.TABLE_NAME; });
                            return resolve(tables);
                        });
                    })];
            });
        });
    };
    /**
     * Reads the schema for a given table.
     *
     * @param {string} tableName table name
     * @returns {Promise<Table>} table schema
     */
    MysqlHandler.prototype.getTableSchema = function (tableName) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var _this = this;
            return tslib_1.__generator(this, function (_a) {
                return [2 /*return*/, new Promise(function (resolve, reject) {
                        var table = {
                            name: tableName,
                            columns: [],
                        };
                        _this.connection.query("SELECT\n          COLUMN_NAME,\n          IS_NULLABLE,\n          DATA_TYPE,\n          CHARACTER_MAXIMUM_LENGTH,\n          COLUMN_KEY,\n          COLUMN_TYPE\n        FROM COLUMNS WHERE TABLE_SCHEMA = '" + _this.options.database + "' AND TABLE_NAME = '" + tableName + "';", function (err, columns) {
                            /* istanbul ignore next */
                            Iif (err) {
                                return reject(err);
                            }
                            _this.getRelationsForTable(tableName).then(function (relations) {
                                columns.forEach(function (result) {
                                    var column = _this.normalizeColumnSchema(result);
                                    var relation = relations.find(function (rel) { return rel.name === column.name; });
                                    if (relation) {
                                        column.foreignKey = true;
                                        column.dataType.references = relation;
                                        column.dataType.type = utils_1.default.toTitleCase(relation.table);
                                        column.name = utils_1.default.singular(relation.table);
                                    }
                                    table.columns.push(column);
                                });
                                return resolve(table);
                            }).catch(reject);
                        });
                    })];
            });
        });
    };
    /**
     * Reads all the relations for a given table.
     *
     * @param {string} table table name
     * @return {Promise<TableReference[]>} foreign key relations
     */
    MysqlHandler.prototype.getRelationsForTable = function (table) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var _this = this;
            return tslib_1.__generator(this, function (_a) {
                return [2 /*return*/, new Promise(function (resolve, reject) {
                        _this.connection.query("SELECT\n          COLUMN_NAME,\n          rc.REFERENCED_TABLE_NAME,\n          REFERENCED_COLUMN_NAME\n        FROM REFERENTIAL_CONSTRAINTS rc JOIN\n          KEY_COLUMN_USAGE cu ON cu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME\n        WHERE rc.CONSTRAINT_SCHEMA = '" + _this.options.database + "' AND rc.TABLE_NAME = '" + table + "'", function (err, relations) {
                            /* istanbul ignore next */
                            Iif (err) {
                                return reject(err);
                            }
                            var references = relations.map(function (relation) {
                                var reference = {
                                    name: relation.COLUMN_NAME,
                                    table: relation.REFERENCED_TABLE_NAME,
                                    column: relation.REFERENCED_COLUMN_NAME,
                                };
                                return reference;
                            });
                            resolve(references);
                        });
                    })];
            });
        });
    };
    /**
     * Closes the MySql connection.
     */
    MysqlHandler.prototype.close = function () {
        this.connection.end();
    };
    return MysqlHandler;
}(BaseHandler_1.default));
exports.default = MysqlHandler;