| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 | // CodeMirror, copyright (c) by Marijn Haverbeke and others// Distributed under an MIT license: https://codemirror.net/LICENSE(function(mod) {  if (typeof exports == "object" && typeof module == "object") // CommonJS    mod(require("../../lib/codemirror"), require("../../mode/sql/sql"));  else if (typeof define == "function" && define.amd) // AMD    define(["../../lib/codemirror", "../../mode/sql/sql"], mod);  else // Plain browser env    mod(CodeMirror);})(function(CodeMirror) {  "use strict";  var tables;  var defaultTable;  var keywords;  var identifierQuote;  var CONS = {    QUERY_DIV: ";",    ALIAS_KEYWORD: "AS"  };  var Pos = CodeMirror.Pos, cmpPos = CodeMirror.cmpPos;  function isArray(val) { return Object.prototype.toString.call(val) == "[object Array]" }  function getKeywords(editor) {    var mode = editor.doc.modeOption;    if (mode === "sql") mode = "text/x-sql";    return CodeMirror.resolveMode(mode).keywords;  }  function getIdentifierQuote(editor) {    var mode = editor.doc.modeOption;    if (mode === "sql") mode = "text/x-sql";    return CodeMirror.resolveMode(mode).identifierQuote || "`";  }  function getText(item) {    return typeof item == "string" ? item : item.text;  }  function wrapTable(name, value) {    if (isArray(value)) value = {columns: value}    if (!value.text) value.text = name    return value  }  function parseTables(input) {    var result = {}    if (isArray(input)) {      for (var i = input.length - 1; i >= 0; i--) {        var item = input[i]        result[getText(item).toUpperCase()] = wrapTable(getText(item), item)      }    } else if (input) {      for (var name in input)        result[name.toUpperCase()] = wrapTable(name, input[name])    }    return result  }  function getTable(name) {    return tables[name.toUpperCase()]  }  function shallowClone(object) {    var result = {};    for (var key in object) if (object.hasOwnProperty(key))      result[key] = object[key];    return result;  }  function match(string, word) {    var len = string.length;    var sub = getText(word).substr(0, len);    return string.toUpperCase() === sub.toUpperCase();  }  function addMatches(result, search, wordlist, formatter) {    if (isArray(wordlist)) {      for (var i = 0; i < wordlist.length; i++)        if (match(search, wordlist[i])) result.push(formatter(wordlist[i]))    } else {      for (var word in wordlist) if (wordlist.hasOwnProperty(word)) {        var val = wordlist[word]        if (!val || val === true)          val = word        else          val = val.displayText ? {text: val.text, displayText: val.displayText} : val.text        if (match(search, val)) result.push(formatter(val))      }    }  }  function cleanName(name) {    // Get rid name from identifierQuote and preceding dot(.)    if (name.charAt(0) == ".") {      name = name.substr(1);    }    // replace doublicated identifierQuotes with single identifierQuotes    // and remove single identifierQuotes    var nameParts = name.split(identifierQuote+identifierQuote);    for (var i = 0; i < nameParts.length; i++)      nameParts[i] = nameParts[i].replace(new RegExp(identifierQuote,"g"), "");    return nameParts.join(identifierQuote);  }  function insertIdentifierQuotes(name) {    var nameParts = getText(name).split(".");    for (var i = 0; i < nameParts.length; i++)      nameParts[i] = identifierQuote +        // doublicate identifierQuotes        nameParts[i].replace(new RegExp(identifierQuote,"g"), identifierQuote+identifierQuote) +        identifierQuote;    var escaped = nameParts.join(".");    if (typeof name == "string") return escaped;    name = shallowClone(name);    name.text = escaped;    return name;  }  function nameCompletion(cur, token, result, editor) {    // Try to complete table, column names and return start position of completion    var useIdentifierQuotes = false;    var nameParts = [];    var start = token.start;    var cont = true;    while (cont) {      cont = (token.string.charAt(0) == ".");      useIdentifierQuotes = useIdentifierQuotes || (token.string.charAt(0) == identifierQuote);      start = token.start;      nameParts.unshift(cleanName(token.string));      token = editor.getTokenAt(Pos(cur.line, token.start));      if (token.string == ".") {        cont = true;        token = editor.getTokenAt(Pos(cur.line, token.start));      }    }    // Try to complete table names    var string = nameParts.join(".");    addMatches(result, string, tables, function(w) {      return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;    });    // Try to complete columns from defaultTable    addMatches(result, string, defaultTable, function(w) {      return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;    });    // Try to complete columns    string = nameParts.pop();    var table = nameParts.join(".");    var alias = false;    var aliasTable = table;    // Check if table is available. If not, find table by Alias    if (!getTable(table)) {      var oldTable = table;      table = findTableByAlias(table, editor);      if (table !== oldTable) alias = true;    }    var columns = getTable(table);    if (columns && columns.columns)      columns = columns.columns;    if (columns) {      addMatches(result, string, columns, function(w) {        var tableInsert = table;        if (alias == true) tableInsert = aliasTable;        if (typeof w == "string") {          w = tableInsert + "." + w;        } else {          w = shallowClone(w);          w.text = tableInsert + "." + w.text;        }        return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;      });    }    return start;  }  function eachWord(lineText, f) {    var words = lineText.split(/\s+/)    for (var i = 0; i < words.length; i++)      if (words[i]) f(words[i].replace(/[,;]/g, ''))  }  function findTableByAlias(alias, editor) {    var doc = editor.doc;    var fullQuery = doc.getValue();    var aliasUpperCase = alias.toUpperCase();    var previousWord = "";    var table = "";    var separator = [];    var validRange = {      start: Pos(0, 0),      end: Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).length)    };    //add separator    var indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV);    while(indexOfSeparator != -1) {      separator.push(doc.posFromIndex(indexOfSeparator));      indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV, indexOfSeparator+1);    }    separator.unshift(Pos(0, 0));    separator.push(Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).text.length));    //find valid range    var prevItem = null;    var current = editor.getCursor()    for (var i = 0; i < separator.length; i++) {      if ((prevItem == null || cmpPos(current, prevItem) > 0) && cmpPos(current, separator[i]) <= 0) {        validRange = {start: prevItem, end: separator[i]};        break;      }      prevItem = separator[i];    }    if (validRange.start) {      var query = doc.getRange(validRange.start, validRange.end, false);      for (var i = 0; i < query.length; i++) {        var lineText = query[i];        eachWord(lineText, function(word) {          var wordUpperCase = word.toUpperCase();          if (wordUpperCase === aliasUpperCase && getTable(previousWord))            table = previousWord;          if (wordUpperCase !== CONS.ALIAS_KEYWORD)            previousWord = word;        });        if (table) break;      }    }    return table;  }  CodeMirror.registerHelper("hint", "sql", function(editor, options) {    tables = parseTables(options && options.tables)    var defaultTableName = options && options.defaultTable;    var disableKeywords = options && options.disableKeywords;    defaultTable = defaultTableName && getTable(defaultTableName);    keywords = getKeywords(editor);    identifierQuote = getIdentifierQuote(editor);    if (defaultTableName && !defaultTable)      defaultTable = findTableByAlias(defaultTableName, editor);    defaultTable = defaultTable || [];    if (defaultTable.columns)      defaultTable = defaultTable.columns;    var cur = editor.getCursor();    var result = [];    var token = editor.getTokenAt(cur), start, end, search;    if (token.end > cur.ch) {      token.end = cur.ch;      token.string = token.string.slice(0, cur.ch - token.start);    }    if (token.string.match(/^[.`"'\w@][\w$#]*$/g)) {      search = token.string;      start = token.start;      end = token.end;    } else {      start = end = cur.ch;      search = "";    }    if (search.charAt(0) == "." || search.charAt(0) == identifierQuote) {      start = nameCompletion(cur, token, result, editor);    } else {      var objectOrClass = function(w, className) {        if (typeof w === "object") {          w.className = className;        } else {          w = { text: w, className: className };        }        return w;      };    addMatches(result, search, defaultTable, function(w) {        return objectOrClass(w, "CodeMirror-hint-table CodeMirror-hint-default-table");    });    addMatches(        result,        search,        tables, function(w) {          return objectOrClass(w, "CodeMirror-hint-table");        }    );    if (!disableKeywords)      addMatches(result, search, keywords, function(w) {          return objectOrClass(w.toUpperCase(), "CodeMirror-hint-keyword");      });  }    return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)};  });});
 |