Add the “set not null” cast option for MySQL (#407)

Use case: Django dissuades setting NULL “on string-based fields […]
because empty string values will always be stored as empty strings, not
as NULL. If a string-based field has null=True, that means it has two
possible values for »no data«: NULL, and the empty string. In most
cases, it’s redundant to have two possible values for »no data«; the
Django convention is to use the empty string, not NULL.”.

pgloader already supports custom transformations which can be used to
replace NULL values in string-based columns with empty strings. Setting
NOT NULL constraint on those columns could possibly be achieved by
running a database query to extract their names and then generating
relevant ALTER TABLE statements, but a cast option in pgloader is a more
convenient way.
This commit is contained in:
Krzysztof Jurewicz 2016-05-18 21:50:09 +02:00 committed by Dimitri Fontaine
parent 7344e1d81e
commit 13f5821547
3 changed files with 15 additions and 5 deletions

View File

@ -1775,7 +1775,7 @@ The `database` command accepts the following clauses and options:
The spelling *keep default* explicitly prevents that behaviour and
can be used to overload the default casting rules.
- *drop not null*, *keep not null*
- *drop not null*, *keep not null*, *set not null*
When the option *drop not null* is listed, pgloader drops any
existing `NOT NULL` constraint associated with the given source
@ -1785,6 +1785,10 @@ The `database` command accepts the following clauses and options:
The spelling *keep not null* explicitly prevents that behaviour and
can be used to overload the default casting rules.
When the option *set not null* is listed, pgloader sets a `NOT NULL`
constraint on the target column regardless whether it has been set
in the source MySQL column.
- *drop typemod*, *keep typemod*
When the option *drop typemod* is listed, pgloader drops any

View File

@ -75,21 +75,26 @@
(defrule cast-drop-not-null (and kw-drop kw-not kw-null)
(:constant (list :drop-not-null t)))
(defrule cast-set-not-null (and kw-set kw-not kw-null)
(:constant (list :set-not-null t)))
(defrule cast-def (+ (or cast-to-type
cast-keep-default
cast-drop-default
cast-keep-typemod
cast-drop-typemod
cast-keep-not-null
cast-drop-not-null))
cast-drop-not-null
cast-set-not-null))
(:lambda (source)
(destructuring-bind
(&key type drop-default drop-typemod drop-not-null &allow-other-keys)
(&key type drop-default drop-typemod drop-not-null set-not-null &allow-other-keys)
(apply #'append source)
(list :type type
:drop-default drop-default
:drop-typemod drop-typemod
:drop-not-null drop-not-null))))
:drop-not-null drop-not-null
:set-not-null set-not-null))))
(defun function-name-character-p (char)
(or (member char #.(quote (coerce "/.-%" 'list)))

View File

@ -91,6 +91,7 @@
(destructuring-bind (&key type
drop-default
drop-not-null
set-not-null
(drop-typemod t)
&allow-other-keys)
target
@ -108,7 +109,7 @@
:type-name type-name
:type-mod (when (and source-typemod (not drop-typemod))
pg-typemod)
:nullable (not (and source-not-null (not drop-not-null)))
:nullable (and (not set-not-null) (or (not source-not-null) drop-not-null))
:default (when (and source-default (not drop-default))
(format-default-value source-default using))
:transform using)))