UNPKG

sql-ddl-to-json-schema

Version:

Parse and convert SQL DDL statements to a JSON Schema.

353 lines (352 loc) 11.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AlterTable = void 0; const utils_1 = require("../../../../../shared/utils"); const table_options_1 = require("../table-options"); const column_1 = require("../column"); const index_1 = require("../index"); const primary_key_1 = require("../primary-key"); const unique_key_1 = require("../unique-key"); const fulltext_index_1 = require("../fulltext-index"); const spatial_index_1 = require("../spatial-index"); const foreign_key_1 = require("../foreign-key"); const column_options_1 = require("../column-options"); const datatype_1 = require("../datatype"); /** * Formatter for P_ALTER_TABLE rule's parsed JSON. */ class AlterTable { database; /** * Get table with given name. * * @param name Table name. */ getTable(name) { return this.database.getTable(name); } /** * Setter for database. * * @param database Database instance. */ setDatabase(database) { this.database = database; } /** * Alters one of the tables. * * @param json JSON format parsed from SQL. */ handleDef(json) { if (json.id === 'P_ALTER_TABLE') { const table = this.getTable(json.def.table); if (!table) { return; } /** * Runs methods in this class according to the * 'action' property of the ALTER TABLE spec. */ json.def.specs.forEach((spec) => { const changeSpec = spec.def.spec; const tableOptions = spec.def.tableOptions; if (changeSpec) { const def = changeSpec.def; const action = def.action; const fn = AlterTable[action]; if ((0, utils_1.isFunction)(fn)) { fn(def, table); } } else if (tableOptions) { if (!table.options) { table.options = new table_options_1.TableOptions(); } table.options.mergeWith(table_options_1.TableOptions.fromDef(tableOptions)); } }); return; } throw new TypeError(`Expected P_ALTER_TABLE rule to be handled but received ${json.id}`); } /** * Performs action in ALTER TABLE statement. * * @param json O_ALTER_TABLE_SPEC def object in JSON. * @param table Table to be altered. */ static addColumn(json, table) { const column = column_1.Column.fromObject(json); /** * Adding columns with REFERENCES should not create FK constraint. * https://github.com/duartealexf/sql-ddl-to-json-schema/issues/16 */ if (column.reference) { delete column.reference; } table.addColumn(column, json.position); } /** * Performs action in ALTER TABLE statement. * * @param json O_ALTER_TABLE_SPEC def object in JSON. * @param table Table to be altered. */ static addColumns(json, table) { json.columns.forEach((c) => { const column = column_1.Column.fromObject(c); /** * Adding columns with REFERENCES should not create FK constraint. * https://github.com/duartealexf/sql-ddl-to-json-schema/issues/16 */ if (column.reference) { delete column.reference; } table.addColumn(column); }); } /** * Performs action in ALTER TABLE statement. * * @param json O_ALTER_TABLE_SPEC def object in JSON. * @param table Table to be altered. */ static addIndex(json, table) { const index = index_1.Index.fromObject(json); table.pushIndex(index); } /** * Performs action in ALTER TABLE statement. * * @param json O_ALTER_TABLE_SPEC def object in JSON. * @param table Table to be altered. */ static addPrimaryKey(json, table) { const key = primary_key_1.PrimaryKey.fromObject(json); table.setPrimaryKey(key); } /** * Performs action in ALTER TABLE statement. * * @param json O_ALTER_TABLE_SPEC def object in JSON. * @param table Table to be altered. */ static addUniqueKey(json, table) { const key = unique_key_1.UniqueKey.fromObject(json); table.pushUniqueKey(key); } /** * Performs action in ALTER TABLE statement. * * @param json O_ALTER_TABLE_SPEC def object in JSON. * @param table Table to be altered. */ static addFulltextIndex(json, table) { const index = fulltext_index_1.FulltextIndex.fromObject(json); table.pushFulltextIndex(index); } /** * Performs action in ALTER TABLE statement. * * @param json O_ALTER_TABLE_SPEC def object in JSON. * @param table Table to be altered. */ static addSpatialIndex(json, table) { const index = spatial_index_1.SpatialIndex.fromObject(json); table.pushFulltextIndex(index); } /** * Performs action in ALTER TABLE statement. * * @param json O_ALTER_TABLE_SPEC def object in JSON. * @param table Table to be altered. */ static addForeignKey(json, table) { const key = foreign_key_1.ForeignKey.fromObject(json); table.pushForeignKey(key); } /** * Performs action in ALTER TABLE statement. * * @param json O_ALTER_TABLE_SPEC def object in JSON. * @param table Table to be altered. */ static setDefaultColumnValue(json, table) { const column = table.getColumn(json.column); if (!(0, utils_1.isDefined)(column) || !(0, utils_1.isDefined)(column.options)) { return; } column.options.default = json.value; } /** * Performs action in ALTER TABLE statement. * * @param json O_ALTER_TABLE_SPEC def object in JSON. * @param table Table to be altered. */ static dropDefaultColumnValue(json, table) { const column = table.getColumn(json.column); if (!(0, utils_1.isDefined)(column) || !(0, utils_1.isDefined)(column.options)) { return; } delete column.options.default; } /** * Performs action in ALTER TABLE statement. * * @param json O_ALTER_TABLE_SPEC def object in JSON. * @param table Table to be altered. */ static changeColumn(json, table) { const column = table.getColumn(json.column); if (!column) { return; } let position; if (json.position) { if (json.position.after) { if (!table.getColumn(json.position.after)) { /** * Referential 'after' column does not exist. */ return; } } position = json.position; } else { position = table.getColumnPosition(column); } const type = datatype_1.Datatype.fromDef(json.datatype); let options; /** * Alter table change column should not bring old * column options, so we completely overwrite it. * https://github.com/duartealexf/sql-ddl-to-json-schema/issues/10 */ if (json.columnDefinition) { options = column_options_1.ColumnOptions.fromArray(json.columnDefinition); } /** * Stop if anything went wrong parsing new column options. */ if (!(0, utils_1.isDefined)(options)) { return; } /** * Alter table does not overwrite primary key. * Statements like these in the DBMS are canceled. */ if (options.primary && table.primaryKey) { return; } /** * Table should have only one column with autoincrement, * except when column being modified is already autoincrement. * Statements like these in the DBMS are canceled. */ if (options.autoincrement && (table.columns ?? []).some((c) => c !== column && c.options?.autoincrement)) { return; } /** * If there is an unique option that would * create duplicate unique key, remove it. */ if (options.unique && table.uniqueKeys?.some((uniqueKey) => uniqueKey.columns.length === 1 && uniqueKey.columns[0].column === column.name)) { delete options.unique; } /** * Finally change the column. */ if (position && table.moveColumn(column, position)) { /** * If there is a new column name in statement, that is different * from current name, rename column and references to it. */ if (json.newName && json.newName !== column.name) { table.renameColumn(column, json.newName); } column.type = type; column.options = options; table.extractColumnKeys(column); } } /** * Performs action in ALTER TABLE statement. * * @param json O_ALTER_TABLE_SPEC def object in JSON. * @param table Table to be altered. */ static dropColumn(json, table) { const column = table.getColumn(json.column); if (!column) { return; } table.dropColumn(column); } /** * Performs action in ALTER TABLE statement. * * @param json O_ALTER_TABLE_SPEC def object in JSON. * @param table Table to be altered. */ static dropIndex(json, table) { if (json.index.toLowerCase() === 'primary') { AlterTable.dropPrimaryKey(json, table); return; } const index = table.getIndexByName(json.index); if (!index) { return; } table.dropIndexByInstance(index); } /** * Performs action in ALTER TABLE statement. * * @param json O_ALTER_TABLE_SPEC def object in JSON. * @param table Table to be altered. */ static dropPrimaryKey(json, table) { table.dropPrimaryKey(); } /** * Performs action in ALTER TABLE statement. * * @param json O_ALTER_TABLE_SPEC def object in JSON. * @param table Table to be altered. */ static dropForeignKey(json, table) { const foreignKey = table.getForeignKey(json.key); if (!foreignKey) { return; } table.dropForeignKey(foreignKey); } /** * Performs action in ALTER TABLE statement. * * @param json O_ALTER_TABLE_SPEC def object in JSON. * @param table Table to be altered. */ static renameIndex(json, table) { const index = table.getIndexByName(json.index); if (!index) { return; } index.name = json.newName; } /** * Performs action in ALTER TABLE statement. * * @param json O_ALTER_TABLE_SPEC def object in JSON. * @param table Table to be altered. */ static rename(json, table) { table.renameTo(json.newName); } } exports.AlterTable = AlterTable;