Update of /project/pg/cvsroot/pg In directory common-lisp.net:/tmp/cvs-serv13664
Modified Files: parsers.lisp Log Message:
From Sven Van Caekenberghe:
- fix to PARSE-TIMESTAMP when no milliseconds are present
- make use of :start and :end arguments to PARSE-INTEGER to reduce consing
Date: Wed Apr 21 15:23:18 2004 Author: emarsden
Index: pg/parsers.lisp diff -u pg/parsers.lisp:1.2 pg/parsers.lisp:1.3 --- pg/parsers.lisp:1.2 Mon Mar 8 09:37:36 2004 +++ pg/parsers.lisp Wed Apr 21 15:23:18 2004 @@ -1,7 +1,6 @@ ;;; parsers.lisp -- type coercion support ;;; ;;; Author: Eric Marsden emarsden@laas.fr -;;; Time-stamp: <2004-03-05 emarsden> ;; ;; ;; When returning data from a SELECT statement, PostgreSQL starts by @@ -100,11 +99,15 @@ ;; FIXME switch to a specialized float parser (defun float-parser (str) (declare (type simple-string str)) - (let ((*read-eval* nil)) (read-from-string str)))
-;; FIXME this may need support for charset decoding +;; here we are assuming that the value of *PG-CLIENT-ENCODING* is +;; compatible with the encoding that the CL implementation uses for +;; strings. The backend should convert all values belonging to one of +;; the text data types from the table's internal representation to +;; that requested by the client, so here we don't need to do any +;; conversion. (defun text-parser (str) str)
(defun bool-parser (str) @@ -116,18 +119,20 @@
(defun parse-timestamp (str) (declare (type simple-string str)) - (let* ((year (parse-integer (subseq str 0 4))) - (month (parse-integer (subseq str 5 7))) - (day (parse-integer (subseq str 8 10))) - (hours (parse-integer (subseq str 11 13))) - (minutes (parse-integer (subseq str 14 16))) - (seconds (parse-integer (subseq str 17 19))) - (start-tz (if (eql #+ (char str (- (length str) 3))) - (- (length str) 3))) + (let* ((year (parse-integer str :start 0 :end 4)) + (month (parse-integer str :start 5 :end 7)) + (day (parse-integer str :start 8 :end 10)) + (hours (parse-integer str :start 11 :end 13)) + (minutes (parse-integer str :start 14 :end 16)) + (seconds (parse-integer str :start 17 :end 19)) + (length (length str)) + (start-tz (if (eql #+ (char str (- length 3))) + (- length 3))) (tz (when start-tz - (parse-integer (subseq str start-tz)))) - (milliseconds (if (eql (char str 19) #.) - (parse-integer (subseq str 20 start-tz)) 0))) + (parse-integer str :start start-tz))) + (milliseconds (if (and (< 19 length) (eql (char str 19) #.)) + (parse-integer str :start 20 :end start-tz) + 0))) (values year month day hours minutes seconds milliseconds tz)))
;; format for abstime/timestamp etc with ISO output syntax is @@ -151,10 +156,10 @@ ;; An interval is what you get when you subtract two timestamps. We ;; convert to a number of seconds. (defun interval-parser (str) - (let* ((hours (parse-integer (subseq str 0 2))) - (minutes (parse-integer (subseq str 3 5))) - (seconds (parse-integer (subseq str 6 8))) - (milliseconds (parse-integer (subseq str 9)))) + (let* ((hours (parse-integer str :start 0 :end 2)) + (minutes (parse-integer str :start 3 :end 5)) + (seconds (parse-integer str :start 6 :end 8)) + (milliseconds (parse-integer str :start 9))) (+ (/ milliseconds (expt 10.0 (- (length str) 9))) seconds (* 60 minutes) @@ -165,22 +170,22 @@ ;;; "1999-01-02 00:00:00+01" ;; which we convert to a CL universal time (defun isodate-parser (str) - (let ((year (parse-integer (subseq str 0 4))) - (month (parse-integer (subseq str 5 7))) - (day (parse-integer (subseq str 8 10))) - (hours (parse-integer (subseq str 11 13))) - (minutes (parse-integer (subseq str 14 16))) - (seconds (parse-integer (subseq str 17 19))) - (tz (parse-integer (subseq str 19 22)))) + (let ((year (parse-integer str :start 0 :end 4)) + (month (parse-integer str :start 5 :end 7)) + (day (parse-integer str :start 8 :end 10)) + (hours (parse-integer str :start 11 :end 13)) + (minutes (parse-integer str :start 14 :end 16)) + (seconds (parse-integer str :start 17 :end 19)) + (tz (parse-integer str :start 19 :end 22))) (encode-universal-time seconds minutes hours day month year tz)))
;; format for date with ISO output syntax is ;;; "1999-01-02" ;; which we convert to a CL universal time (defun date-parser (str) - (let ((year (parse-integer (subseq str 0 4))) - (month (parse-integer (subseq str 5 7))) - (day (parse-integer (subseq str 8 10)))) + (let ((year (parse-integer str :start 0 :end 4)) + (month (parse-integer str :start 5 :end 7)) + (day (parse-integer str :start 8 :end 10))) (encode-universal-time 0 0 0 day month year)))
(defun initialize-parsers (connection) @@ -204,6 +209,8 @@ oid))))) tuples)))
+;; FIXME should perhaps resignal parse errors as a condition derived +;; from POSTGRESQL-ERROR (defun parse (str oid) (declare (type simple-string str)) (let ((parser (assoc oid *parsers* :test #'eql)))