예제 #1
0
        public async Task ExecuteSqlAsync_RequestTransactionIsPopulatedWhenPresent()
        {
            var pool                   = new FakeSessionPool();
            var transactionId          = ByteString.CopyFromUtf8("transaction");
            var mode                   = TransactionOptions.ModeOneofCase.ReadWrite;
            var pooledSession          = PooledSession.FromSessionName(pool, s_sampleSessionName);
            var sessionWithTransaction = pooledSession.WithTransaction(transactionId, mode);

            // Make a successful request
            var request = new ExecuteSqlRequest();

            pool.Mock.Setup(client => client.ExecuteSqlAsync(request, It.IsAny <CallSettings>()))
            .ReturnsAsync(new ResultSet())
            .Verifiable();
            await sessionWithTransaction.ExecuteSqlAsync(request, null);

            // The call modifies the request. (We can't easily check that it was modified before the RPC)
            Assert.Equal(s_sampleSessionName, request.SessionAsSessionName);
            Assert.Equal(transactionId, request.Transaction.Id);

            pool.Mock.Verify();
        }
예제 #2
0
        public Task <long> ExecuteDmlAsync(ExecuteSqlRequest request, CancellationToken cancellationToken, int timeoutSeconds)
        {
            return(ExecuteHelper.WithErrorTranslationAndProfiling(Impl, "EphemeralTransaction.ExecuteDmlAsync", _connection.Logger));

            async Task <long> Impl()
            {
                using (var transaction = await _connection.BeginTransactionImplAsync(_transactionOptions, TransactionMode.ReadWrite, cancellationToken).ConfigureAwait(false))
                {
                    transaction.CommitTimeout  = timeoutSeconds;
                    transaction.CommitPriority = _commitPriority;
                    while (true)
                    {
                        try
                        {
                            long count = await((ISpannerTransaction)transaction)
                                         .ExecuteDmlAsync(request, cancellationToken, timeoutSeconds)
                                         .ConfigureAwait(false);

                            // This is somewhat ugly. PDML commits as it goes, so we don't need to, whereas non-partitioned
                            // DML needs the commit afterwards to finish up.
                            if (_transactionOptions.ModeCase != TransactionOptions.ModeOneofCase.PartitionedDml)
                            {
                                await transaction.CommitAsync(cancellationToken).ConfigureAwait(false);
                            }
                            return(count);
                        }
                        catch (SpannerException e) when(
                            _transactionOptions.ModeCase == TransactionOptions.ModeOneofCase.PartitionedDml &&
                            e.ErrorCode == ErrorCode.Internal &&
                            e.Message.Contains("Received unexpected EOS on DATA frame from server"))
                        {
                            // Retry with the same transaction. Since this error happens in long-lived
                            // transactions (>= 30 mins), it's unnecessary to do exponential backoff.
                            continue;
                        }
                    }
                }
            }
        }
