Added TTSchema producer.
Mark Addison [Thu, 7 Aug 2003 14:19:33 +0000 (14:19 +0000)]
MANIFEST
Makefile.PL
lib/SQL/Translator/Producer/TTSchema.pm [new file with mode: 0644]
t/18ttschema-producer.t [new file with mode: 0644]
t/data/template/basic.tt [new file with mode: 0644]

index 5963dfd..591ffbb 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -29,6 +29,7 @@ lib/SQL/Translator/Producer/PostgreSQL.pm
 lib/SQL/Translator/Producer/SQLite.pm
 lib/SQL/Translator/Producer/Sybase.pm
 lib/SQL/Translator/Producer/SqlfXML.pm
+lib/SQL/Translator/Producer/TTSchema.pm
 lib/SQL/Translator/Schema.pm
 lib/SQL/Translator/Schema/Constants.pm
 lib/SQL/Translator/Schema/Constraint.pm
index 5ae5a21..549808b 100644 (file)
@@ -23,8 +23,10 @@ check_version('IO::Scalar'              => 0    => 0);
 check_version('Parse::RecDescent'       => 1.94 => 0);
 check_version('Pod::Usage'              => 0    => 0);
 check_version('Spreadsheet::ParseExcel' => 0    => 1);
+check_version('Template'                => 2.10 => 1);
 check_version('Test::More'              => 0    => 0);
 check_version('Test::Exception'         => 0    => 0);
+check_version('Test::Differences'       => 0    => 1);
 check_version('Text::ParseWords'        => 0    => 0);
 check_version('Text::RecordParser'      => 0.02 => 0);
 check_version('XML::Writer'             => 0    => 1);
