Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DRILL-5868: Support SQL syntax highlighting of queries #1084

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
83 changes: 79 additions & 4 deletions exec/java-exec/src/main/resources/rest/profile/profile.ftl
Expand Up @@ -19,6 +19,13 @@
<script src="/static/js/jquery.form.js"></script>
<script src="/static/js/querySubmission.js"></script>
</#if>
<!-- Ace Libraries for Syntax Formatting -->
<script src="/static/js/ace-code-editor/ace.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/ace-code-editor/mode-sql.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/ace-code-editor/ext-language_tools.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/ace-code-editor/theme-sqlserver.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/ace-code-editor/snippets/sql.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/ace-code-editor/mode-snippets.js" type="text/javascript" charset="utf-8"></script>

<script>
var globalconfig = {
Expand Down Expand Up @@ -65,7 +72,7 @@ table.sortable thead .sorting_desc { background-image: url("/static/img/black-de
</ul>
<div id="query-content" class="tab-content">
<div id="query-query" class="tab-pane">
<p><pre>${model.getProfile().query}</pre></p>
<p><pre id="query-text" name="query-text" style="background-color: #f5f5f5;">${model.getProfile().query}</pre></p>
</div>
<div id="query-physical" class="tab-pane">
<p><pre>${model.profile.plan}</pre></p>
Expand All @@ -84,9 +91,8 @@ table.sortable thead .sorting_desc { background-image: url("/static/img/black-de
</#if>

<form role="form" id="queryForm" action="/query" method="POST">
<div class="form-group">
<textarea class="form-control" id="query" name="query" style="font-family: Courier;">${model.getProfile().query}</textarea>
</div>
<div id="query-editor" class="form-group">${model.getProfile().query}</div>
<input class="form-control" id="query" name="query" type="hidden" value="${model.getProfile().query}"/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like you have the same code on lines 87-88. These code lines are included when only impersonation is enabled. So if I am not mistaken, you'll end up with two query editors when only impersonation is enabled. Please check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me take a look. This might have slipped past during a merge conflict.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Patched and Verified that with Impersonation enabled, there is only one editor for the profile page.

<div class="form-group">
<div class="radio-inline">
<label>
Expand Down Expand Up @@ -364,6 +370,75 @@ table.sortable thead .sorting_desc { background-image: url("/static/img/black-de
</div>
<div class="page-header">
</div> <br>

<script>
//Configuration for Query Viewer in Profile
ace.require("ace/ext/language_tools");
var viewer = ace.edit("query-text");
viewer.setAutoScrollEditorIntoView(true);
viewer.setOption("minLines", 3);
viewer.setOption("maxLines", 20);
viewer.renderer.setShowGutter(false);
viewer.renderer.setOption('showLineNumbers', false);
viewer.renderer.setOption('showPrintMargin', false);
viewer.renderer.setOption("vScrollBarAlwaysVisible", true);
viewer.renderer.setOption("hScrollBarAlwaysVisible", true);
viewer.renderer.setScrollMargin(10, 10, 10, 10);
viewer.getSession().setMode("ace/mode/sql");
viewer.setTheme("ace/theme/sqlserver");
//CSS Formatting
document.getElementById('query-query').style.fontSize='13px';
document.getElementById('query-query').style.fontFamily='courier';
document.getElementById('query-query').style.lineHeight='1.5';
document.getElementById('query-query').style.width='98%';
document.getElementById('query-query').style.margin='auto';
document.getElementById('query-query').style.backgroundColor='#f5f5f5';
viewer.resize();
viewer.setReadOnly(true);
viewer.setOptions({
enableBasicAutocompletion: false,
enableSnippets: false,
enableLiveAutocompletion: false
});
</script>

<script>
//Configuration for Query Editor in Profile
ace.require("ace/ext/language_tools");
var editor = ace.edit("query-editor");
//Hidden text input for form-submission
var queryText = $('input[name="query"]');
editor.getSession().on("change", function () {
queryText.val(editor.getSession().getValue());
});
editor.setAutoScrollEditorIntoView(true);
editor.setOption("maxLines", 16);
editor.setOption("minLines", 10);
editor.renderer.setShowGutter(true);
editor.renderer.setOption('showLineNumbers', true);
editor.renderer.setOption('showPrintMargin', false);
editor.renderer.setOption("vScrollBarAlwaysVisible", true);
editor.renderer.setOption("hScrollBarAlwaysVisible", true);;
editor.renderer.setScrollMargin(10, 10, 10, 10);
editor.getSession().setMode("ace/mode/sql");
editor.getSession().setTabSize(4);
editor.getSession().setUseSoftTabs(true);
editor.setTheme("ace/theme/sqlserver");
editor.$blockScrolling = "Infinity";
//CSS Formatting
document.getElementById('query-editor').style.fontSize='13px';
document.getElementById('query-editor').style.fontFamily='courier';
document.getElementById('query-editor').style.lineHeight='1.5';
document.getElementById('query-editor').style.width='98%';
document.getElementById('query-editor').style.margin='auto';
document.getElementById('query-editor').style.backgroundColor='#ffffff';
editor.setOptions({
enableSnippets: true,
enableBasicAutocompletion: true,
enableLiveAutocompletion: false
});
</script>

</#macro>

<@page_html/>
43 changes: 42 additions & 1 deletion exec/java-exec/src/main/resources/rest/query/query.ftl
Expand Up @@ -15,6 +15,13 @@
<script src="/static/js/jquery.form.js"></script>
<script src="/static/js/querySubmission.js"></script>
</#if>
<!-- Ace Libraries for Syntax Formatting -->
<script src="/static/js/ace-code-editor/ace.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/ace-code-editor/mode-sql.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/ace-code-editor/ext-language_tools.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/ace-code-editor/theme-sqlserver.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/ace-code-editor/snippets/sql.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/ace-code-editor/mode-snippets.js" type="text/javascript" charset="utf-8"></script>
</#macro>

<#macro page_body>
Expand Down Expand Up @@ -57,13 +64,47 @@
</div>
<div class="form-group">
<label for="query">Query</label>
<textarea class="form-control" id="query" rows="5" name="query" style="font-family: Courier;"></textarea>
<div id="query-editor-format"></div>
<input class="form-control" type="hidden" id="query" name="query"/>
</div>

<button class="btn btn-default" type=<#if model?? && model>"button" onclick="doSubmitQueryWithUserName()"<#else>"submit"</#if>>
Submit
</button>
</form>

<script>
ace.require("ace/ext/language_tools");
var editor = ace.edit("query-editor-format");
var queryText = $('input[name="query"]');
//Hidden text input for form-submission
editor.getSession().on("change", function () {
queryText.val(editor.getSession().getValue());
});
editor.setAutoScrollEditorIntoView(true);
editor.setOption("maxLines", 25);
editor.setOption("minLines", 12);
editor.renderer.setShowGutter(true);
editor.renderer.setOption('showLineNumbers', true);
editor.renderer.setOption('showPrintMargin', false);
editor.getSession().setMode("ace/mode/sql");
editor.getSession().setTabSize(4);
editor.getSession().setUseSoftTabs(true);
editor.setTheme("ace/theme/sqlserver");
editor.$blockScrolling = "Infinity";
//CSS Formatting
document.getElementById('query-editor-format').style.fontSize='13px';
document.getElementById('query-editor-format').style.fontFamily='courier';
document.getElementById('query-editor-format').style.lineHeight='1.5';
document.getElementById('query-editor-format').style.width='98%';
document.getElementById('query-editor-format').style.margin='auto';
editor.setOptions({
enableSnippets: true,
enableBasicAutocompletion: true,
enableLiveAutocompletion: false
});
</script>

</#macro>

<@page_html/>

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Large diffs are not rendered by default.

@@ -0,0 +1,199 @@
ace.define("ace/mode/folding/coffee",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range"], function(require, exports, module) {
"use strict";

var oop = require("../../lib/oop");
var BaseFoldMode = require("./fold_mode").FoldMode;
var Range = require("../../range").Range;

var FoldMode = exports.FoldMode = function() {};
oop.inherits(FoldMode, BaseFoldMode);

(function() {

this.getFoldWidgetRange = function(session, foldStyle, row) {
var range = this.indentationBlock(session, row);
if (range)
return range;

var re = /\S/;
var line = session.getLine(row);
var startLevel = line.search(re);
if (startLevel == -1 || line[startLevel] != "#")
return;

var startColumn = line.length;
var maxRow = session.getLength();
var startRow = row;
var endRow = row;

while (++row < maxRow) {
line = session.getLine(row);
var level = line.search(re);

if (level == -1)
continue;

if (line[level] != "#")
break;

endRow = row;
}

if (endRow > startRow) {
var endColumn = session.getLine(endRow).length;
return new Range(startRow, startColumn, endRow, endColumn);
}
};
this.getFoldWidget = function(session, foldStyle, row) {
var line = session.getLine(row);
var indent = line.search(/\S/);
var next = session.getLine(row + 1);
var prev = session.getLine(row - 1);
var prevIndent = prev.search(/\S/);
var nextIndent = next.search(/\S/);

if (indent == -1) {
session.foldWidgets[row - 1] = prevIndent!= -1 && prevIndent < nextIndent ? "start" : "";
return "";
}
if (prevIndent == -1) {
if (indent == nextIndent && line[indent] == "#" && next[indent] == "#") {
session.foldWidgets[row - 1] = "";
session.foldWidgets[row + 1] = "";
return "start";
}
} else if (prevIndent == indent && line[indent] == "#" && prev[indent] == "#") {
if (session.getLine(row - 2).search(/\S/) == -1) {
session.foldWidgets[row - 1] = "start";
session.foldWidgets[row + 1] = "";
return "";
}
}

if (prevIndent!= -1 && prevIndent < indent)
session.foldWidgets[row - 1] = "start";
else
session.foldWidgets[row - 1] = "";

if (indent < nextIndent)
return "start";
else
return "";
};

}).call(FoldMode.prototype);

});

ace.define("ace/mode/snippets",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/text_highlight_rules","ace/mode/folding/coffee"], function(require, exports, module) {
"use strict";

var oop = require("../lib/oop");
var TextMode = require("./text").Mode;
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;

var SnippetHighlightRules = function() {

var builtins = "SELECTION|CURRENT_WORD|SELECTED_TEXT|CURRENT_LINE|LINE_INDEX|" +
"LINE_NUMBER|SOFT_TABS|TAB_SIZE|FILENAME|FILEPATH|FULLNAME";

this.$rules = {
"start" : [
{token:"constant.language.escape", regex: /\\[\$}`\\]/},
{token:"keyword", regex: "\\$(?:TM_)?(?:" + builtins + ")\\b"},
{token:"variable", regex: "\\$\\w+"},
{onMatch: function(value, state, stack) {
if (stack[1])
stack[1]++;
else
stack.unshift(state, 1);
return this.tokenName;
}, tokenName: "markup.list", regex: "\\${", next: "varDecl"},
{onMatch: function(value, state, stack) {
if (!stack[1])
return "text";
stack[1]--;
if (!stack[1])
stack.splice(0,2);
return this.tokenName;
}, tokenName: "markup.list", regex: "}"},
{token: "doc.comment", regex:/^\${2}-{5,}$/}
],
"varDecl" : [
{regex: /\d+\b/, token: "constant.numeric"},
{token:"keyword", regex: "(?:TM_)?(?:" + builtins + ")\\b"},
{token:"variable", regex: "\\w+"},
{regex: /:/, token: "punctuation.operator", next: "start"},
{regex: /\//, token: "string.regex", next: "regexp"},
{regex: "", next: "start"}
],
"regexp" : [
{regex: /\\./, token: "escape"},
{regex: /\[/, token: "regex.start", next: "charClass"},
{regex: "/", token: "string.regex", next: "format"},
{"token": "string.regex", regex:"."}
],
charClass : [
{regex: "\\.", token: "escape"},
{regex: "\\]", token: "regex.end", next: "regexp"},
{"token": "string.regex", regex:"."}
],
"format" : [
{regex: /\\[ulULE]/, token: "keyword"},
{regex: /\$\d+/, token: "variable"},
{regex: "/[gim]*:?", token: "string.regex", next: "start"},
{"token": "string", regex:"."}
]
};
};
oop.inherits(SnippetHighlightRules, TextHighlightRules);

exports.SnippetHighlightRules = SnippetHighlightRules;

var SnippetGroupHighlightRules = function() {
this.$rules = {
"start" : [
{token: "text", regex: "^\\t", next: "sn-start"},
{token:"invalid", regex: /^ \s*/},
{token:"comment", regex: /^#.*/},
{token:"constant.language.escape", regex: "^regex ", next: "regex"},
{token:"constant.language.escape", regex: "^(trigger|endTrigger|name|snippet|guard|endGuard|tabTrigger|key)\\b"}
],
"regex" : [
{token:"text", regex: "\\."},
{token:"keyword", regex: "/"},
{token:"empty", regex: "$", next: "start"}
]
};
this.embedRules(SnippetHighlightRules, "sn-", [
{token: "text", regex: "^\\t", next: "sn-start"},
{onMatch: function(value, state, stack) {
stack.splice(stack.length);
return this.tokenName;
}, tokenName: "text", regex: "^(?!\t)", next: "start"}
]);

};

oop.inherits(SnippetGroupHighlightRules, TextHighlightRules);

exports.SnippetGroupHighlightRules = SnippetGroupHighlightRules;

var FoldMode = require("./folding/coffee").FoldMode;

var Mode = function() {
this.HighlightRules = SnippetGroupHighlightRules;
this.foldingRules = new FoldMode();
this.$behaviour = this.$defaultBehaviour;
};
oop.inherits(Mode, TextMode);

(function() {
this.$indentWithTabs = true;
this.lineCommentStart = "#";
this.$id = "ace/mode/snippets";
}).call(Mode.prototype);
exports.Mode = Mode;


});