Skip to content

Commit eb45cd1

Browse files
Edit Data Service Updates for Edit Data in the MSSQL for VS Code extension (#2530)
* Adds script generation for edit sessions * Adds tests for ScriptEdits method * Adds column names to EditSubsetResult * Returns reverted row after revert operation * Verifies reverted row contains correct data * Add flag to indicate if a column is editable * Populate newly created row in result * Handle pending row create during delete. * Minor clean up * Add row ID validation to edit session * Fix test assertion for async operation * Clarifies request result documentation * Refactor EditSession row ID validation * Clarifies rename of column property * Clarify request handlers by using named arguments * Refactors EditDataService for error handling * Use fluent assertions * Use named argument for the rowCount * Use HandleSessionRequest to get edit scripts * Clean up comments * Fix broken tests from HandleSessionRequest refactor * Add additional logging
1 parent 357755c commit eb45cd1

File tree

9 files changed

+373
-95
lines changed

9 files changed

+373
-95
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//
2+
// Copyright (c) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4+
//
5+
6+
namespace Microsoft.SqlTools.ServiceLayer.EditData.Contracts
7+
{
8+
/// <summary>
9+
/// Metadata about a column in an editable result set
10+
/// </summary>
11+
public class EditColumnInfo
12+
{
13+
/// <summary>
14+
/// The name of the column
15+
/// </summary>
16+
public string Name { get; set; }
17+
18+
/// <summary>
19+
/// Whether or not the column can be edited. Columns may not be editable for several reasons,
20+
/// such as being computed columns, identity columns, or columns that are part of a primary key.
21+
/// </summary>
22+
public bool IsEditable { get; set; }
23+
}
24+
}

src/Microsoft.SqlTools.ServiceLayer/EditData/Contracts/EditCreateRowRequest.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ public class EditCreateRowResult
3131
/// The internal ID of the newly created row
3232
/// </summary>
3333
public long NewRowId { get; set; }
34+
35+
/// <summary>
36+
/// The newly created row with all cell data and state information
37+
/// </summary>
38+
public EditRow Row { get; set; }
3439
}
3540

3641
public class EditCreateRowRequest

src/Microsoft.SqlTools.ServiceLayer/EditData/Contracts/EditRevertRowRequest.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ public class EditRevertRowParams : RowOperationParams
2121
/// </summary>
2222
public class EditRevertRowResult
2323
{
24+
/// <summary>
25+
/// The row after the revert was applied, representing the original, unedited state
26+
/// </summary>
27+
public EditRow Row { get; set; }
2428
}
2529

2630
public class EditRevertRowRequest
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//
2+
// Copyright (c) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4+
//
5+
6+
using Microsoft.SqlTools.Hosting.Protocol.Contracts;
7+
8+
namespace Microsoft.SqlTools.ServiceLayer.EditData.Contracts
9+
{
10+
/// <summary>
11+
/// Parameters for a request to get a script with all DML statements for an edit session.
12+
/// </summary>
13+
public class EditScriptParams : SessionOperationParams
14+
{
15+
16+
}
17+
18+
/// <summary>
19+
/// Returns the scripts with all DML statements for an edit session.
20+
/// </summary>
21+
public class EditScriptResult
22+
{
23+
public string[] Scripts { get; set; }
24+
}
25+
26+
public class EditScriptRequest
27+
{
28+
public static readonly
29+
RequestType<EditScriptParams, EditScriptResult> Type =
30+
RequestType<EditScriptParams, EditScriptResult>.Create("edit/script");
31+
}
32+
}

src/Microsoft.SqlTools.ServiceLayer/EditData/Contracts/EditSubsetRequest.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ public class EditSubsetResult
4343
/// The requested subset of rows, with information about whether or not the rows are dirty
4444
/// </summary>
4545
public EditRow[] Subset { get; set; }
46+
47+
/// <summary>
48+
/// The column information including name and editability for the result set
49+
/// </summary>
50+
public EditColumnInfo[] ColumnInfo { get; set; }
4651
}
4752

4853
public class EditSubsetRequest

src/Microsoft.SqlTools.ServiceLayer/EditData/EditDataService.cs

