Skip to content

Commit

Permalink
Fixed ToRecordSet issue when query returns no records (should be empt…
Browse files Browse the repository at this point in the history
…y RecordSet instead of null)
  • Loading branch information
VitaliyMF committed Jan 8, 2017
1 parent f58f92c commit 49364a3
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 31 deletions.
8 changes: 4 additions & 4 deletions src/NReco.Data.Tests/DbCommandBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public void BuildCommands() {

// SELECT TEST with prefixes and expressions
IDbCommand cmd = cmdGenerator.GetSelectCommand( q );
string masterSQL = "SELECT name,t.age,(t.age*12) as age_months FROM test t WHERE (((name LIKE @p0) Or (NOT(age>=@p1))) And ((weight=@p2) And (type IN (@p3,@p4)))) Or ((name<>@p5) And (type IS NOT NULL))";
string masterSQL = "SELECT name,t.age,t.age*12 as age_months FROM test t WHERE (((name LIKE @p0) Or (NOT(age>=@p1))) And ((weight=@p2) And (type IN (@p3,@p4)))) Or ((name<>@p5) And (type IS NOT NULL))";

Assert.Equal( masterSQL, cmd.CommandText.Trim() );

Expand Down Expand Up @@ -161,7 +161,7 @@ public void BuildCommands() {
// ------- escape identifiers asserts --------
dbFactory.IdentifierFormat = "[{0}]";
Assert.Equal(
"SELECT [name],[t].[age],(t.age*12) as [age_months] FROM [test] [t] WHERE ((([name] LIKE @p0) Or (NOT([age]>=@p1))) And (([weight]=@p2) And ([type] IN (@p3,@p4)))) Or (([name]<>@p5) And ([type] IS NOT NULL))",
"SELECT [name],[t].[age],t.age*12 as [age_months] FROM [test] [t] WHERE ((([name] LIKE @p0) Or (NOT([age]>=@p1))) And (([weight]=@p2) And ([type] IN (@p3,@p4)))) Or (([name]<>@p5) And ([type] IS NOT NULL))",
cmdGenerator.GetSelectCommand( q ).CommandText.Trim() );
Assert.Equal(
"INSERT INTO [test] ([name],[age],[weight],[type]) VALUES (@p0,@p1,@p2,@p3)",
Expand Down Expand Up @@ -194,13 +194,13 @@ public void DataView() {

// simple count query test
Assert.Equal(
"SELECT (count(p.id)) as cnt FROM persons p LEFT JOIN countries c ON (c.id=p.country_id)",
"SELECT count(p.id) as cnt FROM persons p LEFT JOIN countries c ON (c.id=p.country_id)",
cmdGenerator.GetSelectCommand( new Query("persons_view").Select(QField.Count) ).CommandText.Trim()
);

// field mapping in select columns
Assert.Equal(
"SELECT (p.id) as id,name,(CASE WHEN DATEDIFF(dd, p.added_date, NOW() )>30 THEN 1 ELSE 0 END) as expired FROM persons p LEFT JOIN countries c ON (c.id=p.country_id)",
"SELECT p.id as id,name,CASE WHEN DATEDIFF(dd, p.added_date, NOW() )>30 THEN 1 ELSE 0 END as expired FROM persons p LEFT JOIN countries c ON (c.id=p.country_id)",
cmdGenerator.GetSelectCommand( new Query("persons_view")
.Select("id", "name", "expired") ).CommandText.Trim()
);
Expand Down
11 changes: 9 additions & 2 deletions src/NReco.Data/DataHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,21 @@ internal static QNode MapQValue(QNode qNode, Func<IQueryValue,IQueryValue> mapFu
return qNode;
}

internal static void ExecuteReader(IDbCommand cmd, CommandBehavior cmdBehaviour, int recordOffset, int recordCount, Action<IDataReader> recordHandler) {
internal static void ExecuteReader<T>(
IDbCommand cmd, CommandBehavior cmdBehaviour,
int recordOffset, int recordCount,
IDataReaderResult<T> result) {

EnsureConnectionOpen(cmd.Connection, () => {
try {
using (var rdr = cmd.ExecuteReader(cmdBehaviour)) {
int index = 0;
int processed = 0;
result.Init(rdr);
while (rdr.Read() && processed < recordCount) {
if (index>=recordOffset) {
processed++;
recordHandler(rdr);
result.Read(rdr);
}
index++;
}
Expand Down Expand Up @@ -109,6 +114,8 @@ internal static async Task<T> ExecuteReaderAsync<T>(

int index = 0;
int processed = 0;

result.Init(rdr);
while ( (await rdr.ReadAsync(cancel)) && processed < recordCount) {
if (index>=recordOffset) {
processed++;
Expand Down
12 changes: 10 additions & 2 deletions src/NReco.Data/Internal/DataReaderResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace NReco.Data {

internal interface IDataReaderResult<T> {
T Result { get; }
void Init(IDataReader rdr);
void Read(IDataReader rdr);
}

Expand All @@ -37,6 +38,8 @@ internal SingleDataReaderResult(Func<IDataReader,T> convert) {
Result = default(T);
}

public void Init(IDataReader rdr) { }

public void Read(IDataReader rdr) {
Result = Convert(rdr);
}
Expand All @@ -52,6 +55,8 @@ internal ListDataReaderResult(Func<IDataReader,T> convert) {
Result = new List<T>();
}

public void Init(IDataReader rdr) { }

public void Read(IDataReader rdr) {
Result.Add( Convert(rdr) );
}
Expand All @@ -64,10 +69,13 @@ internal RecordSetDataReaderResult() {
Result = null;
}

public void Read(IDataReader rdr) {
public void Init(IDataReader rdr) {
if (Result==null) {
Result = DataHelper.GetRecordSetByReader(rdr);
}
}
}

public void Read(IDataReader rdr) {
var rowValues = new object[rdr.FieldCount];
rdr.GetValues(rowValues);
Result.Add(rowValues).AcceptChanges();
Expand Down
36 changes: 13 additions & 23 deletions src/NReco.Data/Internal/DbDataAdapter.SelectQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,11 @@ int DataReaderRecordOffset {
/// </summary>
/// <returns>depending on T, single value or all fields values from the first record</returns>
public T Single<T>() {
T result = default(T);
var res = new SingleDataReaderResult<T>( Read<T> );
using (var selectCmd = GetSelectCmd()) {
DataHelper.ExecuteReader(selectCmd, CommandBehavior.SingleRow, DataReaderRecordOffset, 1,
(rdr) => {
result = Read<T>(rdr);
} );
DataHelper.ExecuteReader(selectCmd, CommandBehavior.SingleRow, DataReaderRecordOffset, 1, res);
}
return result;
return res.Result;
}

/// <summary>
Expand Down Expand Up @@ -90,14 +87,11 @@ public Task<T> SingleAsync<T>(CancellationToken cancel) {
/// </summary>
/// <returns>dictionary with field values or null if query returns zero records.</returns>
public Dictionary<string,object> ToDictionary() {
Dictionary<string,object> result = null;
var res = new SingleDataReaderResult<Dictionary<string,object>>( ReadDictionary );
using (var selectCmd = GetSelectCmd()) {
DataHelper.ExecuteReader(selectCmd, CommandBehavior.SingleRow, DataReaderRecordOffset, 1,
(rdr) => {
result = ReadDictionary(rdr);
} );
DataHelper.ExecuteReader(selectCmd, CommandBehavior.SingleRow, DataReaderRecordOffset, 1, res);
}
return result;
return res.Result;
}

/// <summary>
Expand Down Expand Up @@ -150,14 +144,11 @@ public Task<List<Dictionary<string,object>>> ToDictionaryListAsync(CancellationT
/// </summary>
/// <returns>list with query results</returns>
public List<T> ToList<T>() {
var result = new List<T>();
var res = new ListDataReaderResult<T>( Read<T> );
using (var selectCmd = GetSelectCmd()) {
DataHelper.ExecuteReader(selectCmd, CommandBehavior.Default, DataReaderRecordOffset, RecordCount,
(rdr) => {
result.Add( Read<T>(rdr) );
} );
DataHelper.ExecuteReader(selectCmd, CommandBehavior.Default, DataReaderRecordOffset, RecordCount, res);
}
return result;
return res.Result;
}

/// <summary>
Expand All @@ -182,12 +173,11 @@ public Task<List<T>> ToListAsync<T>(CancellationToken cancel) {
/// Returns all query results as <see cref="RecordSet"/>.
/// </summary>
public RecordSet ToRecordSet() {
var result = new RecordSetDataReaderResult();
var res = new RecordSetDataReaderResult();
using (var selectCmd = GetSelectCmd()) {
DataHelper.ExecuteReader(selectCmd, CommandBehavior.Default, DataReaderRecordOffset, RecordCount,
result.Read );
DataHelper.ExecuteReader(selectCmd, CommandBehavior.Default, DataReaderRecordOffset, RecordCount, res);
}
return result.Result;
return res.Result;
}

/// <summary>
Expand Down Expand Up @@ -222,7 +212,7 @@ private Dictionary<string,object> ReadDictionary(IDataReader rdr) {
private T Read<T>(IDataReader rdr) {
var typeCode = Type.GetTypeCode(typeof(T));
// handle primitive single-value result
if (typeCode!=TypeCode.Object) {
if (typeCode!=TypeCode.Object || typeof(T)==typeof(object) ) {
if (rdr.FieldCount==1) {
return ChangeType<T>( rdr[0], typeCode);
} else if (rdr.FieldCount>1) {
Expand Down

0 comments on commit 49364a3

Please sign in to comment.