Skip to content

Commit 901a44e

Browse files
committed
chore: address review comments
1 parent 3c984c9 commit 901a44e

File tree

3 files changed

+93
-28
lines changed

3 files changed

+93
-28
lines changed

apis/Google.Cloud.Spanner.Data/Google.Cloud.Spanner.Data.IntegrationTests/AdminTests.cs

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
using Google.Api.Gax.Grpc;
16+
using Google.Cloud.Spanner.Admin.Database.V1;
1517
using Google.Cloud.Spanner.Data.CommonTesting;
18+
using Google.LongRunning;
19+
using Google.Protobuf;
20+
using Google.Protobuf.WellKnownTypes;
1621
using System;
1722
using System.Threading.Tasks;
1823
using Xunit;
@@ -239,19 +244,76 @@ AlbumTitle STRING(MAX),
239244
using (var connection = new SpannerConnection(builder.WithDatabase(dbName)))
240245
{
241246
var dropSingersCmd = connection.CreateDdlCommand("DROP TABLE Singers");
242-
var dropBothTablesCmd = connection.CreateDdlCommand("DROP TABLE Albums", "DROP TABLE Singers");
247+
var dropAlbumsCmd = connection.CreateDdlCommand("DROP TABLE Albums");
243248

244249
await Assert.ThrowsAsync<SpannerException>(() => dropSingersCmd.ExecuteNonQueryAsync());
245-
var operationName = await dropBothTablesCmd.StartDdlAsync();
246-
Assert.NotEqual("", operationName);
250+
await dropAlbumsCmd.ExecuteNonQueryAsync();
251+
await dropSingersCmd.ExecuteNonQueryAsync();
247252
}
248253

249254
using (var connection = new SpannerConnection(builder))
250255
{
251256
var dropCommand = connection.CreateDdlCommand($"DROP DATABASE {dbName}");
252-
var operationName = await dropCommand.StartDdlAsync();
253-
// DropDatabase does not return a long-running operation.
254-
Assert.Equal("", operationName);
257+
await dropCommand.ExecuteNonQueryAsync();
258+
}
259+
}
260+
261+
[Fact]
262+
public async Task StartDdlReturnsOperationName()
263+
{
264+
string dbName = GenerateDatabaseName();
265+
var builder = new SpannerConnectionStringBuilder(_fixture.Database.NoDbConnectionString);
266+
var connectionOptions = new SpannerClientCreationOptions(builder);
267+
var adminClientBuilder = connectionOptions.CreateDatabaseAdminClientBuilder();
268+
var adminClient = await adminClientBuilder.BuildAsync();
269+
var channel = adminClientBuilder.LastCreatedChannel;
270+
271+
try
272+
{
273+
using (var connection = new SpannerConnection(builder))
274+
{
275+
var createDbCommand = connection.CreateDdlCommand($"CREATE DATABASE {dbName}");
276+
var operationName = await createDbCommand.StartDdlAsync();
277+
Assert.False(string.IsNullOrEmpty(operationName));
278+
279+
await HandleLro<Database, CreateDatabaseMetadata>(
280+
adminClient.CreateDatabaseOperationsClient, operationName);
281+
}
282+
283+
using (var connection = new SpannerConnection(builder.WithDatabase(dbName)))
284+
{
285+
var createTableCommand = connection.CreateDdlCommand(
286+
"CREATE TABLE Singers (SingerId INT64 PRIMARY KEY, Name STRING(1024))");
287+
var operationName = await createTableCommand.StartDdlAsync();
288+
Assert.False(string.IsNullOrEmpty(operationName));
289+
290+
await HandleLro<Empty, UpdateDatabaseDdlMetadata>(
291+
adminClient.UpdateDatabaseDdlOperationsClient, operationName);
292+
}
293+
294+
using (var connection = new SpannerConnection(builder))
295+
{
296+
var dropCommand = connection.CreateDdlCommand($"DROP DATABASE {dbName}");
297+
var operationName = await dropCommand.StartDdlAsync();
298+
// DropDatabase does not return a long-running operation.
299+
Assert.Null(operationName);
300+
}
301+
}
302+
finally
303+
{
304+
channel?.Shutdown();
305+
}
306+
307+
async Task HandleLro<TResponse, TMetadata>(OperationsClient client, string operationName)
308+
where TResponse : class, IMessage<TResponse>, new()
309+
where TMetadata : class, IMessage<TMetadata>, new()
310+
{
311+
var rawOperation = await client.GetOperationAsync(operationName);
312+
var operation = new Operation<TResponse, TMetadata>(rawOperation, client);
313+
var completedOperation = await operation.PollUntilCompletedAsync();
314+
315+
Assert.True(completedOperation.IsCompleted);
316+
Assert.Null(completedOperation.Exception);
255317
}
256318
}
257319
}

