Repository: DerekStride/tree-sitter-sql (language: python)

Issue:
Adding missing SQL Server keywords
Would it be possible to have this parser also include [SQL Server specific keywords](https://learn.microsoft.com/en-us/sql/t-sql/language-reference?view=sql-server-ver16), for example:

NVARCHAR
NCHAR
DATETIME2
DATETIMEOFFSET
SMALLDATETIME
TIME
SMALLMONEY
VARBINARY
IMAGE

Also, some functions are missing, for example: 

OBJECT_ID

I assume others too, this is the only one I checked :)

I can also write a PR for this if that's an issue.

Thanks! ❤️


Discussion / hints:
types absolutely! As for functions, we've been moving away from special-casing those -- for example, there's no standalone `count` or `rank` anymore. `object_id` should already resolve as an `invocation` afaik, and that'll have the `name` field.
NVARCHAR/NCHAR as a type is easy, but referencing it might be a bit more challenging:
```
SELECT * FROM tab WHERE  col = N'BLUBB' 
```

Fix patch:
diff --git a/grammar.js b/grammar.js
index 51f17f1f..49642592 100644
--- a/grammar.js
+++ b/grammar.js
@@ -332,6 +332,8 @@ module.exports = grammar({
     keyword_boolean: _ => make_keyword("boolean"),
     keyword_bit: _ => make_keyword("bit"),
     keyword_binary: _ => make_keyword("binary"),
+    keyword_varbinary: _ => make_keyword("varbinary"),
+    keyword_image: _ => make_keyword("image"),
 
     keyword_smallserial: _ => choice(make_keyword("smallserial"),make_keyword("serial2")),
     keyword_serial: _ => choice(make_keyword("serial"),make_keyword("serial4")),
@@ -350,9 +352,11 @@ module.exports = grammar({
     keyword_inet: _ => make_keyword("inet"),
 
     keyword_money: _ => make_keyword("money"),
+    keyword_smallmoney: _ => make_keyword("smallmoney"),
     keyword_varying: _ => make_keyword("varying"),
 
     keyword_char: _ => choice(make_keyword("char"), make_keyword("character")),
+    keyword_nchar: _ => make_keyword("nchar"),
     keyword_varchar: $ => choice(
       make_keyword("varchar"),
       seq(
@@ -360,6 +364,7 @@ module.exports = grammar({
         $.keyword_varying,
       )
     ),
+    keyword_nvarchar: _ => make_keyword("nvarchar"),
     keyword_text: _ => make_keyword("text"),
     keyword_string: _ => make_keyword("string"),
     keyword_uuid: _ => make_keyword("uuid"),
@@ -374,6 +379,10 @@ module.exports = grammar({
 
     keyword_date: _ => make_keyword("date"),
     keyword_datetime: _ => make_keyword("datetime"),
+    keyword_datetime2: _ => make_keyword("datetime2"),
+    keyword_smalldatetime: _ => make_keyword("smalldatetime"),
+    keyword_datetimeoffset: _ => make_keyword("datetimeoffset"),
+    keyword_time: _ => make_keyword("time"),
     keyword_timestamp: _ => prec.right(
       seq(
         make_keyword("timestamp"),
@@ -415,7 +424,9 @@ module.exports = grammar({
       choice(
         $.keyword_boolean,
         $.bit,
-        $.keyword_binary,
+        $.binary,
+        $.varbinary,
+        $.keyword_image,
 
         $.keyword_smallserial,
         $.keyword_serial,
@@ -432,9 +443,12 @@ module.exports = grammar({
         $.float,
 
         $.keyword_money,
+        $.keyword_smallmoney,
 
         $.char,
         $.varchar,
+        $.nchar,
+        $.nvarchar,
         $.numeric,
         $.keyword_string,
         $.keyword_text,
@@ -452,6 +466,10 @@ module.exports = grammar({
 
         $.keyword_date,
         $.keyword_datetime,
+        $.keyword_datetime2,
+        $.datetimeoffset,
+        $.keyword_smalldatetime,
+        $.time,
         $.keyword_timestamp,
         $.keyword_timestamptz,
         $.keyword_interval,
@@ -501,6 +519,9 @@ module.exports = grammar({
         prec(1, parametric_type($, $.keyword_bit, ['precision'])),
     ),
 
+    binary: $ => parametric_type($, $.keyword_binary, ['precision']),
+    varbinary: $ => parametric_type($, $.keyword_varbinary, ['precision']),
+
     // TODO: should qualify against /\\b(0?[1-9]|[1-4][0-9]|5[0-4])\\b/g
     float: $  => choice(
       parametric_type($, $.keyword_float, ['precision']),
@@ -524,6 +545,11 @@ module.exports = grammar({
     ),
     char: $ => parametric_type($, $.keyword_char),
     varchar: $ => parametric_type($, $.keyword_varchar),
+    nchar: $ => parametric_type($, $.keyword_nchar),
+    nvarchar: $ => parametric_type($, $.keyword_nvarchar),
+
+    datetimeoffset: $ => parametric_type($, $.keyword_datetimeoffset),
+    time: $ => parametric_type($, $.keyword_time),
 
     enum: $ => seq(
       $.keyword_enum,
diff --git a/queries/highlights.scm b/queries/highlights.scm
index 99e33b3a..fdd42238 100644
--- a/queries/highlights.scm
+++ b/queries/highlights.scm
@@ -294,6 +294,8 @@
   (keyword_null)
   (keyword_boolean)
   (keyword_binary)
+  (keyword_varbinary)
+  (keyword_image)
   (keyword_bit)
   (keyword_inet)
   (keyword_character)
@@ -311,8 +313,11 @@
   (keyword_real)
   (double)
   (keyword_money)
+  (keyword_smallmoney)
   (keyword_char)
+  (keyword_nchar)
   (keyword_varchar)
+  (keyword_nvarchar)
   (keyword_varying)
   (keyword_text)
   (keyword_string)
@@ -324,6 +329,10 @@
   (keyword_enum)
   (keyword_date)
   (keyword_datetime)
+  (keyword_time)
+  (keyword_datetime2)
+  (keyword_datetimeoffset)
+  (keyword_smalldatetime)
   (keyword_timestamp)
   (keyword_timestamptz)
   (keyword_geometry)


Test patch:
diff --git a/test/corpus/create.txt b/test/corpus/create.txt
index 69a58ab7..69006142 100644
--- a/test/corpus/create.txt
+++ b/test/corpus/create.txt
@@ -799,6 +799,9 @@ CREATE TABLE type_test (
   a_bit BIT,
   a_bit2 BIT(2),
   a_bit3 BIT VARYING(2),
+  a_binary BINARY,
+  a_varbinary VARBINARY,
+  a_image IMAGE,
   a_smallser SMALLSERIAL,
   a_serial SERIAL,
   a_bigser BIGSERIAL,
@@ -814,10 +817,15 @@ CREATE TABLE type_test (
   a_real REAL,
   a_double_precision DOUBLE PRECISION,
   a_money MONEY,
+  a_smallmoney SMALLMONEY,
   a_char CHAR,
+  a_nchar NCHAR,
+  a_nchar_precision NCHAR(8),
   a_character CHARACTER,
   a_sized_char CHAR (10),
   a_varchar VARCHAR (10),
+  a_nvarchar NVARCHAR,
+  a_nvarchar_precision NVARCHAR (10),
   a_character_varying CHARACTER VARYING (10),
   a_text TEXT,
   a_json JSON,
@@ -827,6 +835,10 @@ CREATE TABLE type_test (
   a_enum ENUM('one','two','three'),
   a_date DATE,
   a_datetime DATETIME,
+  a_datetime2 DATETIME2,
+  a_datetimeoffset DATETIMEOFFSET,
+  a_smalldatetime SMALLDATE,
+  a_time TIME,
   a_timestamp TIMESTAMP,
   a_verbose_timestamp TIMESTAMP WITHOUT TIME ZONE,
   a_tstz TIMESTAMPTZ,
@@ -867,6 +879,17 @@ CREATE TABLE type_test (
             (keyword_bit)
             (keyword_varying)
             precision: (literal)))
+        (column_definition
+          name: (identifier)
+          type: (binary
+            (keyword_binary)))
+        (column_definition
+          name: (identifier)
+          type: (varbinary
+            (keyword_varbinary)))
+        (column_definition
+          name: (identifier)
+          type: (keyword_image))
         (column_definition
           name: (identifier)
           type: (keyword_smallserial))
@@ -930,10 +953,22 @@ CREATE TABLE type_test (
         (column_definition
           name: (identifier)
           type: (keyword_money))
+        (column_definition
+          name: (identifier)
+          type: (keyword_smallmoney))
         (column_definition
           name: (identifier)
           type: (char
             (keyword_char)))
+        (column_definition
+          name: (identifier)
+          type: (nchar
+            (keyword_nchar)))
+        (column_definition
+          name: (identifier)
+          type: (nchar
+            (keyword_nchar)
+            size: (literal)))
         (column_definition
           name: (identifier)
           type: (char
@@ -948,6 +983,15 @@ CREATE TABLE type_test (
           type: (varchar
             (keyword_varchar)
             size: (literal)))
+        (column_definition
+          name: (identifier)
+          type: (nvarchar
+            (keyword_nvarchar)))
+        (column_definition
+          name: (identifier)
+          type: (nvarchar
+            (keyword_nvarchar)
+            size: (literal)))
         (column_definition
           name: (identifier)
           type: (varchar
@@ -982,6 +1026,19 @@ CREATE TABLE type_test (
         (column_definition
           name: (identifier)
           type: (keyword_datetime))
+        (column_definition
+          name: (identifier)
+          type: (keyword_datetime2))
+        (column_definition
+          name: (identifier)
+          type: (datetimeoffset
+            (keyword_datetimeoffset)))
+        (column_definition
+          name: (identifier))
+        (column_definition
+          name: (identifier)
+          type: (time
+            (keyword_time)))
         (column_definition
           name: (identifier)
           type: (keyword_timestamp))
@@ -1401,7 +1458,8 @@ CACHED IN 'pool1' WITH REPLICATION = 2
           type: (keyword_string))
         (column_definition
           name: (identifier)
-          type: (keyword_binary)))
+          type: (binary
+            (keyword_binary))))
       (table_partition
         (keyword_partitioned)
         (keyword_by)