From f323625738511e9828b90e767d2e39f630ca9591 Mon Sep 17 00:00:00 2001 From: Dimitri Fontaine Date: Mon, 22 Dec 2014 18:32:11 +0100 Subject: [PATCH] Improve MS SQL error handling when reading from source. In particular, protect the sysdb-data-to-lisp routine, that calls into CFFI and character decodings, with a restart-case allowing the calling code to just ignore errors on a particular column by skipping it and using nil instead (or something else if needed). --- src/monkey/mssql.lisp | 17 +++++++++++++---- src/sources/mssql.lisp | 8 +++++++- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/monkey/mssql.lisp b/src/monkey/mssql.lisp index d36057a..638b2d4 100644 --- a/src/monkey/mssql.lisp +++ b/src/monkey/mssql.lisp @@ -113,10 +113,19 @@ :until (= rtc +no-more-rows+) :do (let ((row (make-array (%dbnumcols %dbproc)))) (loop :for i :from 1 :to (%dbnumcols %dbproc) - :for value := (sysdb-data-to-lisp %dbproc - (%dbdata %dbproc i) - (%dbcoltype %dbproc i) - (%dbdatlen %dbproc i)) + :for value + := (restart-case + (sysdb-data-to-lisp %dbproc + (%dbdata %dbproc i) + (%dbcoltype %dbproc i) + (%dbdatlen %dbproc i)) + (use-nil () + :report "skip this column's value and use nil instead." + nil) + (use-empty-string () + :report "skip this column's value and use empty-string instead." + "") + (use-value (value) value)) :do (setf (aref row (- i 1)) value)) (funcall row-fn row)))) diff --git a/src/sources/mssql.lisp b/src/sources/mssql.lisp index 611102a..68c3071 100644 --- a/src/sources/mssql.lisp +++ b/src/sources/mssql.lisp @@ -66,7 +66,13 @@ (funcall process-row-fn row)))) (log-message :debug "~a" sql) (handler-case - (mssql::map-query-results sql :row-fn row-fn :connection *mssql-db*) + (handler-bind + ((condition + #'(lambda (c) + (log-message :error "~a" c) + (pgstate-incf *state* (target mssql) :errs 1) + (invoke-restart 'mssql::use-nil)))) + (mssql::map-query-results sql :row-fn row-fn :connection *mssql-db*)) (condition (e) (progn (log-message :error "~a" e)