apis/Google.Cloud.Spanner.Data/Google.Cloud.Spanner.Data/SpannerCommand.ExecutableCommand.cs

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,14 @@ private async Task<int> ExecuteDdlAsync(CancellationToken cancellationToken)
244244
/// <summary>
245245
/// Starts a DDL operation, but does not wait for the long-running operation to finish.
246246
/// </summary>
247-
/// <returns>The name of the long-running operation that was created</returns>
247+
/// <returns>
248+
/// The name of the long-running operation that was created or null if the DDL statement did not
249+
/// create a long-running operation.
250+
/// </returns>
248251
internal async Task<string> StartDdlAsync(CancellationToken cancellationToken)
249252
{
250253
var operation = await ExecuteDdlAsync(pollUntilCompleted: false, cancellationToken).ConfigureAwait(false);
251-
return operation?.Name ?? "";
254+
return operation?.Name;
252255
}
253256

254257
private async Task<Operation> ExecuteDdlAsync(bool pollUntilCompleted, CancellationToken cancellationToken)
@@ -275,15 +278,8 @@ private async Task<Operation> ExecuteDdlAsync(bool pollUntilCompleted, Cancellat
275278
ExtraStatements = { CommandTextBuilder.ExtraStatements ?? new string[0] },
276279
ProtoDescriptors = CommandTextBuilder.ProtobufDescriptors?.ToByteString() ?? ByteString.Empty,
277280
};
278-
var response = await databaseAdminClient.CreateDatabaseAsync(request).ConfigureAwait(false);
279-
if (pollUntilCompleted)
280-
{
281-
response = await response.PollUntilCompletedAsync().ConfigureAwait(false);
282-
}
283-
if (response.IsFaulted)
284-
{
285-
throw SpannerException.FromOperationFailedException(response.Exception);
286-
}
281+
var createDbOperation = await databaseAdminClient.CreateDatabaseAsync(request).ConfigureAwait(false);
282+
var response = await HandleLro(createDbOperation).ConfigureAwait(false);
287283
operation = response.RpcMessage;
288284
}
289285
else if (CommandTextBuilder.IsDropDatabaseCommand)
@@ -315,16 +311,8 @@ private async Task<Operation> ExecuteDdlAsync(bool pollUntilCompleted, Cancellat
315311
Statements = { commandText, CommandTextBuilder.ExtraStatements ?? Enumerable.Empty<string>() },
316312
ProtoDescriptors = CommandTextBuilder.ProtobufDescriptors?.ToByteString() ?? ByteString.Empty,
317313
};
318-
319-
var response = await databaseAdminClient.UpdateDatabaseDdlAsync(request).ConfigureAwait(false);
320-
if (pollUntilCompleted)
321-
{
322-
response = await response.PollUntilCompletedAsync().ConfigureAwait(false);
323-
}
324-
if (response.IsFaulted)
325-
{
326-
throw SpannerException.FromOperationFailedException(response.Exception);
327-
}
314+
var updateDdlOperation = await databaseAdminClient.UpdateDatabaseDdlAsync(request).ConfigureAwait(false);
315+
var response = await HandleLro(updateDdlOperation).ConfigureAwait(false);
328316
operation = response.RpcMessage;
329317
}
330318
}
@@ -339,6 +327,21 @@ private async Task<Operation> ExecuteDdlAsync(bool pollUntilCompleted, Cancellat
339327
}
340328

341329
return operation;
330+
331+
async Task<Operation<TResponse, TMetadata>> HandleLro<TResponse, TMetadata>(Operation<TResponse, TMetadata> operationToPoll)
332+
where TResponse : class, IMessage<TResponse>, new()
333+
where TMetadata : class, IMessage<TMetadata>, new()
334+
{
335+
if (pollUntilCompleted)
336+
{
337+
operationToPoll = await operationToPoll.PollUntilCompletedAsync().ConfigureAwait(false);
338+
}
339+
if (operationToPoll.IsFaulted)
340+
{
341+
throw SpannerException.FromOperationFailedException(operationToPoll.Exception);
342+
}
343+
return operationToPoll;
344+
}
342345
}
343346

344347
private async Task<int> ExecuteMutationsAsync(CancellationToken cancellationToken)

apis/Google.Cloud.Spanner.Data/Google.Cloud.Spanner.Data/SpannerCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
using Google.Api.Gax;
1616
using Google.Cloud.Spanner.V1;
17-
using Google.LongRunning;
1817
using System;
1918
using System.Collections.Generic;
2019
using System.Data;
@@ -522,6 +521,7 @@ public Task<long> ExecutePartitionedUpdateAsync(CancellationToken cancellationTo
522521
/// The command must contain one or more DDL statements;
523522
/// <see cref="SpannerConnection.CreateDdlCommand(string, string[])"/> for details.
524523
/// </summary>
524+
/// <param name="cancellationToken">An optional token for canceling the call.</param>
525525
/// <returns>
526526
/// The name of the long-running operation that was started for the DDL statement(s).
527527
/// Note: The ID is empty for DropDatabase commands.

0 commit comments

Comments
 (0)