Remove copyright headers from individual scripts
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator.pm
CommitLineData
16dc9970 1package SQL::Translator;
2
16dc9970 3use strict;
478f608d 4use vars qw( $VERSION $DEFAULT_SUB $DEBUG $ERROR );
49e1eb70 5use base 'Class::Base';
c2d3a526 6
bd3c4e06 7require 5.005;
4b6a6341 8
7edba2c1 9$VERSION = '0.11007';
11ad2df9 10$DEBUG = 0 unless defined $DEBUG;
11$ERROR = "";
c2d3a526 12
13use Carp qw(carp);
11ad2df9 14
841a3f1a 15use Data::Dumper;
3015bf96 16use File::Find;
c0c4aef9 17use File::Spec::Functions qw(catfile);
11ad2df9 18use File::Basename qw(dirname);
c0c4aef9 19use IO::Dir;
3edb144c 20use SQL::Translator::Producer;
45ee6be0 21use SQL::Translator::Schema;
c0c4aef9 22
b346d8f1 23# ----------------------------------------------------------------------
24# The default behavior is to "pass through" values (note that the
25# SQL::Translator instance is the first value ($_[0]), and the stuff
26# to be parsed is the second value ($_[1])
27# ----------------------------------------------------------------------
05a56b57 28$DEFAULT_SUB = sub { $_[0]->schema } unless defined $DEFAULT_SUB;
16dc9970 29
b346d8f1 30# ----------------------------------------------------------------------
c2d3a526 31# init([ARGS])
b346d8f1 32# The constructor.
dfb4c915 33#
b346d8f1 34# new takes an optional hash of arguments. These arguments may
35# include a parser, specified with the keys "parser" or "from",
36# and a producer, specified with the keys "producer" or "to".
dfb4c915 37#
b346d8f1 38# The values that can be passed as the parser or producer are
39# given directly to the parser or producer methods, respectively.
40# See the appropriate method description below for details about
41# what each expects/accepts.
b346d8f1 42# ----------------------------------------------------------------------
c2d3a526 43sub init {
49e1eb70 44 my ( $self, $config ) = @_;
49e1eb70 45 #
b346d8f1 46 # Set the parser and producer.
ca10f295 47 #
b346d8f1 48 # If a 'parser' or 'from' parameter is passed in, use that as the
49 # parser; if a 'producer' or 'to' parameter is passed in, use that
50 # as the producer; both default to $DEFAULT_SUB.
49e1eb70 51 #
52 $self->parser ($config->{'parser'} || $config->{'from'} || $DEFAULT_SUB);
c2d3a526 53 $self->producer($config->{'producer'} || $config->{'to'} || $DEFAULT_SUB);
ca10f295 54
10f36920 55 #
56 # Set up callbacks for formatting of pk,fk,table,package names in producer
57 # MOVED TO PRODUCER ARGS
58 #
59 #$self->format_table_name($config->{'format_table_name'});
60 #$self->format_package_name($config->{'format_package_name'});
61 #$self->format_fk_name($config->{'format_fk_name'});
62 #$self->format_pk_name($config->{'format_pk_name'});
7d5bcab8 63
49e1eb70 64 #
e2158c40 65 # Set the parser_args and producer_args
49e1eb70 66 #
67 for my $pargs ( qw[ parser_args producer_args ] ) {
68 $self->$pargs( $config->{$pargs} ) if defined $config->{ $pargs };
e2158c40 69 }
70
49e1eb70 71 #
185c34d5 72 # Initialize the filters.
73 #
74 if ( $config->{filters} && ref $config->{filters} eq "ARRAY" ) {
75 $self->filters( @{$config->{filters}} )
76 || return $self->error('Error inititializing filters: '.$self->error);
77 }
78
79 #
9398955f 80 # Set the data source, if 'filename' or 'file' is provided.
49e1eb70 81 #
c2d3a526 82 $config->{'filename'} ||= $config->{'file'} || "";
49e1eb70 83 $self->filename( $config->{'filename'} ) if $config->{'filename'};
9398955f 84
49e1eb70 85 #
185c34d5 86 # Finally, if there is a 'data' parameter, use that in
49e1eb70 87 # preference to filename and file
88 #
89 if ( my $data = $config->{'data'} ) {
90 $self->data( $data );
9398955f 91 }
92
d529894e 93 #
94 # Set various other options.
95 #
49e1eb70 96 $self->{'debug'} = defined $config->{'debug'} ? $config->{'debug'} : $DEBUG;
ca10f295 97
96844cae 98 $self->add_drop_table( $config->{'add_drop_table'} );
185c34d5 99
d529894e 100 $self->no_comments( $config->{'no_comments'} );
101
96844cae 102 $self->show_warnings( $config->{'show_warnings'} );
103
104 $self->trace( $config->{'trace'} );
105
3f4af30d 106 $self->validate( $config->{'validate'} );
5e2c196a 107
108 $self->quote_table_names( (defined $config->{'quote_table_names'}
109 ? $config->{'quote_table_names'} : 1) );
110 $self->quote_field_names( (defined $config->{'quote_field_names'}
111 ? $config->{'quote_field_names'} : 1) );
3f4af30d 112
ca10f295 113 return $self;
dfb4c915 114}
1fd8c91f 115
0f3778d0 116# ----------------------------------------------------------------------
117# add_drop_table([$bool])
118# ----------------------------------------------------------------------
96844cae 119sub add_drop_table {
120 my $self = shift;
121 if ( defined (my $arg = shift) ) {
122 $self->{'add_drop_table'} = $arg ? 1 : 0;
123 }
124 return $self->{'add_drop_table'} || 0;
125}
126
0f3778d0 127# ----------------------------------------------------------------------
128# no_comments([$bool])
129# ----------------------------------------------------------------------
d529894e 130sub no_comments {
131 my $self = shift;
132 my $arg = shift;
133 if ( defined $arg ) {
134 $self->{'no_comments'} = $arg ? 1 : 0;
135 }
136 return $self->{'no_comments'} || 0;
137}
138
e2158c40 139
0f3778d0 140# ----------------------------------------------------------------------
5e2c196a 141# quote_table_names([$bool])
142# ----------------------------------------------------------------------
143sub quote_table_names {
144 my $self = shift;
145 if ( defined (my $arg = shift) ) {
146 $self->{'quote_table_names'} = $arg ? 1 : 0;
147 }
148 return $self->{'quote_table_names'} || 0;
149}
150
151# ----------------------------------------------------------------------
152# quote_field_names([$bool])
153# ----------------------------------------------------------------------
154sub quote_field_names {
155 my $self = shift;
156 if ( defined (my $arg = shift) ) {
157 $self->{'quote_field_names'} = $arg ? 1 : 0;
158 }
159 return $self->{'quote_field_names'} || 0;
160}
161
162# ----------------------------------------------------------------------
0f3778d0 163# producer([$producer_spec])
164#
165# Get or set the producer for the current translator.
166# ----------------------------------------------------------------------
ca10f295 167sub producer {
f4a59b6c 168 shift->_tool({
185c34d5 169 name => 'producer',
f4a59b6c 170 path => "SQL::Translator::Producer",
185c34d5 171 default_sub => "produce",
f4a59b6c 172 }, @_);
173}
077ebf34 174
7a8e1f51 175# ----------------------------------------------------------------------
0f3778d0 176# producer_type()
7a8e1f51 177#
e2158c40 178# producer_type is an accessor that allows producer subs to get
179# information about their origin. This is poptentially important;
ca251f03 180# since all producer subs are called as subroutine references, there is
e2158c40 181# no way for a producer to find out which package the sub lives in
182# originally, for example.
7a8e1f51 183# ----------------------------------------------------------------------
184sub producer_type { $_[0]->{'producer_type'} }
e2158c40 185
7a8e1f51 186# ----------------------------------------------------------------------
0f3778d0 187# producer_args([\%args])
7a8e1f51 188#
e2158c40 189# Arbitrary name => value pairs of paramters can be passed to a
190# producer using this method.
52b828e8 191#
0f3778d0 192# If the first argument passed in is undef, then the hash of arguments
193# is cleared; all subsequent elements are added to the hash of name,
194# value pairs stored as producer_args.
7a8e1f51 195# ----------------------------------------------------------------------
f4a59b6c 196sub producer_args { shift->_args("producer", @_); }
ca10f295 197
0f3778d0 198# ----------------------------------------------------------------------
199# parser([$parser_spec])
200# ----------------------------------------------------------------------
ca10f295 201sub parser {
f4a59b6c 202 shift->_tool({
185c34d5 203 name => 'parser',
f4a59b6c 204 path => "SQL::Translator::Parser",
185c34d5 205 default_sub => "parse",
f4a59b6c 206 }, @_);
16dc9970 207}
1fd8c91f 208
f4a59b6c 209sub parser_type { $_[0]->{'parser_type'}; }
e2158c40 210
f4a59b6c 211sub parser_args { shift->_args("parser", @_); }
96844cae 212
f4a59b6c 213# ----------------------------------------------------------------------
185c34d5 214# e.g.
215# $sqlt->filters => [
216# sub { },
217# [ "NormalizeNames", field => "lc", tabel => "ucfirst" ],
218# [
219# "DataTypeMap",
220# "TEXT" => "BIGTEXT",
221# ],
222# ],
223# ----------------------------------------------------------------------
224sub filters {
225 my $self = shift;
226 my $filters = $self->{filters} ||= [];
227 return @$filters unless @_;
228
44eb9098 229 # Set. Convert args to list of [\&code,@args]
185c34d5 230 foreach (@_) {
44eb9098 231 my ($filt,@args) = ref($_) eq "ARRAY" ? @$_ : $_;
232 if ( isa($filt,"CODE") ) {
233 push @$filters, [$filt,@args];
185c34d5 234 next;
235 }
236 else {
44eb9098 237 $self->debug("Adding $filt filter. Args:".Dumper(\@args)."\n");
238 $filt = _load_sub("$filt\::filter", "SQL::Translator::Filter")
239 || return $self->error(__PACKAGE__->error);
240 push @$filters, [$filt,@args];
185c34d5 241 }
242 }
243 return @$filters;
244}
245
246# ----------------------------------------------------------------------
96844cae 247sub show_warnings {
248 my $self = shift;
249 my $arg = shift;
250 if ( defined $arg ) {
251 $self->{'show_warnings'} = $arg ? 1 : 0;
252 }
253 return $self->{'show_warnings'} || 0;
254}
255
ca10f295 256
0f3778d0 257# filename - get or set the filename
258sub filename {
259 my $self = shift;
260 if (@_) {
261 my $filename = shift;
262 if (-d $filename) {
263 my $msg = "Cannot use directory '$filename' as input source";
264 return $self->error($msg);
f69e9da3 265 } elsif (ref($filename) eq 'ARRAY') {
266 $self->{'filename'} = $filename;
267 $self->debug("Got array of files: ".join(', ',@$filename)."\n");
0f3778d0 268 } elsif (-f _ && -r _) {
269 $self->{'filename'} = $filename;
270 $self->debug("Got filename: '$self->{'filename'}'\n");
271 } else {
272 my $msg = "Cannot use '$filename' as input source: ".
273 "file does not exist or is not readable.";
274 return $self->error($msg);
275 }
276 }
ca10f295 277
0f3778d0 278 $self->{'filename'};
279}
ca10f295 280
0f3778d0 281# ----------------------------------------------------------------------
282# data([$data])
283#
284# if $self->{'data'} is not set, but $self->{'filename'} is, then
285# $self->{'filename'} is opened and read, with the results put into
286# $self->{'data'}.
287# ----------------------------------------------------------------------
288sub data {
289 my $self = shift;
ca10f295 290
0f3778d0 291 # Set $self->{'data'} based on what was passed in. We will
292 # accept a number of things; do our best to get it right.
293 if (@_) {
294 my $data = shift;
295 if (isa($data, "SCALAR")) {
296 $self->{'data'} = $data;
297 }
298 else {
299 if (isa($data, 'ARRAY')) {
300 $data = join '', @$data;
301 }
302 elsif (isa($data, 'GLOB')) {
ca96e7ee 303 seek ($data, 0, 0) if eof ($data);
0f3778d0 304 local $/;
305 $data = <$data>;
306 }
307 elsif (! ref $data && @_) {
308 $data = join '', $data, @_;
309 }
310 $self->{'data'} = \$data;
311 }
312 }
9398955f 313
7a8e1f51 314 # If we have a filename but no data yet, populate.
9398955f 315 if (not $self->{'data'} and my $filename = $self->filename) {
49e1eb70 316 $self->debug("Opening '$filename' to get contents.\n");
9398955f 317 local *FH;
318 local $/;
319 my $data;
320
f69e9da3 321 my @files = ref($filename) eq 'ARRAY' ? @$filename : ($filename);
9398955f 322
f69e9da3 323 foreach my $file (@files) {
960b4e55 324 unless (open FH, $file) {
325 return $self->error("Can't read file '$file': $!");
326 }
9398955f 327
960b4e55 328 $data .= <FH>;
95a2cfb6 329
960b4e55 330 unless (close FH) {
331 return $self->error("Can't close file '$file': $!");
332 }
f69e9da3 333 }
95a2cfb6 334
f69e9da3 335 $self->{'data'} = \$data;
9398955f 336 }
9398955f 337
338 return $self->{'data'};
7a8e1f51 339}
9398955f 340
45ee6be0 341# ----------------------------------------------------------------------
a57ce769 342sub reset {
343#
344# Deletes the existing Schema object so that future calls to translate
345# don't append to the existing.
346#
347 my $self = shift;
348 $self->{'schema'} = undef;
349 return 1;
350}
351
352# ----------------------------------------------------------------------
45ee6be0 353sub schema {
354#
355# Returns the SQL::Translator::Schema object
356#
357 my $self = shift;
358
359 unless ( defined $self->{'schema'} ) {
47fed978 360 $self->{'schema'} = SQL::Translator::Schema->new(
10f36920 361 translator => $self,
47fed978 362 );
45ee6be0 363 }
d529894e 364
45ee6be0 365 return $self->{'schema'};
366}
367
368# ----------------------------------------------------------------------
d529894e 369sub trace {
370 my $self = shift;
371 my $arg = shift;
372 if ( defined $arg ) {
373 $self->{'trace'} = $arg ? 1 : 0;
374 }
375 return $self->{'trace'} || 0;
376}
377
378# ----------------------------------------------------------------------
0f3778d0 379# translate([source], [\%args])
380#
381# translate does the actual translation. The main argument is the
382# source of the data to be translated, which can be a filename, scalar
383# reference, or glob reference.
384#
385# Alternatively, translate takes optional arguements, which are passed
386# to the appropriate places. Most notable of these arguments are
387# parser and producer, which can be used to set the parser and
388# producer, respectively. This is the applications last chance to set
389# these.
390#
391# translate returns a string.
392# ----------------------------------------------------------------------
ca251f03 393sub translate {
394 my $self = shift;
395 my ($args, $parser, $parser_type, $producer, $producer_type);
5e2c196a 396 my ($parser_output, $producer_output, @producer_output);
ca10f295 397
7a8e1f51 398 # Parse arguments
185c34d5 399 if (@_ == 1) {
7a8e1f51 400 # Passed a reference to a hash?
ca10f295 401 if (isa($_[0], 'HASH')) {
7a8e1f51 402 # yep, a hashref
49e1eb70 403 $self->debug("translate: Got a hashref\n");
ca10f295 404 $args = $_[0];
405 }
9398955f 406
0f3778d0 407 # Passed a GLOB reference, i.e., filehandle
408 elsif (isa($_[0], 'GLOB')) {
409 $self->debug("translate: Got a GLOB reference\n");
410 $self->data($_[0]);
411 }
412
7a8e1f51 413 # Passed a reference to a string containing the data
ca10f295 414 elsif (isa($_[0], 'SCALAR')) {
9398955f 415 # passed a ref to a string
49e1eb70 416 $self->debug("translate: Got a SCALAR reference (string)\n");
9398955f 417 $self->data($_[0]);
ca10f295 418 }
9398955f 419
7a8e1f51 420 # Not a reference; treat it as a filename
b346d8f1 421 elsif (! ref $_[0]) {
ca10f295 422 # Not a ref, it's a filename
49e1eb70 423 $self->debug("translate: Got a filename\n");
9398955f 424 $self->filename($_[0]);
ca10f295 425 }
9398955f 426
7a8e1f51 427 # Passed something else entirely.
b346d8f1 428 else {
429 # We're not impressed. Take your empty string and leave.
38254289 430 # return "";
431
7a8e1f51 432 # Actually, if data, parser, and producer are set, then we
433 # can continue. Too bad, because I like my comment
434 # (above)...
38254289 435 return "" unless ($self->data &&
436 $self->producer &&
437 $self->parser);
b346d8f1 438 }
16dc9970 439 }
440 else {
b346d8f1 441 # You must pass in a hash, or you get nothing.
442 return "" if @_ % 2;
ca10f295 443 $args = { @_ };
7a8e1f51 444 }
16dc9970 445
9398955f 446 # ----------------------------------------------------------------------
447 # Can specify the data to be transformed using "filename", "file",
7a8e1f51 448 # "data", or "datasource".
9398955f 449 # ----------------------------------------------------------------------
7a8e1f51 450 if (my $filename = ($args->{'filename'} || $args->{'file'})) {
9398955f 451 $self->filename($filename);
452 }
ca10f295 453
422298aa 454 if (my $data = ($args->{'data'} || $args->{'datasource'})) {
9398955f 455 $self->data($data);
16dc9970 456 }
ca10f295 457
9398955f 458 # ----------------------------------------------------------------
459 # Get the data.
460 # ----------------------------------------------------------------
461 my $data = $self->data;
077ebf34 462
9398955f 463 # ----------------------------------------------------------------
ca10f295 464 # Local reference to the parser subroutine
9398955f 465 # ----------------------------------------------------------------
ca10f295 466 if ($parser = ($args->{'parser'} || $args->{'from'})) {
467 $self->parser($parser);
16dc9970 468 }
7a8e1f51 469 $parser = $self->parser;
470 $parser_type = $self->parser_type;
16dc9970 471
9398955f 472 # ----------------------------------------------------------------
ca10f295 473 # Local reference to the producer subroutine
9398955f 474 # ----------------------------------------------------------------
ca10f295 475 if ($producer = ($args->{'producer'} || $args->{'to'})) {
476 $self->producer($producer);
16dc9970 477 }
7a8e1f51 478 $producer = $self->producer;
479 $producer_type = $self->producer_type;
16dc9970 480
9398955f 481 # ----------------------------------------------------------------
185c34d5 482 # Execute the parser, the filters and then execute the producer.
7a8e1f51 483 # Allowances are made for each piece to die, or fail to compile,
484 # since the referenced subroutines could be almost anything. In
485 # the future, each of these might happen in a Safe environment,
486 # depending on how paranoid we want to be.
9398955f 487 # ----------------------------------------------------------------
185c34d5 488
489 # Run parser
a57ce769 490 unless ( defined $self->{'schema'} ) {
491 eval { $parser_output = $parser->($self, $$data) };
492 if ($@ || ! $parser_output) {
493 my $msg = sprintf "translate: Error with parser '%s': %s",
494 $parser_type, ($@) ? $@ : " no results";
495 return $self->error($msg);
496 }
7a8e1f51 497 }
841a3f1a 498 $self->debug("Schema =\n", Dumper($self->schema), "\n");
499
185c34d5 500 # Validate the schema if asked to.
4b6a6341 501 if ($self->validate) {
3f4af30d 502 my $schema = $self->schema;
503 return $self->error('Invalid schema') unless $schema->is_valid;
504 }
505
185c34d5 506 # Run filters
507 my $filt_num = 0;
508 foreach ($self->filters) {
509 $filt_num++;
44eb9098 510 my ($code,@args) = @$_;
511 eval { $code->($self->schema, @args) };
185c34d5 512 my $err = $@ || $self->error || 0;
513 return $self->error("Error with filter $filt_num : $err") if $err;
514 }
515
516 # Run producer
5e2c196a 517 # Calling wantarray in the eval no work, wrong scope.
518 my $wantarray = wantarray ? 1 : 0;
a83ffc24 519 eval {
520 if ($wantarray) {
521 @producer_output = $producer->($self);
522 } else {
523 $producer_output = $producer->($self);
524 }
525 };
5e2c196a 526 if ($@ || !( $producer_output || @producer_output)) {
a5d57a52 527 my $err = $@ || $self->error || "no results";
528 my $msg = "translate: Error with producer '$producer_type': $err";
c2d3a526 529 return $self->error($msg);
7a8e1f51 530 }
531
5e2c196a 532 return wantarray ? @producer_output : $producer_output;
16dc9970 533}
ca10f295 534
d529894e 535# ----------------------------------------------------------------------
0f3778d0 536# list_parsers()
537#
538# Hacky sort of method to list all available parsers. This has
539# several problems:
540#
541# - Only finds things in the SQL::Translator::Parser namespace
542#
543# - Only finds things that are located in the same directory
544# as SQL::Translator::Parser. Yeck.
545#
546# This method will fail in several very likely cases:
547#
548# - Parser modules in different namespaces
549#
550# - Parser modules in the SQL::Translator::Parser namespace that
551# have any XS componenets will be installed in
552# arch_lib/SQL/Translator.
553#
554# ----------------------------------------------------------------------
555sub list_parsers {
ca1f2237 556 return shift->_list("parser");
0f3778d0 557}
558
559# ----------------------------------------------------------------------
560# list_producers()
561#
562# See notes for list_parsers(), above; all the problems apply to
563# list_producers as well.
564# ----------------------------------------------------------------------
c0c4aef9 565sub list_producers {
ca1f2237 566 return shift->_list("producer");
0f3778d0 567}
568
c0c4aef9 569
0f3778d0 570# ======================================================================
571# Private Methods
572# ======================================================================
c0c4aef9 573
0f3778d0 574# ----------------------------------------------------------------------
575# _args($type, \%args);
576#
577# Gets or sets ${type}_args. Called by parser_args and producer_args.
578# ----------------------------------------------------------------------
579sub _args {
580 my $self = shift;
581 my $type = shift;
582 $type = "${type}_args" unless $type =~ /_args$/;
583
584 unless (defined $self->{$type} && isa($self->{$type}, 'HASH')) {
585 $self->{$type} = { };
586 }
587
588 if (@_) {
589 # If the first argument is an explicit undef (remember, we
590 # don't get here unless there is stuff in @_), then we clear
591 # out the producer_args hash.
592 if (! defined $_[0]) {
593 shift @_;
594 %{$self->{$type}} = ();
595 }
596
597 my $args = isa($_[0], 'HASH') ? shift : { @_ };
598 %{$self->{$type}} = (%{$self->{$type}}, %$args);
599 }
600
601 $self->{$type};
c0c4aef9 602}
603
d529894e 604# ----------------------------------------------------------------------
f4a59b6c 605# Does the get/set work for parser and producer. e.g.
606# return $self->_tool({
607# name => 'producer',
608# path => "SQL::Translator::Producer",
609# default_sub => "produce",
610# }, @_);
611# ----------------------------------------------------------------------
612sub _tool {
613 my ($self,$args) = (shift, shift);
614 my $name = $args->{name};
da3a97b7 615 return $self->{$name} unless @_; # get accessor
616
617 my $path = $args->{path};
618 my $default_sub = $args->{default_sub};
f4a59b6c 619 my $tool = shift;
da3a97b7 620
f4a59b6c 621 # passed an anonymous subroutine reference
622 if (isa($tool, 'CODE')) {
623 $self->{$name} = $tool;
624 $self->{"$name\_type"} = "CODE";
625 $self->debug("Got $name: code ref\n");
da3a97b7 626 }
f4a59b6c 627
da3a97b7 628 # Module name was passed directly
629 # We try to load the name; if it doesn't load, there's a
630 # possibility that it has a function name attached to it,
631 # so we give it a go.
f4a59b6c 632 else {
f4a59b6c 633 $tool =~ s/-/::/g if $tool !~ /::/;
da3a97b7 634 my ($code,$sub);
635 ($code,$sub) = _load_sub("$tool\::$default_sub", $path);
9c0bc5a5 636 unless ($code) {
637 if ( __PACKAGE__->error =~ m/Can't find module/ ) {
638 # Mod not found so try sub
639 ($code,$sub) = _load_sub("$tool", $path) unless $code;
640 die "Can't load $name subroutine '$tool' : ".__PACKAGE__->error
641 unless $code;
642 }
643 else {
644 die "Can't load $name '$tool' : ".__PACKAGE__->error;
645 }
646 }
185c34d5 647
f4a59b6c 648 # get code reference and assign
da3a97b7 649 my (undef,$module,undef) = $sub =~ m/((.*)::)?(\w+)$/;
650 $self->{$name} = $code;
651 $self->{"$name\_type"} = $sub eq "CODE" ? "CODE" : $module;
652 $self->debug("Got $name: $sub\n");
653 }
f4a59b6c 654
655 # At this point, $self->{$name} contains a subroutine
656 # reference that is ready to run
657
658 # Anything left? If so, it's args
659 my $meth = "$name\_args";
660 $self->$meth(@_) if (@_);
661
662 return $self->{$name};
663}
664
665# ----------------------------------------------------------------------
0f3778d0 666# _list($type)
667# ----------------------------------------------------------------------
668sub _list {
3015bf96 669 my $self = shift;
670 my $type = shift || return ();
ca1f2237 671 my $uctype = ucfirst lc $type;
ca1f2237 672
3015bf96 673 #
674 # First find all the directories where SQL::Translator
675 # parsers or producers (the "type") appear to live.
676 #
ca1f2237 677 load("SQL::Translator::$uctype") or return ();
678 my $path = catfile "SQL", "Translator", $uctype;
3015bf96 679 my @dirs;
ca1f2237 680 for (@INC) {
681 my $dir = catfile $_, $path;
4b6a6341 682 $self->debug("_list_${type}s searching $dir\n");
ca1f2237 683 next unless -d $dir;
3015bf96 684 push @dirs, $dir;
ca1f2237 685 }
c0c4aef9 686
3015bf96 687 #
688 # Now use File::File::find to look recursively in those
689 # directories for all the *.pm files, then present them
690 # with the slashes turned into dashes.
691 #
692 my %found;
693 find(
694 sub {
695 if ( -f && m/\.pm$/ ) {
696 my $mod = $_;
697 $mod =~ s/\.pm$//;
698 my $cur_dir = $File::Find::dir;
04db8601 699 my $base_dir = quotemeta catfile 'SQL', 'Translator', $uctype;
3015bf96 700
701 #
702 # See if the current directory is below the base directory.
703 #
704 if ( $cur_dir =~ m/$base_dir(.*)/ ) {
705 $cur_dir = $1;
706 $cur_dir =~ s!^/!!; # kill leading slash
707 $cur_dir =~ s!/!-!g; # turn other slashes into dashes
708 }
709 else {
710 $cur_dir = '';
711 }
712
713 $found{ join '-', map { $_ || () } $cur_dir, $mod } = 1;
714 }
715 },
716 @dirs
717 );
718
719 return sort { lc $a cmp lc $b } keys %found;
c0c4aef9 720}
721
d529894e 722# ----------------------------------------------------------------------
f4a59b6c 723# load(MODULE [,PATH[,PATH]...])
0f3778d0 724#
725# Loads a Perl module. Short circuits if a module is already loaded.
f4a59b6c 726#
727# MODULE - is the name of the module to load.
728#
729# PATH - optional list of 'package paths' to look for the module in. e.g
017580f4 730# If you called load('Super::Foo' => 'My', 'Other') it will
731# try to load the mod Super::Foo then My::Super::Foo then Other::Super::Foo.
f4a59b6c 732#
733# Returns package name of the module actually loaded or false and sets error.
734#
185c34d5 735# Note, you can't load a name from the root namespace (ie one without '::' in
f4a59b6c 736# it), therefore a single word name without a path fails.
0f3778d0 737# ----------------------------------------------------------------------
ca10f295 738sub load {
f4a59b6c 739 my $name = shift;
740 my @path;
741 push @path, "" if $name =~ /::/; # Empty path to check name on its own first
742 push @path, @_ if @_;
743
744 foreach (@path) {
745 my $module = $_ ? "$_\::$name" : $name;
746 my $file = $module; $file =~ s[::][/]g; $file .= ".pm";
747 __PACKAGE__->debug("Loading $name as $file\n");
748 return $module if $INC{$file}; # Already loaded
185c34d5 749
f4a59b6c 750 eval { require $file };
751 next if $@ =~ /Can't locate $file in \@INC/;
617f79f6 752 eval { $module->import() } unless $@;
017580f4 753 return __PACKAGE__->error("Error loading $name as $module : $@")
754 if $@ && $@ !~ /"SQL::Translator::Producer" is not exported/;
f4a59b6c 755
756 return $module; # Module loaded ok
757 }
ca1f2237 758
9c0bc5a5 759 return __PACKAGE__->error("Can't find module $name. Path:".join(",",@path));
da3a97b7 760}
761
762# ----------------------------------------------------------------------
763# Load the sub name given (including package), optionally using a base package
764# path. Returns code ref and name of sub loaded, including its package.
765# (\&code, $sub) = load_sub( 'MySQL::produce', "SQL::Translator::Producer" );
766# (\&code, $sub) = load_sub( 'MySQL::produce', @path );
767# ----------------------------------------------------------------------
768sub _load_sub {
769 my ($tool, @path) = @_;
185c34d5 770
da3a97b7 771 my (undef,$module,$func_name) = $tool =~ m/((.*)::)?(\w+)$/;
772 if ( my $module = load($module => @path) ) {
773 my $sub = "$module\::$func_name";
185c34d5 774 return wantarray ? ( \&{ $sub }, $sub ) : \&$sub;
775 }
da3a97b7 776 return undef;
1fd8c91f 777}
16dc9970 778
67e5ff53 779# ----------------------------------------------------------------------
7d5bcab8 780sub format_table_name {
1ea530d4 781 return shift->_format_name('_format_table_name', @_);
7d5bcab8 782}
783
67e5ff53 784# ----------------------------------------------------------------------
7d5bcab8 785sub format_package_name {
1ea530d4 786 return shift->_format_name('_format_package_name', @_);
7d5bcab8 787}
788
67e5ff53 789# ----------------------------------------------------------------------
7d5bcab8 790sub format_fk_name {
1ea530d4 791 return shift->_format_name('_format_fk_name', @_);
7d5bcab8 792}
793
67e5ff53 794# ----------------------------------------------------------------------
7d5bcab8 795sub format_pk_name {
1ea530d4 796 return shift->_format_name('_format_pk_name', @_);
797}
798
799# ----------------------------------------------------------------------
185c34d5 800# The other format_*_name methods rely on this one. It optionally
1ea530d4 801# accepts a subroutine ref as the first argument (or uses an identity
802# sub if one isn't provided or it doesn't already exist), and applies
803# it to the rest of the arguments (if any).
804# ----------------------------------------------------------------------
805sub _format_name {
f9a0c3b5 806 my $self = shift;
1ea530d4 807 my $field = shift;
808 my @args = @_;
8a990c91 809
1ea530d4 810 if (ref($args[0]) eq 'CODE') {
811 $self->{$field} = shift @args;
8a990c91 812 }
1ea530d4 813 elsif (! exists $self->{$field}) {
814 $self->{$field} = sub { return shift };
8a990c91 815 }
816
1ea530d4 817 return @args ? $self->{$field}->(@args) : $self->{$field};
7d5bcab8 818}
819
d529894e 820# ----------------------------------------------------------------------
0f3778d0 821# isa($ref, $type)
822#
823# Calls UNIVERSAL::isa($ref, $type). I think UNIVERSAL::isa is ugly,
824# but I like function overhead.
825# ----------------------------------------------------------------------
826sub isa($$) {
827 my ($ref, $type) = @_;
828 return UNIVERSAL::isa($ref, $type);
829}
c2d3a526 830
3f4af30d 831# ----------------------------------------------------------------------
c314ec98 832# version
833#
834# Returns the $VERSION of the main SQL::Translator package.
835# ----------------------------------------------------------------------
836sub version {
837 my $self = shift;
838 return $VERSION;
839}
840
841# ----------------------------------------------------------------------
3f4af30d 842sub validate {
3f4af30d 843 my ( $self, $arg ) = @_;
844 if ( defined $arg ) {
845 $self->{'validate'} = $arg ? 1 : 0;
846 }
847 return $self->{'validate'} || 0;
848}
849
16dc9970 8501;
16dc9970 851
389b318c 852# ----------------------------------------------------------------------
853# Who killed the pork chops?
854# What price bananas?
855# Are you my Angel?
856# Allen Ginsberg
857# ----------------------------------------------------------------------
858
859=pod
0f3778d0 860
861=head1 NAME
862
954f31f1 863SQL::Translator - manipulate structured data definitions (SQL and more)
0f3778d0 864
865=head1 SYNOPSIS
866
867 use SQL::Translator;
868
67e5ff53 869 my $translator = SQL::Translator->new(
870 # Print debug info
871 debug => 1,
872 # Print Parse::RecDescent trace
185c34d5 873 trace => 0,
67e5ff53 874 # Don't include comments in output
185c34d5 875 no_comments => 0,
67e5ff53 876 # Print name mutations, conflicts
185c34d5 877 show_warnings => 0,
67e5ff53 878 # Add "drop table" statements
185c34d5 879 add_drop_table => 1,
5e2c196a 880 # to quote or not to quote, thats the question
881 quote_table_names => 1,
882 quote_field_names => 1,
67e5ff53 883 # Validate schema object
185c34d5 884 validate => 1,
f9a0c3b5 885 # Make all table names CAPS in producers which support this option
67e5ff53 886 format_table_name => sub {my $tablename = shift; return uc($tablename)},
f9a0c3b5 887 # Null-op formatting, only here for documentation's sake
7d5bcab8 888 format_package_name => sub {return shift},
889 format_fk_name => sub {return shift},
890 format_pk_name => sub {return shift},
0f3778d0 891 );
892
893 my $output = $translator->translate(
389b318c 894 from => 'MySQL',
895 to => 'Oracle',
f9a0c3b5 896 # Or an arrayref of filenames, i.e. [ $file1, $file2, $file3 ]
185c34d5 897 filename => $file,
0f3778d0 898 ) or die $translator->error;
899
900 print $output;
901
902=head1 DESCRIPTION
903
2d993495 904This documentation covers the API for SQL::Translator. For a more general
905discussion of how to use the modules and scripts, please see
906L<SQL::Translator::Manual>.
907
29efc9fd 908SQL::Translator is a group of Perl modules that converts
909vendor-specific SQL table definitions into other formats, such as
910other vendor-specific SQL, ER diagrams, documentation (POD and HTML),
911XML, and Class::DBI classes. The main focus of SQL::Translator is
912SQL, but parsers exist for other structured data formats, including
913Excel spreadsheets and arbitrarily delimited text files. Through the
914separation of the code into parsers and producers with an object model
915in between, it's possible to combine any parser with any producer, to
916plug in custom parsers or producers, or to manipulate the parsed data
917via the built-in object model. Presently only the definition parts of
918SQL are handled (CREATE, ALTER), not the manipulation of data (INSERT,
919UPDATE, DELETE).
0f3778d0 920
921=head1 CONSTRUCTOR
922
5760246d 923The constructor is called C<new>, and accepts a optional hash of options.
0f3778d0 924Valid options are:
925
926=over 4
927
ca251f03 928=item *
929
930parser / from
931
932=item *
933
934parser_args
0f3778d0 935
ca251f03 936=item *
0f3778d0 937
ca251f03 938producer / to
0f3778d0 939
ca251f03 940=item *
0f3778d0 941
ca251f03 942producer_args
0f3778d0 943
ca251f03 944=item *
945
185c34d5 946filters
947
948=item *
949
ca251f03 950filename / file
951
952=item *
953
954data
955
956=item *
0f3778d0 957
ca251f03 958debug
0f3778d0 959
389b318c 960=item *
961
962add_drop_table
963
964=item *
965
5e2c196a 966quote_table_names
967
968=item *
969
970quote_field_names
971
972=item *
973
389b318c 974no_comments
975
976=item *
977
978trace
979
980=item *
981
982validate
983
0f3778d0 984=back
985
986All options are, well, optional; these attributes can be set via
987instance methods. Internally, they are; no (non-syntactical)
988advantage is gained by passing options to the constructor.
989
990=head1 METHODS
991
5760246d 992=head2 add_drop_table
0f3778d0 993
994Toggles whether or not to add "DROP TABLE" statements just before the
995create definitions.
996
5e2c196a 997=head2 quote_table_names
998
999Toggles whether or not to quote table names with " in DROP and CREATE
1000statements. The default (true) is to quote them.
1001
1002=head2 quote_field_names
1003
1004Toggles whether or not to quote field names with " in most
1005statements. The default (true), is to quote them.
1006
5760246d 1007=head2 no_comments
0f3778d0 1008
1009Toggles whether to print comments in the output. Accepts a true or false
1010value, returns the current value.
1011
5760246d 1012=head2 producer
0f3778d0 1013
5760246d 1014The C<producer> method is an accessor/mutator, used to retrieve or
0f3778d0 1015define what subroutine is called to produce the output. A subroutine
1016defined as a producer will be invoked as a function (I<not a method>)
8e1fc861 1017and passed its container C<SQL::Translator> instance, which it should
1018call the C<schema> method on, to get the C<SQL::Translator::Schema>
1019generated by the parser. It is expected that the function transform the
1020schema structure to a string. The C<SQL::Translator> instance is also useful
1021for informational purposes; for example, the type of the parser can be
5760246d 1022retrieved using the C<parser_type> method, and the C<error> and
1023C<debug> methods can be called when needed.
0f3778d0 1024
ca251f03 1025When defining a producer, one of several things can be passed in: A
5760246d 1026module name (e.g., C<My::Groovy::Producer>), a module name relative to
1027the C<SQL::Translator::Producer> namespace (e.g., C<MySQL>), a module
ca251f03 1028name and function combination (C<My::Groovy::Producer::transmogrify>),
0f3778d0 1029or a reference to an anonymous subroutine. If a full module name is
1030passed in (for the purposes of this method, a string containing "::"
1031is considered to be a module name), it is treated as a package, and a
ca251f03 1032function called "produce" will be invoked: C<$modulename::produce>.
1033If $modulename cannot be loaded, the final portion is stripped off and
0f3778d0 1034treated as a function. In other words, if there is no file named
ca251f03 1035F<My/Groovy/Producer/transmogrify.pm>, C<SQL::Translator> will attempt
5760246d 1036to load F<My/Groovy/Producer.pm> and use C<transmogrify> as the name of
1037the function, instead of the default C<produce>.
0f3778d0 1038
1039 my $tr = SQL::Translator->new;
1040
1041 # This will invoke My::Groovy::Producer::produce($tr, $data)
1042 $tr->producer("My::Groovy::Producer");
1043
1044 # This will invoke SQL::Translator::Producer::Sybase::produce($tr, $data)
1045 $tr->producer("Sybase");
1046
1047 # This will invoke My::Groovy::Producer::transmogrify($tr, $data),
1048 # assuming that My::Groovy::Producer::transmogrify is not a module
1049 # on disk.
1050 $tr->producer("My::Groovy::Producer::transmogrify");
1051
1052 # This will invoke the referenced subroutine directly, as
1053 # $subref->($tr, $data);
1054 $tr->producer(\&my_producer);
1055
5760246d 1056There is also a method named C<producer_type>, which is a string
1057containing the classname to which the above C<produce> function
0f3778d0 1058belongs. In the case of anonymous subroutines, this method returns
1059the string "CODE".
1060
5760246d 1061Finally, there is a method named C<producer_args>, which is both an
0f3778d0 1062accessor and a mutator. Arbitrary data may be stored in name => value
1063pairs for the producer subroutine to access:
1064
1065 sub My::Random::producer {
1066 my ($tr, $data) = @_;
1067 my $pr_args = $tr->producer_args();
1068
1069 # $pr_args is a hashref.
1070
5760246d 1071Extra data passed to the C<producer> method is passed to
1072C<producer_args>:
0f3778d0 1073
1074 $tr->producer("xSV", delimiter => ',\s*');
1075
1076 # In SQL::Translator::Producer::xSV:
1077 my $args = $tr->producer_args;
1078 my $delimiter = $args->{'delimiter'}; # value is ,\s*
1079
5760246d 1080=head2 parser
0f3778d0 1081
5760246d 1082The C<parser> method defines or retrieves a subroutine that will be
0f3778d0 1083called to perform the parsing. The basic idea is the same as that of
5760246d 1084C<producer> (see above), except the default subroutine name is
ca251f03 1085"parse", and will be invoked as C<$module_name::parse($tr, $data)>.
0f3778d0 1086Also, the parser subroutine will be passed a string containing the
1087entirety of the data to be parsed.
1088
1089 # Invokes SQL::Translator::Parser::MySQL::parse()
1090 $tr->parser("MySQL");
1091
1092 # Invokes My::Groovy::Parser::parse()
1093 $tr->parser("My::Groovy::Parser");
1094
1095 # Invoke an anonymous subroutine directly
1096 $tr->parser(sub {
1097 my $dumper = Data::Dumper->new([ $_[1] ], [ "SQL" ]);
1098 $dumper->Purity(1)->Terse(1)->Deepcopy(1);
1099 return $dumper->Dump;
1100 });
1101
5760246d 1102There is also C<parser_type> and C<parser_args>, which perform
1103analogously to C<producer_type> and C<producer_args>
0f3778d0 1104
185c34d5 1105=head2 filters
1106
1107Set or retreive the filters to run over the schema during the
1108translation, before the producer creates its output. Filters are sub
1109routines called, in order, with the schema object to filter as the 1st
44eb9098 1110arg and a hash of options (passed as a list) for the rest of the args.
1111They are free to do whatever they want to the schema object, which will be
1112handed to any following filters, then used by the producer.
185c34d5 1113
1114Filters are set as an array, which gives the order they run in.
1115Like parsers and producers, they can be defined by a module name, a
1116module name relative to the SQL::Translator::Filter namespace, a module
1117name and function name together or a reference to an anonymous subroutine.
1118When using a module name a function called C<filter> will be invoked in
44eb9098 1119that package to do the work.
1120
1121To pass args to the filter set it as an array ref with the 1st value giving
1122the filter (name or sub) and the rest its args. e.g.
185c34d5 1123
1124 $tr->filters(
1125 sub {
1126 my $schema = shift;
1127 # Do stuff to schema here!
1128 },
44eb9098 1129 DropFKeys,
1130 [ "Names", table => 'lc' ],
1131 [ "Foo", foo => "bar", hello => "world" ],
1132 [ "Filter5" ],
185c34d5 1133 );
1134
44eb9098 1135Although you normally set them in the constructor, which calls
185c34d5 1136through to filters. i.e.
1137
1138 my $translator = SQL::Translator->new(
1139 ...
1140 filters => [
1141 sub { ... },
44eb9098 1142 [ "Names", table => 'lc' ],
185c34d5 1143 ],
1144 ...
1145 );
1146
1147See F<t/36-filters.t> for more examples.
1148
1149Multiple set calls to filters are cumulative with new filters added to
1150the end of the current list.
1151
1152Returns the filters as a list of array refs, the 1st value being a
44eb9098 1153reference to the filter sub and the rest its args.
185c34d5 1154
5760246d 1155=head2 show_warnings
0f3778d0 1156
1157Toggles whether to print warnings of name conflicts, identifier
1158mutations, etc. Probably only generated by producers to let the user
1159know when something won't translate very smoothly (e.g., MySQL "enum"
1160fields into Oracle). Accepts a true or false value, returns the
1161current value.
1162
5760246d 1163=head2 translate
0f3778d0 1164
185c34d5 1165The C<translate> method calls the subroutine referenced by the
1166C<parser> data member, then calls any C<filters> and finally calls
1167the C<producer> sub routine (these members are described above).
1168It accepts as arguments a number of things, in key => value format,
1169including (potentially) a parser and a producer (they are passed
1170directly to the C<parser> and C<producer> methods).
0f3778d0 1171
5760246d 1172Here is how the parameter list to C<translate> is parsed:
0f3778d0 1173
1174=over
1175
1176=item *
1177
11781 argument means it's the data to be parsed; which could be a string
ca251f03 1179(filename) or a reference to a scalar (a string stored in memory), or a
0f3778d0 1180reference to a hash, which is parsed as being more than one argument
1181(see next section).
1182
1183 # Parse the file /path/to/datafile
1184 my $output = $tr->translate("/path/to/datafile");
1185
1186 # Parse the data contained in the string $data
1187 my $output = $tr->translate(\$data);
1188
1189=item *
1190
1191More than 1 argument means its a hash of things, and it might be
1192setting a parser, producer, or datasource (this key is named
1193"filename" or "file" if it's a file, or "data" for a SCALAR reference.
1194
1195 # As above, parse /path/to/datafile, but with different producers
1196 for my $prod ("MySQL", "XML", "Sybase") {
1197 print $tr->translate(
1198 producer => $prod,
1199 filename => "/path/to/datafile",
1200 );
1201 }
1202
1203 # The filename hash key could also be:
1204 datasource => \$data,
1205
1206You get the idea.
1207
1208=back
1209
5760246d 1210=head2 filename, data
0f3778d0 1211
5760246d 1212Using the C<filename> method, the filename of the data to be parsed
1213can be set. This method can be used in conjunction with the C<data>
1214method, below. If both the C<filename> and C<data> methods are
1215invoked as mutators, the data set in the C<data> method is used.
0f3778d0 1216
1217 $tr->filename("/my/data/files/create.sql");
1218
1219or:
1220
1221 my $create_script = do {
1222 local $/;
1223 open CREATE, "/my/data/files/create.sql" or die $!;
1224 <CREATE>;
1225 };
1226 $tr->data(\$create_script);
1227
5760246d 1228C<filename> takes a string, which is interpreted as a filename.
1229C<data> takes a reference to a string, which is used as the data to be
0f3778d0 1230parsed. If a filename is set, then that file is opened and read when
5760246d 1231the C<translate> method is called, as long as the data instance
0f3778d0 1232variable is not set.
1233
45ee6be0 1234=head2 schema
1235
1236Returns the SQL::Translator::Schema object.
1237
5760246d 1238=head2 trace
0f3778d0 1239
1240Turns on/off the tracing option of Parse::RecDescent.
1241
389b318c 1242=head2 validate
1243
1244Whether or not to validate the schema object after parsing and before
1245producing.
1246
c314ec98 1247=head2 version
1248
1249Returns the version of the SQL::Translator release.
1250
7a8e1f51 1251=head1 AUTHORS
16dc9970 1252
93580045 1253Alexander Hartmaier <abraxxa@cpan.org>
1254
1255Allen Day <allenday@users.sourceforge.net>
1256
1257Anders Nor Berle <berle@cpan.org>
1258
1259Andrew Moore <amoore@cpan.org>
1260
1261Ben Faga <faga@cshl.edu>
1262
1263Chris Hilton <chilton@alterpoint.com>
1264
1265Chris Mungall <cjm@fruitfly.org>
1266
1267Chris To <christot@users.sourceforge.net>
1268
1269Daniel Ruoso <daniel@ruoso.com>
1270
1271Darren Chamberlain <dlc@users.sourceforge.net>
1272
1273Dave Cash <dave@gnofn.org>
1274
1275Fabien Wernli <faxmodem@cpan.org>
1276
1277Geoff Cant <geoff@catalyst.net.nz>
1278
1279Gudmundur A. Thorisson <mummi@cshl.org>
1280
1281Guillermo Roditi <groditi@cpan.org>
1282
1283Jason Williams <smdwilliams@users.sourceforge.net>
1284
1285Jonathan Yu <jawnsy@cpan.org>
1286
1287John Goulah <jgoulah@cpan.org>
1288
1289Ken Youens-Clark <kclark@cpan.org>
1290
1291Kevin McClellan <kdmcclel@gmail.com>
1292
1293Mark Addison <grommit@users.sourceforge.net>
1294
1295Mikey Melillo <mmelillo@users.sourceforge.net>
1296
1297Moritz Onken <onken@netcubed.de>
1298
1299Paul Harrington <phrrngtn@users.sourceforge.net>
1300
1301Peter Rabbitson <ribasushi@cpan.org>
1302
1303Ross Smith II <rossta@users.sf.net>
1304
1305Ryan D Johnson <ryan@innerfence.com>
1306
1307Sam Angiuoli <angiuoli@users.sourceforge.net>
1308
1309Stephen Bennett <stephen@freenode.net>
1310
1311Stephen Clouse <stephenclouse@gmail.com>
1312
1313Wallace Reis <wreis@cpan.org>
1314
1315Ying Zhang <zyolive@yahoo.com>
1316
1317=head1 COPYRIGHT
1318
1319Copyright (c) 2002-2011 the SQL::Translator L</AUTHORS> as listed
1320above.
841a3f1a 1321
1322If you would like to contribute to the project, you can send patches
1323to the developers mailing list:
1324
1325 sqlfairy-developers@lists.sourceforge.net
1326
1327Or send us a message (with your Sourceforge username) asking to be
1328added to the project and what you'd like to contribute.
1329
93580045 1330=head1 LICENSE
16dc9970 1331
ca10f295 1332This program is free software; you can redistribute it and/or modify
1333it under the terms of the GNU General Public License as published by
1334the Free Software Foundation; version 2.
dfb4c915 1335
ca10f295 1336This program is distributed in the hope that it will be useful, but
1337WITHOUT ANY WARRANTY; without even the implied warranty of
1338MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1339General Public License for more details.
16dc9970 1340
ca10f295 1341You should have received a copy of the GNU General Public License
1342along with this program; if not, write to the Free Software
1343Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
1344USA
16dc9970 1345
87bf8a3a 1346=head1 BUGS
1347
841a3f1a 1348Please use L<http://rt.cpan.org/> for reporting bugs.
1349
1350=head1 PRAISE
1351
1352If you find this module useful, please use
1353L<http://cpanratings.perl.org/rate/?distribution=SQL-Translator> to rate it.
87bf8a3a 1354
16dc9970 1355=head1 SEE ALSO
1356
abfa405a 1357L<perl>,
1358L<SQL::Translator::Parser>,
1359L<SQL::Translator::Producer>,
389b318c 1360L<Parse::RecDescent>,
1361L<GD>,
1362L<GraphViz>,
1363L<Text::RecordParser>,
841a3f1a 1364L<Class::DBI>,
389b318c 1365L<XML::Writer>.