Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,14 @@ public static class DataTestUtility

// SQL server Version
private static string s_sQLServerVersion = string.Empty;
private static bool s_isTDS8Supported;

//SQL Server EngineEdition
private static string s_sqlServerEngineEdition;

// SQL Server capabilities
private static bool? s_isDataClassificationSupported;
private static bool? s_isVectorSupported;

// Azure Synapse EngineEditionId == 6
// More could be read at https://learn.microsoft.com/en-us/sql/t-sql/functions/serverproperty-transact-sql?view=sql-server-ver16#propertyname
public static bool IsAzureSynapse
Expand Down Expand Up @@ -130,17 +133,28 @@ public static string SQLServerVersion
}

// Is TDS8 supported
public static bool IsTDS8Supported
{
get
{
if (!string.IsNullOrEmpty(TCPConnectionString))
{
s_isTDS8Supported = GetSQLServerStatusOnTDS8(TCPConnectionString);
}
return s_isTDS8Supported;
}
}
public static bool IsTDS8Supported =>
IsTCPConnStringSetup() &&
GetSQLServerStatusOnTDS8(TCPConnectionString);

/// <summary>
/// Checks if object SYS.SENSITIVITY_CLASSIFICATIONS exists in SQL Server
/// </summary>
/// <returns>True, if target SQL Server supports Data Classification</returns>
public static bool IsDataClassificationSupported =>
s_isDataClassificationSupported ??= IsTCPConnStringSetup() &&
IsObjectPresent("SYS.SENSITIVITY_CLASSIFICATIONS");

/// <summary>
/// Determines whether the SQL Server supports the 'vector' data type.
/// </summary>
/// <remarks>This method attempts to connect to the SQL Server and check for the existence of the
/// 'vector' data type. If a connection cannot be established or an error occurs during the query, the method
/// returns <see langword="false"/>.</remarks>
/// <returns><see langword="true"/> if the 'vector' data type is supported; otherwise, <see langword="false"/>.</returns>
public static bool IsSqlVectorSupported =>
s_isVectorSupported ??= IsTCPConnStringSetup() &&
IsTypePresent("vector");

static DataTestUtility()
{
Expand Down Expand Up @@ -382,7 +396,7 @@ public static string GetSqlServerProperty(SqlConnection connection, ServerProper

#nullable disable

public static bool GetSQLServerStatusOnTDS8(string connectionString)
private static bool GetSQLServerStatusOnTDS8(string connectionString)
{
bool isTDS8Supported = false;
SqlConnectionStringBuilder builder = new(connectionString)
Expand Down Expand Up @@ -424,6 +438,28 @@ public static bool IsDatabasePresent(string name)
return present;
}

public static bool IsObjectPresent(string objectName)
{
using SqlConnection connection = new(TCPConnectionString);
using SqlCommand command = new("SELECT OBJECT_ID(@name)", connection);

connection.Open();
command.Parameters.AddWithValue("@name", objectName);

return command.ExecuteScalar() is not DBNull;
}

public static bool IsTypePresent(string typeName)
{
using SqlConnection connection = new(TCPConnectionString);
using SqlCommand command = new("SELECT COUNT(1) FROM SYS.TYPES WHERE [name] = @name", connection);

connection.Open();
command.Parameters.AddWithValue("@name", typeName);

return (int)command.ExecuteScalar() > 0;
}

public static bool IsAdmin
{
get
Expand All @@ -435,32 +471,6 @@ public static bool IsAdmin
}
}

/// <summary>
/// Checks if object SYS.SENSITIVITY_CLASSIFICATIONS exists in SQL Server
/// </summary>
/// <returns>True, if target SQL Server supports Data Classification</returns>
public static bool IsSupportedDataClassification()
{
try
{
using (var connection = new SqlConnection(TCPConnectionString))
using (var command = new SqlCommand("SELECT * FROM SYS.SENSITIVITY_CLASSIFICATIONS", connection))
{
connection.Open();
command.ExecuteNonQuery();
}
}
catch (SqlException e)
{
// Check for Error 208: Invalid Object Name
if (e.Errors != null && e.Errors[0].Number == 208)
{
return false;
}
}
return true;
}

public static bool IsDNSCachingSetup() => !string.IsNullOrEmpty(DNSCachingConnString);

// Synapse: Always Encrypted is not supported with Azure Synapse.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public static class DataClassificationTest
private static string s_tableName;

// Synapse: Azure Synapse does not support RANK
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse), nameof(DataTestUtility.IsSupportedDataClassification))]
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse), nameof(DataTestUtility.IsDataClassificationSupported))]
public static void TestDataClassificationResultSetRank()
{
s_tableName = DataTestUtility.GetLongName("DC");
Expand All @@ -25,7 +25,7 @@ public static void TestDataClassificationResultSetRank()
try
{
sqlConnection.Open();
Assert.True(DataTestUtility.IsSupportedDataClassification());
Assert.True(DataTestUtility.IsDataClassificationSupported);
CreateTable(sqlCommand);
AddSensitivity(sqlCommand, rankEnabled: true);
InsertData(sqlCommand);
Expand All @@ -38,7 +38,7 @@ public static void TestDataClassificationResultSetRank()
}
}

