UNPKG

sql-parser-mistic

Version:
271 lines (219 loc) 9.34 kB
// Generated by CoffeeScript 1.8.0 (function() { var Lexer; Lexer = (function() { var BOOLEAN, DBLSTRING, LITERAL, MATH, MATH_MULTI, NUMBER, PARAMETER, SEPARATOR, SQL_BETWEENS, SQL_CONDITIONALS, SQL_FUNCTIONS, SQL_OPERATORS, SQL_SORT_ORDERS, STAR, STRING, SUB_SELECT_OP, SUB_SELECT_UNARY_OP, WHITESPACE; function Lexer(sql, opts) { var bytesConsumed, i; if (opts == null) { opts = {}; } this.sql = sql; this.preserveWhitespace = opts.preserveWhitespace || false; this.tokens = []; this.currentLine = 1; this.currentOffset = 0; i = 0; while (this.chunk = sql.slice(i)) { bytesConsumed = this.keywordToken() || this.starToken() || this.booleanToken() || this.functionToken() || this.windowExtension() || this.sortOrderToken() || this.seperatorToken() || this.operatorToken() || this.numberToken() || this.mathToken() || this.dotToken() || this.conditionalToken() || this.betweenToken() || this.subSelectOpToken() || this.subSelectUnaryOpToken() || this.stringToken() || this.parameterToken() || this.parensToken() || this.whitespaceToken() || this.literalToken(); if (bytesConsumed < 1) { throw new Error("NOTHING CONSUMED: Stopped at - '" + (this.chunk.slice(0, 30)) + "'"); } i += bytesConsumed; this.currentOffset += bytesConsumed; } this.token('EOF', ''); this.postProcess(); } Lexer.prototype.postProcess = function() { var i, next_token, token, _i, _len, _ref, _results; _ref = this.tokens; _results = []; for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { token = _ref[i]; if (token[0] === 'STAR') { next_token = this.tokens[i + 1]; if (!(next_token[0] === 'SEPARATOR' || next_token[0] === 'FROM')) { _results.push(token[0] = 'MATH_MULTI'); } else { _results.push(void 0); } } else { _results.push(void 0); } } return _results; }; Lexer.prototype.token = function(name, value) { return this.tokens.push([name, value, this.currentLine, this.currentOffset]); }; Lexer.prototype.tokenizeFromStringRegex = function(name, regex, part, lengthPart, output) { var match, partMatch; if (part == null) { part = 0; } if (lengthPart == null) { lengthPart = part; } if (output == null) { output = true; } if (!(match = regex.exec(this.chunk))) { return 0; } partMatch = match[part].replace(/''/g, "'"); if (output) { this.token(name, partMatch); } return match[lengthPart].length; }; Lexer.prototype.tokenizeFromRegex = function(name, regex, part, lengthPart, output) { var match, partMatch; if (part == null) { part = 0; } if (lengthPart == null) { lengthPart = part; } if (output == null) { output = true; } if (!(match = regex.exec(this.chunk))) { return 0; } partMatch = match[part]; if (output) { this.token(name, partMatch); } return match[lengthPart].length; }; Lexer.prototype.tokenizeFromWord = function(name, word) { var match, matcher; if (word == null) { word = name; } word = this.regexEscape(word); matcher = /^\w+$/.test(word) ? new RegExp("^(" + word + ")\\b", 'ig') : new RegExp("^(" + word + ")", 'ig'); match = matcher.exec(this.chunk); if (!match) { return 0; } this.token(name, match[1]); return match[1].length; }; Lexer.prototype.tokenizeFromList = function(name, list) { var entry, ret, _i, _len; ret = 0; for (_i = 0, _len = list.length; _i < _len; _i++) { entry = list[_i]; ret = this.tokenizeFromWord(name, entry); if (ret > 0) { break; } } return ret; }; Lexer.prototype.keywordToken = function() { return this.tokenizeFromWord('SELECT') || this.tokenizeFromWord('INSERT') || this.tokenizeFromWord('INTO') || this.tokenizeFromWord('DEFAULT') || this.tokenizeFromWord('VALUES') || this.tokenizeFromWord('DISTINCT') || this.tokenizeFromWord('FROM') || this.tokenizeFromWord('WHERE') || this.tokenizeFromWord('GROUP') || this.tokenizeFromWord('ORDER') || this.tokenizeFromWord('BY') || this.tokenizeFromWord('HAVING') || this.tokenizeFromWord('LIMIT') || this.tokenizeFromWord('JOIN') || this.tokenizeFromWord('LEFT') || this.tokenizeFromWord('RIGHT') || this.tokenizeFromWord('INNER') || this.tokenizeFromWord('OUTER') || this.tokenizeFromWord('ON') || this.tokenizeFromWord('AS') || this.tokenizeFromWord('CASE') || this.tokenizeFromWord('WHEN') || this.tokenizeFromWord('THEN') || this.tokenizeFromWord('ELSE') || this.tokenizeFromWord('END') || this.tokenizeFromWord('UNION') || this.tokenizeFromWord('ALL') || this.tokenizeFromWord('LIMIT') || this.tokenizeFromWord('OFFSET') || this.tokenizeFromWord('FETCH') || this.tokenizeFromWord('ROW') || this.tokenizeFromWord('ROWS') || this.tokenizeFromWord('ONLY') || this.tokenizeFromWord('NEXT') || this.tokenizeFromWord('FIRST'); }; Lexer.prototype.dotToken = function() { return this.tokenizeFromWord('DOT', '.'); }; Lexer.prototype.operatorToken = function() { return this.tokenizeFromList('OPERATOR', SQL_OPERATORS); }; Lexer.prototype.mathToken = function() { return this.tokenizeFromList('MATH', MATH) || this.tokenizeFromList('MATH_MULTI', MATH_MULTI); }; Lexer.prototype.conditionalToken = function() { return this.tokenizeFromList('CONDITIONAL', SQL_CONDITIONALS); }; Lexer.prototype.betweenToken = function() { return this.tokenizeFromList('BETWEEN', SQL_BETWEENS); }; Lexer.prototype.subSelectOpToken = function() { return this.tokenizeFromList('SUB_SELECT_OP', SUB_SELECT_OP); }; Lexer.prototype.subSelectUnaryOpToken = function() { return this.tokenizeFromList('SUB_SELECT_UNARY_OP', SUB_SELECT_UNARY_OP); }; Lexer.prototype.functionToken = function() { return this.tokenizeFromList('FUNCTION', SQL_FUNCTIONS); }; Lexer.prototype.sortOrderToken = function() { return this.tokenizeFromList('DIRECTION', SQL_SORT_ORDERS); }; Lexer.prototype.booleanToken = function() { return this.tokenizeFromList('BOOLEAN', BOOLEAN); }; Lexer.prototype.starToken = function() { return this.tokenizeFromRegex('STAR', STAR); }; Lexer.prototype.seperatorToken = function() { return this.tokenizeFromRegex('SEPARATOR', SEPARATOR); }; Lexer.prototype.literalToken = function() { return this.tokenizeFromRegex('LITERAL', LITERAL, 1, 0); }; Lexer.prototype.numberToken = function() { return this.tokenizeFromRegex('NUMBER', NUMBER); }; Lexer.prototype.parameterToken = function() { return this.tokenizeFromRegex('PARAMETER', PARAMETER, 1, 0); }; Lexer.prototype.stringToken = function() { return this.tokenizeFromStringRegex('STRING', STRING, 1, 0) || this.tokenizeFromRegex('DBLSTRING', DBLSTRING, 1, 0); }; Lexer.prototype.parensToken = function() { return this.tokenizeFromRegex('LEFT_PAREN', /^\(/) || this.tokenizeFromRegex('RIGHT_PAREN', /^\)/); }; Lexer.prototype.windowExtension = function() { var match; match = /^\.(win):(length|time)/i.exec(this.chunk); if (!match) { return 0; } this.token('WINDOW', match[1]); this.token('WINDOW_FUNCTION', match[2]); return match[0].length; }; Lexer.prototype.whitespaceToken = function() { var match, newlines, partMatch; if (!(match = WHITESPACE.exec(this.chunk))) { return 0; } partMatch = match[0]; if (this.preserveWhitespace) { this.token('WHITESPACE', partMatch); } newlines = partMatch.match(/\n/g, ''); this.currentLine += (newlines != null ? newlines.length : void 0) || 0; return partMatch.length; }; Lexer.prototype.regexEscape = function(str) { return str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); }; SQL_FUNCTIONS = ['AVG', 'COUNT', 'MIN', 'MAX', 'SUM']; SQL_SORT_ORDERS = ['ASC', 'DESC']; SQL_OPERATORS = ['=', '!=', '>=', '>', '<=', '<>', '<', 'LIKE', 'NOT LIKE', 'ILIKE', 'NOT ILIKE', 'IS NOT', 'IS', 'REGEXP', 'NOT REGEXP']; SUB_SELECT_OP = ['IN', 'NOT IN', 'ANY', 'ALL', 'SOME']; SUB_SELECT_UNARY_OP = ['EXISTS']; SQL_CONDITIONALS = ['AND', 'OR']; SQL_BETWEENS = ['BETWEEN', 'NOT BETWEEN']; BOOLEAN = ['TRUE', 'FALSE', 'NULL']; MATH = ['+', '-', '||', '&&']; MATH_MULTI = ['/', '*']; STAR = /^\*/; SEPARATOR = /^,/; WHITESPACE = /^[ \n\r]+/; LITERAL = /^`?([a-z_][a-z0-9_]{0,}(\:(number|float|string|date|boolean))?)`?/i; PARAMETER = /^\$([a-z0-9_]+(\:(number|float|string|date|boolean))?)/; NUMBER = /^[+-]?[0-9]+(\.[0-9]+)?/; STRING = /^'((?:[^\\']+?|\\.|'')*)'(?!')/; DBLSTRING = /^"([^\\"]*(?:\\.[^\\"]*)*)"/; return Lexer; })(); exports.tokenize = function(sql, opts) { return (new Lexer(sql, opts)).tokens; }; }).call(this);