;;; ;;; Tools to handle data conversion to PostgreSQL format ;;; ;;; Any function that you want to use to transform data with will get looked ;;; up in the pgloader.transforms package, when using the default USING ;;; syntax for transformations. (defpackage #:pgloader.transforms (:use #:cl) (:export #:intern-symbol)) (in-package :pgloader.transforms) (defun intern-symbol (symbol-name) (intern (string-upcase symbol-name) (find-package "PGLOADER.TRANSFORMS"))) (defun zero-dates-to-null (date-string) "MySQL accepts '0000-00-00' as a date, we want :null instead." (cond ((null date-string) nil) ((string= date-string "") nil) ((string= date-string "0000-00-00") nil) ((string= date-string "0000-00-00 00:00:00") nil) (t date-string))) (defun date-with-no-separator (date-string &optional (format '((:year 0 4) (:month 4 6) (:day 6 8) (:hour 8 10) (:minute 10 12) (:seconds 12 14)))) "Apply this function when input date in like '20041002152952'" ;; only process non-zero dates (if (null (zero-dates-to-null date-string)) nil (destructuring-bind (&key year month day hour minute seconds &allow-other-keys) (loop for (name start end) in format append (list name (subseq date-string start end))) (format nil "~a-~a-~a ~a:~a:~a" year month day hour minute seconds)))) (defun tinyint-to-boolean (integer-string) "When using MySQL, strange things will happen, like encoding booleans into tinyiny that are either 0 (false) or 1 (true). Of course PostgreSQL wants 'f' and 't', respectively." (if (string= "0" integer-string) "f" "t")) (declaim (inline int-to-ip)) (defun int-to-ip (int) "Transform an IP as integer into its dotted notation, optimised code from stassats." (declare (optimize speed) (type (unsigned-byte 32) int)) (let ((table (load-time-value (let ((vec (make-array (+ 1 #xFFFF)))) (loop for i to #xFFFF do (setf (aref vec i) (coerce (format nil "~a.~a" (ldb (byte 8 8) i) (ldb (byte 8 0) i)) 'simple-base-string))) vec) t))) (declare (type (simple-array simple-base-string (*)) table)) (concatenate 'simple-base-string (aref table (ldb (byte 16 16) int)) "." (aref table (ldb (byte 16 0) int))))) (declaim (inline ip-range)) (defun ip-range (start-integer-string end-integer-string) "Transform a couple of integers to an IP4R ip range notation." (declare (optimize speed) (type string start-integer-string end-integer-string)) (let ((ip-start (int-to-ip (parse-integer start-integer-string))) (ip-end (int-to-ip (parse-integer end-integer-string)))) (concatenate 'simple-base-string ip-start "-" ip-end)))