UNPKG

@dbml/core

Version:
361 lines (360 loc) 19.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _lodash = _interopRequireDefault(require("lodash")); var _utils = require("./utils"); var _config = require("../model_structure/config"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } var PostgresExporter = /*#__PURE__*/function () { function PostgresExporter() { _classCallCheck(this, PostgresExporter); } _createClass(PostgresExporter, null, [{ key: "exportEnums", value: function exportEnums(enumIds, model) { var enumArr = enumIds.map(function (enumId) { var _enum = model.enums[enumId]; var schema = model.schemas[_enum.schemaId]; var enumValueArr = _enum.valueIds.map(function (valueId) { var value = model.enumValues[valueId]; return " '".concat(value.name, "'"); }); var enumValueStr = enumValueArr.join(',\n'); var line = "CREATE TYPE ".concat((0, _utils.shouldPrintSchema)(schema, model) ? "\"".concat(schema.name, "\".") : '', "\"").concat(_enum.name, "\" AS ENUM (\n").concat(enumValueStr, "\n);\n"); return line; }); return enumArr; } }, { key: "getFieldLines", value: function getFieldLines(tableId, model) { var table = model.tables[tableId]; var lines = table.fieldIds.map(function (fieldId) { var field = model.fields[fieldId]; var line = ''; if (field.increment) { var typicalIntergers = new Set(['BIGINT', 'INT', 'INTEGER', 'SMALLINT']); var incrementIntergers = new Set(['SMALLSERIAL', 'SERIAL', 'BIGSERIAL']); var typeRaw = field.type.type_name.toUpperCase(); var type = ''; if (typicalIntergers.has(typeRaw)) type = "".concat(typeRaw, " GENERATED BY DEFAULT AS IDENTITY");else if (incrementIntergers.has(typeRaw)) type = typeRaw;else type = 'SERIAL'; line = "\"".concat(field.name, "\" ").concat(type); } else { var schemaName = ''; if (field.type.schemaName && field.type.schemaName !== _config.DEFAULT_SCHEMA_NAME) { schemaName = (0, _utils.hasWhiteSpace)(field.type.schemaName) ? "\"".concat(field.type.schemaName, "\".") : "".concat(field.type.schemaName, "."); } var typeName = (0, _utils.hasWhiteSpace)(field.type.type_name) ? "\"".concat(field.type.type_name, "\"") : field.type.type_name; line = "\"".concat(field.name, "\" ").concat(schemaName).concat(typeName); } if (field.unique) { line += ' UNIQUE'; } if (field.pk) { line += ' PRIMARY KEY'; } if (field.not_null) { line += ' NOT NULL'; } if (field.dbdefault) { if (field.dbdefault.type === 'expression') { line += " DEFAULT (".concat(field.dbdefault.value, ")"); } else if (field.dbdefault.type === 'string') { line += " DEFAULT '".concat(field.dbdefault.value, "'"); } else { line += " DEFAULT ".concat(field.dbdefault.value); } } return line; }); return lines; } }, { key: "getCompositePKs", value: function getCompositePKs(tableId, model) { var table = model.tables[tableId]; var compositePkIds = table.indexIds ? table.indexIds.filter(function (indexId) { return model.indexes[indexId].pk; }) : []; var lines = compositePkIds.map(function (keyId) { var key = model.indexes[keyId]; var line = 'PRIMARY KEY'; var columnArr = []; key.columnIds.forEach(function (columnId) { var column = model.indexColumns[columnId]; var columnStr = ''; if (column.type === 'expression') { columnStr = "(".concat(column.value, ")"); } else { columnStr = "\"".concat(column.value, "\""); } columnArr.push(columnStr); }); line += " (".concat(columnArr.join(', '), ")"); return line; }); return lines; } }, { key: "getTableContentArr", value: function getTableContentArr(tableIds, model) { var tableContentArr = tableIds.map(function (tableId) { var fieldContents = PostgresExporter.getFieldLines(tableId, model); var compositePKs = PostgresExporter.getCompositePKs(tableId, model); return { tableId: tableId, fieldContents: fieldContents, compositePKs: compositePKs }; }); return tableContentArr; } }, { key: "exportTables", value: function exportTables(tableIds, model) { var tableContentArr = PostgresExporter.getTableContentArr(tableIds, model); var tableStrs = tableContentArr.map(function (tableContent) { var content = [].concat(_toConsumableArray(tableContent.fieldContents), _toConsumableArray(tableContent.compositePKs)); var table = model.tables[tableContent.tableId]; var schema = model.schemas[table.schemaId]; var tableStr = "CREATE TABLE ".concat((0, _utils.shouldPrintSchema)(schema, model) ? "\"".concat(schema.name, "\".") : '', "\"").concat(table.name, "\" (\n").concat(content.map(function (line) { return " ".concat(line); }).join(',\n'), "\n);\n"); return tableStr; }); return tableStrs; } }, { key: "buildFieldName", value: function buildFieldName(fieldIds, model) { var fieldNames = fieldIds.map(function (fieldId) { return "\"".concat(model.fields[fieldId].name, "\""); }).join(', '); return "(".concat(fieldNames, ")"); } }, { key: "buildTableManyToMany", value: function buildTableManyToMany(firstTableFieldsMap, secondTableFieldsMap, tableName, refEndpointSchema, model) { var line = "CREATE TABLE ".concat((0, _utils.shouldPrintSchema)(refEndpointSchema, model) ? "\"".concat(refEndpointSchema.name, "\".") : '', "\"").concat(tableName, "\" (\n"); var key1s = _toConsumableArray(firstTableFieldsMap.keys()).join('", "'); var key2s = _toConsumableArray(secondTableFieldsMap.keys()).join('", "'); firstTableFieldsMap.forEach(function (fieldType, fieldName) { line += " \"".concat(fieldName, "\" ").concat(fieldType, ",\n"); }); secondTableFieldsMap.forEach(function (fieldType, fieldName) { line += " \"".concat(fieldName, "\" ").concat(fieldType, ",\n"); }); line += " PRIMARY KEY (\"".concat(key1s, "\", \"").concat(key2s, "\")\n"); line += ');\n\n'; return line; } }, { key: "buildForeignKeyManyToMany", value: function buildForeignKeyManyToMany(fieldsMap, foreignEndpointFields, refEndpointTableName, foreignEndpointTableName, refEndpointSchema, foreignEndpointSchema, model) { var refEndpointFields = _toConsumableArray(fieldsMap.keys()).join('", "'); var line = "ALTER TABLE ".concat((0, _utils.shouldPrintSchema)(refEndpointSchema, model) ? "\"".concat(refEndpointSchema.name, "\".") : '', "\"").concat(refEndpointTableName, "\" ADD FOREIGN KEY (\"").concat(refEndpointFields, "\") REFERENCES ").concat((0, _utils.shouldPrintSchema)(foreignEndpointSchema, model) ? "\"".concat(foreignEndpointSchema.name, "\".") : '', "\"").concat(foreignEndpointTableName, "\" ").concat(foreignEndpointFields, ";\n\n"); return line; } }, { key: "exportRefs", value: function exportRefs(refIds, model, usedTableNames) { var _this = this; var strArr = refIds.map(function (refId) { var line = ''; var ref = model.refs[refId]; var refOneIndex = ref.endpointIds.findIndex(function (endpointId) { return model.endpoints[endpointId].relation === '1'; }); var refEndpointIndex = refOneIndex === -1 ? 0 : refOneIndex; var foreignEndpointId = ref.endpointIds[1 - refEndpointIndex]; var refEndpointId = ref.endpointIds[refEndpointIndex]; var foreignEndpoint = model.endpoints[foreignEndpointId]; var refEndpoint = model.endpoints[refEndpointId]; var refEndpointField = model.fields[refEndpoint.fieldIds[0]]; var refEndpointTable = model.tables[refEndpointField.tableId]; var refEndpointSchema = model.schemas[refEndpointTable.schemaId]; var refEndpointFieldName = _this.buildFieldName(refEndpoint.fieldIds, model, 'postgres'); var foreignEndpointField = model.fields[foreignEndpoint.fieldIds[0]]; var foreignEndpointTable = model.tables[foreignEndpointField.tableId]; var foreignEndpointSchema = model.schemas[foreignEndpointTable.schemaId]; var foreignEndpointFieldName = _this.buildFieldName(foreignEndpoint.fieldIds, model, 'postgres'); if (refOneIndex === -1) { // many to many relationship var firstTableFieldsMap = (0, _utils.buildJunctionFields1)(refEndpoint.fieldIds, model); var secondTableFieldsMap = (0, _utils.buildJunctionFields2)(foreignEndpoint.fieldIds, model, firstTableFieldsMap); var newTableName = (0, _utils.buildNewTableName)(refEndpointTable.name, foreignEndpointTable.name, usedTableNames); line += _this.buildTableManyToMany(firstTableFieldsMap, secondTableFieldsMap, newTableName, refEndpointSchema, model); line += _this.buildForeignKeyManyToMany(firstTableFieldsMap, refEndpointFieldName, newTableName, refEndpointTable.name, refEndpointSchema, refEndpointSchema, model); line += _this.buildForeignKeyManyToMany(secondTableFieldsMap, foreignEndpointFieldName, newTableName, foreignEndpointTable.name, refEndpointSchema, foreignEndpointSchema, model); } else { line = "ALTER TABLE ".concat((0, _utils.shouldPrintSchema)(foreignEndpointSchema, model) ? "\"".concat(foreignEndpointSchema.name, "\".") : '', "\"").concat(foreignEndpointTable.name, "\" ADD "); if (ref.name) { line += "CONSTRAINT \"".concat(ref.name, "\" "); } line += "FOREIGN KEY ".concat(foreignEndpointFieldName, " REFERENCES ").concat((0, _utils.shouldPrintSchema)(refEndpointSchema, model) ? "\"".concat(refEndpointSchema.name, "\".") : '', "\"").concat(refEndpointTable.name, "\" ").concat(refEndpointFieldName); if (ref.onDelete) { line += " ON DELETE ".concat(ref.onDelete.toUpperCase()); } if (ref.onUpdate) { line += " ON UPDATE ".concat(ref.onUpdate.toUpperCase()); } line += ';\n'; } return line; }); return strArr; } }, { key: "exportIndexes", value: function exportIndexes(indexIds, model) { // exclude composite pk index var indexArr = indexIds.filter(function (indexId) { return !model.indexes[indexId].pk; }).map(function (indexId) { var index = model.indexes[indexId]; var table = model.tables[index.tableId]; var schema = model.schemas[table.schemaId]; var line = 'CREATE'; if (index.unique) { line += ' UNIQUE'; } var indexName = index.name ? "\"".concat(index.name, "\"") : ''; line += ' INDEX'; if (indexName) { line += " ".concat(indexName); } line += " ON ".concat((0, _utils.shouldPrintSchema)(schema, model) ? "\"".concat(schema.name, "\".") : '', "\"").concat(table.name, "\""); if (index.type) { line += " USING ".concat(index.type.toUpperCase()); } var columnArr = []; index.columnIds.forEach(function (columnId) { var column = model.indexColumns[columnId]; var columnStr = ''; if (column.type === 'expression') { columnStr = "(".concat(column.value, ")"); } else { columnStr = "\"".concat(column.value, "\""); } columnArr.push(columnStr); }); line += " (".concat(columnArr.join(', '), ")"); line += ';\n'; return line; }); return indexArr; } }, { key: "exportComments", value: function exportComments(comments, model) { var commentArr = comments.map(function (comment) { var line = 'COMMENT ON'; var table = model.tables[comment.tableId]; var schema = model.schemas[table.schemaId]; switch (comment.type) { case 'table': { line += " TABLE ".concat((0, _utils.shouldPrintSchema)(schema, model) ? "\"".concat(schema.name, "\".") : '', "\"").concat(table.name, "\" IS '").concat(table.note.replace(/'/g, "''"), "'"); break; } case 'column': { var field = model.fields[comment.fieldId]; line += " COLUMN ".concat((0, _utils.shouldPrintSchema)(schema, model) ? "\"".concat(schema.name, "\".") : '', "\"").concat(table.name, "\".\"").concat(field.name, "\" IS '").concat(field.note.replace(/'/g, "''"), "'"); break; } default: break; } line += ';\n'; return line; }); return commentArr; } }, { key: "export", value: function _export(model) { var database = model.database['1']; var usedTableNames = new Set(Object.values(model.tables).map(function (table) { return table.name; })); var statements = database.schemaIds.reduce(function (prevStatements, schemaId) { var schema = model.schemas[schemaId]; var tableIds = schema.tableIds, enumIds = schema.enumIds, refIds = schema.refIds; if ((0, _utils.shouldPrintSchema)(schema, model)) { prevStatements.schemas.push("CREATE SCHEMA \"".concat(schema.name, "\";\n")); } if (!_lodash["default"].isEmpty(enumIds)) { var _prevStatements$enums; (_prevStatements$enums = prevStatements.enums).push.apply(_prevStatements$enums, _toConsumableArray(PostgresExporter.exportEnums(enumIds, model))); } if (!_lodash["default"].isEmpty(tableIds)) { var _prevStatements$table; (_prevStatements$table = prevStatements.tables).push.apply(_prevStatements$table, _toConsumableArray(PostgresExporter.exportTables(tableIds, model))); } var indexIds = _lodash["default"].flatten(tableIds.map(function (tableId) { return model.tables[tableId].indexIds; })); if (!_lodash["default"].isEmpty(indexIds)) { var _prevStatements$index; (_prevStatements$index = prevStatements.indexes).push.apply(_prevStatements$index, _toConsumableArray(PostgresExporter.exportIndexes(indexIds, model))); } var commentNodes = _lodash["default"].flatten(tableIds.map(function (tableId) { var _model$tables$tableId = model.tables[tableId], fieldIds = _model$tables$tableId.fieldIds, note = _model$tables$tableId.note; var fieldObjects = fieldIds.filter(function (fieldId) { return model.fields[fieldId].note; }).map(function (fieldId) { return { type: 'column', fieldId: fieldId, tableId: tableId }; }); return note ? [{ type: 'table', tableId: tableId }].concat(fieldObjects) : fieldObjects; })); if (!_lodash["default"].isEmpty(commentNodes)) { var _prevStatements$comme; (_prevStatements$comme = prevStatements.comments).push.apply(_prevStatements$comme, _toConsumableArray(PostgresExporter.exportComments(commentNodes, model))); } if (!_lodash["default"].isEmpty(refIds)) { var _prevStatements$refs; (_prevStatements$refs = prevStatements.refs).push.apply(_prevStatements$refs, _toConsumableArray(PostgresExporter.exportRefs(refIds, model, usedTableNames))); } return prevStatements; }, { schemas: [], enums: [], tables: [], indexes: [], comments: [], refs: [] }); var res = _lodash["default"].concat(statements.schemas, statements.enums, statements.tables, statements.indexes, statements.comments, statements.refs).join('\n'); return res; } }]); return PostgresExporter; }(); var _default = PostgresExporter; exports["default"] = _default;