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-SYNT... +;; +;; 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