Handle default value transforms errors, fix #333.

It turns out that MySQL catalog always store default value as strings
even when the column itself is of type bytea. In some cases, it's then
impossible to transform the expected bytea from a string.

In passing, move some code around to fix dependencies and make it
possible to issue log warnings from the default value printing code.
This commit is contained in:
Dimitri Fontaine 2016-02-03 12:27:58 +01:00
parent e7771ff3d8
commit 782561fd4e
5 changed files with 49 additions and 37 deletions

View File

@ -76,6 +76,10 @@
"report"))
(:file "archive" :depends-on ("logs"))
(:file "pg-format-column" :depends-on ("schema-structs"
"monitor"
"state"))
;; generic connection api
(:file "connection" :depends-on ("archive"))))

View File

@ -68,7 +68,7 @@
#:column-name
#:column-type-name
#:column-type-mod
#:column-type-nullable
#:column-nullable
#:column-default
#:column-comment
#:column-transform
@ -99,9 +99,7 @@
#:push-to-end
#:with-schema
#:format-table-name
#:format-default-value
#:format-column))
#:format-table-name))
(defpackage #:pgloader.state
(:use #:cl #:pgloader.params #:pgloader.schema)

View File

@ -0,0 +1,40 @@
;;;
;;; PostgreSQL column and type output
;;;
(in-package #:pgloader.utils)
(defun format-default-value (default &optional transform)
"Returns suitably quoted default value for CREATE TABLE command."
(cond
((null default) "NULL")
((and (stringp default) (string= "NULL" default)) default)
((and (stringp default) (string= "CURRENT_TIMESTAMP" default)) default)
((and (stringp default) (string= "CURRENT TIMESTAMP" default))
"CURRENT_TIMESTAMP")
((and (stringp default) (string= "newsequentialid()" default))
"uuid_generate_v1()")
(t
;; apply the transformation function to the default value
(if transform (format-default-value
(handler-case
(funcall transform default)
(condition (c)
(log-message :warning
"Failed to transform default value ~s: ~a"
default c)
;; can't transform: return nil
nil)))
(format nil "'~a'" default)))))
(defmethod format-column ((column column))
"Format the PostgreSQL data type."
(format nil
"~a ~22t ~a~:[~*~;~a~]~:[ not null~;~]~:[~; default ~a~]"
(column-name column)
(column-type-name column)
(column-type-mod column)
(column-type-mod column)
(column-nullable column)
(column-default column)
(column-default column)))

View File

@ -347,35 +347,3 @@
(cdr ,table-name)))
(string ,table-name))))
,@body))
;;;
;;; PostgreSQL column and type output
;;;
(defun format-default-value (default &optional transform)
"Returns suitably quoted default value for CREATE TABLE command."
(cond
((null default) "NULL")
((and (stringp default) (string= "NULL" default)) default)
((and (stringp default) (string= "CURRENT_TIMESTAMP" default)) default)
((and (stringp default) (string= "CURRENT TIMESTAMP" default))
"CURRENT_TIMESTAMP")
((and (stringp default) (string= "newsequentialid()" default))
"uuid_generate_v1()")
(t
;; apply the transformation function to the default value
(if transform (format-default-value (funcall transform default))
(format nil "'~a'" default)))))
(defmethod format-column ((column column))
"Format the PostgreSQL data type."
(with-slots (name type-name type-mod nullable default transform) column
(format nil
"~a ~22t ~a~:[~*~;~a~]~:[ not null~;~]~:[~; default ~a~]"
name
type-name
type-mod
type-mod
nullable
default default)))

View File

@ -226,7 +226,9 @@
(declare (type (or null string (simple-array (unsigned-byte 8) (*))) vector))
(etypecase vector
(null nil)
(string (assert (string= "" vector)) nil)
(string (if (string= "" vector)
nil
(error "byte-vector-to-bytea called on a string: ~s" vector)))
(simple-array
(let ((hex-digits "0123456789abcdef")
(bytea (make-array (+ 2 (* 2 (length vector)))