Bug: NO-NEXT-METHOD error on read-sql-value (SBCL)

Mariano Montone <[email protected]> Tue, 10 Mar 2015 14:52:57 -0300
Newsgroups gmane.lisp.clsql.general
Message-ID <[email protected]>
Hi.

When trying to use latest version from SBCL, read-sql-value signals a
NO-NEXT-METHOD error for the :around read-sql-value definition. It
should work, as I understand the code, and maybe this is a bug in SBCL,
but I'm posting FYI. Dosn't work on latest SBCL or older versions.

This is the conflicting code:


596 (defmethod read-sql-value :around
597     (val type database db-type
598      ;; never eval while reading values, always read base 10
599      &aux *read-eval* (*read-base* #10r10))
600   (declare (ignore db-type))
601   (cond
602     ;; null value or type
603     ((or (equalp "nil" val) (eql 'null val)) nil)
604    
605     ;; no specified type or already the right type
606     ((or (null type)
607          (ignore-errors (typep val type)))
608      val)
609
610     ;; actually convert
611     (t
612      (let ((res (handler-bind
613                     ;; all errors should be converted to
sql-value-conversion-error
614                     ((error (lambda (c)
615                               (when *debugger-hook*
616                                 (invoke-debugger c))
617                               (unless (typep c
'sql-value-conversion-error)
618                                 (error-converting-value val type
database)))))
619                   (call-next-method))))
620        ;; if we didnt get the right type after converting, we should
probably
621        ;; error right away
622        (maybe-error-converting-value
623         res val type database)))))
624
625 (defmethod read-sql-value (val type database db-type)
626   ;; errors, nulls and preconverted types are already handled in around
627   (typecase type
628     (symbol
629      (case type
630        ((string varchar) val)
631        (char (string (schar val 0)))
632        ((or keyword symbol)
633         (read-from-string val))
634        ((smallint mediumint bigint integer universal-time)
635         (parse-integer val))
636        ((double-float float)
637         ;; ensure that whatever we got is coerced to a float of the
correct
638         ;; type (eg: 1=>1.0d0)
639         (float
640          (etypecase val
641            (string (let ((*read-default-float-format*
642                            (ecase type
643                              (float 'single-float)
644                              (double-float 'double-float))))
645                      (read-from-string val)))
646            ;; maybe wrong type of float
647            (float val))
648          (if (eql type 'double-float) 1.0d0 1.0s0)))
649        (number (read-from-string val))
650        ((boolean generalized-boolean)
651         (if (member val '(nil t))
652             val
653             (etypecase val
654               (string
655                (when (member val '("1" "t" "true" "y") :test
#'string-equal)
656                  t))
657               (number (not (zerop val))))))
658        ((wall-time duration) (parse-timestring val))
659        (date (parse-datestring val))
660        (t (call-next-method))))
661     (t (typecase val
662          (string (read-from-string val))
663          (t (error-converting-value val type database))))))

Mariano