Thanks, Simon,

perhaps I did not formulate may question clearly enough. The class of course
works as you wrote, the only problem relates to the error handling.

If you are interested, the C# wrapper (original code) is  here
<https://raw.githubusercontent.com/OpenDataSpace/System.Data.SQLite/master/System.Data.SQLite/SQLite3.cs>
 
. (UnsafeNativeMethods class contains a collection of function pointers to
sqlite3.dll.)

This is the part of the code I want to discuss (a shortened version):

<code>
    internal override bool Step(SQLiteStatement stmt)
    {
      Random rnd = new Random();
      uint starttick = (uint)Environment.TickCount;
      uint timeout = (uint)(stmt._command._commandTimeout * 1000);

      while (true)
      {
        SQLiteErrorCode n =
UnsafeNativeMethods.sqlite3_step(stmt._sqlite_stmt);
        if (n == SQLiteErrorCode.Row) return true;
        if (n == SQLiteErrorCode.Done) return false;

        if (n != SQLiteErrorCode.Ok)   //*) 
        {
          SQLiteErrorCode r = Reset(stmt);
          if (r == SQLiteErrorCode.Ok)
            throw new SQLiteException(n, GetLastError());

          // Only Locked/Busy err code can pass here
          if ((uint)Environment.TickCount - starttick > timeout)
              throw new SQLiteException(r, GetLastError());
          System.Threading.Thread.Sleep(rnd.Next(1, 150));
        }
      }
    }

    internal override SQLiteErrorCode Reset(SQLiteStatement stmt)
    {
      SQLiteErrorCode n =
UnsafeNativeMethods.sqlite3_reset(stmt._sqlite_stmt);
      if (n == SQLiteErrorCode.Locked || n == SQLiteErrorCode.Busy || n ==
SQLiteErrorCode.Ok)
        return n;
      throw new SQLiteException(n, GetLastError());
    }
</code>

*) STRANGE:
1) SQLITE_OK should not happen. (Official documentation allows /ANY/ result
code. I hope this not true.)
2) If it happens, then this looks dangerous. 

I don't like a lot of things about the C# wrapper (heavy overhead,
SQL_SCHEMA dealing, timeouts...). But those points are not crucial. What I
ask is following:

a) If sqlite3_step() returns error code different from 100/101, should we
call sqlite3_reset()? This looks like a bug to me. (Imagine we are reading a
table.)

b) If we get Locked/Busy errors, is it safe and reasonable to retry
sqlite3_step? Note that if we solve this way some multi-access conflicts,
then this is a welcome feature.

Meanwhile I collected more info about the problem.

First, a reduced version of the sqlite3_step() official documentation that
applies to these conditions:
- Sqlite 3.7.15, SQLITE_OMIT_AUTORESET was not defined
- The statement was prepared using sqlite3_prepare_v2()
/
sqlite3_step returns SQLITE_BUSY, SQLITE_DONE, SQLITE_ROW, SQLITE_ERROR,
SQLITE_MISUSE, or any other result code
SQLITE_ROW/SQLITE_DONE... (description omitted)
SQLITE_BUSY means a failure to acquire a DB lock. If the statement is a
COMMIT or occurs outside of an explicit transaction, then you can retry the
statement. Otherwise you should rollback.
SQLITE_ERROR means a run-time error. sqlite3_step() should not be called,
sqlite3_errmsg() provides additional info.
SQLITE_MISUSE means that this routine was called inappropriately, such as on
a finalized statement. 
If sqlite3_step() returns anything other than SQLITE_ROW, then the next call
to sqlite3_step() automatically calls sqlite3_reset().
/

Another SQLite document  says <http://www.sqlite.org/unlock_notify.html>  
"/SQLITE_LOCKED error may only occur on the first call to sqlite3_step()/".
And  Mr. Hipp
<http://sqlite.1065341.n5.nabble.com/Questions-about-VDBE-deadlocks-and-SQLITE-BUSY-tp1025p1026.html>
  
seems to have confirmed the same for SQLITE_BUSY. (Although 10 years ago)

Dan Kennedy  says
<http://sqlite.1065341.n5.nabble.com/shared-cache-and-SQLITE-MISUSE-on-sqlite3-step-tp47214p47232.html>
  
"/After SQLITE_BUSY is returned, you can call sqlite3_step() again
immediately/". (Note that this is not the same as the official documentation
says.)

Knowing now above info, I don't see the C# wrapper code that bad as
yesterday, though I am still far from being sure that it is 100% ok.




--
View this message in context: 
http://sqlite.1065341.n5.nabble.com/sqlite3-step-and-SQLITE-LOCKED-BUSY-tp77690p77707.html
Sent from the SQLite mailing list archive at Nabble.com.
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to