diff --git a/demo/kitchen-sink/docs/sqlserver.sqlserver b/demo/kitchen-sink/docs/sqlserver.sqlserver new file mode 100644 index 00000000..bf8b0aeb --- /dev/null +++ b/demo/kitchen-sink/docs/sqlserver.sqlserver @@ -0,0 +1,19 @@ +CREATE VIEW V_Orders +AS +SELECT + +--#region Orders + Orders.OrderID + ,Orders.CustomerID + ,Orders.OrderDate +--#endregion + + +/*#region Customers*/ + ,Customers.CompanyName + ,Customers.ContactName +/*#endregion*/ + +FROM Orders +INNER JOIN Customers + ON Orders.CustomerID = Customers.CustomerID diff --git a/lib/ace/ext/modelist.js b/lib/ace/ext/modelist.js index 0351567b..7a5a1e9c 100644 --- a/lib/ace/ext/modelist.js +++ b/lib/ace/ext/modelist.js @@ -146,6 +146,7 @@ var supportedModes = { Soy_Template:["soy"], Space: ["space"], SQL: ["sql"], + SQLServer: ["sqlserver"], Stylus: ["styl|stylus"], SVG: ["svg"], Tcl: ["tcl"], diff --git a/lib/ace/mode/folding/sqlserver.js b/lib/ace/mode/folding/sqlserver.js new file mode 100644 index 00000000..12993757 --- /dev/null +++ b/lib/ace/mode/folding/sqlserver.js @@ -0,0 +1,97 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { +"use strict"; + +var oop = require("../../lib/oop"); +var Range = require("../../range").Range; +var BaseFoldMode = require("./fold_mode").FoldMode; + +var FoldMode = exports.FoldMode = function() {}; + +oop.inherits(FoldMode, BaseFoldMode); + +(function() { + + // Currently the only supported folding is #region comments + // TODO: add more folding (will require in depth testing because this has never existed before) for things like: + // CASE ... END https://msdn.microsoft.com/en-us/library/ms181765.aspx + // BEGIN ... END https://msdn.microsoft.com/en-us/library/ms182717.aspx + + // this.foldingStartMarker = + // this.foldingStopMarker = + + this.startRegionRe = /^\s*(\/\*|--)#region\b/; + + this.getFoldWidget = function(session, foldStyle, row) { + var line = session.getLine(row); + + if (this.startRegionRe.test(line)) + return "start"; + + return ""; + }; + + this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) { + var line = session.getLine(row); + + if (this.startRegionRe.test(line)) + return this.getCommentRegionBlock(session, line, row); + + return; + }; + + this.getCommentRegionBlock = function(session, line, row) { + var startColumn = line.search(/\s*$/); + var maxRow = session.getLength(); + var startRow = row; + + var re = /^\s*(?:\/\*|--)#(end)?region\b/; + var depth = 1; + while (++row < maxRow) { + line = session.getLine(row); + var m = re.exec(line); + if (!m) continue; + if (m[1]) depth--; + else depth++; + + if (!depth) break; + } + + var endRow = row; + if (endRow > startRow) { + return new Range(startRow, startColumn, endRow, line.length); + } + }; + +}).call(FoldMode.prototype); + +}); diff --git a/lib/ace/mode/sqlserver.js b/lib/ace/mode/sqlserver.js new file mode 100644 index 00000000..0f66c1e5 --- /dev/null +++ b/lib/ace/mode/sqlserver.js @@ -0,0 +1,55 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var SqlServerHighlightRules = require("./sqlserver_highlight_rules").SqlHighlightRules; +var Range = require("../range").Range; +var SqlServerFoldMode = require("./folding/sqlserver").FoldMode; + +var Mode = function() { + this.HighlightRules = SqlServerHighlightRules; + this.foldingRules = new SqlServerFoldMode(); +}; +oop.inherits(Mode, TextMode); + +(function() { + this.lineCommentStart = "--"; + this.blockComment = {start: "/*", end: "*/"}; + + this.$id = "ace/mode/sql"; +}).call(Mode.prototype); + +exports.Mode = Mode; + +}); diff --git a/lib/ace/mode/sqlserver_highlight_rules.js b/lib/ace/mode/sqlserver_highlight_rules.js new file mode 100644 index 00000000..fd09e256 --- /dev/null +++ b/lib/ace/mode/sqlserver_highlight_rules.js @@ -0,0 +1,151 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var SqlServerHighlightRules = function() { + /** + * each section has a link and some javacript code. + * go to the link, open dev tools, run code to get the string + */ + + var builtinConstants = ( + "TRUE|FALSE" + ); + + // multiple pages for built in functions, the following code works for all + // var r = []; $('.tableSection').find('td').find('a').each(function() { var t = $(this).text().trim().toUpperCase(); /*dont add things with spaces */ if (t.indexOf(' ') !== -1) return; r.push(t); }); r = r.filter(function(value, index, self) { return self.indexOf(value) === index; }); r.sort(); console.log(r.join('|')); + + var builtinFunctions = ( + /* https://msdn.microsoft.com/en-us/library/ms187957.aspx */ + "OPENDATASOURCE|OPENQUERY|OPENROWSET|OPENXML" + + /* https://msdn.microsoft.com/en-us/library/ms173454.aspx */ + "AVG|CHECKSUM_AGG|COUNT|COUNT_BIG|GROUPING|GROUPING_ID|MAX|MIN|STDEV|STDEVP|SUM|VAR|VARP" + + /* https://msdn.microsoft.com/en-us/library/ms189798.aspx */ + "DENSE_RANK|NTILE|RANK|ROW_NUMBER" + + /* https://msdn.microsoft.com/en-us/library/ms173823.aspx */ + "@@DATEFIRST|@@DBTS|@@LANGID|@@LANGUAGE|@@LOCK_TIMEOUT|@@MAX_CONNECTIONS|@@MAX_PRECISION|@@NESTLEVEL|@@OPTIONS|@@REMSERVER|@@SERVERNAME|@@SERVICENAME|@@SPID|@@TEXTSIZE|@@VERSION" + + /* https://msdn.microsoft.com/en-us/library/hh231076.aspx (MANUAL) */ + "CAST|CONVERT|PARSE|TRY_CAST|TRY_CONVERT|TRY_PARSE" + + /* https://msdn.microsoft.com/en-us/library/ms186285.aspx */ + "@@CURSOR_ROWS|@@FETCH_STATUS|CURSOR_STATUS" + + /* https://msdn.microsoft.com/en-us/library/ms186724.aspx (MANUAL) */ + "@@DATEFIRST|@@LANGUAGE|CURRENT_TIMESTAMP|DATEADD|DATEDIFF|DATEFROMPARTS|DATENAME|DATEPART|DATETIME2FROMPARTS|DATETIMEFROMPARTS|DATETIMEOFFSETFROMPARTS|DAY|EOMONTH|GETDATE|GETUTCDATE|ISDATE|MONTH|SET DATEFIRST|SET DATEFORMAT|SET LANGUAGE|SMALLDATETIMEFROMPARTS|SP_HELPLANGUAGE|SWITCHOFFSET|SYSDATETIME|SYSDATETIMEOFFSET|SYSUTCDATETIME|TIMEFROMPARTS|TODATETIMEOFFSET|YEAR" + + /* https://msdn.microsoft.com/en-us/library/hh213226.aspx (MANUAL) */ + "CHOOSE|IIF" + + /* https://msdn.microsoft.com/en-us/library/ms177516.aspx */ + "ABS|ACOS|ASIN|ATAN|ATN2|CEILING|COS|COT|DEGREES|EXP|FLOOR|LOG|LOG10|PI|POWER|RADIANS|RAND|ROUND|SIGN|SIN|SQRT|SQUARE|TAN" + + /* https://msdn.microsoft.com/en-us/library/ms187812.aspx */ + "@@PROCID|APPLOCK_MODE|APPLOCK_TEST|APP_NAME|ASSEMBLYPROPERTY|COLUMNPROPERTY|COL_LENGTH|COL_NAME|DATABASEPROPERTYEX|DATABASE_PRINCIPAL_ID|DB_ID|DB_NAME|FILEGROUPPROPERTY|FILEGROUP_ID|FILEGROUP_NAME|FILEPROPERTY|FILE_ID|FILE_IDEX|FILE_NAME|FULLTEXTCATALOGPROPERTY|FULLTEXTSERVICEPROPERTY|INDEXKEY_PROPERTY|INDEXPROPERTY|INDEX_COL|OBJECTPROPERTY|OBJECTPROPERTYEX|OBJECT_DEFINITION|OBJECT_ID|OBJECT_NAME|OBJECT_SCHEMA_NAME|ORIGINAL_DB_NAME|PARSENAME|SCHEMA_ID|SCHEMA_NAME|SCOPE_IDENTITY|SERVERPROPERTY|STATS_DATE|TYPEPROPERTY|TYPE_ID|TYPE_NAME" + + /* https://msdn.microsoft.com/en-us/library/ms186236.aspx (MANUAL) */ + "CERTENCODED|CERTPRIVATEKEY|CURRENT_USER|DATABASE_PRINCIPAL_ID|HAS_PERMS_BY_NAME|IS_MEMBER|IS_ROLEMEMBER|IS_SRVROLEMEMBER|ORIGINAL_LOGIN|PERMISSIONS|PWDCOMPARE|PWDENCRYPT|SCHEMA_ID|SCHEMA_NAME|SESSION_USER|SUSER_ID|SUSER_NAME|SUSER_SID|SUSER_SNAME|SYS.FN_BUILTIN_PERMISSIONS|SYS.FN_GET_AUDIT_FILE|SYS.FN_MY_PERMISSIONS|SYSTEM_USER|USER_ID|USER_NAME" + + /* https://msdn.microsoft.com/en-us/library/ms181984.aspx */ + "ASCII|CHAR|CHARINDEX|CONCAT|DIFFERENCE|FORMAT|LEFT|LEN|LOWER|LTRIM|NCHAR|PATINDEX|QUOTENAME|REPLACE|REPLICATE|REVERSE|RIGHT|RTRIM|SOUNDEX|SPACE|STR|STUFF|SUBSTRING|UNICODE|UPPER" + + /* https://msdn.microsoft.com/en-us/library/ms187786.aspx */ + "$PARTITION|@@ERROR|@@IDENTITY|@@PACK_RECEIVED|@@ROWCOUNT|@@TRANCOUNT|BINARY_CHECKSUM|CHECKSUM|CONNECTIONPROPERTY|CONTEXT_INFO|CURRENT_REQUEST_ID|ERROR_LINE|ERROR_MESSAGE|ERROR_NUMBER|ERROR_PROCEDURE|ERROR_SEVERITY|ERROR_STATE|FORMATMESSAGE|GETANSINULL|GET_FILESTREAM_TRANSACTION_CONTEXT|HOST_ID|HOST_NAME|ISNULL|ISNUMERIC|MIN_ACTIVE_ROWVERSION|NEWID|NEWSEQUENTIALID|ROWCOUNT_BIG|XACT_STATE" + + /* https://msdn.microsoft.com/en-us/library/ms177520.aspx */ + "@@CONNECTIONS|@@CPU_BUSY|@@IDLE|@@IO_BUSY|@@PACKET_ERRORS|@@PACK_RECEIVED|@@PACK_SENT|@@TIMETICKS|@@TOTAL_ERRORS|@@TOTAL_READ|@@TOTAL_WRITE|FN_VIRTUALFILESTATS" + + /* https://msdn.microsoft.com/en-us/library/ms188353.aspx */ + "PATINDEX|TEXTPTR|TEXTVALID" + + /* */ + "" + + + "COUNT|MIN|MAX|AVG|SUM|RANK|NOW|COALESCE" + ); + + // https://msdn.microsoft.com/en-us/library/ms187752.aspx + // var r = []; $('.tableSection').find('td').find('a').each(function() { var t = $(this).text().trim().toUpperCase(); /*dont add things with spaces */ if (t.indexOf(' ') !== -1) return; r.push($(this).text().trim().toUpperCase()); }); r = r.filter(function(value, index, self) { return self.indexOf(value) === index; }); r.sort(); console.log(r.join('|')); + + var dataTypes = ( + "BIGINT|BINARY|BIT|CHAR|CURSOR|DATE|DATETIME|DATETIME2|DATETIMEOFFSET|DECIMAL|FLOAT|HIERARCHYID|IMAGE|INT|MONEY|NCHAR|NTEXT|NUMERIC|NVARCHAR|REAL|SMALLDATETIME|SMALLINT|SMALLMONEY|SQL_VARIANT|TABLE|TEXT|TIME|TIMESTAMP|TINYINT|UNIQUEIDENTIFIER|VARBINARY|VARCHAR|XML" + ); + + + + var keywordMapper = this.createKeywordMapper({ + "support.function": builtinFunctions, + "keyword": keywords, + "constant.language": builtinConstants, + "storage.type": dataTypes + }, "identifier", true); + + // createKeywordMapper ignores case which we want because SqlServer keywords are not case sensitive which + // causes our keywords to get changed to lowercase. + // However, the preferred standard for keywords is uppercase, so this transforms them back to uppercase for code completion + for (var i = 0; i < this.$keywordList.length; i++) { + this.$keywordList[i] = this.$keywordList[i].toUpperCase(); + } + + this.$rules = { + "start" : [ { + token : "comment", + regex : "--.*$" + }, { + token : "comment", + start : "/\\*", + end : "\\*/" + }, { + token : "string", // " string + regex : '".*?"' + }, { + token : "string", // ' string + regex : "'.*?'" + }, { + token : "constant.numeric", // float + regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b" + }, { + token : keywordMapper, + regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b" + }, { + token : "keyword.operator", + regex : "\\+|\\-|\\/|\\/\\/|%|<@>|@>|<@|&|\\^|~|<|>|<=|=>|==|!=|<>|=" + }, { + token : "paren.lparen", + regex : "[\\(]" + }, { + token : "paren.rparen", + regex : "[\\)]" + }, { + token : "text", + regex : "\\s+" + } ] + }; + this.normalizeRules(); +}; + +oop.inherits(SqlServerHighlightRules, TextHighlightRules); + +exports.SqlHighlightRules = SqlServerHighlightRules; +}); + diff --git a/lib/ace/snippets/sqlserver.js b/lib/ace/snippets/sqlserver.js new file mode 100644 index 00000000..f84694dc --- /dev/null +++ b/lib/ace/snippets/sqlserver.js @@ -0,0 +1,7 @@ +define(function(require, exports, module) { +"use strict"; + +exports.snippetText = require("../requirejs/text!./sqlserver.snippets"); +exports.scope = "sqlserver"; + +}); diff --git a/lib/ace/snippets/sqlserver.snippets b/lib/ace/snippets/sqlserver.snippets new file mode 100644 index 00000000..c1007485 --- /dev/null +++ b/lib/ace/snippets/sqlserver.snippets @@ -0,0 +1,18 @@ +# Create Procedure +snippet createproc + -- ============================================= + -- Author: ${1:Author} + -- Create date: ${2:Date} + -- Description: ${3:Description} + -- ============================================= + CREATE PROCEDURE ${4:Procedure_Name} + -- Add the parameters for the stored procedure here + AS + BEGIN + -- SET NOCOUNT ON added to prevent extra result sets from + -- interfering with SELECT statements. + SET NOCOUNT ON; + + -- Insert statements for procedure here + END + GO