diff --git a/SqlScriptDom/Parser/TSql/Ast.xml b/SqlScriptDom/Parser/TSql/Ast.xml index e5764b2..c8ebb38 100644 --- a/SqlScriptDom/Parser/TSql/Ast.xml +++ b/SqlScriptDom/Parser/TSql/Ast.xml @@ -4607,6 +4607,13 @@ + + + + + + + @@ -4639,6 +4646,14 @@ + + + + + + + + diff --git a/SqlScriptDom/Parser/TSql/CodeGenerationSupporter.cs b/SqlScriptDom/Parser/TSql/CodeGenerationSupporter.cs index 7c00dbe..4deaa86 100644 --- a/SqlScriptDom/Parser/TSql/CodeGenerationSupporter.cs +++ b/SqlScriptDom/Parser/TSql/CodeGenerationSupporter.cs @@ -225,6 +225,7 @@ internal static class CodeGenerationSupporter internal const string CompressionDelay = "COMPRESSION_DELAY"; internal const string CompressAllRowGroups = "COMPRESS_ALL_ROW_GROUPS"; internal const string Concat = "CONCAT"; + internal const string Cosine = "COSINE"; internal const string Configuration = "CONFIGURATION"; internal const string ConnectionOptions = "CONNECTION_OPTIONS"; internal const string Contained = "CONTAINED"; @@ -299,6 +300,8 @@ internal static class CodeGenerationSupporter internal const string Dependents = "DEPENDENTS"; internal const string Description = "DESCRIPTION"; internal const string DesiredState = "DESIRED_STATE"; + internal const string DiskANN = "DISKANN"; + internal const string Dot = "DOT"; internal const string Delay = "DELAY"; internal const string DelayedDurability = "DELAYED_DURABILITY"; internal const string DelimitedText = "DELIMITEDTEXT"; @@ -347,6 +350,7 @@ internal static class CodeGenerationSupporter internal const string EnvironmentVariables = "ENVIRONMENT_VARIABLES"; internal const string Equal = "="; internal const string Error = "ERROR"; + internal const string Euclidean = "EUCLIDEAN"; internal const string ErrorBrokerConversations = "ERROR_BROKER_CONVERSATIONS"; internal const string ErrorDataSource = "ERRORFILE_DATA_SOURCE"; internal const string ErrorFile = "ERRORFILE"; @@ -612,6 +616,7 @@ internal static class CodeGenerationSupporter internal const string MessageForwarding = "MESSAGE_FORWARDING"; internal const string MessageForwardSize = "MESSAGE_FORWARD_SIZE"; internal const string MigrationState = "MIGRATION_STATE"; + internal const string Metric = "METRIC"; internal const string Min = "MIN"; internal const string MinGrantPercent = "MIN_GRANT_PERCENT"; internal const string MinCpuPercent = "MIN_CPU_PERCENT"; diff --git a/SqlScriptDom/Parser/TSql/IndexOptionHelper.cs b/SqlScriptDom/Parser/TSql/IndexOptionHelper.cs index d552933..1a0545f 100644 --- a/SqlScriptDom/Parser/TSql/IndexOptionHelper.cs +++ b/SqlScriptDom/Parser/TSql/IndexOptionHelper.cs @@ -43,6 +43,9 @@ private IndexOptionHelper() AddOptionMapping(IndexOptionKind.XmlCompression, CodeGenerationSupporter.XmlCompression, SqlVersionFlags.TSql160AndAbove); + AddOptionMapping(IndexOptionKind.VectorMetric, CodeGenerationSupporter.Metric, SqlVersionFlags.TSql170AndAbove); + AddOptionMapping(IndexOptionKind.VectorType, CodeGenerationSupporter.Type, SqlVersionFlags.TSql170AndAbove); + } internal static readonly IndexOptionHelper Instance = new IndexOptionHelper(); diff --git a/SqlScriptDom/Parser/TSql/IndexOptionKind.cs b/SqlScriptDom/Parser/TSql/IndexOptionKind.cs index 795fa3f..7f2914a 100644 --- a/SqlScriptDom/Parser/TSql/IndexOptionKind.cs +++ b/SqlScriptDom/Parser/TSql/IndexOptionKind.cs @@ -38,6 +38,8 @@ public enum IndexOptionKind WaitAtLowPriority = 21, OptimizeForSequentialKey = 22, XmlCompression = 23, + VectorMetric = 24, + VectorType = 25, } #pragma warning restore 1591 diff --git a/SqlScriptDom/Parser/TSql/OptionsHelper.cs b/SqlScriptDom/Parser/TSql/OptionsHelper.cs index 284ec4e..7262ab6 100644 --- a/SqlScriptDom/Parser/TSql/OptionsHelper.cs +++ b/SqlScriptDom/Parser/TSql/OptionsHelper.cs @@ -135,7 +135,7 @@ internal SqlVersionFlags MapSqlVersionToSqlVersionFlags(SqlVersion sqlVersion) } } - internal OptionType ParseOption(antlr.IToken token, SqlVersionFlags version) + internal virtual OptionType ParseOption(antlr.IToken token, SqlVersionFlags version) { OptionInfo optionInfo; if (_stringToOptionInfo.TryGetValue(token.getText(), out optionInfo) && diff --git a/SqlScriptDom/Parser/TSql/TSql170.g b/SqlScriptDom/Parser/TSql/TSql170.g index 031bc61..1ef4339 100644 --- a/SqlScriptDom/Parser/TSql/TSql170.g +++ b/SqlScriptDom/Parser/TSql/TSql170.g @@ -886,6 +886,9 @@ create2005Statements returns [TSqlStatement vResult = null] | {NextTokenMatches(CodeGenerationSupporter.Json)}? vResult=createJsonIndexStatement[null, null] + | + {NextTokenMatches(CodeGenerationSupporter.Vector)}? + vResult=createVectorIndexStatement[null, null] | {NextTokenMatches(CodeGenerationSupporter.Contract)}? vResult=createContractStatement @@ -16848,6 +16851,7 @@ createIndexStatement returns [TSqlStatement vResult = null] vResult=createRelationalIndexStatement[tUnique, isClustered] | vResult=createColumnStoreIndexStatement[tUnique, isClustered] | vResult=createJsonIndexStatement[tUnique, isClustered] + | vResult=createVectorIndexStatement[tUnique, isClustered] ) ) | @@ -17036,6 +17040,50 @@ createJsonIndexStatement [IToken tUnique, bool? isClustered] returns [CreateJson )? ; +createVectorIndexStatement [IToken tUnique, bool? isClustered] returns [CreateVectorIndexStatement vResult = FragmentFactory.CreateFragment()] +{ + Identifier vIdentifier; + SchemaObjectName vSchemaObjectName; + Identifier vVectorColumn; + FileGroupOrPartitionScheme vFileGroupOrPartitionScheme; + + if (tUnique != null) + { + ThrowIncorrectSyntaxErrorException(tUnique); + } + if (isClustered.HasValue) + { + ThrowIncorrectSyntaxErrorException(LT(1)); + } +} + : tVector:Identifier tIndex:Index vIdentifier=identifier + { + Match(tVector, CodeGenerationSupporter.Vector); + vResult.Name = vIdentifier; + } + tOn:On vSchemaObjectName=schemaObjectThreePartName + { + vResult.OnName = vSchemaObjectName; + } + LeftParenthesis vVectorColumn=identifier tRParen:RightParenthesis + { + vResult.VectorColumn = vVectorColumn; + UpdateTokenInfo(vResult, tRParen); + } + ( + // Greedy due to conflict with withCommonTableExpressionsAndXmlNamespaces + options {greedy = true; } : + With + indexOptionList[IndexAffectingStatement.CreateIndex, vResult.IndexOptions, vResult] + )? + ( + On vFileGroupOrPartitionScheme=filegroupOrPartitionScheme + { + vResult.OnFileGroupOrPartitionScheme = vFileGroupOrPartitionScheme; + } + )? + ; + indexKeyColumnList[CreateIndexStatement vParent] { ColumnWithSortOrder vColumnWithSortOrder; @@ -17680,6 +17728,12 @@ indexOption returns [IndexOption vResult = null] | {NextTokenMatches(CodeGenerationSupporter.WaitAtLowPriority)}? vResult=waitAtLowPriorityOption + | + {NextTokenMatches(CodeGenerationSupporter.Metric)}? + vResult=vectorMetricOption + | + {NextTokenMatches(CodeGenerationSupporter.Type)}? + vResult=vectorTypeOption | vResult=indexStateOption ; @@ -27669,6 +27723,27 @@ xmlCompressionOption returns [XmlCompressionOption vResult = FragmentFactory.Cre )? ; +vectorMetricOption returns [VectorMetricIndexOption vResult = FragmentFactory.CreateFragment()] + : tMetric:Identifier EqualsSign tMetricValue:AsciiStringLiteral + { + Match(tMetric, CodeGenerationSupporter.Metric); + vResult.OptionKind = IndexOptionKind.VectorMetric; + vResult.MetricType = VectorMetricTypeHelper.Instance.ParseOption(tMetricValue); + + UpdateTokenInfo(vResult, tMetric); + } + ; + +vectorTypeOption returns [VectorTypeIndexOption vResult = FragmentFactory.CreateFragment()] + : tType:Identifier EqualsSign tTypeValue:AsciiStringLiteral + { + Match(tType, CodeGenerationSupporter.Type); + vResult.OptionKind = IndexOptionKind.VectorType; + vResult.VectorType = VectorIndexTypeHelper.Instance.ParseOption(tTypeValue); + UpdateTokenInfo(vResult, tType); + } + ; + compressionPartitionRange returns [CompressionPartitionRange vResult = FragmentFactory.CreateFragment()] { ScalarExpression vExpression; diff --git a/SqlScriptDom/Parser/TSql/VectorIndexType.cs b/SqlScriptDom/Parser/TSql/VectorIndexType.cs new file mode 100644 index 0000000..8f70a02 --- /dev/null +++ b/SqlScriptDom/Parser/TSql/VectorIndexType.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//------------------------------------------------------------------------------ + + + +namespace Microsoft.SqlServer.TransactSql.ScriptDom +{ +#pragma warning disable 1591 + + /// + /// The possible values for vector index type + /// + public enum VectorIndexType + { + DiskANN = 0 + } + +#pragma warning restore 1591 +} + \ No newline at end of file diff --git a/SqlScriptDom/Parser/TSql/VectorIndexTypeHelper.cs b/SqlScriptDom/Parser/TSql/VectorIndexTypeHelper.cs new file mode 100644 index 0000000..602617f --- /dev/null +++ b/SqlScriptDom/Parser/TSql/VectorIndexTypeHelper.cs @@ -0,0 +1,21 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//------------------------------------------------------------------------------ + + + +namespace Microsoft.SqlServer.TransactSql.ScriptDom +{ + + internal class VectorIndexTypeHelper : OptionsHelper + { + private VectorIndexTypeHelper() + { + AddOptionMapping(VectorIndexType.DiskANN, "'" + CodeGenerationSupporter.DiskANN + "'"); + } + + public static readonly VectorIndexTypeHelper Instance = new VectorIndexTypeHelper(); + } +} \ No newline at end of file diff --git a/SqlScriptDom/Parser/TSql/VectorMetricType.cs b/SqlScriptDom/Parser/TSql/VectorMetricType.cs new file mode 100644 index 0000000..44b24a8 --- /dev/null +++ b/SqlScriptDom/Parser/TSql/VectorMetricType.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//------------------------------------------------------------------------------ + + + +namespace Microsoft.SqlServer.TransactSql.ScriptDom +{ +#pragma warning disable 1591 + + /// + /// The possible values for vector index metric + /// + public enum VectorMetricType + { + Cosine = 0, + Dot = 1, + Euclidean = 2 + } + +#pragma warning restore 1591 +} + \ No newline at end of file diff --git a/SqlScriptDom/Parser/TSql/VectorMetricTypeHelper.cs b/SqlScriptDom/Parser/TSql/VectorMetricTypeHelper.cs new file mode 100644 index 0000000..6b1479a --- /dev/null +++ b/SqlScriptDom/Parser/TSql/VectorMetricTypeHelper.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//------------------------------------------------------------------------------ + + + +using static Microsoft.SqlServer.TransactSql.ScriptDom.SensitivityClassification; + +namespace Microsoft.SqlServer.TransactSql.ScriptDom +{ + + internal class VectorMetricTypeHelper : OptionsHelper + { + private VectorMetricTypeHelper() + { + AddOptionMapping(VectorMetricType.Cosine, "'" + CodeGenerationSupporter.Cosine + "'"); + AddOptionMapping(VectorMetricType.Dot, "'" + CodeGenerationSupporter.Dot + "'"); + AddOptionMapping(VectorMetricType.Euclidean, "'" + CodeGenerationSupporter.Euclidean + "'"); + } + + public static readonly VectorMetricTypeHelper Instance = new VectorMetricTypeHelper(); + } +} \ No newline at end of file diff --git a/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.CreateVectorIndexStatement.cs b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.CreateVectorIndexStatement.cs new file mode 100644 index 0000000..cb47a2f --- /dev/null +++ b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.CreateVectorIndexStatement.cs @@ -0,0 +1,48 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//------------------------------------------------------------------------------ +using System.Collections.Generic; +using Microsoft.SqlServer.TransactSql.ScriptDom; + +namespace Microsoft.SqlServer.TransactSql.ScriptDom.ScriptGenerator +{ + partial class SqlScriptGeneratorVisitor + { + public override void ExplicitVisit(CreateVectorIndexStatement node) + { + GenerateKeyword(TSqlTokenType.Create); + + GenerateSpaceAndIdentifier(CodeGenerationSupporter.Vector); + + GenerateSpaceAndKeyword(TSqlTokenType.Index); + + // name + GenerateSpaceAndFragmentIfNotNull(node.Name); + + NewLineAndIndent(); + GenerateKeyword(TSqlTokenType.On); + GenerateSpaceAndFragmentIfNotNull(node.OnName); + + // Vector column + if (node.VectorColumn != null) + { + GenerateSpace(); + GenerateSymbol(TSqlTokenType.LeftParenthesis); + GenerateFragmentIfNotNull(node.VectorColumn); + GenerateSymbol(TSqlTokenType.RightParenthesis); + } + + GenerateIndexOptions(node.IndexOptions); + + if (node.OnFileGroupOrPartitionScheme != null) + { + NewLineAndIndent(); + GenerateKeyword(TSqlTokenType.On); + + GenerateSpaceAndFragmentIfNotNull(node.OnFileGroupOrPartitionScheme); + } + } + } +} \ No newline at end of file diff --git a/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.VectorMetricIndexOption.cs b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.VectorMetricIndexOption.cs new file mode 100644 index 0000000..9beeeaf --- /dev/null +++ b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.VectorMetricIndexOption.cs @@ -0,0 +1,19 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.SqlServer.TransactSql.ScriptDom.ScriptGenerator +{ + partial class SqlScriptGeneratorVisitor + { + public override void ExplicitVisit(VectorMetricIndexOption node) + { + IndexOptionHelper.Instance.GenerateSourceForOption(_writer, node.OptionKind); + GenerateSpaceAndSymbol(TSqlTokenType.EqualsSign); + GenerateSpace(); + VectorMetricTypeHelper.Instance.GenerateSourceForOption(_writer, node.MetricType); + } + } +} \ No newline at end of file diff --git a/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.VectorTypeIndexOption.cs b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.VectorTypeIndexOption.cs new file mode 100644 index 0000000..85bcadb --- /dev/null +++ b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.VectorTypeIndexOption.cs @@ -0,0 +1,19 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.SqlServer.TransactSql.ScriptDom.ScriptGenerator +{ + partial class SqlScriptGeneratorVisitor + { + public override void ExplicitVisit(VectorTypeIndexOption node) + { + IndexOptionHelper.Instance.GenerateSourceForOption(_writer, node.OptionKind); + GenerateSpaceAndSymbol(TSqlTokenType.EqualsSign); + GenerateSpace(); + VectorIndexTypeHelper.Instance.GenerateSourceForOption(_writer, node.VectorType); + } + } +} \ No newline at end of file diff --git a/Test/SqlDom/Baselines170/VectorIndexTests170.sql b/Test/SqlDom/Baselines170/VectorIndexTests170.sql new file mode 100644 index 0000000..729b3ab --- /dev/null +++ b/Test/SqlDom/Baselines170/VectorIndexTests170.sql @@ -0,0 +1,37 @@ +CREATE VECTOR INDEX IX_Vector_Basic + ON dbo.Documents (VectorData); + +CREATE VECTOR INDEX IX_Vector_Cosine + ON dbo.Documents (VectorData) WITH (METRIC = 'COSINE'); + +CREATE VECTOR INDEX IX_Vector_Dot + ON dbo.Documents (VectorData) WITH (METRIC = 'DOT'); + +CREATE VECTOR INDEX IX_Vector_Euclidean + ON dbo.Documents (VectorData) WITH (METRIC = 'EUCLIDEAN'); + +CREATE VECTOR INDEX IX_Vector_DiskANN + ON dbo.Documents (VectorData) WITH (TYPE = 'DISKANN'); + +CREATE VECTOR INDEX IX_Vector_Complete + ON dbo.Documents (VectorData) WITH (METRIC = 'COSINE', TYPE = 'DISKANN'); + +CREATE VECTOR INDEX IX_Vector_MaxDop + ON dbo.Documents (VectorData) WITH (MAXDOP = 4); + +CREATE VECTOR INDEX IX_Vector_AllOptions + ON dbo.Documents (VectorData) WITH (METRIC = 'DOT', TYPE = 'DISKANN', MAXDOP = 8); + +CREATE VECTOR INDEX IX_Vector_Schema + ON MySchema.MyTable (VectorColumn) WITH (METRIC = 'EUCLIDEAN'); + +CREATE VECTOR INDEX [IX Vector Index] + ON [dbo].[Documents] ([Vector Data]) WITH (METRIC = 'COSINE'); + +CREATE VECTOR INDEX IX_Vector_Filegroup + ON dbo.Documents (VectorData) WITH (METRIC = 'COSINE') + ON [PRIMARY]; + +CREATE VECTOR INDEX IX_Vector_DefaultFG + ON dbo.Documents (VectorData) WITH (METRIC = 'DOT') + ON "default"; \ No newline at end of file diff --git a/Test/SqlDom/Only170SyntaxTests.cs b/Test/SqlDom/Only170SyntaxTests.cs index 654fcdb..05ade64 100644 --- a/Test/SqlDom/Only170SyntaxTests.cs +++ b/Test/SqlDom/Only170SyntaxTests.cs @@ -11,6 +11,7 @@ public partial class SqlDomTests { new ParserTest170("RegexpTVFTests170.sql", nErrors80: 1, nErrors90: 1, nErrors100: 0, nErrors110: 0, nErrors120: 0, nErrors130: 0, nErrors140: 0, nErrors150: 0, nErrors160: 0), new ParserTest170("JsonIndexTests170.sql", nErrors80: 2, nErrors90: 8, nErrors100: 8, nErrors110: 8, nErrors120: 8, nErrors130: 8, nErrors140: 8, nErrors150: 8, nErrors160: 8), + new ParserTest170("VectorIndexTests170.sql", nErrors80: 2, nErrors90: 12, nErrors100: 12, nErrors110: 12, nErrors120: 12, nErrors130: 12, nErrors140: 12, nErrors150: 12, nErrors160: 12), new ParserTest170("AlterDatabaseManualCutoverTests170.sql", nErrors80: 4, nErrors90: 4, nErrors100: 4, nErrors110: 4, nErrors120: 4, nErrors130: 4, nErrors140: 4, nErrors150: 4, nErrors160: 4), new ParserTest170("CreateColumnStoreIndexTests170.sql", nErrors80: 3, nErrors90: 3, nErrors100: 3, nErrors110: 3, nErrors120: 3, nErrors130: 0, nErrors140: 0, nErrors150: 0, nErrors160: 0) }; diff --git a/Test/SqlDom/ParserErrorsTests.cs b/Test/SqlDom/ParserErrorsTests.cs index f7632b5..23d2be1 100644 --- a/Test/SqlDom/ParserErrorsTests.cs +++ b/Test/SqlDom/ParserErrorsTests.cs @@ -6950,5 +6950,86 @@ Description NVARCHAR(200) "; ParserTestUtils.ErrorTestFabricDW(identityColumnSyntax2, new ParserErrorInfo(identityColumnSyntax2.IndexOf("IDENTITY(") + 8, "SQL46010", "(")); } + + /// + /// Negative tests for VECTOR INDEX syntax + /// + [TestMethod] + [Priority(0)] + [SqlStudioTestCategory(Category.UnitTest)] + public void VectorIndexNegativeTests() + { + // Missing INDEX keyword + ParserTestUtils.ErrorTest170("CREATE VECTOR IX_Test ON dbo.Documents (VectorData)", + new ParserErrorInfo(7, "SQL46010", "VECTOR")); + + // Missing table name + ParserTestUtils.ErrorTest170("CREATE VECTOR INDEX IX_Test ON (VectorData)", + new ParserErrorInfo(31, "SQL46010", "(")); + + // Missing column specification + ParserTestUtils.ErrorTest170("CREATE VECTOR INDEX IX_Test ON dbo.Documents", + new ParserErrorInfo(44, "SQL46029", "")); + + // Empty column list + ParserTestUtils.ErrorTest170("CREATE VECTOR INDEX IX_Test ON dbo.Documents ()", + new ParserErrorInfo(46, "SQL46010", ")")); + + // Multiple columns (not supported for vector indexes) + ParserTestUtils.ErrorTest170("CREATE VECTOR INDEX IX_Test ON dbo.Documents (VectorData, OtherColumn)", + new ParserErrorInfo(56, "SQL46010", ",")); + + // Invalid metric value + ParserTestUtils.ErrorTest170("CREATE VECTOR INDEX IX_Test ON dbo.Documents (VectorData) WITH (METRIC = 'invalid')", + new ParserErrorInfo(73, "SQL46010", "'invalid'")); + + // Invalid type value + ParserTestUtils.ErrorTest170("CREATE VECTOR INDEX IX_Test ON dbo.Documents (VectorData) WITH (TYPE = 'invalid')", + new ParserErrorInfo(71, "SQL46010", "'invalid'")); + + // Missing option value + ParserTestUtils.ErrorTest170("CREATE VECTOR INDEX IX_Test ON dbo.Documents (VectorData) WITH (METRIC = )", + new ParserErrorInfo(73, "SQL46010", ")")); + + // Empty option value + ParserTestUtils.ErrorTest170("CREATE VECTOR INDEX IX_Test ON dbo.Documents (VectorData) WITH (METRIC = '')", + new ParserErrorInfo(73, "SQL46010", "''")); + + // Missing WITH keyword when options are present + ParserTestUtils.ErrorTest170("CREATE VECTOR INDEX IX_Test ON dbo.Documents (VectorData) (METRIC = 'cosine')", + new ParserErrorInfo(59, "SQL46010", "METRIC")); + + // Missing parentheses around options + ParserTestUtils.ErrorTest170("CREATE VECTOR INDEX IX_Test ON dbo.Documents (VectorData) WITH METRIC = 'cosine'", + new ParserErrorInfo(63, "SQL46010", "METRIC")); + + // Invalid option name + ParserTestUtils.ErrorTest170("CREATE VECTOR INDEX IX_Test ON dbo.Documents (VectorData) WITH (INVALID_OPTION = 'value')", + new ParserErrorInfo(64, "SQL46010", "INVALID_OPTION")); + + // Metric value without quotes + ParserTestUtils.ErrorTest170("CREATE VECTOR INDEX IX_Test ON dbo.Documents (VectorData) WITH (METRIC = cosine)", + new ParserErrorInfo(73, "SQL46010", "cosine")); + + // Type value without quotes + ParserTestUtils.ErrorTest170("CREATE VECTOR INDEX IX_Test ON dbo.Documents (VectorData) WITH (TYPE = DiskANN)", + new ParserErrorInfo(71, "SQL46010", "DiskANN")); + + // MAXDOP with invalid value + ParserTestUtils.ErrorTest170("CREATE VECTOR INDEX IX_Test ON dbo.Documents (VectorData) WITH (MAXDOP = 'invalid')", + new ParserErrorInfo(73, "SQL46010", "'invalid'")); + + // MAXDOP with negative value + ParserTestUtils.ErrorTest170("CREATE VECTOR INDEX IX_Test ON dbo.Documents (VectorData) WITH (MAXDOP = -1)", + new ParserErrorInfo(73, "SQL46010", "-")); + + // Missing equals sign in option + ParserTestUtils.ErrorTest170("CREATE VECTOR INDEX IX_Test ON dbo.Documents (VectorData) WITH (METRIC 'cosine')", + new ParserErrorInfo(64, "SQL46010", "METRIC")); + + // Incomplete WITH clause + ParserTestUtils.ErrorTest170("CREATE VECTOR INDEX IX_Test ON dbo.Documents (VectorData) WITH", + new ParserErrorInfo(58, "SQL46010", "WITH")); + } } } diff --git a/Test/SqlDom/TestScripts/VectorIndexTests170.sql b/Test/SqlDom/TestScripts/VectorIndexTests170.sql new file mode 100644 index 0000000..d3a1a79 --- /dev/null +++ b/Test/SqlDom/TestScripts/VectorIndexTests170.sql @@ -0,0 +1,46 @@ +-- Basic VECTOR index creation +CREATE VECTOR INDEX IX_Vector_Basic ON dbo.Documents (VectorData); + +-- VECTOR index with METRIC option +CREATE VECTOR INDEX IX_Vector_Cosine ON dbo.Documents (VectorData) +WITH (METRIC = 'cosine'); + +CREATE VECTOR INDEX IX_Vector_Dot ON dbo.Documents (VectorData) +WITH (METRIC = 'dot'); + +CREATE VECTOR INDEX IX_Vector_Euclidean ON dbo.Documents (VectorData) +WITH (METRIC = 'euclidean'); + +-- VECTOR index with TYPE option +CREATE VECTOR INDEX IX_Vector_DiskANN ON dbo.Documents (VectorData) +WITH (TYPE = 'DiskANN'); + +-- VECTOR index with both METRIC and TYPE options +CREATE VECTOR INDEX IX_Vector_Complete ON dbo.Documents (VectorData) +WITH (METRIC = 'cosine', TYPE = 'DiskANN'); + +-- VECTOR index with MAXDOP option +CREATE VECTOR INDEX IX_Vector_MaxDop ON dbo.Documents (VectorData) +WITH (MAXDOP = 4); + +-- VECTOR index with multiple options +CREATE VECTOR INDEX IX_Vector_AllOptions ON dbo.Documents (VectorData) +WITH (METRIC = 'dot', TYPE = 'DiskANN', MAXDOP = 8); + +-- VECTOR index on schema-qualified table +CREATE VECTOR INDEX IX_Vector_Schema ON MySchema.MyTable (VectorColumn) +WITH (METRIC = 'euclidean'); + +-- VECTOR index with quoted identifiers +CREATE VECTOR INDEX [IX Vector Index] ON [dbo].[Documents] ([Vector Data]) +WITH (METRIC = 'cosine'); + +-- VECTOR index with filegroup +CREATE VECTOR INDEX IX_Vector_Filegroup ON dbo.Documents (VectorData) +WITH (METRIC = 'cosine') +ON [PRIMARY]; + +-- VECTOR index with filegroup as string +CREATE VECTOR INDEX IX_Vector_DefaultFG ON dbo.Documents (VectorData) +WITH (METRIC = 'dot') +ON "default"; \ No newline at end of file