Parser::MySQL to handle CHECK CONSTRAINT
Ed J [Fri, 28 Feb 2020 23:57:03 +0000 (23:57 +0000)]
lib/SQL/Translator/Parser/MySQL.pm
lib/SQL/Translator/Producer/MySQL.pm
t/30sqlt-new-diff-mysql.t
t/data/mysql/create.sql
t/data/mysql/create2.sql

index df63744..c3a60bb 100644 (file)
@@ -700,8 +700,31 @@ primary_key : /primary/i /key/i { 1 }
 constraint : primary_key_def
     | unique_key_def
     | foreign_key_def
+    | check_def
     | <error>
 
+expr : /[^)]* \( [^)]+ \) [^)]*/x # parens, balanced one deep
+    | /[^)]+/
+
+check_def : check_def_begin '(' expr ')'
+    {
+        $return              =  {
+            supertype        => 'constraint',
+            type             => 'check',
+            name             => $item[1],
+            expression       => $item[3],
+        }
+    }
+
+check_def_begin : /constraint/i /check/i NAME
+    { $return = $item[3] }
+    |
+    /constraint/i NAME /check/i
+    { $return = $item[2] }
+    |
+    /constraint/i /check/i
+    { $return = '' }
+
 foreign_key_def : foreign_key_def_begin parens_field_list reference_definition
     {
         $return              =  {
@@ -1017,6 +1040,7 @@ sub parse {
                 name             => $cdata->{'name'},
                 type             => $cdata->{'type'},
                 fields           => $cdata->{'fields'},
+                expression       => $cdata->{'expression'},
                 reference_table  => $cdata->{'reference_table'},
                 reference_fields => $cdata->{'reference_fields'},
                 match_type       => $cdata->{'match_type'} || '',
index 9e06b54..5106dfb 100644 (file)
@@ -743,12 +743,14 @@ sub create_constraint
 
     my $reference_table_name = $generator->quote($c->reference_table);
 
-    my @fields = $c->fields or return;
+    my @fields = $c->fields;
 
     if ( $c->type eq PRIMARY_KEY ) {
+        return unless @fields;
         return 'PRIMARY KEY (' . join(", ", map { $generator->quote($_) } @fields) . ')';
     }
     elsif ( $c->type eq UNIQUE ) {
+        return unless @fields;
         return sprintf 'UNIQUE %s(%s)',
           ((defined $c->name && $c->name)
             ? $generator->quote(
@@ -760,6 +762,7 @@ sub create_constraint
         ;
     }
     elsif ( $c->type eq FOREIGN_KEY ) {
+        return unless @fields;
         #
         # Make sure FK field is indexed or MySQL complains.
         #
@@ -813,6 +816,20 @@ sub create_constraint
         }
         return $def;
     }
+    elsif ( $c->type eq CHECK_C ) {
+        my $table = $c->table;
+        my $c_name = truncate_id_uniquely( $c->name, $options->{max_id_length} || $DEFAULT_MAX_ID_LENGTH );
+
+        my $def = join(' ',
+                         'CONSTRAINT',
+                         ($c_name ? $generator->quote($c_name) : () ),
+                         'CHECK'
+                      );
+
+
+        $def .= ' ('. $c->expression . ')';
+        return $def;
+    }
 
     return undef;
 }
index ee6674e..79df23f 100644 (file)
@@ -193,6 +193,7 @@ CREATE TABLE added (
 SET foreign_key_checks=1;
 
 ALTER TABLE employee DROP FOREIGN KEY FK5302D47D93FE702E,
+                     DROP CONSTRAINT demo_constraint,
                      DROP COLUMN job_title,
                      ADD CONSTRAINT FK5302D47D93FE702E_diff FOREIGN KEY (employee_id) REFERENCES person (person_id);
 
index 642d9a2..37a3c85 100644 (file)
@@ -15,6 +15,7 @@ create table employee (
        employee_id integer,
   job_title varchar(255),
        CONSTRAINT FK5302D47D93FE702E FOREIGN KEY (employee_id) REFERENCES person (person_id),
+       CONSTRAINT `demo_constraint` CHECK (`employee_id` > 0 and `employee_id` IS NOT NULL),
        PRIMARY KEY  (position, employee_id) USING BTREE
 ) ENGINE=InnoDB;
 
index 54cf4bb..037b182 100644 (file)
@@ -16,6 +16,7 @@ create table employee (
        position varchar(50),
        employee_id INTEGER,
        CONSTRAINT FK5302D47D93FE702E_diff FOREIGN KEY (employee_id) REFERENCES person (person_id),
+       CONSTRAINT `demo_constraint` CHECK (`employee_id` > 0 and `employee_id` IS NOT NULL and `employee_id` not in (0)),
        PRIMARY KEY  (employee_id, position)
 ) ENGINE=InnoDB;