예제 #3
0
        public async Task ExecuteSqlAsync_RequestTransactionIsLeftAlonePopulatedWhenPresent()
        {
            var pool          = new FakeSessionPool();
            var pooledSession = PooledSession.FromSessionName(pool, s_sampleSessionName);

            // Make a successful request
            var request = new ExecuteSqlRequest {
                Transaction = new TransactionSelector {
                    Begin = new TransactionOptions {
                        ReadOnly = new TransactionOptions.Types.ReadOnly()
                    }
                }
            };

            pool.Mock.Setup(client => client.ExecuteSqlAsync(request, It.IsAny <CallSettings>())).ReturnsAsync(new ResultSet());
            await pooledSession.ExecuteSqlAsync(request, 5, CancellationToken.None);

            // The call modifies the request's session, but not transaction.
            Assert.Equal(s_sampleSessionName, request.SessionAsSessionName);
            Assert.Equal(TransactionSelector.SelectorOneofCase.Begin, request.Transaction.SelectorCase);
            Assert.Equal(new TransactionOptions.Types.ReadOnly(), request.Transaction.Begin.ReadOnly);
        }
    public async Task <long> CustomTimeoutsAndRetriesAsync(string projectId, string instanceId, string databaseId)
    {
        // Create a SessionPool.
        SpannerClient client      = SpannerClient.Create();
        SessionPool   sessionPool = new SessionPool(client, new SessionPoolOptions());

        // Acquire a session with a read-write transaction to run a query.
        DatabaseName databaseName =
            DatabaseName.FromProjectInstanceDatabase(projectId, instanceId, databaseId);
        TransactionOptions transactionOptions = new TransactionOptions
        {
            ReadWrite = new ReadWrite()
        };

        using PooledSession session = await sessionPool.AcquireSessionAsync(
                  databaseName, transactionOptions, CancellationToken.None);

        ExecuteSqlRequest request = new ExecuteSqlRequest
        {
            Sql = "INSERT Singers (SingerId, FirstName, LastName) VALUES (20, 'George', 'Washington')"
        };

        // Prepare the call settings with custom timeout and retry settings.
        CallSettings settings = CallSettings
                                .FromExpiration(Expiration.FromTimeout(TimeSpan.FromSeconds(60)))
                                .WithRetry(RetrySettings.FromExponentialBackoff(
                                               maxAttempts: 12,
                                               initialBackoff: TimeSpan.FromMilliseconds(500),
                                               maxBackoff: TimeSpan.FromMilliseconds(6400),
                                               backoffMultiplier: 1.5,
                                               retryFilter: RetrySettings.FilterForStatusCodes(
                                                   new StatusCode[] { StatusCode.Unavailable, StatusCode.DeadlineExceeded })));

        ResultSet result = await session.ExecuteSqlAsync(request, settings);

        await session.CommitAsync(new CommitRequest(), null);

        return(result.Stats.RowCountExact);
    }
        public Task <long> ExecuteDmlAsync(ExecuteSqlRequest request, CancellationToken cancellationToken, int timeoutSeconds)
        {
            return(ExecuteHelper.WithErrorTranslationAndProfiling(Impl, "EphemeralTransaction.ExecuteDmlAsync", _connection.Logger));

            async Task <long> Impl()
            {
                using (var transaction = await _connection.BeginTransactionImplAsync(_transactionOptions, TransactionMode.ReadWrite, cancellationToken).ConfigureAwait(false))
                {
                    transaction.CommitTimeout = timeoutSeconds;
                    long count = await((ISpannerTransaction)transaction)
                                 .ExecuteDmlAsync(request, cancellationToken, timeoutSeconds)
                                 .ConfigureAwait(false);

                    // This is somewhat ugly. PDML commits as it goes, so we don't need to, whereas non-partitioned
                    // DML needs the commit afterwards to finish up.
                    if (_transactionOptions.ModeCase != TransactionOptions.ModeOneofCase.PartitionedDml)
                    {
                        await transaction.CommitAsync(cancellationToken).ConfigureAwait(false);
                    }
                    return(count);
                }
            }
        }
예제 #6
0
        public Task <ReliableStreamReader> ExecuteQueryAsync(
            ExecuteSqlRequest request,
            CancellationToken cancellationToken)
        {
            return(ExecuteHelper.WithErrorTranslationAndProfiling(
                       async() =>
            {
                GaxPreconditions.CheckNotNull(request, nameof(request));
                Logger.Debug(() => "Executing a query through an ephemeral transaction.");

                using (var holder = await SpannerConnection.SessionHolder
                                    .Allocate(_connection, cancellationToken)
                                    .ConfigureAwait(false))
                {
                    var streamReader = _connection.SpannerClient.GetSqlStreamReader(request, holder.Session);

                    holder.TakeOwnership();
                    streamReader.StreamClosed += (o, e) => { _connection.ReleaseSession(streamReader.Session); };

                    return streamReader;
                }
            }, "EphemeralTransaction.ExecuteQuery"));
        }
        public void Equals_ExecuteSqlRequest()
        {
            var request = new ExecuteSqlRequest
            {
                Sql         = "SELECT * FROM Foo",
                Session     = "sessionName",
                Transaction = new TransactionSelector
                {
                    Id = ByteString.CopyFrom("some_id", Encoding.UTF8)
                }
            };
            var request2   = request.Clone();
            var request3   = new ExecuteSqlRequest();
            var partition1 = new CommandPartition(ReadOrQueryRequest.FromRequest(request));
            var partition2 = new CommandPartition(ReadOrQueryRequest.FromRequest(request2));
            var partition3 = new CommandPartition(ReadOrQueryRequest.FromRequest(request3));
            var partition4 = new CommandPartition(ReadOrQueryRequest.FromRequest(new ReadRequest()));

            Assert.Equal(partition1, partition2);
            Assert.NotEqual(partition1, partition3);
            Assert.NotEqual(partition1, partition4);
            Assert.NotEqual(partition3, partition4);
            Assert.Equal(partition1, partition1.Clone());
        }
 public Task <long> ExecuteDmlAsync(ExecuteSqlRequest request, CancellationToken cancellationToken, int timeoutSeconds) =>
 throw new NotSupportedException("A single use transaction can only be used for read operations.");
예제 #9
0
        public async Task <long> ExecuteDmlAsync(ExecuteSqlRequest request, CancellationToken cancellationToken, int timeoutSeconds)
        {
            ISpannerTransaction transaction = await GetTransactionAsync(cancellationToken, timeoutSeconds).ConfigureAwait(false);

            return(await transaction.ExecuteDmlAsync(request, cancellationToken, timeoutSeconds).ConfigureAwait(false));
        }
