Improve trigger 'scope' attribute support (RT#119997)
[dbsrgits/SQL-Translator.git] / t / 17sqlfxml-producer.t
index 64c90c7..7989e35 100644 (file)
@@ -1,15 +1,18 @@
-#!/usr/bin/perl -w 
+#!/usr/bin/perl -w
 # vim:filetype=perl
 
 # Before `make install' is performed this script should be runnable with
 # `make test'. After `make install' it should work as `perl test.pl'
 
+local $^W = 0;
+
 use strict;
 use Test::More;
 use Test::Exception;
+use Test::SQL::Translator qw(maybe_plan);
 
 use Data::Dumper;
-our %opt;
+my %opt;
 BEGIN { map { $opt{$_}=1 if s/^-// } @ARGV; }
 use constant DEBUG => (exists $opt{d} ? 1 : 0);
 use constant TRACE => (exists $opt{t} ? 1 : 0);
@@ -18,115 +21,86 @@ use FindBin qw/$Bin/;
 
 my $file = "$Bin/data/mysql/sqlfxml-producer-basic.sql";
 
+local $SIG{__WARN__} = sub {
+    CORE::warn(@_)
+        unless $_[0] =~ m!XML/Writer!;
+};
 
 # Testing 1,2,3,4...
 #=============================================================================
 
-eval { require XML::Writer; };
-if ($@ && $@ =~ m!locate XML::Writer.pm in!) {
-    plan skip_all => "You need XML::Writer to use SqlfXML.";
-}
-eval { require Test::Differences; };
-if ($@ && $@ =~ m!locate Test/Differences.pm in!) {
-    plan skip_all => "You need Test::Differences for this test.";
+BEGIN {
+    maybe_plan(14,
+        'XML::Writer',
+        'Test::Differences',
+        'SQL::Translator::Producer::XML::SQLFairy');
 }
+
 use Test::Differences;
-plan tests => 6;
-    
 use SQL::Translator;
-use SQL::Translator::Producer::SqlfXML;
+use SQL::Translator::Producer::XML::SQLFairy;
 
-my ($obj,$ans,$xml);
+# Due to formatters being able to change style, e.g. by entries in .rc files
+# in $HOME, the layout and or indent might differ slightly. As leading white
+# is not important in XML, strip it when comparing
+sub xml_equals
+{
+    my ($got, $expect, $msg) = (@_, "XML looks right");
+    $got    =~ s/^ +//gm;
+    $expect =~ s/^ +//gm;
+    eq_or_diff $got, $expect, $msg;
+}
 
 #
-# emit_empty_tags => 0
+# basic stuff
 #
+{
+my ($obj,$ans,$xml);
 
 $ans = <<EOXML;
-<sqlt:schema xmlns:sqlt="http://sqlfairy.sourceforge.net/sqlfairy.xml">
-  <sqlt:table>
-    <sqlt:name>Basic</sqlt:name>
-    <sqlt:order>1</sqlt:order>
-    <sqlt:fields>
-      <sqlt:field>
-        <sqlt:name>id</sqlt:name>
-        <sqlt:data_type>integer</sqlt:data_type>
-        <sqlt:is_auto_increment>1</sqlt:is_auto_increment>
-        <sqlt:is_primary_key>1</sqlt:is_primary_key>
-        <sqlt:is_nullable>0</sqlt:is_nullable>
-        <sqlt:is_foreign_key>0</sqlt:is_foreign_key>
-        <sqlt:order>1</sqlt:order>
-        <sqlt:size>10</sqlt:size>
-      </sqlt:field>
-      <sqlt:field>
-        <sqlt:name>title</sqlt:name>
-        <sqlt:data_type>varchar</sqlt:data_type>
-        <sqlt:default_value>hello</sqlt:default_value>
-        <sqlt:is_auto_increment>0</sqlt:is_auto_increment>
-        <sqlt:is_primary_key>0</sqlt:is_primary_key>
-        <sqlt:is_nullable>0</sqlt:is_nullable>
-        <sqlt:is_foreign_key>0</sqlt:is_foreign_key>
-        <sqlt:order>2</sqlt:order>
-        <sqlt:size>100</sqlt:size>
-      </sqlt:field>
-      <sqlt:field>
-        <sqlt:name>description</sqlt:name>
-        <sqlt:data_type>text</sqlt:data_type>
-        <sqlt:default_value></sqlt:default_value>
-        <sqlt:is_auto_increment>0</sqlt:is_auto_increment>
-        <sqlt:is_primary_key>0</sqlt:is_primary_key>
-        <sqlt:is_nullable>1</sqlt:is_nullable>
-        <sqlt:is_foreign_key>0</sqlt:is_foreign_key>
-        <sqlt:order>3</sqlt:order>
-        <sqlt:size>0</sqlt:size>
-      </sqlt:field>
-      <sqlt:field>
-        <sqlt:name>email</sqlt:name>
-        <sqlt:data_type>varchar</sqlt:data_type>
-        <sqlt:is_auto_increment>0</sqlt:is_auto_increment>
-        <sqlt:is_primary_key>0</sqlt:is_primary_key>
-        <sqlt:is_nullable>1</sqlt:is_nullable>
-        <sqlt:is_foreign_key>0</sqlt:is_foreign_key>
-        <sqlt:order>4</sqlt:order>
-        <sqlt:size>255</sqlt:size>
-      </sqlt:field>
-    </sqlt:fields>
-    <sqlt:indices>
-      <sqlt:index>
-        <sqlt:fields>title</sqlt:fields>
-        <sqlt:name>titleindex</sqlt:name>
-        <sqlt:options></sqlt:options>
-        <sqlt:type>NORMAL</sqlt:type>
-      </sqlt:index>
-    </sqlt:indices>
-    <sqlt:constraints>
-      <sqlt:constraint>
-        <sqlt:deferrable>1</sqlt:deferrable>
-        <sqlt:expression></sqlt:expression>
-        <sqlt:fields>id</sqlt:fields>
-        <sqlt:match_type></sqlt:match_type>
-        <sqlt:name></sqlt:name>
-        <sqlt:options></sqlt:options>
-        <sqlt:on_delete></sqlt:on_delete>
-        <sqlt:on_update></sqlt:on_update>
-        <sqlt:reference_table></sqlt:reference_table>
-        <sqlt:type>PRIMARY KEY</sqlt:type>
-      </sqlt:constraint>
-      <sqlt:constraint>
-        <sqlt:deferrable>1</sqlt:deferrable>
-        <sqlt:expression></sqlt:expression>
-        <sqlt:fields>email</sqlt:fields>
-        <sqlt:match_type></sqlt:match_type>
-        <sqlt:name></sqlt:name>
-        <sqlt:options></sqlt:options>
-        <sqlt:on_delete></sqlt:on_delete>
-        <sqlt:on_update></sqlt:on_update>
-        <sqlt:reference_table></sqlt:reference_table>
-        <sqlt:type>UNIQUE</sqlt:type>
-      </sqlt:constraint>
-    </sqlt:constraints>
-  </sqlt:table>
-</sqlt:schema>
+<schema name="" database="" xmlns="http://sqlfairy.sourceforge.net/sqlfairy.xml">
+  <extra />
+  <tables>
+    <table name="Basic" order="1">
+      <extra />
+      <fields>
+        <field name="id" data_type="integer" size="10" is_nullable="0" is_auto_increment="1" is_primary_key="1" is_foreign_key="0" order="1">
+          <extra />
+          <comments>comment on id field</comments>
+        </field>
+        <field name="title" data_type="varchar" size="100" is_nullable="0" default_value="hello" is_auto_increment="0" is_primary_key="0" is_foreign_key="0" order="2">
+          <extra />
+          <comments></comments>
+        </field>
+        <field name="description" data_type="text" size="65535" is_nullable="1" default_value="" is_auto_increment="0" is_primary_key="0" is_foreign_key="0" order="3">
+          <extra />
+          <comments></comments>
+        </field>
+        <field name="email" data_type="varchar" size="255" is_nullable="1" is_auto_increment="0" is_primary_key="0" is_foreign_key="0" order="4">
+          <extra />
+          <comments></comments>
+        </field>
+      </fields>
+      <indices>
+        <index name="titleindex" type="NORMAL" fields="title" options="">
+          <extra />
+        </index>
+      </indices>
+      <constraints>
+        <constraint name="" type="PRIMARY KEY" fields="id" reference_table="" reference_fields="" on_delete="" on_update="" match_type="" expression="" options="" deferrable="1">
+          <extra />
+        </constraint>
+        <constraint name="" type="UNIQUE" fields="email" reference_table="" reference_fields="" on_delete="" on_update="" match_type="" expression="" options="" deferrable="1">
+          <extra />
+        </constraint>
+      </constraints>
+      <comments></comments>
+    </table>
+  </tables>
+  <views></views>
+  <triggers></triggers>
+  <procedures></procedures>
+</schema>
 EOXML
 
 $obj = SQL::Translator->new(
@@ -135,137 +109,261 @@ $obj = SQL::Translator->new(
     show_warnings  => 1,
     add_drop_table => 1,
     from           => "MySQL",
-    to             => "SqlfXML",
+    to             => "XML-SQLFairy",
 );
-lives_ok { $xml = $obj->translate($file); }  "Translate ran";
+$xml = $obj->translate($file) or die $obj->error;
 ok("$xml" ne ""                             ,"Produced something!");
 print "XML:\n$xml" if DEBUG;
 # Strip sqlf header with its variable date so we diff safely
-$xml =~ s/^([^\n]*\n){7}//m; 
-eq_or_diff $xml, $ans                       ,"XML looks right";
+$xml =~ s/^([^\n]*\n){7}//m;
+xml_equals $xml, $ans;
+
+} # end basic stuff
 
 #
-# emit_empty_tags => 1
+# View
 #
+# Thanks to Ken for the schema setup lifted from 13schema.t
+{
+my ($obj,$ans,$xml);
 
 $ans = <<EOXML;
-<sqlt:schema xmlns:sqlt="http://sqlfairy.sourceforge.net/sqlfairy.xml">
-  <sqlt:table>
-    <sqlt:name>Basic</sqlt:name>
-    <sqlt:order>2</sqlt:order>
-    <sqlt:fields>
-      <sqlt:field>
-        <sqlt:name>id</sqlt:name>
-        <sqlt:data_type>integer</sqlt:data_type>
-        <sqlt:default_value></sqlt:default_value>
-        <sqlt:is_auto_increment>1</sqlt:is_auto_increment>
-        <sqlt:is_primary_key>1</sqlt:is_primary_key>
-        <sqlt:is_nullable>0</sqlt:is_nullable>
-        <sqlt:is_foreign_key>0</sqlt:is_foreign_key>
-        <sqlt:order>5</sqlt:order>
-        <sqlt:size>10</sqlt:size>
-      </sqlt:field>
-      <sqlt:field>
-        <sqlt:name>title</sqlt:name>
-        <sqlt:data_type>varchar</sqlt:data_type>
-        <sqlt:default_value>hello</sqlt:default_value>
-        <sqlt:is_auto_increment>0</sqlt:is_auto_increment>
-        <sqlt:is_primary_key>0</sqlt:is_primary_key>
-        <sqlt:is_nullable>0</sqlt:is_nullable>
-        <sqlt:is_foreign_key>0</sqlt:is_foreign_key>
-        <sqlt:order>6</sqlt:order>
-        <sqlt:size>100</sqlt:size>
-      </sqlt:field>
-      <sqlt:field>
-        <sqlt:name>description</sqlt:name>
-        <sqlt:data_type>text</sqlt:data_type>
-        <sqlt:default_value></sqlt:default_value>
-        <sqlt:is_auto_increment>0</sqlt:is_auto_increment>
-        <sqlt:is_primary_key>0</sqlt:is_primary_key>
-        <sqlt:is_nullable>1</sqlt:is_nullable>
-        <sqlt:is_foreign_key>0</sqlt:is_foreign_key>
-        <sqlt:order>7</sqlt:order>
-        <sqlt:size>0</sqlt:size>
-      </sqlt:field>
-      <sqlt:field>
-        <sqlt:name>email</sqlt:name>
-        <sqlt:data_type>varchar</sqlt:data_type>
-        <sqlt:default_value></sqlt:default_value>
-        <sqlt:is_auto_increment>0</sqlt:is_auto_increment>
-        <sqlt:is_primary_key>0</sqlt:is_primary_key>
-        <sqlt:is_nullable>1</sqlt:is_nullable>
-        <sqlt:is_foreign_key>0</sqlt:is_foreign_key>
-        <sqlt:order>8</sqlt:order>
-        <sqlt:size>255</sqlt:size>
-      </sqlt:field>
-    </sqlt:fields>
-    <sqlt:indices>
-      <sqlt:index>
-        <sqlt:fields>title</sqlt:fields>
-        <sqlt:name>titleindex</sqlt:name>
-        <sqlt:options></sqlt:options>
-        <sqlt:type>NORMAL</sqlt:type>
-      </sqlt:index>
-    </sqlt:indices>
-    <sqlt:constraints>
-      <sqlt:constraint>
-        <sqlt:deferrable>1</sqlt:deferrable>
-        <sqlt:expression></sqlt:expression>
-        <sqlt:fields>id</sqlt:fields>
-        <sqlt:match_type></sqlt:match_type>
-        <sqlt:name></sqlt:name>
-        <sqlt:options></sqlt:options>
-        <sqlt:on_delete></sqlt:on_delete>
-        <sqlt:on_update></sqlt:on_update>
-        <sqlt:reference_fields></sqlt:reference_fields>
-        <sqlt:reference_table></sqlt:reference_table>
-        <sqlt:type>PRIMARY KEY</sqlt:type>
-      </sqlt:constraint>
-      <sqlt:constraint>
-        <sqlt:deferrable>1</sqlt:deferrable>
-        <sqlt:expression></sqlt:expression>
-        <sqlt:fields>email</sqlt:fields>
-        <sqlt:match_type></sqlt:match_type>
-        <sqlt:name></sqlt:name>
-        <sqlt:options></sqlt:options>
-        <sqlt:on_delete></sqlt:on_delete>
-        <sqlt:on_update></sqlt:on_update>
-        <sqlt:reference_fields></sqlt:reference_fields>
-        <sqlt:reference_table></sqlt:reference_table>
-        <sqlt:type>UNIQUE</sqlt:type>
-      </sqlt:constraint>
-    </sqlt:constraints>
-  </sqlt:table>
-</sqlt:schema>
+<schema name="" database="" xmlns="http://sqlfairy.sourceforge.net/sqlfairy.xml">
+  <extra />
+  <tables></tables>
+  <views>
+    <view name="foo_view" fields="name,age" order="1">
+      <sql>select name, age from person</sql>
+      <extra hello="world" />
+    </view>
+  </views>
+  <triggers></triggers>
+  <procedures></procedures>
+</schema>
 EOXML
 
-undef $obj;
-$obj = SQL::Translator->new(
-    debug          => DEBUG,
-    trace          => TRACE,
-    show_warnings  => 1,
-    add_drop_table => 1,
-    from           => "MySQL",
-    to             => "SqlfXML",
-    producer_args  => { emit_empty_tags => 1 },
-);
-lives_ok { $xml = $obj->translate($file); }  "Translate ran";
-ok("$xml" ne ""                             ,"Produced something!");
-print "XML emit_empty_tags=>1:\n$xml" if DEBUG;
-# Strip sqlf header with its variable date so we diff safely
-$xml =~ s/^([^\n]*\n){7}//m; 
-eq_or_diff $xml, $ans                       ,"XML looks right";
-    # This diff probably isn't a very good test! Should really check the
-    # result with XPath or something, but that would take ages to write ;-)
+    $obj = SQL::Translator->new(
+        debug          => DEBUG,
+        trace          => TRACE,
+        show_warnings  => 1,
+        add_drop_table => 1,
+        from           => "MySQL",
+        to             => "XML-SQLFairy",
+    );
+    my $s      = $obj->schema;
+    my $name   = 'foo_view';
+    my $sql    = 'select name, age from person';
+    my $fields = 'name, age';
+    my $v      = $s->add_view(
+        name   => $name,
+        sql    => $sql,
+        fields => $fields,
+        extra  => { hello => "world" },
+        schema => $s,
+    ) or die $s->error;
 
-#print "Debug:", Dumper($obj) if DEBUG;
-$obj = SQL::Translator->new(
-    debug          => DEBUG,
-    trace          => TRACE,
-    show_warnings  => 1,
-    add_drop_table => 1,
-    from           => "MySQL",
-    to             => "SqlfXML",
-    producer_args  => { emit_empty_tags => 0 },
-);
-print $obj->translate("/home/grommit/src/NADS-build/sql/document.mysql.sql");
+    # As we have created a Schema we give translate a dummy string so that
+    # it will run the produce.
+    lives_ok {$xml =$obj->translate("FOO");} "Translate (View) ran";
+    ok("$xml" ne ""                             ,"Produced something!");
+    print "XML attrib_values=>1:\n$xml" if DEBUG;
+    # Strip sqlf header with its variable date so we diff safely
+    $xml =~ s/^([^\n]*\n){7}//m;
+    xml_equals $xml, $ans;
+} # end View
+
+#
+# Trigger
+#
+# Thanks to Ken for the schema setup lifted from 13schema.t
+{
+my ($obj,$ans,$xml);
+
+$ans = <<EOXML;
+<schema name="" database="" xmlns="http://sqlfairy.sourceforge.net/sqlfairy.xml">
+  <extra />
+  <tables>
+    <table name="Basic" order="1">
+      <extra />
+      <fields></fields>
+      <indices></indices>
+      <constraints></constraints>
+      <comments></comments>
+    </table>
+  </tables>
+  <views></views>
+  <triggers>
+    <trigger name="foo_trigger" database_events="insert" on_table="Basic" perform_action_when="after" order="1" scope="row">
+      <action>update modified=timestamp();</action>
+      <extra hello="world" />
+    </trigger>
+  </triggers>
+  <procedures></procedures>
+</schema>
+EOXML
+
+    $obj = SQL::Translator->new(
+        debug          => DEBUG,
+        trace          => TRACE,
+        show_warnings  => 1,
+        add_drop_table => 1,
+        from           => "MySQL",
+        to             => "XML-SQLFairy",
+    );
+    my $s                   = $obj->schema;
+    my $name                = 'foo_trigger';
+    my $perform_action_when = 'after';
+    my $database_event      = 'insert';
+    my $action              = 'update modified=timestamp();';
+    my $table = $s->add_table( name => "Basic" ) or die $s->error;
+    my $t                   = $s->add_trigger(
+        name                => $name,
+        perform_action_when => $perform_action_when,
+        database_events     => [$database_event],
+        table               => $table,
+        action              => $action,
+        scope               => 'row',
+        extra               => { hello => "world" },
+    ) or die $s->error;
+
+    # As we have created a Schema we give translate a dummy string so that
+    # it will run the produce.
+    lives_ok {$xml =$obj->translate("FOO");} "Translate (Trigger) ran";
+    ok("$xml" ne ""                             ,"Produced something!");
+    print "XML attrib_values=>1:\n$xml" if DEBUG;
+    # Strip sqlf header with its variable date so we diff safely
+    $xml =~ s/^([^\n]*\n){7}//m;
+    xml_equals $xml, $ans;
+} # end Trigger
+
+#
+# Procedure
+#
+# Thanks to Ken for the schema setup lifted from 13schema.t
+{
+my ($obj,$ans,$xml);
+
+$ans = <<EOXML;
+<schema name="" database="" xmlns="http://sqlfairy.sourceforge.net/sqlfairy.xml">
+  <extra />
+  <tables></tables>
+  <views></views>
+  <triggers></triggers>
+  <procedures>
+    <procedure name="foo_proc" parameters="foo,bar" owner="Nomar" order="1">
+      <sql>select foo from bar</sql>
+      <comments>Go Sox!</comments>
+      <extra hello="world" />
+    </procedure>
+  </procedures>
+</schema>
+EOXML
+
+    $obj = SQL::Translator->new(
+        debug          => DEBUG,
+        trace          => TRACE,
+        show_warnings  => 1,
+        add_drop_table => 1,
+        from           => "MySQL",
+        to             => "XML-SQLFairy",
+    );
+    my $s          = $obj->schema;
+    my $name       = 'foo_proc';
+    my $sql        = 'select foo from bar';
+    my $parameters = 'foo, bar';
+    my $owner      = 'Nomar';
+    my $comments   = 'Go Sox!';
+    my $p          = $s->add_procedure(
+        name       => $name,
+        sql        => $sql,
+        parameters => $parameters,
+        owner      => $owner,
+        comments   => $comments,
+        extra      => { hello => "world" },
+    ) or die $s->error;
+
+    # As we have created a Schema we give translate a dummy string so that
+    # it will run the produce.
+    lives_ok {$xml =$obj->translate("FOO");} "Translate (Procedure) ran";
+    ok("$xml" ne ""                             ,"Produced something!");
+    print "XML attrib_values=>1:\n$xml" if DEBUG;
+    # Strip sqlf header with its variable date so we diff safely
+    $xml =~ s/^([^\n]*\n){7}//m;
+    xml_equals $xml, $ans;
+} # end Procedure
+
+#
+# Field.extra
+#
+{
+my ($obj,$ans,$xml);
+
+$ans = <<EOXML;
+<schema name="" database="" xmlns="http://sqlfairy.sourceforge.net/sqlfairy.xml">
+  <extra />
+  <tables>
+    <table name="Basic" order="1">
+      <extra />
+      <fields>
+        <field name="foo" data_type="integer" size="10" is_nullable="1" is_auto_increment="0" is_primary_key="0" is_foreign_key="0" order="1">
+          <extra ZEROFILL="1" />
+          <comments></comments>
+        </field>
+        <field name="bar" data_type="numeric" size="10,2" is_nullable="1" is_auto_increment="0" is_primary_key="0" is_foreign_key="0" order="2">
+          <extra />
+          <comments></comments>
+        </field>
+        <field name="baz" data_type="decimal" size="8,3" is_nullable="1" is_auto_increment="0" is_primary_key="0" is_foreign_key="0" order="3">
+          <extra />
+          <comments></comments>
+        </field>
+      </fields>
+      <indices></indices>
+      <constraints></constraints>
+      <comments></comments>
+    </table>
+  </tables>
+  <views></views>
+  <triggers></triggers>
+  <procedures></procedures>
+</schema>
+EOXML
+
+    $obj = SQL::Translator->new(
+        debug          => DEBUG,
+        trace          => TRACE,
+        show_warnings  => 1,
+        add_drop_table => 1,
+        from           => "MySQL",
+        to             => "XML-SQLFairy",
+    );
+    my $s = $obj->schema;
+    my $t = $s->add_table( name => "Basic" ) or die $s->error;
+    my $f = $t->add_field(
+        name      => "foo",
+        data_type => "integer",
+        size      => "10",
+    ) or die $t->error;
+    $f->extra(ZEROFILL => "1");
+
+    $t->add_field(
+        name      => "bar",
+        data_type => "numeric",
+        size      => "10,2",
+    ) or die $t->error;
+    $t->add_field(
+        name      => "baz",
+        data_type => "decimal",
+        size      => [8,3],
+    ) or die $t->error;
+
+
+    # As we have created a Schema we give translate a dummy string so that
+    # it will run the produce.
+    lives_ok {$xml =$obj->translate("FOO");} "Translate (Field.extra) ran";
+    ok("$xml" ne ""                             ,"Produced something!");
+    print "XML:\n$xml" if DEBUG;
+    # Strip sqlf header with its variable date so we diff safely
+    $xml =~ s/^([^\n]*\n){7}//m;
+    xml_equals $xml, $ans;
+} # end extra