[pg-cvs] CVS pg
emarsden
emarsden at common-lisp.net
Mon Sep 18 21:37:48 UTC 2006
Update of /project/pg/cvsroot/pg
In directory clnet:/tmp/cvs-serv12747
Modified Files:
v3-protocol.lisp
Log Message:
Fix problems with text data in prepared statements. Unlike the rest of
the protocol, strings are not sent NUL-terminated.
--- /project/pg/cvsroot/pg/v3-protocol.lisp 2006/09/15 20:49:03 1.21
+++ /project/pg/cvsroot/pg/v3-protocol.lisp 2006/09/18 21:37:48 1.22
@@ -306,6 +306,7 @@
((:int16) 2)
((:int32) 4)
((:rawdata) (length value))
+ ((:string) (length (convert-string-to-bytes value)))
((:cstring) (1+ (length (convert-string-to-bytes value))))
((:ucstring) (1+ (length value)))))))
(data (make-array (- length 4)
@@ -356,6 +357,13 @@
(setf (elt data position) 0)
(incf position))
+ ;; a string without the trailing NUL character
+ ((:string)
+ (check-type value string)
+ (let ((encoded (convert-string-to-bytes value)))
+ (replace data encoded :start1 position)
+ (incf position (length encoded))))
+
((:rawdata)
(check-type value (array (unsigned-byte 8) *))
(replace data value :start1 position)
@@ -374,26 +382,16 @@
to connect to the database using a Unix socket."
(let* ((stream (socket-connect port host))
(connection (make-instance 'pgcon-v3 :stream stream :host host :port port))
- (user-packet-length (+ 4 ; length
- 4 ; protocol version
- (length "user")
- 1
- (length user)
- 1
- (length "database")
- 1
- (length dbname)
- 1
- 1)))
+ (connect-options `("user" ,user
+ "database" ,dbname))
+ (user-packet-length (+ 4 4 (loop :for item :in connect-options :sum (1+ (length item))) 1)))
;; send the startup packet
;; this is one of the only non-standard packets!
(%send-net-int stream user-packet-length 4)
(%send-net-int stream 3 2) ; major
(%send-net-int stream 0 2) ; minor
- (%send-cstring stream "user")
- (%send-cstring stream user)
- (%send-cstring stream "database")
- (%send-cstring stream dbname)
+ (dolist (item connect-options)
+ (%send-cstring stream item))
(%send-net-int stream 0 1)
(%flush connection)
@@ -634,9 +632,7 @@
(warn "Got unexpected packet: ~S, resetting connection"
packet)
;; sync
- (send-packet connection
- #\S
- nil)
+ (send-packet connection #\S nil)
(%flush connection)))))))
(defmethod pg-exec ((connection pgcon-v3) &rest args)
@@ -851,16 +847,16 @@
t))
(defmethod pg-bind ((connection pgcon-v3) (portal string) (statement-name string) list-of-types-and-values)
- (let ((formats (when list-of-types-and-values
+ (let ((formats (when list-of-types-and-values
(loop :for (type value) :in list-of-types-and-values
:collect
(ecase type
- ((:string) `(:int16 0))
- ((:byte :int16 :int32 :char) `(:int16 1))))))
- (data nil))
+ ((:string) '(:int16 0))
+ ((:byte :int16 :int32 :char) '(:int16 1))))))
+ (data nil))
(when list-of-types-and-values
- (loop :for (type value) :in list-of-types-and-values
+ (loop :for (type value) :in list-of-types-and-values
:do
(ecase type
((:int32)
@@ -875,10 +871,12 @@
((:char)
(push '(:int32 1) data)
(push `(:int8 ,(char-code value)) data))
+ ;; this is not a NUL-terminated string, so send exactly
+ ;; the string length rather than 1+
((:string)
- (push `(:int32 ,(1+ (length value))) data)
- (push `(:cstring ,value) data))))
-
+ (let ((encoded-length (length (convert-string-to-bytes value (pg-client-encoding connection)))))
+ (push `(:int32 ,encoded-length) data)
+ (push `(:string ,value) data)))))
(setf data (nreverse data)))
(cond
@@ -912,13 +910,10 @@
(send-packet connection
#\E
`((:cstring ,portal)
- (:int32 ,maxinum-number-of-rows)))
+ (:int32 ,maximum-number-of-rows)))
;; send all data:
- (send-packet connection
- #\S
- nil)
+ (send-packet connection #\S nil)
(%flush connection)
-
(do-followup-query connection))
(defun pg-close (connection name type)
More information about the Pg-cvs
mailing list