Skip to content

Commit 327407f

Browse files
committed
Proper handling of status of fetch on embedded to prevent fetching "zero" buffers. (#998)
1 parent 540294b commit 327407f

File tree

5 files changed

+109
-48
lines changed

5 files changed

+109
-48
lines changed

Provider/src/FirebirdSql.Data.FirebirdClient.Tests/FbDecFloat16SupportTests.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,19 @@ public async Task PassesValueNullCorrectly()
111111
}
112112
}
113113

114+
[Test]
115+
public async Task SelectEmptyResultSet()
116+
{
117+
await using (var cmd = Connection.CreateCommand())
118+
{
119+
cmd.CommandText = "select cast(null as decfloat(16)) from rdb$database where 0=1";
120+
await using (var reader = await cmd.ExecuteReaderAsync())
121+
{
122+
Assert.DoesNotThrowAsync(reader.ReadAsync);
123+
}
124+
}
125+
}
126+
114127
[Test]
115128
public async Task SimpleSelectSchemaTableTest()
116129
{

Provider/src/FirebirdSql.Data.FirebirdClient.Tests/FbDecFloat34SupportTests.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,19 @@ public async Task PassesValueNullCorrectly()
111111
}
112112
}
113113

114+
[Test]
115+
public async Task SelectEmptyResultSet()
116+
{
117+
await using (var cmd = Connection.CreateCommand())
118+
{
119+
cmd.CommandText = "select cast(null as decfloat(34)) from rdb$database where 0=1";
120+
await using (var reader = await cmd.ExecuteReaderAsync())
121+
{
122+
Assert.DoesNotThrowAsync(reader.ReadAsync);
123+
}
124+
}
125+
}
126+
114127
[Test]
115128
public async Task SimpleSelectSchemaTableTest()
116129
{

Provider/src/FirebirdSql.Data.FirebirdClient.Tests/FbInt128SupportTests.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,19 @@ public async Task PassesValueNullCorrectly()
9999
}
100100
}
101101

102+
[Test]
103+
public async Task SelectEmptyResultSet()
104+
{
105+
await using (var cmd = Connection.CreateCommand())
106+
{
107+
cmd.CommandText = "select cast(null as int128) from rdb$database where 0=1";
108+
await using (var reader = await cmd.ExecuteReaderAsync())
109+
{
110+
Assert.DoesNotThrowAsync(reader.ReadAsync);
111+
}
112+
}
113+
}
114+
102115
[Test]
103116
public async Task SimpleSelectSchemaTableTest()
104117
{

Provider/src/FirebirdSql.Data.FirebirdClient.Tests/FbTimeZonesSupportTests.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,24 @@ public async Task PassesZonedTimeNullCorrectly(bool isExtended)
178178
}
179179
}
180180

181+
[TestCase(true)]
182+
[TestCase(false)]
183+
public async Task SelectEmptyResultSet(bool isExtended)
184+
{
185+
if (isExtended)
186+
{
187+
await SetExtended();
188+
}
189+
await using (var cmd = Connection.CreateCommand())
190+
{
191+
cmd.CommandText = "select cast(null as time with time zone) from rdb$database where 0=1";
192+
await using (var reader = await cmd.ExecuteReaderAsync())
193+
{
194+
Assert.DoesNotThrowAsync(reader.ReadAsync);
195+
}
196+
}
197+
}
198+
181199
[Test]
182200
public async Task SimpleSelectSchemaTableTest()
183201
{

Provider/src/FirebirdSql.Data.FirebirdClient/Client/Native/FesStatement.cs

Lines changed: 52 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -477,20 +477,31 @@ public override DbValue[] Fetch()
477477
return null;
478478
}
479479

480-
DbValue[] row = null;
481-
if (!_allRowsFetched)
480+
if (_allRowsFetched)
482481
{
483-
_fields.ResetValues();
482+
return null;
483+
}
484484

485-
if (_fetchSqlDa == IntPtr.Zero)
486-
{
487-
_fetchSqlDa = XsqldaMarshaler.MarshalManagedToNative(_db.Charset, _fields);
488-
}
485+
_fields.ResetValues();
489486

