Skip to content
Merged
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
Update this document for externally visible changes. Put most recent changes first.
Once we push a new version to nuget.org add a double hash header for that version.

# 172.64.0

- Add DesignMode support to `QueryStoreOptions` class
- Add Vector data type support

# 172.61.0

- Remove major version restriction on Microsoft.Data.SqlClient dependency Fixes [Issue 188](https://github.com/microsoft/sqlmanagementobjects/issues/188)
Expand Down
60 changes: 0 additions & 60 deletions Packages.props

This file was deleted.

15 changes: 15 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,21 @@ Create a corresponding partial class in `%basedir%\src\Microsoft\SqlServer\Manag
7. Add a UrnSuffix: `public static string UrnSuffix => "<ObjectType>";`
8. If the object is scriptable on its own, not directly included as part of the script for its parent, reference its UrnSuffix in the scriptableTypes HashSet in ScriptMaker.cs.

### DesignMode

`DesignMode` (or `Design Mode`) is the label for an instance of the object hierarchy whose root `Server` object is using a `ServerConnection` that's in `Offline` mode. Any object added to a child collection in a `DesignMode` hierarchy is automatically set to the `Existing` state.


When the connection is offline, many code paths get short circuited and skip running queries, leaving the objects in whatever state the caller has set them. Correct support for DesignMode in your object will enable it to be used for offline unit tests. In `DesignMode`, certain methods like `Alter` are blocked completely, but unit tests can call the internal `ScriptAlter` method and validate that correct scripts are generated based on the set of properties the unit test set. Such a unit test can detect bugs that affect non-DesignMode operation, such as a failure to properly check if a property has been set on the object before trying to reference its value.

If an object property is not explicitly set by a caller and that object doesn't have a `default` value set for it in [cfg.xml](/src/Codegen/cfg.xml), attempting to get the property value will result in an exception. Typically, readonly properties _should_ have a default value assigned. Default values for settable properties are optional, and may be limited to the properties that don't directly affect the `ScriptAlter` implementation of the object.

To make an object available in `DesignMode`, add `is_design_mode="true"` attribute to its definition in `cfg.xml`. To mark a property explicitly as `DesignMode`-friendly, use `mode="design"` in its definition in the object XML file. Note that `mode="deploy"` no longer seems to have any effect and can be removed or changed to `mode="all"` if you want to make an existing property available for `DesignMode`.

Adding an existing property to `DesignMode` is safe because it doesn't change its behavior at all in normal connected scenarios.

It's not clear how decisions were made in the past to choose which objects and properties support DesignMode. Going forward, we recommend new code supports DesignMode and includes appropriate offline unit tests.

### Collections

If your new object is part of a collection under a parent object, create a corresponding .cs file for your new collection. This can be done by adding an entry to [collections_codegen.proj](/src/codegen/README.md#collections_codegen.proj) and building that project. Then add the appropriate ```<Compile>``` tag to [Microsoft.SqlServer.Smo.csproj](/src/Microsoft/SqlServer/Management/Smo/Microsoft.SqlServer.Smo.csproj).
Expand Down
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "8.0.405",
"version": "8.0.406",
"rollForward": "latestMinor"
},
"msbuild-sdks": {
Expand Down
4 changes: 3 additions & 1 deletion src/Codegen/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,9 @@ public void Deny(ObjectPermissionSet permission, System.String granteeName)

#### Parent_has_setter

#### Is_design_mode
#### is_design_mode

Set this property to `true` to allow your object to participate in `DesignMode`. Such objects can be unit tested with an offline connection. Most objects should have this set.

#### Parent_mode

Expand Down
4 changes: 4 additions & 0 deletions src/Codegen/SmoCodeGen.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
<Compile Include="$(SfcSrc)\NetCoreExtension.cs" />
<Compile Include="$(SfcSrc)\SmoManagementUtil.cs" />
<Compile Include="$(SfcSrc)\TraceHelper.cs" />
<Compile Include="$(SmoSrc)\QueryStoreEnums.cs" />
<Compile Include="$(SqlEnumSrc)\ConditionedSql.cs" />
<Compile Include="$(SqlEnumSrc)\DatabaseLevel.cs" />
<Compile Include="$(SqlEnumSrc)\DatabaseOption.cs" />
Expand Down Expand Up @@ -129,6 +130,9 @@
<SqlStringResource Include="$(SqlEnumSrc)\StringSqlEnumerator.strings" namespace="Microsoft.SqlServer.Management.Smo.SqlEnum" resourcename="CodeGen" additionaloptions="-an CodeGen"/>
<SqlStringResource Include="$(SfcSrc)\SfcStrings.strings" namespace="Microsoft.SqlServer.Management.Sdk.Sfc" resourcename="CodeGen" additionaloptions="-an CodeGen"/>
</ItemGroup>
<ItemGroup>
<None Include="cfg.xml" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" />
</ItemGroup>
Expand Down
8 changes: 4 additions & 4 deletions src/Codegen/cfg.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
<property name="BuildNumber" generate="true" is_intrinsic="false" />
<property name="IsCaseSensitive" generate="true" is_intrinsic="false" />
<property name="IsFullTextInstalled" generate="true" is_intrinsic="false" />
<property name="IsJsonDataTypeEnabled" generate="true" is_intrinsic="false" />
<property name="IsJsonDataTypeEnabled" generate="true" is_intrinsic="false" />
<property name="MasterDBLogPath" generate="true" is_intrinsic="false" />
<property name="MasterDBPath" generate="true" is_intrinsic="false" />
<property name="ErrorLogPath" generate="true" is_intrinsic="false" />
Expand Down Expand Up @@ -2179,15 +2179,15 @@
</object>

<object class_name="QueryStoreOptions" urn="Server[@Name='']/Database/QueryStoreOptions" is_design_mode="true" parent_type="Database" singleton="true" has_constructors="false">
<property name="ActualState" generate="true" is_intrinsic="false"/>
<property name="ActualState" generate="true" is_intrinsic="false" default="Off" />
<property name="DesiredState" generate="true" is_intrinsic="false"/>
<property name="ReadOnlyReason" generate="true" is_intrinsic="false"/>
<property name="ReadOnlyReason" generate="true" is_intrinsic="false" default="0" />
<property name="CurrentStorageSizeInMB" generate="true" is_intrinsic="false"/>
<property name="MaxStorageSizeInMB" generate="true" is_intrinsic="false"/>
<property name="StaleQueryThresholdInDays" generate="true" is_intrinsic="false"/>
<property name="DataFlushIntervalInSeconds" generate="true" is_intrinsic="false"/>
<property name="StatisticsCollectionIntervalInMinutes" generate="true" is_intrinsic="false"/>
<property name="QueryCaptureMode" generate="true" is_intrinsic="false"/>
<property name="QueryCaptureMode" generate="true" is_intrinsic="false" default="None" />
<property name="SizeBasedCleanupMode" generate="true" is_intrinsic="false"/>
<property name="MaxPlansPerQuery" generate="true" is_intrinsic="false"/>
<property name="WaitStatsCaptureMode" generate="true" is_intrinsic="false"/>
Expand Down
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
</PropertyGroup>
<PropertyGroup>
<!-- these variables are referenced by packagebuild.proj for inclusion in nuspecs and used by packages.props -->
<SqlParserPackageVersion>172.1.1</SqlParserPackageVersion>
<SqlParserPackageVersion>172.18.0</SqlParserPackageVersion>
<SqlClientPackage>Microsoft.Data.SqlClient</SqlClientPackage>
<SqlClientPackageVersion>5.1.6</SqlClientPackageVersion>
</PropertyGroup>
Expand Down
5 changes: 5 additions & 0 deletions src/FunctionalTest/Smo/ScriptingTests/Column_SmoTestSuite.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@ private static IEnumerable<ColumnProperties> GetAllDataTypeColumns(_SMO.Database
{
yield return new ColumnProperties($"col{i++}", _SMO.DataType.Json);
}

if (database.Parent.ServerType != DatabaseEngineType.Standalone || database.Parent.VersionMajor > 17)
{
yield return new ColumnProperties($"col{i++}", _SMO.DataType.Vector(2));
}
}

[TestMethod]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,18 @@ public static IEnumerable<Tuple<string, ScriptingOptions>> TestServerScriptingOp
OptimizerData = true,
Permissions = true
});
yield return new Tuple<string, ScriptingOptions>(
"Sqlv170",
new ScriptingOptions()
{
ExtendedProperties = true,
TargetDatabaseEngineType = DatabaseEngineType.Standalone,
TargetServerVersion = SqlServerVersion.Version170,
IncludeScriptingParametersHeader = true,
OptimizerData = true,
Permissions = true
});
// VBUMP : Add new server versions here
yield return new Tuple<string, ScriptingOptions>(
"AzureSterlingV12",
new ScriptingOptions()
Expand Down
44 changes: 44 additions & 0 deletions src/FunctionalTest/Smo/ScriptingTests/Table_SmoTestSuite.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4065,6 +4065,50 @@ public void ScriptingJsonColumnCrossVersionTest()

#endregion

#region Vector column tests
/// <summary>
/// This test verifies that JSON column is correctly scripted for insert statements.
/// </summary>
[TestMethod]
[SupportedServerVersionRange(DatabaseEngineType = DatabaseEngineType.SqlAzureDatabase)]
[SupportedServerVersionRange(DatabaseEngineType = DatabaseEngineType.Standalone, MinMajor = 17)]
[UnsupportedDatabaseEngineEdition(DatabaseEngineEdition.SqlDataWarehouse)]
public void ScriptingInsertTableWithVectorColumnTest()
{
ExecuteFromDbPool(
this.TestContext.FullyQualifiedTestClassName,
(database) =>
{
if (database.Parent.ServerType != DatabaseEngineType.Standalone || database.Parent.VersionMajor > 17)
{
string queryMatch = @"INSERT \[.*\]\.\[.*\] \(\[vectorColumn\]\) VALUES \(CAST\(N'\[0\.0000000e\+000,0\.0000000e\+000\]' AS Vector\(2\)\)\)";

var table = new Table(database, "vectorTable");
var vectorColumn = new Column(table, "vectorColumn", DataType.Vector(2));
table.Columns.Add(vectorColumn);
table.Create();

string insertQuery = $"INSERT INTO {table.Name.SqlBracketQuoteString()} values('[0,0]')";

database.ExecuteNonQuery(insertQuery);

var scripter = new Scripter(database.Parent);
scripter.Options.ScriptData = true;
scripter.Options.ScriptSchema = true;

IEnumerable<string> scripts = scripter.EnumScript(new Urn[] { table.Urn });
Assert.That(scripts, Has.One.Matches(queryMatch).IgnoreCase, "Scripting of Vector tables is expected to generate a valid INSERT statement");

table.DropIfExists();
string tableCreateScript = (from string script in scripts where script.StartsWith("CREATE", StringComparison.InvariantCultureIgnoreCase) select script).First();
database.ExecuteNonQuery(tableCreateScript);
database.Tables.ClearAndInitialize(string.Empty, null);
Assert.That(database.Tables, Has.One.Items.Matches<Table>(i => i.Name == table.Name), "Table should be created successfully.");
}
});
}
#endregion // Vector column tests

#endregion // Scripting Tests

#region Sparse column tests
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

/*************************************************************
* *
* Copyright (C) Microsoft Corporation. All rights reserved.*
* *
*************************************************************/

using System;
using System.Collections.Generic;
using System.Text;
Expand Down
Loading