Reverted to a version 1.1, due to botched branch attempt.
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator.pm
CommitLineData
16dc9970 1package SQL::Translator;
2
3#-----------------------------------------------------
dfb4c915 4# $Id: Translator.pm,v 1.3 2002-03-07 14:11:40 dlc Exp $
1fd8c91f 5#
dfb4c915 6# File : SQL/Translator.pm
7# Programmer : Ken Y. Clark, kclark@logsoft.com
8# Created : 2002/02/27
9# Purpose : convert schema from one database to another
10#-----------------------------------------------------
16dc9970 11
12use strict;
dfb4c915 13use vars qw( $VERSION );
14$VERSION = (qw$Revision: 1.3 $)[-1];
16dc9970 15
dfb4c915 16use Data::Dumper;
16dc9970 17
dfb4c915 18use SQL::Translator::Parser::MySQL;
19use SQL::Translator::Parser::Sybase;
20use SQL::Translator::Producer::Oracle;
21use SQL::Translator::Producer::XML;
16dc9970 22
dfb4c915 23#
24# These are the inputs we can parse.
25#
26my %parsers = (
27 mysql => 'MySQL',
28 sybase => 'Sybase',
29);
1fd8c91f 30
dfb4c915 31#
32# These are the formats we can produce.
33#
34my %producers = (
35 oracle => 'Oracle',
36 xml => 'XML',
37);
16dc9970 38
dfb4c915 39#-----------------------------------------------------
16dc9970 40sub new {
dfb4c915 41#
42# Makes a new object. Intentionally made very bare as
43# it is used by all subclasses (unless they override,
44# of course).
45#
16dc9970 46 my $class = shift;
dfb4c915 47 my %args = @_;
48 my $self = { %args };
49 return bless $self, $class;
16dc9970 50}
1fd8c91f 51
dfb4c915 52#-----------------------------------------------------
53sub error {
54#
55# Return the last error.
56#
57 return shift()->{'error'} || '';
58}
1fd8c91f 59
dfb4c915 60#-----------------------------------------------------
61sub error_out {
62#
63# Record the error and return undef.
64#
1fd8c91f 65 my $self = shift;
dfb4c915 66 if ( my $error = shift ) {
67 $self->{'error'} = $error;
1fd8c91f 68 }
dfb4c915 69 return;
16dc9970 70}
1fd8c91f 71
dfb4c915 72#-----------------------------------------------------
16dc9970 73sub translate {
dfb4c915 74#
75# Translates any number of given files.
76#
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;
83
84 if ( exists $parsers{ $from } ) {
85 $self->{'from'} = $from;
86 warn "Using parser '$from.'\n" if $verbose;
16dc9970 87 }
88 else {
dfb4c915 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 );
16dc9970 93 }
94
dfb4c915 95 if ( exists $producers{ $to } ) {
96 $self->{'to'} = $to;
97 warn "Using producer '$to.'\n" if $verbose;
16dc9970 98 }
dfb4c915 99 else {
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 );
16dc9970 104 }
105
106 #
dfb4c915 107 # Slurp the entire text file we're parsing.
16dc9970 108 #
dfb4c915 109 my $parser = $self->parser;
110 my $producer = $self->producer;
111 my $data;
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: $!" );
115 local $/;
116 $data = $parser->parse( <$fh> );
16dc9970 117 }
118
dfb4c915 119 warn "Data =\n", Dumper( $data ) if $verbose;
120 my $output = $producer->translate( $data );
16dc9970 121}
122
123#-----------------------------------------------------
dfb4c915 124sub parser {
16dc9970 125#
dfb4c915 126# Figures out which module to load based on the "from" argument
16dc9970 127#
128 my $self = shift;
dfb4c915 129 unless ( $self->{'parser'} ) {
130 my $parser_module =
131 'SQL::Translator::Parser::'.$parsers{ $self->{'from'} };
132 $self->{'parser'} = $parser_module->new;
16dc9970 133 }
dfb4c915 134 return $self->{'parser'};
16dc9970 135}
1fd8c91f 136
dfb4c915 137#-----------------------------------------------------
138sub producer {
139#
140# Figures out which module to load based on the "to" argument
141#
16dc9970 142 my $self = shift;
dfb4c915 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 );
148 }
149 return $self->{'producer'};
1fd8c91f 150}
16dc9970 151
1521;
153
154#-----------------------------------------------------
155# Rescue the drowning and tie your shoestrings.
156# Henry David Thoreau
157#-----------------------------------------------------
158
dfb4c915 159=head1 NAME
16dc9970 160
dfb4c915 161SQL::Translator - convert schema from one database to another
16dc9970 162
dfb4c915 163=head1 SYNOPSIS
16dc9970 164
dfb4c915 165 use SQL::Translator;
166 my $translator = SQL::Translator->new;
167 my $output = $translator->translate(
168 from => 'mysql',
169 to => 'oracle',
170 file => $file,
171 ) or die $translator->error;
172 print $output;
173
174=head1 DESCRIPTION
16dc9970 175
dfb4c915 176This module attempts to simplify the task of converting one database
177create syntax to another through the use of Parsers and Producers.
178The idea is that any Parser can be used with any Producer in the
179conversion process. So, if you wanted PostgreSQL-to-Oracle, you could
180just write the PostgreSQL parser and use an existing Oracle producer.
181
182Currently, the existing parsers use Parse::RecDescent, and the
183producers are just printing formatted output of the parsed data
184structure. New parsers don't necessarily have to use
185Parse::RecDescent, however, as long as the data structure conforms to
186what the producers are expecting. With this separation of code, it is
187hoped that developers will find it easy to add more database dialects
188by using what's written, writing only what they need, and then
189contributing their parsers or producers back to the project.
190
191=head1 AUTHOR
16dc9970 192
dfb4c915 193Ken Y. Clark, kclark@logsoft.com
16dc9970 194
195=head1 SEE ALSO
196
dfb4c915 197perl(1).
16dc9970 198
199=cut