My favorites | Sign in
Project Logo
Project hosting will be READ-ONLY Wednesday at 8am PST due to brief network maintenance.
                
New issue | Search
for
| Advanced search | Search tips
Issue 85: Getting reoptimize requires using prepare_v2
1 person starred this issue and may be notified of changes. Back to list
Status:  Verified
Owner:  rogerbinns
Closed:  Oct 20
Type-Enhancement
Priority-Medium


Sign in to add a comment
 
Reported by rogerbinns, Oct 20, 2009
The original sqlite3 API to prepare statements would result in
SQLITE_SCHEMA being returned from sqlite3_step if the schema changed.  This
is because the underlying vdbe program said things like get the value from
column 3 in table 10 and the numbers could have changed. (SQLite did not do
extensive bookkeeping - generally any change would invalidate all
statements). You would then have to call prepare again on the SQL text and
try stepping again.

This caused enough grief that a new sqlite3_prepare_v2 api was added.  This
version kept a copy of the SQL text and in the sqlite3_step internals would
automatically reprepare the statement on a schema change.  Unfortunately it
messed up error handling.  For example if a statement is prepared using an
unknown collation then SQLITE_ERROR is returned from prepare.  But if a
statement was reprepared (because a collation had been removed) then
SQLITE_SCHEMA would be returned instead.  The effect of this is that
different exception types would be returned depending on whether a
statement was being freshly prepared or was in the statement cache and
sqlite reprepared it.  I tried to convince them of the sillyness but they
were determined to keep this broken behaviour -
http://www.sqlite.org/src/info/8d510499cc

Consequently I reverted to using version 1 of prepare since there was no
benefit to using v2.  In addition to having broken error handling, it also
a kept a copy of the sql which I already have as the key for the statement
cache.

SQLite has optimizations for LIKE and ranges (BETWEEN) but these only
applied when the values are part of the SQL text and could not be done when
using bindings.  3.6.20 has new code that can optimize the query if using
bound values.  It was originally added as a new API -
http://www.sqlite.org/src/vinfo/c48f8ffedc30841aa4994eb925d09c2ee97a864d

However on discussion in the developer's mailing list it became apparent
that everyone should just call the new API before calling the first step. 
Since this was going to be the case, the functionality was folded into the
SQLite core.  But the kicker is that it requires the statement to have been
prepared using v2 of the API.
Comment 1 by rogerbinns, Oct 20, 2009
Since this is the only benefit of prepare_v2 and it requires bindings I am only using
v2 when bindings are present, otherwise v1 is used.  That will hopefully result in
less memory being used (compared to using v2 for all statements) and statements with
bindings are more likely to be reused anyway.

When SQLITE_SCHEMA is returned from v1 or v2 I reprepare. For v1 statements it is no
change.  For v2 it means that a statement that is now an error is reprepared twice -
once inside sqlite_step which will return the bogus SQLITE_SCHEMA error code and then
a second time by APSW to get the correct error code.  Fortunately returning errors
from now invalid statements is not a frequent thing.
Comment 2 by rogerbinns, Oct 20, 2009
Fixed in revision d1d1c97b3a  
Status: Verified
Labels: -Type-Defect Type-Enhancement
Sign in to add a comment

Hosted by Google Code