[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsSupportedDataClassification))]
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsDataClassificationSupported))]
public static void TestDataClassificationResultSet()
{
s_tableName = DataTestUtility.GetLongName("DC");
Expand All @@ -48,7 +48,7 @@ public static void TestDataClassificationResultSet()
try
{
sqlConnection.Open();
Assert.True(DataTestUtility.IsSupportedDataClassification());
Assert.True(DataTestUtility.IsDataClassificationSupported);
CreateTable(sqlCommand);
AddSensitivity(sqlCommand);
InsertData(sqlCommand);
Expand Down Expand Up @@ -219,7 +219,7 @@ private static void InsertData(SqlCommand sqlCommand)
sqlCommand.ExecuteNonQuery();
}

[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsSupportedDataClassification))]
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsDataClassificationSupported))]
public static void TestDataClassificationBulkCopy()
{
var data = new DataTable("Company");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests.SQL.VectorTest
public static class VectorFloat32TestData
{
public const int VectorHeaderSize = 8;
public static float[] testData = new float[] { 1.1f, 2.2f, 3.3f };
public static float[] testData = new float[] { 1.1f, 2.2f, 3.3f, 1.01f, float.MinValue, -0.0f };
public static int vectorColumnLength = testData.Length;
// Incorrect size for SqlParameter.Size
public static int IncorrectParamSize = 3234;
Expand Down Expand Up @@ -59,16 +59,17 @@ public sealed class NativeVectorFloat32Tests : IDisposable
private static readonly string s_connectionString = ManualTesting.Tests.DataTestUtility.TCPConnectionString;
private static readonly string s_tableName = DataTestUtility.GetShortName("VectorTestTable");
private static readonly string s_bulkCopySrcTableName = DataTestUtility.GetShortName("VectorBulkCopyTestTable");
private static readonly string s_bulkCopySrcTableDef = $@"(Id INT PRIMARY KEY IDENTITY, VectorData vector(3) NULL)";
private static readonly string s_tableDefinition = $@"(Id INT PRIMARY KEY IDENTITY, VectorData vector(3) NULL)";
private static readonly int s_vectorDimensions = VectorFloat32TestData.vectorColumnLength;
private static readonly string s_bulkCopySrcTableDef = $@"(Id INT PRIMARY KEY IDENTITY, VectorData vector({s_vectorDimensions}) NULL)";
private static readonly string s_tableDefinition = $@"(Id INT PRIMARY KEY IDENTITY, VectorData vector({s_vectorDimensions}) NULL)";
private static readonly string s_selectCmdString = $"SELECT VectorData FROM {s_tableName} ORDER BY Id DESC";
private static readonly string s_insertCmdString = $"INSERT INTO {s_tableName} (VectorData) VALUES (@VectorData)";
private static readonly string s_vectorParamName = $"@VectorData";
private static readonly string s_outputVectorParamName = $"@OutputVectorData";
private static readonly string s_storedProcName = DataTestUtility.GetShortName("VectorsAsVarcharSp");
private static readonly string s_storedProcBody = $@"
{s_vectorParamName} vector(3), -- Input: Serialized float[] as JSON string
{s_outputVectorParamName} vector(3) OUTPUT -- Output: Echoed back from latest inserted row
{s_vectorParamName} vector({s_vectorDimensions}), -- Input: Serialized float[] as JSON string
{s_outputVectorParamName} vector({s_vectorDimensions}) OUTPUT -- Output: Echoed back from latest inserted row
AS
BEGIN
SET NOCOUNT ON;
Expand Down Expand Up @@ -147,7 +148,7 @@ private void ValidateInsertedData(SqlConnection connection, float[] expectedData
}
}

[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAzureServer), nameof(DataTestUtility.IsNotManagedInstance))]
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsSqlVectorSupported))]
[MemberData(nameof(VectorFloat32TestData.GetVectorFloat32TestData), MemberType = typeof(VectorFloat32TestData), DisableDiscoveryEnumeration = true)]
public void TestSqlVectorFloat32ParameterInsertionAndReads(
int pattern,
Expand Down Expand Up @@ -213,7 +214,7 @@ private async Task ValidateInsertedDataAsync(SqlConnection connection, float[] e
}
}

