private static async Task <T> ExecuteCommandAsync <T>(
            SpannerConnection connection, Func <DbCommand, Task <T> > executeAsync, string sql, bool useTransaction,
            IReadOnlyList <object> parameters)
        {
            if (connection.State != ConnectionState.Closed)
            {
                connection.Close();
            }
            await connection.OpenAsync().ConfigureAwait(false);

            try
            {
                using (var transaction = useTransaction ? connection.BeginTransaction() : null)
                {
                    T result;
                    using (var command = CreateCommand(connection, sql, parameters))
                    {
                        result = await executeAsync(command).ConfigureAwait(false);
                    }
                    transaction?.Commit();

                    return(result);
                }
            }
            finally
            {
                if (connection.State == ConnectionState.Closed &&
                    connection.State != ConnectionState.Closed)
                {
                    connection.Close();
                }
            }
        }
        public void TagsCanBeSetToNull()
        {
            Mock <SpannerClient> spannerClientMock = SpannerClientHelpers
                                                     .CreateMockClient(Logger.DefaultLogger, MockBehavior.Strict);

            spannerClientMock
            .SetupBatchCreateSessionsAsync()
            .SetupBeginTransactionAsync()
            .SetupExecuteStreamingSql()
            .SetupCommitAsync();
            SpannerConnection  connection  = BuildSpannerConnection(spannerClientMock);
            SpannerTransaction transaction = connection.BeginTransaction();

            transaction.Tag = null;

            var command = connection.CreateSelectCommand("SELECT * FROM FOO");

            command.Transaction = transaction;
            command.Tag         = null;
            using (var reader = command.ExecuteReader())
            {
                Assert.True(reader.HasRows);
            }
            transaction.Commit();

            spannerClientMock.Verify(client => client.ExecuteStreamingSql(
                                         It.Is <ExecuteSqlRequest>(request => request.RequestOptions.RequestTag == "" && request.RequestOptions.TransactionTag == ""),
                                         It.IsAny <CallSettings>()), Times.Once());
            spannerClientMock.Verify(client => client.CommitAsync(
                                         It.Is <CommitRequest>(request => request.RequestOptions.RequestTag == "" && request.RequestOptions.TransactionTag == ""),
                                         It.IsAny <CallSettings>()), Times.Once());
        }
        private static T ExecuteCommand <T>(
            SpannerConnection connection, Func <DbCommand, T> execute, string sql, bool useTransaction,
            object[] parameters)
        {
            if (connection.State != ConnectionState.Closed)
            {
                connection.Close();
            }
            connection.Open();
            try
            {
                using (var transaction = useTransaction ? connection.BeginTransaction() : null)
                {
                    T result;
                    using (var command = CreateCommand(connection, sql, parameters))
                    {
                        command.Transaction = transaction;
                        result = execute(command);
                    }
                    transaction?.Commit();

                    return(result);
                }
            }
            finally
            {
                if (connection.State == ConnectionState.Closed &&
                    connection.State != ConnectionState.Closed)
                {
                    connection.Close();
                }
                //To debug the parse error, set SkipToLine= this value.
                Trace.WriteLine($"Error encountered at statement {s_gStatements}");
            }
        }
        public void CommitPriorityCanBeSetAfterCommandExecution()
        {
            var priority = Priority.Medium;
            Mock <SpannerClient> spannerClientMock = SpannerClientHelpers
                                                     .CreateMockClient(Logger.DefaultLogger, MockBehavior.Strict);

            spannerClientMock
            .SetupBatchCreateSessionsAsync()
            .SetupBeginTransactionAsync()
            .SetupExecuteStreamingSql()
            .SetupCommitAsync();
            SpannerConnection  connection  = BuildSpannerConnection(spannerClientMock);
            SpannerTransaction transaction = connection.BeginTransaction();

            // Execute a command on the transaction.
            var command = connection.CreateSelectCommand("SELECT * FROM FOO");

            command.Transaction = transaction;
            using (var reader = command.ExecuteReader())
            {
                Assert.True(reader.HasRows);
            }
            // Verify that we can set the commit priority after a command has been executed.
            transaction.CommitPriority = priority;
            transaction.Commit();

            spannerClientMock.Verify(client => client.CommitAsync(
                                         It.Is <CommitRequest>(request => request.RequestOptions.Priority == PriorityConverter.ToProto(priority)),
                                         It.IsAny <CallSettings>()), Times.Once());
        }
        public void TransactionTagCannotBeSetAfterCommandExecution()
        {
            var transactionTag = "transaction-tag-1";
            Mock <SpannerClient> spannerClientMock = SpannerClientHelpers
                                                     .CreateMockClient(Logger.DefaultLogger, MockBehavior.Strict);

            spannerClientMock
            .SetupBatchCreateSessionsAsync()
            .SetupBeginTransactionAsync()
            .SetupExecuteStreamingSql()
            .SetupCommitAsync();
            SpannerConnection  connection  = BuildSpannerConnection(spannerClientMock);
            SpannerTransaction transaction = connection.BeginTransaction();

            // Execute a command on the transaction without a transaction tag.
            var command1 = connection.CreateSelectCommand("SELECT * FROM FOO");

            command1.Transaction = transaction;
            using (var reader = command1.ExecuteReader())
            {
                Assert.True(reader.HasRows);
            }
            Assert.Throws <InvalidOperationException>(() => transaction.Tag = transactionTag);

            transaction.Commit();

            spannerClientMock.Verify(client => client.ExecuteStreamingSql(
                                         It.Is <ExecuteSqlRequest>(request => request.RequestOptions.RequestTag == "" && request.RequestOptions.TransactionTag == ""),
                                         It.IsAny <CallSettings>()), Times.Once());
            spannerClientMock.Verify(client => client.CommitAsync(
                                         It.Is <CommitRequest>(request => request.RequestOptions.RequestTag == "" && request.RequestOptions.TransactionTag == ""),
                                         It.IsAny <CallSettings>()), Times.Once());
        }
        public void CommitIncludesPriority()
        {
            var commitPriority  = Priority.Medium;
            var commandPriority = Priority.High;
            Mock <SpannerClient> spannerClientMock = SpannerClientHelpers
                                                     .CreateMockClient(Logger.DefaultLogger, MockBehavior.Strict);

            spannerClientMock
            .SetupBatchCreateSessionsAsync()
            .SetupBeginTransactionAsync()
            .SetupExecuteStreamingSql()
            .SetupCommitAsync();
            SpannerConnection  connection  = BuildSpannerConnection(spannerClientMock);
            SpannerTransaction transaction = connection.BeginTransaction();

            transaction.CommitPriority = commitPriority;

            var command = connection.CreateSelectCommand("SELECT * FROM FOO");

            command.Transaction = transaction;
            command.Priority    = commandPriority;
            using (var reader = command.ExecuteReader())
            {
                Assert.True(reader.HasRows);
            }
            transaction.Commit();

            spannerClientMock.Verify(client => client.ExecuteStreamingSql(
                                         It.Is <ExecuteSqlRequest>(request => request.RequestOptions.Priority == PriorityConverter.ToProto(commandPriority)),
                                         It.IsAny <CallSettings>()), Times.Once());
            spannerClientMock.Verify(client => client.CommitAsync(
                                         It.Is <CommitRequest>(request => request.RequestOptions.Priority == PriorityConverter.ToProto(commitPriority)),
                                         It.IsAny <CallSettings>()), Times.Once());
        }
        public void CommandIncludesRequestAndTransactionTag()
        {
            var requestTag     = "request-tag-1";
            var transactionTag = "transaction-tag-1";
            Mock <SpannerClient> spannerClientMock = SpannerClientHelpers
                                                     .CreateMockClient(Logger.DefaultLogger, MockBehavior.Strict);

            spannerClientMock
            .SetupBatchCreateSessionsAsync()
            .SetupBeginTransactionAsync()
            .SetupExecuteBatchDmlAsync()
            .SetupCommitAsync();
            SpannerConnection  connection  = SpannerCommandTests.BuildSpannerConnection(spannerClientMock);
            SpannerTransaction transaction = connection.BeginTransaction();

            transaction.Tag = transactionTag;

            var command = transaction.CreateBatchDmlCommand();

            command.Add("UPDATE FOO SET BAR=1 WHERE TRUE");
            command.Tag = requestTag;
            command.ExecuteNonQuery();
            transaction.Commit();

            spannerClientMock.Verify(client => client.ExecuteBatchDmlAsync(
                                         It.Is <ExecuteBatchDmlRequest>(request => request.RequestOptions.RequestTag == requestTag && request.RequestOptions.TransactionTag == transactionTag),
                                         It.IsAny <CallSettings>()), Times.Once());
            spannerClientMock.Verify(client => client.CommitAsync(
                                         It.Is <CommitRequest>(request => request.RequestOptions.RequestTag == "" && request.RequestOptions.TransactionTag == transactionTag),
                                         It.IsAny <CallSettings>()), Times.Once());
        }
        public void CommandIncludesPriority()
        {
            var priority = Priority.High;
            Mock <SpannerClient> spannerClientMock = SpannerClientHelpers
                                                     .CreateMockClient(Logger.DefaultLogger, MockBehavior.Strict);

            spannerClientMock
            .SetupBatchCreateSessionsAsync()
            .SetupBeginTransactionAsync()
            .SetupExecuteBatchDmlAsync()
            .SetupCommitAsync();
            SpannerConnection  connection  = SpannerCommandTests.BuildSpannerConnection(spannerClientMock);
            SpannerTransaction transaction = connection.BeginTransaction();

            var command = transaction.CreateBatchDmlCommand();

            command.Add("UPDATE FOO SET BAR=1 WHERE TRUE");
            command.Priority = priority;
            command.ExecuteNonQuery();
            transaction.Commit();

            spannerClientMock.Verify(client => client.ExecuteBatchDmlAsync(
                                         It.Is <ExecuteBatchDmlRequest>(request => request.RequestOptions.Priority == PriorityConverter.ToProto(priority)),
                                         It.IsAny <CallSettings>()), Times.Once());
        }
        public void CommandIncludesRequestAndTransactionTag()
        {
            var requestTag1    = "request-tag-1";
            var requestTag2    = "request-tag-2";
            var transactionTag = "transaction-tag-1";
            Mock <SpannerClient> spannerClientMock = SpannerClientHelpers
                                                     .CreateMockClient(Logger.DefaultLogger, MockBehavior.Strict);

            spannerClientMock
            .SetupBatchCreateSessionsAsync()
            .SetupBeginTransactionAsync()
            .SetupExecuteStreamingSql()
            .SetupCommitAsync();
            SpannerConnection  connection  = BuildSpannerConnection(spannerClientMock);
            SpannerTransaction transaction = connection.BeginTransaction();

            transaction.Tag = transactionTag;

            var command1 = connection.CreateSelectCommand("SELECT * FROM FOO");

            command1.Transaction = transaction;
            command1.Tag         = requestTag1;
            using (var reader = command1.ExecuteReader())
            {
                Assert.True(reader.HasRows);
            }

            var command2 = connection.CreateSelectCommand("SELECT * FROM FOO");

            command2.Transaction = transaction;
            command2.Tag         = requestTag2;
            using (var reader = command2.ExecuteReader())
            {
                Assert.True(reader.HasRows);
            }

            // Execute a statement without a request tag on the same transaction.
            var command3 = connection.CreateSelectCommand("SELECT * FROM FOO");

            command3.Transaction = transaction;
            using (var reader = command3.ExecuteReader())
            {
                Assert.True(reader.HasRows);
            }
            transaction.Commit();

            spannerClientMock.Verify(client => client.ExecuteStreamingSql(
                                         It.Is <ExecuteSqlRequest>(request => request.RequestOptions.RequestTag == requestTag1 && request.RequestOptions.TransactionTag == transactionTag),
                                         It.IsAny <CallSettings>()), Times.Once());
            spannerClientMock.Verify(client => client.ExecuteStreamingSql(
                                         It.Is <ExecuteSqlRequest>(request => request.RequestOptions.RequestTag == requestTag2 && request.RequestOptions.TransactionTag == transactionTag),
                                         It.IsAny <CallSettings>()), Times.Once());
            spannerClientMock.Verify(client => client.ExecuteStreamingSql(
                                         It.Is <ExecuteSqlRequest>(request => request.RequestOptions.RequestTag == "" && request.RequestOptions.TransactionTag == transactionTag),
                                         It.IsAny <CallSettings>()), Times.Once());
            spannerClientMock.Verify(client => client.CommitAsync(
                                         It.Is <CommitRequest>(request => request.RequestOptions.RequestTag == "" && request.RequestOptions.TransactionTag == transactionTag),
                                         It.IsAny <CallSettings>()), Times.Once());
        }
        public void CommitPriorityDefaultsToUnspecified()
        {
            Mock <SpannerClient> spannerClientMock = SpannerClientHelpers
                                                     .CreateMockClient(Logger.DefaultLogger, MockBehavior.Strict);

            spannerClientMock
            .SetupBatchCreateSessionsAsync()
            .SetupBeginTransactionAsync();
            SpannerConnection  connection  = BuildSpannerConnection(spannerClientMock);
            SpannerTransaction transaction = connection.BeginTransaction();

            Assert.Equal(Priority.Unspecified, transaction.CommitPriority);
        }