[pg-cvs] CVS update: pg/defpackage.lisp pg/v3-protocol.lisp

Peter Van Eynde pvaneynde at common-lisp.net
Tue Mar 9 16:27:20 UTC 2004


Update of /project/pg/cvsroot/pg
In directory common-lisp.net:/tmp/cvs-serv8897

Modified Files:
	defpackage.lisp v3-protocol.lisp 
Log Message:
untested COPY IN/OUT code. I am not happy about how this looks...
Date: Tue Mar  9 11:27:20 2004
Author: pvaneynde

Index: pg/defpackage.lisp
diff -u pg/defpackage.lisp:1.2 pg/defpackage.lisp:1.3
--- pg/defpackage.lisp:1.2	Mon Mar  8 09:38:07 2004
+++ pg/defpackage.lisp	Tue Mar  9 11:27:20 2004
@@ -6,6 +6,7 @@
         #+openmcl :ccl)
   #+openmcl (:shadow ccl:socket-connect)
   (:export #:pg-connect #:pg-exec #:pg-result #:pg-disconnect
+	   #:pgcon-sql-stream
            #:*pg-disable-type-coercion*
            #:pg-databases #:pg-tables #:pg-columns
            #:pg-backend-version


Index: pg/v3-protocol.lisp
diff -u pg/v3-protocol.lisp:1.5 pg/v3-protocol.lisp:1.6
--- pg/v3-protocol.lisp:1.5	Mon Mar  8 13:12:45 2004
+++ pg/v3-protocol.lisp	Tue Mar  9 11:27:20 2004
@@ -7,8 +7,10 @@
 
 (defclass pgcon-v3 (pgcon)
   ((parameters  :accessor pgcon-parameters
-                :initform (list))))
-
+                :initform (list))
+   (sql-stream  :initform nil
+		:accessor pgcon-sql-stream
+		:type (or nil stream))))
 
 
 (define-condition error-response (postgresql-error)
@@ -279,7 +281,8 @@
                                 ((:byte :char) 1)
                                 ((:int16) 2)
                                 ((:int32) 4)
-                                ((:cstring)
+                                ((:cstring
+				  :rawdata)
                                  (+ 1
                                     (length value)))))))
          (data (make-array (- length 4)
@@ -320,7 +323,12 @@
                          (char-code char))
                    (incf position))
              (setf (elt data position) 0)
-             (incf position))))
+             (incf position))
+	    ((:rawdata)
+             (check-type value (array (unsigned-byte 8) *))
+
+	     (replace data value :start1 position)
+	     (incf position (length value)))))
 
     (%send-net-int stream (char-code code) 1)
     (%send-net-int stream length 4 )
@@ -449,6 +457,7 @@
     (loop
      :for packet = (read-packet connection)
      :with got-data-p = nil
+     :with receive-data-p = nil
      :do
      (when packet
        (case (pg-packet-type packet)
@@ -472,27 +481,72 @@
           (setf got-data-p t))
          ((#\G)
           ;; CopyInResponse
-          (cerror "Just ignore it" "What to do with #\G?")
-          ;; The backend is ready to copy data from the frontend to a table;
-          ;; see Section 44.2.5 in http://www.postgresql.org/docs/7.4/interactive/protocol-flow.html
-          ;; for now we make it fail gracefully:
-          (send-packet connection
-                       #\f
-                       ;;CopyFail
-                       '((:cstring "not implemented by pg.lisp yet")))
-          )
+	  (cond
+	    ((and (streamp (pgcon-sql-stream connection))
+		  (input-stream-p (pgcon-sql-stream connection)))
+	     ;; we ignore the data stuff.
+	     (handler-case
+	      (progn
+		(loop :with buffer = (make-array 4096
+						 :element-type '(unsigned-byte 8)
+						 :adjustable t)
+		      :for length = (read-sequence buffer (pgcon-sql-stream connection))
+		      :until (= length 0)
+		      :do
+		      ;; send data
+		      (unless (= length 4096)
+			(setf buffer
+			      (adjust-array buffer (list length))))
+		      (send-packet connection
+				   #\d
+				   `((:rawdata ,buffer))))
+		
+		;; CopyDone
+		(send-packet connection
+			     #\c
+			     nil))
+	      ((or error serious-condition) (condition)
+	       (warn "Got an error while writing sql data: ~S aborting transfer!"
+		     condition)
+	       (send-packet connection
+			    #\f
+			    ;;CopyFail
+			    '((:cstring "No input data provided")))))
+	     (%flush connection))
+	    (t
+	     (warn "We had to provide data, but my sql-stream isn't an input-stream. Aborting transfer")
+
+	     (send-packet connection
+			  #\f
+			  ;;CopyFail
+			  '((:cstring "No input data provided"))))))
          ((#\H)
           ;; CopyOutResponse
-          (cerror "Just ignore it" "What to do with #\H?")
-          ;; The backend is ready to copy data from a table to the frontend;
-          ;; see Section 44.2.5.
-          ;; for now we make it fail gracefully (we cannot stop the transfer...
-          )
-         (( #\d
-            ;; CopyData
-            #\c
-            ;;CopyDone
-            )
+	  (cond
+	    ((and (streamp (pgcon-sql-stream connection))
+		  (output-stream-p (pgcon-sql-stream connection)))
+	     (setf receive-data-p t))
+	    (t
+	     (setf receive-data-p nil)
+	     (warn "I should receive data but my sql-stream isn't an outputstream!~%Ignoring data"))))
+         (( #\d)
+	  ;; CopyData
+	  (when receive-data-p
+	    ;; we break the nice packet abstraction here to
+	    ;; get some speed:
+	    (let ((length (read-from-packet packet :int32)))
+	      (write-sequence (make-array length
+					  :element-type '(unsigned-byte 8)
+					  :displaced-to (slot-value packet
+								    'data)
+					  :displaced-index-offset
+					  (slot-value packet 'position))
+			      (pgcon-sql-stream connection)))))
+	 (( #\c )
+	  ;;CopyDone
+	  ;; we do nothing (the exec will return and the user
+	  ;; can do something if he/she wants
+	  (setf receive-data-p nil)
           t)
          ((#\T)
           ;; RowDescription (metadata for subsequent tuples), #\T





More information about the Pg-cvs mailing list