From fb54d19357480fac27f4ab2a17d234cd05d06c9b Mon Sep 17 00:00:00 2001 From: Dimitri Fontaine Date: Mon, 18 Nov 2013 10:28:38 +0100 Subject: [PATCH] Review some default casting rules, in particular add tinyint(1) to boolean. --- pgloader.1.md | 19 +++++++++++---- src/sources/mysql-cast-rules.lisp | 39 ++++++++++++++----------------- test/parse/hans.goeuro.load | 11 +++++---- 3 files changed, 39 insertions(+), 30 deletions(-) diff --git a/pgloader.1.md b/pgloader.1.md index 42ad612..8533913 100644 --- a/pgloader.1.md +++ b/pgloader.1.md @@ -870,6 +870,10 @@ The `database` command accepts the following clauses and options: flexibility allows to cope with cases where the type `tinyint` might have been used as a `boolean` in some cases but as a `smallint` in others. + + The *casting rules* are applied in order, the first match prevents + following rules to be applied, and user defined rules are evaluated + first. The supported guards are: @@ -1027,12 +1031,14 @@ When migrating from MySQL the following Casting Rules are provided: Numbers: - - type int to serial when auto_increment and (< typemod 10) - - type int to bigserial when auto_increment and (<= 10 typemod) - - type int to int when not auto_increment and (< typemod 10) - - type int to bigint when not auto_increment and (<= 10 typemod) + - type int to serial when auto_increment and (< precision 10) + - type int to bigserial when auto_increment and (<= 10 precision) + - type int to int when not auto_increment and (< precision 10) + - type int to bigint when not auto_increment and (<= 10 precision) - type bigint to bigserial when auto_increment + - type tinyint to boolean when (= 1 precision) using tinyint-to-boolean + - type tinyint to smallint drop typemod - type smallint to smallint drop typemod - type mediumint to integer drop typemod @@ -1066,17 +1072,22 @@ Date: - type datetime when default "0000-00-00 00:00:00" and not null to timestamptz drop not null drop default + using zero-dates-to-null - type datetime when default "0000-00-00 00:00:00" to timestamptz drop default + using zero-dates-to-null - type timestamp when default "0000-00-00 00:00:00" and not null to timestamptz drop not null drop default + using zero-dates-to-null - type timestamp when default "0000-00-00 00:00:00" to timestamptz drop default + using zero-dates-to-null - type date when default "0000-00-00" to date drop default + using zero-dates-to-null - type date to date - type datetime to timestamptz diff --git a/src/sources/mysql-cast-rules.lisp b/src/sources/mysql-cast-rules.lisp index 998094c..0ba4d66 100644 --- a/src/sources/mysql-cast-rules.lisp +++ b/src/sources/mysql-cast-rules.lisp @@ -60,6 +60,11 @@ ;; bigint with auto_increment always are bigserial (:source (:type "bigint" :auto-increment t) :target (:type "bigserial")) + ;; actually tinyint(1) is most often used as a boolean + (:source (:type "tinyint" :typemod (= 1 precision)) + :target (:type "boolean" :drop-typemod t) + :using pgloader.transforms::tinyint-to-boolean) + ;; we need the following to benefit from :drop-typemod (:source (:type "tinyint") :target (:type "smallint" :drop-typemod t)) (:source (:type "smallint") :target (:type "smallint" :drop-typemod t)) @@ -100,19 +105,24 @@ (:source (:type "longblob") :target (:type "bytea")) (:source (:type "datetime" :default "0000-00-00 00:00:00" :not-null t) - :target (:type "timestamptz" :drop-default t :drop-not-null t)) + :target (:type "timestamptz" :drop-default t :drop-not-null t) + :using pgloader.transforms::zero-dates-to-null) (:source (:type "datetime" :default "0000-00-00 00:00:00") - :target (:type "timestamptz" :drop-default t)) + :target (:type "timestamptz" :drop-default t) + :using pgloader.transforms::zero-dates-to-null) (:source (:type "timestamp" :default "0000-00-00 00:00:00" :not-null t) - :target (:type "timestamptz" :drop-default t :drop-not-null t)) + :target (:type "timestamptz" :drop-default t :drop-not-null t) + :using pgloader.transforms::zero-dates-to-null) (:source (:type "timestamp" :default "0000-00-00 00:00:00") - :target (:type "timestamptz" :drop-default t)) + :target (:type "timestamptz" :drop-default t) + :using pgloader.transforms::zero-dates-to-null) (:source (:type "date" :default "0000-00-00") - :target (:type "date" :drop-default t)) + :target (:type "date" :drop-default t) + :using pgloader.transforms::zero-dates-to-null) ;; date types without strange defaults (:source (:type "date") :target (:type "date")) @@ -333,22 +343,6 @@ that would be int and int(7) or varchar and varchar(25)." :target (:type "text" :drop-default nil :drop-not-null nil) :using nil) - (:source (:type "tinyint" :auto-increment nil) - :target (:type "boolean" :drop-default nil :drop-not-null nil) - :using pgloader.transforms::tinyint-to-boolean) - - (:source (:type "datetime" :auto-increment nil) - :target (:type "timestamptz" :drop-default t :drop-not-null t) - :using pgloader.transforms::zero-dates-to-null) - - (:source (:type "timestamp" :auto-increment nil) - :target (:type "timestamptz" :drop-default nil :drop-not-null t) - :using pgloader.transforms::zero-dates-to-null) - - (:source (:type "date" :auto-increment nil) - :target (:type "date" :drop-default t :drop-not-null t) - :using pgloader.transforms::zero-dates-to-null) - (:source (:type "char" :typemod (= (car typemod) 1)) :target (:type "char" :drop-typemod nil)))) @@ -372,7 +366,8 @@ that would be int and int(7) or varchar and varchar(25)." ("p" "point" "point" nil "YES" nil) ("q" "char" "char(5)" nil "YES" nil) ("l" "char" "char(1)" nil "YES" nil) - ("m" "integer" "integer(4)" nil "YES" nil)))) + ("m" "integer" "integer(4)" nil "YES" nil) + ("o" "tinyint" "tinyint(1)" "0" nil nil)))) ;; ;; format-pgsql-column when given a mysql-column would call `cast' for diff --git a/test/parse/hans.goeuro.load b/test/parse/hans.goeuro.load index 06615c3..68cdd55 100644 --- a/test/parse/hans.goeuro.load +++ b/test/parse/hans.goeuro.load @@ -6,10 +6,13 @@ LOAD DATABASE CAST type datetime to timestamptz drop default drop not null using zero-dates-to-null, type date drop not null drop default using zero-dates-to-null, - column bools.a to boolean drop typemod using tinyint-to-boolean, - type char when (= precision 1) to char keep typemod, - type year to integer, - type timestamp to timestamptz drop not null using zero-dates-to-null + type timestamp to timestamptz drop not null using zero-dates-to-null, + + -- now the default for tinyint(1) + -- column bools.a to boolean drop typemod using tinyint-to-boolean, + + -- override char(1) to varchar(1), just use char(1) here. + type char when (= precision 1) to char keep typemod MATERIALIZE VIEWS d as $$