From e21ce09ad76cb7763ff85c29af70d9c26f19b6b8 Mon Sep 17 00:00:00 2001 From: Dimitri Fontaine Date: Tue, 15 Aug 2017 15:26:06 +0200 Subject: [PATCH] Implement support for MySQL linestring data type. This data type is now converted automatically to a PostgreSQL path data type, using the open path notation with square brackets: https://www.postgresql.org/docs/current/static/datatype-geometric.html#AEN7103 Fix #445. --- src/sources/mysql/mysql-cast-rules.lisp | 6 +++++- src/sources/mysql/mysql-schema.lisp | 7 ++++--- src/utils/transforms.lisp | 18 ++++++++++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/sources/mysql/mysql-cast-rules.lisp b/src/sources/mysql/mysql-cast-rules.lisp index 1dea915..45a8234 100644 --- a/src/sources/mysql/mysql-cast-rules.lisp +++ b/src/sources/mysql/mysql-cast-rules.lisp @@ -141,7 +141,11 @@ (:source (:type "point") :target (:type "point") - :using pgloader.transforms::convert-mysql-point)) + :using pgloader.transforms::convert-mysql-point) + + (:source (:type "linestring") + :target (:type "path") + :using pgloader.transforms::convert-mysql-linestring)) "Data Type Casting rules to migrate from MySQL to PostgreSQL") diff --git a/src/sources/mysql/mysql-schema.lisp b/src/sources/mysql/mysql-schema.lisp index a111832..21bd80f 100644 --- a/src/sources/mysql/mysql-schema.lisp +++ b/src/sources/mysql/mysql-schema.lisp @@ -339,9 +339,10 @@ Mostly we just use the name, but in case of POINT we need to use astext(name)." (case (intern (string-upcase type) "KEYWORD") - (:geometry (format nil "astext(`~a`) as `~a`" name name)) - (:point (format nil "astext(`~a`) as `~a`" name name)) - (t (format nil "`~a`" name)))) + (:geometry (format nil "astext(`~a`) as `~a`" name name)) + (:point (format nil "astext(`~a`) as `~a`" name name)) + (:linestring (format nil "astext(`~a`) as `~a`" name name)) + (t (format nil "`~a`" name)))) (defun get-column-list (dbname table-name) "Some MySQL datatypes have a meaningless default output representation, we diff --git a/src/utils/transforms.lisp b/src/utils/transforms.lisp index 0f1c2a0..f5b43dd 100644 --- a/src/utils/transforms.lisp +++ b/src/utils/transforms.lisp @@ -187,6 +187,24 @@ (setf (aref point (position #\Space point)) #\,) point))) +(defun convert-mysql-linestring (mysql-linestring-as-string) + "Transform the MYSQL-POINT-AS-STRING into a suitable representation for + PostgreSQL. + + Input: \"LINESTRING(-87.87342467651445 45.79684462673078,-87.87170806274479 45.802110434248966)\" ; that's using astext(column) + Output: [(-87.87342467651445,45.79684462673078),(-87.87170806274479,45.802110434248966)]" + (when mysql-linestring-as-string + (let* ((data (subseq mysql-linestring-as-string + 11 + (- (length mysql-linestring-as-string) 1)))) + (with-output-to-string (s) + (write-string "[" s) + (loop :for first := t :then nil + :for point :in (split-sequence:split-sequence #\, data) + :for (x y) := (split-sequence:split-sequence #\Space point) + :do (format s "~:[,~;~](~a,~a)" first x y)) + (write-string "]" s))))) + (defun integer-to-string (integer-string) "Transform INTEGER-STRING parameter into a proper string representation of it. In particular be careful of quoted-integers, thanks to SQLite default