-
Notifications
You must be signed in to change notification settings - Fork 36
Add support for JSON Index creation syntax in SQL Server 2025 (TSql170) #147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
269592c
90ad82c
3e23f8b
9d7e0db
753a74b
73a1645
9de9b7f
4865dd4
373dc4d
ff38699
53a2aba
28c5564
667ca5c
9656c7e
89c0efc
50a1bff
d0e2993
b6073da
ab3a74f
eee2f48
04e7f67
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -356,4 +356,7 @@ MigrationBackup/ | |
| out/ | ||
|
|
||
| # Project packages folder | ||
| .packages/ | ||
| .packages/ | ||
|
|
||
| # Temporary build artifacts | ||
| tmp/ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -883,6 +883,9 @@ create2005Statements returns [TSqlStatement vResult = null] | |
| | | ||
| {NextTokenMatches(CodeGenerationSupporter.ColumnStore)}? | ||
| vResult=createColumnStoreIndexStatement[null, null] | ||
| | | ||
| {NextTokenMatches(CodeGenerationSupporter.Json)}? | ||
| vResult=createJsonIndexStatement[null, null] | ||
| | | ||
| {NextTokenMatches(CodeGenerationSupporter.Contract)}? | ||
| vResult=createContractStatement | ||
|
|
@@ -16844,6 +16847,7 @@ createIndexStatement returns [TSqlStatement vResult = null] | |
| ( | ||
| vResult=createRelationalIndexStatement[tUnique, isClustered] | ||
| | vResult=createColumnStoreIndexStatement[tUnique, isClustered] | ||
| | vResult=createJsonIndexStatement[tUnique, isClustered] | ||
| ) | ||
| ) | ||
| | | ||
|
|
@@ -16980,6 +16984,58 @@ createColumnStoreIndexStatement [IToken tUnique, bool? isClustered] returns [Cre | |
| )? | ||
| ; | ||
|
|
||
| createJsonIndexStatement [IToken tUnique, bool? isClustered] returns [CreateJsonIndexStatement vResult = FragmentFactory.CreateFragment<CreateJsonIndexStatement>()] | ||
| { | ||
| Identifier vIdentifier; | ||
| SchemaObjectName vSchemaObjectName; | ||
| Identifier vJsonColumn; | ||
| StringLiteral vPath; | ||
|
|
||
| if (tUnique != null) | ||
| { | ||
| ThrowIncorrectSyntaxErrorException(tUnique); | ||
| } | ||
| if (isClustered.HasValue) | ||
| { | ||
| ThrowIncorrectSyntaxErrorException(LT(1)); | ||
| } | ||
| } | ||
| : tJson:Identifier tIndex:Index vIdentifier=identifier | ||
| { | ||
| Match(tJson, CodeGenerationSupporter.Json); | ||
| vResult.Name = vIdentifier; | ||
| } | ||
| tOn:On vSchemaObjectName=schemaObjectThreePartName | ||
| { | ||
| vResult.OnName = vSchemaObjectName; | ||
| } | ||
| LeftParenthesis vJsonColumn=identifier tRParen:RightParenthesis | ||
| { | ||
| vResult.JsonColumn = vJsonColumn; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's this for?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The "options {greedy = true; }" directive is used to resolve parser conflicts with common table expressions and XML namespaces. This is a standard ANTLR pattern used throughout the grammar file (appears in 30+ locations) to ensure the WITH clause is properly recognized in CREATE JSON INDEX statements. The comment explains this is needed due to conflict with withCommonTableExpressionsAndXmlNamespaces. |
||
| UpdateTokenInfo(vResult, tRParen); | ||
| } | ||
| ( | ||
| tFor:For LeftParenthesis | ||
| vPath=stringLiteral | ||
| { | ||
| AddAndUpdateTokenInfo(vResult, vResult.ForJsonPaths, vPath); | ||
| } | ||
| ( | ||
| Comma vPath=stringLiteral | ||
| { | ||
| AddAndUpdateTokenInfo(vResult, vResult.ForJsonPaths, vPath); | ||
| } | ||
| )* | ||
| RightParenthesis | ||
| )? | ||
| ( | ||
| // Greedy due to conflict with withCommonTableExpressionsAndXmlNamespaces | ||
| options {greedy = true; } : | ||
| With | ||
| indexOptionList[IndexAffectingStatement.CreateIndex, vResult.IndexOptions, vResult] | ||
| )? | ||
| ; | ||
|
|
||
| indexKeyColumnList[CreateIndexStatement vParent] | ||
| { | ||
| ColumnWithSortOrder vColumnWithSortOrder; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| //------------------------------------------------------------------------------ | ||
| // <copyright file="SqlScriptGeneratorVisitor.CreateJsonIndexStatement.cs" company="Microsoft"> | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // </copyright> | ||
| //------------------------------------------------------------------------------ | ||
| using System.Collections.Generic; | ||
| using Microsoft.SqlServer.TransactSql.ScriptDom; | ||
|
|
||
| namespace Microsoft.SqlServer.TransactSql.ScriptDom.ScriptGenerator | ||
| { | ||
| partial class SqlScriptGeneratorVisitor | ||
| { | ||
| public override void ExplicitVisit(CreateJsonIndexStatement node) | ||
| { | ||
| GenerateKeyword(TSqlTokenType.Create); | ||
|
|
||
| GenerateSpaceAndIdentifier(CodeGenerationSupporter.Json); | ||
|
|
||
| GenerateSpaceAndKeyword(TSqlTokenType.Index); | ||
|
|
||
| // name | ||
| GenerateSpaceAndFragmentIfNotNull(node.Name); | ||
|
|
||
| NewLineAndIndent(); | ||
| GenerateKeyword(TSqlTokenType.On); | ||
| GenerateSpaceAndFragmentIfNotNull(node.OnName); | ||
|
|
||
| // JSON column | ||
| if (node.JsonColumn != null) | ||
| { | ||
| GenerateSpace(); | ||
| GenerateSymbol(TSqlTokenType.LeftParenthesis); | ||
| GenerateFragmentIfNotNull(node.JsonColumn); | ||
| GenerateSymbol(TSqlTokenType.RightParenthesis); | ||
| } | ||
|
|
||
| // FOR clause with JSON paths | ||
| if (node.ForJsonPaths != null && node.ForJsonPaths.Count > 0) | ||
| { | ||
| NewLineAndIndent(); | ||
| GenerateKeyword(TSqlTokenType.For); | ||
| GenerateSpace(); | ||
| GenerateParenthesisedCommaSeparatedList(node.ForJsonPaths); | ||
| } | ||
|
|
||
| GenerateIndexOptions(node.IndexOptions); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| CREATE JSON INDEX IX_JSON_Basic | ||
| ON dbo.Users (JsonData); | ||
|
|
||
| CREATE JSON INDEX IX_JSON_SinglePath | ||
| ON dbo.Users (JsonData) | ||
| FOR ('$.name'); | ||
|
|
||
| CREATE JSON INDEX IX_JSON_MultiplePaths | ||
| ON dbo.Users (JsonData) | ||
| FOR ('$.name', '$.email', '$.age'); | ||
|
|
||
| CREATE JSON INDEX IX_JSON_WithOptions | ||
| ON dbo.Users (JsonData) WITH (FILLFACTOR = 90, ONLINE = OFF); | ||
|
|
||
| CREATE JSON INDEX IX_JSON_Complete | ||
| ON dbo.Users (JsonData) | ||
| FOR ('$.profile.name', '$.profile.email') WITH (MAXDOP = 4, DATA_COMPRESSION = ROW); | ||
|
|
||
| CREATE JSON INDEX IX_JSON_Schema | ||
| ON MySchema.MyTable (JsonColumn) | ||
| FOR ('$.properties.value'); | ||
|
|
||
| CREATE JSON INDEX [IX JSON Index] | ||
| ON [dbo].[Users] ([Json Data]) | ||
| FOR ('$.data.attributes'); | ||
|
|
||
| CREATE JSON INDEX IX_JSON_Complex | ||
| ON dbo.Documents (Content) | ||
| FOR ('$.metadata.title', '$.content.sections[*].text', '$.tags[*]'); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| -- Basic JSON index creation | ||
| CREATE JSON INDEX IX_JSON_Basic ON dbo.Users (JsonData); | ||
|
|
||
| -- JSON index with FOR clause (single path) | ||
| CREATE JSON INDEX IX_JSON_SinglePath ON dbo.Users (JsonData) | ||
| FOR ('$.name'); | ||
|
|
||
| -- JSON index with FOR clause (multiple paths) | ||
| CREATE JSON INDEX IX_JSON_MultiplePaths ON dbo.Users (JsonData) | ||
| FOR ('$.name', '$.email', '$.age'); | ||
|
|
||
| -- JSON index with WITH options | ||
| CREATE JSON INDEX IX_JSON_WithOptions ON dbo.Users (JsonData) | ||
| WITH (FILLFACTOR = 90, ONLINE = OFF); | ||
|
|
||
| -- JSON index with FOR clause and WITH options | ||
| CREATE JSON INDEX IX_JSON_Complete ON dbo.Users (JsonData) | ||
| FOR ('$.profile.name', '$.profile.email') | ||
| WITH (MAXDOP = 4, DATA_COMPRESSION = ROW); | ||
|
|
||
| -- JSON index on schema-qualified table | ||
| CREATE JSON INDEX IX_JSON_Schema ON MySchema.MyTable (JsonColumn) | ||
| FOR ('$.properties.value'); | ||
|
|
||
| -- JSON index with quoted identifiers | ||
| CREATE JSON INDEX [IX JSON Index] ON [dbo].[Users] ([Json Data]) | ||
| FOR ('$.data.attributes'); | ||
|
|
||
| -- JSON index with complex path expressions | ||
| CREATE JSON INDEX IX_JSON_Complex ON dbo.Documents (Content) | ||
| FOR ('$.metadata.title', '$.content.sections[*].text', '$.tags[*]'); |
Uh oh!
There was an error while loading. Please reload this page.