-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Anil Madhavapeddy wrote:
> The custom functions are registered against the database handle, but  
> when prepared statements are garbage collected (and hence call  
> sqlite3_finalize() on the statement handle), the custom functions  
> appear to disappear also.

That is certainly not how it works under the hood.  The functions are
stored against the database handle which you can see in the SQLite
source code.

> Any subsequent use of that function in
> other prepared statements result in a MISUSE error.

I recommend you run the whole thing in Valgrind.  My best guess is that
you are finalizing the statements multiple times or perhaps also closing
the database handle.  Or perhaps the GC is freeing stuff it shouldn't.
Also compile the SQLite code with -DSQLITE_DEBUG

In my Python wrapper (which uses reference counting for GC) the
statements are wrapped by a 'cursor' object.  The existence of a cursor
increments the reference count on the database handle which ensures all
cursors must be GC before the database is.

> The source to the bindings are up at 
> http://github.com/avsm/ocaml-sqlite3-agg/ 
>   with a testcase in tests/test_agg.ml

Looking at the C code, it seems like error codes aren't tracked very
well and instead only the strings are looked at for return to the user.
 The error codes are far more important and the error string could have
corresponded to an earlier error.  I'd recommend you change the various
raise routines to include the error code, especially getting it from the
routine that called raise in the first place.

The error handling around functions is also all shot.  (I am assuming
that caml_raise_with_string doesn't do a longjmp.)  You can register the
same function name with different numbers of arguments (eg "foo" with 2
args is distinct from "foo" with 3 args).  You will get errors
unregistering or registering if there oustanding executing statements
(ie finalize uncalled) using that function.

Using caml_sqlite3_delete_function (at the bottom of sqlite3_stubs.c) as
an example, I see at least the following problems:

- - check_db should return on error (unless caml_raise does longjmp)
- - Doesn't specify/keep track of nargs and so unregisters version of
function with any number of args
- - If rc is not SQLITE_OK then whatever value rc has is discarded
- - The if(rc!=SQLITE_OK) bit should be on a different line than the raise
bit which means that can run coverage testing and will be able to see
that both paths have been taken
- - unregister_user_function is called no matter what which would cause
memory corruption if for example the function was in use

If caml_raise_* does use longjmp (I don't believe it does, but if it
does then it changes control flow from what is written to effectively
jumping out of executing functions) then things are different.

If not then I see a whole bunch of problems, especially very sloppy
error handling and a lack of testing.  I strongly recommend the testing
also measure code coverage.  Just the process of testing calls
succeeding and failing will uncover numerous issues.

As a second issue, you need to give up on the idea of being able to free
functions except when the database is closed.  The reason is that you
cannot reliably tell when a function is no longer in use.  For example
it can be replaced by one with the same name and same number of args,
but what about case?  Then throw in some unicode to make life more
interesting.  Unless you duplicate the SQLite code, you can never be
sure.  The api for collations and modules did add a "destructor"
callback which makes life far easier.  I have asked for the same for
functions on the mailing list and ticket without an answer:

  http://www.sqlite.org/cvstrac/tktview?tn=3141

Roger
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEARECAAYFAkmjITwACgkQmOOfHg372QT6oACgmR9X8h7ad87XQnlvEM2XYmmM
vhkAn2/6uDJfUNb/9ikccvngBDcNhnHd
=SeK/
-----END PGP SIGNATURE-----
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to