Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Avatar for KuCalc : devops.
Download
50672 views
1
// CodeMirror, copyright (c) by Marijn Haverbeke and others
2
// Distributed under an MIT license: http://codemirror.net/LICENSE
3
4
(function(mod) {
5
if (typeof exports == "object" && typeof module == "object") // CommonJS
6
mod(require("../../lib/codemirror"), require("../../mode/sql/sql"));
7
else if (typeof define == "function" && define.amd) // AMD
8
define(["../../lib/codemirror", "../../mode/sql/sql"], mod);
9
else // Plain browser env
10
mod(CodeMirror);
11
})(function(CodeMirror) {
12
"use strict";
13
14
var tables;
15
var defaultTable;
16
var keywords;
17
var CONS = {
18
QUERY_DIV: ";",
19
ALIAS_KEYWORD: "AS"
20
};
21
var Pos = CodeMirror.Pos;
22
23
function getKeywords(editor) {
24
var mode = editor.doc.modeOption;
25
if (mode === "sql") mode = "text/x-sql";
26
return CodeMirror.resolveMode(mode).keywords;
27
}
28
29
function match(string, word) {
30
var len = string.length;
31
var sub = word.substr(0, len);
32
return string.toUpperCase() === sub.toUpperCase();
33
}
34
35
function addMatches(result, search, wordlist, formatter) {
36
for (var word in wordlist) {
37
if (!wordlist.hasOwnProperty(word)) continue;
38
if (Array.isArray(wordlist)) {
39
word = wordlist[word];
40
}
41
if (match(search, word)) {
42
result.push(formatter(word));
43
}
44
}
45
}
46
47
function nameCompletion(cur, token, result, editor) {
48
var useBacktick = (token.string.charAt(0) == "`");
49
var string = token.string.substr(1);
50
var prevToken = editor.getTokenAt(Pos(cur.line, token.start));
51
if (token.string.charAt(0) == "." || prevToken.string == "."){
52
//Suggest colunm names
53
if (prevToken.string == ".") {
54
var prevToken = editor.getTokenAt(Pos(cur.line, token.start - 1));
55
}
56
var table = prevToken.string;
57
//Check if backtick is used in table name. If yes, use it for columns too.
58
var useBacktickTable = false;
59
if (table.match(/`/g)) {
60
useBacktickTable = true;
61
table = table.replace(/`/g, "");
62
}
63
//Check if table is available. If not, find table by Alias
64
if (!tables.hasOwnProperty(table))
65
table = findTableByAlias(table, editor);
66
var columns = tables[table];
67
if (!columns) return;
68
69
if (useBacktick) {
70
addMatches(result, string, columns, function(w) {return "`" + w + "`";});
71
}
72
else if(useBacktickTable) {
73
addMatches(result, string, columns, function(w) {return ".`" + w + "`";});
74
}
75
else {
76
addMatches(result, string, columns, function(w) {return "." + w;});
77
}
78
}
79
else {
80
//Suggest table names or colums in defaultTable
81
while (token.start && string.charAt(0) == ".") {
82
token = editor.getTokenAt(Pos(cur.line, token.start - 1));
83
string = token.string + string;
84
}
85
if (useBacktick) {
86
addMatches(result, string, tables, function(w) {return "`" + w + "`";});
87
addMatches(result, string, defaultTable, function(w) {return "`" + w + "`";});
88
}
89
else {
90
addMatches(result, string, tables, function(w) {return w;});
91
addMatches(result, string, defaultTable, function(w) {return w;});
92
}
93
}
94
}
95
96
function eachWord(lineText, f) {
97
if (!lineText) return;
98
var excepted = /[,;]/g;
99
var words = lineText.split(" ");
100
for (var i = 0; i < words.length; i++) {
101
f(words[i]?words[i].replace(excepted, '') : '');
102
}
103
}
104
105
function convertCurToNumber(cur) {
106
// max characters of a line is 999,999.
107
return cur.line + cur.ch / Math.pow(10, 6);
108
}
109
110
function convertNumberToCur(num) {
111
return Pos(Math.floor(num), +num.toString().split('.').pop());
112
}
113
114
function findTableByAlias(alias, editor) {
115
var doc = editor.doc;
116
var fullQuery = doc.getValue();
117
var aliasUpperCase = alias.toUpperCase();
118
var previousWord = "";
119
var table = "";
120
var separator = [];
121
var validRange = {
122
start: Pos(0, 0),
123
end: Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).length)
124
};
125
126
//add separator
127
var indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV);
128
while(indexOfSeparator != -1) {
129
separator.push(doc.posFromIndex(indexOfSeparator));
130
indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV, indexOfSeparator+1);
131
}
132
separator.unshift(Pos(0, 0));
133
separator.push(Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).text.length));
134
135
//find valid range
136
var prevItem = 0;
137
var current = convertCurToNumber(editor.getCursor());
138
for (var i=0; i< separator.length; i++) {
139
var _v = convertCurToNumber(separator[i]);
140
if (current > prevItem && current <= _v) {
141
validRange = { start: convertNumberToCur(prevItem), end: convertNumberToCur(_v) };
142
break;
143
}
144
prevItem = _v;
145
}
146
147
var query = doc.getRange(validRange.start, validRange.end, false);
148
149
for (var i = 0; i < query.length; i++) {
150
var lineText = query[i];
151
eachWord(lineText, function(word) {
152
var wordUpperCase = word.toUpperCase();
153
if (wordUpperCase === aliasUpperCase && tables.hasOwnProperty(previousWord)) {
154
table = previousWord;
155
}
156
if (wordUpperCase !== CONS.ALIAS_KEYWORD) {
157
previousWord = word;
158
}
159
});
160
if (table) break;
161
}
162
return table;
163
}
164
165
CodeMirror.registerHelper("hint", "sql", function(editor, options) {
166
tables = (options && options.tables) || {};
167
var defaultTableName = options && options.defaultTable;
168
defaultTable = (defaultTableName && tables[defaultTableName] || []);
169
keywords = keywords || getKeywords(editor);
170
171
var cur = editor.getCursor();
172
var result = [];
173
var token = editor.getTokenAt(cur), start, end, search;
174
if (token.end > cur.ch) {
175
token.end = cur.ch;
176
token.string = token.string.slice(0, cur.ch - token.start);
177
}
178
179
if (token.string.match(/^[.`\w@]\w*$/)) {
180
search = token.string;
181
start = token.start;
182
end = token.end;
183
} else {
184
start = end = cur.ch;
185
search = "";
186
}
187
if (search.charAt(0) == "." || search.charAt(0) == "`") {
188
nameCompletion(cur, token, result, editor);
189
} else {
190
addMatches(result, search, tables, function(w) {return w;});
191
addMatches(result, search, defaultTable, function(w) {return w;});
192
addMatches(result, search, keywords, function(w) {return w.toUpperCase();});
193
}
194
195
return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)};
196
});
197
});
198
199