Properly handle blob formats, converting then to PostgreSQL bytea input.

This commit is contained in:
Dimitri Fontaine 2013-11-22 11:01:20 +01:00
parent 74cabeb6f5
commit 78b42cc4ae
2 changed files with 42 additions and 10 deletions

View File

@ -93,16 +93,22 @@
:target (:type "varchar" :drop-typemod nil))
;;
;; cl-mysql and postmodern are adapting binary values as a simple-array
;; (or vector) of (UNSIGNED-BYTE 8), so there should be no other
;; explicit conversion to do here.
;; cl-mysql returns binary values as a simple-array of bytes (as in
;; (UNSIGNED-BYTE 8)), that we then need to represent as proper
;; PostgreSQL bytea input.
;;
(:source (:type "binary") :target (:type "bytea"))
(:source (:type "varbinary") :target (:type "bytea"))
(:source (:type "tinyblob") :target (:type "bytea"))
(:source (:type "blob") :target (:type "bytea"))
(:source (:type "mediumblob") :target (:type "bytea"))
(:source (:type "longblob") :target (:type "bytea"))
(:source (:type "binary") :target (:type "bytea")
:using pgloader.transforms::byte-vector-to-bytea)
(:source (:type "varbinary") :target (:type "bytea")
:using pgloader.transforms::byte-vector-to-bytea)
(:source (:type "tinyblob") :target (:type "bytea")
:using pgloader.transforms::byte-vector-to-bytea)
(:source (:type "blob") :target (:type "bytea")
:using pgloader.transforms::byte-vector-to-bytea)
(:source (:type "mediumblob") :target (:type "bytea")
:using pgloader.transforms::byte-vector-to-bytea)
(:source (:type "longblob") :target (:type "bytea")
:using pgloader.transforms::byte-vector-to-bytea)
(:source (:type "datetime" :default "0000-00-00 00:00:00" :not-null t)
:target (:type "timestamptz" :drop-default t :drop-not-null t)

View File

@ -21,7 +21,8 @@
convert-mysql-point
float-to-string
set-to-enum-array
right-trim))
right-trim
byte-vector-to-bytea))
;;;
@ -143,3 +144,28 @@
"Remove whitespaces at end of STRING."
(declare (type simple-string string))
(string-right-trim '(#\Space) string))
(defun byte-vector-to-bytea (vector)
"Transform a simple array of unsigned bytes to the PostgreSQL bytea
representation as documented at
http://www.postgresql.org/docs/9.3/interactive/datatype-binary.html
Note that we choose here the bytea Hex Format."
(declare (type simple-array vector))
(let ((hex-digits "0123456789abcdef")
(bytea (make-array (+ 2 (* 2 (length vector)))
:initial-element #\0
:element-type 'standard-char)))
;; The entire string is preceded by the sequence \x (to distinguish it
;; from the escape format).
(setf (aref bytea 0) #\\)
(setf (aref bytea 1) #\x)
(loop for pos from 2 by 2
for byte across vector
do (let ((high (ldb (byte 4 4) byte))
(low (ldb (byte 4 0) byte)))
(setf (aref bytea pos) (aref hex-digits high))
(setf (aref bytea (+ pos 1)) (aref hex-digits low)))
finally (return bytea))))