[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAzureServer), nameof(DataTestUtility.IsNotManagedInstance))]
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsSqlVectorSupported))]
[MemberData(nameof(VectorFloat32TestData.GetVectorFloat32TestData), MemberType = typeof(VectorFloat32TestData), DisableDiscoveryEnumeration = true)]
public async Task TestSqlVectorFloat32ParameterInsertionAndReadsAsync(
int pattern,
Expand Down Expand Up @@ -247,7 +248,7 @@ public async Task TestSqlVectorFloat32ParameterInsertionAndReadsAsync(
await ValidateInsertedDataAsync(conn, expectedValues, expectedLength);
}

[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAzureServer), nameof(DataTestUtility.IsNotManagedInstance))]
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsSqlVectorSupported))]
[MemberData(nameof(VectorFloat32TestData.GetVectorFloat32TestData), MemberType = typeof(VectorFloat32TestData), DisableDiscoveryEnumeration = true)]
public void TestStoredProcParamsForVectorFloat32(
int pattern,
Expand Down Expand Up @@ -304,7 +305,7 @@ public void TestStoredProcParamsForVectorFloat32(
Assert.Throws<InvalidOperationException>(() => command.ExecuteNonQuery());
}

[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAzureServer), nameof(DataTestUtility.IsNotManagedInstance))]
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsSqlVectorSupported))]
[MemberData(nameof(VectorFloat32TestData.GetVectorFloat32TestData), MemberType = typeof(VectorFloat32TestData), DisableDiscoveryEnumeration = true)]
public async Task TestStoredProcParamsForVectorFloat32Async(
int pattern,
Expand Down Expand Up @@ -361,7 +362,7 @@ public async Task TestStoredProcParamsForVectorFloat32Async(
await Assert.ThrowsAsync<InvalidOperationException>(async () => await command.ExecuteNonQueryAsync());
}

[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAzureServer), nameof(DataTestUtility.IsNotManagedInstance))]
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsSqlVectorSupported))]
[InlineData(1)]
[InlineData(2)]
public void TestBulkCopyFromSqlTable(int bulkCopySourceMode)
Expand Down Expand Up @@ -460,7 +461,7 @@ public void TestBulkCopyFromSqlTable(int bulkCopySourceMode)
Assert.Equal(VectorFloat32TestData.testData.Length, ((SqlVector<float>)verifyReader.GetSqlVector<float>(0)).Length);
}

[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAzureServer), nameof(DataTestUtility.IsNotManagedInstance))]
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsSqlVectorSupported))]
[InlineData(1)]
[InlineData(2)]
public async Task TestBulkCopyFromSqlTableAsync(int bulkCopySourceMode)
Expand Down Expand Up @@ -560,7 +561,7 @@ public async Task TestBulkCopyFromSqlTableAsync(int bulkCopySourceMode)
Assert.Equal(VectorFloat32TestData.testData.Length, vector.Length);
}

[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAzureServer), nameof(DataTestUtility.IsNotManagedInstance))]
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsSqlVectorSupported))]
public void TestInsertVectorsFloat32WithPrepare()
{
SqlConnection conn = new SqlConnection(s_connectionString);
Expand All @@ -571,15 +572,15 @@ public void TestInsertVectorsFloat32WithPrepare()
command.Prepare();
for (int i = 0; i < 10; i++)
{
vectorParam.Value = new SqlVector<float>(new float[] { i + 0.1f, i + 0.2f, i + 0.3f });
vectorParam.Value = new SqlVector<float>(new float[] { i + 0.1f, i + 0.2f, i + 0.3f, i + 0.4f, i + 0.5f, i + 0.6f });
command.ExecuteNonQuery();
}
SqlCommand validateCommand = new SqlCommand($"SELECT VectorData FROM {s_tableName}", conn);
using SqlDataReader reader = validateCommand.ExecuteReader();
int rowcnt = 0;
while (reader.Read())
{
float[] expectedData = new float[] { rowcnt + 0.1f, rowcnt + 0.2f, rowcnt + 0.3f };
float[] expectedData = new float[] { rowcnt + 0.1f, rowcnt + 0.2f, rowcnt + 0.3f, rowcnt + 0.4f, rowcnt + 0.5f, rowcnt + 0.6f };
float[] dbData = reader.GetSqlVector<float>(0).Memory.ToArray();
Assert.Equal(expectedData, dbData);
rowcnt++;
Expand Down
Loading
Loading