490-
ClearStatusVector();
487+
if (_fetchSqlDa == IntPtr.Zero)
488+
{
489+
_fetchSqlDa = XsqldaMarshaler.MarshalManagedToNative(_db.Charset, _fields);
490+
}
491+
492+
ClearStatusVector();
493+
494+
var status = _db.FbClient.isc_dsql_fetch(_statusVector, ref _handle, IscCodes.SQLDA_VERSION1, _fetchSqlDa);
495+
if (status == new IntPtr(100))
496+
{
497+
_allRowsFetched = true;
491498

492-
var status = _db.FbClient.isc_dsql_fetch(_statusVector, ref _handle, IscCodes.SQLDA_VERSION1, _fetchSqlDa);
499+
XsqldaMarshaler.CleanUpNativeData(ref _fetchSqlDa);
493500

501+
return null;
502+
}
503+
else
504+
{
494505
var rowDesc = XsqldaMarshaler.MarshalNativeToManaged(_db.Charset, _fetchSqlDa, true);
495506

496507
if (_fields.Count == rowDesc.Count)
@@ -508,24 +519,15 @@ public override DbValue[] Fetch()
508519

509520
_db.ProcessStatusVector(_statusVector);
510521

511-
if (status == new IntPtr(100))
522+
var row = new DbValue[_fields.ActualCount];
523+
for (var i = 0; i < row.Length; i++)
512524
{
513-
_allRowsFetched = true;
514-
515-
XsqldaMarshaler.CleanUpNativeData(ref _fetchSqlDa);
516-
}
517-
else
518-
{
519-
row = new DbValue[_fields.ActualCount];
520-
for (var i = 0; i < row.Length; i++)
521-
{
522-
var d = _fields[i];
523-
var value = d.DbValue.GetValue();
524-
row[i] = new DbValue(this, d, value);
525-
}
525+
var d = _fields[i];
526+
var value = d.DbValue.GetValue();
527+
row[i] = new DbValue(this, d, value);
526528
}
529+
return row;
527530
}
528-
return row;
529531
}
530532
public override async ValueTask<DbValue[]> FetchAsync(CancellationToken cancellationToken = default)
531533
{
@@ -545,20 +547,31 @@ public override async ValueTask<DbValue[]> FetchAsync(CancellationToken cancella
545547
return null;
546548
}
547549

548-
DbValue[] row = null;
549-
if (!_allRowsFetched)
550+
if (_allRowsFetched)
550551
{
551-
_fields.ResetValues();
552+
return null;
553+
}
552554

553-
if (_fetchSqlDa == IntPtr.Zero)
554-
{
555-
_fetchSqlDa = XsqldaMarshaler.MarshalManagedToNative(_db.Charset, _fields);
556-
}
555+
_fields.ResetValues();
557556

558-
ClearStatusVector();
557+
if (_fetchSqlDa == IntPtr.Zero)
558+
{
559+
_fetchSqlDa = XsqldaMarshaler.MarshalManagedToNative(_db.Charset, _fields);
560+
}
561+
562+
ClearStatusVector();
563+
564+
var status = _db.FbClient.isc_dsql_fetch(_statusVector, ref _handle, IscCodes.SQLDA_VERSION1, _fetchSqlDa);
565+
if (status == new IntPtr(100))
566+
{
567+
_allRowsFetched = true;
559568

560-
var status = _db.FbClient.isc_dsql_fetch(_statusVector, ref _handle, IscCodes.SQLDA_VERSION1, _fetchSqlDa);
569+
XsqldaMarshaler.CleanUpNativeData(ref _fetchSqlDa);
561570

571+
return null;
572+
}
573+
else
574+
{
562575
var rowDesc = XsqldaMarshaler.MarshalNativeToManaged(_db.Charset, _fetchSqlDa, true);
563576

564577
if (_fields.Count == rowDesc.Count)
@@ -576,24 +589,15 @@ public override async ValueTask<DbValue[]> FetchAsync(CancellationToken cancella
576589

577590
_db.ProcessStatusVector(_statusVector);
578591

579-
if (status == new IntPtr(100))
592+
var row = new DbValue[_fields.ActualCount];
593+
for (var i = 0; i < row.Length; i++)
580594
{
581-
_allRowsFetched = true;
582-
583-
XsqldaMarshaler.CleanUpNativeData(ref _fetchSqlDa);
584-
}
585-
else
586-
{
587-
row = new DbValue[_fields.ActualCount];
588-
for (var i = 0; i < row.Length; i++)
589-
{
590-
var d = _fields[i];
591-
var value = await d.DbValue.GetValueAsync(cancellationToken).ConfigureAwait(false);
592-
row[i] = new DbValue(this, d, value);
593-
}
595+
var d = _fields[i];
596+
var value = await d.DbValue.GetValueAsync(cancellationToken).ConfigureAwait(false);
597+
row[i] = new DbValue(this, d, value);
594598
}
599+
return row;
595600
}
596-
return row;
597601
}
598602

599603
public override void Describe()

0 commit comments

Comments
 (0)