-----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