Mercurial
comparison third_party/highlight/languages/sql.js @ 157:2db6253f355d
[ThirdParty] Added highlight library for better readability on blog.
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Tue, 13 Jan 2026 19:18:47 -0800 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 156:cd35e600ae34 | 157:2db6253f355d |
|---|---|
| 1 /*! `sql` grammar compiled for Highlight.js 11.11.1 */ | |
| 2 (function(){ | |
| 3 var hljsGrammar = (function () { | |
| 4 'use strict'; | |
| 5 | |
| 6 /* | |
| 7 Language: SQL | |
| 8 Website: https://en.wikipedia.org/wiki/SQL | |
| 9 Category: common, database | |
| 10 */ | |
| 11 | |
| 12 /* | |
| 13 | |
| 14 Goals: | |
| 15 | |
| 16 SQL is intended to highlight basic/common SQL keywords and expressions | |
| 17 | |
| 18 - If pretty much every single SQL server includes supports, then it's a canidate. | |
| 19 - It is NOT intended to include tons of vendor specific keywords (Oracle, MySQL, | |
| 20 PostgreSQL) although the list of data types is purposely a bit more expansive. | |
| 21 - For more specific SQL grammars please see: | |
| 22 - PostgreSQL and PL/pgSQL - core | |
| 23 - T-SQL - https://github.com/highlightjs/highlightjs-tsql | |
| 24 - sql_more (core) | |
| 25 | |
| 26 */ | |
| 27 | |
| 28 function sql(hljs) { | |
| 29 const regex = hljs.regex; | |
| 30 const COMMENT_MODE = hljs.COMMENT('--', '$'); | |
| 31 const STRING = { | |
| 32 scope: 'string', | |
| 33 variants: [ | |
| 34 { | |
| 35 begin: /'/, | |
| 36 end: /'/, | |
| 37 contains: [ { match: /''/ } ] | |
| 38 } | |
| 39 ] | |
| 40 }; | |
| 41 const QUOTED_IDENTIFIER = { | |
| 42 begin: /"/, | |
| 43 end: /"/, | |
| 44 contains: [ { match: /""/ } ] | |
| 45 }; | |
| 46 | |
| 47 const LITERALS = [ | |
| 48 "true", | |
| 49 "false", | |
| 50 // Not sure it's correct to call NULL literal, and clauses like IS [NOT] NULL look strange that way. | |
| 51 // "null", | |
| 52 "unknown" | |
| 53 ]; | |
| 54 | |
| 55 const MULTI_WORD_TYPES = [ | |
| 56 "double precision", | |
| 57 "large object", | |
| 58 "with timezone", | |
| 59 "without timezone" | |
| 60 ]; | |
| 61 | |
| 62 const TYPES = [ | |
| 63 'bigint', | |
| 64 'binary', | |
| 65 'blob', | |
| 66 'boolean', | |
| 67 'char', | |
| 68 'character', | |
| 69 'clob', | |
| 70 'date', | |
| 71 'dec', | |
| 72 'decfloat', | |
| 73 'decimal', | |
| 74 'float', | |
| 75 'int', | |
| 76 'integer', | |
| 77 'interval', | |
| 78 'nchar', | |
| 79 'nclob', | |
| 80 'national', | |
| 81 'numeric', | |
| 82 'real', | |
| 83 'row', | |
| 84 'smallint', | |
| 85 'time', | |
| 86 'timestamp', | |
| 87 'varchar', | |
| 88 'varying', // modifier (character varying) | |
| 89 'varbinary' | |
| 90 ]; | |
| 91 | |
| 92 const NON_RESERVED_WORDS = [ | |
| 93 "add", | |
| 94 "asc", | |
| 95 "collation", | |
| 96 "desc", | |
| 97 "final", | |
| 98 "first", | |
| 99 "last", | |
| 100 "view" | |
| 101 ]; | |
| 102 | |
| 103 // https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#reserved-word | |
| 104 const RESERVED_WORDS = [ | |
| 105 "abs", | |
| 106 "acos", | |
| 107 "all", | |
| 108 "allocate", | |
| 109 "alter", | |
| 110 "and", | |
| 111 "any", | |
| 112 "are", | |
| 113 "array", | |
| 114 "array_agg", | |
| 115 "array_max_cardinality", | |
| 116 "as", | |
| 117 "asensitive", | |
| 118 "asin", | |
| 119 "asymmetric", | |
| 120 "at", | |
| 121 "atan", | |
| 122 "atomic", | |
| 123 "authorization", | |
| 124 "avg", | |
| 125 "begin", | |
| 126 "begin_frame", | |
| 127 "begin_partition", | |
| 128 "between", | |
| 129 "bigint", | |
| 130 "binary", | |
| 131 "blob", | |
| 132 "boolean", | |
| 133 "both", | |
| 134 "by", | |
| 135 "call", | |
| 136 "called", | |
| 137 "cardinality", | |
| 138 "cascaded", | |
| 139 "case", | |
| 140 "cast", | |
| 141 "ceil", | |
| 142 "ceiling", | |
| 143 "char", | |
| 144 "char_length", | |
| 145 "character", | |
| 146 "character_length", | |
| 147 "check", | |
| 148 "classifier", | |
| 149 "clob", | |
| 150 "close", | |
| 151 "coalesce", | |
| 152 "collate", | |
| 153 "collect", | |
| 154 "column", | |
| 155 "commit", | |
| 156 "condition", | |
| 157 "connect", | |
| 158 "constraint", | |
| 159 "contains", | |
| 160 "convert", | |
| 161 "copy", | |
| 162 "corr", | |
| 163 "corresponding", | |
| 164 "cos", | |
| 165 "cosh", | |
| 166 "count", | |
| 167 "covar_pop", | |
| 168 "covar_samp", | |
| 169 "create", | |
| 170 "cross", | |
| 171 "cube", | |
| 172 "cume_dist", | |
| 173 "current", | |
| 174 "current_catalog", | |
| 175 "current_date", | |
| 176 "current_default_transform_group", | |
| 177 "current_path", | |
| 178 "current_role", | |
| 179 "current_row", | |
| 180 "current_schema", | |
| 181 "current_time", | |
| 182 "current_timestamp", | |
| 183 "current_path", | |
| 184 "current_role", | |
| 185 "current_transform_group_for_type", | |
| 186 "current_user", | |
| 187 "cursor", | |
| 188 "cycle", | |
| 189 "date", | |
| 190 "day", | |
| 191 "deallocate", | |
| 192 "dec", | |
| 193 "decimal", | |
| 194 "decfloat", | |
| 195 "declare", | |
| 196 "default", | |
| 197 "define", | |
| 198 "delete", | |
| 199 "dense_rank", | |
| 200 "deref", | |
| 201 "describe", | |
| 202 "deterministic", | |
| 203 "disconnect", | |
| 204 "distinct", | |
| 205 "double", | |
| 206 "drop", | |
| 207 "dynamic", | |
| 208 "each", | |
| 209 "element", | |
| 210 "else", | |
| 211 "empty", | |
| 212 "end", | |
| 213 "end_frame", | |
| 214 "end_partition", | |
| 215 "end-exec", | |
| 216 "equals", | |
| 217 "escape", | |
| 218 "every", | |
| 219 "except", | |
| 220 "exec", | |
| 221 "execute", | |
| 222 "exists", | |
| 223 "exp", | |
| 224 "external", | |
| 225 "extract", | |
| 226 "false", | |
| 227 "fetch", | |
| 228 "filter", | |
| 229 "first_value", | |
| 230 "float", | |
| 231 "floor", | |
| 232 "for", | |
| 233 "foreign", | |
| 234 "frame_row", | |
| 235 "free", | |
| 236 "from", | |
| 237 "full", | |
| 238 "function", | |
| 239 "fusion", | |
| 240 "get", | |
| 241 "global", | |
| 242 "grant", | |
| 243 "group", | |
| 244 "grouping", | |
| 245 "groups", | |
| 246 "having", | |
| 247 "hold", | |
| 248 "hour", | |
| 249 "identity", | |
| 250 "in", | |
| 251 "indicator", | |
| 252 "initial", | |
| 253 "inner", | |
| 254 "inout", | |
| 255 "insensitive", | |
| 256 "insert", | |
| 257 "int", | |
| 258 "integer", | |
| 259 "intersect", | |
| 260 "intersection", | |
| 261 "interval", | |
| 262 "into", | |
| 263 "is", | |
| 264 "join", | |
| 265 "json_array", | |
| 266 "json_arrayagg", | |
| 267 "json_exists", | |
| 268 "json_object", | |
| 269 "json_objectagg", | |
| 270 "json_query", | |
| 271 "json_table", | |
| 272 "json_table_primitive", | |
| 273 "json_value", | |
| 274 "lag", | |
| 275 "language", | |
| 276 "large", | |
| 277 "last_value", | |
| 278 "lateral", | |
| 279 "lead", | |
| 280 "leading", | |
| 281 "left", | |
| 282 "like", | |
| 283 "like_regex", | |
| 284 "listagg", | |
| 285 "ln", | |
| 286 "local", | |
| 287 "localtime", | |
| 288 "localtimestamp", | |
| 289 "log", | |
| 290 "log10", | |
| 291 "lower", | |
| 292 "match", | |
| 293 "match_number", | |
| 294 "match_recognize", | |
| 295 "matches", | |
| 296 "max", | |
| 297 "member", | |
| 298 "merge", | |
| 299 "method", | |
| 300 "min", | |
| 301 "minute", | |
| 302 "mod", | |
| 303 "modifies", | |
| 304 "module", | |
| 305 "month", | |
| 306 "multiset", | |
| 307 "national", | |
| 308 "natural", | |
| 309 "nchar", | |
| 310 "nclob", | |
| 311 "new", | |
| 312 "no", | |
| 313 "none", | |
| 314 "normalize", | |
| 315 "not", | |
| 316 "nth_value", | |
| 317 "ntile", | |
| 318 "null", | |
| 319 "nullif", | |
| 320 "numeric", | |
| 321 "octet_length", | |
| 322 "occurrences_regex", | |
| 323 "of", | |
| 324 "offset", | |
| 325 "old", | |
| 326 "omit", | |
| 327 "on", | |
| 328 "one", | |
| 329 "only", | |
| 330 "open", | |
| 331 "or", | |
| 332 "order", | |
| 333 "out", | |
| 334 "outer", | |
| 335 "over", | |
| 336 "overlaps", | |
| 337 "overlay", | |
| 338 "parameter", | |
| 339 "partition", | |
| 340 "pattern", | |
| 341 "per", | |
| 342 "percent", | |
| 343 "percent_rank", | |
| 344 "percentile_cont", | |
| 345 "percentile_disc", | |
| 346 "period", | |
| 347 "portion", | |
| 348 "position", | |
| 349 "position_regex", | |
| 350 "power", | |
| 351 "precedes", | |
| 352 "precision", | |
| 353 "prepare", | |
| 354 "primary", | |
| 355 "procedure", | |
| 356 "ptf", | |
| 357 "range", | |
| 358 "rank", | |
| 359 "reads", | |
| 360 "real", | |
| 361 "recursive", | |
| 362 "ref", | |
| 363 "references", | |
| 364 "referencing", | |
| 365 "regr_avgx", | |
| 366 "regr_avgy", | |
| 367 "regr_count", | |
| 368 "regr_intercept", | |
| 369 "regr_r2", | |
| 370 "regr_slope", | |
| 371 "regr_sxx", | |
| 372 "regr_sxy", | |
| 373 "regr_syy", | |
| 374 "release", | |
| 375 "result", | |
| 376 "return", | |
| 377 "returns", | |
| 378 "revoke", | |
| 379 "right", | |
| 380 "rollback", | |
| 381 "rollup", | |
| 382 "row", | |
| 383 "row_number", | |
| 384 "rows", | |
| 385 "running", | |
| 386 "savepoint", | |
| 387 "scope", | |
| 388 "scroll", | |
| 389 "search", | |
| 390 "second", | |
| 391 "seek", | |
| 392 "select", | |
| 393 "sensitive", | |
| 394 "session_user", | |
| 395 "set", | |
| 396 "show", | |
| 397 "similar", | |
| 398 "sin", | |
| 399 "sinh", | |
| 400 "skip", | |
| 401 "smallint", | |
| 402 "some", | |
| 403 "specific", | |
| 404 "specifictype", | |
| 405 "sql", | |
| 406 "sqlexception", | |
| 407 "sqlstate", | |
| 408 "sqlwarning", | |
| 409 "sqrt", | |
| 410 "start", | |
| 411 "static", | |
| 412 "stddev_pop", | |
| 413 "stddev_samp", | |
| 414 "submultiset", | |
| 415 "subset", | |
| 416 "substring", | |
| 417 "substring_regex", | |
| 418 "succeeds", | |
| 419 "sum", | |
| 420 "symmetric", | |
| 421 "system", | |
| 422 "system_time", | |
| 423 "system_user", | |
| 424 "table", | |
| 425 "tablesample", | |
| 426 "tan", | |
| 427 "tanh", | |
| 428 "then", | |
| 429 "time", | |
| 430 "timestamp", | |
| 431 "timezone_hour", | |
| 432 "timezone_minute", | |
| 433 "to", | |
| 434 "trailing", | |
| 435 "translate", | |
| 436 "translate_regex", | |
| 437 "translation", | |
| 438 "treat", | |
| 439 "trigger", | |
| 440 "trim", | |
| 441 "trim_array", | |
| 442 "true", | |
| 443 "truncate", | |
| 444 "uescape", | |
| 445 "union", | |
| 446 "unique", | |
| 447 "unknown", | |
| 448 "unnest", | |
| 449 "update", | |
| 450 "upper", | |
| 451 "user", | |
| 452 "using", | |
| 453 "value", | |
| 454 "values", | |
| 455 "value_of", | |
| 456 "var_pop", | |
| 457 "var_samp", | |
| 458 "varbinary", | |
| 459 "varchar", | |
| 460 "varying", | |
| 461 "versioning", | |
| 462 "when", | |
| 463 "whenever", | |
| 464 "where", | |
| 465 "width_bucket", | |
| 466 "window", | |
| 467 "with", | |
| 468 "within", | |
| 469 "without", | |
| 470 "year", | |
| 471 ]; | |
| 472 | |
| 473 // these are reserved words we have identified to be functions | |
| 474 // and should only be highlighted in a dispatch-like context | |
| 475 // ie, array_agg(...), etc. | |
| 476 const RESERVED_FUNCTIONS = [ | |
| 477 "abs", | |
| 478 "acos", | |
| 479 "array_agg", | |
| 480 "asin", | |
| 481 "atan", | |
| 482 "avg", | |
| 483 "cast", | |
| 484 "ceil", | |
| 485 "ceiling", | |
| 486 "coalesce", | |
| 487 "corr", | |
| 488 "cos", | |
| 489 "cosh", | |
| 490 "count", | |
| 491 "covar_pop", | |
| 492 "covar_samp", | |
| 493 "cume_dist", | |
| 494 "dense_rank", | |
| 495 "deref", | |
| 496 "element", | |
| 497 "exp", | |
| 498 "extract", | |
| 499 "first_value", | |
| 500 "floor", | |
| 501 "json_array", | |
| 502 "json_arrayagg", | |
| 503 "json_exists", | |
| 504 "json_object", | |
| 505 "json_objectagg", | |
| 506 "json_query", | |
| 507 "json_table", | |
| 508 "json_table_primitive", | |
| 509 "json_value", | |
| 510 "lag", | |
| 511 "last_value", | |
| 512 "lead", | |
| 513 "listagg", | |
| 514 "ln", | |
| 515 "log", | |
| 516 "log10", | |
| 517 "lower", | |
| 518 "max", | |
| 519 "min", | |
| 520 "mod", | |
| 521 "nth_value", | |
| 522 "ntile", | |
| 523 "nullif", | |
| 524 "percent_rank", | |
| 525 "percentile_cont", | |
| 526 "percentile_disc", | |
| 527 "position", | |
| 528 "position_regex", | |
| 529 "power", | |
| 530 "rank", | |
| 531 "regr_avgx", | |
| 532 "regr_avgy", | |
| 533 "regr_count", | |
| 534 "regr_intercept", | |
| 535 "regr_r2", | |
| 536 "regr_slope", | |
| 537 "regr_sxx", | |
| 538 "regr_sxy", | |
| 539 "regr_syy", | |
| 540 "row_number", | |
| 541 "sin", | |
| 542 "sinh", | |
| 543 "sqrt", | |
| 544 "stddev_pop", | |
| 545 "stddev_samp", | |
| 546 "substring", | |
| 547 "substring_regex", | |
| 548 "sum", | |
| 549 "tan", | |
| 550 "tanh", | |
| 551 "translate", | |
| 552 "translate_regex", | |
| 553 "treat", | |
| 554 "trim", | |
| 555 "trim_array", | |
| 556 "unnest", | |
| 557 "upper", | |
| 558 "value_of", | |
| 559 "var_pop", | |
| 560 "var_samp", | |
| 561 "width_bucket", | |
| 562 ]; | |
| 563 | |
| 564 // these functions can | |
| 565 const POSSIBLE_WITHOUT_PARENS = [ | |
| 566 "current_catalog", | |
| 567 "current_date", | |
| 568 "current_default_transform_group", | |
| 569 "current_path", | |
| 570 "current_role", | |
| 571 "current_schema", | |
| 572 "current_transform_group_for_type", | |
| 573 "current_user", | |
| 574 "session_user", | |
| 575 "system_time", | |
| 576 "system_user", | |
| 577 "current_time", | |
| 578 "localtime", | |
| 579 "current_timestamp", | |
| 580 "localtimestamp" | |
| 581 ]; | |
| 582 | |
| 583 // those exist to boost relevance making these very | |
| 584 // "SQL like" keyword combos worth +1 extra relevance | |
| 585 const COMBOS = [ | |
| 586 "create table", | |
| 587 "insert into", | |
| 588 "primary key", | |
| 589 "foreign key", | |
| 590 "not null", | |
| 591 "alter table", | |
| 592 "add constraint", | |
| 593 "grouping sets", | |
| 594 "on overflow", | |
| 595 "character set", | |
| 596 "respect nulls", | |
| 597 "ignore nulls", | |
| 598 "nulls first", | |
| 599 "nulls last", | |
| 600 "depth first", | |
| 601 "breadth first" | |
| 602 ]; | |
| 603 | |
| 604 const FUNCTIONS = RESERVED_FUNCTIONS; | |
| 605 | |
| 606 const KEYWORDS = [ | |
| 607 ...RESERVED_WORDS, | |
| 608 ...NON_RESERVED_WORDS | |
| 609 ].filter((keyword) => { | |
| 610 return !RESERVED_FUNCTIONS.includes(keyword); | |
| 611 }); | |
| 612 | |
| 613 const VARIABLE = { | |
| 614 scope: "variable", | |
| 615 match: /@[a-z0-9][a-z0-9_]*/, | |
| 616 }; | |
| 617 | |
| 618 const OPERATOR = { | |
| 619 scope: "operator", | |
| 620 match: /[-+*/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?/, | |
| 621 relevance: 0, | |
| 622 }; | |
| 623 | |
| 624 const FUNCTION_CALL = { | |
| 625 match: regex.concat(/\b/, regex.either(...FUNCTIONS), /\s*\(/), | |
| 626 relevance: 0, | |
| 627 keywords: { built_in: FUNCTIONS } | |
| 628 }; | |
| 629 | |
| 630 // turns a multi-word keyword combo into a regex that doesn't | |
| 631 // care about extra whitespace etc. | |
| 632 // input: "START QUERY" | |
| 633 // output: /\bSTART\s+QUERY\b/ | |
| 634 function kws_to_regex(list) { | |
| 635 return regex.concat( | |
| 636 /\b/, | |
| 637 regex.either(...list.map((kw) => { | |
| 638 return kw.replace(/\s+/, "\\s+") | |
| 639 })), | |
| 640 /\b/ | |
| 641 ) | |
| 642 } | |
| 643 | |
| 644 const MULTI_WORD_KEYWORDS = { | |
| 645 scope: "keyword", | |
| 646 match: kws_to_regex(COMBOS), | |
| 647 relevance: 0, | |
| 648 }; | |
| 649 | |
| 650 // keywords with less than 3 letters are reduced in relevancy | |
| 651 function reduceRelevancy(list, { | |
| 652 exceptions, when | |
| 653 } = {}) { | |
| 654 const qualifyFn = when; | |
| 655 exceptions = exceptions || []; | |
| 656 return list.map((item) => { | |
| 657 if (item.match(/\|\d+$/) || exceptions.includes(item)) { | |
| 658 return item; | |
| 659 } else if (qualifyFn(item)) { | |
| 660 return `${item}|0`; | |
| 661 } else { | |
| 662 return item; | |
| 663 } | |
| 664 }); | |
| 665 } | |
| 666 | |
| 667 return { | |
| 668 name: 'SQL', | |
| 669 case_insensitive: true, | |
| 670 // does not include {} or HTML tags `</` | |
| 671 illegal: /[{}]|<\//, | |
| 672 keywords: { | |
| 673 $pattern: /\b[\w\.]+/, | |
| 674 keyword: | |
| 675 reduceRelevancy(KEYWORDS, { when: (x) => x.length < 3 }), | |
| 676 literal: LITERALS, | |
| 677 type: TYPES, | |
| 678 built_in: POSSIBLE_WITHOUT_PARENS | |
| 679 }, | |
| 680 contains: [ | |
| 681 { | |
| 682 scope: "type", | |
| 683 match: kws_to_regex(MULTI_WORD_TYPES) | |
| 684 }, | |
| 685 MULTI_WORD_KEYWORDS, | |
| 686 FUNCTION_CALL, | |
| 687 VARIABLE, | |
| 688 STRING, | |
| 689 QUOTED_IDENTIFIER, | |
| 690 hljs.C_NUMBER_MODE, | |
| 691 hljs.C_BLOCK_COMMENT_MODE, | |
| 692 COMMENT_MODE, | |
| 693 OPERATOR | |
| 694 ] | |
| 695 }; | |
| 696 } | |
| 697 | |
| 698 return sql; | |
| 699 | |
| 700 })(); | |
| 701 | |
| 702 hljs.registerLanguage('sql', hljsGrammar); | |
| 703 })(); |