UNPKG

@dbml/core

Version:
1,317 lines (1,261 loc) 56.5 kB
"use strict"; 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); } Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _lodash = require("lodash"); var _TSqlParserVisitor2 = _interopRequireDefault(require("../../parsers/mssql/TSqlParserVisitor")); var _constants = require("../constants"); var _helpers = require("../helpers"); var _AST = require("../AST"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 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); } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } 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 _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 _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure 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 _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 _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i["return"] && (_r = _i["return"](), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } /* eslint-disable class-methods-use-this */ var ADD_DESCRIPTION_FUNCTION_NAME = 'sp_addextendedproperty'; var CHECK_CONSTRAINT_CONDITION_TYPE = { RAW: 'raw', ENUM: 'enum' }; var getSchemaAndTableName = function getSchemaAndTableName(names) { var tableName = (0, _lodash.last)(names); var schemaName = names.length > 1 ? (0, _lodash.nth)(names, -2) : undefined; return { schemaName: schemaName, tableName: tableName }; }; var getStringFromRawString = function getStringFromRawString(rawString) { if (rawString.startsWith("N'")) { return rawString; } return rawString.slice(1, rawString.length - 1); }; /** * @param {any[]} columnDefTableConstraints * @returns {{ * fieldsData: any[], * indexes: any[], * tableRefs: any[], * columnDefaults: any[], * checkConstraints: any[], * }} */ var splitColumnDefTableConstraints = function splitColumnDefTableConstraints(columnDefTableConstraints) { var _columnDefTableConstr = columnDefTableConstraints.reduce(function (acc, columnDefTableConstraint) { switch (columnDefTableConstraint.kind) { case _constants.TABLE_CONSTRAINT_KIND.FIELD: acc[0].push(columnDefTableConstraint.value); break; case _constants.TABLE_CONSTRAINT_KIND.INDEX: case _constants.TABLE_CONSTRAINT_KIND.PK: case _constants.TABLE_CONSTRAINT_KIND.UNIQUE: acc[1].push(columnDefTableConstraint.value); break; case _constants.TABLE_CONSTRAINT_KIND.FK: acc[2].push(columnDefTableConstraint.value); break; case _constants.TABLE_CONSTRAINT_KIND.DEFAULT: acc[3].push(columnDefTableConstraint.value); break; case _constants.TABLE_CONSTRAINT_KIND.CHECK: acc[4].push(columnDefTableConstraint.value); break; default: break; } return acc; }, [[], [], [], [], []]), _columnDefTableConstr2 = _slicedToArray(_columnDefTableConstr, 5), fieldsData = _columnDefTableConstr2[0], indexes = _columnDefTableConstr2[1], tableRefs = _columnDefTableConstr2[2], columnDefaults = _columnDefTableConstr2[3], checkConstraints = _columnDefTableConstr2[4]; return { fieldsData: fieldsData, indexes: indexes, tableRefs: tableRefs, columnDefaults: columnDefaults, checkConstraints: checkConstraints }; }; var parseFieldsAndInlineRefsFromFieldsData = function parseFieldsAndInlineRefsFromFieldsData(fieldsData, tableName, schemaName) { var _fieldsData$reduce = fieldsData.reduce(function (acc, fieldData) { var _acc$; var inlineRefs = fieldData.inline_refs.map(function (inlineRef) { inlineRef.endpoints[0].tableName = tableName; inlineRef.endpoints[0].schemaName = schemaName; inlineRef.endpoints[0].fieldNames = [fieldData.field.name]; return inlineRef; }); acc[0].push(inlineRefs); acc[1].push(fieldData.field); (_acc$ = acc[2]).push.apply(_acc$, _toConsumableArray(fieldData.checkConstraints)); return acc; }, [[], [], []]), _fieldsData$reduce2 = _slicedToArray(_fieldsData$reduce, 3), resInlineRefs = _fieldsData$reduce2[0], fields = _fieldsData$reduce2[1], checkConstraints = _fieldsData$reduce2[2]; return { inlineRefs: resInlineRefs, fields: fields, checkConstraints: checkConstraints }; }; var MssqlASTGen = /*#__PURE__*/function (_TSqlParserVisitor) { _inherits(MssqlASTGen, _TSqlParserVisitor); var _super = _createSuper(MssqlASTGen); function MssqlASTGen() { var _this; _classCallCheck(this, MssqlASTGen); _this = _super.call(this); _this.data = { schemas: [], tables: [], refs: [], enums: [], tableGroups: [], aliases: [], project: {}, records: [] }; return _this; } // tsql_file // : batch* EOF // | execute_body_batch go_statement* EOF // ; _createClass(MssqlASTGen, [{ key: "visitTsql_file", value: function visitTsql_file(ctx) { var _this2 = this; ctx.batch().forEach(function (batch) { return batch.accept(_this2); }); return this.data; } // batch // : go_statement // | execute_body_batch? (go_statement | sql_clauses+) go_statement* // | batch_level_statement go_statement* // ; }, { key: "visitBatch", value: function visitBatch(ctx) { var _this3 = this; if (ctx.sql_clauses()) { ctx.sql_clauses().forEach(function (sqlClause) { return sqlClause.accept(_this3); }); } } // sql_clauses // : dml_clause SEMI? // | cfl_statement SEMI? // | another_statement SEMI? // | ddl_clause SEMI? // | dbcc_clause SEMI? // | backup_statement SEMI? // | SEMI // ; }, { key: "visitSql_clauses", value: function visitSql_clauses(ctx) { if (ctx.ddl_clause()) { ctx.ddl_clause().accept(this); return; } if (ctx.dml_clause()) { ctx.dml_clause().accept(this); return; } if (ctx.another_statement()) { ctx.another_statement().accept(this); } } // dml_clause // : merge_statement // | delete_statement // | insert_statement // | select_statement_standalone // | update_statement // ; }, { key: "visitDml_clause", value: function visitDml_clause(ctx) { if (ctx.insert_statement()) { ctx.insert_statement().accept(this); } } // insert_statement // : with_expression? INSERT (TOP '(' expression ')' PERCENT?)? INTO? ( // ddl_object // | rowset_function_limited // ) with_table_hints? ('(' insert_column_name_list ')')? output_clause? insert_statement_value for_clause? option_clause? ';'? // ; }, { key: "visitInsert_statement", value: function visitInsert_statement(ctx) { // [ 'users' ] // [ 'test', 'users' ] // [ 'db', 'test', 'users' ] // [ 'server', 'db', 'test', 'users' ] // The last: table name // The second-last: schema name var names = ctx.ddl_object().accept(this); var tableName = (0, _lodash.last)(names); var schemaName = names.length > 1 ? (0, _lodash.nth)(names, -2) : undefined; var columns = ctx.insert_column_name_list() ? ctx.insert_column_name_list().accept(this) : []; var values = ctx.insert_statement_value().accept(this); var record = new _AST.TableRecord({ tableName: tableName, schemaName: schemaName, columns: columns, values: values }); this.data.records.push(record); } // ddl_object // : full_table_name // | LOCAL_ID // ; }, { key: "visitDdl_object", value: function visitDdl_object(ctx) { return ctx.full_table_name().accept(this); } // full_table_name // : ( // linkedServer = id_ '.' '.' schema = id_ '.' // | server = id_ '.' database = id_ '.' schema = id_ '.' // | database = id_ '.' schema = id_? '.' // | schema = id_ '.' // )? table = id_ // ; }, { key: "visitFull_table_name", value: function visitFull_table_name(ctx) { var _this4 = this; return ctx.id_().map(function (id) { return id.accept(_this4); }); } // id_ // : ID // | TEMP_ID // | DOUBLE_QUOTE_ID // | DOUBLE_QUOTE_BLANK // | SQUARE_BRACKET_ID // | keyword // | RAW // ; }, { key: "visitId_", value: function visitId_(ctx) { if (ctx.DOUBLE_QUOTE_ID() || ctx.SQUARE_BRACKET_ID()) return (0, _helpers.getOriginalText)(ctx).slice(1, -1); return (0, _helpers.getOriginalText)(ctx); } // insert_column_name_list // : col += insert_column_id (',' col += insert_column_id)* // ; }, { key: "visitInsert_column_name_list", value: function visitInsert_column_name_list(ctx) { var _this5 = this; var columns = ctx.insert_column_id().map(function (column) { return column.accept(_this5); }); return (0, _lodash.flattenDepth)(columns, 1); } // insert_column_id // : (ignore += id_? '.')* id_ // ; // insert_statement_value // : table_value_constructor // | derived_table // | execute_statement // | DEFAULT VALUES // ; }, { key: "visitInsert_statement_value", value: function visitInsert_statement_value(ctx) { if (!ctx.table_value_constructor()) return []; var rawValues = ctx.table_value_constructor().accept(this); return rawValues; } // table_value_constructor // : VALUES '(' exps += expression_list_ ')' (',' '(' exps += expression_list_ ')')* // ; }, { key: "visitTable_value_constructor", value: function visitTable_value_constructor(ctx) { var _this6 = this; return ctx.expression_list_().map(function (expression) { return expression.accept(_this6); }); } // expression_list_ // : exp += expression (',' exp += expression)* // ; }, { key: "visitExpression_list_", value: function visitExpression_list_(ctx) { var _this7 = this; return ctx.expression().map(function (expression) { return expression.accept(_this7); }); } // expression // : primitive_expression // | function_call // | expression '.' (value_call | query_call | exist_call | modify_call) // | expression '.' hierarchyid_call // | expression COLLATE id_ // | case_expression // | full_column_name // | bracket_expression // | unary_operator_expression // | expression op = ('*' | '/' | '%') expression // | expression op = ('+' | '-' | '&' | '^' | '|' | '||') expression // | expression time_zone // | over_clause // | DOLLAR_ACTION // ; }, { key: "visitExpression", value: function visitExpression(ctx) { if (ctx.primitive_expression()) { return ctx.primitive_expression().accept(this); } if (ctx.function_call()) { return ctx.function_call().accept(this); } if (ctx.unary_operator_expression()) { return ctx.unary_operator_expression().accept(this); } if (ctx.bracket_expression()) { return ctx.bracket_expression().accept(this); } if (ctx.full_column_name()) { return ctx.full_column_name().accept(this); } // Default case for any other expression type return { value: (0, _helpers.getOriginalText)(ctx), type: _constants.DATA_TYPE.EXPRESSION }; } // bracket_expression // : '(' expression ')' // | '(' subquery ')' // ; }, { key: "visitBracket_expression", value: function visitBracket_expression(ctx) { return ctx.expression() ? ctx.expression().accept(this) : null; } // full_column_name // : ((DELETED | INSERTED | full_table_name) '.')? ( // column_name = id_ // | ('$' (IDENTITY | ROWGUID)) // ) // ; }, { key: "visitFull_column_name", value: function visitFull_column_name(ctx) { var columnName = ctx.id_().accept(this); var fullTableName = ctx.full_table_name() ? ctx.full_table_name().accept(this) : []; return { value: [].concat(_toConsumableArray(fullTableName), [columnName]), type: _constants.DATA_TYPE.EXPRESSION }; } // primitive_constant // : STRING // string, datetime or uniqueidentifier // | BINARY // | (DECIMAL | REAL | FLOAT) // float or decimal // | dollar = '$' ('-' | '+')? (DECIMAL | FLOAT) // money // | parameter // ; }, { key: "visitPrimitive_constant", value: function visitPrimitive_constant(ctx) { if (ctx.STRING() || ctx.BINARY()) { var value = getStringFromRawString(ctx.getText()); return { value: value, type: value.startsWith("N'") ? _constants.DATA_TYPE.EXPRESSION : _constants.DATA_TYPE.STRING }; } if (ctx.DOLLAR()) { var dollar = (0, _lodash.first)(ctx.children).getText(); var sign = ctx.children.length > 2 ? (0, _lodash.nth)(ctx.children, -2) : ''; var _value = (0, _lodash.last)(ctx.children).getText(); return { value: "".concat(dollar).concat(sign).concat(_value), type: _constants.DATA_TYPE.STRING }; } if (ctx.REAL() || ctx.DECIMAL() || ctx.FLOAT()) { return { value: ctx.getText(), type: _constants.DATA_TYPE.NUMBER }; } return { value: (0, _helpers.getOriginalText)(ctx), type: _constants.DATA_TYPE.EXPRESSION }; } // function_call // : ranking_windowed_function # RANKING_WINDOWED_FUNC // | aggregate_windowed_function # AGGREGATE_WINDOWED_FUNC // | analytic_windowed_function # ANALYTIC_WINDOWED_FUNC // | built_in_functions # BUILT_IN_FUNC // | scalar_function_name '(' expression_list_? ')' # SCALAR_FUNCTION // | freetext_function # FREE_TEXT // | partition_function # PARTITION_FUNC // | hierarchyid_static_method # HIERARCHYID_METHOD // ; // See packages/dbml-core/src/parse/ANTLR/parsers/mssql/TSqlParser.g4 at line 4338 }, { key: "visitBUILT_IN_FUNC", value: function visitBUILT_IN_FUNC(ctx) { return { value: (0, _helpers.getOriginalText)(ctx), type: _constants.DATA_TYPE.EXPRESSION }; } }, { key: "visitSCALAR_FUNCTION", value: function visitSCALAR_FUNCTION(ctx) { return { value: (0, _helpers.getOriginalText)(ctx), type: _constants.DATA_TYPE.EXPRESSION }; } // unary_operator_expression // : '~' expression // | op = ('+' | '-') expression // ; }, { key: "visitUnary_operator_expression", value: function visitUnary_operator_expression(ctx) { var operator = ctx.children[0].getText(); var expression = ctx.expression().accept(this); return { value: "".concat(operator).concat(expression.value), type: expression.type }; } // data_type // : scaled = (VARCHAR | NVARCHAR | BINARY_KEYWORD | VARBINARY_KEYWORD | SQUARE_BRACKET_ID) '(' MAX ')' // | ext_type = id_ '(' scale = DECIMAL ',' prec = DECIMAL ')' // | ext_type = id_ '(' scale = DECIMAL ')' // | ext_type = id_ IDENTITY ('(' seed = DECIMAL ',' inc = DECIMAL ')')? // | double_prec = DOUBLE PRECISION? // | unscaled_type = id_ // ; }, { key: "visitData_type", value: function visitData_type(ctx) { if (ctx.MAX()) { var type = ''; if (ctx.SQUARE_BRACKET_ID()) { type = ctx.SQUARE_BRACKET_ID().getText().slice(1, -1); } else { var typeNode = ctx.VARCHAR() || ctx.NVARCHAR() || ctx.BINARY_KEYWORD() || ctx.VARBINARY_KEYWORD() || ctx.SQUARE_BRACKET_ID(); type = typeNode.getText(); } return "".concat(type, "(MAX)"); } if (ctx.DOUBLE()) { var _double = ctx.DOUBLE().getText(); var precision = ctx.PRECISION() ? " ".concat(ctx.PRECISION().getText()) : ''; return "".concat(_double).concat(precision); } var id = ctx.id_().accept(this); if (ctx.IDENTITY()) { if (ctx.DECIMAL().length) { var seedAndInc = ctx.DECIMAL().map(function (decimal) { return decimal.getText(); }); return "".concat(id, " IDENTITY(").concat(seedAndInc, ")"); } return "".concat(id, " IDENTITY"); } if (ctx.DECIMAL().length) { var scaleAndPrec = ctx.DECIMAL().map(function (decimal) { return decimal.getText(); }); return "".concat(id, "(").concat(scaleAndPrec.join(','), ")"); } return id; } }, { key: "visitPrimitive_expression", value: function visitPrimitive_expression(ctx) { if (ctx.NULL_()) { return { value: ctx.getText(), type: _constants.DATA_TYPE.BOOLEAN }; } if (ctx.primitive_constant()) { return ctx.primitive_constant().accept(this); } return { value: ctx.getText(), type: _constants.DATA_TYPE.EXPRESSION }; } // ddl_clause // | alter_table // | create_index // | create_table // ; // more details at: packages/dbml-core/src/parse/ANTLR/parsers/mssql/TSqlParser.g4 line 73 }, { key: "visitDdl_clause", value: function visitDdl_clause(ctx) { if (ctx.create_table()) { ctx.create_table().accept(this); return; } if (ctx.alter_table()) { ctx.alter_table().accept(this); return; } if (ctx.create_index()) { ctx.create_index().accept(this); } } // create_table // : CREATE TABLE table_name '(' column_def_table_constraints (','? table_indices)* ','? ')' ( // LOCK simple_id // )? table_options* (ON id_ | DEFAULT | on_partition_or_filegroup)? (TEXTIMAGE_ON id_ | DEFAULT)? ';'? // ; }, { key: "visitCreate_table", value: function visitCreate_table(ctx) { var _this8 = this, _this$data$refs, _this$data$refs2; var _getSchemaAndTableNam = getSchemaAndTableName(ctx.table_name().accept(this)), schemaName = _getSchemaAndTableNam.schemaName, tableName = _getSchemaAndTableNam.tableName; var columnDefTableConstraints = ctx.column_def_table_constraints().accept(this); var tableIndices = ctx.table_indices().map(function (tableIndex) { return tableIndex.accept(_this8); }); var _splitColumnDefTableC = splitColumnDefTableConstraints(columnDefTableConstraints), fieldsData = _splitColumnDefTableC.fieldsData, indexes = _splitColumnDefTableC.indexes, tableRefs = _splitColumnDefTableC.tableRefs, tableCheckConstraints = _splitColumnDefTableC.checkConstraints; var _parseFieldsAndInline = parseFieldsAndInlineRefsFromFieldsData(fieldsData, tableName, schemaName), inlineRefs = _parseFieldsAndInline.inlineRefs, fields = _parseFieldsAndInline.fields, columnCheckConstraints = _parseFieldsAndInline.checkConstraints; (_this$data$refs = this.data.refs).push.apply(_this$data$refs, _toConsumableArray((0, _lodash.flatten)(inlineRefs))); (_this$data$refs2 = this.data.refs).push.apply(_this$data$refs2, _toConsumableArray(tableRefs.map(function (tableRef) { tableRef.endpoints[0].tableName = tableName; tableRef.endpoints[0].schemaName = schemaName; return tableRef; }))); // these check constraints represent enums var checkConstraints = columnCheckConstraints.concat(tableCheckConstraints); checkConstraints.forEach(function (checkConstraint) { var field = fields.find(function (fieldItem) { return fieldItem.name === checkConstraint.column; }); if (!field) return; var enumObject = new _AST.Enum({ name: "".concat(tableName, "_").concat(field.name, "_enum"), values: checkConstraint.columnValues.map(function (value) { return { name: value }; }), schemaName: schemaName }); _this8.data.enums.push(enumObject); // TODO: handle multiple enums for the same field field.type.type_name = enumObject.name; field.type.schemaName = enumObject.schemaName; }); var table = new _AST.Table({ name: tableName, schemaName: schemaName, fields: fields, indexes: tableIndices.concat(indexes) }); this.data.tables.push(table); } // table_name // : (database = id_ '.' schema = id_? '.' | schema = id_ '.')? ( // table = id_ // | blocking_hierarchy = BLOCKING_HIERARCHY // ) // ; }, { key: "visitTable_name", value: function visitTable_name(ctx) { var _this9 = this; return ctx.id_().map(function (id) { return id.accept(_this9); }); } // column_def_table_constraints // : column_def_table_constraint (','? column_def_table_constraint)* // ; }, { key: "visitColumn_def_table_constraints", value: function visitColumn_def_table_constraints(ctx) { var _this10 = this; return ctx.column_def_table_constraint().map(function (columnDef) { return columnDef.accept(_this10); }).filter(function (columnDef) { return columnDef; }); } // column_def_table_constraint // : column_definition // | materialized_column_definition // | table_constraint // ; }, { key: "visitColumn_def_table_constraint", value: function visitColumn_def_table_constraint(ctx) { if (ctx.column_definition()) { return ctx.column_definition().accept(this); } if (ctx.table_constraint()) { return ctx.table_constraint().accept(this); } return null; } // column_definition // : id_ (data_type | AS expression PERSISTED?) column_definition_element* column_index? // ; }, { key: "visitColumn_definition", value: function visitColumn_definition(ctx) { var _this11 = this; var columnName = ctx.id_().accept(this); var type = ''; if (ctx.data_type()) { type = ctx.data_type().accept(this); } else if (ctx.expression()) { // { value: "(first_name + ' ' + last_name)", type: 'expression' } var expression = ctx.expression().accept(this); var as = ctx.AS().getText(); var persisted = ctx.PERSISTED() ? " ".concat(ctx.PERSISTED().getText()) : ''; type = "".concat(as, " ").concat(expression.value).concat(persisted); } var field = new _AST.Field({ name: columnName, type: { type_name: type, schemaName: null } }); var definition = { kind: _constants.TABLE_CONSTRAINT_KIND.FIELD, value: { field: field, inline_refs: [], checkConstraints: [] } }; var columnDefinitions = ctx.column_definition_element().map(function (columnDef) { return columnDef.accept(_this11); }); // e.g. // [ // { kind: 'not_null', value: true }, // { kind: 'dbdefault', value: { value: 'GETDATE()', type: 'expression' } } // ] columnDefinitions.filter(function (columnDef) { return columnDef; }).forEach(function (columnDef) { switch (columnDef.kind) { case _constants.COLUMN_CONSTRAINT_KIND.DEFAULT: field.dbdefault = columnDef.value; break; case _constants.COLUMN_CONSTRAINT_KIND.INCREMENT: field.increment = columnDef.value; break; case _constants.COLUMN_CONSTRAINT_KIND.NOT_NULL: field.not_null = columnDef.value; break; case _constants.COLUMN_CONSTRAINT_KIND.PK: field.pk = columnDef.value; break; case _constants.COLUMN_CONSTRAINT_KIND.UNIQUE: field.unique = columnDef.value; break; case _constants.COLUMN_CONSTRAINT_KIND.INLINE_REF: definition.value.inline_refs.push(columnDef.value); break; case _constants.COLUMN_CONSTRAINT_KIND.CHECK: { var _columnDef$value = columnDef.value, columnDefType = _columnDef$value.type, value = _columnDef$value.value; // we keep the current behavior: when a field has a check constraints cannot be converted to enum, we will ignore it if (columnDefType !== CHECK_CONSTRAINT_CONDITION_TYPE.ENUM) return; definition.value.checkConstraints.push(value); break; } default: break; } }); // skip column index since it is just the name of the index that a column belongs to return definition; } // column_definition_element // : FILESTREAM // | COLLATE collation_name = id_ // | SPARSE // | MASKED WITH '(' FUNCTION '=' mask_function = STRING ')' // | (CONSTRAINT constraint = id_)? DEFAULT constant_expr = expression // | IDENTITY ('(' seed = DECIMAL ',' increment = DECIMAL ')')? // | NOT FOR REPLICATION // | GENERATED ALWAYS AS (ROW | TRANSACTION_ID | SEQUENCE_NUMBER) (START | END) HIDDEN_KEYWORD? // // NULL / NOT NULL is a constraint // | ROWGUIDCOL // | ENCRYPTED WITH '(' COLUMN_ENCRYPTION_KEY '=' key_name = STRING ',' ENCRYPTION_TYPE '=' ( // DETERMINISTIC // | RANDOMIZED // ) ',' ALGORITHM '=' algo = STRING ')' // | column_constraint // ; }, { key: "visitColumn_definition_element", value: function visitColumn_definition_element(ctx) { if (ctx.DEFAULT()) { return { kind: _constants.COLUMN_CONSTRAINT_KIND.DEFAULT, value: ctx.expression().accept(this) }; } if (ctx.IDENTITY()) { return { kind: _constants.COLUMN_CONSTRAINT_KIND.INCREMENT, value: true }; } if (ctx.column_constraint()) { return ctx.column_constraint().accept(this); } return null; } // column_constraint // : (CONSTRAINT constraint = id_)? ( // null_notnull // | ( (PRIMARY KEY | UNIQUE) clustered? primary_key_options) // | ( (FOREIGN KEY)? foreign_key_options) // | check_constraint // ) // ; }, { key: "visitColumn_constraint", value: function visitColumn_constraint(ctx) { if (ctx.null_notnull()) { var notNull = false; var nullNotnull = ctx.null_notnull().accept(this); if (nullNotnull.includes('NOT')) notNull = true; return { kind: _constants.COLUMN_CONSTRAINT_KIND.NOT_NULL, value: notNull }; } if (ctx.UNIQUE()) { return { kind: _constants.COLUMN_CONSTRAINT_KIND.UNIQUE, value: true }; } if (ctx.PRIMARY()) { return { kind: _constants.COLUMN_CONSTRAINT_KIND.PK, value: true }; } if (ctx.foreign_key_options()) { var _ctx$foreign_key_opti = ctx.foreign_key_options().accept(this), refTableName = _ctx$foreign_key_opti.refTableName, refSchemaName = _ctx$foreign_key_opti.refSchemaName, fieldNames = _ctx$foreign_key_opti.fieldNames, onDelete = _ctx$foreign_key_opti.onDelete, onUpdate = _ctx$foreign_key_opti.onUpdate; return { kind: _constants.COLUMN_CONSTRAINT_KIND.INLINE_REF, value: { endpoints: [{ tableName: null, schemaName: null, fieldNames: null, relation: '*' }, { tableName: refTableName, schemaName: refSchemaName, fieldNames: fieldNames, relation: '1' }], onDelete: onDelete, onUpdate: onUpdate } }; } // we do not handle check constraint since it is complicated and hard to extract enum from it if (ctx.check_constraint()) { return { kind: _constants.COLUMN_CONSTRAINT_KIND.CHECK, value: ctx.check_constraint().accept(this) }; } return null; } // check_constraint // : CHECK (NOT FOR REPLICATION)? '(' search_condition ')' // ; }, { key: "visitCheck_constraint", value: function visitCheck_constraint(ctx) { return ctx.search_condition().accept(this); } // search_condition // : NOT* (predicate | '(' search_condition ')') // | search_condition AND search_condition // AND takes precedence over OR // | search_condition OR search_condition // ; }, { key: "visitSearch_condition", value: function visitSearch_condition(ctx) { // we will parse the enum from the most basic condition - map to the old behavior // others, we will get the check constraint to ensure the constraint is applied - enhance the old behavior if (!ctx.predicate() || ctx.NOT().length) { return { type: CHECK_CONSTRAINT_CONDITION_TYPE.RAW, value: (0, _helpers.getOriginalText)(ctx) }; } var predicate = ctx.predicate().accept(this); if (!predicate) { return { type: CHECK_CONSTRAINT_CONDITION_TYPE.RAW, value: (0, _helpers.getOriginalText)(ctx) }; } return { type: CHECK_CONSTRAINT_CONDITION_TYPE.ENUM, value: predicate }; } // predicate // : EXISTS '(' subquery ')' // | freetext_predicate // | expression comparison_operator expression // | expression MULT_ASSIGN expression ////SQL-82 syntax for left outer joins; '*='. See https://stackoverflow.com/questions/40665/in-sybase-sql // | expression comparison_operator (ALL | SOME | ANY) '(' subquery ')' // | expression NOT* BETWEEN expression AND expression // | expression NOT* IN '(' (subquery | expression_list_) ')' // | expression NOT* LIKE expression (ESCAPE expression)? // | expression IS null_notnull // ; }, { key: "visitPredicate", value: function visitPredicate(ctx) { var _this12 = this; if (ctx.IN() && ctx.expression_list_() && ctx.NOT().length === 0) { var _expression$value; var _ctx$expression$map = ctx.expression().map(function (e) { return e.accept(_this12); }), _ctx$expression$map2 = _slicedToArray(_ctx$expression$map, 1), _ctx$expression$map2$ = _ctx$expression$map2[0], expression = _ctx$expression$map2$ === void 0 ? {} : _ctx$expression$map2$; // { // value: [ 'myschema', 'sample_table', 'column_name' ], // type: 'expression' // } var column = (0, _lodash.last)((_expression$value = expression.value) !== null && _expression$value !== void 0 ? _expression$value : []); var expressionList = ctx.expression_list_().accept(this).map(function (e) { return e.value; }); return { column: column, columnValues: expressionList }; } return null; } }, { key: "visitNull_notnull", value: function visitNull_notnull(ctx) { return (0, _helpers.getOriginalText)(ctx); } // foreign_key_options // : REFERENCES table_name '(' pk = column_name_list ')' (on_delete | on_update)* ( // NOT FOR REPLICATION // )? // ; }, { key: "visitForeign_key_options", value: function visitForeign_key_options(ctx) { var _this13 = this; var names = ctx.table_name().accept(this); var _getSchemaAndTableNam2 = getSchemaAndTableName(names), refSchemaName = _getSchemaAndTableNam2.schemaName, refTableName = _getSchemaAndTableNam2.tableName; var fieldNames = ctx.column_name_list().accept(this); var onDelete = ctx.on_delete() ? ctx.on_delete().map(function (action) { return action.accept(_this13); })[0] : null; var onUpdate = ctx.on_update() ? ctx.on_update().map(function (action) { return action.accept(_this13); })[0] : null; return { refTableName: refTableName, refSchemaName: refSchemaName, onDelete: onDelete, onUpdate: onUpdate, fieldNames: fieldNames }; } // column_name_list // : col += id_ (',' col += id_)* // ; }, { key: "visitColumn_name_list", value: function visitColumn_name_list(ctx) { var _this14 = this; return ctx.id_().map(function (id) { return id.accept(_this14); }); } // on_delete // : ON DELETE (NO ACTION | CASCADE | SET NULL_ | SET DEFAULT) // ; }, { key: "visitOn_delete", value: function visitOn_delete(ctx) { if (ctx.NO()) { return 'NO ACTION'; } if (ctx.CASCADE()) { return 'CASCADE'; } if (ctx.NULL_()) { return 'SET NULL'; } return 'SET DEFAULT'; } // on_update // : ON UPDATE (NO ACTION | CASCADE | SET NULL_ | SET DEFAULT) // ; }, { key: "visitOn_update", value: function visitOn_update(ctx) { if (ctx.NO()) { return 'NO ACTION'; } if (ctx.CASCADE()) { return 'CASCADE'; } if (ctx.NULL_()) { return 'SET NULL'; } return 'SET DEFAULT'; } // table_constraint // : (CONSTRAINT constraint = id_)? ( // ((PRIMARY KEY | UNIQUE) clustered? '(' column_name_list_with_order ')' primary_key_options) // | ( FOREIGN KEY '(' fk = column_name_list ')' foreign_key_options) // | ( CONNECTION '(' connection_node ( ',' connection_node)* ')') // | ( DEFAULT constant_expr = expression FOR column = id_ (WITH VALUES)?) // | check_constraint // ) // ; }, { key: "visitTable_constraint", value: function visitTable_constraint(ctx) { var _this15 = this; var name = ctx.id_() ? ctx.id_().map(function (id) { return id.accept(_this15); })[0] : ''; if (ctx.PRIMARY() || ctx.UNIQUE()) { var columns = ctx.column_name_list_with_order().accept(this); var index = new _AST.Index({ name: name, columns: columns }); if (ctx.PRIMARY()) { index.pk = true; } if (ctx.UNIQUE()) { index.unique = true; } return { kind: ctx.PRIMARY() ? _constants.TABLE_CONSTRAINT_KIND.PK : _constants.TABLE_CONSTRAINT_KIND.UNIQUE, value: index }; } if (ctx.FOREIGN()) { var _columns = ctx.column_name_list().accept(this); var _ctx$foreign_key_opti2 = ctx.foreign_key_options().accept(this), refTableName = _ctx$foreign_key_opti2.refTableName, refSchemaName = _ctx$foreign_key_opti2.refSchemaName, fieldNames = _ctx$foreign_key_opti2.fieldNames, onDelete = _ctx$foreign_key_opti2.onDelete, onUpdate = _ctx$foreign_key_opti2.onUpdate; return { kind: _constants.TABLE_CONSTRAINT_KIND.FK, value: { name: name, endpoints: [{ tableName: null, schemaName: null, fieldNames: _columns, relation: '*' }, { tableName: refTableName, schemaName: refSchemaName, fieldNames: fieldNames, relation: '1' }], onDelete: onDelete, onUpdate: onUpdate } }; } if (ctx.DEFAULT()) { var column = ctx.column.accept(this); var expression = ctx.expression().accept(this); return { kind: _constants.TABLE_CONSTRAINT_KIND.DEFAULT, value: { column: column, defaultValue: expression } }; } if (ctx.check_constraint()) { var checkConstraint = ctx.check_constraint().accept(this); if (checkConstraint.type !== CHECK_CONSTRAINT_CONDITION_TYPE.ENUM) return null; return { kind: _constants.TABLE_CONSTRAINT_KIND.CHECK, value: checkConstraint.value }; } return null; } // column_name_list_with_order // : id_ (ASC | DESC)? (',' id_ (ASC | DESC)?)* // ; }, { key: "visitColumn_name_list_with_order", value: function visitColumn_name_list_with_order(ctx) { var _this16 = this; return ctx.id_().map(function (id) { return { value: id.accept(_this16), type: 'column' }; }); } // table_indices // : INDEX id_ UNIQUE? clustered? '(' column_name_list_with_order ')' // | INDEX id_ CLUSTERED COLUMNSTORE // | INDEX id_ NONCLUSTERED? COLUMNSTORE '(' column_name_list ')' create_table_index_options? ( // ON id_ // )? // ; }, { key: "visitTable_indices", value: function visitTable_indices(ctx) { var _this17 = this; var index = new _AST.Index({ name: ctx.id_().map(function (id) { return id.accept(_this17); })[0], unique: !!ctx.UNIQUE(), columns: ctx.column_name_list_with_order().accept(this) }); return index; } // alter_table // : ALTER TABLE table_name ( // SET '(' LOCK_ESCALATION '=' (AUTO | TABLE | DISABLE) ')' // | ADD column_def_table_constraints // | ALTER COLUMN (column_definition | column_modifier) // | DROP COLUMN id_ (',' id_)* // | DROP CONSTRAINT constraint = id_ // | WITH (CHECK | NOCHECK) ADD (CONSTRAINT constraint = id_)? ( // FOREIGN KEY '(' fk = column_name_list ')' REFERENCES table_name ( // '(' pk = column_name_list ')' // )? (on_delete | on_update)* // | CHECK '(' search_condition ')' // ) // | (NOCHECK | CHECK) CONSTRAINT constraint = id_ // | (ENABLE | DISABLE) TRIGGER id_? // | REBUILD table_options // | SWITCH switch_partition // ) ';'? // ; }, { key: "visitAlter_table", value: function visitAlter_table(ctx) { var _this$data$refs3, _this$data$refs4, _table$fields, _table$indexes, _this18 = this; // table_name() returns an array because there are multiple table_name in the clause (REFERENCES table_name ...) var names = ctx.table_name()[0].accept(this); var _getSchemaAndTableNam3 = getSchemaAndTableName(names), schemaName = _getSchemaAndTableNam3.schemaName, tableName = _getSchemaAndTableNam3.tableName; var table = this.data.tables.find(function (t) { return t.name === tableName && t.schemaName === schemaName; }); if (!table) return; // ALTER TABLE should appear after CREATE TABLE, so skip if table is not created yet var columnDefTableConstraints = ctx.column_def_table_constraints() ? ctx.column_def_table_constraints().accept(this) : []; var _splitColumnDefTableC2 = splitColumnDefTableConstraints(columnDefTableConstraints), fieldsData = _splitColumnDefTableC2.fieldsData, indexes = _splitColumnDefTableC2.indexes, tableRefs = _splitColumnDefTableC2.tableRefs, columnDefaults = _splitColumnDefTableC2.columnDefaults, checkConstraints = _splitColumnDefTableC2.checkConstraints; var _parseFieldsAndInline2 = parseFieldsAndInlineRefsFromFieldsData(fieldsData, tableName, schemaName), inlineRefs = _parseFieldsAndInline2.inlineRefs, fields = _parseFieldsAndInline2.fields; (_this$data$refs3 = this.data.refs).push.apply(_this$data$refs3, _toConsumableArray((0, _lodash.flatten)(inlineRefs))); (_this$data$refs4 = this.data.refs).push.apply(_this$data$refs4, _toConsumableArray(tableRefs.map(function (tableRef) { tableRef.endpoints[0].tableName = tableName; tableRef.endpoints[0].schemaName = schemaName; return tableRef; }))); (_table$fields = table.fields).push.apply(_table$fields, _toConsumableArray(fields)); (_table$indexes = table.indexes).push.apply(_table$indexes, _toConsumableArray(indexes)); columnDefaults.forEach(function (columnDefault) { var field = table.fields.find(function (f) { return f.name === columnDefault.column; }); if (!field) return; field.dbdefault = columnDefault.defaultValue; }); checkConstraints.forEach(function (checkConstraint) { var field = table.fields.find(function (fieldItem) { return fieldItem.name === checkConstraint.column; }); if (!field) return; var enumObject = new _AST.Enum({ name: "".concat(tableName, "_").concat(field.name, "_enum"), values: checkConstraint.columnValues.map(function (value) { return { name: value }; }), schemaName: schemaName }); _this18.data.enums.push(enumObject); // TODO: handle multiple enums for the same field field.type.type_name = enumObject.name; field.type.schemaName = enumObject.schemaName; }); } // create_index // : CREATE UNIQUE? clustered? INDEX id_ ON table_name '(' column_name_list_with_order ')' ( // INCLUDE '(' column_name_list ')' // )? (WHERE where = search_condition)? (create_index_options)? (ON id_)? ';'? // ; }, { key: "visitCreate_index", value: function visitCreate_index(ctx) { var _getSchemaAndTableNam4 = getSchemaAndTableName(ctx.table_name().accept(this)), schemaName = _getSchemaAndTableNam4.schemaName, tableName = _getSchemaAndTableNam4.tableName; var table = this.data.tables.find(function (t) { return t.name === tableName && t.schemaName === schemaName; }); if (!table) return; // ALTER TABLE should appear after CREATE TABLE, so skip if table is not created yet var index = new _AST.Index({ name: ctx.id_()[0].accept(this), unique: !!ctx.UNIQUE(), columns: ctx.column_name_list_with_order().accept(this) }); table.indexes.push(index); } // another_statement // : alter_queue // | checkpoint_statement // | conversation_statement // | create_contract // | create_queue // | cursor_statement // | declare_statement // | execute_statement // | kill_statement // | message_statement // | reconfigure_statement // | security_statement // | set_statement // | setuser_statement // | shutdown_statement // | transaction_statement // | use_statement // ; }, { key: "visitAnother_statement", value: function visitAnother_statement(ctx) { if (ctx.execute_statement()) { ctx.execute_statement().accept(this); } } // execute_statement // : EXECUTE execute_body ';'? // ; }, { key: "visitExecute_statement", value: function visitExecute_statement(ctx) { ctx.execute_body().accept(this); } // execute_body // : (return_status = LOCAL_ID '=')? (func_proc_name_server_database_schema | execute_var_string) execute_statement_arg? // | '(' execute_var_string (',' execute_var_string)* ')' (AS (LOGIN | USER) '=' STRING)? ( // AT_KEYWORD linkedServer = id_ // )? // | AS ( (LOGIN | USER) '=' STRING | CALLER) // ; }, { key: "visitExecute_body", value: function visitExecute_body(ctx) { var funcNames = ctx.func_proc_name_server_database_schema() ? ctx.func_proc_name_server_database_schema().accept(this) : []; var funcName = (0, _lodash.last)(funcNames); if (funcName !