Today we made a couple of minor changes in the code generation to take care of some lingering issues.
The first is that when you did a
throw inside a
catch to basically rethrow the error, you would lose
the error code if something had succeeded within the catch handler.
The old codegen looked something like this:
The problem being that while the
printf above is fine and well, if you did any SQL operation then
_rc_ would be
clobbered and you'd end up throwing an unrelated error code.
cql_best_error would at least make sure it was
a failure code (
SQLITE_ERROR) but the original error code was lost.
The new code looks like this:
So now if there are db operations, the original return code is still preserved. Note: you still lose
SQLite doesn't know that cleanup logic is running.
This brings us to the second new thing: general purpose error traces.
Error checking of result codes happens very consistently in CQL output. The usual pattern looks something like this:
or if it's inside a try block a little different... very little actually
Basically if the local
_rc_ doersn't match the necessary condition we
goto the appropriate error label... either the relevant
catch block or else the procedure's cleanup code.
We generalize this a bit now so that it looks like this:
Now the default implementation of
cql_error_trace() is in
cqlrt.h which you can and should customize. I'll be writing more
about that later but suffice to say you're supposed to replace
cqlrt.c with suitable runtime helpers for your environment
So for instance, your
cqlrt.h could look like this:
So then when you need to debug problems involving lots of error recovery you can watch the entire chain of events easily.
Note that there are some useful variables there:
In any procedure
_db_ is the current database and
_rc_ is the most recent return code from SQLite.
of course come from the preprocessor. and
_PROC_ (one underscore) is now generated by the compiler. Every procedure's
body now begins with:
So by defining your own cql_error_trace macro you can cause whatever logging you need to happen. Note this can be very expensive indeed because this happens a lot and even the string literals needed are a significant cost. So generally this should be off for production builds and enabled as needed for debug builds.
The default implementation is just an empty block
But the hook is enough to light up whatever logging you might need, and you can use
sqlite3_errmsg() before that message is gone.