Hello! Ricardo Wurmus <rek...@elephly.net> skribis:
>> diff --git a/src/cuirass/database.scm b/src/cuirass/database.scm >> index 91133c2..9c7e69a 100644 >> --- a/src/cuirass/database.scm >> +++ b/src/cuirass/database.scm >> @@ -181,15 +181,30 @@ string." >> ((char=? char #\') (loop (cons* char char chars))) >> (else (loop (cons char chars))))))) >> >> +;; Extended error codes (see <sqlite3.h>). >> +;; XXX: This should be defined by (sqlite3). >> +(define SQLITE_CONSTRAINT 19) >> +(define SQLITE_CONSTRAINT_PRIMARYKEY >> + (logior SQLITE_CONSTRAINT (ash 6 8))) >> + >> (define (db-add-build db build) >> - "Store BUILD in database DB." >> - (sqlite-exec db "\ >> + "Store BUILD in database DB. This is idempotent." >> + (catch 'sqlite-error >> + (lambda () >> + (sqlite-exec db "\ >> INSERT INTO Builds (derivation, evaluation, log, output)\ >> VALUES ('~A', '~A', '~A', '~A');" >> - (assq-ref build #:derivation) >> - (assq-ref build #:eval-id) >> - (assq-ref build #:log) >> - (assq-ref build #:output)) >> + (assq-ref build #:derivation) >> + (assq-ref build #:eval-id) >> + (assq-ref build #:log) >> + (assq-ref build #:output))) >> + (lambda (key who code . rest) >> + ;; If we get a primary-key-constraint-violated error, that means we >> have >> + ;; already inserted the same (derivation,eval-id,log) tuple, which we >> + ;; can safely ignore. >> + (unless (= code SQLITE_CONSTRAINT_PRIMARYKEY) >> + (apply throw key who code rest)))) >> + > > Unfortunately, re-throwing the error doesn’t print any meaningful error > message. To get the error message that I showed above I caught any > sqlite errors and re-threw the exception only after printing the > arguments to sqlite-exec: > > (format (current-error-port) "Database error with ~a and ~a~%" msg args) > > I think it would be good to include a line like this right after > “(unless (= code SQLITE_CONSTRAINT_PRIMARYKEY)”. Good idea. Pushed with a test case as 72f2b6b77cc4e3d7629bdf34e6daee05398b8de1. Thanks, Ludo’.