[pg-cvs] CVS pg

emarsden emarsden at common-lisp.net
Sun Oct 22 19:29:48 UTC 2006


Update of /project/pg/cvsroot/pg
In directory clnet:/tmp/cvs-serv12033

Modified Files:
	parsers.lisp 
Log Message:
 - implement basic parsing support for the PostgreSQL record type

 - supply a utility function to escape binary data into a format that
   can be used within an SQL string to initialize a field of type
   BYTEA

 - add optimize declarations for improved performance


--- /project/pg/cvsroot/pg/parsers.lisp	2005/12/19 22:29:59	1.8
+++ /project/pg/cvsroot/pg/parsers.lisp	2006/10/22 19:29:47	1.9
@@ -36,6 +36,9 @@
 ;;
 
 
+(declaim (optimize (speed 3) (safety 1)))
+
+
 (in-package :postgresql)
 
 
@@ -82,6 +85,10 @@
     ;; oidvector
     ;; bit
     ;; varbit
+    ;; record
+    ;; cstring
+    ;; any
+    ("row"       . ,'row-parser)
     ("float4"    . ,'float-parser)
     ("float8"    . ,'float-parser)
     ("money"     . ,'text-parser)       ; "$12.34"
@@ -225,6 +232,19 @@
         (day     (parse-integer str :start 8 :end 10)))
     (encode-universal-time 0 0 0 day month year)))
 
+
+;; http://www.postgresql.org/docs/8.1/interactive/sql-expressions.html#SQL-SYNTAX-ROW-CONSTRUCTORS
+;;
+;; these are in the format "(foo,bar,baz)"
+(defun row-parser (str)
+  (assert (char= #\( (char str 0)))
+  (loop :with start = 1
+        :with last = (- (length str) 1)
+        :for end = (or (position #\, str :start start) last)
+        :collect (subseq str start end)
+        :do (setq start (1+ end))
+        :until (>= end last)))
+
 (defun initialize-parsers (connection)
   (let* ((pgtypes (pg-exec connection "SELECT typname,oid FROM pg_type"))
          (tuples (pg-result pgtypes :tuples)))
@@ -265,4 +285,29 @@
                  (intern type :keyword)))))
     (gethash type *type-to-oid*)))
 
+
+
+;; PQescapeBytea	- converts from binary string to the
+;; minimal encoding necessary to include the string in an SQL
+;; INSERT statement with a bytea type column as the target.
+;; 
+;; The following transformations are applied
+;; '\0' == ASCII  0 == \000
+;; '\'' == ASCII 39 == ''
+;; '\\' == ASCII 92 == \\
+;; anything < 0x20, or > 0x7e ---> \ooo
+;; 								(where ooo is an octal expression)
+;; If not std_strings, all backslashes sent to the output are doubled.
+;;
+;; http://www.postgresql.org/docs/8.1/static/datatype-binary.html
+(defun bytea->string (data)
+  (declare (type (vector (unsigned-byte 8) *) data))
+  (with-output-to-string (out)
+    (loop :for octet :across data :do
+          (cond ((<= 32 octet 126)
+                 (write-char (code-char octet) out))
+                (t
+                 (format out "\\~3,'0O" octet))))))
+
+
 ;; EOF




More information about the Pg-cvs mailing list