diff --git a/src/FirebirdSql.Data.FirebirdClient/Client/Managed/Version10/GdsStatement.cs b/src/FirebirdSql.Data.FirebirdClient/Client/Managed/Version10/GdsStatement.cs index f920c270..a4d5c18e 100644 --- a/src/FirebirdSql.Data.FirebirdClient/Client/Managed/Version10/GdsStatement.cs +++ b/src/FirebirdSql.Data.FirebirdClient/Client/Managed/Version10/GdsStatement.cs @@ -1,4 +1,4 @@ -/* +/* * The contents of this file are subject to the Initial * Developer's Public License Version 1.0 (the "License"); * you may not use this file except in compliance with the @@ -19,6 +19,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using FirebirdSql.Data.Common; @@ -36,7 +37,7 @@ internal class GdsStatement : StatementBase protected Descriptor _parameters; protected Descriptor _fields; protected bool _allRowsFetched; - private Queue _rows; + private Queue _rows; private int _fetchSize; #endregion @@ -110,7 +111,8 @@ public GdsStatement(GdsDatabase database, GdsTransaction transaction) { _handle = IscCodes.INVALID_OBJECT; _fetchSize = 200; - _rows = new Queue(); + //_rows = new Queue(); + _rows = new Queue(); // optimized OutputParameters = new Queue(); _database = database; @@ -375,6 +377,26 @@ public override async ValueTask ExecuteAsync(int timeout, IDescriptorFiller desc } } + protected DbValue[] _dbValues; // optimized + protected void CreateDbValues() + { + _dbValues = new DbValue[_fields.Count]; + for (int i = 0; i < _fields.Count; i++) + { + _dbValues[i] = new DbValue(this, _fields[i], null); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected DbValue[] GetDbValues(object[] values) + { + for (int i=0; i < _fields.Count; ++i) + { + _dbValues[i].SetValue(values[i]); + } + return _dbValues; + } + public override DbValue[] Fetch() { EnsureNotDeallocated(); @@ -407,14 +429,14 @@ public override DbValue[] Fetch() var operation = _database.ReadOperation(); if (operation == IscCodes.op_fetch_response) { + CreateDbValues(); + var hasOperation = true; while (!_allRowsFetched) { - var response = hasOperation + if ((hasOperation ? _database.ReadResponse(operation) - : _database.ReadResponse(); - hasOperation = false; - if (response is FetchResponse fetchResponse) + : _database.ReadResponse()) is FetchResponse fetchResponse) { if (fetchResponse.Count > 0 && fetchResponse.Status == 0) { @@ -433,6 +455,7 @@ public override DbValue[] Fetch() { break; } + hasOperation = false; } } else @@ -448,7 +471,7 @@ public override DbValue[] Fetch() if (_rows != null && _rows.Count > 0) { - return _rows.Dequeue(); + return GetDbValues(_rows.Dequeue()); } else { @@ -488,14 +511,13 @@ public override async ValueTask FetchAsync(CancellationToken cancella var operation = await _database.ReadOperationAsync(cancellationToken).ConfigureAwait(false); if (operation == IscCodes.op_fetch_response) { + CreateDbValues(); var hasOperation = true; while (!_allRowsFetched) { - var response = hasOperation + if ((hasOperation ? await _database.ReadResponseAsync(operation, cancellationToken).ConfigureAwait(false) - : await _database.ReadResponseAsync(cancellationToken).ConfigureAwait(false); - hasOperation = false; - if (response is FetchResponse fetchResponse) + : await _database.ReadResponseAsync(cancellationToken).ConfigureAwait(false)) is FetchResponse fetchResponse) { if (fetchResponse.Count > 0 && fetchResponse.Status == 0) { @@ -514,6 +536,7 @@ public override async ValueTask FetchAsync(CancellationToken cancella { break; } + hasOperation = false; } } else @@ -529,7 +552,7 @@ public override async ValueTask FetchAsync(CancellationToken cancella if (_rows != null && _rows.Count > 0) { - return _rows.Dequeue(); + return GetDbValues(_rows.Dequeue()); } else { @@ -850,7 +873,8 @@ protected void ProcessStoredProcedureExecuteResponse(SqlResponse response) { if (response.Count > 0) { - OutputParameters.Enqueue(ReadRow()); + CreateDbValues(); + OutputParameters.Enqueue(GetDbValues(ReadRow())); } } catch (IOException ex) @@ -864,7 +888,8 @@ protected async ValueTask ProcessStoredProcedureExecuteResponseAsync(SqlResponse { if (response.Count > 0) { - OutputParameters.Enqueue(await ReadRowAsync(cancellationToken).ConfigureAwait(false)); + CreateDbValues(); + OutputParameters.Enqueue(GetDbValues(await ReadRowAsync(cancellationToken).ConfigureAwait(false))); } } catch (IOException ex) @@ -1735,9 +1760,9 @@ protected void ClearAll() _fields = null; } - protected virtual DbValue[] ReadRow() + protected virtual object[] ReadRow() { - var row = new DbValue[_fields.Count]; + var row = new object[_fields.Count]; try { for (var i = 0; i < _fields.Count; i++) @@ -1746,11 +1771,11 @@ protected virtual DbValue[] ReadRow() var sqlInd = _database.Xdr.ReadInt32(); if (sqlInd == -1) { - row[i] = new DbValue(this, _fields[i], null); + row[i] = null; } else if (sqlInd == 0) { - row[i] = new DbValue(this, _fields[i], value); + row[i] = value; } else { @@ -1764,9 +1789,11 @@ protected virtual DbValue[] ReadRow() } return row; } - protected virtual async ValueTask ReadRowAsync(CancellationToken cancellationToken = default) + + + protected virtual async ValueTask ReadRowAsync(CancellationToken cancellationToken = default) { - var row = new DbValue[_fields.Count]; + var row = new object[_fields.Count]; try { for (var i = 0; i < _fields.Count; i++) @@ -1775,11 +1802,11 @@ protected virtual async ValueTask ReadRowAsync(CancellationToken canc var sqlInd = await _database.Xdr.ReadInt32Async(cancellationToken).ConfigureAwait(false); if (sqlInd == -1) { - row[i] = new DbValue(this, _fields[i], null); + row[i] = null; } else if (sqlInd == 0) { - row[i] = new DbValue(this, _fields[i], value); + row[i] = value; } else { diff --git a/src/FirebirdSql.Data.FirebirdClient/Client/Managed/Version13/GdsStatement.cs b/src/FirebirdSql.Data.FirebirdClient/Client/Managed/Version13/GdsStatement.cs index 0ea95378..c09d5c42 100644 --- a/src/FirebirdSql.Data.FirebirdClient/Client/Managed/Version13/GdsStatement.cs +++ b/src/FirebirdSql.Data.FirebirdClient/Client/Managed/Version13/GdsStatement.cs @@ -1,4 +1,4 @@ -/* +/* * The contents of this file are subject to the Initial * Developer's Public License Version 1.0 (the "License"); * you may not use this file except in compliance with the @@ -131,9 +131,9 @@ protected override async ValueTask WriteParametersAsync(CancellationToke } } - protected override DbValue[] ReadRow() + protected override object[] ReadRow() { - var row = new DbValue[_fields.Count]; + var row = new object[_fields.Count]; try { if (_fields.Count > 0) @@ -144,12 +144,11 @@ protected override DbValue[] ReadRow() { if (nullBits.Get(i)) { - row[i] = new DbValue(this, _fields[i], null); + row[i] = null; } else { - var value = ReadRawValue(_database.Xdr, _fields[i]); - row[i] = new DbValue(this, _fields[i], value); + row[i] = ReadRawValue(_database.Xdr, _fields[i]); } } } @@ -160,9 +159,10 @@ protected override DbValue[] ReadRow() } return row; } - protected override async ValueTask ReadRowAsync(CancellationToken cancellationToken = default) + + protected override async ValueTask ReadRowAsync(CancellationToken cancellationToken = default) { - var row = new DbValue[_fields.Count]; + var row = new object[_fields.Count]; try { if (_fields.Count > 0) @@ -173,12 +173,11 @@ protected override async ValueTask ReadRowAsync(CancellationToken can { if (nullBits.Get(i)) { - row[i] = new DbValue(this, _fields[i], null); + row[i] = null; } else { - var value = await ReadRawValueAsync(_database.Xdr, _fields[i], cancellationToken).ConfigureAwait(false); - row[i] = new DbValue(this, _fields[i], value); + row[i] = await ReadRawValueAsync(_database.Xdr, _fields[i], cancellationToken).ConfigureAwait(false); } } }