Commit baed7a3f authored by Eric Marsden's avatar Eric Marsden

- 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
parent 6a1a221c
......@@ -36,6 +36,9 @@
;;
(declaim (optimize (speed 3) (safety 1)))
(in-package :postgresql)
......@@ -82,6 +85,10 @@ Needed to define the type of objects in pg-prepare")
;; oidvector
;; bit
;; varbit
;; record
;; cstring
;; any
("row" . ,'row-parser)
("float4" . ,'float-parser)
("float8" . ,'float-parser)
("money" . ,'text-parser) ; "$12.34"
......@@ -225,6 +232,19 @@ Needed to define the type of objects in pg-prepare")
(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 @@ not found"
(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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment