[pg-cvs] CVS update: pg/parsers.lisp

Eric Marsden emarsden at common-lisp.net
Wed Apr 21 19:23:18 UTC 2004


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 at 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)))





More information about the Pg-cvs mailing list