├── .travis.yml ├── index.js ├── .idea ├── misc.xml ├── vcs.xml ├── modules.xml ├── druid-sql-parser.iml └── workspace.xml ├── package.json ├── LICENSE ├── README.md ├── druidsqltostring.js ├── druidsql.pegjs ├── test └── test.js └── druidsql.js /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "stable" 4 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const parse = require('./druidsql'); 2 | const stringify = require('./druidsqltostring'); 3 | 4 | module.exports = { 5 | parse: parse.parse, 6 | stringify: stringify.toSQL 7 | } 8 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/druid-sql-parser.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "druid-sql-parser", 3 | "version": "1.2.6", 4 | "description": "Parses Sql to an AST and re-stringifies SQL ASTs", 5 | "main": "index.js", 6 | "homepage": "https://github.com/mcbrewster/druid-sql-parser", 7 | "scripts": { 8 | "test": "mocha" 9 | }, 10 | "keywords": [ 11 | "sql", 12 | "sql-parser", 13 | "parser", 14 | "node", 15 | "node-parser", 16 | "node-sql-parser", 17 | "ast", 18 | "sql-ast" 19 | ], 20 | "author": "Maggie Brewster", 21 | "license": "MIT", 22 | "devDependencies": { 23 | "mocha": "^6.1.4" 24 | }, 25 | "dependencies": {} 26 | } 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 mcbrewster 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/mcbrewster/druid-sql-parser.svg?branch=master)](https://travis-ci.org/mcbrewster/druid-sql-parser) 2 | [![npm version](https://badge.fury.io/js/druid-sql-parser.svg)](//npmjs.com/package/druid-sql-parser) 3 | # Druid Sql Parser 4 | Parses Sql to an AST and re-stringifies SQL ASTs 5 | 6 | ## Set up 7 | 8 | install druid-sql-parser 9 | 10 | `npm i druid-sql-parser` 11 | 12 | ## Sql to AST 13 | 14 | ``` 15 | const parser = require('druid-sql-parser'); 16 | cosnt ast = parser.parse('SELECT "server" FROM sys.server_segments'); 17 | console.log(ast); 18 | 19 | ``` 20 | logs: 21 | ``` 22 | { 23 | "type": "query", 24 | "queryType": "SELECT", 25 | "selectParts": [ 26 | { 27 | "type": "selectPart", 28 | "distinct": null, 29 | "expr": { 30 | "type": "variable", 31 | "value": "server", 32 | "spacing": [], 33 | "quote": "\"" 34 | }, 35 | "alias": null, 36 | "spacing": [ 37 | " " 38 | ] 39 | } 40 | ], 41 | "from": { 42 | "type": "from", 43 | "value": { 44 | "type": "table", 45 | "schema": "sys", 46 | "alias": null, 47 | "table": "server_segments", 48 | "spacing": [ 49 | " " 50 | ] 51 | }, 52 | "spacing": [ 53 | " " 54 | ], 55 | "syntax": "FROM" 56 | }, 57 | "where": null, 58 | "groupby": null, 59 | "having": null, 60 | "orderBy": null, 61 | "limit": null, 62 | "unionAll": null, 63 | "syntax": "SELECT", 64 | "spacing": [], 65 | "endSpacing": [] 66 | } 67 | 68 | ``` 69 | 70 | ## AST to SQL 71 | 72 | ``` 73 | const parser = require('druid-sql-parser'); 74 | ast = { 75 | "type": "query", 76 | "queryType": "SELECT", 77 | "selectParts": [ 78 | { 79 | "type": "selectPart", 80 | "distinct": null, 81 | "expr": { 82 | "type": "variable", 83 | "value": "server", 84 | "spacing": [], 85 | "quote": "\"" 86 | }, 87 | "alias": null, 88 | "spacing": [ 89 | " " 90 | ] 91 | } 92 | ], 93 | "from": { 94 | "type": "from", 95 | "value": { 96 | "type": "table", 97 | "schema": "sys", 98 | "alias": null, 99 | "table": "server_segments", 100 | "spacing": [ 101 | " " 102 | ] 103 | }, 104 | "spacing": [ 105 | " " 106 | ], 107 | "syntax": "FROM" 108 | }, 109 | "where": null, 110 | "groupby": null, 111 | "having": null, 112 | "orderBy": null, 113 | "limit": null, 114 | "unionAll": null, 115 | "syntax": "SELECT", 116 | "spacing": [], 117 | "endSpacing": [] 118 | } 119 | const sql = parser.stringify(ast); 120 | ``` 121 | logs: `'SELECT "server" FROM sys.server_segments'` 122 | 123 | ## License 124 | [MIT](LICENSE) 125 | -------------------------------------------------------------------------------- /druidsqltostring.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Generated by PEG.js 0.10.0. 3 | * 4 | * http://pegjs.org/ 5 | */ 6 | let sqlString = []; 7 | 8 | function toString(ast) { 9 | sqlString = []; 10 | TypeToValue(ast); 11 | return sqlString.join(""); 12 | } 13 | 14 | function TypeToValue(value) { 15 | if (value.spacing) { 16 | value.spacing.map((spacing) => { 17 | sqlString.push(spacing); 18 | }) 19 | 20 | } 21 | switch(value.type){ 22 | case 'expressionOnly': 23 | TypeToValue(value.expression); 24 | value.endSpacing.map((spacing) => { 25 | sqlString.push(spacing); 26 | }); 27 | break; 28 | case 'query': 29 | sqlString.push(value.syntax); 30 | value.selectParts.map((selectpart) => { 31 | TypeToValue(selectpart); 32 | }) 33 | TypeToValue(value.from); 34 | if(value.where) { 35 | TypeToValue(value.where); 36 | } 37 | if(value.groupby) { 38 | TypeToValue(value.groupby); 39 | } 40 | if(value.having) { 41 | TypeToValue(value.having); 42 | } 43 | if(value.orderBy) { 44 | TypeToValue(value.orderBy); 45 | } 46 | if(value.limit) { 47 | TypeToValue(value.limit); 48 | } 49 | if(value.unionAll) { 50 | TypeToValue(value.limit); 51 | } 52 | value.endSpacing.map((spacing) => { 53 | sqlString.push(spacing); 54 | }); 55 | break; 56 | case 'where': 57 | sqlString.push(value.syntax); 58 | TypeToValue(value.expr); 59 | break; 60 | case 'having': 61 | sqlString.push(value.syntax); 62 | TypeToValue(value.expr); 63 | break; 64 | case 'innerJoin': 65 | sqlString.push(value.syntax); 66 | TypeToValue(value.expr); 67 | break; 68 | case 'limit': 69 | sqlString.push(value.syntax); 70 | TypeToValue(value.value); 71 | break; 72 | case 'orderBy': 73 | sqlString.push(value.syntax); 74 | value.orderByParts.map((orderByPart, index) => { 75 | TypeToValue(orderByPart); 76 | }) 77 | break; 78 | case 'selectPart': 79 | if(value.paren) { 80 | sqlString.push('(') 81 | } 82 | if(value.distinct) { 83 | TypeToValue(value.distinct) 84 | } 85 | TypeToValue(value.expr); 86 | if(value.alias){ 87 | TypeToValue(value.alias); 88 | } 89 | if(value.paren) { 90 | sqlString.push(')') 91 | } 92 | break; 93 | case 'variable': 94 | 95 | sqlString.push(value.quote + value.value + value.quote); 96 | break; 97 | case 'Constant': 98 | sqlString.push(value.value); 99 | break; 100 | case 'star': 101 | sqlString.push("*"); 102 | break; 103 | case 'function': 104 | sqlString.push(value.functionCall + "("); 105 | value.arguments.map((argument, index) => { 106 | TypeToValue(argument); 107 | }) 108 | sqlString.push(")"); 109 | break; 110 | case 'from': 111 | sqlString.push(value.syntax); 112 | TypeToValue(value.value); 113 | break; 114 | case 'table': 115 | if(value.table.type) { 116 | TypeToValue(value.table); 117 | } else { 118 | sqlString.push( value.schema ? value.schema + "." + value.table : value.table) ; 119 | } 120 | break; 121 | case 'argument': 122 | if(value.distinct) { 123 | TypeToValue(value.distinct) 124 | } 125 | TypeToValue(value.argumentValue); 126 | break; 127 | case 'argumentValue': 128 | if(value.argument.type) { 129 | TypeToValue(value.argument); 130 | } else { 131 | sqlString.push(value.argument); 132 | } 133 | break; 134 | case 'distinct' : 135 | sqlString.push(value.distinct); 136 | break; 137 | case 'groupBy': 138 | sqlString.push(value.syntax); 139 | value.groupByParts.map((groupByPart, index) => { 140 | TypeToValue(groupByPart); 141 | }) 142 | break; 143 | case 'orderByPart': 144 | value.expr.map((expr, index) => { 145 | TypeToValue(expr); 146 | }) 147 | if(value.direction) { 148 | TypeToValue(value.direction); 149 | } 150 | break; 151 | case 'direction': 152 | sqlString.push(value.direction); 153 | break; 154 | case 'exprPart': 155 | TypeToValue(value.value); 156 | break; 157 | case 'Integer': 158 | sqlString.push(value.value); 159 | break; 160 | case 'Interval': 161 | sqlString.push(value.value); 162 | break; 163 | case 'binaryExpression': 164 | TypeToValue(value.lhs); 165 | TypeToValue(value.operator); 166 | TypeToValue(value.rhs); 167 | break; 168 | case 'expression': 169 | TypeToValue(value.lhs); 170 | TypeToValue(value.operator); 171 | TypeToValue(value.rhs); 172 | break; 173 | case 'operator': 174 | sqlString.push(value.operator); 175 | break; 176 | case 'timestamp': 177 | sqlString.push("TIMESTAMP " + "'" + value.value + "'"); 178 | break; 179 | case 'case': 180 | sqlString.push(value.syntax); 181 | if(value.caseValue) { 182 | TypeToValue(value.caseValue); 183 | } 184 | value.when.map((when, index) => { 185 | TypeToValue(when); 186 | }) 187 | if(value.elseValue) { 188 | TypeToValue(value.elseValue); 189 | } 190 | TypeToValue(value.end); 191 | break; 192 | case 'caseValue': 193 | TypeToValue(value.caseValue); 194 | break; 195 | case 'when': 196 | sqlString.push(value.syntax); 197 | TypeToValue(value.when); 198 | TypeToValue(value.then); 199 | break; 200 | case 'elseValue': 201 | sqlString.push(value.syntax); 202 | TypeToValue(value.elseValue); 203 | break; 204 | case 'end': 205 | sqlString.push(value.syntax); 206 | break; 207 | case 'alias': 208 | sqlString.push(value.syntax); 209 | TypeToValue(value.value); 210 | break; 211 | case 'then': 212 | sqlString.push(value.syntax); 213 | TypeToValue(value.then); 214 | break; 215 | } 216 | 217 | } 218 | 219 | module.exports = { 220 | toSQL: toString 221 | }; 222 | -------------------------------------------------------------------------------- /druidsql.pegjs: -------------------------------------------------------------------------------- 1 | { 2 | var functions = ["COUNT", 3 | "SUM","MIN", "MAX","AVG","APPROX_COUNT_DISTINCT", 4 | "APPROX_COUNT_DISTINCT_DS_HLL", "APPROX_COUNT_DISTINCT_DS_THETA", 5 | "APPROX_QUANTILE", "APPROX_QUANTILE_DS", "APPROX_QUANTILE_FIXED_BUCKETS", 6 | "BLOOM_FILTER", "ABS", "CEIL", "EXP", "FLOOR", "LN", "LOG10", "POWER", "SQRT", 7 | "TRUNCATE", "TRUNC", "ROUND", "MOD", "SIN", "COS", "TAN", "COT", "ASIN", "ACOS", 8 | "ATAN", "ATAN2", "DEGREES", "RADIANS", "CONCAT", "TEXTCAT", "STRING_FORMAT", 9 | "LENGTH", "CHAR_LENGTH", "CHARARACTER_LENGTH", "STRLEN", "LOOKUP", "LOWER", 10 | "PARSE_LONG", "POSITION", "REGEXP_EXTRACT", "REPLACE", "STRPOS", "SUBSTRING", 11 | "RIGHT", "LEFT", "SUBSTR", "TRIM", "BTRIM", "LTRIM", "RTRIM", "UPPER", "REVERSE", 12 | "REPEAT", "LPAD", "RPAD", "CURRENT_TIMESTAMP", "CURRENT_DATE", "DATE_TRUNC", 13 | "TIME_FLOOR", "TIME_SHIFT", "TIME_EXTRACT", "TIME_PARSE", "TIME_FORMAT", 14 | "MILLIS_TO_TIMESTAMP", "TIMESTAMP_TO_MILIS", "EXTRACT", "FLOOR", "CEIL", "TIMESTAMPADD", 15 | "timestamp_expr", "CAST", "NULLIF", "COALESCE", "BLOOM_FILTER_TEST"]; 16 | } 17 | 18 | Start = 19 | Query 20 | / spacing:_ expression: Expression endspacing:_ { 21 | return {type: 'expressionOnly', 22 | spacing: spacing, 23 | expression: expression, 24 | endSpacing: endspacing }} 25 | 26 | Query = 27 | spacing: _ 28 | syntax: "SELECT"i 29 | selectParts: SelectParts 30 | from: From? 31 | where: Where? 32 | groupby: GroupBy? 33 | having: Having? 34 | orderBy: OrderBy? 35 | limit: Limit? 36 | unionAll: UnionAll? 37 | endSpacing: _ 38 | { 39 | return { 40 | type: 'query', 41 | queryType: "SELECT", 42 | selectParts: selectParts, 43 | from: from, 44 | where: where, 45 | groupby: groupby, 46 | having: having, 47 | orderBy: orderBy, 48 | limit: limit, 49 | unionAll: unionAll, 50 | syntax: syntax, 51 | spacing: spacing, 52 | endSpacing: endSpacing 53 | } 54 | } 55 | 56 | SelectParts = 57 | SelectPart: (SelectPart)+ 58 | { 59 | return SelectPart 60 | } 61 | 62 | SelectPart = 63 | spacing: _ 64 | distinct: Distinct? 65 | selectPart: ( 66 | Variable 67 | / Function 68 | / Case 69 | / Constant 70 | / star 71 | ) 72 | alias:Alias? 73 | { 74 | return { 75 | type: "selectPart", 76 | distinct: distinct, 77 | expr: selectPart, 78 | alias: alias, 79 | spacing: spacing 80 | } 81 | } 82 | 83 | From = 84 | spacing: _ 85 | syntax: "FROM"i 86 | value: ( 87 | Query 88 | / Table 89 | ) 90 | { 91 | return { 92 | type: 'from', 93 | value: value, 94 | spacing: spacing, 95 | syntax: syntax 96 | } 97 | } 98 | 99 | Where = 100 | spacing: _ 101 | syntax: "WHERE"i 102 | expr: 103 | Expression 104 | { 105 | return { 106 | type: "where", 107 | expr: expr, 108 | spacing: spacing, 109 | syntax: syntax 110 | } 111 | } 112 | 113 | GroupBy = 114 | spacing: _ 115 | syntax:"GROUP BY"i 116 | groupByParts: GroupByPart+ 117 | { 118 | return { 119 | type: 'groupBy', 120 | groupByParts: groupByParts, 121 | spacing: spacing, 122 | syntax: syntax 123 | } 124 | } 125 | 126 | GroupByPart = 127 | !Reserved 128 | groupByPart: ( 129 | Integer 130 | / Variable 131 | / Constant 132 | ) 133 | { 134 | return groupByPart 135 | } 136 | 137 | 138 | Having = 139 | spacing: _ 140 | syntax: "HAVING"i 141 | expr: ( 142 | Expression 143 | / BinaryExpression 144 | ) 145 | { 146 | return { 147 | type: "having", 148 | expr: expr, 149 | spacing: spacing, 150 | syntax: syntax 151 | } 152 | } 153 | 154 | OrderBy = 155 | spacing: _ 156 | syntax: "ORDER BY"i 157 | orderByParts: OrderByPart+ 158 | { 159 | return { 160 | type: 'orderBy', 161 | orderByParts: orderByParts, 162 | spacing: spacing, 163 | syntax: syntax 164 | } 165 | } 166 | 167 | OrderByPart = 168 | spacing: _ 169 | !"LIMIT"i 170 | expr: ExprPart+ 171 | direction: Direction? 172 | { 173 | return { 174 | type: "orderByPart", 175 | expr: expr, 176 | direction: direction, 177 | spacing: spacing 178 | } 179 | } 180 | 181 | Direction = 182 | spacing: _ 183 | direction: ( 184 | "DESC"i 185 | / "ASC"i 186 | ) 187 | { 188 | return { 189 | type: 'direction', 190 | direction: direction, 191 | spacing: spacing 192 | } 193 | } 194 | 195 | ExprPart = 196 | spacing: _ 197 | !Direction 198 | value: ( 199 | Function 200 | / Variable 201 | / Constant 202 | ) 203 | { 204 | return { 205 | type: 'exprPart', 206 | value: value, 207 | spacing: spacing 208 | } 209 | } 210 | 211 | Limit = 212 | spacing: _ 213 | syntax: "LIMIT"i 214 | value: Integer 215 | { 216 | return { 217 | type: 'limit', 218 | value: value, 219 | spacing: spacing, 220 | syntax: syntax 221 | } 222 | } 223 | 224 | UnionAll = 225 | spacing: _ 226 | syntax: "UNION ALL"i 227 | newQuery: Query 228 | { 229 | return { 230 | type: 'unionAll', 231 | expr: newQuery, 232 | spacing: spacing, 233 | syntax:syntax 234 | } 235 | } 236 | 237 | Case = 238 | spacing:_ 239 | syntax: "CASE"i 240 | caseValue: CaseValue? 241 | whenClause: WhenClause+ 242 | elseValue: ElseValue 243 | end: End? 244 | { 245 | return { 246 | type: "case", 247 | caseValue: caseValue, 248 | when: whenClause, 249 | elseValue: elseValue, 250 | end: end, 251 | spacing: spacing, 252 | syntax: syntax 253 | 254 | } 255 | } 256 | 257 | CaseValue = 258 | spacing: _ 259 | !"WHEN"i 260 | caseValue: (Variable/Constant) 261 | { 262 | return { 263 | type: 'caseValue', 264 | caseValue: caseValue, 265 | spacing: spacing 266 | } 267 | } 268 | 269 | ElseValue = 270 | spacing: _ 271 | syntax: "ELSE"i? 272 | elseValue: ( 273 | BinaryExpression 274 | / Expression 275 | / Integer 276 | / Variable 277 | / Constant 278 | )? 279 | { 280 | return { 281 | type: 'elseValue', 282 | elseValue: elseValue, 283 | spacing: spacing, 284 | syntax: syntax 285 | } 286 | } 287 | 288 | End = 289 | spacing: _ 290 | syntax: "END"i 291 | { 292 | return { 293 | type:'end', 294 | spacing: spacing, 295 | syntax: syntax 296 | } 297 | } 298 | 299 | WhenClause = 300 | spacing:_ 301 | syntax: "WHEN"i 302 | when: ( 303 | BinaryExpression 304 | / Expression 305 | / Variable 306 | / Constant 307 | / Integer 308 | ) 309 | then: Then 310 | { 311 | return { 312 | type:'when', 313 | when: when, 314 | then: then, 315 | syntax: syntax, 316 | spacing: spacing 317 | } 318 | } 319 | 320 | Then = 321 | spacing: _ 322 | syntax: "THEN"i 323 | then: ( 324 | Integer 325 | / Case 326 | / BinaryExpression 327 | / Expression 328 | / Variable 329 | ) 330 | { 331 | return { 332 | type: 'then', 333 | syntax: syntax, 334 | then: then, 335 | spacing: spacing 336 | } 337 | } 338 | 339 | 340 | BinaryExpression = 341 | spacing: _ 342 | lhs: ( 343 | Expression 344 | / Function 345 | / TimeStamp 346 | / Variable 347 | / Constant 348 | / Integer 349 | )? 350 | operator: BinaryOperator 351 | rhs: ( 352 | BinaryExpression 353 | / Function 354 | / TimeStamp 355 | / Expression 356 | / Variable 357 | / Constant 358 | / Integer 359 | )? 360 | { 361 | return { 362 | type: "binaryExpression", 363 | operator: operator, 364 | lhs: lhs, 365 | rhs: rhs, 366 | spacing: spacing 367 | } 368 | } 369 | 370 | Expression = 371 | spacing: _ 372 | lhs: ( 373 | Function 374 | / TimeStamp 375 | / Variable 376 | / Constant 377 | / Integer 378 | ) 379 | operator: ( 380 | Operator / 381 | BinaryOperator 382 | ) 383 | rhs: ( 384 | Expression 385 | / Function 386 | / TimeStamp 387 | / Interval 388 | / Variable 389 | / Constant 390 | / Integer 391 | ) 392 | { 393 | return { 394 | type: "expression", 395 | operator: operator, 396 | lhs: lhs, 397 | rhs: rhs, 398 | spacing: spacing 399 | } 400 | } 401 | 402 | Function = 403 | spacing: _ 404 | functionCall: Functions 405 | OpenParen 406 | argument: Argument+ 407 | CloseParen 408 | { 409 | return { 410 | type: "function", 411 | functionCall: functionCall, 412 | arguments: argument, 413 | spacing: spacing 414 | } 415 | } 416 | 417 | Distinct = 418 | spacing: _ 419 | distinct: "DISTINCT"i 420 | { 421 | return { 422 | type: 'distinct', 423 | distinct: distinct, 424 | spacing: spacing 425 | } 426 | } 427 | 428 | Argument = 429 | distinct: Distinct? 430 | argumentValue: ArgumentValue 431 | { 432 | return { 433 | type: 'argument', 434 | distinct: distinct, 435 | argumentValue: argumentValue 436 | } 437 | } 438 | 439 | ArgumentValue = 440 | spacing: _ 441 | !Reserved 442 | argument: ( 443 | Constant 444 | / Variable 445 | / star 446 | / [^(), ]+ 447 | ) 448 | { 449 | return { 450 | type:'argumentValue', 451 | spacing: spacing, 452 | argument: Array.isArray(argument) ? argument.join("") : argument 453 | } 454 | } 455 | 456 | Variable = 457 | spacing: _ 458 | quote: ( 459 | QuoteMark 460 | / Apostrophe 461 | ) 462 | value: [^"'()]+ 463 | ( 464 | QuoteMark 465 | / Apostrophe 466 | ) 467 | { 468 | return { 469 | type: "variable", 470 | value: value.join(""), 471 | spacing: spacing, 472 | quote: quote 473 | } 474 | } 475 | 476 | Constant = 477 | spacing: _ 478 | !Reserved 479 | value: [a-zA-Z_.]+ 480 | { 481 | return { 482 | type: "Constant", 483 | value: value.join(""), 484 | spacing: spacing 485 | } 486 | } 487 | 488 | Integer = 489 | spacing: _ 490 | value: [0-9]+ 491 | { 492 | return { 493 | type: "Integer", 494 | value: value.join(""), 495 | spacing: spacing 496 | } 497 | } 498 | 499 | TimeStamp = 500 | spacing: _ 501 | "TIMESTAMP"i 502 | _ Apostrophe 503 | timeStamp: [0-9" ":-]+ 504 | Apostrophe { 505 | return { 506 | type: "timestamp", 507 | value: timeStamp.join(""), 508 | spacing: spacing 509 | } 510 | } 511 | 512 | Operator = 513 | spacing:_ operator:( 514 | "+" 515 | /"-" 516 | /"/" 517 | /"*" 518 | /"=" 519 | ) 520 | { 521 | return { 522 | type: 'operator', 523 | spacing: spacing, 524 | operator: operator 525 | } 526 | } 527 | 528 | Interval = 529 | spacing:_ 530 | "INTERVAL"i 531 | value: ( 532 | Apostrophe 533 | / Integer 534 | / Apostrophe 535 | / Variable 536 | ) 537 | constant: Constant 538 | { 539 | return { 540 | type: "interval", 541 | value: value, 542 | constant: constant, 543 | spacing: spacing 544 | } 545 | } 546 | 547 | Alias = 548 | spacing:_ syntax:"AS"i value:(Variable/Constant/Integer) { 549 | return {type:'alias', 550 | value: value, 551 | spacing: spacing, 552 | syntax: syntax 553 | } 554 | } 555 | 556 | Functions = 557 | Function: IdentifierPart { 558 | if (functions.includes(Function)) { 559 | return Function 560 | } 561 | } 562 | 563 | 564 | 565 | BinaryOperator = 566 | spacing: _ !Parts operator:( 567 | ">=" 568 | / ">" 569 | / "=<" 570 | / "=" 571 | / "!=" 572 | / "<" 573 | / "<>" 574 | / "BETWEEN"i 575 | / "NOT BETWEEN"i 576 | / "NOT LIKE"i 577 | / "LIKE"i 578 | / "IS NULL"i 579 | / "IS NOT NULL"i 580 | / "IS TRUE"i 581 | / "IS NOT TRUE"i 582 | / "IS FALSE"i 583 | / "IN"i 584 | / "NOT IN"i 585 | / "NOT IN"i 586 | / "OR"i 587 | / "AND"i 588 | / "NOT"i 589 | ) 590 | { 591 | return { 592 | type: 'operator', 593 | operator: operator, 594 | spacing: spacing 595 | } 596 | } 597 | _ 598 | = [ \t\n\r(),;]* 599 | 600 | Table = 601 | spacing: _ 602 | schema: ( 603 | IdentifierPart 604 | Dot 605 | )? 606 | table: ( 607 | Variable 608 | / IdentifierPart 609 | ) 610 | alias: Alias? 611 | { 612 | return { 613 | type: 'table', 614 | schema: schema ? schema.join("").replace(/[,.]/g, ""): null, 615 | alias: alias, 616 | table: table, 617 | spacing: spacing 618 | } 619 | } 620 | 621 | star = 622 | "*" 623 | { 624 | return { 625 | type: "star", 626 | } 627 | } 628 | 629 | OpenParen = 630 | "(" 631 | 632 | CloseParen = 633 | ")" 634 | 635 | QuoteMark = 636 | "\"" 637 | 638 | Comma = 639 | "," 640 | 641 | SemiColon = 642 | ";" 643 | 644 | Apostrophe = 645 | "\'" 646 | 647 | Dot = 648 | "." 649 | 650 | IdentifierPart = 651 | part:[a-z_]i+ 652 | { 653 | return part.join("") 654 | } 655 | 656 | Reserved = 657 | BinaryOperator 658 | /Operator 659 | /Function 660 | /Parts 661 | 662 | Parts = 663 | "FROM"i 664 | /"WHERE"i 665 | /"GROUP BY"i 666 | /"HAVING"i 667 | /"LIMIT"i 668 | /"UNION ALL"i 669 | /"SELECT"i 670 | /"AS"i 671 | /"ORDER BY"i 672 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | equal 114 | distinct 115 | deep 116 | 117 | 118 | 119 | 121 | 122 | 138 | 139 | 140 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 |