Skip to content

Commit

Permalink
fix for issue bordoley#40 (helpful exception on invalid use of query …
Browse files Browse the repository at this point in the history
…API)
  • Loading branch information
gentledepp committed Mar 19, 2017
1 parent 7d13ea5 commit 977749a
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 2 deletions.
58 changes: 58 additions & 0 deletions SQLitePCL.pretty.tests/DatabaseConnectionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,9 @@ public void TestWalCheckpoint()
db.Execute("INSERT INTO foo (x) VALUES (1);");
db.Execute("INSERT INTO foo (x) VALUES (2);");

var res = db.Query("Select * from foo limit 1").FirstOrDefault();


int logSize;
int framesCheckPointed;
db.WalCheckPoint("main", WalCheckPointMode.Full, out logSize, out framesCheckPointed);
Expand Down Expand Up @@ -679,6 +682,61 @@ public void TestWalCheckpoint()
raw.sqlite3__vfs__delete(null, tmpFile, 1);
}

[Fact]
public void TestHelpfulExceptionOnDisposedResultset()
{
var tmpFile = GetTempFile();
try
{
using (var db = SQLite3.Open(tmpFile))
{
db.ExecuteAll("CREATE TABLE foo (x int);" +
"INSERT INTO foo (x) VALUES (1);" +
"INSERT INTO foo (x) VALUES (2);");


var rows = db.Query("Select * from foo")
// with the call to "ToArray()" the StatementImpl is being disposed
// as any IResultSetValue call basically uses the StatementImpl, it will throw an ObjectDisposedException
.ToArray();

Assert.Equal(2, rows.Length);

try
{
rows[0][0].ToInt();

Assert.True(false, "ObjectDisposedException expected");
}
catch (ObjectDisposedException ex)
{
var contains =
ex.Message.Contains(
"The statement is already disposed. Calling any member of IResultSetValue after the enumeration has completed is not supported. Either access the members using a projection ('.Select(x => x[0].ToInt())') or during enumeration ('foreach(var row in db.Query(...)){row[0].ToInt()}'). Go to https://github.com/bordoley/SQLitePCL.pretty/blob/master/README.md to learn more.");
Assert.True(contains, "helpful message pointing at correct API usage was missing");
}
try
{
rows[0].Count();

Assert.True(false, "ObjectDisposedException expected");
}
catch (ObjectDisposedException ex)
{
var contains =
ex.Message.Contains(
"The statement is already disposed. Calling any member of IResultSetValue after the enumeration has completed is not supported. Either access the members using a projection ('.Select(x => x[0].ToInt())') or during enumeration ('foreach(var row in db.Query(...)){row[0].ToInt()}'). Go to https://github.com/bordoley/SQLitePCL.pretty/blob/master/README.md to learn more.");
Assert.True(contains, "helpful message pointing at correct API usage was missing");
}
}

}
finally
{
raw.sqlite3__vfs__delete(null, tmpFile, 1);
}
}

[Fact]
public void TestTableColumnMetadata()
{
Expand Down
23 changes: 21 additions & 2 deletions SQLitePCL.pretty/Implementation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ public bool IsBusy
}
}

internal bool Disposed
{
get { return disposed; }
}

public void ClearBindings()
{
if (disposed) { throw new ObjectDisposedException(this.GetType().FullName); }
Expand Down Expand Up @@ -451,6 +456,8 @@ IEnumerator IEnumerable.GetEnumerator() =>

internal sealed class ResultSetImpl : IReadOnlyList<IResultSetValue>
{
private const string Helpmessage =
"The statement is already disposed. Calling any member of IResultSetValue after the enumeration has completed is not supported. Either access the members using a projection ('.Select(x => x[0].ToInt())') or during enumeration ('foreach(var row in db.Query(...)){row[0].ToInt()}'). Go to https://github.com/bordoley/SQLitePCL.pretty/blob/master/README.md to learn more.";
private readonly StatementImpl stmt;

internal ResultSetImpl(StatementImpl stmt)
Expand All @@ -459,7 +466,19 @@ internal ResultSetImpl(StatementImpl stmt)
}

public int Count =>
raw.sqlite3_data_count(stmt.sqlite3_stmt);
raw.sqlite3_data_count(Stmt.sqlite3_stmt);

private StatementImpl Stmt
{
get
{
if (stmt.Disposed)
{
throw new ObjectDisposedException(Helpmessage);
}
return stmt;
}
}

public IEnumerator<IResultSetValue> GetEnumerator()
{
Expand All @@ -481,7 +500,7 @@ public IResultSetValue this[int index]
throw new ArgumentOutOfRangeException();
}

return stmt.ResultSetValueAt(index);
return Stmt.ResultSetValueAt(index);
}
}
}
Expand Down

0 comments on commit 977749a

Please sign in to comment.