예제 #10
0
 internal CommandPartition(ExecuteSqlRequest executeSqlRequest)
 {
     ExecuteSqlRequest = executeSqlRequest;
 }
예제 #11
0
        public async Task <ReliableStreamReader> ExecuteQueryAsync(ExecuteSqlRequest request, CancellationToken cancellationToken, int timeoutSeconds)
        {
            ISpannerTransaction transaction = await SpannerTransactionTask.ConfigureAwait(false);

            return(await transaction.ExecuteQueryAsync(request, cancellationToken, timeoutSeconds).ConfigureAwait(false));
        }
예제 #12
0
        public IActionResult ExecuteResult([FromRoute] string id, [FromBody] ExecuteSqlRequest request)
        {
            var conn            = ConnectionHelper.Connections[id];
            var ret             = new List <MySqlQueryResult>();
            var splitedCommands = MySqlCommandSpliter.SplitCommand(request.Sql);

            using (var command = new MySqlCommand())
            {
                command.Connection  = conn;
                command.CommandText = $"USE `{request.Database}`;";
                try
                {
                    command.ExecuteNonQuery();
                }
                catch (MySqlException ex)
                {
                    Response.StatusCode = 400;
                    return(Json(new DBError
                    {
                        Code = ex.Number,
                        Message = ex.Message
                    }));
                }
                foreach (var x in splitedCommands)
                {
                    var res = new MySqlQueryResult();
                    res.Command = x;
                    var analyze = MySqlCommandSpliter.AnalyzeCommand(x);
                    res.Table           = analyze.Table;
                    command.CommandText = x;
                    var begin = DateTime.Now;
                    IEnumerable <MySqlTableColumn> tableColumns = null;
                    try
                    {
                        tableColumns = MySqlCommandSpliter.GetTableColumns(res.Table, conn).ToList();
                        res.Readonly = string.IsNullOrWhiteSpace(analyze.Table) || !(analyze.IsSimpleSelect && MySqlCommandSpliter.IsContainedKeys(analyze.Columns, tableColumns));
                    }
                    catch (MySqlException)
                    {
                        res.Readonly = true;
                    }
                    try
                    {
                        using (var reader = command.ExecuteReader())
                        {
                            if (res.Readonly)
                            {
                                res.Columns      = GenerateColumnsFromReader(reader).ToList();
                                res.ColumnTypes  = null;
                                res.Nullable     = null;
                                res.Keys         = null;
                                res.RowsAffected = reader.RecordsAffected;
                            }
                            else
                            {
                                res.Columns = analyze.Columns;
                                if (res.Columns.Count() == 1 && res.Columns.First() == "*")
                                {
                                    res.Columns = tableColumns.Select(x => x.Field);
                                }
                                else
                                {
                                    res.Columns = analyze.Columns;
                                }
                                res.ColumnTypes  = res.Columns.Select(x => tableColumns.SingleOrDefault(y => y.Field == x)?.Type);
                                res.Nullable     = res.Columns.Select(x => tableColumns.SingleOrDefault(y => y.Field == x)?.Null);
                                res.Keys         = tableColumns.Where(x => x.Key == "PRI").Select(x => x.Field);
                                res.RowsAffected = reader.RecordsAffected;
                            }
                            if (reader.HasRows)
                            {
                                res.Rows = new List <List <string> >();
                                while (reader.Read())
                                {
                                    var row = new List <string>();
                                    for (var i = 0; i < reader.FieldCount; ++i)
                                    {
                                        if (reader.IsDBNull(i))
                                        {
                                            row.Add(null);
                                        }
                                        else if (reader.GetFieldType(i) == typeof(byte[]))
                                        {
                                            row.Add(Convert.ToBase64String((byte[])reader[i]));
                                        }
                                        else
                                        {
                                            row.Add(reader[i].ToString());
                                        }
                                    }
                                    res.Rows.Add(row);
                                }
                            }
                        }
                    }
                    catch (MySqlException ex)
                    {
                        Response.StatusCode = 400;
                        return(Json(new DBError
                        {
                            Code = ex.Number,
                            Message = ex.Message
                        }));
                    }
                    var end = DateTime.Now;
                    res.TimeSpan = Convert.ToInt64((end - begin).TotalMilliseconds);
                    ret.Add(res);
                }
            }
            return(Json(ret));
        }
 public Task <ReliableStreamReader> ExecuteQueryAsync(ExecuteSqlRequest request,
                                                      CancellationToken cancellationToken,
                                                      int timeoutSeconds) =>
 throw new NotSupportedException("A partitioned update transaction can only be used for DML operations.");