Add views to mysql producer, thanks groditi
Jess Robinson [Tue, 19 Aug 2008 15:14:43 +0000 (15:14 +0000)]
Changes
lib/SQL/Translator/Producer/MySQL.pm
t/38-mysql-producer.t

diff --git a/Changes b/Changes
index b76a343..7174cdf 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,4 +1,5 @@
 
+* Added support for CREATE VIEW + tests in the mysql producer (groditi)
 * Added support for SET fields in the mysql producer + test (groditi)
 * Added support for proper booleans in the mysql producer, when a mysql version of at least 4.x is supplied
 * Added support for proper enums under pg (as of 8.3), with pg version check, and deferrable constraints
index 0ec71f1..7cf24c0 100644 (file)
@@ -286,12 +286,69 @@ sub produce {
                                          });
     }
 
+    for my $view ( $schema->get_views ) {
+#        print $view->name, "\n";
+        push @table_defs, create_view($view,
+                                       { add_replace_view  => $add_drop_table,
+                                         show_warnings     => $show_warnings,
+                                         no_comments       => $no_comments,
+                                         quote_table_names => $qt,
+                                         quote_field_names => $qf,
+                                         max_id_length     => $max_id_length,
+                                         mysql_version     => $mysql_version
+                                         });
+    }
+
+
 #    print "@table_defs\n";
     push @table_defs, "SET foreign_key_checks=1;\n\n";
 
     return wantarray ? ($create, @table_defs) : $create . join ('', @table_defs);
 }
 
+sub create_view {
+    my ($view, $options) = @_;
+    my $qt = $options->{quote_table_names} || '';
+    my $qf = $options->{quote_field_names} || '';
+
+    my $view_name = $view->name;
+    debug("PKG: Looking at view '${view_name}'\n");
+
+    # Header.  Should this look like what mysqldump produces?
+    my $create = '';
+    $create .= "--\n-- View: ${qt}${view_name}${qt}\n--\n" unless $options->{no_comments};
+    $create .= 'CREATE';
+    $create .= ' OR REPLACE' if $options->{add_replace_view};
+    $create .= "\n";
+
+    my $extra = $view->extra;
+    # ALGORITHM
+    if( exists($extra->{mysql_algorithm}) && defined(my $algorithm = $extra->{mysql_algorithm}) ){
+      $create .= "   ALGORITHM = ${algorithm}\n" if $algorithm =~ /(?:UNDEFINED|MERGE|TEMPTABLE)/i;
+    }
+    # DEFINER
+    if( exists($extra->{mysql_definer}) && defined(my $user = $extra->{mysql_definer}) ){
+      $create .= "   DEFINER = ${user}\n";
+    }
+    # SECURITY
+    if( exists($extra->{mysql_security}) && defined(my $security = $extra->{mysql_security}) ){
+      $create .= "   SQL SECURITY ${security}\n" if $security =~ /(?:DEFINER|INVOKER)/i;
+    }
+
+    #Header, cont.
+    $create .= "  VIEW ${qt}${view_name}${qt}";
+
+    if( my @fields = $view->fields ){
+      my $list = join ', ', map { "${qf}${_}${qf}"} @fields;
+      $create .= " ( ${list} )";
+    }
+    if( my $sql = $view->sql ){
+      $create .= " AS (\n    ${sql}\n  )";
+    }
+    $create .= ";\n\n";
+    return $create;
+}
+
 sub create_table
 {
     my ($table, $options) = @_;
index 39b127e..50eb682 100644 (file)
@@ -19,7 +19,7 @@ use FindBin qw/$Bin/;
 #=============================================================================
 
 BEGIN {
-    maybe_plan(14,
+    maybe_plan(16,
         'YAML',
         'SQL::Translator::Producer::MySQL',
         'Test::Differences',
@@ -261,3 +261,39 @@ $field3_sql = SQL::Translator::Producer::MySQL::create_field($field3, { mysql_ve
 is($field3_sql, "myfield enum('0','1') NOT NULL", 'For Mysql < 4, use enum for boolean type');
 $field3_sql = SQL::Translator::Producer::MySQL::create_field($field3,);
 is($field3_sql, "myfield enum('0','1') NOT NULL", 'When no version specified, use enum for boolean type');
+
+{
+  my $view1 = SQL::Translator::Schema::View->new( name => 'view_foo',
+                                                  fields => [qw/id name/],
+                                                  sql => 'SELECT id, name FROM thing',
+                                                  extra => {
+                                                    mysql_definer => 'CURRENT_USER',
+                                                    mysql_algorithm => 'MERGE',
+                                                    mysql_security => 'DEFINER',
+                                                  });
+  my $create_opts = { add_replace_view => 1, no_comments => 1 };
+  my $view1_sql1 = SQL::Translator::Producer::MySQL::create_view($view1, $create_opts);
+
+  my $view_sql_replace = "CREATE OR REPLACE
+   ALGORITHM = MERGE
+   DEFINER = CURRENT_USER
+   SQL SECURITY DEFINER
+  VIEW view_foo ( id, name ) AS (
+    SELECT id, name FROM thing
+  );\n\n";
+  is($view1_sql1, $view_sql_replace, 'correct "CREATE OR REPLACE VIEW" SQL');
+
+
+  my $view2 = SQL::Translator::Schema::View->new( name => 'view_foo',
+                                                  fields => [qw/id name/],
+                                                  sql => 'SELECT id, name FROM thing',);
+  my $create2_opts = { add_replace_view => 0, no_comments => 1 };
+  my $view1_sql2 = SQL::Translator::Producer::MySQL::create_view($view2, $create2_opts);
+  my $view_sql_noreplace = "CREATE
+  VIEW view_foo ( id, name ) AS (
+    SELECT id, name FROM thing
+  );\n\n";
+  is($view1_sql2, $view_sql_noreplace, 'correct "CREATE VIEW" SQL');
+}
+
+