Skip to content

Commit

Permalink
fix(sql) fix multi-word combos with flexible spacing (#4106)
Browse files Browse the repository at this point in the history
Co-authored-by: Josh Goebel <[email protected]>
  • Loading branch information
Dxuian and joshgoebel authored Sep 30, 2024
1 parent 0af0968 commit ff3985d
Show file tree
Hide file tree
Showing 4 changed files with 268 additions and 20 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Core Grammars:
- fix(c) - Fixed hex numbers with decimals [Dxuian]
- fix(typescript) - Fixedoptional property not highlighted correctly [Dxuian]
- fix(ruby) - fix `|=` operator false positives (as block arguments) [Aboobacker MK]
- fix(sql) - Fixed sql primary key and foreign key spacing issue [Dxuian]

New Grammars:

Expand Down
51 changes: 31 additions & 20 deletions src/languages/sql.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,19 @@ export default function(hljs) {
const regex = hljs.regex;
const COMMENT_MODE = hljs.COMMENT('--', '$');
const STRING = {
className: 'string',
scope: 'string',
variants: [
{
begin: /'/,
end: /'/,
contains: [ { begin: /''/ } ]
contains: [ { match: /''/ } ]
}
]
};
const QUOTED_IDENTIFIER = {
begin: /"/,
end: /"/,
contains: [ { begin: /""/ } ]
contains: [ { match: /""/ } ]
};

const LITERALS = [
Expand Down Expand Up @@ -606,22 +606,42 @@ export default function(hljs) {
});

const VARIABLE = {
className: "variable",
begin: /@[a-z0-9][a-z0-9_]*/,
scope: "variable",
match: /@[a-z0-9][a-z0-9_]*/,
};

const OPERATOR = {
className: "operator",
begin: /[-+*/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?/,
scope: "operator",
match: /[-+*/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?/,
relevance: 0,
};

const FUNCTION_CALL = {
begin: regex.concat(/\b/, regex.either(...FUNCTIONS), /\s*\(/),
match: regex.concat(/\b/, regex.either(...FUNCTIONS), /\s*\(/),
relevance: 0,
keywords: { built_in: FUNCTIONS }
};

// turns a multi-word keyword combo into a regex that doesn't
// care about extra whitespace etc.
// input: "START QUERY"
// output: /\bSTART\s+QUERY\b/
function kws_to_regex(list) {
return regex.concat(
/\b/,
regex.either(...list.map((kw) => {
return kw.replace(/\s+/, "\\s+")
})),
/\b/
)
}

const MULTI_WORD_KEYWORDS = {
scope: "keyword",
match: kws_to_regex(COMBOS),
relevance: 0,
};

// keywords with less than 3 letters are reduced in relevancy
function reduceRelevancy(list, {
exceptions, when
Expand Down Expand Up @@ -654,19 +674,10 @@ export default function(hljs) {
},
contains: [
{
begin: regex.either(...COMBOS),
relevance: 0,
keywords: {
$pattern: /[\w\.]+/,
keyword: KEYWORDS.concat(COMBOS),
literal: LITERALS,
type: TYPES
},
},
{
className: "type",
begin: regex.either(...MULTI_WORD_TYPES)
scope: "type",
match: kws_to_regex(MULTI_WORD_TYPES)
},
MULTI_WORD_KEYWORDS,
FUNCTION_CALL,
VARIABLE,
STRING,
Expand Down
118 changes: 118 additions & 0 deletions test/markup/sql/combos.expect.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<span class="hljs-comment">-- Basic Table with a Single Primary Key</span>
<span class="hljs-keyword">CREATE TABLE</span> users (
id <span class="hljs-type">INT</span> <span class="hljs-keyword">PRIMARY KEY</span>,
username <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">50</span>),
email <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">100</span>)
);

<span class="hljs-comment">-- Table with Composite Primary Key</span>
<span class="hljs-keyword">CREATE TABLE</span> orders (
order_id <span class="hljs-type">INT</span>,
user_id <span class="hljs-type">INT</span>,
<span class="hljs-keyword">PRIMARY KEY</span> (order_id, user_id)
);

<span class="hljs-comment">-- Table with Primary Key and Auto Increment</span>
<span class="hljs-keyword">CREATE TABLE</span> products (
product_id <span class="hljs-type">INT</span> <span class="hljs-keyword">PRIMARY KEY</span> AUTO_INCREMENT,
name <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">100</span>),
price <span class="hljs-type">DECIMAL</span>(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>)
);

<span class="hljs-comment">-- Table with Primary Key and Foreign Key</span>
<span class="hljs-keyword">CREATE TABLE</span> order_items (
item_id <span class="hljs-type">INT</span>,
order_id <span class="hljs-type">INT</span>,
product_id <span class="hljs-type">INT</span>,
<span class="hljs-keyword">PRIMARY KEY</span> (item_id),
<span class="hljs-keyword">FOREIGN KEY</span> (order_id) <span class="hljs-keyword">REFERENCES</span> orders(order_id)
);

<span class="hljs-comment">-- Table with Date and Primary Key</span>
<span class="hljs-keyword">CREATE TABLE</span> events (
event_id <span class="hljs-type">INT</span> <span class="hljs-keyword">PRIMARY KEY</span>,
event_name <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">100</span>),
event_date <span class="hljs-type">DATE</span>
);

<span class="hljs-comment">-- Basic Table with a Single Primary Key</span>
<span class="hljs-keyword">CREATE
TABLE</span>
users
(
id
<span class="hljs-type">INT</span>
<span class="hljs-keyword">PRIMARY
KEY</span>,
username
<span class="hljs-type">VARCHAR</span>(<span class="hljs-number">50</span>),
email
<span class="hljs-type">VARCHAR</span>(<span class="hljs-number">100</span>)
);

<span class="hljs-comment">-- Table with Composite Primary Key</span>
<span class="hljs-keyword">CREATE
TABLE</span>
orders
(
order_id
<span class="hljs-type">INT</span>,
user_id
<span class="hljs-type">INT</span>,
<span class="hljs-keyword">PRIMARY
KEY</span>
(order_id,
user_id)
);

<span class="hljs-comment">-- Table with Primary Key and Auto Increment</span>
<span class="hljs-keyword">CREATE
TABLE</span>
products
(
product_id
<span class="hljs-type">INT</span>
<span class="hljs-keyword">PRIMARY
KEY</span>
AUTO_INCREMENT,
name
<span class="hljs-type">VARCHAR</span>(<span class="hljs-number">100</span>),
price
<span class="hljs-type">DECIMAL</span>(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>)
);

<span class="hljs-comment">-- Table with Primary Key and Foreign Key</span>
<span class="hljs-keyword">CREATE
TABLE</span>
order_items
(
item_id
<span class="hljs-type">INT</span>,
order_id
<span class="hljs-type">INT</span>,
product_id
<span class="hljs-type">INT</span>,
<span class="hljs-keyword">PRIMARY
KEY</span>
(item_id),
<span class="hljs-keyword">FOREIGN
KEY</span>
(order_id)
<span class="hljs-keyword">REFERENCES</span>
orders(order_id)
);

<span class="hljs-comment">-- Table with Date and Primary Key</span>
<span class="hljs-keyword">CREATE
TABLE</span>
events
(
event_id
<span class="hljs-type">INT</span>
<span class="hljs-keyword">PRIMARY
KEY</span>,
event_name
<span class="hljs-type">VARCHAR</span>(<span class="hljs-number">100</span>),
event_date
<span class="hljs-type">DATE</span> <span class="hljs-type">with timezone</span>
);
118 changes: 118 additions & 0 deletions test/markup/sql/combos.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
-- Basic Table with a Single Primary Key
CREATE TABLE users (
id INT PRIMARY KEY,
username VARCHAR(50),
email VARCHAR(100)
);

-- Table with Composite Primary Key
CREATE TABLE orders (
order_id INT,
user_id INT,
PRIMARY KEY (order_id, user_id)
);

-- Table with Primary Key and Auto Increment
CREATE TABLE products (
product_id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100),
price DECIMAL(10, 2)
);

-- Table with Primary Key and Foreign Key
CREATE TABLE order_items (
item_id INT,
order_id INT,
product_id INT,
PRIMARY KEY (item_id),
FOREIGN KEY (order_id) REFERENCES orders(order_id)
);

-- Table with Date and Primary Key
CREATE TABLE events (
event_id INT PRIMARY KEY,
event_name VARCHAR(100),
event_date DATE
);

-- Basic Table with a Single Primary Key
CREATE
TABLE
users
(
id
INT
PRIMARY
KEY,
username
VARCHAR(50),
email
VARCHAR(100)
);

-- Table with Composite Primary Key
CREATE
TABLE
orders
(
order_id
INT,
user_id
INT,
PRIMARY
KEY
(order_id,
user_id)
);

-- Table with Primary Key and Auto Increment
CREATE
TABLE
products
(
product_id
INT
PRIMARY
KEY
AUTO_INCREMENT,
name
VARCHAR(100),
price
DECIMAL(10, 2)
);

-- Table with Primary Key and Foreign Key
CREATE
TABLE
order_items
(
item_id
INT,
order_id
INT,
product_id
INT,
PRIMARY
KEY
(item_id),
FOREIGN
KEY
(order_id)
REFERENCES
orders(order_id)
);

-- Table with Date and Primary Key
CREATE
TABLE
events
(
event_id
INT
PRIMARY
KEY,
event_name
VARCHAR(100),
event_date
DATE with timezone
);

0 comments on commit ff3985d

Please sign in to comment.