diff --git a/src/Microsoft.SqlTools.ServiceLayer/EditData/Contracts/EditInitializeFiltering.cs b/src/Microsoft.SqlTools.ServiceLayer/EditData/Contracts/EditInitializeFiltering.cs
new file mode 100644
index 00000000..4074953c
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/EditData/Contracts/EditInitializeFiltering.cs
@@ -0,0 +1,18 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+namespace Microsoft.SqlTools.ServiceLayer.EditData.Contracts
+{
+ ///
+ /// Parameters for filtering a the rows in a table to make querying easier
+ ///
+ public class EditInitializeFiltering
+ {
+ ///
+ /// Limit the records queried from the database to this many. If null, all rows are returned
+ ///
+ public int? LimitResults { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.SqlTools.ServiceLayer/EditData/Contracts/EditInitializeRequest.cs b/src/Microsoft.SqlTools.ServiceLayer/EditData/Contracts/EditInitializeRequest.cs
index b03c0ff3..49533757 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/EditData/Contracts/EditInitializeRequest.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/EditData/Contracts/EditInitializeRequest.cs
@@ -12,6 +12,11 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.Contracts
///
public class EditInitializeParams : SessionOperationParams
{
+ ///
+ /// Filtering parameters
+ ///
+ public EditInitializeFiltering Filters { get; set; }
+
///
/// The object to use for generating an edit script
///
diff --git a/src/Microsoft.SqlTools.ServiceLayer/EditData/EditDataService.cs b/src/Microsoft.SqlTools.ServiceLayer/EditData/EditDataService.cs
index 1f7abc26..5f0b65f4 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/EditData/EditDataService.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/EditData/EditDataService.cs
@@ -162,14 +162,14 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
Validate.IsNotNullOrWhitespaceString(nameof(initParams.ObjectType), initParams.ObjectType);
// Create a session and add it to the session list
- EditSession session = new EditSession(metadataFactory, initParams.ObjectName, initParams.ObjectType);
+ EditSession session = new EditSession(metadataFactory);
if (!ActiveSessions.TryAdd(initParams.OwnerUri, session))
{
throw new InvalidOperationException(SR.EditDataSessionAlreadyExists);
}
// Initialize the session
- session.Initialize(connector, queryRunner, executionSuccessHandler, executionFailureHandler);
+ session.Initialize(initParams, connector, queryRunner, executionSuccessHandler, executionFailureHandler);
}
catch (Exception e)
{
diff --git a/src/Microsoft.SqlTools.ServiceLayer/EditData/EditSession.cs b/src/Microsoft.SqlTools.ServiceLayer/EditData/EditSession.cs
index b0eec669..3b8db94e 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/EditData/EditSession.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/EditData/EditSession.cs
@@ -9,6 +9,7 @@ using System.Collections.Generic;
using System.Data.Common;
using System.IO;
using System.Linq;
+using System.Text;
using System.Threading.Tasks;
using Microsoft.SqlTools.ServiceLayer.EditData.Contracts;
using Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement;
@@ -29,25 +30,17 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
private readonly IEditMetadataFactory metadataFactory;
private EditTableMetadata objectMetadata;
- private readonly string objectName;
- private readonly string objectType;
///
/// Constructs a new edit session bound to the result set and metadat object provided
///
/// Factory for creating metadata
- /// The name of the object to edit
- /// The type of the object to edit
- public EditSession(IEditMetadataFactory metaFactory, string objName, string objType)
+ public EditSession(IEditMetadataFactory metaFactory)
{
Validate.IsNotNull(nameof(metaFactory), metaFactory);
- Validate.IsNotNullOrWhitespaceString(nameof(objName), objName);
- Validate.IsNotNullOrWhitespaceString(nameof(objType), objType);
// Setup the internal state
metadataFactory = metaFactory;
- objectName = objName;
- objectType = objType;
}
#region Properties
@@ -86,7 +79,22 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
#region Public Methods
- public void Initialize(Connector connector, QueryRunner queryRunner, Func successHandler, Func errorHandler)
+ ///
+ /// Initializes the edit session, asynchronously, by retrieving metadata about the table to
+ /// edit and querying the table for the rows of the table.
+ ///
+ /// Parameters for initializing the edit session
+ /// Delegate that will return a DbConnection when executed
+ ///
+ /// Delegate that will run the requested query and return a
+ /// object on execution
+ ///
+ /// Func to call when initialization has completed successfully
+ /// Func to call when initialization has completed with errors
+ ///
+ /// When session is already initialized or in progress of initializing
+ ///
+ public void Initialize(EditInitializeParams initParams, Connector connector, QueryRunner queryRunner, Func successHandler, Func errorHandler)
{
if (IsInitialized)
{
@@ -98,13 +106,17 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
throw new InvalidOperationException(SR.EditDataSessionAlreadyInitializing);
}
+ Validate.IsNotNullOrWhitespaceString(nameof(initParams.ObjectName), initParams.ObjectName);
+ Validate.IsNotNullOrWhitespaceString(nameof(initParams.ObjectType), initParams.ObjectType);
+ Validate.IsNotNull(nameof(initParams.Filters), initParams.Filters);
+
Validate.IsNotNull(nameof(connector), connector);
Validate.IsNotNull(nameof(queryRunner), queryRunner);
Validate.IsNotNull(nameof(successHandler), successHandler);
Validate.IsNotNull(nameof(errorHandler), errorHandler);
// Start up the initialize process
- InitializeTask = InitializeInternal(connector, queryRunner, successHandler, errorHandler);
+ InitializeTask = InitializeInternal(initParams, connector, queryRunner, successHandler, errorHandler);
}
///
@@ -403,16 +415,19 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
#endregion
- private async Task InitializeInternal(Connector connector, QueryRunner queryRunner,
- Func successHandler, Func failureHandler)
+ #region Private Helpers
+
+ private async Task InitializeInternal(EditInitializeParams initParams, Connector connector,
+ QueryRunner queryRunner, Func successHandler, Func failureHandler)
{
try
{
// Step 1) Look up the SMO metadata
- objectMetadata = metadataFactory.GetObjectMetadata(await connector(), objectName, objectType);
+ objectMetadata = metadataFactory.GetObjectMetadata(await connector(), initParams.ObjectName,
+ initParams.ObjectType);
// Step 2) Get and execute a query for the rows in the object we're looking up
- EditSessionQueryExecutionState state = await queryRunner(ConstructInitializeQuery());
+ EditSessionQueryExecutionState state = await queryRunner(ConstructInitializeQuery(objectMetadata, initParams.Filters));
if (state.Query == null)
{
// TODO: Move to SR file
@@ -467,13 +482,33 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
}
}
- private string ConstructInitializeQuery()
+ ///
+ /// Constructs a query for selecting rows in a table based on the filters provided.
+ /// Internal for unit testing purposes only.
+ ///
+ internal static string ConstructInitializeQuery(EditTableMetadata metadata, EditInitializeFiltering initFilters)
{
- // Using the columns we know, put together a query for the rows in the table
- var columns = objectMetadata.Columns.Select(col => col.EscapedName);
- var columnClause = string.Join(", ", columns);
+ StringBuilder queryBuilder = new StringBuilder("SELECT ");
- return $"SELECT ${columnClause} FROM ${objectMetadata.EscapedMultipartName}";
+ // If there is a filter for top n rows, then apply it
+ if (initFilters.LimitResults.HasValue)
+ {
+ if (initFilters.LimitResults < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(initFilters.LimitResults), SR.EditDataFilteringNegativeLimit);
+ }
+ queryBuilder.AppendFormat("TOP {0} ", initFilters.LimitResults.Value);
+ }
+
+ // Using the columns we know, add them to the query
+ var columns = metadata.Columns.Select(col => col.EscapedName);
+ var columnClause = string.Join(", ", columns);
+ queryBuilder.Append(columnClause);
+
+ // Add the FROM
+ queryBuilder.AppendFormat(" FROM {0}", metadata.EscapedMultipartName);
+
+ return queryBuilder.ToString();
}
private void ThrowIfNotInitialized()
@@ -484,6 +519,8 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData
}
}
+ #endregion
+
///
/// State object to return upon completion of an edit session intialization query
///
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs
index 818a3b01..a7c6883c 100755
--- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs
@@ -413,6 +413,14 @@ namespace Microsoft.SqlTools.ServiceLayer
}
}
+ public static string EditDataFilteringNegativeLimit
+ {
+ get
+ {
+ return Keys.GetString(Keys.EditDataFilteringNegativeLimit);
+ }
+ }
+
public static string EditDataQueryFailed
{
get
@@ -1098,6 +1106,9 @@ namespace Microsoft.SqlTools.ServiceLayer
public const string EditDataSessionAlreadyInitializing = "EditDataSessionAlreadyInitializing";
+ public const string EditDataFilteringNegativeLimit = "EditDataFilteringNegativeLimit";
+
+
public const string EditDataUnsupportedObjectType = "EditDataUnsupportedObjectType";
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx
index 5768fa52..d52e5e9b 100755
--- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx
+++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx
@@ -374,6 +374,10 @@
Edit session has already been initialized or is in the process of initializing
+
+ Result limit cannot be negative
+
+
Database object {0} cannot be used for editing..
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings
index 8e7b7d6f..da300ed4 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings
+++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings
@@ -176,6 +176,8 @@ EditDataSessionAlreadyInitialized = Edit session has already been initialized
EditDataSessionAlreadyInitializing = Edit session has already been initialized or is in the process of initializing
+EditDataFilteringNegativeLimit = Result limit cannot be negative
+
EditDataUnsupportedObjectType(string typeName) = Database object {0} cannot be used for editing.
EditDataQueryFailed = Query execution failed, see messages for details
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf
index 529bd088..2922cecb 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf
+++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf
@@ -591,6 +591,11 @@
Query execution failed, see messages for details
+
+ Result limit cannot be negative
+ Result limit cannot be negative
+
+