diff --git a/lib/SQL/Translator/Producer/TTSchema.pm b/lib/SQL/Translator/Producer/TTSchema.pm
new file mode 100644 (file)
index 0000000..dc9b64e
--- /dev/null
@@ -0,0 +1,113 @@
+package SQL::Translator::Producer::TTSchema;
+
+=pod 
+
+=head1 NAME
+
+SQL::Translator::Producer::TTSchema - Produces output using the template toolkit
+from a SQL schema.
+
+=cut
+
+
+use strict;
+use warnings;
+
+use vars qw[ $DEBUG $VERSION @EXPORT_OK ];
+#$VERSION = sprintf "%d.%02d", q$Revision: 1.1 $ =~ /(\d+)\.(\d+)/;
+$VERSION = 0.1;
+$DEBUG   = 0 unless defined $DEBUG;
+
+use Data::Dumper;
+use Exporter;
+use base qw(Exporter);
+@EXPORT_OK = qw(produce);
+
+use base qw/SQL::Translator::Producer/;  # Doesn't do anything at the mo!
+use Template;
+
+sub debug {
+    warn @_,"\n" if $DEBUG;
+}
+
+sub produce {
+    my $translator = shift;
+    local $DEBUG = $translator->debug;
+    my $scma = $translator->schema;
+    my $args = $translator->producer_args;
+    my $file = delete $args->{ttfile} or die "No template file!";
+   
+    debug "Processing template $file\n";
+    my $out;
+    my $tt = Template->new(
+        DEBUG => $DEBUG,
+        ABSOLUTE => 1, # Set so we can use from the command line sensible.
+        RELATIVE => 1, #   Maybe the cmd line code should set it! Security!
+        %$args,        # Allow any TT opts to be passed in the producer_args
+        
+    ) || die "Failed to initialize Template object: ".Template->error;
+    $tt->process($file,{ schema => $scma },\$out) 
+    or die "Error processing template '$file': ".$tt->error;
+
+    return $out;
+};
+
+1;
+
+__END__
+
+=pod
+
+=head1 SYNOPSIS
+
+  use SQL::Translator;
+  $translator = SQL::Translator->new(
+      from      => "MySQL",
+      filename  => "foo_schema.sql",
+      to        => "TT",
+      producer_args  => {
+          ttfile => "foo_template.tt",
+      },
+  );
+  print $translator->translate;
+
+=head1 DESCRIPTION
+
+Produces schema output using a given Template Tookit template.
+
+It needs one additional producer_arg of C<ttfile> that is the file name of the
+template to use. This template has one var added to it called C<schema>, which 
+is the SQL::Translator::Producer::Schema object so you can then template via 
+its methods.
+
+    database: [% schema.database %]
+    tables:
+    [% FOREACH table = schema.get_tables %]
+        [% table.name %]
+        ================
+        [% FOREACH field = table.get_fields %]
+            [% field.name %]   [% field.datatype %]([% field.size %])
+        [% END -%]
+    [% END %]
+
+See F<t/data/template/basic.tt> for a more complete example.
+
+You can also set any of the options used to initiallize the Template object by 
+adding them to your producer_args. See Template Toolkit docs for details of
+the options.
+
+  $translator = SQL::Translator->new(
+      to        => "TT",
+      producer_args  => {
+          ttfile => "foo_template.tt",
+        INCLUDE_PATH => "/foo/templates/tt",
+        INTERPOLATE => 1,
+      },
+  );
+
+=head1 TODO
+
+B<More template vars?> e.g. [% tables %] as a shortcut for
+[% schema.get_tables %].
+
+=cut
diff --git a/t/18ttschema-producer.t b/t/18ttschema-producer.t
new file mode 100644 (file)
index 0000000..a398f66
--- /dev/null
@@ -0,0 +1,192 @@
+#!/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'
+
+use Test::More;
+use Test::Exception;
+
+use Data::Dumper;
+BEGIN { our %opt; map { $opt{$_}=1 if s/^-// } @ARGV; }
+use constant DEBUG => (exists $opt{d} ? 1 : 0);
+local $SIG{__WARN__} = sub { diag "[warn] ", @_; };
+
+use FindBin qw/$Bin/;
+
+# Testing 1,2,3,4...
+#=============================================================================
+
+eval { require Template; };
+if ($@ && $@ =~ m!locate Template.pm in!) {
+    plan skip_all => "You need Template Toolkit to run this test.";
+}
+eval { require Test::Differences; };
+if ($@ && $@ =~ m!locate Test/Differences.pm in!) {
+    plan skip_all => "You need Test::Differences for this test.";
+}
+use Test::Differences;
+plan tests => 3;
+    
+use SQL::Translator;
+use SQL::Translator::Producer::TTSchema;
+
+# Parse the test XML schema
+our $obj;
+$obj = SQL::Translator->new(
+    debug          => DEBUG, #$opt{d},
+    show_warnings  => 1,
+    add_drop_table => 1,
+    from           => "SqlfXML",
+    filename       => "$Bin/data/xml/schema-basic.xml",
+    to             => "TTSchema",
+     producer_args  => {
+        ttfile => "$Bin/data/template/basic.tt",
+    },
+);
+my $out;
+lives_ok { $out = $obj->translate; }  "Produced template";
+ok $out ne ""                        ,"Output has some content";
+local $/ = undef; # slurp
+eq_or_diff $out, <DATA>              ,"Output looks right";
+# I'm sure if this diff is the best test, it is probaly too sensitive. But it
+# at least it will blow up if anything changes!
+
+print $out if DEBUG;
+#print "Debug:", Dumper($obj) if DEBUG;
+
+__DATA__
+Schema: 
+Database: 
+
+Table: Basic
+==========================================================================
+
+Fields
+    id
+        data_type:             int
+        size:                  10
+        is_nullable:           0
+        default_value:         
+        is_primary_key:        1
+        is_unique:             0
+        is_auto_increment:     1
+        is_foreign_key:        0
+        foreign_key_reference: 
+        is_valid:              1
+        order:                 1
+        extra:                 
+        table:                 Basic
+    
+    title
+        data_type:             varchar
+        size:                  100
+        is_nullable:           0
+        default_value:         hello
+        is_primary_key:        0
+        is_unique:             0
+        is_auto_increment:     0
+        is_foreign_key:        0
+        foreign_key_reference: 
+        is_valid:              1
+        order:                 2
+        extra:                 
+        table:                 Basic
+    
+    description
+        data_type:             text
+        size:                  0
+        is_nullable:           1
+        default_value:         
+        is_primary_key:        0
+        is_unique:             0
+        is_auto_increment:     0
+        is_foreign_key:        0
+        foreign_key_reference: 
+        is_valid:              1
+        order:                 3
+        extra:                 
+        table:                 Basic
+    
+    email
+        data_type:             varchar
+        size:                  255
+        is_nullable:           1
+        default_value:         
+        is_primary_key:        0
+        is_unique:             1
+        is_auto_increment:     0
+        is_foreign_key:        0
+        foreign_key_reference: 
+        is_valid:              1
+        order:                 4
+        extra:                 
+        table:                 Basic
+    
+    explicitnulldef
+        data_type:             varchar
+        size:                  0
+        is_nullable:           1
+        default_value:         
+        is_primary_key:        0
+        is_unique:             0
+        is_auto_increment:     0
+        is_foreign_key:        0
+        foreign_key_reference: 
+        is_valid:              1
+        order:                 5
+        extra:                 
+        table:                 Basic
+    
+    explicitemptystring
+        data_type:             varchar
+        size:                  0
+        is_nullable:           1
+        default_value:         
+        is_primary_key:        0
+        is_unique:             0
+        is_auto_increment:     0
+        is_foreign_key:        0
+        foreign_key_reference: 
+        is_valid:              1
+        order:                 6
+        extra:                 
+        table:                 Basic
+    
+
+Indices
+    titleindex
+        table:    Basic
+        fields:   title
+        type:     NORMAL
+        options:  
+        is_valid: 1
+    
+    
+Constraints
+    ?
+        type:             PRIMARY KEY
+        fields:           id
+        expression:       
+        match_type:       
+        reference_fields: 
+        reference_table:  
+        deferrable:       1
+        on_delete:        
+        on_update:        
+        options:          
+        is_valid:         1
+    
+    emailuniqueindex
+        type:             UNIQUE
+        fields:           email
+        expression:       
+        match_type:       
+        reference_fields: 
+        reference_table:  
+        deferrable:       1
+        on_delete:        
+        on_update:        
+        options:          
+        is_valid:         1
+    
diff --git a/t/data/template/basic.tt b/t/data/template/basic.tt
new file mode 100644 (file)
index 0000000..aaf1285
--- /dev/null
@@ -0,0 +1,51 @@
+Schema: [% schema.name %]
+Database: [% schema.database %]
+
+[%- FOREACH table = schema.get_tables %]
+Table: [% table.name %]
+==========================================================================
+
+Fields
+    [%- FOREACH field = table.get_fields %]
+    [% field.name %]
+        data_type:             [% field.data_type %]
+        size:                  [% field.size %]
+        is_nullable:           [% field.is_nullable %]
+        default_value:         [% field.default_value %]
+        is_primary_key:        [% field.is_primary_key %]
+        is_unique:             [% field.is_unique %]
+        is_auto_increment:     [% field.is_auto_increment %]
+        is_foreign_key:        [% field.is_foreign_key %]
+        foreign_key_reference: [% field.foreign_key_reference %]
+        is_valid:              [% field.is_valid %]
+        order:                 [% field.order %]
+        extra:                 [% field.extra %]
+        table:                 [% field.table.name %]
+    [% END %]
+
+Indices
+    [%- FOREACH index = table.get_indices %]
+    [% index.name %]
+        table:    [% index.table.name %]
+        fields:   [% index.fields.join(', ') %]
+        type:     [% index.type %]
+        options:  [% index.options %]
+        is_valid: [% index.is_valid %]
+    [% END %]
+    
+Constraints
+    [%- FOREACH constraint = table.get_constraints %]
+    [% constraint.name OR "?" %]
+        type:             [% constraint.type %]
+        fields:           [% constraint.fields.join(', ') %]
+        expression:       [% constraint.expression %]
+        match_type:       [% constraint.match_type %]
+        reference_fields: [% constraint.reference_fields.join(', ') %]
+        reference_table:  [% constraint.reference_table.join(', ') %]
+        deferrable:       [% constraint.deferrable %]
+        on_delete:        [% constraint.on_delete %]
+        on_update:        [% constraint.on_update %]
+        options:          [% constraint.options %]
+        is_valid:         [% constraint.is_valid %]
+    [% END -%]
+[% END %]