diff --git a/SqlScriptDom/Parser/TSql/Ast.xml b/SqlScriptDom/Parser/TSql/Ast.xml index c8ebb38..842a787 100644 --- a/SqlScriptDom/Parser/TSql/Ast.xml +++ b/SqlScriptDom/Parser/TSql/Ast.xml @@ -403,8 +403,8 @@ Summary="Actual JSON for clause options. First one is always present (JSON mode)."/> - - + + @@ -642,6 +642,7 @@ + @@ -1346,6 +1347,27 @@ + + + + + + + + + + + + + + + + + + + + + @@ -3558,7 +3580,7 @@ - + @@ -4713,4 +4735,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SqlScriptDom/Parser/TSql/CodeGenerationSupporter.cs b/SqlScriptDom/Parser/TSql/CodeGenerationSupporter.cs index 4deaa86..1106636 100644 --- a/SqlScriptDom/Parser/TSql/CodeGenerationSupporter.cs +++ b/SqlScriptDom/Parser/TSql/CodeGenerationSupporter.cs @@ -99,6 +99,8 @@ internal static class CodeGenerationSupporter internal const string Affinity = "AFFINITY"; internal const string After = "AFTER"; internal const string Aggregate = "AGGREGATE"; + internal const string AiGenerateChunks = "AI_GENERATE_CHUNKS"; + internal const string AIGenerateEmbeddings = "AI_GENERATE_EMBEDDINGS"; internal const string Algorithm = "ALGORITHM"; internal const string AlterColumn = "ALTERCOLUMN"; internal const string All = "ALL"; @@ -118,6 +120,7 @@ internal static class CodeGenerationSupporter internal const string Always = "ALWAYS"; internal const string Anonymous = "ANONYMOUS"; internal const string AnsiNullDefault = "ANSI_NULL_DEFAULT"; + internal const string ApiFormat = "API_FORMAT"; internal const string Application = "APPLICATION"; internal const string ApplicationLog = "APPLICATION_LOG"; internal const string Apply = "APPLY"; @@ -198,6 +201,8 @@ internal static class CodeGenerationSupporter internal const string CheckPolicy = "CHECK_POLICY"; internal const string Checksum = "CHECKSUM"; internal const string ChecksumAgg = "CHECKSUM_AGG"; + internal const string ChunkSize = "CHUNK_SIZE"; + internal const string ChunkType = "CHUNK_TYPE"; internal const string ModularSum = "MODULAR_SUM"; internal const string Classifier = "CLASSIFIER"; internal const string Classification = "CLASSIFICATION"; @@ -225,7 +230,6 @@ 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"; @@ -244,6 +248,7 @@ internal static class CodeGenerationSupporter internal const string CopyCommand = "COPY"; internal const string CopyOnly = "COPY_ONLY"; internal const string Correlated = "CORRELATED"; + internal const string Cosine = "COSINE"; internal const string Count = "COUNT"; internal const string CountBig = "COUNT_BIG"; internal const string Counter = "COUNTER"; @@ -301,7 +306,6 @@ internal static class CodeGenerationSupporter 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"; @@ -320,6 +324,7 @@ internal static class CodeGenerationSupporter internal const string Document = "DOCUMENT"; internal const string DollarSign = "$"; internal const string DollarPartition = "$PARTITION"; + internal const string Dot = "DOT"; internal const string Drop = "DROP"; internal const string DropExisting = "DROP_EXISTING"; internal const string DTSBuffers = "DTS_BUFFERS"; @@ -329,11 +334,13 @@ internal static class CodeGenerationSupporter internal const string Edition = "EDITION"; internal const string ElasticPool = "ELASTIC_POOL"; internal const string Elements = "ELEMENTS"; + internal const string Embeddings = "EMBEDDINGS"; internal const string Emergency = "EMERGENCY"; internal const string Empty = "EMPTY"; internal const string Enable = "ENABLE"; internal const string Enabled = "ENABLED"; internal const string EnableBroker = "ENABLE_BROKER"; + internal const string EnableChunkSetId = "ENABLE_CHUNK_SET_ID"; internal const string EnclaveComputations = "ENCLAVE_COMPUTATIONS"; internal const string Encoding = "ENCODING"; internal const string Encrypted = "ENCRYPTED"; @@ -350,13 +357,13 @@ 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"; internal const string ErrorFileCredential = "ERRORFILE_CREDENTIAL"; internal const string EscapeChar = "ESCAPECHAR"; internal const string EstimateOnly = "ESTIMATEONLY"; + internal const string Euclidean = "EUCLIDEAN"; internal const string Event = "EVENT"; internal const string EventRetentionMode = "EVENT_RETENTION_MODE"; internal const string Exclamation = "!"; @@ -415,6 +422,7 @@ internal static class CodeGenerationSupporter internal const string FieldQuote = "FIELDQUOTE"; internal const string FipsFlagger = "FIPS_FLAGGER"; internal const string First = "FIRST"; + internal const string Fixed = "FIXED"; internal const string FlushIntervalSeconds = "FLUSH_INTERVAL_SECONDS"; internal const string FlushIntervalSecondsAlt = "DATA_FLUSH_INTERVAL_SECONDS"; internal const string Fn = "FN"; @@ -514,6 +522,7 @@ internal static class CodeGenerationSupporter internal const string Json = "JSON"; internal const string JsonArray = "JSON_ARRAY"; internal const string JsonObject = "JSON_OBJECT"; + internal const string JsonObjectAgg = "JSON_OBJECTAGG"; internal const string Keep = "KEEP"; internal const string KeepDefaults = "KEEPDEFAULTS"; internal const string KeepFixed = "KEEPFIXED"; @@ -555,6 +564,7 @@ internal static class CodeGenerationSupporter internal const string LoadHistory = "LOADHISTORY"; internal const string LobCompaction = "LOB_COMPACTION"; internal const string Local = "LOCAL"; + internal const string LocalRuntimePath = "LOCAL_RUNTIME_PATH"; internal const string Location = "LOCATION"; internal const string LocationUserDB = "USER_DB"; internal const string LocalServiceName = "LOCAL_SERVICE_NAME"; @@ -615,8 +625,8 @@ internal static class CodeGenerationSupporter internal const string Message = "MESSAGE"; 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 MigrationState = "MIGRATION_STATE"; internal const string Min = "MIN"; internal const string MinGrantPercent = "MIN_GRANT_PERCENT"; internal const string MinCpuPercent = "MIN_CPU_PERCENT"; @@ -628,6 +638,8 @@ internal static class CodeGenerationSupporter internal const string Mirror = "MIRROR"; internal const string Mixed = "MIXED"; internal const string MixedPageAllocation = "MIXED_PAGE_ALLOCATION"; + internal const string ModelType = "MODEL_TYPE"; + internal const string ModelName = "MODEL"; internal const string Modify = "MODIFY"; internal const string Money = "MONEY"; internal const string Move = "MOVE"; @@ -761,6 +773,7 @@ internal static class CodeGenerationSupporter internal const string Model = "MODEL"; internal const string RunTime = "RUNTIME"; internal const string Onnx = "ONNX"; + internal const string Overlap = "OVERLAP"; internal const string Process = "PROCESS"; internal const string PropertySetGuid = "PROPERTY_SET_GUID"; @@ -842,6 +855,7 @@ internal static class CodeGenerationSupporter internal const string RetentionDays = "RETENTION_DAYS"; internal const string RetentionPeriod = "RETENTION_PERIOD"; internal const string Returns = "RETURNS"; + internal const string Returning = "RETURNING"; internal const string RequestMaxCpuTimeSec = "REQUEST_MAX_CPU_TIME_SEC"; internal const string RequestMaxMemoryGrantPercent = "REQUEST_MAX_MEMORY_GRANT_PERCENT"; internal const string RequestMemoryGrantTimeoutSec = "REQUEST_MEMORY_GRANT_TIMEOUT_SEC"; @@ -916,6 +930,7 @@ internal static class CodeGenerationSupporter internal const string ShrinkDb = "SHRINKDB"; internal const string Sid = "SID"; internal const string Signature = "SIGNATURE"; + internal const string SimilarTo = "SIMILAR_TO"; internal const string Simple = "SIMPLE"; internal const string SingleBlob = "SINGLE_BLOB"; internal const string SingleClob = "SINGLE_CLOB"; @@ -1025,6 +1040,7 @@ internal static class CodeGenerationSupporter internal const string Timer = "TIMER"; internal const string TimeStamp = "TIMESTAMP"; internal const string TinyInt = "TINYINT"; + internal const string TopN = "TOP_N"; internal const string TornPageDetection = "TORN_PAGE_DETECTION"; internal const string TrackCausality = "TRACK_CAUSALITY"; internal const string TrackColumnsUpdated = "TRACK_COLUMNS_UPDATED"; @@ -1059,6 +1075,7 @@ internal static class CodeGenerationSupporter internal const string Unpivot = "UNPIVOT"; internal const string UpdLock = "UPDLOCK"; internal const string Url = "URL"; + internal const string Use = "USE"; internal const string Used = "USED"; internal const string UseIdentity = "USE_IDENTITY"; internal const string UseTypeDefault = "USE_TYPE_DEFAULT"; @@ -1076,6 +1093,7 @@ internal static class CodeGenerationSupporter internal const string Varp = "VARP"; internal const string VDevNo = "VDEVNO"; internal const string Vector = "Vector"; + internal const string VectorSearch = "VECTOR_SEARCH"; internal const string Verbose = "VERBOSE"; internal const string VerboseLogging = "VerboseLogging"; internal const string VerifyOnly = "VERIFYONLY"; diff --git a/SqlScriptDom/Parser/TSql/ExternalModelTypeOption.cs b/SqlScriptDom/Parser/TSql/ExternalModelTypeOption.cs new file mode 100644 index 0000000..858784e --- /dev/null +++ b/SqlScriptDom/Parser/TSql/ExternalModelTypeOption.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//------------------------------------------------------------------------------ +using System; + +namespace Microsoft.SqlServer.TransactSql.ScriptDom +{ +#pragma warning disable 1591 + + /// + /// The enumeration specifies the external model type + /// Currently, we support EMBEDDINGS only. + /// + public enum ExternalModelTypeOption + { + /// + /// MODEL_TYPE = EMBEDDINGS + /// + EMBEDDINGS = 0, + + } + +#pragma warning restore 1591 +} diff --git a/SqlScriptDom/Parser/TSql/SecurityObjectKind.cs b/SqlScriptDom/Parser/TSql/SecurityObjectKind.cs index 8d72de8..4d1cf17 100644 --- a/SqlScriptDom/Parser/TSql/SecurityObjectKind.cs +++ b/SqlScriptDom/Parser/TSql/SecurityObjectKind.cs @@ -42,6 +42,7 @@ public enum SecurityObjectKind SearchPropertyList = 23, ServerRole = 24, AvailabilityGroup = 25, + ExternalModel = 26, } #pragma warning restore 1591 diff --git a/SqlScriptDom/Parser/TSql/TSql170.g b/SqlScriptDom/Parser/TSql/TSql170.g index 1ef4339..a8f9bf2 100644 --- a/SqlScriptDom/Parser/TSql/TSql170.g +++ b/SqlScriptDom/Parser/TSql/TSql170.g @@ -906,7 +906,7 @@ create2005Statements returns [TSqlStatement vResult = null] vResult=createEventStatement // NOTIFICATION or SESSION | {NextTokenMatches(CodeGenerationSupporter.External)}? - vResult=createExternalStatements // EXTERNAL DATA SOURCE, FILE FORMAT, STREAM, TABLE, RESOURCE POOL, LIBRARY, LANGUAGE + vResult=createExternalStatements // EXTERNAL DATA SOURCE, FILE FORMAT, STREAM, TABLE, RESOURCE POOL, LIBRARY, LANGUAGE, MODEL | {NextTokenMatches(CodeGenerationSupporter.Fulltext)}? vResult=createFulltextStatement // Index or CATALOG @@ -4299,8 +4299,8 @@ alterDatabaseEncryptionKey [IToken tAlter] returns [AlterDatabaseEncryptionKeySt addSensitivityClassificationStatement returns [AddSensitivityClassificationStatement vResult = this.FragmentFactory.CreateFragment()] { ColumnReferenceExpression vColumn; - SensitivityClassificationOption vOption; - long encounteredOptions = 0; + SensitivityClassificationOption vOption; + long encounteredOptions = 0; } : tSensitivity:Identifier tClassification:Identifier To { @@ -4309,24 +4309,24 @@ addSensitivityClassificationStatement returns [AddSensitivityClassificationState } (vColumn = column { - CheckTableNameExistsForColumn(vColumn, true); + CheckTableNameExistsForColumn(vColumn, true); AddAndUpdateTokenInfo(vResult, vResult.Columns, vColumn); } (Comma vColumn = column { - CheckTableNameExistsForColumn(vColumn, true); + CheckTableNameExistsForColumn(vColumn, true); AddAndUpdateTokenInfo(vResult, vResult.Columns, vColumn); } )* ) - With LeftParenthesis vOption = sensitivityClassificationOption + With LeftParenthesis vOption = sensitivityClassificationOption { - CheckOptionDuplication(ref encounteredOptions, (int)vOption.Type, vOption); + CheckOptionDuplication(ref encounteredOptions, (int)vOption.Type, vOption); AddAndUpdateTokenInfo(vResult, vResult.Options, vOption); } (Comma vOption = sensitivityClassificationOption { - CheckOptionDuplication(ref encounteredOptions, (int)vOption.Type, vOption); + CheckOptionDuplication(ref encounteredOptions, (int)vOption.Type, vOption); AddAndUpdateTokenInfo(vResult, vResult.Options, vOption); } )* @@ -4357,10 +4357,10 @@ sensitivityClassificationOption returns [SensitivityClassificationOption vResult break; } - vResult = FragmentFactory.CreateFragment(); + vResult = FragmentFactory.CreateFragment(); vResult.Value = vSensitivityValue; - vResult.Type = optionType; + vResult.Type = optionType; UpdateTokenInfo(vResult, tOption); } @@ -4409,17 +4409,17 @@ dropSensitivityClassificationStatement returns [DropSensitivityClassificationSta } (vColumn = column { - CheckTableNameExistsForColumn(vColumn, true); + CheckTableNameExistsForColumn(vColumn, true); AddAndUpdateTokenInfo(vResult, vResult.Columns, vColumn); } (Comma vColumn = column { - CheckTableNameExistsForColumn(vColumn, true); + CheckTableNameExistsForColumn(vColumn, true); AddAndUpdateTokenInfo(vResult, vResult.Columns, vColumn); } )* ) - ; + ; ////////////////////////////////////////////////////////////////////// // Create Database @@ -6266,7 +6266,7 @@ simpleBulkInsertOptionWithValue returns [LiteralBulkInsertOption vResult = Fragm | iValue = identifier { vResult.OptionKind = BulkInsertStringOptionsHelper.Instance.ParseOption(tOption, SqlVersionFlags.TSql150); - UpdateTokenInfo(vResult, tOption); + UpdateTokenInfo(vResult, tOption); if (vResult.OptionKind == BulkInsertOptionKind.HeaderRow) if(!TryMatch(iValue, CodeGenerationSupporter.True)) Match(iValue, CodeGenerationSupporter.False); @@ -8947,6 +8947,9 @@ createExternalStatements returns [TSqlStatement vResult = null] | {NextTokenMatches(CodeGenerationSupporter.Stream)}? vResult = createExternalStreamStatement + | + {NextTokenMatches(CodeGenerationSupporter.Model)}? + vResult = createExternalModelStatement ) ; @@ -8964,6 +8967,9 @@ alterExternalStatements returns [TSqlStatement vResult = null] | {NextTokenMatches(CodeGenerationSupporter.Language)}? vResult = alterExternalLanguageStatement + | + {NextTokenMatches(CodeGenerationSupporter.Model)}? + vResult = alterExternalModelStatement ) ; @@ -13945,7 +13951,7 @@ securityTargetObjectCommon[SecurityTargetObject vParent] ( vIdentifier2=securityStatementPermission { - vParent.ObjectKind = ParseSecurityObjectKind(vIdentifier1, vIdentifier2); + vParent.ObjectKind = ParseSecurityObjectKindTSql170(vIdentifier1, vIdentifier2); } | vIdentifier2=securityStatementPermission vIdentifier3=securityStatementPermission @@ -14768,9 +14774,9 @@ dropStatements returns [TSqlStatement vResult] | {NextTokenMatches(CodeGenerationSupporter.Column)}? vResult = dropColumnStatements | {NextTokenMatches(CodeGenerationSupporter.External)}? - vResult = dropExternalStatement // EXTERNAL DATA SOURCE, FILE FORMAT, TABLE or RESOURCE POOL - | {NextTokenMatches(CodeGenerationSupporter.Sensitivity)}? - vResult = dropSensitivityClassificationStatement + vResult = dropExternalStatement // EXTERNAL DATA SOURCE, FILE FORMAT, TABLE , MODEL or RESOURCE POOL + | {NextTokenMatches(CodeGenerationSupporter.Sensitivity)}? + vResult = dropSensitivityClassificationStatement | vResult = dropServerStatements | vResult = dropUserStatement ) @@ -15662,6 +15668,9 @@ dropExternalStatement returns [TSqlStatement vResult = null] | {NextTokenMatches(CodeGenerationSupporter.Resource)}? vResult = dropExternalResourcePoolStatement + | + {NextTokenMatches(CodeGenerationSupporter.Model)}? + vResult = dropExternalModelStatement ) ; @@ -16952,13 +16961,13 @@ createColumnStoreIndexStatement [IToken tUnique, bool? isClustered] returns [Cre ( identifierColumnList[vResult, vResult.OrderedColumns] { - foreach (var col in vResult.OrderedColumns) - { - if (PseudoColumnHelper.IsGraphPseudoColumn(col)) - { + foreach (var col in vResult.OrderedColumns) + { + if (PseudoColumnHelper.IsGraphPseudoColumn(col)) + { ThrowIncorrectSyntaxErrorException(col); } - } + } } ) )? @@ -17184,9 +17193,9 @@ filterExpressionPrimary returns [BooleanExpression vResult] vExpression = filterColumn ( Is - ( - vResult = filterNullPredicate[vExpression] - | + ( + vResult = filterNullPredicate[vExpression] + | ( Not { @@ -17199,7 +17208,7 @@ filterExpressionPrimary returns [BooleanExpression vResult] | vResult = filterDistinctPredicate[vExpression, vNotDefined] ) - ) + ) | vResult = filterComparisonPredicate[vExpression] | vResult = filterInPredicate[vExpression] ) @@ -17252,9 +17261,9 @@ filterDistinctPredicate[ScalarExpression vColumn, bool vNotDefined] returns [Dis ScalarExpression vExpression; } : - vExpression = expression + vExpression = expression { - vResult.FirstExpression = vColumn; + vResult.FirstExpression = vColumn; vResult.SecondExpression = vExpression; vResult.IsNot = vNotDefined; } @@ -17262,9 +17271,9 @@ filterDistinctPredicate[ScalarExpression vColumn, bool vNotDefined] returns [Dis filterNullPredicateFromDistinctPredicate[ScalarExpression vColumn, bool vNotDefined] returns [BooleanIsNullExpression vResult = this.FragmentFactory.CreateFragment()] : - tNull:Null + tNull:Null { - vResult.IsNot = vNotDefined; + vResult.IsNot = vNotDefined; vResult.Expression = vColumn; UpdateTokenInfo(vResult,tNull); } @@ -19122,6 +19131,8 @@ selectTableReferenceElementWithoutJoinParenthesis[SubDmlFlags subDmlFlags] retur : {NextTokenMatches(CodeGenerationSupporter.ChangeTable)}? vResult=changeTableTableReference + | {NextTokenMatches(CodeGenerationSupporter.AiGenerateChunks)}? + vResult = aiGenerateChunksTableReference | vResult=builtInFunctionTableReference | {NextIdentifierMatchesOneOf(new string[] {CodeGenerationSupporter.StringSplit, CodeGenerationSupporter.GenerateSeries, CodeGenerationSupporter.RegexpMatches, CodeGenerationSupporter.RegexpSplitToTable})}? vResult=globalFunctionTableReference @@ -19137,124 +19148,259 @@ selectTableReferenceElementWithoutJoinParenthesis[SubDmlFlags subDmlFlags] retur | vResult=subDmlTableReference[subDmlFlags] | {NextTokenMatches(CodeGenerationSupporter.Predict)}? vResult=predictTableReference[subDmlFlags] + | {NextTokenMatches(CodeGenerationSupporter.VectorSearch)}? + vResult=vectorSearchTableReference | vResult=schemaObjectOrFunctionTableReference ; +aiGenerateChunksTableReference returns [AIGenerateChunksTableReference vResult = null] +{ + ScalarExpression vSource; + Identifier vChunkType; +} + : + {NextTokenMatches(CodeGenerationSupporter.AiGenerateChunks)}? + tFunc:Identifier + { + Match(tFunc, CodeGenerationSupporter.AiGenerateChunks); + } + LeftParenthesis + tSourceToken:Identifier + { + Match(tSourceToken, CodeGenerationSupporter.Source); + } + EqualsSign + vSource = expression + Comma + tChunkTypeToken:Identifier + { + Match(tChunkTypeToken, CodeGenerationSupporter.ChunkType); + } + EqualsSign + vChunkType = identifier + Comma + vResult = aiGenerateFixedChunksTableReference[vSource, vChunkType] + tRParen:RightParenthesis + { + if (vResult != null) + { + UpdateTokenInfo(vResult, tFunc); + UpdateTokenInfo(vResult, tRParen); + } + } + simpleTableReferenceAliasOpt[vResult] + ; + +aiGenerateFixedChunksTableReference [ScalarExpression vSource, Identifier vChunkType] + returns [AIGenerateFixedChunksTableReference vResult = FragmentFactory.CreateFragment()] +{ + Identifier vChunkSizeParam; + Identifier vOverlapParam = null; + Identifier vEnableChunkSetIdParam = null; + + ScalarExpression vChunkSize = null; + ScalarExpression vOverlap = null; + ScalarExpression vEnableChunkSetId = null; +} + : + { + Match(vChunkType, CodeGenerationSupporter.Fixed); + vResult.Source = vSource; + vResult.ChunkType = vChunkType; + } + vChunkSizeParam = identifier + { + Match(vChunkSizeParam, CodeGenerationSupporter.ChunkSize); + } + EqualsSign + vChunkSize = expression + { + vResult.ChunkSize = vChunkSize; + } + + ( + Comma + vOverlapParam = identifier + { + Match(vOverlapParam, CodeGenerationSupporter.Overlap); + } + EqualsSign + vOverlap = expression + { + vResult.Overlap = vOverlap; + } + )? + + ( + Comma + vEnableChunkSetIdParam = identifier + { + Match(vEnableChunkSetIdParam, CodeGenerationSupporter.EnableChunkSetId); + } + EqualsSign + vEnableChunkSetId = expression + { + vResult.EnableChunkSetId = vEnableChunkSetId; + } + )? + ; + +vectorSearchTableReference returns [VectorSearchTableReference vResult = FragmentFactory.CreateFragment()] +{ + TableReferenceWithAlias vTable; + ColumnReferenceExpression vColumn; + ScalarExpression vSimilarTo; + StringLiteral vMetric; + IntegerLiteral vTopN; +} + : + tVectorSearch:Identifier LeftParenthesis + { + Match(tVectorSearch, CodeGenerationSupporter.VectorSearch); + UpdateTokenInfo(vResult, tVectorSearch); + } + Table EqualsSign vTable = mergeTarget[false] + { + vResult.Table = vTable; + } + Comma Column EqualsSign vColumn = fixedColumn + { + vResult.Column = vColumn; + } + Comma tSimilarTo:Identifier EqualsSign vSimilarTo = expression + { + Match(tSimilarTo, CodeGenerationSupporter.SimilarTo); + vResult.SimilarTo = vSimilarTo; + } + Comma tMetric:Identifier EqualsSign vMetric = stringLiteral + { + Match(tMetric, CodeGenerationSupporter.Metric); + MatchString(vMetric, CodeGenerationSupporter.Cosine, CodeGenerationSupporter.Dot, CodeGenerationSupporter.Euclidean); + vResult.Metric = vMetric; + } + Comma tTopN:Identifier EqualsSign vTopN = integer + { + Match(tTopN, CodeGenerationSupporter.TopN); + vResult.TopN = vTopN; + } + RightParenthesis simpleTableReferenceAliasOpt[vResult] + ; + predictTableReference[SubDmlFlags subDmlFlags] returns [PredictTableReference vResult] - : - {NextTokenMatches(CodeGenerationSupporter.Predict)}? - tPredict:Identifier LeftParenthesis vResult = predictParams[subDmlFlags, ExpressionFlags.None] tRParen:RightParenthesis predictWithClauseOpt[vResult] simpleTableReferenceAliasOpt[vResult] - { - Match(tPredict, CodeGenerationSupporter.Predict); - UpdateTokenInfo(vResult, tPredict); - UpdateTokenInfo(vResult, tRParen); - } - ; + : + {NextTokenMatches(CodeGenerationSupporter.Predict)}? + tPredict:Identifier LeftParenthesis vResult = predictParams[subDmlFlags, ExpressionFlags.None] tRParen:RightParenthesis predictWithClauseOpt[vResult] simpleTableReferenceAliasOpt[vResult] + { + Match(tPredict, CodeGenerationSupporter.Predict); + UpdateTokenInfo(vResult, tPredict); + UpdateTokenInfo(vResult, tRParen); + } + ; predictParams[SubDmlFlags subDmlFlags, ExpressionFlags expressionFlags] returns [PredictTableReference vResult = FragmentFactory.CreateFragment()] { - ScalarExpression vModelVariable; - ScalarSubquery vModelSubquery; - TableReferenceWithAlias vDataSource; - Identifier vRuntime; -} - : - ( - tModelVariable:Identifier EqualsSign vModelVariable = expression - { - Match(tModelVariable, CodeGenerationSupporter.Model); - vResult.ModelVariable = vModelVariable; - UpdateTokenInfo(vResult, tModelVariable); - } - | tModelSubquery:Identifier EqualsSign vModelSubquery = subquery[SubDmlFlags.SelectNotForInsert, expressionFlags] - { - vResult.ModelSubquery = vModelSubquery; - } - ) - Comma tData:Identifier EqualsSign vDataSource = mergeTarget[false] - { - vResult.DataSource = vDataSource; - } - ( - Comma tRunTime:Identifier EqualsSign vRuntime = identifier - { - vResult.RunTime = vRuntime; - } - )? - ; + ScalarExpression vModelVariable; + ScalarSubquery vModelSubquery; + TableReferenceWithAlias vDataSource; + Identifier vRuntime; +} + : + ( + tModelVariable:Identifier EqualsSign vModelVariable = expression + { + Match(tModelVariable, CodeGenerationSupporter.Model); + vResult.ModelVariable = vModelVariable; + UpdateTokenInfo(vResult, tModelVariable); + } + | tModelSubquery:Identifier EqualsSign vModelSubquery = subquery[SubDmlFlags.SelectNotForInsert, expressionFlags] + { + vResult.ModelSubquery = vModelSubquery; + } + ) + Comma tData:Identifier EqualsSign vDataSource = mergeTarget[false] + { + vResult.DataSource = vDataSource; + } + ( + Comma tRunTime:Identifier EqualsSign vRuntime = identifier + { + vResult.RunTime = vRuntime; + } + )? + ; predictWithClauseOpt [PredictTableReference vParent] - : (With) => - ( - (With LeftParenthesis predictSchemaItemList[vParent] tRParen:RightParenthesis - { - UpdateTokenInfo(vParent,tRParen); - } - ) - ) - ; + : (With) => + ( + (With LeftParenthesis predictSchemaItemList[vParent] tRParen:RightParenthesis + { + UpdateTokenInfo(vParent,tRParen); + } + ) + ) + ; predictSchemaItemList [PredictTableReference vParent] { - SchemaDeclarationItem vItem; + SchemaDeclarationItem vItem; } - : vItem = predictSchemaItem - { - AddAndUpdateTokenInfo(vParent, vParent.SchemaDeclarationItems, vItem); - } - (Comma vItem = predictSchemaItem - { - AddAndUpdateTokenInfo(vParent, vParent.SchemaDeclarationItems, vItem); - } - )* - ; + : vItem = predictSchemaItem + { + AddAndUpdateTokenInfo(vParent, vParent.SchemaDeclarationItems, vItem); + } + (Comma vItem = predictSchemaItem + { + AddAndUpdateTokenInfo(vParent, vParent.SchemaDeclarationItems, vItem); + } + )* + ; predictSchemaItem returns [SchemaDeclarationItem vResult = FragmentFactory.CreateFragment()] { - ValueExpression vMapping; - ColumnDefinitionBase vColumn; -} - : vColumn = columnDefinitionBasic - { - vResult.ColumnDefinition = vColumn; - } - (vMapping = stringLiteral - { - vResult.Mapping = vMapping; - } - )? - (As tPredict:Identifier - { - Match(tPredict, CodeGenerationSupporter.Predict); - } - )? - ; + ValueExpression vMapping; + ColumnDefinitionBase vColumn; +} + : vColumn = columnDefinitionBasic + { + vResult.ColumnDefinition = vColumn; + } + (vMapping = stringLiteral + { + vResult.Mapping = vMapping; + } + )? + (As tPredict:Identifier + { + Match(tPredict, CodeGenerationSupporter.Predict); + } + )? + ; mergeTarget[bool indexHintAllowed] returns [TableReferenceWithAlias vResult] { - Identifier vAlias; -} - : - vResult=dmlTarget[indexHintAllowed] - ( - ( - As vAlias = identifier - { - vResult.Alias = vAlias; - } - ) - | - {!NextTokenMatches(CodeGenerationSupporter.Using)}? - ( - vAlias = identifier - { - vResult.Alias = vAlias; - } - ) - | - /* empty */ - ) - ; + Identifier vAlias; +} + : + vResult=dmlTarget[indexHintAllowed] + ( + ( + As vAlias = identifier + { + vResult.Alias = vAlias; + } + ) + | + {!NextTokenMatches(CodeGenerationSupporter.Using)}? + ( + vAlias = identifier + { + vResult.Alias = vAlias; + } + ) + | + /* empty */ + ) + ; changeTableTableReference returns [TableReferenceWithAliasAndColumns vResult] { @@ -20158,20 +20304,20 @@ insertColumn returns [ColumnReferenceExpression vResult = FragmentFactory.Create openRowsetColumn returns [OpenRowsetColumnDefinition vResult = FragmentFactory.CreateFragment()] { ColumnDefinitionBase vColumn; - IntegerLiteral vColumnOrdinal; - StringLiteral vStringLiteral; + IntegerLiteral vColumnOrdinal; + StringLiteral vStringLiteral; } : vColumn = columnDefinitionBasic - { - vResult.ColumnIdentifier = vColumn.ColumnIdentifier; - vResult.DataType = vColumn.DataType; - vResult.Collation = vColumn.Collation; - } - (vColumnOrdinal=integer + { + vResult.ColumnIdentifier = vColumn.ColumnIdentifier; + vResult.DataType = vColumn.DataType; + vResult.Collation = vColumn.Collation; + } + (vColumnOrdinal=integer { vResult.ColumnOrdinal = vColumnOrdinal; } - | vStringLiteral=stringLiteral + | vStringLiteral=stringLiteral { vResult.JsonPath = vStringLiteral; })? @@ -20264,13 +20410,23 @@ schemaObjectTableDmlTarget [bool indexHintAllowed] returns [NamedTableReference )? ; -schemaObjectOrFunctionTableReference returns [TableReference vResult] +schemaObjectOrFunctionTableReference returns [TableReference vResult = null] { SchemaObjectName vSchemaObjectName; } : vSchemaObjectName=schemaObjectFourPartName ( + { + vSchemaObjectName.BaseIdentifier != null && + vSchemaObjectName.BaseIdentifier.Value.Equals(CodeGenerationSupporter.AiGenerateChunks, StringComparison.OrdinalIgnoreCase) && + vSchemaObjectName.BaseIdentifier.QuoteType == QuoteType.NotQuoted && + LT(2).getText().Equals(CodeGenerationSupporter.Source, StringComparison.OrdinalIgnoreCase) + }? + { + vResult = aiGenerateChunksTableReference(); + } + | {IsTableReference(false)}? vResult=schemaObjectTableReference[vSchemaObjectName] | vResult=schemaObjectFunctionTableReference[vSchemaObjectName] @@ -20806,7 +20962,7 @@ openRowsetCosmos returns [OpenRowsetCosmos vResult = FragmentFactory.CreateFragm { long encountered = 0; OpenRowsetCosmosOption vOption; - OpenRowsetColumnDefinition vColumn; + OpenRowsetColumnDefinition vColumn; } : vOption = openRowsetCosmosOptionHint @@ -20867,7 +21023,7 @@ openRowsetBulk returns [BulkOpenRowset vResult = FragmentFactory.CreateFragment< BulkInsertOption vOption; StringLiteral vDataFile; - OpenRowsetColumnDefinition vColumn; + OpenRowsetColumnDefinition vColumn; } : Bulk (( @@ -20902,10 +21058,10 @@ openRowsetBulk returns [BulkOpenRowset vResult = FragmentFactory.CreateFragment< tRParen:RightParenthesis { CheckForDataFileFormatProhibitedOptionsInOpenRowsetBulk(encountered, vDataFile); - CheckForParquetFormatProhibitedOptionsInOpenRowsetBulk(encountered, vResult); + CheckForParquetFormatProhibitedOptionsInOpenRowsetBulk(encountered, vResult); UpdateTokenInfo(vResult,tRParen); } - (tWith:With + (tWith:With { UpdateTokenInfo(vResult,tWith); } @@ -21541,23 +21697,23 @@ simpleGroupByItem [ref bool alreadyEncounteredDistributedAggHint] returns [Expre { vResult.Expression = vExpression; } - ( - // Greedy due to conflict with withCommonTableExpressionsAndXmlNamespaces - options { greedy = true; } : - With LeftParenthesis tDistributedAgg:Identifier tRParen:RightParenthesis - { - Match(tDistributedAgg, CodeGenerationSupporter.DistributedAgg); + ( + // Greedy due to conflict with withCommonTableExpressionsAndXmlNamespaces + options { greedy = true; } : + With LeftParenthesis tDistributedAgg:Identifier tRParen:RightParenthesis + { + Match(tDistributedAgg, CodeGenerationSupporter.DistributedAgg); - if (alreadyEncounteredDistributedAggHint) - ThrowParseErrorException("SQL46129", tDistributedAgg, TSqlParserResource.SQL46129Message); + if (alreadyEncounteredDistributedAggHint) + ThrowParseErrorException("SQL46129", tDistributedAgg, TSqlParserResource.SQL46129Message); - vResult.DistributedAggregation = true; - UpdateTokenInfo(vResult, tDistributedAgg); - UpdateTokenInfo(vResult, tRParen); + vResult.DistributedAggregation = true; + UpdateTokenInfo(vResult, tDistributedAgg); + UpdateTokenInfo(vResult, tRParen); - alreadyEncounteredDistributedAggHint = true; - } - )? + alreadyEncounteredDistributedAggHint = true; + } + )? ; // End of Group By clause @@ -23281,9 +23437,9 @@ createColumnMasterKeyStatement returns [CreateColumnMasterKeyStatement vResult = columnMasterkeyParameter returns [ColumnMasterKeyParameter vResult] : {NextTokenMatches(CodeGenerationSupporter.KeyStoreProviderName)}? vResult = columnMasterKeyStoreProviderNameParameter - | {NextTokenMatches(CodeGenerationSupporter.KeyPath)}? + | {NextTokenMatches(CodeGenerationSupporter.KeyPath)}? vResult = columnMasterKeyPathParameter - | {NextTokenMatches(CodeGenerationSupporter.EnclaveComputations)}? + | {NextTokenMatches(CodeGenerationSupporter.EnclaveComputations)}? vResult = columnMasterKeyEnclaveComputationsParameter ; @@ -23311,14 +23467,14 @@ columnMasterKeyPathParameter returns [ColumnMasterKeyPathParameter vResult = Fra } ; - columnMasterKeyEnclaveComputationsParameter returns [ColumnMasterKeyEnclaveComputationsParameter vResult = FragmentFactory.CreateFragment()] + columnMasterKeyEnclaveComputationsParameter returns [ColumnMasterKeyEnclaveComputationsParameter vResult = FragmentFactory.CreateFragment()] { BinaryLiteral vSignature; } : tEnclaveComputations:Identifier tLeftParens:LeftParenthesis tSignature:Identifier tEquals3:EqualsSign vSignature=binary tRightParens:RightParenthesis { Match(tEnclaveComputations, CodeGenerationSupporter.EnclaveComputations); - Match(tSignature, CodeGenerationSupporter.Signature); + Match(tSignature, CodeGenerationSupporter.Signature); vResult.ParameterKind = ColumnMasterKeyParameterKind.Signature; vResult.Signature = vSignature; } @@ -23763,6 +23919,247 @@ dropSecurityPolicyStatement returns [DropSecurityPolicyStatement vResult = Fragm } ; +createExternalModelStatement returns [CreateExternalModelStatement vResult = FragmentFactory.CreateFragment()] +{ + Identifier vName; + long encounteredOptions = 0; +} + : tModel:Identifier vName = identifier + { + Match(tModel, CodeGenerationSupporter.Model); + vResult.Name = vName; + ThrowPartialAstIfPhaseOne(vResult); + } + authorizationOpt[vResult] + tWith:With LeftParenthesis + ( + {NextTokenMatches(CodeGenerationSupporter.Location)}? + externalModelLocation[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.ApiFormat)}? + externalModelApiFormat[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.ModelType)}? + externalModelModelType[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.ModelName)}? + externalModelModelName[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.Credential)}? + externalModelCredential[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.LocalRuntimePath)}? + externalModelLocalRuntimePath[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.Parameters)}? + externalModelParameters[vResult] + ) + + ( + tComma:Comma + ( + {NextTokenMatches(CodeGenerationSupporter.Location)}? + externalModelLocation[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.ApiFormat)}? + externalModelApiFormat[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.ModelType)}? + externalModelModelType[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.ModelName)}? + externalModelModelName[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.Credential)}? + externalModelCredential[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.LocalRuntimePath)}? + externalModelLocalRuntimePath[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.Parameters)}? + externalModelParameters[vResult] + ) + )* + + tRParen:RightParenthesis + { + UpdateTokenInfo(vResult,tRParen); + } + ; + +externalModelLocation[ExternalModelStatement vParent] +{ + StringLiteral vLocation; +} + : + tLocation:Identifier EqualsSign vLocation = stringLiteral + { + Match(tLocation, CodeGenerationSupporter.Location); + vParent.Location = vLocation; + } + ; + +externalModelApiFormat[ExternalModelStatement vParent] +{ +StringLiteral vApiFormat; +} +: + tApiFormat:Identifier EqualsSign vApiFormat = stringLiteral + { + Match(tApiFormat, CodeGenerationSupporter.ApiFormat); + vParent.ApiFormat = vApiFormat; + } +; + +externalModelModelType[ExternalModelStatement vParent] + : + tModelType:Identifier + { + Match(tModelType, CodeGenerationSupporter.ModelType); + UpdateTokenInfo(vParent, tModelType); + } + EqualsSign + ( + tEmbeddings:Identifier + { + if (TryMatch(tEmbeddings, CodeGenerationSupporter.Embeddings)) + { + vParent.ModelType = ExternalModelTypeOption.EMBEDDINGS; + UpdateTokenInfo(vParent, tEmbeddings); + } + else + { + ThrowIncorrectSyntaxErrorException(tEmbeddings); + } + } + ) + ; + +externalModelModelName[ExternalModelStatement vParent] +{ + StringLiteral vModelName; +} + : + tModelName:Identifier EqualsSign vModelName = stringLiteral + { + Match(tModelName, CodeGenerationSupporter.ModelName); + vParent.ModelName = vModelName; + } + ; + +externalModelCredential[ExternalModelStatement vParent] +{ +Identifier vCredential; +} +: + tCredential:Identifier EqualsSign vCredential = identifier + { + Match(tCredential, CodeGenerationSupporter.Credential); + vParent.Credential = vCredential; + } +; +externalModelLocalRuntimePath[ExternalModelStatement vParent] +{ +StringLiteral vLocalRuntimePath; +} + : + tLocalRuntimePath:Identifier EqualsSign vLocalRuntimePath = stringLiteral + { + Match(tLocalRuntimePath, CodeGenerationSupporter.LocalRuntimePath); + vParent.LocalRuntimePath = vLocalRuntimePath; + } + ; +externalModelParameters[ExternalModelStatement vParent] +{ + StringLiteral vParameters; +} + : + tParameters:Identifier EqualsSign vParameters = stringLiteral + { + Match(tParameters, CodeGenerationSupporter.Parameters); + vParent.Parameters = vParameters; + } + ; + +alterExternalModelStatement returns [AlterExternalModelStatement vResult = FragmentFactory.CreateFragment()] +{ + Identifier vName; + long encounteredOptions = 0; +} + : tModel:Identifier vName = identifier + { + Match(tModel, CodeGenerationSupporter.Model); + vResult.Name = vName; + ThrowPartialAstIfPhaseOne(vResult); + } + tSet:Set LeftParenthesis + ( + {NextTokenMatches(CodeGenerationSupporter.Location)}? + externalModelLocation[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.ApiFormat)}? + externalModelApiFormat[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.ModelType)}? + externalModelModelType[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.ModelName)}? + externalModelModelName[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.Credential)}? + externalModelCredential[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.LocalRuntimePath)}? + externalModelLocalRuntimePath[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.Parameters)}? + externalModelParameters[vResult] + ) + + ( + tComma:Comma + ( + {NextTokenMatches(CodeGenerationSupporter.Location)}? + externalModelLocation[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.ApiFormat)}? + externalModelApiFormat[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.ModelType)}? + externalModelModelType[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.ModelName)}? + externalModelModelName[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.Credential)}? + externalModelCredential[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.LocalRuntimePath)}? + externalModelLocalRuntimePath[vResult] + | + {NextTokenMatches(CodeGenerationSupporter.Parameters)}? + externalModelParameters[vResult] + ) + )* + + tRParen:RightParenthesis + { + UpdateTokenInfo(vResult,tRParen); + } + ; + +dropExternalModelStatement returns [DropExternalModelStatement vResult = FragmentFactory.CreateFragment()] +{ + Identifier vName; +} + : tModel:Identifier vName = identifier + { + Match(tModel, CodeGenerationSupporter.Model); + vResult.Name = vName; + ThrowPartialAstIfPhaseOne(vResult); + } + ; + createExternalDataSourceStatement returns [CreateExternalDataSourceStatement vResult = FragmentFactory.CreateFragment()] { Identifier vName; @@ -23852,11 +24249,11 @@ externalDataSourceType[CreateExternalDataSourceStatement vParent] UpdateTokenInfo(vParent, tExternalDataSourceType); vParent.DataSourceType = ExternalDataSourceType.BLOB_STORAGE; } - else - { - UpdateTokenInfo(vParent, tExternalDataSourceType); + else + { + UpdateTokenInfo(vParent, tExternalDataSourceType); vParent.DataSourceType = ExternalDataSourceType.EXTERNAL_GENERICS; - } + } } ) ; @@ -24026,7 +24423,7 @@ createExternalStreamStatement returns [CreateExternalStreamStatement vResult = F {NextTokenMatches(CodeGenerationSupporter.Location)}? externalStreamLocation[vResult] | - {NextTokenMatches(CodeGenerationSupporter.InputOptions)}? + {NextTokenMatches(CodeGenerationSupporter.InputOptions)}? externalStreamInputOptions[vResult] | {NextTokenMatches(CodeGenerationSupporter.OutputOptions)}? @@ -29393,11 +29790,11 @@ generatedAlwaysClause [ColumnDefinition vResult] } else if (TryMatch(tGeneratedType, CodeGenerationSupporter.TransactionId)) { - vResult.GeneratedAlways = GeneratedAlwaysType.TransactionIdStart; + vResult.GeneratedAlways = GeneratedAlwaysType.TransactionIdStart; } else if (TryMatch(tGeneratedType, CodeGenerationSupporter.SequenceNumber)) - { - vResult.GeneratedAlways = GeneratedAlwaysType.SequenceNumberStart; + { + vResult.GeneratedAlways = GeneratedAlwaysType.SequenceNumberStart; } else { @@ -29861,7 +30258,7 @@ uniqueTableConstraint [IndexAffectingStatement statementType] returns [UniqueCon ( uniqueConstraintEnforcement[vResult] | - uniqueConstraintTailOpt[statementType, vResult] + uniqueConstraintTailOpt[statementType, vResult] ) ; @@ -31629,6 +32026,9 @@ expressionPrimary [ExpressionFlags expressionFlags] returns [PrimaryExpression v | {NextTokenMatches(CodeGenerationSupporter.IIf) && (LA(2) == LeftParenthesis)}? vResult=iIfCall + | + {NextTokenMatches(CodeGenerationSupporter.AIGenerateEmbeddings) && LA(2) == LeftParenthesis}? + vResult = aiGenerateEmbeddingsFunctionCall | (Identifier LeftParenthesis)=> vResult=builtInFunctionCall @@ -31663,6 +32063,58 @@ expressionPrimary [ExpressionFlags expressionFlags] returns [PrimaryExpression v collationOpt[vResult] ; +aiGenerateEmbeddingsFunctionCall + returns [AIGenerateEmbeddingsFunctionCall vResult = this.FragmentFactory.CreateFragment()] +{ + ScalarExpression vInput; + SchemaObjectName vModelName; + ScalarExpression vParams = null; +} + : + tFunc:Identifier LeftParenthesis + { + Match(tFunc, CodeGenerationSupporter.AIGenerateEmbeddings); + UpdateTokenInfo(vResult, tFunc); + } + vInput=expression + { + vResult.Input = vInput; + } + + tUse:Use // your reserved keyword + { + UpdateTokenInfo(vResult, tUse); + } + + tModel:Identifier + { + Match(tModel, CodeGenerationSupporter.Model); + } + + vModelName=schemaObjectThreePartName + { + vResult.ModelName = vModelName; + } + + ( + tParams:Identifier + { + Match(tParams, CodeGenerationSupporter.Parameters); + } + LeftParenthesis + vParams=expression + RightParenthesis + { + vResult.OptionalParameters = vParams; + } + )? + + tRParen:RightParenthesis + { + UpdateTokenInfo(vResult, tRParen); + } + ; + parenthesisDisambiguatorForExpressions [ExpressionFlags expressionFlags] returns [PrimaryExpression vResult] : @@ -31962,6 +32414,36 @@ expressionList [TSqlFragment vParent, IList expressions] | /* empty */ ) + ( + jsonReturningClause[vParent] + | + /* empty */ + ) + ; + + jsonObjectAggExpressionList [FunctionCall vParent] + { + JsonKeyValue vExpression; + } + : + ( + vExpression=jsonKeyValueExpression + { + AddAndUpdateTokenInfo(vParent, vParent.JsonParameters, vExpression); + } + | + /* empty */ + ) + ( + jsonNullClauseFunction[vParent] + | + /* empty */ + ) + ( + jsonReturningClause[vParent] + | + /* empty */ + ) ; jsonNullClauseFunction [FunctionCall vParent] @@ -31970,7 +32452,7 @@ expressionList [TSqlFragment vParent, IList expressions] Identifier vAbsent; } : - ( + ( Null On Null { vNull = FragmentFactory.CreateFragment(); @@ -31988,24 +32470,40 @@ expressionList [TSqlFragment vParent, IList expressions] } ) ; - + +jsonReturningClause [FunctionCall vParent] +{ + Identifier vJson; +} +: + tReturning:Identifier tJson:Identifier + { + Match(tReturning, CodeGenerationSupporter.Returning); + Match(tJson, CodeGenerationSupporter.Json); + UpdateTokenInfo(vParent,tJson); + vJson = FragmentFactory.CreateFragment(); + AddAndUpdateTokenInfo(vParent, vParent.ReturnType, vJson); + vJson.SetUnquotedIdentifier(tJson.getText()); + } +; + jsonKeyValueExpression returns [JsonKeyValue vResult = FragmentFactory.CreateFragment()] { ScalarExpression vKey; ScalarExpression vValue; } - : + : ( vKey=expression - { - vResult.JsonKeyName=vKey; - } + { + vResult.JsonKeyName=vKey; + } Colon vValue=expression - { - vResult.JsonValue=vValue; + { + vResult.JsonValue=vValue; } - ) - ; + ) + ; windowClause returns [WindowClause vResult = FragmentFactory.CreateFragment()] { @@ -32284,6 +32782,9 @@ builtInFunctionCall returns [FunctionCall vResult = FragmentFactory.CreateFragme | {(vResult.FunctionName != null && vResult.FunctionName.Value.ToUpper(CultureInfo.InvariantCulture) == CodeGenerationSupporter.JsonObject)}? jsonObjectBuiltInFunctionCall[vResult] + | + {(vResult.FunctionName != null && vResult.FunctionName.Value.ToUpper(CultureInfo.InvariantCulture) == CodeGenerationSupporter.JsonObjectAgg)}? + jsonObjectAggBuiltInFunctionCall[vResult] | {(vResult.FunctionName != null && vResult.FunctionName.Value.ToUpper(CultureInfo.InvariantCulture) == CodeGenerationSupporter.Trim) && (NextTokenMatches(CodeGenerationSupporter.Leading) | NextTokenMatches(CodeGenerationSupporter.Trailing) | NextTokenMatches(CodeGenerationSupporter.Both))}? @@ -32317,6 +32818,11 @@ jsonArrayBuiltInFunctionCall [FunctionCall vParent] | /* empty */ ) + ( + jsonReturningClause[vParent] + | + /* empty */ + ) tRParen:RightParenthesis { UpdateTokenInfo(vParent, tRParen); @@ -32339,6 +32845,20 @@ jsonObjectBuiltInFunctionCall [FunctionCall vParent] } ; +jsonObjectAggBuiltInFunctionCall [FunctionCall vParent] +{ +} + : ( + jsonObjectAggExpressionList[vParent] + | + /* empty */ + ) + tRParen:RightParenthesis + { + UpdateTokenInfo(vParent, tRParen); + } + ; + regularBuiltInFunctionCall [FunctionCall vParent] { ColumnReferenceExpression vColumn; @@ -32402,19 +32922,19 @@ ignoreRespectNulls [FunctionCall vParent] Identifier vNulls; } : - tIgnoreOrRespect:Identifier + tIgnoreOrRespect:Identifier { - Match(tIgnoreOrRespect, CodeGenerationSupporter.Ignore, CodeGenerationSupporter.Respect); + Match(tIgnoreOrRespect, CodeGenerationSupporter.Ignore, CodeGenerationSupporter.Respect); vIgnoreOrRespect = FragmentFactory.CreateFragment(); - AddAndUpdateTokenInfo(vParent, vParent.IgnoreRespectNulls, vIgnoreOrRespect); - vIgnoreOrRespect.SetUnquotedIdentifier(tIgnoreOrRespect.getText()); + AddAndUpdateTokenInfo(vParent, vParent.IgnoreRespectNulls, vIgnoreOrRespect); + vIgnoreOrRespect.SetUnquotedIdentifier(tIgnoreOrRespect.getText()); } tNulls:Identifier { - Match(tNulls, CodeGenerationSupporter.Nulls); + Match(tNulls, CodeGenerationSupporter.Nulls); vNulls = FragmentFactory.CreateFragment(); - AddAndUpdateTokenInfo(vParent, vParent.IgnoreRespectNulls, vNulls); - vNulls.SetUnquotedIdentifier(tNulls.getText()); + AddAndUpdateTokenInfo(vParent, vParent.IgnoreRespectNulls, vNulls); + vNulls.SetUnquotedIdentifier(tNulls.getText()); } ; @@ -33480,9 +34000,9 @@ nonEmptyString returns [StringLiteral vResult] } ; - defaultValueLiteral returns [ScalarExpression vResult] - : vResult = literal - | vResult = signedIntegerOrReal; + defaultValueLiteral returns [ScalarExpression vResult] + : vResult = literal + | vResult = signedIntegerOrReal; stringLiteral returns [StringLiteral vResult = this.FragmentFactory.CreateFragment()] : tAsciiStringLiteral:AsciiStringLiteral @@ -33744,6 +34264,7 @@ securityStatementPermission returns [Identifier vResult = this.FragmentFactory.C } : tId:Identifier + | AiGenerateEmbeddings | Add | All | Alter diff --git a/SqlScriptDom/Parser/TSql/TSql170ParserBaseInternal.cs b/SqlScriptDom/Parser/TSql/TSql170ParserBaseInternal.cs index 5c332e5..2ca8412 100644 --- a/SqlScriptDom/Parser/TSql/TSql170ParserBaseInternal.cs +++ b/SqlScriptDom/Parser/TSql/TSql170ParserBaseInternal.cs @@ -46,5 +46,29 @@ public TSql170ParserBaseInternal(bool initialQuotedIdentifiersOn) } #endregion + + /// + /// Parses security object kind with support for External Model (TSql170+) + /// + /// The first identifier. + /// The second identifier. + /// The security object kind. + protected SecurityObjectKind ParseSecurityObjectKindTSql170(Identifier identifier1, Identifier identifier2) + { + if (identifier1 == null) + { + throw new ArgumentNullException(nameof(identifier1)); + } + + switch (identifier1.Value.ToUpperInvariant()) + { + case CodeGenerationSupporter.External: + Match(identifier2, CodeGenerationSupporter.Model); + return SecurityObjectKind.ExternalModel; + default: + // Fall back to the base class implementation for all other cases + return TSql160ParserBaseInternal.ParseSecurityObjectKind(identifier1, identifier2); + } + } } } diff --git a/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGenerator.AlterExternalModelStatement.cs b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGenerator.AlterExternalModelStatement.cs new file mode 100644 index 0000000..3129899 --- /dev/null +++ b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGenerator.AlterExternalModelStatement.cs @@ -0,0 +1,121 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//------------------------------------------------------------------------------ + +using System.Globalization; +using System.Collections.Generic; +using Microsoft.SqlServer.TransactSql.ScriptDom; +namespace Microsoft.SqlServer.TransactSql.ScriptDom.ScriptGenerator +{ + partial class SqlScriptGeneratorVisitor + { + public override void ExplicitVisit(AlterExternalModelStatement node) + { + GenerateKeyword(TSqlTokenType.Alter); + GenerateSpaceAndIdentifier(CodeGenerationSupporter.External); + GenerateSpaceAndIdentifier(CodeGenerationSupporter.Model); + GenerateAlterExternalModelStatementBody(node); + } + + protected void GenerateAlterExternalModelStatementBody(AlterExternalModelStatement node) + { + // external model name + GenerateSpaceAndFragmentIfNotNull(node.Name); + + NewLine(); + GenerateKeywordAndSpace(TSqlTokenType.Set); + GenerateKeyword(TSqlTokenType.LeftParenthesis); + bool ifFirst = true; + // external model location + if (node.Location != null) + { + if (!ifFirst) + { + GenerateSymbol(TSqlTokenType.Comma); + } + ifFirst = false; + NewLine(); + GenerateNameEqualsValue(CodeGenerationSupporter.Location, node.Location); + } + + // external model API Format options + if (node.ApiFormat != null) + { + if (!ifFirst) + { + GenerateSymbol(TSqlTokenType.Comma); + } + ifFirst = false; + NewLine(); + GenerateNameEqualsValue(CodeGenerationSupporter.ApiFormat, node.ApiFormat); + } + + // external model Model Type options + if (node.ModelType == ExternalModelTypeOption.EMBEDDINGS) + { + if (!ifFirst) + { + GenerateSymbol(TSqlTokenType.Comma); + } + ifFirst = false; + ExternalModelTypeOption typeOption = ExternalModelTypeOption.EMBEDDINGS; + string externalModelTypeOption = GetValueForEnumKey(_externalModelTypeOption, typeOption); + NewLine(); + GenerateNameEqualsValue(CodeGenerationSupporter.ModelType, externalModelTypeOption); + } + + // external model name options + if (node.ModelName != null) + { + if (!ifFirst) + { + GenerateSymbol(TSqlTokenType.Comma); + } + ifFirst = false; + NewLine(); + GenerateNameEqualsValue(CodeGenerationSupporter.ModelName, node.ModelName); + } + + // external model credential options + if (node.Credential != null) + { + if (!ifFirst) + { + GenerateSymbol(TSqlTokenType.Comma); + } + ifFirst = false; + NewLine(); + GenerateNameEqualsValue(CodeGenerationSupporter.Credential, node.Credential); + } + + // external model parameters options + if (node.Parameters != null) + { + if (!ifFirst) + { + GenerateSymbol(TSqlTokenType.Comma); + } + ifFirst = false; + NewLine(); + GenerateNameEqualsValue(CodeGenerationSupporter.Parameters, node.Parameters); + } + + // external model local runtime path options + if (node.LocalRuntimePath != null) + { + if (!ifFirst) + { + GenerateSymbol(TSqlTokenType.Comma); + } + ifFirst = false; + NewLine(); + GenerateNameEqualsValue(CodeGenerationSupporter.LocalRuntimePath, node.LocalRuntimePath); + } + + NewLine(); + GenerateKeyword(TSqlTokenType.RightParenthesis); + } + } +} diff --git a/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGenerator.DropExternalModelStatement.cs b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGenerator.DropExternalModelStatement.cs new file mode 100644 index 0000000..707fe8f --- /dev/null +++ b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGenerator.DropExternalModelStatement.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.SqlServer.TransactSql.ScriptDom.ScriptGenerator +{ + partial class SqlScriptGeneratorVisitor + { + // Generates the statement + // DROP EXTERNAL MODEL [{node.Name}] + // + public override void ExplicitVisit(DropExternalModelStatement node) + { + GenerateKeyword(TSqlTokenType.Drop); + GenerateSpaceAndIdentifier(CodeGenerationSupporter.External); + GenerateSpaceAndIdentifier(CodeGenerationSupporter.Model); + + GenerateSpaceAndFragmentIfNotNull(node.Name); + } + } +} diff --git a/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.AIGenerateFixedChunksTableReference.cs b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.AIGenerateFixedChunksTableReference.cs new file mode 100644 index 0000000..318cee0 --- /dev/null +++ b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.AIGenerateFixedChunksTableReference.cs @@ -0,0 +1,31 @@ +//------------------------------------------------------------------------------ +// +// 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(AIGenerateFixedChunksTableReference node) + { + List<(string, TSqlFragment)> specificParameters = new List<(string, TSqlFragment)>(); + specificParameters.Add((CodeGenerationSupporter.ChunkSize, node.ChunkSize)); + + if (node.Overlap != null) + { + specificParameters.Add((CodeGenerationSupporter.Overlap, node.Overlap)); + } + + if (node.EnableChunkSetId != null) + { + specificParameters.Add((CodeGenerationSupporter.EnableChunkSetId, node.EnableChunkSetId)); + } + + GenerateAIChunkTableReference(node, specificParameters); + } + } +} diff --git a/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.AiGenerateChunksTableReference.cs b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.AiGenerateChunksTableReference.cs new file mode 100644 index 0000000..eefa100 --- /dev/null +++ b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.AiGenerateChunksTableReference.cs @@ -0,0 +1,51 @@ +//------------------------------------------------------------------------------ +// +// 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 void GenerateNameValuePairs(IList<(string Name, TSqlFragment Value)> pairs) + { + for (int index = 0; index < pairs.Count; index++) + { + (string name, TSqlFragment value) = pairs[index]; + + if (index > 0) + { + GenerateSymbol(TSqlTokenType.Comma); + GenerateSpace(); + } + + GenerateIdentifierWithoutCasing(name); + GenerateSpace(); + GenerateSymbol(TSqlTokenType.EqualsSign); + GenerateSpace(); + GenerateFragmentIfNotNull(value); + } + } + + public void GenerateAIChunkTableReference(AIGenerateChunksTableReference node, IList<(string, TSqlFragment)> additionalParameters) + { + GenerateIdentifierWithoutCasing(CodeGenerationSupporter.AiGenerateChunks); + GenerateSpaceAndSymbol(TSqlTokenType.LeftParenthesis); + + // Include common parameters: source, chunk_type + List<(string, TSqlFragment)> parameters = new List<(string, TSqlFragment)>(); + parameters.Add((CodeGenerationSupporter.Source, node.Source)); + parameters.Add((CodeGenerationSupporter.ChunkType, node.ChunkType)); + parameters.AddRange(additionalParameters); + + GenerateNameValuePairs(parameters); + + GenerateSymbol(TSqlTokenType.RightParenthesis); + + GenerateSpaceAndAlias(node.Alias); + } + } +} diff --git a/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.AiGenerateEmbeddingsFunction.cs b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.AiGenerateEmbeddingsFunction.cs new file mode 100644 index 0000000..0efdc60 --- /dev/null +++ b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.AiGenerateEmbeddingsFunction.cs @@ -0,0 +1,48 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//------------------------------------------------------------------------------ + +using Microsoft.SqlServer.TransactSql.ScriptDom; + +namespace Microsoft.SqlServer.TransactSql.ScriptDom.ScriptGenerator +{ + partial class SqlScriptGeneratorVisitor + { + public override void ExplicitVisit(AIGenerateEmbeddingsFunctionCall node) + { + if (node.Input == null || node.ModelName == null) + { + return; + } + + // Emit function name without extra space before '(' + GenerateIdentifierWithoutCasing(CodeGenerationSupporter.AIGenerateEmbeddings); + GenerateSymbol(TSqlTokenType.LeftParenthesis); + + // Emit input expression + GenerateFragmentIfNotNull(node.Input); + + // Emit " USE MODEL" with explicit spaces + GenerateSpace(); + GenerateKeyword(TSqlTokenType.Use); + GenerateSpace(); + GenerateIdentifierWithoutCasing(CodeGenerationSupporter.Model); + GenerateSpaceAndFragmentIfNotNull(node.ModelName); + + // Emit optional PARAMETERS block + if (node.OptionalParameters != null) + { + GenerateSpace(); + GenerateIdentifierWithoutCasing(CodeGenerationSupporter.Parameters); + GenerateSpaceAndSymbol(TSqlTokenType.LeftParenthesis); + GenerateFragmentIfNotNull(node.OptionalParameters); + GenerateSymbol(TSqlTokenType.RightParenthesis); + } + + // Emit closing parenthesis + GenerateSymbol(TSqlTokenType.RightParenthesis); + } + } +} diff --git a/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.CreateExternalModelStatement.cs b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.CreateExternalModelStatement.cs new file mode 100644 index 0000000..8e01b6b --- /dev/null +++ b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.CreateExternalModelStatement.cs @@ -0,0 +1,122 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//------------------------------------------------------------------------------ +using System.Collections.Generic; +using System.Globalization; +using Microsoft.SqlServer.TransactSql.ScriptDom; +namespace Microsoft.SqlServer.TransactSql.ScriptDom.ScriptGenerator +{ + partial class SqlScriptGeneratorVisitor + { + public override void ExplicitVisit(CreateExternalModelStatement node) + { + GenerateKeyword(TSqlTokenType.Create); + GenerateSpaceAndIdentifier(CodeGenerationSupporter.External); + GenerateSpaceAndIdentifier(CodeGenerationSupporter.Model); + GenerateCreateExternalModelStatementBody(node); + } + protected static Dictionary _externalModelTypeOption = new Dictionary() + { + {ExternalModelTypeOption.EMBEDDINGS, CodeGenerationSupporter.Embeddings} + }; + + protected void GenerateCreateExternalModelStatementBody(CreateExternalModelStatement node) + { + // external model name + GenerateSpaceAndFragmentIfNotNull(node.Name); + GenerateOwnerIfNotNull(node.Owner); + + NewLine(); + GenerateKeywordAndSpace(TSqlTokenType.With); + GenerateKeyword(TSqlTokenType.LeftParenthesis); + bool ifFirst = true; + + // external model location + if (node.Location != null) + { + NewLine(); + GenerateNameEqualsValue(CodeGenerationSupporter.Location, node.Location); + ifFirst = false; + } + + // external model API Format options + if (node.ApiFormat != null) + { + if (!ifFirst) + { + GenerateSymbol(TSqlTokenType.Comma); + } + ifFirst = false; + NewLine(); + GenerateNameEqualsValue(CodeGenerationSupporter.ApiFormat, node.ApiFormat); + } + + // external model Model Type options + if (node.ModelType == ExternalModelTypeOption.EMBEDDINGS) + { + if (!ifFirst) + { + GenerateSymbol(TSqlTokenType.Comma); + } + ifFirst = false; + ExternalModelTypeOption typeOption = ExternalModelTypeOption.EMBEDDINGS; + string externalModelTypeOption = GetValueForEnumKey(_externalModelTypeOption, typeOption); + NewLine(); + GenerateNameEqualsValue(CodeGenerationSupporter.ModelType, externalModelTypeOption); + } + + // external model name options + if (node.ModelName != null) + { + if (!ifFirst) + { + GenerateSymbol(TSqlTokenType.Comma); + } + ifFirst = false; + NewLine(); + GenerateNameEqualsValue(CodeGenerationSupporter.ModelName, node.ModelName); + } + + // external model credential options + if (node.Credential != null) + { + if (!ifFirst) + { + GenerateSymbol(TSqlTokenType.Comma); + } + ifFirst = false; + NewLine(); + GenerateNameEqualsValue(CodeGenerationSupporter.Credential, node.Credential); + } + + // external model parameters options + if (node.Parameters != null) + { + if (!ifFirst) + { + GenerateSymbol(TSqlTokenType.Comma); + } + ifFirst = false; + NewLine(); + GenerateNameEqualsValue(CodeGenerationSupporter.Parameters, node.Parameters); + } + + // external model local runtime path options + if (node.LocalRuntimePath != null) + { + if (!ifFirst) + { + GenerateSymbol(TSqlTokenType.Comma); + } + ifFirst = false; + NewLine(); + GenerateNameEqualsValue(CodeGenerationSupporter.LocalRuntimePath, node.LocalRuntimePath); + } + + NewLine(); + GenerateKeyword(TSqlTokenType.RightParenthesis); + } + } +} diff --git a/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.FunctionCall.cs b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.FunctionCall.cs index daf325d..f4e50f9 100644 --- a/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.FunctionCall.cs +++ b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.FunctionCall.cs @@ -55,6 +55,20 @@ public override void ExplicitVisit(FunctionCall node) if (node.JsonParameters?.Count > 0 && node.AbsentOrNullOnNull?.Count > 0) //If there are values and null on null or absent on null present then generate space in between them GenerateSpace(); GenerateNullOnNullOrAbsentOnNull(node?.AbsentOrNullOnNull); + if (node.JsonParameters?.Count > 0 && node.ReturnType?.Count > 0) //If there are values and null on null or absent on null present then generate space in between them + GenerateSpace(); + GenerateReturnType(node?.ReturnType); + GenerateSymbol(TSqlTokenType.RightParenthesis); + } + else if (node.FunctionName.Value.ToUpper(CultureInfo.InvariantCulture) == CodeGenerationSupporter.JsonObjectAgg) + { + GenerateCommaSeparatedList(node.JsonParameters); + if (node.JsonParameters?.Count > 0 && node.AbsentOrNullOnNull?.Count > 0) //If there are values and null on null or absent on null present then generate space in between them + GenerateSpace(); + GenerateNullOnNullOrAbsentOnNull(node?.AbsentOrNullOnNull); + if (node.JsonParameters?.Count > 0 && node.ReturnType?.Count > 0) //If there are values and null on null or absent on null present then generate space in between them + GenerateSpace(); + GenerateReturnType(node?.ReturnType); GenerateSymbol(TSqlTokenType.RightParenthesis); } else if (node.FunctionName.Value.ToUpper(CultureInfo.InvariantCulture) == CodeGenerationSupporter.JsonArray) @@ -63,6 +77,9 @@ public override void ExplicitVisit(FunctionCall node) if (node.Parameters?.Count > 0 && node?.AbsentOrNullOnNull?.Count > 0) //If there are values and null on null or absent on null present then generate space in between them GenerateSpace(); GenerateNullOnNullOrAbsentOnNull(node?.AbsentOrNullOnNull); + if (node.ReturnType?.Count > 0) //If there are values and null on null or absent on null present then generate space in between them + GenerateSpace(); + GenerateReturnType(node?.ReturnType); GenerateSymbol(TSqlTokenType.RightParenthesis); } else @@ -117,5 +134,14 @@ private void GenerateNullOnNullOrAbsentOnNull(IList list) GenerateKeyword(TSqlTokenType.Null); } } + private void GenerateReturnType(IList list) + { + if (list?.Count > 0 && list[0].Value?.ToUpper(CultureInfo.InvariantCulture) == CodeGenerationSupporter.Json) + { + GenerateIdentifier("RETURNING"); + GenerateSpace(); + GenerateSpaceSeparatedList(list); + } + } } } diff --git a/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.SecurityTargetObject.cs b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.SecurityTargetObject.cs index ebceaa0..571e65d 100644 --- a/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.SecurityTargetObject.cs +++ b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.SecurityTargetObject.cs @@ -13,7 +13,7 @@ partial class SqlScriptGeneratorVisitor protected static Dictionary> _securityObjectKindGenerators = new Dictionary>() { - { SecurityObjectKind.AvailabilityGroup, new List() { + { SecurityObjectKind.AvailabilityGroup, new List() { new IdentifierGenerator(CodeGenerationSupporter.Availability, true), new IdentifierGenerator(CodeGenerationSupporter.Group) }}, @@ -96,11 +96,15 @@ partial class SqlScriptGeneratorVisitor { SecurityObjectKind.FullTextStopList, new List() { new IdentifierGenerator(CodeGenerationSupporter.Fulltext, true), new KeywordGenerator(TSqlTokenType.StopList)}}, - + { SecurityObjectKind.SearchPropertyList, new List() { new IdentifierGenerator(CodeGenerationSupporter.Search, true), new IdentifierGenerator(CodeGenerationSupporter.Property, true), new IdentifierGenerator(CodeGenerationSupporter.List)}}, + + { SecurityObjectKind.ExternalModel, new List() { + new IdentifierGenerator(CodeGenerationSupporter.External, true), + new IdentifierGenerator(CodeGenerationSupporter.Model) }}, }; diff --git a/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.VectorSearchTableReference.cs b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.VectorSearchTableReference.cs new file mode 100644 index 0000000..55e4730 --- /dev/null +++ b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.VectorSearchTableReference.cs @@ -0,0 +1,56 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.SqlServer.TransactSql.ScriptDom.ScriptGenerator +{ + partial class SqlScriptGeneratorVisitor + { + /// + /// Script generator visitor for VECTOR_SEARCH function: https://learn.microsoft.com/sql/t-sql/functions/vector-search-transact-sql + /// Syntax: + /// VECTOR_SEARCH( + /// TABLE = object[AS source_table_alias], + /// COLUMN = vector_column, + /// SIMILAR_TO = query_vector, + /// METRIC = { 'cosine' | 'dot' | 'euclidean' }, + /// TOP_N = k + /// ) [AS result_table_alias] + /// + public override void ExplicitVisit(VectorSearchTableReference node) + { + AlignmentPoint start = new AlignmentPoint(); + MarkAndPushAlignmentPoint(start); + + GenerateIdentifier(CodeGenerationSupporter.VectorSearch); + GenerateSymbol(TSqlTokenType.LeftParenthesis); + + NewLineAndIndent(); + GenerateNameEqualsValue(TSqlTokenType.Table, node.Table); + GenerateSymbol(TSqlTokenType.Comma); + + NewLineAndIndent(); + GenerateNameEqualsValue(TSqlTokenType.Column, node.Column); + GenerateSymbol(TSqlTokenType.Comma); + + NewLineAndIndent(); + GenerateNameEqualsValue(CodeGenerationSupporter.SimilarTo, node.SimilarTo); + GenerateSymbol(TSqlTokenType.Comma); + + NewLineAndIndent(); + GenerateNameEqualsValue(CodeGenerationSupporter.Metric, node.Metric); + GenerateSymbol(TSqlTokenType.Comma); + + NewLineAndIndent(); + GenerateNameEqualsValue(CodeGenerationSupporter.TopN, node.TopN); + + NewLine(); + GenerateSymbol(TSqlTokenType.RightParenthesis); + GenerateSpaceAndAlias(node.Alias); + + PopAlignmentPoint(); + } + } +} diff --git a/Test/SqlDom/Baselines170/AiGenerateChunksTests170.sql b/Test/SqlDom/Baselines170/AiGenerateChunksTests170.sql new file mode 100644 index 0000000..8374acc --- /dev/null +++ b/Test/SqlDom/Baselines170/AiGenerateChunksTests170.sql @@ -0,0 +1,101 @@ +SELECT * +FROM AI_GENERATE_CHUNKS (SOURCE = 'some text', CHUNK_TYPE = fixed, CHUNK_SIZE = 5); + +SELECT * +FROM AI_GENERATE_CHUNKS (SOURCE = N'some text', CHUNK_TYPE = fixed, CHUNK_SIZE = 5); + +SELECT * +FROM AI_GENERATE_CHUNKS (SOURCE = 'some text', CHUNK_TYPE = fixed, CHUNK_SIZE = 5, OVERLAP = 50); + +SELECT * +FROM AI_GENERATE_CHUNKS (SOURCE = 'some text', CHUNK_TYPE = fixed, CHUNK_SIZE = 5, OVERLAP = NULL, ENABLE_CHUNK_SET_ID = 50); + +SELECT * +FROM AI_GENERATE_CHUNKS (SOURCE = 'some text', CHUNK_TYPE = fixed, CHUNK_SIZE = 5, OVERLAP = 10, ENABLE_CHUNK_SET_ID = 1); + +SELECT * +FROM AI_GENERATE_CHUNKS (SOURCE = @SOURCE, CHUNK_TYPE = fixed, CHUNK_SIZE = @CHUNK_SIZE); + +SELECT * +FROM AI_GENERATE_CHUNKS (SOURCE = @SOURCE, CHUNK_TYPE = fixed, CHUNK_SIZE = @CHUNK_SIZE, OVERLAP = @OVERLAP, ENABLE_CHUNK_SET_ID = @ENABLE_CHUNK_SET_ID); + +SELECT * +FROM AI_GENERATE_CHUNKS (SOURCE = NULL, CHUNK_TYPE = fixed, CHUNK_SIZE = 5); + +SELECT * +FROM t1 CROSS APPLY AI_GENERATE_CHUNKS (SOURCE = t1.c1, CHUNK_TYPE = fixed, CHUNK_SIZE = 10); + +SELECT * +FROM t1 CROSS APPLY AI_GENERATE_CHUNKS (SOURCE = 'some text', CHUNK_TYPE = fixed, CHUNK_SIZE = t1.c1); + +SELECT * +FROM t1 CROSS APPLY AI_GENERATE_CHUNKS (SOURCE = 'some text', CHUNK_TYPE = fixed, CHUNK_SIZE = 10, OVERLAP = t1.c1); + +SELECT * +FROM t1 CROSS APPLY AI_GENERATE_CHUNKS (SOURCE = 'some text', CHUNK_TYPE = fixed, CHUNK_SIZE = 10, OVERLAP = 5, ENABLE_CHUNK_SET_ID = t1.c1); + +SELECT * +FROM AI_GENERATE_CHUNKS (SOURCE = N'some text', CHUNK_TYPE = fixed, CHUNK_SIZE = NULL); + +SELECT * +FROM AI_GENERATE_CHUNKS (SOURCE = N'some text', CHUNK_TYPE = fixed, CHUNK_SIZE = 10, OVERLAP = NULL); + +SELECT * +FROM AI_GENERATE_CHUNKS (SOURCE = N'some text', CHUNK_TYPE = fixed, CHUNK_SIZE = 10, OVERLAP = 5, ENABLE_CHUNK_SET_ID = NULL); + +CREATE TABLE t2 ( + Id INT IDENTITY PRIMARY KEY, + Text NVARCHAR (MAX) +); +GO + +INSERT INTO t2 (Text) +VALUES (N'This is the first text.'), +(N'Second sample text.'), +(N'Third example text.'); +GO + +CREATE VIEW v_GeneratedChunksFromTable +AS +SELECT t2.Id, + chunks.* +FROM t2 CROSS APPLY AI_GENERATE_CHUNKS (SOURCE = t2.Text, CHUNK_TYPE = fixed, CHUNK_SIZE = 5) AS chunks; +GO + +CREATE PROCEDURE usp_GenerateChunks +AS +BEGIN + SELECT * + FROM AI_GENERATE_CHUNKS (SOURCE = N'This is some sample text that will be chunked.', CHUNK_TYPE = fixed, CHUNK_SIZE = 5, OVERLAP = 2); +END +GO + +CREATE FUNCTION dbo.AI_GENERATE_CHUNKS +(@input NVARCHAR (MAX)) +RETURNS NVARCHAR (MAX) +AS +BEGIN + RETURN CONCAT('Chunked: ', @input); +END +GO + +CREATE TABLE dbo.AI_GENERATE_CHUNKS ( + id INT PRIMARY KEY, + data NVARCHAR (MAX) +); + +SELECT SOURCE +FROM userTable CROSS APPLY dbo.AI_GENERATE_CHUNKS(target); + +SELECT SOURCE +FROM userTable CROSS APPLY dbo.[AI_GENERATE_CHUNKS](SOURCE); + + +SELECT SOURCE +FROM userTable CROSS APPLY dbo.AI_GENERATE_CHUNKS([SOURCE]); + +SELECT SOURCE +FROM userTable CROSS APPLY dbo.[AI_GENERATE_CHUNKS]([SOURCE]); + +SELECT * +FROM dbo.AI_GENERATE_CHUNKS(3); \ No newline at end of file diff --git a/Test/SqlDom/Baselines170/AiGenerateEmbeddingsTests170.sql b/Test/SqlDom/Baselines170/AiGenerateEmbeddingsTests170.sql new file mode 100644 index 0000000..72493c7 --- /dev/null +++ b/Test/SqlDom/Baselines170/AiGenerateEmbeddingsTests170.sql @@ -0,0 +1,52 @@ +SELECT AI_GENERATE_EMBEDDINGS('My Default Input Text' USE MODEL MyDefaultModel); +SELECT AI_GENERATE_EMBEDDINGS(N'My Default Input Text' USE MODEL MyDefaultModel); +SELECT AI_GENERATE_EMBEDDINGS('My Default Input Text' USE MODEL MyDefaultModel PARAMETERS (TRY_CONVERT (JSON, N'{}'))); +SELECT AI_GENERATE_EMBEDDINGS('My Default Input Text' USE MODEL dbo.MyDefaultModel); +SELECT AI_GENERATE_EMBEDDINGS('My Default Input Text' USE MODEL MyDatabase.dbo.MyDefaultModel); +GO + +CREATE FUNCTION dbo.AI_GENERATE_EMBEDDINGS +(@input NVARCHAR (MAX)) +RETURNS NVARCHAR (MAX) +AS +BEGIN + RETURN CONCAT('Embed: ', @input); +END +GO + +CREATE TABLE dbo.AI_GENERATE_EMBEDDINGS ( + id INT PRIMARY KEY, + data NVARCHAR (MAX) +); +GO + +CREATE VIEW dbo.ai_generate_embeddings +AS +SELECT 'View result' AS result; +GO + +CREATE FUNCTION dbo.MyEmbeddingFunction +( ) +RETURNS TABLE +AS +RETURN + SELECT AI_GENERATE_EMBEDDINGS('Function Input' USE MODEL MyDefaultModel) AS EmbeddingResult +GO + +CREATE VIEW dbo.MyEmbeddingView +AS +SELECT AI_GENERATE_EMBEDDINGS(N'View Input' USE MODEL dbo.MyDefaultModel) AS EmbeddingResult; +GO + +CREATE TABLE dbo.SimpleEmbeddingTable ( + InputText NVARCHAR (MAX), + Embedding AS CONVERT (NVARCHAR (MAX), AI_GENERATE_EMBEDDINGS(InputText USE MODEL MyDefaultModel)) +); +GO + +CREATE PROCEDURE dbo.GetEmbedding +@InputText NVARCHAR (MAX) +AS +BEGIN + SELECT CONVERT (NVARCHAR (MAX), AI_GENERATE_EMBEDDINGS(@InputText USE MODEL MyDefaultModel)) AS Embedding; +END diff --git a/Test/SqlDom/Baselines170/AlterExternalModelStatementTests170.sql b/Test/SqlDom/Baselines170/AlterExternalModelStatementTests170.sql new file mode 100644 index 0000000..e9b590c --- /dev/null +++ b/Test/SqlDom/Baselines170/AlterExternalModelStatementTests170.sql @@ -0,0 +1,27 @@ +ALTER EXTERNAL MODEL abc +SET ( +LOCATION = 'new_location', +API_FORMAT = 'Ollama', +MODEL_TYPE = EMBEDDINGS, +MODEL = 'new_model', +PARAMETERS = '{"key":"new_value"}' +); +ALTER EXTERNAL MODEL abc +SET ( +MODEL = 'new_model' +); +ALTER EXTERNAL MODEL params_model +SET ( +PARAMETERS = '{"temperature":0.7, "max_tokens":2048}' +); +ALTER EXTERNAL MODEL ml_model +SET ( +API_FORMAT = 'OpenAI', +MODEL = 'gpt-3.5-turbo-16k', +PARAMETERS = '{"stream":true}' +); +ALTER EXTERNAL MODEL location_change +SET ( +LOCATION = '/new/model/path', +MODEL_TYPE = EMBEDDINGS +); \ No newline at end of file diff --git a/Test/SqlDom/Baselines170/CreateExternalModelStatementTests170.sql b/Test/SqlDom/Baselines170/CreateExternalModelStatementTests170.sql new file mode 100644 index 0000000..8891476 --- /dev/null +++ b/Test/SqlDom/Baselines170/CreateExternalModelStatementTests170.sql @@ -0,0 +1,33 @@ +CREATE EXTERNAL MODEL abc + AUTHORIZATION dbo +WITH ( +LOCATION = 'sdfasfd', +API_FORMAT = 'Ollama', +MODEL_TYPE = EMBEDDINGS, +MODEL = 'shghfh', +PARAMETERS = '{"key":"valuoipe"}' +); +CREATE EXTERNAL MODEL simple_model +WITH ( +LOCATION = '/models/simple', +API_FORMAT = 'OpenAI', +MODEL_TYPE = EMBEDDINGS, +MODEL = 'gpt-3.5-turbo' +); +CREATE EXTERNAL MODEL advanced_model +WITH ( +LOCATION = 'https://models.example.com/advanced', +API_FORMAT = 'Azure OpenAI', +MODEL_TYPE = EMBEDDINGS, +MODEL = 'bert-base-uncased', +PARAMETERS = '{"batch_size":32,"device":"cuda"}' +); +CREATE EXTERNAL MODEL [model_name] +WITH ( +LOCATION = 'FILE PATH', +API_FORMAT = 'onnx runtime', +MODEL_TYPE = EMBEDDINGS, +MODEL = 'text-embedding-ada-002,etc', +PARAMETERS = '{ "valid":"JSON"}', +LOCAL_RUNTIME_PATH = 'Path on local server to onnx runtime' +); \ No newline at end of file diff --git a/Test/SqlDom/Baselines170/DropExternalModelStatementTests170.sql b/Test/SqlDom/Baselines170/DropExternalModelStatementTests170.sql new file mode 100644 index 0000000..127b413 --- /dev/null +++ b/Test/SqlDom/Baselines170/DropExternalModelStatementTests170.sql @@ -0,0 +1 @@ +DROP EXTERNAL MODEL my_model1; \ No newline at end of file diff --git a/Test/SqlDom/Baselines170/JsonFunctionTests170.sql b/Test/SqlDom/Baselines170/JsonFunctionTests170.sql new file mode 100644 index 0000000..29adc38 --- /dev/null +++ b/Test/SqlDom/Baselines170/JsonFunctionTests170.sql @@ -0,0 +1,101 @@ +SELECT id, + json_col +FROM tab1 +WHERE ISJSON(json_col) = 1; + +SELECT id, + json_col +FROM tab1 +WHERE ISJSON(json_col, SCALAR) = 1; + +SELECT ISJSON('true', VALUE); + +DECLARE @jsonInfo AS NVARCHAR (MAX); + +SET @jsonInfo = N'{"info":{"address":[{"town":"Paris"},{"town":"London"}]}}'; + +SELECT JSON_PATH_EXISTS(@jsonInfo, '$.info.address'); + +SELECT JSON_OBJECT('name':'value'); + +SELECT JSON_OBJECT('name':'value', 'type':1 NULL ON NULL); + +SELECT JSON_OBJECT(NULL ON NULL); + +SELECT JSON_OBJECT('name':'value', 'type':NULL ABSENT ON NULL); + +SELECT JSON_OBJECT('name':'value', 'type':JSON_OBJECT('type_id':1, 'name':'a')); + +SELECT JSON_OBJECT(); + +SELECT JSON_OBJECT('name':'value', 'type':1); + +SELECT JSON_OBJECT('name':'value', 'type':JSON_ARRAY(1, 2)); + +DECLARE @id_key AS NVARCHAR (10) = N'id', @id_value AS NVARCHAR (64) = NEWID(); + +SELECT JSON_OBJECT('user_name':USER_NAME(), @id_key:@id_value, 'sid':(SELECT @@SPID)); + +SELECT s.session_id, + JSON_OBJECT('security_id':s.security_id, 'login':s.login_name, 'status':s.status) AS info +FROM sys.dm_exec_sessions AS s +WHERE s.is_user_process = 1; + +SELECT JSON_OBJECT('name':'b' RETURNING JSON); + +SELECT JSON_OBJECT('name':'b' NULL ON NULL RETURNING JSON); + +SELECT JSON_OBJECT('name':'b' ABSENT ON NULL RETURNING JSON); + +SELECT JSON_ARRAY('a', JSON_OBJECT('name':'value', 'type':1 NULL ON NULL) NULL ON NULL); + +SELECT JSON_ARRAY(); + +SELECT JSON_ARRAY('name'); + +SELECT JSON_ARRAY('a', 1, 'b', 2); + +SELECT JSON_ARRAY('a', 1, NULL, 2 NULL ON NULL); + +SELECT JSON_ARRAY('a', 1, NULL, 2 ABSENT ON NULL); + +SELECT JSON_ARRAY(NULL ON NULL); + +SELECT JSON_ARRAY(ABSENT ON NULL); + +DECLARE @id_value AS NVARCHAR (64) = NEWID(); + +SELECT JSON_ARRAY(1, @id_value, (SELECT @@SPID)); + +SELECT s.session_id, + JSON_ARRAY(s.host_name, s.program_name, s.client_interface_name) +FROM sys.dm_exec_sessions AS s +WHERE s.is_user_process = 1; + +SELECT JSON_ARRAY('a', 1, NULL, 2 RETURNING JSON); + +SELECT JSON_ARRAY('a', 1, NULL, 2 NULL ON NULL RETURNING JSON); + +SELECT JSON_ARRAY('a', 1, NULL, 2 ABSENT ON NULL RETURNING JSON); + +SELECT JSON_OBJECTAGG('name':'value'); + +SELECT JSON_OBJECTAGG('name':'value' NULL ON NULL); + +SELECT JSON_OBJECTAGG(NULL ON NULL); + +SELECT JSON_OBJECTAGG('name':NULL ABSENT ON NULL); + +SELECT JSON_OBJECTAGG('name':JSON_OBJECT('type_id':1, 'name':'a')); + +SELECT JSON_OBJECTAGG(); + +SELECT JSON_OBJECTAGG('name':1); + +SELECT JSON_OBJECTAGG('name':JSON_ARRAY(1, 2)); +SELECT JSON_OBJECTAGG('name':'b' NULL ON NULL RETURNING JSON); + +SELECT JSON_OBJECTAGG('name':'b' ABSENT ON NULL RETURNING JSON); + +SELECT JSON_OBJECTAGG('name':'b' RETURNING JSON); + diff --git a/Test/SqlDom/Baselines170/RegexpTests170.sql b/Test/SqlDom/Baselines170/RegexpTests170.sql new file mode 100644 index 0000000..e13c3da --- /dev/null +++ b/Test/SqlDom/Baselines170/RegexpTests170.sql @@ -0,0 +1,22 @@ +SELECT REGEXP_COUNT('hello', 'he(l+)o'); +SELECT REGEXP_COUNT('hello', 'he(l+)o', 1); +SELECT REGEXP_COUNT('hello', 'he(l+)o', 1, 'i'); + +SELECT REGEXP_INSTR('hello', 'he(l+)o'); +SELECT REGEXP_INSTR('hello', 'he(l+)o', 1); +SELECT REGEXP_INSTR('hello', 'he(l+)o', 1, 1); +SELECT REGEXP_INSTR('hello', 'he(l+)o', 1, 1, 0); +SELECT REGEXP_INSTR('hello', 'he(l+)o', 1, 1, 0, 'i'); +SELECT REGEXP_INSTR('hello', 'he(l+)o', 1, 1, 0, 'c', 1); + +SELECT REGEXP_REPLACE('hello', 'he(l+)o'); +SELECT REGEXP_REPLACE('hello', 'he(l+)o', 'hi\1o'); +SELECT REGEXP_REPLACE('hello', 'he(l+)o', 'hi\1o', 1); +SELECT REGEXP_REPLACE('hello', 'he(l+)o', 'hi\1o', 1, 1); +SELECT REGEXP_REPLACE('hello', 'he(l+)o', 'hi\1o', 1, 1, 'm'); + +SELECT REGEXP_SUBSTR('hello', 'he(l+)o'); +SELECT REGEXP_SUBSTR('hello', 'he(l+)o', 1); +SELECT REGEXP_SUBSTR('hello', 'he(l+)o', 1, 1); +SELECT REGEXP_SUBSTR('hello', 'he(l+)o', 1, 1, 's'); +SELECT REGEXP_SUBSTR('hello', 'he(l+)o', 1, 1, 'c', 1); \ No newline at end of file diff --git a/Test/SqlDom/Baselines170/SecurityStatementExternalModelTests170.sql b/Test/SqlDom/Baselines170/SecurityStatementExternalModelTests170.sql new file mode 100644 index 0000000..a64b7b7 --- /dev/null +++ b/Test/SqlDom/Baselines170/SecurityStatementExternalModelTests170.sql @@ -0,0 +1,71 @@ +GRANT ALTER ANY EXTERNAL MODEL TO datascientist; + +GRANT ALTER ANY EXTERNAL MODEL TO PUBLIC + WITH GRANT OPTION; + +GRANT ALTER ANY EXTERNAL MODEL TO mlrole, adminrole + AS dbo; + +GRANT EXECUTE + ON EXTERNAL MODEL::MyPredictionModel TO analyst; + +GRANT EXECUTE + ON EXTERNAL MODEL::schema1.ModelName TO user1, user2 + WITH GRANT OPTION; + +GRANT CONTROL + ON EXTERNAL MODEL::dbo.SalesModel TO mladmin + AS dbo; + +GRANT VIEW DEFINITION + ON EXTERNAL MODEL::MySchema.MyModel TO PUBLIC; + +DENY ALTER ANY EXTERNAL MODEL TO restricteduser; + +DENY EXECUTE + ON EXTERNAL MODEL::TestModel TO guest CASCADE; + +DENY CONTROL + ON EXTERNAL MODEL::test.model1 TO user1, user2 CASCADE + AS admin; + +REVOKE ALTER ANY EXTERNAL MODEL TO olduser; + +REVOKE GRANT OPTION FOR EXECUTE + ON EXTERNAL MODEL::MyModel TO tempuser CASCADE; + +REVOKE CONTROL + ON EXTERNAL MODEL::prod.RecommendationModel TO contractor + AS manager; + +REVOKE EXECUTE + ON EXTERNAL MODEL::dbo.CustomerModel TO PUBLIC CASCADE; + +ALTER AUTHORIZATION + ON EXTERNAL MODEL::MyModel + TO newowner; + +ALTER AUTHORIZATION + ON EXTERNAL MODEL::schema1.ModelName + TO SCHEMA OWNER; + +ALTER AUTHORIZATION + ON EXTERNAL MODEL::test.experimentalmodel + TO datateam; + +GRANT EXECUTE, VIEW DEFINITION + ON EXTERNAL MODEL::MultiPermModel TO analyst; + +DENY EXECUTE, CONTROL + ON EXTERNAL MODEL::RestrictedModel TO guest; + +REVOKE EXECUTE, VIEW DEFINITION + ON EXTERNAL MODEL::OldModel TO formeranalyst; + +GRANT EXECUTE + ON EXTERNAL MODEL::MyDatabase.MySchema.ModelWithSpaces TO testuser; + +DENY ALTER ANY EXTERNAL MODEL TO userwithspaces; + +REVOKE CONTROL + ON EXTERNAL MODEL::QuotedModel TO QuotedUser; \ No newline at end of file diff --git a/Test/SqlDom/Baselines170/VectorFunctionTests170.sql b/Test/SqlDom/Baselines170/VectorFunctionTests170.sql new file mode 100644 index 0000000..dc893ed --- /dev/null +++ b/Test/SqlDom/Baselines170/VectorFunctionTests170.sql @@ -0,0 +1,23 @@ +DECLARE @qv AS VECTOR (1536) = AI_GENERATE_EMBEDDINGS(N'Pink Floyd music style' USE MODEL Ada2Embeddings); + +SELECT t.id, + s.distance, + t.title +FROM VECTOR_SEARCH( + TABLE = [dbo].[wikipedia_articles_embeddings] AS t, + COLUMN = [content_vector], + SIMILAR_TO = @qv, + METRIC = 'cosine', + TOP_N = 10 + ) AS s +ORDER BY s.distance; + +SELECT * +FROM VECTOR_SEARCH( + TABLE = wikipedia_articles_embeddings, + COLUMN = dbo.wikipedia_articles_embeddings.content_vector, + SIMILAR_TO = @qv, + METRIC = 'dot', + TOP_N = 10 + ) +ORDER BY distance; \ No newline at end of file diff --git a/Test/SqlDom/Only170SyntaxTests.cs b/Test/SqlDom/Only170SyntaxTests.cs index 05ade64..a339cf7 100644 --- a/Test/SqlDom/Only170SyntaxTests.cs +++ b/Test/SqlDom/Only170SyntaxTests.cs @@ -13,7 +13,17 @@ public partial class SqlDomTests 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) + new ParserTest170("CreateColumnStoreIndexTests170.sql", nErrors80: 3, nErrors90: 3, nErrors100: 3, nErrors110: 3, nErrors120: 3, nErrors130: 0, nErrors140: 0, nErrors150: 0, nErrors160: 0), + new ParserTest170("RegexpTests170.sql", nErrors80: 0, nErrors90: 0, nErrors100: 0, nErrors110: 0, nErrors120: 0, nErrors130: 0, nErrors140: 0, nErrors150: 0, nErrors160: 0), + new ParserTest170("AiGenerateChunksTests170.sql", nErrors80: 21, nErrors90: 18, nErrors100: 17, nErrors110: 17, nErrors120: 17, nErrors130: 17, nErrors140: 17, nErrors150: 17, nErrors160: 17), + new ParserTest170("JsonFunctionTests170.sql", nErrors80: 9, nErrors90: 8, nErrors100: 30, nErrors110: 30, nErrors120: 30, nErrors130: 30, nErrors140: 30, nErrors150: 30, nErrors160: 30), + new ParserTest170("AiGenerateEmbeddingsTests170.sql", nErrors80: 12, nErrors90: 9, nErrors100: 9, nErrors110: 9, nErrors120: 9, nErrors130: 9, nErrors140: 9, nErrors150: 9, nErrors160: 9), + new ParserTest170("CreateExternalModelStatementTests170.sql", nErrors80: 2, nErrors90: 2, nErrors100: 2, nErrors110: 2, nErrors120: 2, nErrors130: 4, nErrors140: 4, nErrors150: 4, nErrors160: 4), + new ParserTest170("AlterExternalModelStatementTests170.sql", nErrors80: 2, nErrors90: 2, nErrors100: 2, nErrors110: 2, nErrors120: 2, nErrors130: 5, nErrors140: 5, nErrors150: 5, nErrors160: 5), + new ParserTest170("DropExternalModelStatementTests170.sql", nErrors80: 1, nErrors90: 1, nErrors100: 1, nErrors110: 1, nErrors120: 1, nErrors130: 1, nErrors140: 1, nErrors150: 1, nErrors160: 1), + new ParserTest170("VectorFunctionTests170.sql", nErrors80: 1, nErrors90: 1, nErrors100: 2, nErrors110: 2, nErrors120: 2, nErrors130: 2, nErrors140: 2, nErrors150: 2, nErrors160: 2), + new ParserTest170("SecurityStatementExternalModelTests170.sql", nErrors80: 2, nErrors90: 17, nErrors100: 17, nErrors110: 17, nErrors120: 17, nErrors130: 17, nErrors140: 17, nErrors150: 17, nErrors160: 17), + }; private static readonly ParserTest[] SqlAzure170_TestInfos = diff --git a/Test/SqlDom/ParserErrorsTests.cs b/Test/SqlDom/ParserErrorsTests.cs index 23d2be1..6a46317 100644 --- a/Test/SqlDom/ParserErrorsTests.cs +++ b/Test/SqlDom/ParserErrorsTests.cs @@ -503,6 +503,51 @@ public void JsonArraySyntaxNegativeTest() new ParserErrorInfo(48, "SQL46010", "ON")); } + /// + /// Negative tests for JSON_OBJECTAGG syntax in functions + /// + [TestMethod] + [Priority(0)] + [SqlStudioTestCategory(Category.UnitTest)] + public void JsonObjectAGGSyntaxNegativeTest() + { + // Incorrect key value parameter number + ParserTestUtils.ErrorTest170("SELECT JSON_OBJECTAGG('name':'value', 'type':1)", + new ParserErrorInfo(36, "SQL46010", ",")); + + // No closing quotation mark + ParserTestUtils.ErrorTest170("SELECT JSON_OBJECTAGG('name':'value)", + new ParserErrorInfo(29, "SQL46030", "'value)")); + + // Incorrect placing of colon + ParserTestUtils.ErrorTest170("SELECT JSON_OBJECTAGG('name':'value''type':1)", + new ParserErrorInfo(42, "SQL46010", ":")); + + // cannot use expression without colon + ParserTestUtils.ErrorTest170("SELECT JSON_OBJECTAGG('name')", + new ParserErrorInfo(22, "SQL46010", "'name'")); + + // cannot use expression without colon + ParserTestUtils.ErrorTest170("SELECT JSON_OBJECTAGG('name' ABSENT ON NULL)", + new ParserErrorInfo(29, "SQL46010", "ABSENT")); + + // Cannot use empty value + ParserTestUtils.ErrorTest170("SELECT JSON_OBJECTAGG('name':)", + new ParserErrorInfo(29, "SQL46010", ")")); + + // Cannot use incomplete absent on null clause cases + ParserTestUtils.ErrorTest170("SELECT JSON_OBJECTAGG('name':NULL ABSENT ON)", + new ParserErrorInfo(43, "SQL46010", ")")); + + // Cannot use Incomplete RETURNING clause + ParserTestUtils.ErrorTest170("SELECT JSON_OBJECTAGG('name':NULL RETURNING ON)", + new ParserErrorInfo(46, "SQL46010", ")")); + + // Cannot use anything other than JSON in RETURNING clause + ParserTestUtils.ErrorTest170("SELECT JSON_OBJECTAGG('name':NULL RETURNING INT)", + new ParserErrorInfo(44, "SQL46005", "JSON", "INT")); + } + /// /// Negative tests for Data Masking Alter Column syntax. /// @@ -6864,7 +6909,7 @@ FROM OPENROWSET ('a', 'b', [ab cd]) WITH a;"; ParserTestUtils.ErrorTest160(invalidWithClause3Syntax, new ParserErrorInfo(invalidWithClause3Syntax.IndexOf(@"a;"), "SQL46010", "a")); } - + /// /// Negative tests for Scalar Functions in Fabric DW. /// @@ -7031,5 +7076,412 @@ public void VectorIndexNegativeTests() ParserTestUtils.ErrorTest170("CREATE VECTOR INDEX IX_Test ON dbo.Documents (VectorData) WITH", new ParserErrorInfo(58, "SQL46010", "WITH")); } + + /// + /// Negative tests for AI_GENERATE_CHUNKS syntax + /// + [TestMethod] + [Priority(0)] + [SqlStudioTestCategory(Category.UnitTest)] + public void GenerateChunksNegativeTest170() + { + // Missing required parameters + ParserTestUtils.ErrorTest170( + "SELECT * FROM AI_GENERATE_CHUNKS(source = 'text')", + new ParserErrorInfo(48, "SQL46010", ")")); + + // Missing CHUNK_SIZE + ParserTestUtils.ErrorTest170( + "SELECT * FROM AI_GENERATE_CHUNKS(source = 'text', CHUNK_TYPE = fixed)", + new ParserErrorInfo(68, "SQL46010", ")")); + + // Invalid order: CHUNK_SIZE before CHUNK_TYPE + ParserTestUtils.ErrorTest170( + "SELECT * FROM AI_GENERATE_CHUNKS(source = 'text', CHUNK_SIZE = 5, CHUNK_TYPE = fixed)", + new ParserErrorInfo(50, "SQL46005", "CHUNK_TYPE", "CHUNK_SIZE")); + + // Invalid order: enable_chunk_set_id before overlap + ParserTestUtils.ErrorTest170( + "SELECT * FROM AI_GENERATE_CHUNKS(source = 'text', CHUNK_TYPE = fixed, CHUNK_SIZE = 5, enable_chunk_set_id = 1, overlap = 10)", + new ParserErrorInfo(86, "SQL46010", "enable_chunk_set_id")); + + // Invalid order: enable_chunk_set_id before CHUNK_SIZE + ParserTestUtils.ErrorTest170( + "SELECT * FROM AI_GENERATE_CHUNKS(source = 'text', CHUNK_TYPE = fixed, enable_chunk_set_id = 1, CHUNK_SIZE = 5, overlap = 10)", + new ParserErrorInfo(70, "SQL46010", "enable_chunk_set_id")); + + // Invalid value: CHUNK_TYPE = 'fixed' (should be keyword, not string) + ParserTestUtils.ErrorTest170( + "SELECT * FROM AI_GENERATE_CHUNKS(source = 'text', CHUNK_TYPE = 'fixed', CHUNK_SIZE = 5)", + new ParserErrorInfo(63, "SQL46010", "'fixed'")); + + // Invalid expression: CHUNK_TYPE = @CHUNK_TYPE (should not be variable) + ParserTestUtils.ErrorTest170( + "SELECT * FROM AI_GENERATE_CHUNKS(source = 'text', CHUNK_TYPE = @CHUNK_TYPE, CHUNK_SIZE = 5)", + new ParserErrorInfo(63, "SQL46010", "@CHUNK_TYPE")); + + // Invalid parameter: CHUNK_TYPE = t1.c1 (should not be column reference) + ParserTestUtils.ErrorTest170( + "SELECT * FROM t1 CROSS APPLY AI_GENERATE_CHUNKS(source = 'text', CHUNK_TYPE = t1.c1, CHUNK_SIZE = 5)", + new ParserErrorInfo(80, "SQL46010", ".")); + + // Missing value after equals + ParserTestUtils.ErrorTest170( + "SELECT * FROM AI_GENERATE_CHUNKS(source = , CHUNK_TYPE = fixed, CHUNK_SIZE = 5)", + new ParserErrorInfo(42, "SQL46010", ",")); + + // Missing value for CHUNK_SIZE + ParserTestUtils.ErrorTest170( + "SELECT * FROM AI_GENERATE_CHUNKS(source = 'text', CHUNK_TYPE = fixed, CHUNK_SIZE = )", + new ParserErrorInfo(83, "SQL46010", ")")); + + // Unknown parameter + ParserTestUtils.ErrorTest170( + "SELECT * FROM AI_GENERATE_CHUNKS(source = 'text', CHUNK_TYPE = fixed, CHUNK_SIZE = 5, invalid_param = 123)", + new ParserErrorInfo(86, "SQL46010", "invalid_param")); + + // Extra comma at end + ParserTestUtils.ErrorTest170( + "SELECT * FROM AI_GENERATE_CHUNKS(source = 'text', CHUNK_TYPE = fixed, CHUNK_SIZE = 5,)", + new ParserErrorInfo(85, "SQL46010", ")")); + + // Too many parameters + ParserTestUtils.ErrorTest170( + "SELECT * FROM AI_GENERATE_CHUNKS(source = 'text', CHUNK_TYPE = fixed, CHUNK_SIZE = 5, overlap = 1, enable_chunk_set_id = 2, extra = 3)", + new ParserErrorInfo(122, "SQL46010", ",")); + + // Function call with constant input, not keyword params + ParserTestUtils.ErrorTest170( + "SELECT * FROM ai_generate_chunks(3)", + new ParserErrorInfo(33, "SQL46010", "3")); + + // Missing paramter "source" + ParserTestUtils.ErrorTest170( + "SELECT source, target FROM userTable cross apply ai_generate_chunks(target)", + new ParserErrorInfo(68, "SQL46005", "SOURCE", "target")); + + // Misuse of parameter "source" + ParserTestUtils.ErrorTest170( + "SELECT source, target FROM userTable cross apply ai_generate_chunks(source)", + new ParserErrorInfo(74, "SQL46010", ")")); + + // Misuse of bracketed function name + ParserTestUtils.ErrorTest170( + "SELECT * FROM [ai_generate_chunks](source = 'something to chunk', chunk_type = fixed, chunk_size = 5)", + new ParserErrorInfo(42, "SQL46010", "=")); + + // Misuse of 2-part identifier + ParserTestUtils.ErrorTest170( + "SELECT * FROM dbo.ai_generate_chunks(source = 'something to chunk', chunk_type = fixed, chunk_size = 5)", + new ParserErrorInfo(36, "SQL46010", "(")); + + // 2-part identifier misuse in CROSS APPLY + ParserTestUtils.ErrorTest170( + "SELECT * FROM source CROSS APPLY dbo.ai_generate_chunks(source.c1)", + new ParserErrorInfo(55, "SQL46010", "(")); + + // 2-part identifier misuse in CROSS APPLY + ParserTestUtils.ErrorTest170( + "SELECT source, target FROM userTable cross apply dbo.ai_generate_chunks(source)", + new ParserErrorInfo(71, "SQL46010", "(")); + + // Invalid CHUNK_TYPE + ParserTestUtils.ErrorTest170( + "SELECT * FROM AI_GENERATE_CHUNKS (source = 'some text', chunk_type = other, chunk_size = 5)", + new ParserErrorInfo(69, "SQL46010", "other")); + } + + /// + /// Negative tests for AI_GENERATE_EMBEDDINGS syntax + /// + [TestMethod] + [Priority(0)] + [SqlStudioTestCategory(Category.UnitTest)] + public void GenerateEmbeddingsNegativeTest170() + { + // Missing required USE MODEL clause + ParserTestUtils.ErrorTest170( + "SELECT AI_GENERATE_EMBEDDINGS('My Default Input Text')", + new ParserErrorInfo(53, "SQL46010", ")")); + + // Missing model name after USE MODEL + ParserTestUtils.ErrorTest170( + "SELECT AI_GENERATE_EMBEDDINGS('My Default Input Text' USE MODEL)", + new ParserErrorInfo(63, "SQL46010", ")")); + + // Missing USE keyword before MODEL + ParserTestUtils.ErrorTest170( + "SELECT AI_GENERATE_EMBEDDINGS('My Default Input Text' MODEL MyModel)", + new ParserErrorInfo(54, "SQL46010", "MODEL")); + + // USE keyword misplaced before input expression + ParserTestUtils.ErrorTest170( + "SELECT AI_GENERATE_EMBEDDINGS(USE MODEL MyModel 'My Default Input Text')", + new ParserErrorInfo(30, "SQL46010", "USE")); + + // PARAMETERS specified without USE MODEL + ParserTestUtils.ErrorTest170( + "SELECT AI_GENERATE_EMBEDDINGS('My Default Input Text' PARAMETERS (TRY_CONVERT(JSON, N'{}')))", + new ParserErrorInfo(54, "SQL46010", "PARAMETERS")); + + // PARAMETERS missing parentheses + ParserTestUtils.ErrorTest170( + "SELECT AI_GENERATE_EMBEDDINGS('My Default Input Text' USE MODEL MyModel PARAMETERS TRY_CONVERT(JSON, N'{}'))", + new ParserErrorInfo(83, "SQL46010", "TRY_CONVERT")); + + // Invalid expression inside PARAMETERS (missing closing parenthesis) + ParserTestUtils.ErrorTest170( + "SELECT AI_GENERATE_EMBEDDINGS('My Default Input Text' USE MODEL MyModel PARAMETERS (TRY_CONVERT(JSON, N'{}')", + new ParserErrorInfo(108, "SQL46029", "EOF")); + + // Extra comma at end inside PARAMETERS + ParserTestUtils.ErrorTest170( + "SELECT AI_GENERATE_EMBEDDINGS('My Default Input Text' USE MODEL MyModel PARAMETERS (TRY_CONVERT(JSON, N'{}'),))", + new ParserErrorInfo(108, "SQL46010", ",")); + + // PARAMETERS misplaced before input + ParserTestUtils.ErrorTest170( + "SELECT AI_GENERATE_EMBEDDINGS(PARAMETERS (TRY_CONVERT(JSON, N'{}') 'My Default Input Text'))", + new ParserErrorInfo(67, "SQL46010", "'My Default Input Text'")); + + // Missing MODEL keyword after USE + ParserTestUtils.ErrorTest170( + "SELECT AI_GENERATE_EMBEDDINGS('My Default Input Text' USE MyModel)", + new ParserErrorInfo(58, "SQL46005", "MODEL", "MyModel")); + + // NULL model name after USE MODEL + ParserTestUtils.ErrorTest170( + "SELECT AI_GENERATE_EMBEDDINGS('My Default Input Text' USE MODEL NULL)", + new ParserErrorInfo(64, "SQL46010", "NULL")); + } + + + [TestMethod] + [Priority(0)] + [SqlStudioTestCategory(Category.UnitTest)] + public void CreateExternalModelNegativeTest() + { + // Keyword typos + // + ParserTestUtils.ErrorTest170( + "CREATE EXTERNAL MODLE abc WITH (LOCATION = 'www.somemodellocation.235',API_FORMAT = 'Ollama',MODEL_TYPE = EMBEDDIGS,MODEL = 'shghfh',PARAMETERS = '{\"key\":\"value\"}');", + new ParserErrorInfo(16, "SQL46010", "MODLE")); + + // Invalid Model type + // + ParserTestUtils.ErrorTest170( + "CREATE EXTERNAL MODEL abc WITH (LOCATION = 'www.somemodellocation.235',API_FORMAT = 'Ollama',MODEL_TYPE = EMBEDDIGS,MODEL = 'shghfh',PARAMETERS = '{\"key\":\"value\"}');", + new ParserErrorInfo(106, "SQL46010", "EMBEDDIGS")); + + // Model type not identifier + // + ParserTestUtils.ErrorTest170( + "CREATE EXTERNAL MODEL abc WITH (LOCATION = 'www.somemodellocation.235',API_FORMAT = 'Ollama',MODEL_TYPE = 'EMBEDDINGS',MODEL = 'shghfh',PARAMETERS = '{\"key\":\"value\"}');", + new ParserErrorInfo(106, "SQL46010", "'EMBEDDINGS'")); + + // Missing With Clause + // + ParserTestUtils.ErrorTest170( + "CREATE EXTERNAL MODEL abc (LOCATION = 'www.somemodellocation.235',API_FORMAT = 'Ollama',MODEL_TYPE = EMBEDDINGS,MODEL = 'shghfh',PARAMETERS = '{\"key\":\"value\"}');", + new ParserErrorInfo(26, "SQL46010", "(")); + + // Missing Model Name + // + ParserTestUtils.ErrorTest170( + "CREATE EXTERNAL MODEL WITH (LOCATION = 'www.somemodellocation.235',API_FORMAT = 'Ollama',MODEL_TYPE = EMBEDDINGS,MODEL = 'shghfh',PARAMETERS = '{\"key\":\"value\"}');", + new ParserErrorInfo(16, "SQL46010", "MODEL")); + } + + [TestMethod] + [Priority(0)] + [SqlStudioTestCategory(Category.UnitTest)] + public void AlterExternalModelNegativeTest() + { + // Keyword typos + // + ParserTestUtils.ErrorTest170( + "ALTER EXTERNAL MODLE abc SET (LOCATION = 'www.somemodellocation.235',API_FORMAT = 'Ollama',MODEL_TYPE = EMBEDDINGS,MODEL = 'shghfh',PARAMETERS = '{\"key\":\"value\"}');", + new ParserErrorInfo(15, "SQL46010", "MODLE")); + + // Invalid Model type + // + ParserTestUtils.ErrorTest170( + "ALTER EXTERNAL MODEL abc SET (MODEL_TYPE = EMBEDDINS);", + new ParserErrorInfo(43, "SQL46010", "EMBEDDINS")); + + // Model type not identifier + // + ParserTestUtils.ErrorTest170( + "ALTER EXTERNAL MODEL abc SET (LOCATION = 'www.somemodellocation.235',API_FORMAT = 'Ollama',MODEL_TYPE = 'EMBEDDINGS',MODEL = 'shghfh',PARAMETERS = '{\"key\":\"value\"}');", + new ParserErrorInfo(104, "SQL46010", "'EMBEDDINGS'")); + + // Missing SET Clause + // + ParserTestUtils.ErrorTest170( + "ALTER EXTERNAL MODEL abc (MODEL = 'shghfh');", + new ParserErrorInfo(25, "SQL46010", "(")); + + // WITH instead of SET clause + // + ParserTestUtils.ErrorTest170( + "ALTER EXTERNAL MODEL abc WITH (LOCATION = 'www.somemodellocation.235',API_FORMAT = 'Ollama',MODEL_TYPE = EMBEDDINGS,MODEL = 'shghfh',PARAMETERS = '{\"key\":\"value\"}');", + new ParserErrorInfo(25, "SQL46010", "WITH")); + + // Missing Model Name + // + ParserTestUtils.ErrorTest170( + "ALTER EXTERNAL MODEL SET (LOCATION = 'www.somemodellocation.235',API_FORMAT = 'Ollama',MODEL_TYPE = EMBEDDINGS,MODEL = 'shghfh',PARAMETERS = '{\"key\":\"value\"}');", + new ParserErrorInfo(15, "SQL46010", "MODEL")); + } + + [TestMethod] + [Priority(0)] + [SqlStudioTestCategory(Category.UnitTest)] + public void DropExternalModelNegativeTest() + { + // Keyword typos + // + ParserTestUtils.ErrorTest170( + "DROP EXTERNAL MODLE abc;", + new ParserErrorInfo(14, "SQL46010", "MODLE")); + + // Missing Model Name + // + ParserTestUtils.ErrorTest170( + "DROP EXTERNAL MODEL;", + new ParserErrorInfo(14, "SQL46010", "MODEL")); + + // Extra keyword + // + ParserTestUtils.ErrorTest170( + "DROP EXTERNAL MODEL abc WITH (LOCATION = 'www.somemodellocation.235');", + new ParserErrorInfo(29, "SQL46010", "(")); + } + + [TestMethod] + [Priority(0)] + [SqlStudioTestCategory(Category.UnitTest)] + public void VectorSearchErrorTest170() + { + // Missing required parameters: TABLE + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH()", + new ParserErrorInfo(28, "SQL46010", ")")); + + // Missing required parameters: COLUMN + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH(TABLE = tbl1)", + new ParserErrorInfo(40, "SQL46010", ")")); + + // Missing required parameters: SIMILAR_TO + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH(TABLE = tbl1, COLUMN = col1)", + new ParserErrorInfo(55, "SQL46010", ")")); + + // Missing required parameters: METRIC + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH(TABLE = tbl1, COLUMN = col1, SIMILAR_TO = query_vector)", + new ParserErrorInfo(82, "SQL46010", ")")); + + // Missing required parameters: TOP_N + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH(TABLE = tbl1, COLUMN = col1, SIMILAR_TO = query_vector, METRIC = 'dot')", + new ParserErrorInfo(98, "SQL46010", ")")); + + // Invalid order: COLUMN before TABLE + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH(COLUMN = col1, TABLE = tbl1, SIMILAR_TO = query_vector, METRIC = 'dot', TOP_N = 5)", + new ParserErrorInfo(28, "SQL46010", "COLUMN")); + + // Invalid order: SIMILAR_TO before COLUMN + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH(TABLE = tbl1, SIMILAR_TO = query_vector, COLUMN = col1, METRIC = 'dot', TOP_N = 5)", + new ParserErrorInfo(42, "SQL46010", "SIMILAR_TO")); + + // Invalid order: METRIC before SIMILAR_TO + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH(TABLE = tbl1, COLUMN = col1, METRIC = 'dot', SIMILAR_TO = query_vector, TOP_N = 5)", + new ParserErrorInfo(57, "SQL46005", "SIMILAR_TO", "METRIC")); + + // Invalid value: TABLE = 'tbl1' (should be identifier, not string) + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH(TABLE = 'tbl1', COLUMN = col1, SIMILAR_TO = query_vector, METRIC = 'dot', TOP_N = 5)", + new ParserErrorInfo(36, "SQL46010", "'tbl1'")); + + // Invalid value: TABLE = 123 (should be identifier, not integer) + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH(TABLE = 123, COLUMN = col1, SIMILAR_TO = query_vector, METRIC = 'dot', TOP_N = 5)", + new ParserErrorInfo(36, "SQL46010", "123")); + + // Invalid value: COLUMN = 'col1' (should be identifier, not string) + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH(TABLE = tbl1, COLUMN = 'col1', SIMILAR_TO = query_vector, METRIC = 'dot', TOP_N = 5)", + new ParserErrorInfo(51, "SQL46010", "'col1'")); + + // Invalid value: COLUMN = 123 (should be identifier, not integer) + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH(TABLE = tbl1, COLUMN = 123, SIMILAR_TO = query_vector, METRIC = 'dot', TOP_N = 5)", + new ParserErrorInfo(51, "SQL46010", "123")); + + // Invalid value: METRIC = dot (should be string literal) + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH(TABLE = tbl1, COLUMN = col1, SIMILAR_TO = query_vector, METRIC = dot, TOP_N = 5)", + new ParserErrorInfo(93, "SQL46010", "dot")); + + // Invalid value: METRIC = 'invalid_value' (should be either 'cosine', 'dot', or 'euclidean') + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH(TABLE = tbl1, COLUMN = col1, SIMILAR_TO = query_vector, METRIC = 'invalid_value', TOP_N = 5)", + new ParserErrorInfo(93, "SQL46010", "'invalid_value'")); + + // Invalid value: TOP_N = '5' (should be integer, not string) + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH(TABLE = tbl1, COLUMN = col1, SIMILAR_TO = query_vector, METRIC = 'dot', TOP_N = '5')", + new ParserErrorInfo(108, "SQL46010", "'5'")); + + // Invalid value: TOP_N = -5 (should be positive integer) + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH(TABLE = tbl1, COLUMN = col1, SIMILAR_TO = query_vector, METRIC = 'dot', TOP_N = -5)", + new ParserErrorInfo(108, "SQL46010", "-")); + + // Missing value after equals for TABLE + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH(TABLE = , COLUMN = col1, SIMILAR_TO = query_vector, METRIC = 'dot', TOP_N = 5)", + new ParserErrorInfo(36, "SQL46010", ",")); + + // Missing value after equals for COLUMN + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH(TABLE = tbl1, COLUMN = , SIMILAR_TO = query_vector, METRIC = 'dot', TOP_N = 5)", + new ParserErrorInfo(51, "SQL46010", ",")); + + // Missing value after equals for SIMILAR_TO + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH(TABLE = tbl1, COLUMN = col1, SIMILAR_TO = , METRIC = 'dot', TOP_N = 5)", + new ParserErrorInfo(70, "SQL46010", ",")); + + // Missing value after equals for METRIC + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH(TABLE = tbl1, COLUMN = col1, SIMILAR_TO = query_vector, METRIC = , TOP_N = 5)", + new ParserErrorInfo(93, "SQL46010", ",")); + + // Missing value after equals for TOP_N + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH(TABLE = tbl1, COLUMN = col1, SIMILAR_TO = query_vector, METRIC = 'dot', TOP_N = )", + new ParserErrorInfo(108, "SQL46010", ")")); + + // Extra parameter + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH(TABLE = tbl1, COLUMN = col1, SIMILAR_TO = query_vector, METRIC = 'dot', TOP_N = 5, EXTRA_PARAM = 'value')", + new ParserErrorInfo(109, "SQL46010", ",")); + + // Extra comma at end + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH(TABLE = tbl1, COLUMN = col1, SIMILAR_TO = query_vector, METRIC = 'dot', TOP_N = 5,)", + new ParserErrorInfo(109, "SQL46010", ",")); + + // Function call with constant input, not keyword params + ParserTestUtils.ErrorTest170( + "SELECT * FROM VECTOR_SEARCH('tbl1', 'col1', 'query_vector', 'dot', 5)", + new ParserErrorInfo(28, "SQL46010", "'tbl1'")); + } } } diff --git a/Test/SqlDom/TestScripts/AiGenerateChunksTests170.sql b/Test/SqlDom/TestScripts/AiGenerateChunksTests170.sql new file mode 100644 index 0000000..8374acc --- /dev/null +++ b/Test/SqlDom/TestScripts/AiGenerateChunksTests170.sql @@ -0,0 +1,101 @@ +SELECT * +FROM AI_GENERATE_CHUNKS (SOURCE = 'some text', CHUNK_TYPE = fixed, CHUNK_SIZE = 5); + +SELECT * +FROM AI_GENERATE_CHUNKS (SOURCE = N'some text', CHUNK_TYPE = fixed, CHUNK_SIZE = 5); + +SELECT * +FROM AI_GENERATE_CHUNKS (SOURCE = 'some text', CHUNK_TYPE = fixed, CHUNK_SIZE = 5, OVERLAP = 50); + +SELECT * +FROM AI_GENERATE_CHUNKS (SOURCE = 'some text', CHUNK_TYPE = fixed, CHUNK_SIZE = 5, OVERLAP = NULL, ENABLE_CHUNK_SET_ID = 50); + +SELECT * +FROM AI_GENERATE_CHUNKS (SOURCE = 'some text', CHUNK_TYPE = fixed, CHUNK_SIZE = 5, OVERLAP = 10, ENABLE_CHUNK_SET_ID = 1); + +SELECT * +FROM AI_GENERATE_CHUNKS (SOURCE = @SOURCE, CHUNK_TYPE = fixed, CHUNK_SIZE = @CHUNK_SIZE); + +SELECT * +FROM AI_GENERATE_CHUNKS (SOURCE = @SOURCE, CHUNK_TYPE = fixed, CHUNK_SIZE = @CHUNK_SIZE, OVERLAP = @OVERLAP, ENABLE_CHUNK_SET_ID = @ENABLE_CHUNK_SET_ID); + +SELECT * +FROM AI_GENERATE_CHUNKS (SOURCE = NULL, CHUNK_TYPE = fixed, CHUNK_SIZE = 5); + +SELECT * +FROM t1 CROSS APPLY AI_GENERATE_CHUNKS (SOURCE = t1.c1, CHUNK_TYPE = fixed, CHUNK_SIZE = 10); + +SELECT * +FROM t1 CROSS APPLY AI_GENERATE_CHUNKS (SOURCE = 'some text', CHUNK_TYPE = fixed, CHUNK_SIZE = t1.c1); + +SELECT * +FROM t1 CROSS APPLY AI_GENERATE_CHUNKS (SOURCE = 'some text', CHUNK_TYPE = fixed, CHUNK_SIZE = 10, OVERLAP = t1.c1); + +SELECT * +FROM t1 CROSS APPLY AI_GENERATE_CHUNKS (SOURCE = 'some text', CHUNK_TYPE = fixed, CHUNK_SIZE = 10, OVERLAP = 5, ENABLE_CHUNK_SET_ID = t1.c1); + +SELECT * +FROM AI_GENERATE_CHUNKS (SOURCE = N'some text', CHUNK_TYPE = fixed, CHUNK_SIZE = NULL); + +SELECT * +FROM AI_GENERATE_CHUNKS (SOURCE = N'some text', CHUNK_TYPE = fixed, CHUNK_SIZE = 10, OVERLAP = NULL); + +SELECT * +FROM AI_GENERATE_CHUNKS (SOURCE = N'some text', CHUNK_TYPE = fixed, CHUNK_SIZE = 10, OVERLAP = 5, ENABLE_CHUNK_SET_ID = NULL); + +CREATE TABLE t2 ( + Id INT IDENTITY PRIMARY KEY, + Text NVARCHAR (MAX) +); +GO + +INSERT INTO t2 (Text) +VALUES (N'This is the first text.'), +(N'Second sample text.'), +(N'Third example text.'); +GO + +CREATE VIEW v_GeneratedChunksFromTable +AS +SELECT t2.Id, + chunks.* +FROM t2 CROSS APPLY AI_GENERATE_CHUNKS (SOURCE = t2.Text, CHUNK_TYPE = fixed, CHUNK_SIZE = 5) AS chunks; +GO + +CREATE PROCEDURE usp_GenerateChunks +AS +BEGIN + SELECT * + FROM AI_GENERATE_CHUNKS (SOURCE = N'This is some sample text that will be chunked.', CHUNK_TYPE = fixed, CHUNK_SIZE = 5, OVERLAP = 2); +END +GO + +CREATE FUNCTION dbo.AI_GENERATE_CHUNKS +(@input NVARCHAR (MAX)) +RETURNS NVARCHAR (MAX) +AS +BEGIN + RETURN CONCAT('Chunked: ', @input); +END +GO + +CREATE TABLE dbo.AI_GENERATE_CHUNKS ( + id INT PRIMARY KEY, + data NVARCHAR (MAX) +); + +SELECT SOURCE +FROM userTable CROSS APPLY dbo.AI_GENERATE_CHUNKS(target); + +SELECT SOURCE +FROM userTable CROSS APPLY dbo.[AI_GENERATE_CHUNKS](SOURCE); + + +SELECT SOURCE +FROM userTable CROSS APPLY dbo.AI_GENERATE_CHUNKS([SOURCE]); + +SELECT SOURCE +FROM userTable CROSS APPLY dbo.[AI_GENERATE_CHUNKS]([SOURCE]); + +SELECT * +FROM dbo.AI_GENERATE_CHUNKS(3); \ No newline at end of file diff --git a/Test/SqlDom/TestScripts/AiGenerateEmbeddingsTests170.sql b/Test/SqlDom/TestScripts/AiGenerateEmbeddingsTests170.sql new file mode 100644 index 0000000..72493c7 --- /dev/null +++ b/Test/SqlDom/TestScripts/AiGenerateEmbeddingsTests170.sql @@ -0,0 +1,52 @@ +SELECT AI_GENERATE_EMBEDDINGS('My Default Input Text' USE MODEL MyDefaultModel); +SELECT AI_GENERATE_EMBEDDINGS(N'My Default Input Text' USE MODEL MyDefaultModel); +SELECT AI_GENERATE_EMBEDDINGS('My Default Input Text' USE MODEL MyDefaultModel PARAMETERS (TRY_CONVERT (JSON, N'{}'))); +SELECT AI_GENERATE_EMBEDDINGS('My Default Input Text' USE MODEL dbo.MyDefaultModel); +SELECT AI_GENERATE_EMBEDDINGS('My Default Input Text' USE MODEL MyDatabase.dbo.MyDefaultModel); +GO + +CREATE FUNCTION dbo.AI_GENERATE_EMBEDDINGS +(@input NVARCHAR (MAX)) +RETURNS NVARCHAR (MAX) +AS +BEGIN + RETURN CONCAT('Embed: ', @input); +END +GO + +CREATE TABLE dbo.AI_GENERATE_EMBEDDINGS ( + id INT PRIMARY KEY, + data NVARCHAR (MAX) +); +GO + +CREATE VIEW dbo.ai_generate_embeddings +AS +SELECT 'View result' AS result; +GO + +CREATE FUNCTION dbo.MyEmbeddingFunction +( ) +RETURNS TABLE +AS +RETURN + SELECT AI_GENERATE_EMBEDDINGS('Function Input' USE MODEL MyDefaultModel) AS EmbeddingResult +GO + +CREATE VIEW dbo.MyEmbeddingView +AS +SELECT AI_GENERATE_EMBEDDINGS(N'View Input' USE MODEL dbo.MyDefaultModel) AS EmbeddingResult; +GO + +CREATE TABLE dbo.SimpleEmbeddingTable ( + InputText NVARCHAR (MAX), + Embedding AS CONVERT (NVARCHAR (MAX), AI_GENERATE_EMBEDDINGS(InputText USE MODEL MyDefaultModel)) +); +GO + +CREATE PROCEDURE dbo.GetEmbedding +@InputText NVARCHAR (MAX) +AS +BEGIN + SELECT CONVERT (NVARCHAR (MAX), AI_GENERATE_EMBEDDINGS(@InputText USE MODEL MyDefaultModel)) AS Embedding; +END diff --git a/Test/SqlDom/TestScripts/AlterExternalModelStatementTests170.sql b/Test/SqlDom/TestScripts/AlterExternalModelStatementTests170.sql new file mode 100644 index 0000000..e9b590c --- /dev/null +++ b/Test/SqlDom/TestScripts/AlterExternalModelStatementTests170.sql @@ -0,0 +1,27 @@ +ALTER EXTERNAL MODEL abc +SET ( +LOCATION = 'new_location', +API_FORMAT = 'Ollama', +MODEL_TYPE = EMBEDDINGS, +MODEL = 'new_model', +PARAMETERS = '{"key":"new_value"}' +); +ALTER EXTERNAL MODEL abc +SET ( +MODEL = 'new_model' +); +ALTER EXTERNAL MODEL params_model +SET ( +PARAMETERS = '{"temperature":0.7, "max_tokens":2048}' +); +ALTER EXTERNAL MODEL ml_model +SET ( +API_FORMAT = 'OpenAI', +MODEL = 'gpt-3.5-turbo-16k', +PARAMETERS = '{"stream":true}' +); +ALTER EXTERNAL MODEL location_change +SET ( +LOCATION = '/new/model/path', +MODEL_TYPE = EMBEDDINGS +); \ No newline at end of file diff --git a/Test/SqlDom/TestScripts/CreateExternalModelStatementTests170.sql b/Test/SqlDom/TestScripts/CreateExternalModelStatementTests170.sql new file mode 100644 index 0000000..8891476 --- /dev/null +++ b/Test/SqlDom/TestScripts/CreateExternalModelStatementTests170.sql @@ -0,0 +1,33 @@ +CREATE EXTERNAL MODEL abc + AUTHORIZATION dbo +WITH ( +LOCATION = 'sdfasfd', +API_FORMAT = 'Ollama', +MODEL_TYPE = EMBEDDINGS, +MODEL = 'shghfh', +PARAMETERS = '{"key":"valuoipe"}' +); +CREATE EXTERNAL MODEL simple_model +WITH ( +LOCATION = '/models/simple', +API_FORMAT = 'OpenAI', +MODEL_TYPE = EMBEDDINGS, +MODEL = 'gpt-3.5-turbo' +); +CREATE EXTERNAL MODEL advanced_model +WITH ( +LOCATION = 'https://models.example.com/advanced', +API_FORMAT = 'Azure OpenAI', +MODEL_TYPE = EMBEDDINGS, +MODEL = 'bert-base-uncased', +PARAMETERS = '{"batch_size":32,"device":"cuda"}' +); +CREATE EXTERNAL MODEL [model_name] +WITH ( +LOCATION = 'FILE PATH', +API_FORMAT = 'onnx runtime', +MODEL_TYPE = EMBEDDINGS, +MODEL = 'text-embedding-ada-002,etc', +PARAMETERS = '{ "valid":"JSON"}', +LOCAL_RUNTIME_PATH = 'Path on local server to onnx runtime' +); \ No newline at end of file diff --git a/Test/SqlDom/TestScripts/DropExternalModelStatementTests170.sql b/Test/SqlDom/TestScripts/DropExternalModelStatementTests170.sql new file mode 100644 index 0000000..127b413 --- /dev/null +++ b/Test/SqlDom/TestScripts/DropExternalModelStatementTests170.sql @@ -0,0 +1 @@ +DROP EXTERNAL MODEL my_model1; \ No newline at end of file diff --git a/Test/SqlDom/TestScripts/JsonFunctionTests170.sql b/Test/SqlDom/TestScripts/JsonFunctionTests170.sql new file mode 100644 index 0000000..d15a477 --- /dev/null +++ b/Test/SqlDom/TestScripts/JsonFunctionTests170.sql @@ -0,0 +1,98 @@ +-- ISJSON +SELECT id, json_col +FROM tab1 +WHERE ISJSON(json_col) = 1 + +SELECT id, json_col +FROM tab1 +WHERE ISJSON(json_col, SCALAR) = 1 + +SELECT ISJSON('true', VALUE) + +-- JSON_PATH_EXISTS +DECLARE @jsonInfo NVARCHAR(MAX); +SET @jsonInfo=N'{"info":{"address":[{"town":"Paris"},{"town":"London"}]}}'; +SELECT JSON_PATH_EXISTS(@jsonInfo,'$.info.address'); + +SELECT JSON_OBJECT('name':'value'); + +SELECT JSON_OBJECT('name':'value', 'type':1 NULL ON NULL); + +SELECT JSON_OBJECT(NULL ON NULL); + +SELECT JSON_OBJECT('name':'value', 'type':NULL ABSENT ON NULL); + +SELECT JSON_OBJECT('name':'value', 'type':JSON_OBJECT('type_id':1, 'name':'a')); + +SELECT JSON_OBJECT(); + +SELECT JSON_OBJECT('name':'value', 'type':1); + +SELECT JSON_OBJECT('name':'value', 'type':JSON_ARRAY(1, 2)); + +DECLARE @id_key AS NVARCHAR (10) = N'id', @id_value AS NVARCHAR (64) = NEWID(); + +SELECT JSON_OBJECT('user_name':USER_NAME(), @id_key:@id_value, 'sid':(SELECT @@SPID)); + +SELECT s.session_id, + JSON_OBJECT('security_id':s.security_id, 'login':s.login_name, 'status':s.status) AS info +FROM sys.dm_exec_sessions AS s +WHERE s.is_user_process = 1; + +SELECT JSON_OBJECT('name':'b' RETURNING JSON); + +SELECT JSON_OBJECT('name':'b' NULL ON NULL RETURNING JSON); + +SELECT JSON_OBJECT('name':'b' ABSENT ON NULL RETURNING JSON); + +SELECT JSON_ARRAY('a', JSON_OBJECT('name':'value', 'type':1 NULL ON NULL) NULL ON NULL); + +SELECT JSON_ARRAY(); + +SELECT JSON_ARRAY('name'); + +SELECT JSON_ARRAY('a', 1, 'b', 2); + +SELECT JSON_ARRAY('a', 1, NULL, 2 NULL ON NULL); + +SELECT JSON_ARRAY('a', 1, NULL, 2 ABSENT ON NULL); + +SELECT JSON_ARRAY(NULL ON NULL); + +SELECT JSON_ARRAY(ABSENT ON NULL); + +DECLARE @id_value AS NVARCHAR (64) = NEWID(); + +SELECT JSON_ARRAY(1, @id_value, (SELECT @@SPID)); + +SELECT s.session_id, + JSON_ARRAY(s.host_name, s.program_name, s.client_interface_name) +FROM sys.dm_exec_sessions AS s +WHERE s.is_user_process = 1; + +SELECT JSON_ARRAY('a', 1, NULL, 2 RETURNING JSON); + +SELECT JSON_ARRAY('a', 1, NULL, 2 NULL ON NULL RETURNING JSON); + +SELECT JSON_ARRAY('a', 1, NULL, 2 ABSENT ON NULL RETURNING JSON); + +SELECT JSON_OBJECTAGG('name':'value'); + +SELECT JSON_OBJECTAGG('name':'value' NULL ON NULL); + +SELECT JSON_OBJECTAGG(NULL ON NULL); + +SELECT JSON_OBJECTAGG('name':NULL ABSENT ON NULL); + +SELECT JSON_OBJECTAGG('name':JSON_OBJECT('type_id':1, 'name':'a')); + +SELECT JSON_OBJECTAGG(); + +SELECT JSON_OBJECTAGG('name':1); + +SELECT JSON_OBJECTAGG('name':JSON_ARRAY(1, 2)); +SELECT JSON_OBJECTAGG('name':'b' NULL ON NULL RETURNING JSON); + +SELECT JSON_OBJECTAGG('name':'b' ABSENT ON NULL RETURNING JSON); + +SELECT JSON_OBJECTAGG('name':'b' RETURNING JSON); diff --git a/Test/SqlDom/TestScripts/RegexpTests170.sql b/Test/SqlDom/TestScripts/RegexpTests170.sql new file mode 100644 index 0000000..160857a --- /dev/null +++ b/Test/SqlDom/TestScripts/RegexpTests170.sql @@ -0,0 +1,26 @@ +-- REGEXP_COUNT(text, pattern [, start [, flags ]]) +SELECT REGEXP_COUNT('hello', 'he(l+)o'); +SELECT REGEXP_COUNT('hello', 'he(l+)o', 1); +SELECT REGEXP_COUNT('hello', 'he(l+)o', 1, 'i'); + +-- REGEXP_INSTR(text, pattern [, start [, occurrence [, return_option [, flags [, group ]]]]]) +SELECT REGEXP_INSTR('hello', 'he(l+)o'); +SELECT REGEXP_INSTR('hello', 'he(l+)o', 1); +SELECT REGEXP_INSTR('hello', 'he(l+)o', 1, 1); +SELECT REGEXP_INSTR('hello', 'he(l+)o', 1, 1, 0); +SELECT REGEXP_INSTR('hello', 'he(l+)o', 1, 1, 0, 'i'); +SELECT REGEXP_INSTR('hello', 'he(l+)o', 1, 1, 0, 'c', 1); + +-- REGEXP_REPLACE(text, pattern [, replacement [, start [, occurrence [, flags ]]]]) +SELECT REGEXP_REPLACE('hello', 'he(l+)o'); +SELECT REGEXP_REPLACE('hello', 'he(l+)o', 'hi\1o'); +SELECT REGEXP_REPLACE('hello', 'he(l+)o', 'hi\1o', 1); +SELECT REGEXP_REPLACE('hello', 'he(l+)o', 'hi\1o', 1, 1); +SELECT REGEXP_REPLACE('hello', 'he(l+)o', 'hi\1o', 1, 1, 'm'); + +-- REGEXP_SUBSTR(text, pattern [, start [, occurrence [, flags [, group ]]]]) +SELECT REGEXP_SUBSTR('hello', 'he(l+)o'); +SELECT REGEXP_SUBSTR('hello', 'he(l+)o', 1); +SELECT REGEXP_SUBSTR('hello', 'he(l+)o', 1, 1); +SELECT REGEXP_SUBSTR('hello', 'he(l+)o', 1, 1, 's'); +SELECT REGEXP_SUBSTR('hello', 'he(l+)o', 1, 1, 'c', 1); \ No newline at end of file diff --git a/Test/SqlDom/TestScripts/SecurityStatementExternalModelTests170.sql b/Test/SqlDom/TestScripts/SecurityStatementExternalModelTests170.sql new file mode 100644 index 0000000..04442d6 --- /dev/null +++ b/Test/SqlDom/TestScripts/SecurityStatementExternalModelTests170.sql @@ -0,0 +1,47 @@ +GRANT ALTER ANY EXTERNAL MODEL TO datascientist; +GRANT ALTER ANY EXTERNAL MODEL TO PUBLIC + WITH GRANT OPTION; +GRANT ALTER ANY EXTERNAL MODEL TO mlrole, adminrole + AS dbo; +GRANT EXECUTE + ON EXTERNAL MODEL::MyPredictionModel TO analyst; +GRANT EXECUTE + ON EXTERNAL MODEL::schema1.ModelName TO user1, user2 + WITH GRANT OPTION; +GRANT CONTROL + ON EXTERNAL MODEL::dbo.SalesModel TO mladmin + AS dbo; +GRANT VIEW DEFINITION + ON EXTERNAL MODEL::MySchema.MyModel TO PUBLIC; +DENY ALTER ANY EXTERNAL MODEL TO restricteduser; +DENY EXECUTE + ON EXTERNAL MODEL::TestModel TO guest + CASCADE; +DENY CONTROL + ON EXTERNAL MODEL::test.model1 TO user1, user2 + CASCADE + AS admin; +REVOKE ALTER ANY EXTERNAL MODEL FROM olduser; +REVOKE GRANT OPTION FOR EXECUTE + ON EXTERNAL MODEL::MyModel FROM tempuser + CASCADE; +REVOKE CONTROL + ON EXTERNAL MODEL::prod.RecommendationModel FROM contractor + AS manager; +REVOKE EXECUTE + ON EXTERNAL MODEL::dbo.CustomerModel FROM PUBLIC + CASCADE; +ALTER AUTHORIZATION ON EXTERNAL MODEL::MyModel TO newowner; +ALTER AUTHORIZATION ON EXTERNAL MODEL::schema1.ModelName TO SCHEMA OWNER; +ALTER AUTHORIZATION ON EXTERNAL MODEL::test.experimentalmodel TO datateam; +GRANT EXECUTE, VIEW DEFINITION + ON EXTERNAL MODEL::MultiPermModel TO analyst; +DENY EXECUTE, CONTROL + ON EXTERNAL MODEL::RestrictedModel TO guest; +REVOKE EXECUTE, VIEW DEFINITION + ON EXTERNAL MODEL::OldModel FROM formeranalyst; +GRANT EXECUTE + ON EXTERNAL MODEL::MyDatabase.MySchema.ModelWithSpaces TO testuser; +DENY ALTER ANY EXTERNAL MODEL TO userwithspaces; +REVOKE CONTROL + ON EXTERNAL MODEL::QuotedModel FROM QuotedUser; \ No newline at end of file diff --git a/Test/SqlDom/TestScripts/VectorFunctionTests170.sql b/Test/SqlDom/TestScripts/VectorFunctionTests170.sql new file mode 100644 index 0000000..1d1c679 --- /dev/null +++ b/Test/SqlDom/TestScripts/VectorFunctionTests170.sql @@ -0,0 +1,25 @@ +DECLARE @qv VECTOR(1536) = AI_GENERATE_EMBEDDINGS(N'Pink Floyd music style' USE MODEL Ada2Embeddings); + +SELECT + t.id, s.distance, t.title +FROM + VECTOR_SEARCH( + TABLE = [dbo].[wikipedia_articles_embeddings] as t, + COLUMN = [content_vector], + SIMILAR_TO = @qv, + METRIC = 'cosine', + TOP_N = 10 + ) AS s +ORDER BY s.distance + +SELECT + * +FROM + VECTOR_SEARCH( + TABLE = wikipedia_articles_embeddings, + COLUMN = dbo.wikipedia_articles_embeddings.content_vector, + SIMILAR_TO = @qv, + METRIC = 'dot', + TOP_N = 10 + ) +ORDER BY distance \ No newline at end of file diff --git a/global.json b/global.json index 457d429..b812260 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.117", + "version": "8.0.413", "rollForward": "latestMajor" }, "msbuild-sdks": { diff --git a/release-notes/170/170.82.0.md b/release-notes/170/170.82.0.md new file mode 100644 index 0000000..59e0112 --- /dev/null +++ b/release-notes/170/170.82.0.md @@ -0,0 +1,27 @@ +# Release Notes + +## Microsoft.SqlServer.TransactSql.ScriptDom 170.82.0 +This update brings the below changes over the previous release: + +### Target Platform Support + +* .NET Framework 4.7.2 (Windows x86, Windows x64) +* .NET 8 (Windows x86, Windows x64, Linux, macOS) +* .NET Standard 2.0+ (Windows x86, Windows x64, Linux, macOS) + +### Dependencies +* Updates.NET SDK to latest patch version 8.0.413 + +#### .NET Framework +#### .NET Core + +### New Features +* Adds support for `AI_GENERATE_CHUNKS`, `JSON_OBJECTAGG`, `AI_GENERATE_EMBEDDINGS` and `VECTOR_SEARCH` Functions. +* Adds supports for `EXTERNAL MODEL` object type. + +### Fixed + +### Changes +* Updated Fabric DW syntax to better match the definition for identity columns. + +### Known Issues