[plt-scheme] sqlite:finalize statement throws unexpectedly
On Mon, Oct 12, 2009 at 3:19 PM, David Storrs <david.storrs at gmail.com> wrote:
> On Mon, Oct 12, 2009 at 5:07 PM, Jay McCarthy <jay.mccarthy at gmail.com> wrote:
>> The contract for finalize specifies #2.
>
> No, I got that. I was just surprised. It would be nice if the
> contract was (-> statement? void?) instead of (-> open-statement?
> void?).
It can cause a core dump if you finalize twice. This contract avoids
that problem without hiding the error from the programmer. There may
be other ways to avoid it in the implementation... but I prefer
exposing errors like this to programmer... just my philosophy I guess.
>
>> Re: #3 --- SQLite's sqlite3_finalize returns a status. I uniformly
>> turn these status values into exns. My attitude is that the C API
>> allows you to forget to handle errors but the Scheme API should never
>> fail without warning.
>
> Agreed, absolutely. My thought was only that, in practice, the author
> *must* have already dealt with this error, because an exception would
> have been thrown when he tried to execute the statement in the first
> place. The finalize is re-raising an already-dealt-with error. For
> example:
>
> ;; Assume the users table has a UNIQUE constraint on username
> (let ((stmt (prepare db "insert into users (username, password) values
> (?, ?)")))
> (with-handlers ((sqlite:exn? (finalize stmt) (void)))
> (run stmt 'Joe' 'pass1') ; executes fine, row is inserted
> (run stmt 'Joe' 'pass1') ; => exn:sqlite. This user already exists
> )
>
> This is a simplified version of what I was just debugging. It took me
> a while to realize that the with-handlers was working fine; it's
> simply that the handler function was re-raising the error, when I
> expected it to ensure that the statement was finalized and then eat
> the exception.
>
> The way the sqlite module is currently written, one needs to wrap a
> with-handlers around every call to finalize, just in case the
> statement had problems when it was run. That seems redundant.
I agree that it is silly that SQLite errors in this situation. I am
worried that removing the possibility of error on finalize will hide
real errors. I am not an expert on its implementation, so I trust the
API they've developed. FWIW, you can define your own finalize* that is
implicitly in a with-handlers.
Jay
>
> --Dks
>
--
Jay McCarthy <jay at cs.byu.edu>
Assistant Professor / Brigham Young University
http://teammccarthy.org/jay
"The glory of God is Intelligence" - D&C 93