예제 #1
0
    public override async ValueTask ExecuteAsync(int timeout, IDescriptorFiller descriptorFiller, CancellationToken cancellationToken = default)
    {
        EnsureNotDeallocated();

        await descriptorFiller.FillAsync(_parameters, 0, cancellationToken).ConfigureAwait(false);

        ClearStatusVector();
        NativeHelpers.CallIfExists(() =>
        {
            _db.FbClient.fb_dsql_set_timeout(_statusVector, ref _handle, (uint)timeout);
            _db.ProcessStatusVector(_statusVector);
        });

        ClearStatusVector();

        var inSqlda  = IntPtr.Zero;
        var outSqlda = IntPtr.Zero;

        if (_parameters != null)
        {
            inSqlda = XsqldaMarshaler.MarshalManagedToNative(_db.Charset, _parameters);
        }
        if (StatementType == DbStatementType.StoredProcedure)
        {
            Fields.ResetValues();
            outSqlda = XsqldaMarshaler.MarshalManagedToNative(_db.Charset, _fields);
        }

        var trHandle = _transaction.HandlePtr;

        _db.FbClient.isc_dsql_execute2(
            _statusVector,
            ref trHandle,
            ref _handle,
            IscCodes.SQLDA_VERSION1,
            inSqlda,
            outSqlda);

        if (outSqlda != IntPtr.Zero)
        {
            var descriptor = XsqldaMarshaler.MarshalNativeToManaged(_db.Charset, outSqlda, true);

            var values = new DbValue[descriptor.Count];

            for (var i = 0; i < values.Length; i++)
            {
                var d     = descriptor[i];
                var value = await d.DbValue.GetValueAsync(cancellationToken).ConfigureAwait(false);

                values[i] = new DbValue(this, d, value);
            }

            OutputParameters.Enqueue(values);
        }

        XsqldaMarshaler.CleanUpNativeData(ref inSqlda);
        XsqldaMarshaler.CleanUpNativeData(ref outSqlda);

        _db.ProcessStatusVector(_statusVector);

        if (DoRecordsAffected)
        {
            RecordsAffected = await GetRecordsAffectedAsync(cancellationToken).ConfigureAwait(false);
        }
        else
        {
            RecordsAffected = -1;
        }

        State = StatementState.Executed;
    }
    public override async ValueTask <ExecuteResultItem[]> ExecuteAsync(int count, IDescriptorFiller descriptorFiller, CancellationToken cancellationToken = default)
    {
        var parametersData = new byte[count][];

        for (var i = 0; i < parametersData.Length; i++)
        {
            await descriptorFiller.FillAsync(_statement.Parameters, i, cancellationToken).ConfigureAwait(false);

            // this may throw error, so it needs to be before any writing
            parametersData[i] = await _statement.WriteParametersAsync(cancellationToken).ConfigureAwait(false);
        }

        await Database.Xdr.WriteAsync(IscCodes.op_batch_create, cancellationToken).ConfigureAwait(false);

        await Database.Xdr.WriteAsync(_statement.Handle, cancellationToken).ConfigureAwait(false);         // p_batch_statement

        var blr = _statement.Parameters.ToBlr();
        await Database.Xdr.WriteBufferAsync(blr.Data, cancellationToken).ConfigureAwait(false);     // p_batch_blr

        await Database.Xdr.WriteAsync(blr.Length, cancellationToken).ConfigureAwait(false);         // p_batch_msglen

        var pb = new BatchParameterBuffer();

        if (_statement.ReturnRecordsAffected)
        {
            pb.Append(IscCodes.Batch.TAG_RECORD_COUNTS, 1);
        }
        if (MultiError)
        {
            pb.Append(IscCodes.Batch.TAG_MULTIERROR, 1);
        }
        await Database.Xdr.WriteBufferAsync(pb.ToArray(), cancellationToken).ConfigureAwait(false);         // p_batch_pb

        await Database.Xdr.WriteAsync(IscCodes.op_batch_msg, cancellationToken).ConfigureAwait(false);

        await Database.Xdr.WriteAsync(_statement.Handle, cancellationToken).ConfigureAwait(false);         // p_batch_statement

        await Database.Xdr.WriteAsync(parametersData.Length, cancellationToken).ConfigureAwait(false);     // p_batch_messages

        foreach (var item in parametersData)
        {
            await Database.Xdr.WriteOpaqueAsync(item, item.Length, cancellationToken).ConfigureAwait(false);             // p_batch_data
        }

        await Database.Xdr.WriteAsync(IscCodes.op_batch_exec, cancellationToken).ConfigureAwait(false);

        await Database.Xdr.WriteAsync(_statement.Handle, cancellationToken).ConfigureAwait(false);             // p_batch_statement

        await Database.Xdr.WriteAsync(_statement.Transaction.Handle, cancellationToken).ConfigureAwait(false); // p_batch_transaction;

        await Database.Xdr.FlushAsync(cancellationToken).ConfigureAwait(false);

        var numberOfResponses = 3;

        try
        {
            numberOfResponses--;
            var batchCreateResponse = await Database.ReadResponseAsync(cancellationToken).ConfigureAwait(false);

            numberOfResponses--;
            var batchMsgResponse = await Database.ReadResponseAsync(cancellationToken).ConfigureAwait(false);

            numberOfResponses--;
            var batchExecResponse = (BatchCompletionStateResponse)await Database.ReadResponseAsync(cancellationToken).ConfigureAwait(false);

            return(BuildResult(batchExecResponse));
        }
        finally
        {
            await Database.SafeFinishFetchingAsync(numberOfResponses, cancellationToken).ConfigureAwait(false);
        }
    }