Lines changed: 75 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -77,33 +77,66 @@ internal EditDataService(QueryExecutionService qes, ConnectionService cs, IEditM
7777
public void InitializeService(ServiceHost serviceHost)
7878
{
7979
// Register handlers for requests
80-
serviceHost.SetRequestHandler(EditCreateRowRequest.Type, HandleCreateRowRequest, true);
81-
serviceHost.SetRequestHandler(EditDeleteRowRequest.Type, HandleDeleteRowRequest, true);
82-
serviceHost.SetRequestHandler(EditDisposeRequest.Type, HandleDisposeRequest, true);
83-
serviceHost.SetRequestHandler(EditInitializeRequest.Type, HandleInitializeRequest, true);
84-
serviceHost.SetRequestHandler(EditRevertCellRequest.Type, HandleRevertCellRequest, true);
85-
serviceHost.SetRequestHandler(EditRevertRowRequest.Type, HandleRevertRowRequest, true);
86-
serviceHost.SetRequestHandler(EditSubsetRequest.Type, HandleSubsetRequest, true);
87-
serviceHost.SetRequestHandler(EditUpdateCellRequest.Type, HandleUpdateCellRequest, true);
88-
serviceHost.SetRequestHandler(EditCommitRequest.Type, HandleCommitRequest, true);
80+
serviceHost.SetRequestHandler(EditCreateRowRequest.Type, HandleCreateRowRequest, isParallelProcessingSupported: true);
81+
serviceHost.SetRequestHandler(EditDeleteRowRequest.Type, HandleDeleteRowRequest, isParallelProcessingSupported: true);
82+
serviceHost.SetRequestHandler(EditDisposeRequest.Type, HandleDisposeRequest, isParallelProcessingSupported: true);
83+
serviceHost.SetRequestHandler(EditInitializeRequest.Type, HandleInitializeRequest, isParallelProcessingSupported: true);
84+
serviceHost.SetRequestHandler(EditRevertCellRequest.Type, HandleRevertCellRequest, isParallelProcessingSupported: true);
85+
serviceHost.SetRequestHandler(EditRevertRowRequest.Type, HandleRevertRowRequest, isParallelProcessingSupported: true);
86+
serviceHost.SetRequestHandler(EditSubsetRequest.Type, HandleSubsetRequest, isParallelProcessingSupported: true);
87+
serviceHost.SetRequestHandler(EditUpdateCellRequest.Type, HandleUpdateCellRequest, isParallelProcessingSupported: true);
88+
serviceHost.SetRequestHandler(EditCommitRequest.Type, HandleCommitRequest, isParallelProcessingSupported: true);
89+
serviceHost.SetRequestHandler(EditScriptRequest.Type, HandleEditScriptRequest, isParallelProcessingSupported: true);
8990
}
9091

9192
#region Request Handlers
9293

9394
internal async Task HandleSessionRequest<TResult>(SessionOperationParams sessionParams,
9495
RequestContext<TResult> requestContext, Func<EditSession, TResult> sessionOperation)
9596
{
96-
EditSession editSession = GetActiveSessionOrThrow(sessionParams.OwnerUri);
97+
try
98+
{
99+
EditSession editSession = GetActiveSessionOrThrow(sessionParams.OwnerUri);
100+
101+
// Get the result from execution of the editSession operation
102+
TResult result = sessionOperation(editSession);
103+
await requestContext.SendResult(result);
104+
}
105+
catch (Exception e)
106+
{
107+
await requestContext.SendError(e.Message);
108+
}
109+
}
97110

98-
// Get the result from execution of the editSession operation
99-
TResult result = sessionOperation(editSession);
100-
await requestContext.SendResult(result);
111+
internal async Task HandleSessionRequestAsync<TResult>(SessionOperationParams sessionParams,
112+
RequestContext<TResult> requestContext, Func<EditSession, Task<TResult>> sessionOperationAsync)
113+
{
114+
try
115+
{
116+
EditSession editSession = GetActiveSessionOrThrow(sessionParams.OwnerUri);
117+
118+
// Get the result from execution of the async editSession operation
119+
TResult result = await sessionOperationAsync(editSession);
120+
await requestContext.SendResult(result);
121+
}
122+
catch (Exception e)
123+
{
124+
await requestContext.SendError(e.Message);
125+
}
101126
}
102127

103128
internal Task HandleCreateRowRequest(EditCreateRowParams createParams,
104129
RequestContext<EditCreateRowResult> requestContext)
105130
{
106-
return HandleSessionRequest(createParams, requestContext, s => s.CreateRow());
131+
return HandleSessionRequestAsync(createParams, requestContext, async session =>
132+
{
133+
EditCreateRowResult result = session.CreateRow();
134+
135+
EditRow[] rows = await session.GetRows(result.NewRowId, rowCount: 1);
136+
result.Row = rows.Length > 0 ? rows[0] : null;
137+
138+
return result;
139+
});
107140
}
108141

109142
internal Task HandleDeleteRowRequest(EditDeleteRowParams deleteParams,
@@ -156,7 +189,7 @@ internal async Task HandleInitializeRequest(EditInitializeParams initParams,
156189
throw new InvalidOperationException(SR.EditDataSessionAlreadyExists);
157190
}
158191

159-
context.ResultSetHandler = (ResultSetEventParams resultSetEventParams) => { session.UpdateColumnInformationWithMetadata(resultSetEventParams.ResultSetSummary.ColumnInfo); };
192+
context.ResultSetHandler = resultSetEventParams => { session.UpdateColumnInformationWithMetadata(resultSetEventParams.ResultSetSummary.ColumnInfo); };
160193

161194
// Initialize the session
162195
session.Initialize(initParams, connector, queryRunner, executionSuccessHandler, executionFailureHandler);
@@ -175,26 +208,31 @@ internal Task HandleRevertCellRequest(EditRevertCellParams revertParams,
175208
internal Task HandleRevertRowRequest(EditRevertRowParams revertParams,
176209
RequestContext<EditRevertRowResult> requestContext)
177210
{
178-
return HandleSessionRequest(revertParams, requestContext, session =>
211+
return HandleSessionRequestAsync(revertParams, requestContext, async session =>
179212
{
180-
session.RevertRow(revertParams.RowId);
181-
return new EditRevertRowResult();
213+
EditRow revertedRow = await session.RevertRow(revertParams.RowId);
214+
215+
return new EditRevertRowResult
216+
{
217+
Row = revertedRow
218+
};
182219
});
183220
}
184221

185-
internal async Task HandleSubsetRequest(EditSubsetParams subsetParams,
222+
internal Task HandleSubsetRequest(EditSubsetParams subsetParams,
186223
RequestContext<EditSubsetResult> requestContext)
187224
{
188-
EditSession session = GetActiveSessionOrThrow(subsetParams.OwnerUri);
189-
190-
EditRow[] rows = await session.GetRows(subsetParams.RowStartIndex, subsetParams.RowCount);
191-
EditSubsetResult result = new EditSubsetResult
225+
return HandleSessionRequestAsync(subsetParams, requestContext, async session =>
192226
{
193-
RowCount = rows.Length,
194-
Subset = rows
195-
};
196-
197-
await requestContext.SendResult(result);
227+
EditRow[] rows = await session.GetRows(subsetParams.RowStartIndex, subsetParams.RowCount);
228+
229+
return new EditSubsetResult
230+
{
231+
RowCount = rows.Length,
232+
Subset = rows,
233+
ColumnInfo = session.GetColumnInfo()
234+
};
235+
});
198236
}
199237

200238
internal Task HandleUpdateCellRequest(EditUpdateCellParams updateParams,
@@ -229,6 +267,15 @@ internal async Task HandleCommitRequest(EditCommitParams commitParams,
229267
}
230268
}
231269

270+
internal Task HandleEditScriptRequest(EditScriptParams scriptParams, RequestContext<EditScriptResult> requestContext)
271+
{
272+
return HandleSessionRequest(scriptParams, requestContext, session =>
273+
{
274+
string[] scripts = session.ScriptEdits();
275+
return new EditScriptResult { Scripts = scripts };
276+
});
277+
}
278+
232279
#endregion
233280

234281
#region Private Helpers

0 commit comments

Comments
 (0)