diff --git a/Markdown/syntax_test_markdown.md b/Markdown/syntax_test_markdown.md index f78401f115..a2cc25873d 100644 --- a/Markdown/syntax_test_markdown.md +++ b/Markdown/syntax_test_markdown.md @@ -2578,8 +2578,8 @@ okay ```sql |^^^^^ meta.code-fence.definition.begin.sql | ^^^ constant.other.language-name -SELECT 10 * -|^^^^^^^^^^^ markup.raw.code-fence.sql +SELECT * +|^^^^^^^^ markup.raw.code-fence.sql |^^^^^ keyword.other.DML.sql FROM TableName ``` diff --git a/PHP/tests/syntax_test_php.php b/PHP/tests/syntax_test_php.php index db38593122..07138d93d4 100644 --- a/PHP/tests/syntax_test_php.php +++ b/PHP/tests/syntax_test_php.php @@ -1639,12 +1639,12 @@ function generate2() // ^ meta.string.php string.quoted.double.php punctuation.definition.string.begin.php - meta.interpolation - string string // ^^^^^^^^^^^^^^^^^^^^ meta.string.php meta.interpolation.php source.sql - string.quoted.double.php // ^ meta.string.php string.quoted.double.php punctuation.definition.string.end.php - meta.interpolation - string string -// ^^^^^^ keyword.other.create.sql +// ^^^^^^ keyword.other.ddl.sql $sql = " CREATE TABLE `version`... // ^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.php meta.interpolation.php source.sql - string.quoted.double.php -// ^^^^^^ keyword.other.create.sql +// ^^^^^^ keyword.other.ddl.sql "; // Do not highlight plain SQL indicator as SQL diff --git a/SQL/SQL (basic).sublime-syntax b/SQL/SQL (basic).sublime-syntax index 299e5b0c46..aac30abee1 100644 --- a/SQL/SQL (basic).sublime-syntax +++ b/SQL/SQL (basic).sublime-syntax @@ -9,6 +9,7 @@ variables: string_escape: (?:\\.) simple_identifier: (?:\w+) dml_targets: (?i:aggregate|conversion|database|domain|function|group|((?:fulltext|spatial|unique)\s+)?index|language|operator class|operator|procedure|rule|schema|sequence|table(?:space)?|trigger|type|user|view) + reserved: (?i:\b(?:from|order|group|select|where|inner|outer|left|right|join|on|set|;|with)\b) contexts: prototype: @@ -132,7 +133,7 @@ contexts: drop-condition: - include: dml-condition - match: (?=\S) - pop: true + set: single-identifier-after-whitespace dml-condition: - match: (?i:\b(if)\b) @@ -228,31 +229,20 @@ contexts: ddl-statements: - match: \b(?i:create(?:\s+or\s+replace)?)\b - scope: keyword.other.create.sql + scope: keyword.other.ddl.sql push: ddl-create-target - - match: (?i:\s*\b(drop)\s+({{dml_targets}})) - scope: meta.drop.sql - captures: - 1: keyword.other.create.sql - 2: keyword.other.sql - push: drop-condition - - match: (?i:\s*(drop)\s+(table)\s+(\w+)(\s+cascade)?\b) - scope: meta.drop.sql - captures: - 1: keyword.other.create.sql - 2: keyword.other.table.sql - 3: entity.name.function.sql - 4: keyword.other.cascade.sql - - match: (?i:\s*\b(alter)\s+({{dml_targets}})\s+) - scope: meta.alter.sql - captures: - 1: keyword.other.create.sql - 2: keyword.other.table.sql - - match: (?i:\s*\b(add)\s+(column|constraint|fulltext\s+(index|key)|index|spatial\s+(index|key))) - scope: meta.add.sql - captures: - 1: keyword.other.add.sql - 2: keyword.other.sql + - match: (?i:\bdrop\s+table\b) + scope: keyword.other.ddl.sql + push: ddl-drop-table + - match: \b(?i:drop)\b + scope: keyword.other.ddl.sql + push: ddl-drop-target + - match: \b(?i:alter\s+table)\b + scope: keyword.other.ddl.sql + push: [ddl-alter-table, table-name, single-identifier-after-whitespace] + - match: \b(?i:alter)\b + scope: keyword.other.ddl.sql + push: ddl-alter-target - match: (?i:\b(((?:foreign|fulltext|primary|unique)\s+)?key|references|on\sdelete(\s+cascade)?|on\supdate(\s+cascade)?|check|constraint|default)\b) scope: storage.modifier.sql - match: (?i:\b(grant(\swith\sgrant\soption)?|revoke)\b) @@ -270,6 +260,46 @@ contexts: - match: (?=\S) pop: true + ddl-drop-target: + - meta_scope: meta.drop.sql + - match: |- + (?xi) + \b{{dml_targets}}\b + captures: + 1: keyword.other.sql + set: drop-condition + - match: (?=\S) + set: drop-condition + + ddl-drop-table: + - meta_scope: meta.drop.sql + - include: dml-condition + - match: (?=\S) + set: [table-name, single-identifier-after-whitespace] + + ddl-alter-table: + - meta_scope: meta.alter.sql + - match: \b(?i:add(?:\s+column)?|alter\s+column)\b + scope: keyword.other.ddl.sql + push: [column-alias, single-identifier-after-whitespace] + - include: expressions + - include: ddl-alter-common + - match: (?=\S) + pop: true + + ddl-alter-target: + - meta_scope: meta.alter.sql + - include: ddl-alter-common + - match: (?=\S) + pop: true + + ddl-alter-common: + - match: (?i:\s*\b(add)\s+(constraint|(?:fulltext|spatial)\s+(index|key)|index)) + scope: meta.add.sql + captures: + 1: keyword.other.add.sql + 2: keyword.other.sql + dml-statements: - match: (?i:\bselect\b) scope: keyword.other.DML.sql @@ -278,8 +308,9 @@ contexts: - match: (?i:\b(?:insert\s+into|update|delete(?:\s+from)?|truncate)\b) scope: keyword.other.DML.sql push: [table-name, single-identifier-after-whitespace] - - match: (?i:\b(?:set|with)\b) + - match: (?i:\bset\b) scope: keyword.other.DML.sql + push: set - match: (?i:\bvalues\b) scope: keyword.other.DML.II.sql - include: joins @@ -292,13 +323,11 @@ contexts: push: maybe-subquery - match: (?i)\b(asc|desc)\b scope: keyword.other.order.sql - - match: (?i)\bon\b - scope: keyword.operator.join.sql joins: - match: (?i)\b(?:inner|(?:full\s+)?outer|cross|left|right)\s+join\b scope: keyword.other.DML.sql - push: maybe-subquery + push: [join-on, maybe-subquery] column-alias: - meta_content_scope: meta.column-name.sql constant.other.placeholder.sql @@ -325,7 +354,27 @@ contexts: table-alias: - match: \b(?i:as)\b scope: keyword.operator.assignment.alias.sql - - match: (?i)(?=\b(?:from|order|group|select|where|inner|outer|left|right|join|on|set|;|with)\b) + - match: (?={{reserved}}) + pop: true + - match: (?=\S) + set: [after-table-alias, table-name, single-identifier] + + after-table-alias: + - match: (?=\S) + pop: true + + join-on: + - match: (?i)\bon\b + scope: keyword.operator.join.sql + push: [join-operators, column-alias, single-identifier-after-whitespace] + - match: (?=\S) pop: true + + join-operators: + - include: operators - match: (?=\S) - set: [table-name, single-identifier] + set: [column-alias, single-identifier-after-whitespace] + + set: + - match: (?=\S) + pop: true diff --git a/SQL/TSQL.sublime-syntax b/SQL/TSQL.sublime-syntax index 0f7a74cb3d..7247f0e6ed 100644 --- a/SQL/TSQL.sublime-syntax +++ b/SQL/TSQL.sublime-syntax @@ -161,7 +161,7 @@ contexts: types: - meta_append: true - - match: (?i:\b(?:smallint|sysname)\b) + - match: (?i:\b(?:smallint|sysname|uniqueidentifier|decimal)\b) scope: storage.type.sql statements: @@ -207,7 +207,8 @@ contexts: scope: keyword.control.conditional.case.sql push: inside-case-expression - include: variables - - match: \b(?i:output|nowait)\b + - include: with + - match: \b(?i:output|over|partition\s+by)\b scope: keyword.other.sql - match: \b(?i:cursor\s+for|open|fetch(?:(?:\s+next)?\s+from)?|close|deallocate)\b scope: keyword.other.sql @@ -264,3 +265,40 @@ contexts: set: [cursor-name, single-identifier] - match: (?=\S) pop: true + + set: + - meta_prepend: true + - match: \b(?i:nocount)\b + scope: constant.language.switch.tsql + - match: \b(?i:on|off)\b + scope: constant.language.boolean.tsql + - match: (?=\S) + pop: true + + after-table-alias: + - meta_prepend: true + - include: with + + with: + - match: (?i)\bwith\b + scope: keyword.other.DML.sql + push: with-paren + + with-paren: + - match: \( + scope: punctuation.section.group.begin.sql + set: inside-with-group + - match: \b(?i:nowait)\b + scope: keyword.other.tsql + - match: (?=\S) + pop: true + + inside-with-group: + - meta_scope: meta.group.sql + - match: \) + scope: punctuation.section.group.end.sql + pop: true + - match: \w+ + scope: constant.language.with.tsql + - match: ',' + scope: punctuation.separator.sequence.tsql diff --git a/SQL/syntax_test_mysql.sql b/SQL/syntax_test_mysql.sql index 5651a832fc..1d5d894faf 100644 --- a/SQL/syntax_test_mysql.sql +++ b/SQL/syntax_test_mysql.sql @@ -20,35 +20,35 @@ SELECT "My /* Crazy Column Name" FROM my_table; ;CREATE TABLE foo (id INTEGER PRIMARY KEY); - -- <- keyword.other.create ---^^^^^ keyword.other.create + -- <- meta.create keyword.other.ddl +--^^^^^ keyword.other.ddl -- ^^^^^ keyword.other -- ^^^ entity.name.function -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - entity.name.function create table some_schema.test2( id serial ); ---^^^^ meta.create keyword.other.create +--^^^^ meta.create keyword.other.ddl -- ^^^^^ meta.create keyword.other -- ^^^^^^^^^^^^^^^^^ entity.name.function -- ^ punctuation.accessor.dot -- ^^^^^^^^^^^^^^ - entity.name.function create table some_schema . test2 ( id serial ); ---^^^^ meta.create keyword.other.create +--^^^^ meta.create keyword.other.ddl -- ^^^^^ meta.create keyword.other -- ^^^^^^^^^^^^^^^^^^^ entity.name -- ^ punctuation.accessor.dot -- ^^^^^^^^^^^^^^^ - entity.name.function create table "testing123" (id integer); ---^^^^ meta.create keyword.other.create +--^^^^ meta.create keyword.other.ddl -- ^^^^^ meta.create keyword.other -- ^ punctuation.definition.identifier.begin -- ^^^^^^^^^^ entity.name.function -- ^ punctuation.definition.identifier.end create table `dbo`."testing123" (id integer); ---^^^^ meta.create keyword.other.create +--^^^^ meta.create keyword.other.ddl -- ^^^^^ meta.create keyword.other -- ^^^^^^^^^^^^^^^^^^ entity.name.function -- ^ punctuation.accessor.dot @@ -130,18 +130,22 @@ create fulltext index if not exists `myindex` ON mytable; -- ^^^^^^^^^^^^^^ keyword.other.sql ALTER TABLE dbo.testing123 ADD COLUMN mycolumn longtext; --- ^^ keyword.other --- ^^^^^ keyword.other.table --- ^^^ keyword.other.add.sql --- ^^^^^^ keyword.other.sql +-- ^^^^^^^^ meta.alter keyword.other.ddl +-- ^^^ keyword.other.ddl.sql +-- ^^^^^^ keyword.other.ddl.sql +-- ^^^^^^^^ meta.alter meta.column-name constant.other.placeholder -- ^^^^^^^^ storage.type.sql ALTER TABLE testing123 CHANGE COLUMN mycolumn mycolumn ENUM('foo', 'bar'); -- ^^^^ storage.type.sql DROP TABLE IF EXISTS testing123; --- <- meta.drop.sql keyword.other.create.sql +-- <- meta.drop.sql keyword.other.ddl.sql +-- ^^^^^^^ meta.drop keyword.other.ddl +-- ^^ meta.drop keyword.control.flow -- ^^^^^^ keyword.operator.logical.sql +-- ^^^^^^^^^^ meta.table-name constant.other.placeholder +-- ^ punctuation.terminator.statement select * from some_table diff --git a/SQL/syntax_test_tsql.sql b/SQL/syntax_test_tsql.sql index 9d6535be32..64f451b383 100644 --- a/SQL/syntax_test_tsql.sql +++ b/SQL/syntax_test_tsql.sql @@ -267,12 +267,16 @@ DEALLOCATE db_cursor DECLARE @FileExists INT SET NOCOUNT ON --- ^^ keyword +--^ keyword.other.DML +-- ^^^^^^^ constant.language.switch +-- ^^ constant.language.boolean EXEC master.dbo.xp_fileexist @FromFile, @FileExists OUTPUT -- ^ keyword.control.flow -- ^^^^^^ keyword.other SET NOCOUNT OFF --- ^^^ keyword.other +--^ keyword.other.DML +-- ^^^^^^^ constant.language.switch +-- ^^^ constant.language.boolean IF @FileExists = 0 BEGIN RAISERROR ('File "%s" does not exist', 16, -1, @FromFile) @@ -370,7 +374,8 @@ from (select * from some_table) alias_table WITH (NOLOCK) -- ^ punctuation.section.group.end -- ^^^^^^^^^^^ meta.table-name constant.other.placeholder -- ^^^^ keyword.other.DML --- ^ meta.group punctuation.section.group.begin +-- ^ punctuation.section.group.begin +-- ^^^^^^ meta.group constant.language.with -- ^ punctuation.section.group.end where exists(select * from other_table where id = some_table.id) -- ^^^^^^ keyword.operator.logical @@ -383,19 +388,34 @@ SET column1 = v.column1, --^ keyword.other.DML column2 = 'testing123 TODO: assert the = operator is scoped as assignment instead of comparison' -- ^ keyword.operator -FROM RealTableName TableAlias WITH (UPDLOCK) +FROM RealTableName TableAlias WITH (UPDLOCK, SOMETHING) -- ^ keyword.other.DML -- ^^^^^^^^^^^^^ meta.table-name constant.other.placeholder -- ^^^^^^^^^^ meta.table-name constant.other.placeholder --- ^^^^ keyword.other.DML +-- ^^^^ keyword.other +-- ^^^^^^^^^^^^^^^^^^^^ meta.group +-- ^ - meta.group +-- ^ punctuation.section.group.begin +-- ^^^^^^^ constant.language.with +-- ^ punctuation.separator.sequence +-- ^^^^^^^^^ meta.group constant.language.with +-- ^ punctuation.section.group.end INNER JOIN some_view AS v WITH (NOLOCK) ON v.some_id = TableAlias.some_id -- ^^^^^^^ keyword.other.DML -- ^^^^^^^^^ meta.table-name constant.other.placeholder -- ^^ keyword.operator.assignment.alias -- ^ meta.table-name constant.other.placeholder -- ^^^^ keyword.other.DML +-- ^^^^^^^^ meta.group +-- ^ punctuation.section.group.begin +-- ^^^^^^ constant.language.with +-- ^ punctuation.section.group.end -- ^^ keyword.operator.join +-- ^^^^^^^^^ meta.column-name constant.other.placeholder +-- ^ punctuation.accessor.dot -- ^ keyword.operator.comparison +-- ^^^^^^^^^^^^^^^^^^ meta.column-name constant.other.placeholder +-- ^ punctuation.accessor.dot WHERE TableAlias.some_id IN ( -- ^^ keyword.other.DML -- ^^ keyword.operator.logical @@ -419,4 +439,37 @@ AND (v.column2 IS NULL OR ISNULL(TableAlias.column1, 0) != v.column1) -- ^^^^^^ meta.function-call support.function -- ^^ keyword.operator.comparison +drop table foobar +-- ^^^^^^^ meta.drop keyword.other.ddl +-- ^^^^^^ meta.table-name constant.other.placeholder + +alter table foo +-- ^^^^^^^^ meta.alter keyword.other.ddl +-- ^^^ meta.alter meta.table-name constant.other.placeholder +add bar uniqueidentifier +--^ meta.alter keyword.other.ddl +-- ^^^ meta.alter meta.column-name constant.other.placeholder +-- ^^^^^^^^^^^^^^^^ meta.alter storage.type + +alter table foo +--^^^^^^^^^ meta.alter keyword.other.ddl - meta.alter meta.alter +-- ^^^ meta.alter meta.table-name constant.other.placeholder +alter column bar uniqueidentifier not null +--^^^^^^^^^^ meta.alter keyword.other.ddl +-- ^^^ meta.alter meta.column-name constant.other.placeholder +-- ^^^^^^^^^^^^^^^^ meta.alter storage.type +-- ^^^ meta.alter keyword.operator.logical +-- ^^^^ meta.alter constant.language.null + +USE AdventureWorks2012; +GO +SELECT i.ProductID, p.Name, i.LocationID, i.Quantity + ,RANK() OVER + (PARTITION BY i.LocationID ORDER BY i.Quantity DESC) AS Rank +FROM Production.ProductInventory AS i +INNER JOIN Production.Product AS p + ON i.ProductID = p.ProductID +WHERE i.LocationID BETWEEN 3 AND 4 +ORDER BY i.LocationID; + -- merge, CTEs