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.
This commit is contained in:
Dimitri Fontaine 2017-08-15 15:26:06 +02:00
parent 20a85055f4
commit e21ce09ad7
3 changed files with 27 additions and 4 deletions

View File

@ -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")

View File

@ -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

View File

@ -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