1 package SQL::Translator;
3 #-----------------------------------------------------
4 # $Id: Translator.pm,v 1.1.1.1 2002-03-01 02:26:25 kycl4rk Exp $
6 # File : SQL/Translator.pm
7 # Programmer : Ken Y. Clark, kclark@logsoft.com
9 # Purpose : convert schema from one database to another
10 #-----------------------------------------------------
13 use vars qw( $VERSION );
14 $VERSION = (qw$Revision: 1.1.1.1 $)[-1];
18 use SQL::Translator::Parser::MySQL;
19 use SQL::Translator::Parser::Sybase;
20 use SQL::Translator::Producer::Oracle;
21 use SQL::Translator::Producer::XML;
24 # These are the inputs we can parse.
32 # These are the formats we can produce.
39 #-----------------------------------------------------
42 # Makes a new object. Intentionally made very bare as
43 # it is used by all subclasses (unless they override,
49 return bless $self, $class;
52 #-----------------------------------------------------
55 # Return the last error.
57 return shift()->{'error'} || '';
60 #-----------------------------------------------------
63 # Record the error and return undef.
66 if ( my $error = shift ) {
67 $self->{'error'} = $error;
72 #-----------------------------------------------------
75 # Translates any number of given files.
77 my ( $self, %args ) = @_;
78 my $from = $args{'from'} || '';
79 my $to = $args{'to'} || '';
80 my $input = $args{'input'} || [];
81 my $verbose = $args{'verbose'} || 0;
82 my $no_comments = $args{'no_comments'} || 0;
84 if ( exists $parsers{ $from } ) {
85 $self->{'from'} = $from;
86 warn "Using parser '$from.'\n" if $verbose;
89 my $msg = "The parsers '$from' is not valid.\n" .
90 "Please choose from the following list:\n";
91 $msg .= " $_\n" for sort keys %parsers;
92 return $self->error_out( $msg );
95 if ( exists $producers{ $to } ) {
97 warn "Using producer '$to.'\n" if $verbose;
100 my $msg = "The producer '$to' is not valid.\n" .
101 "Please choose from the following list:\n";
102 $msg .= " $_\n" for sort keys %producers;
103 return $self->error_out( $msg );
107 # Slurp the entire text file we're parsing.
109 my $parser = $self->parser;
110 my $producer = $self->producer;
112 for my $file ( @$input ) {
113 warn "Parsing file '$file.'\n" if $verbose;
114 open my $fh, $file or return $self->error_out( "Can't read $file: $!" );
116 $data = $parser->parse( <$fh> );
119 warn "Data =\n", Dumper( $data ) if $verbose;
120 my $output = $producer->translate( $data );
123 #-----------------------------------------------------
126 # Figures out which module to load based on the "from" argument
129 unless ( $self->{'parser'} ) {
131 'SQL::Translator::Parser::'.$parsers{ $self->{'from'} };
132 $self->{'parser'} = $parser_module->new;
134 return $self->{'parser'};
137 #-----------------------------------------------------
140 # Figures out which module to load based on the "to" argument
143 unless ( $self->{'producer'} ) {
144 my $from = $parsers{ $self->{'from'} };
145 my $producer_module =
146 'SQL::Translator::Producer::'.$producers{ $self->{'to'} };
147 $self->{'producer'} = $producer_module->new( from => $from );
149 return $self->{'producer'};
154 #-----------------------------------------------------
155 # Rescue the drowning and tie your shoestrings.
156 # Henry David Thoreau
157 #-----------------------------------------------------
161 SQL::Translator - convert schema from one database to another
166 my $translator = SQL::Translator->new;
167 my $output = $translator->translate(
171 ) or die $translator->error;
176 This module attempts to simplify the task of converting one database
177 create syntax to another through the use of Parsers and Producers.
178 The idea is that any Parser can be used with any Producer in the
179 conversion process. So, if you wanted PostgreSQL-to-Oracle, you could
180 just write the PostgreSQL parser and use an existing Oracle producer.
182 Currently, the existing parsers use Parse::RecDescent, and the
183 producers are just printing formatted output of the parsed data
184 structure. New parsers don't necessarily have to use
185 Parse::RecDescent, however, as long as the data structure conforms to
186 what the producers are expecting. With this separation of code, it is
187 hoped that developers will find it easy to add more database dialects
188 by using what's written, writing only what they need, and then
189 contributing their parsers or producers back to the project.
193 Ken Y. Clark, kclark@logsoft.com