Adding new GraphViz producer.
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator.pm
CommitLineData
16dc9970 1package SQL::Translator;
2
b346d8f1 3# ----------------------------------------------------------------------
95a2cfb6 4# $Id: Translator.pm,v 1.23 2003-04-19 23:32:34 allenday Exp $
b346d8f1 5# ----------------------------------------------------------------------
abfa405a 6# Copyright (C) 2003 Ken Y. Clark <kclark@cpan.org>,
7# darren chamberlain <darren@cpan.org>,
8# Chris Mungall <cjm@fruitfly.org>
1fd8c91f 9#
077ebf34 10# This program is free software; you can redistribute it and/or
11# modify it under the terms of the GNU General Public License as
12# published by the Free Software Foundation; version 2.
ca10f295 13#
077ebf34 14# This program is distributed in the hope that it will be useful, but
15# WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17# General Public License for more details.
ca10f295 18#
077ebf34 19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22# 02111-1307 USA
ca10f295 23# -------------------------------------------------------------------
24
16dc9970 25use strict;
d529894e 26use vars qw( $VERSION $REVISION $DEFAULT_SUB $DEBUG $ERROR );
49e1eb70 27use base 'Class::Base';
c2d3a526 28
d529894e 29$VERSION = '0.01';
95a2cfb6 30$REVISION = sprintf "%d.%02d", q$Revision: 1.23 $ =~ /(\d+)\.(\d+)/;
d529894e 31$DEBUG = 0 unless defined $DEBUG;
32$ERROR = "";
c2d3a526 33
34use Carp qw(carp);
16dc9970 35
c0c4aef9 36use File::Spec::Functions qw(catfile);
37use File::Basename qw(dirname);
38use IO::Dir;
39
b346d8f1 40# ----------------------------------------------------------------------
41# The default behavior is to "pass through" values (note that the
42# SQL::Translator instance is the first value ($_[0]), and the stuff
43# to be parsed is the second value ($_[1])
44# ----------------------------------------------------------------------
45$DEFAULT_SUB = sub { $_[1] } unless defined $DEFAULT_SUB;
16dc9970 46
b346d8f1 47# ----------------------------------------------------------------------
c2d3a526 48# init([ARGS])
b346d8f1 49# The constructor.
dfb4c915 50#
b346d8f1 51# new takes an optional hash of arguments. These arguments may
52# include a parser, specified with the keys "parser" or "from",
53# and a producer, specified with the keys "producer" or "to".
dfb4c915 54#
b346d8f1 55# The values that can be passed as the parser or producer are
56# given directly to the parser or producer methods, respectively.
57# See the appropriate method description below for details about
58# what each expects/accepts.
b346d8f1 59# ----------------------------------------------------------------------
c2d3a526 60sub init {
49e1eb70 61 my ( $self, $config ) = @_;
1fd8c91f 62
49e1eb70 63 #
b346d8f1 64 # Set the parser and producer.
ca10f295 65 #
b346d8f1 66 # If a 'parser' or 'from' parameter is passed in, use that as the
67 # parser; if a 'producer' or 'to' parameter is passed in, use that
68 # as the producer; both default to $DEFAULT_SUB.
49e1eb70 69 #
70 $self->parser ($config->{'parser'} || $config->{'from'} || $DEFAULT_SUB);
c2d3a526 71 $self->producer($config->{'producer'} || $config->{'to'} || $DEFAULT_SUB);
ca10f295 72
7d5bcab8 73 #
74 # Set up callbacks for formatting of pk,fk,table,package names in producer
75 #
76 $self->format_table_name($config->{'format_table_name'});
77 $self->format_package_name($config->{'format_package_name'});
78 $self->format_fk_name($config->{'format_fk_name'});
79 $self->format_pk_name($config->{'format_pk_name'});
80
49e1eb70 81 #
e2158c40 82 # Set the parser_args and producer_args
49e1eb70 83 #
84 for my $pargs ( qw[ parser_args producer_args ] ) {
85 $self->$pargs( $config->{$pargs} ) if defined $config->{ $pargs };
e2158c40 86 }
87
49e1eb70 88 #
9398955f 89 # Set the data source, if 'filename' or 'file' is provided.
49e1eb70 90 #
c2d3a526 91 $config->{'filename'} ||= $config->{'file'} || "";
49e1eb70 92 $self->filename( $config->{'filename'} ) if $config->{'filename'};
9398955f 93
49e1eb70 94 #
95 # Finally, if there is a 'data' parameter, use that in
96 # preference to filename and file
97 #
98 if ( my $data = $config->{'data'} ) {
99 $self->data( $data );
9398955f 100 }
101
d529894e 102 #
103 # Set various other options.
104 #
49e1eb70 105 $self->{'debug'} = defined $config->{'debug'} ? $config->{'debug'} : $DEBUG;
ca10f295 106
96844cae 107
108 $self->add_drop_table( $config->{'add_drop_table'} );
d529894e 109
110 $self->custom_translate( $config->{'xlate'} );
111
112 $self->no_comments( $config->{'no_comments'} );
113
96844cae 114 $self->show_warnings( $config->{'show_warnings'} );
115
116 $self->trace( $config->{'trace'} );
117
ca10f295 118 return $self;
dfb4c915 119}
1fd8c91f 120
0f3778d0 121# ----------------------------------------------------------------------
122# add_drop_table([$bool])
123# ----------------------------------------------------------------------
96844cae 124sub add_drop_table {
125 my $self = shift;
126 if ( defined (my $arg = shift) ) {
127 $self->{'add_drop_table'} = $arg ? 1 : 0;
128 }
129 return $self->{'add_drop_table'} || 0;
130}
131
132
0f3778d0 133# ----------------------------------------------------------------------
134# custom_translate([$bool])
135# ----------------------------------------------------------------------
d529894e 136sub custom_translate {
137 my $self = shift;
138 $self->{'custom_translate'} = shift if @_;
139 return $self->{'custom_translate'} || {};
140}
141
0f3778d0 142# ----------------------------------------------------------------------
143# no_comments([$bool])
144# ----------------------------------------------------------------------
d529894e 145sub no_comments {
146 my $self = shift;
147 my $arg = shift;
148 if ( defined $arg ) {
149 $self->{'no_comments'} = $arg ? 1 : 0;
150 }
151 return $self->{'no_comments'} || 0;
152}
153
e2158c40 154
0f3778d0 155# ----------------------------------------------------------------------
156# producer([$producer_spec])
157#
158# Get or set the producer for the current translator.
159# ----------------------------------------------------------------------
ca10f295 160sub producer {
1fd8c91f 161 my $self = shift;
b346d8f1 162
7a8e1f51 163 # producer as a mutator
ca10f295 164 if (@_) {
165 my $producer = shift;
b346d8f1 166
7a8e1f51 167 # Passed a module name (string containing "::")
ca10f295 168 if ($producer =~ /::/) {
077ebf34 169 my $func_name;
b346d8f1 170
7a8e1f51 171 # Module name was passed directly
b346d8f1 172 # We try to load the name; if it doesn't load, there's
173 # a possibility that it has a function name attached to
174 # it.
077ebf34 175 if (load($producer)) {
176 $func_name = "produce";
7a8e1f51 177 }
b346d8f1 178
7a8e1f51 179 # Module::function was passed
b346d8f1 180 else {
181 # Passed Module::Name::function; try to recover
077ebf34 182 my @func_parts = split /::/, $producer;
183 $func_name = pop @func_parts;
184 $producer = join "::", @func_parts;
b346d8f1 185
186 # If this doesn't work, then we have a legitimate
187 # problem.
077ebf34 188 load($producer) or die "Can't load $producer: $@";
7a8e1f51 189 }
077ebf34 190
7a8e1f51 191 # get code reference and assign
077ebf34 192 $self->{'producer'} = \&{ "$producer\::$func_name" };
193 $self->{'producer_type'} = $producer;
49e1eb70 194 $self->debug("Got producer: $producer\::$func_name\n");
7a8e1f51 195 }
b346d8f1 196
7a8e1f51 197 # passed an anonymous subroutine reference
b346d8f1 198 elsif (isa($producer, 'CODE')) {
ca10f295 199 $self->{'producer'} = $producer;
077ebf34 200 $self->{'producer_type'} = "CODE";
49e1eb70 201 $self->debug("Got producer: code ref\n");
7a8e1f51 202 }
b346d8f1 203
7a8e1f51 204 # passed a string containing no "::"; relative package name
b346d8f1 205 else {
ca10f295 206 my $Pp = sprintf "SQL::Translator::Producer::$producer";
207 load($Pp) or die "Can't load $Pp: $@";
077ebf34 208 $self->{'producer'} = \&{ "$Pp\::produce" };
209 $self->{'producer_type'} = $Pp;
49e1eb70 210 $self->debug("Got producer: $Pp\n");
7a8e1f51 211 }
b346d8f1 212
ca10f295 213 # At this point, $self->{'producer'} contains a subroutine
b346d8f1 214 # reference that is ready to run
e2158c40 215
7a8e1f51 216 # Anything left? If so, it's producer_args
217 $self->producer_args(@_) if (@_);
218 }
b346d8f1 219
ca10f295 220 return $self->{'producer'};
221};
077ebf34 222
7a8e1f51 223# ----------------------------------------------------------------------
0f3778d0 224# producer_type()
7a8e1f51 225#
e2158c40 226# producer_type is an accessor that allows producer subs to get
227# information about their origin. This is poptentially important;
ca251f03 228# since all producer subs are called as subroutine references, there is
e2158c40 229# no way for a producer to find out which package the sub lives in
230# originally, for example.
7a8e1f51 231# ----------------------------------------------------------------------
232sub producer_type { $_[0]->{'producer_type'} }
e2158c40 233
7a8e1f51 234# ----------------------------------------------------------------------
0f3778d0 235# producer_args([\%args])
7a8e1f51 236#
e2158c40 237# Arbitrary name => value pairs of paramters can be passed to a
238# producer using this method.
52b828e8 239#
0f3778d0 240# If the first argument passed in is undef, then the hash of arguments
241# is cleared; all subsequent elements are added to the hash of name,
242# value pairs stored as producer_args.
7a8e1f51 243# ----------------------------------------------------------------------
e2158c40 244sub producer_args {
245 my $self = shift;
0f3778d0 246 return $self->_args("producer", @_);
7a8e1f51 247}
ca10f295 248
0f3778d0 249# ----------------------------------------------------------------------
250# parser([$parser_spec])
251# ----------------------------------------------------------------------
ca10f295 252sub parser {
253 my $self = shift;
b346d8f1 254
7a8e1f51 255 # parser as a mutator
ca10f295 256 if (@_) {
257 my $parser = shift;
b346d8f1 258
7a8e1f51 259 # Passed a module name (string containing "::")
ca10f295 260 if ($parser =~ /::/) {
b346d8f1 261 my $func_name;
262
7a8e1f51 263 # Module name was passed directly
b346d8f1 264 # We try to load the name; if it doesn't load, there's
265 # a possibility that it has a function name attached to
266 # it.
267 if (load($parser)) {
268 $func_name = "parse";
7a8e1f51 269 }
b346d8f1 270
7a8e1f51 271 # Module::function was passed
b346d8f1 272 else {
273 # Passed Module::Name::function; try to recover
274 my @func_parts = split /::/, $parser;
275 $func_name = pop @func_parts;
276 $parser = join "::", @func_parts;
277
278 # If this doesn't work, then we have a legitimate
279 # problem.
280 load($parser) or die "Can't load $parser: $@";
7a8e1f51 281 }
b346d8f1 282
7a8e1f51 283 # get code reference and assign
b346d8f1 284 $self->{'parser'} = \&{ "$parser\::$func_name" };
077ebf34 285 $self->{'parser_type'} = $parser;
49e1eb70 286 $self->debug("Got parser: $parser\::$func_name\n");
7a8e1f51 287 }
b346d8f1 288
7a8e1f51 289 # passed an anonymous subroutine reference
49e1eb70 290 elsif ( isa( $parser, 'CODE' ) ) {
291 $self->{'parser'} = $parser;
077ebf34 292 $self->{'parser_type'} = "CODE";
49e1eb70 293 $self->debug("Got parser: code ref\n");
7a8e1f51 294 }
b346d8f1 295
7a8e1f51 296 # passed a string containing no "::"; relative package name
b346d8f1 297 else {
49e1eb70 298 my $Pp = "SQL::Translator::Parser::$parser";
299 load( $Pp ) or die "Can't load $Pp: $@";
300 $self->{'parser'} = \&{ "$Pp\::parse" };
077ebf34 301 $self->{'parser_type'} = $Pp;
49e1eb70 302 $self->debug("Got parser: $Pp\n");
7a8e1f51 303 }
b346d8f1 304
49e1eb70 305 #
b346d8f1 306 # At this point, $self->{'parser'} contains a subroutine
307 # reference that is ready to run
49e1eb70 308 #
309 $self->parser_args( @_ ) if (@_);
7a8e1f51 310 }
b346d8f1 311
ca10f295 312 return $self->{'parser'};
16dc9970 313}
1fd8c91f 314
d529894e 315# ----------------------------------------------------------------------
077ebf34 316sub parser_type { $_[0]->{'parser_type'} }
e2158c40 317
e2158c40 318sub parser_args {
319 my $self = shift;
0f3778d0 320 return $self->_args("parser", @_);
321}
96844cae 322
323sub show_warnings {
324 my $self = shift;
325 my $arg = shift;
326 if ( defined $arg ) {
327 $self->{'show_warnings'} = $arg ? 1 : 0;
328 }
329 return $self->{'show_warnings'} || 0;
330}
331
ca10f295 332
0f3778d0 333# filename - get or set the filename
334sub filename {
335 my $self = shift;
336 if (@_) {
337 my $filename = shift;
338 if (-d $filename) {
339 my $msg = "Cannot use directory '$filename' as input source";
340 return $self->error($msg);
95a2cfb6 341 } elsif (ref($filename) eq 'ARRAY') {
342 $self->{'filename'} = $filename;
343 $self->debug("Got array of files: ".join(', ',@$filename)."\n");
0f3778d0 344 } elsif (-f _ && -r _) {
345 $self->{'filename'} = $filename;
346 $self->debug("Got filename: '$self->{'filename'}'\n");
347 } else {
348 my $msg = "Cannot use '$filename' as input source: ".
349 "file does not exist or is not readable.";
350 return $self->error($msg);
351 }
352 }
ca10f295 353
0f3778d0 354 $self->{'filename'};
355}
ca10f295 356
0f3778d0 357# ----------------------------------------------------------------------
358# data([$data])
359#
360# if $self->{'data'} is not set, but $self->{'filename'} is, then
361# $self->{'filename'} is opened and read, with the results put into
362# $self->{'data'}.
363# ----------------------------------------------------------------------
364sub data {
365 my $self = shift;
ca10f295 366
0f3778d0 367 # Set $self->{'data'} based on what was passed in. We will
368 # accept a number of things; do our best to get it right.
369 if (@_) {
370 my $data = shift;
371 if (isa($data, "SCALAR")) {
372 $self->{'data'} = $data;
373 }
374 else {
375 if (isa($data, 'ARRAY')) {
376 $data = join '', @$data;
377 }
378 elsif (isa($data, 'GLOB')) {
379 local $/;
380 $data = <$data>;
381 }
382 elsif (! ref $data && @_) {
383 $data = join '', $data, @_;
384 }
385 $self->{'data'} = \$data;
386 }
387 }
9398955f 388
7a8e1f51 389 # If we have a filename but no data yet, populate.
9398955f 390 if (not $self->{'data'} and my $filename = $self->filename) {
49e1eb70 391 $self->debug("Opening '$filename' to get contents.\n");
9398955f 392 local *FH;
393 local $/;
394 my $data;
395
95a2cfb6 396 my @files = ref($filename) eq 'ARRAY' ? @$filename : ($filename);
9398955f 397
95a2cfb6 398 foreach my $file (@files) {
399 unless (open FH, $file) {
400 return $self->error("Can't read file '$file': $!");
401 }
9398955f 402
95a2cfb6 403 $data .= <FH>;
404
405 unless (close FH) {
406 return $self->error("Can't close file '$file': $!");
407 }
408 }
409
410 $self->{'data'} = \$data;
9398955f 411 }
9398955f 412
413 return $self->{'data'};
7a8e1f51 414}
9398955f 415
d529894e 416
417sub trace {
418 my $self = shift;
419 my $arg = shift;
420 if ( defined $arg ) {
421 $self->{'trace'} = $arg ? 1 : 0;
422 }
423 return $self->{'trace'} || 0;
424}
425
426# ----------------------------------------------------------------------
0f3778d0 427# translate([source], [\%args])
428#
429# translate does the actual translation. The main argument is the
430# source of the data to be translated, which can be a filename, scalar
431# reference, or glob reference.
432#
433# Alternatively, translate takes optional arguements, which are passed
434# to the appropriate places. Most notable of these arguments are
435# parser and producer, which can be used to set the parser and
436# producer, respectively. This is the applications last chance to set
437# these.
438#
439# translate returns a string.
440# ----------------------------------------------------------------------
ca251f03 441sub translate {
442 my $self = shift;
443 my ($args, $parser, $parser_type, $producer, $producer_type);
444 my ($parser_output, $producer_output);
ca10f295 445
7a8e1f51 446 # Parse arguments
9398955f 447 if (@_ == 1) {
7a8e1f51 448 # Passed a reference to a hash?
ca10f295 449 if (isa($_[0], 'HASH')) {
7a8e1f51 450 # yep, a hashref
49e1eb70 451 $self->debug("translate: Got a hashref\n");
ca10f295 452 $args = $_[0];
453 }
9398955f 454
0f3778d0 455 # Passed a GLOB reference, i.e., filehandle
456 elsif (isa($_[0], 'GLOB')) {
457 $self->debug("translate: Got a GLOB reference\n");
458 $self->data($_[0]);
459 }
460
7a8e1f51 461 # Passed a reference to a string containing the data
ca10f295 462 elsif (isa($_[0], 'SCALAR')) {
9398955f 463 # passed a ref to a string
49e1eb70 464 $self->debug("translate: Got a SCALAR reference (string)\n");
9398955f 465 $self->data($_[0]);
ca10f295 466 }
9398955f 467
7a8e1f51 468 # Not a reference; treat it as a filename
b346d8f1 469 elsif (! ref $_[0]) {
ca10f295 470 # Not a ref, it's a filename
49e1eb70 471 $self->debug("translate: Got a filename\n");
9398955f 472 $self->filename($_[0]);
ca10f295 473 }
9398955f 474
7a8e1f51 475 # Passed something else entirely.
b346d8f1 476 else {
477 # We're not impressed. Take your empty string and leave.
38254289 478 # return "";
479
7a8e1f51 480 # Actually, if data, parser, and producer are set, then we
481 # can continue. Too bad, because I like my comment
482 # (above)...
38254289 483 return "" unless ($self->data &&
484 $self->producer &&
485 $self->parser);
b346d8f1 486 }
16dc9970 487 }
488 else {
b346d8f1 489 # You must pass in a hash, or you get nothing.
490 return "" if @_ % 2;
ca10f295 491 $args = { @_ };
7a8e1f51 492 }
16dc9970 493
9398955f 494 # ----------------------------------------------------------------------
495 # Can specify the data to be transformed using "filename", "file",
7a8e1f51 496 # "data", or "datasource".
9398955f 497 # ----------------------------------------------------------------------
7a8e1f51 498 if (my $filename = ($args->{'filename'} || $args->{'file'})) {
9398955f 499 $self->filename($filename);
500 }
ca10f295 501
422298aa 502 if (my $data = ($args->{'data'} || $args->{'datasource'})) {
9398955f 503 $self->data($data);
16dc9970 504 }
ca10f295 505
9398955f 506 # ----------------------------------------------------------------
507 # Get the data.
508 # ----------------------------------------------------------------
509 my $data = $self->data;
5457eaf0 510 unless (ref($data) eq 'SCALAR' and length $$data) {
c2d3a526 511 return $self->error("Empty data file!");
9398955f 512 }
077ebf34 513
9398955f 514 # ----------------------------------------------------------------
ca10f295 515 # Local reference to the parser subroutine
9398955f 516 # ----------------------------------------------------------------
ca10f295 517 if ($parser = ($args->{'parser'} || $args->{'from'})) {
518 $self->parser($parser);
16dc9970 519 }
7a8e1f51 520 $parser = $self->parser;
521 $parser_type = $self->parser_type;
16dc9970 522
9398955f 523 # ----------------------------------------------------------------
ca10f295 524 # Local reference to the producer subroutine
9398955f 525 # ----------------------------------------------------------------
ca10f295 526 if ($producer = ($args->{'producer'} || $args->{'to'})) {
527 $self->producer($producer);
16dc9970 528 }
7a8e1f51 529 $producer = $self->producer;
530 $producer_type = $self->producer_type;
16dc9970 531
9398955f 532 # ----------------------------------------------------------------
7a8e1f51 533 # Execute the parser, then execute the producer with that output.
534 # Allowances are made for each piece to die, or fail to compile,
535 # since the referenced subroutines could be almost anything. In
536 # the future, each of these might happen in a Safe environment,
537 # depending on how paranoid we want to be.
9398955f 538 # ----------------------------------------------------------------
7a8e1f51 539 eval { $parser_output = $parser->($self, $$data) };
540 if ($@ || ! $parser_output) {
541 my $msg = sprintf "translate: Error with parser '%s': %s",
542 $parser_type, ($@) ? $@ : " no results";
c2d3a526 543 return $self->error($msg);
7a8e1f51 544 }
545
546 eval { $producer_output = $producer->($self, $parser_output) };
547 if ($@ || ! $producer_output) {
548 my $msg = sprintf "translate: Error with producer '%s': %s",
549 $producer_type, ($@) ? $@ : " no results";
c2d3a526 550 return $self->error($msg);
7a8e1f51 551 }
552
553 return $producer_output;
16dc9970 554}
ca10f295 555
d529894e 556# ----------------------------------------------------------------------
0f3778d0 557# list_parsers()
558#
559# Hacky sort of method to list all available parsers. This has
560# several problems:
561#
562# - Only finds things in the SQL::Translator::Parser namespace
563#
564# - Only finds things that are located in the same directory
565# as SQL::Translator::Parser. Yeck.
566#
567# This method will fail in several very likely cases:
568#
569# - Parser modules in different namespaces
570#
571# - Parser modules in the SQL::Translator::Parser namespace that
572# have any XS componenets will be installed in
573# arch_lib/SQL/Translator.
574#
575# ----------------------------------------------------------------------
576sub list_parsers {
ca1f2237 577 return shift->_list("parser");
0f3778d0 578}
579
580# ----------------------------------------------------------------------
581# list_producers()
582#
583# See notes for list_parsers(), above; all the problems apply to
584# list_producers as well.
585# ----------------------------------------------------------------------
c0c4aef9 586sub list_producers {
ca1f2237 587 return shift->_list("producer");
0f3778d0 588}
589
c0c4aef9 590
0f3778d0 591# ======================================================================
592# Private Methods
593# ======================================================================
c0c4aef9 594
0f3778d0 595# ----------------------------------------------------------------------
596# _args($type, \%args);
597#
598# Gets or sets ${type}_args. Called by parser_args and producer_args.
599# ----------------------------------------------------------------------
600sub _args {
601 my $self = shift;
602 my $type = shift;
603 $type = "${type}_args" unless $type =~ /_args$/;
604
605 unless (defined $self->{$type} && isa($self->{$type}, 'HASH')) {
606 $self->{$type} = { };
607 }
608
609 if (@_) {
610 # If the first argument is an explicit undef (remember, we
611 # don't get here unless there is stuff in @_), then we clear
612 # out the producer_args hash.
613 if (! defined $_[0]) {
614 shift @_;
615 %{$self->{$type}} = ();
616 }
617
618 my $args = isa($_[0], 'HASH') ? shift : { @_ };
619 %{$self->{$type}} = (%{$self->{$type}}, %$args);
620 }
621
622 $self->{$type};
c0c4aef9 623}
624
0f3778d0 625
d529894e 626# ----------------------------------------------------------------------
0f3778d0 627# _list($type)
628# ----------------------------------------------------------------------
629sub _list {
ca1f2237 630 my $self = shift;
631 my $type = shift || return ();
632 my $uctype = ucfirst lc $type;
633 my %found;
634
635 load("SQL::Translator::$uctype") or return ();
636 my $path = catfile "SQL", "Translator", $uctype;
637 for (@INC) {
638 my $dir = catfile $_, $path;
639 $self->debug("_list_${type}s searching $dir");
640 next unless -d $dir;
641
642 my $dh = IO::Dir->new($dir);
643 for (grep /\.pm$/, $dh->read) {
644 s/\.pm$//;
645 $found{ join "::", "SQL::Translator::$uctype", $_ } = 1;
646 }
647 }
c0c4aef9 648
ca1f2237 649 return keys %found;
c0c4aef9 650}
651
d529894e 652# ----------------------------------------------------------------------
0f3778d0 653# load($module)
654#
655# Loads a Perl module. Short circuits if a module is already loaded.
656# ----------------------------------------------------------------------
ca10f295 657sub load {
658 my $module = do { my $m = shift; $m =~ s[::][/]g; "$m.pm" };
659 return 1 if $INC{$module};
ca1f2237 660
ca10f295 661 eval { require $module };
ca1f2237 662
663 return __PACKAGE__->error($@) if ($@);
ca10f295 664 return 1;
1fd8c91f 665}
16dc9970 666
7d5bcab8 667sub format_table_name {
668 my $self = shift;
669 my $sub = shift;
670 $self->{_format_table_name} = $sub if ref($sub) eq 'CODE';
671 return $self->{_format_table_name}->($sub,@_) if defined($self->{_format_table_name});
672 return($sub);
673}
674
675sub format_package_name {
676 my $self = shift;
677 my $sub = shift;
678 $self->{_format_package_name} = $sub if ref($sub) eq 'CODE';
679 return $self->{_format_package_name}->($sub,@_) if defined($self->{_format_package_name});
680 return($sub);
681}
682
683sub format_fk_name {
684 my $self = shift;
685 my $sub = shift;
686 $self->{_format_fk_name} = $sub if ref($sub) eq 'CODE';
687 return $self->{_format_fk_name}->($sub,@_) if defined($self->{_format_fk_name});
688 return($sub);
689}
690
691sub format_pk_name {
692 my $self = shift;
693 my $sub = shift;
694 $self->{_format_pk_name} = $sub if ref($sub) eq 'CODE';
695 return $self->{_format_pk_name}->($sub,@_) if defined($self->{_format_pk_name});
696 return($sub);
697}
698
d529894e 699# ----------------------------------------------------------------------
0f3778d0 700# isa($ref, $type)
701#
702# Calls UNIVERSAL::isa($ref, $type). I think UNIVERSAL::isa is ugly,
703# but I like function overhead.
704# ----------------------------------------------------------------------
705sub isa($$) {
706 my ($ref, $type) = @_;
707 return UNIVERSAL::isa($ref, $type);
708}
c2d3a526 709
16dc9970 7101;
16dc9970 711#-----------------------------------------------------
712# Rescue the drowning and tie your shoestrings.
713# Henry David Thoreau
714#-----------------------------------------------------
715
0f3778d0 716__END__
717
718=head1 NAME
719
720SQL::Translator - convert schema from one database to another
721
722=head1 SYNOPSIS
723
724 use SQL::Translator;
725
726 my $translator = SQL::Translator->new(
87bf8a3a 727 debug => 1, # Print debug info
728 trace => 0, # Print Parse::RecDescent trace
729 no_comments => 0, # Don't include comments in output
730 show_warnings => 0, # Print name mutations, conflicts
731 add_drop_table => 1, # Add "drop table" statements
7d5bcab8 732
733 #make all table names CAPS in producers which support this option
734 format_table_name => sub {my $tablename = shift; return uc($tablename)},
735 #null-op formatting, only here for documentation's sake
736 format_package_name => sub {return shift},
737 format_fk_name => sub {return shift},
738 format_pk_name => sub {return shift},
0f3778d0 739 );
740
741 my $output = $translator->translate(
742 from => "MySQL",
743 to => "Oracle",
95a2cfb6 744 filename => $file, #or an arrayref of filenames, ie [$file1,$file2,$file3]
0f3778d0 745 ) or die $translator->error;
746
747 print $output;
748
749=head1 DESCRIPTION
750
751This module attempts to simplify the task of converting one database
752create syntax to another through the use of Parsers (which understand
753the source format) and Producers (which understand the destination
754format). The idea is that any Parser can be used with any Producer in
755the conversion process. So, if you wanted Postgres-to-Oracle, you
756would use the Postgres parser and the Oracle producer.
757
758=head1 CONSTRUCTOR
759
760The constructor is called B<new>, and accepts a optional hash of options.
761Valid options are:
762
763=over 4
764
ca251f03 765=item *
766
767parser / from
768
769=item *
770
771parser_args
0f3778d0 772
ca251f03 773=item *
0f3778d0 774
ca251f03 775producer / to
0f3778d0 776
ca251f03 777=item *
0f3778d0 778
ca251f03 779producer_args
0f3778d0 780
ca251f03 781=item *
782
783filename / file
784
785=item *
786
787data
788
789=item *
0f3778d0 790
ca251f03 791debug
0f3778d0 792
793=back
794
795All options are, well, optional; these attributes can be set via
796instance methods. Internally, they are; no (non-syntactical)
797advantage is gained by passing options to the constructor.
798
799=head1 METHODS
800
801=head2 B<add_drop_table>
802
803Toggles whether or not to add "DROP TABLE" statements just before the
804create definitions.
805
806=head2 B<custom_translate>
807
808Allows the user to override default translation of fields. For example,
809if a MySQL "text" field would normally be converted to a "long" for Oracle,
810the user could specify to change it to a "CLOB." Accepts a hashref where
811keys are the "from" value and values are the "to," returns the current
812value of the field.
813
814=head2 B<no_comments>
815
816Toggles whether to print comments in the output. Accepts a true or false
817value, returns the current value.
818
819=head2 B<producer>
820
821The B<producer> method is an accessor/mutator, used to retrieve or
822define what subroutine is called to produce the output. A subroutine
823defined as a producer will be invoked as a function (I<not a method>)
ca251f03 824and passed 2 parameters: its container C<SQL::Translator> instance and a
0f3778d0 825data structure. It is expected that the function transform the data
ca251f03 826structure to a string. The C<SQL::Transformer> instance is provided for
0f3778d0 827informational purposes; for example, the type of the parser can be
828retrieved using the B<parser_type> method, and the B<error> and
829B<debug> methods can be called when needed.
830
ca251f03 831When defining a producer, one of several things can be passed in: A
832module name (e.g., C<My::Groovy::Producer>, a module name relative to
833the C<SQL::Translator::Producer> namespace (e.g., MySQL), a module
834name and function combination (C<My::Groovy::Producer::transmogrify>),
0f3778d0 835or a reference to an anonymous subroutine. If a full module name is
836passed in (for the purposes of this method, a string containing "::"
837is considered to be a module name), it is treated as a package, and a
ca251f03 838function called "produce" will be invoked: C<$modulename::produce>.
839If $modulename cannot be loaded, the final portion is stripped off and
0f3778d0 840treated as a function. In other words, if there is no file named
ca251f03 841F<My/Groovy/Producer/transmogrify.pm>, C<SQL::Translator> will attempt
842to load F<My/Groovy/Producer.pm> and use transmogrify as the name of
843the function, instead of the default "produce".
0f3778d0 844
845 my $tr = SQL::Translator->new;
846
847 # This will invoke My::Groovy::Producer::produce($tr, $data)
848 $tr->producer("My::Groovy::Producer");
849
850 # This will invoke SQL::Translator::Producer::Sybase::produce($tr, $data)
851 $tr->producer("Sybase");
852
853 # This will invoke My::Groovy::Producer::transmogrify($tr, $data),
854 # assuming that My::Groovy::Producer::transmogrify is not a module
855 # on disk.
856 $tr->producer("My::Groovy::Producer::transmogrify");
857
858 # This will invoke the referenced subroutine directly, as
859 # $subref->($tr, $data);
860 $tr->producer(\&my_producer);
861
862There is also a method named B<producer_type>, which is a string
863containing the classname to which the above B<produce> function
864belongs. In the case of anonymous subroutines, this method returns
865the string "CODE".
866
867Finally, there is a method named B<producer_args>, which is both an
868accessor and a mutator. Arbitrary data may be stored in name => value
869pairs for the producer subroutine to access:
870
871 sub My::Random::producer {
872 my ($tr, $data) = @_;
873 my $pr_args = $tr->producer_args();
874
875 # $pr_args is a hashref.
876
877Extra data passed to the B<producer> method is passed to
878B<producer_args>:
879
880 $tr->producer("xSV", delimiter => ',\s*');
881
882 # In SQL::Translator::Producer::xSV:
883 my $args = $tr->producer_args;
884 my $delimiter = $args->{'delimiter'}; # value is ,\s*
885
886=head2 B<parser>
887
888The B<parser> method defines or retrieves a subroutine that will be
889called to perform the parsing. The basic idea is the same as that of
890B<producer> (see above), except the default subroutine name is
ca251f03 891"parse", and will be invoked as C<$module_name::parse($tr, $data)>.
0f3778d0 892Also, the parser subroutine will be passed a string containing the
893entirety of the data to be parsed.
894
895 # Invokes SQL::Translator::Parser::MySQL::parse()
896 $tr->parser("MySQL");
897
898 # Invokes My::Groovy::Parser::parse()
899 $tr->parser("My::Groovy::Parser");
900
901 # Invoke an anonymous subroutine directly
902 $tr->parser(sub {
903 my $dumper = Data::Dumper->new([ $_[1] ], [ "SQL" ]);
904 $dumper->Purity(1)->Terse(1)->Deepcopy(1);
905 return $dumper->Dump;
906 });
907
908There is also B<parser_type> and B<parser_args>, which perform
909analogously to B<producer_type> and B<producer_args>
910
911=head2 B<show_warnings>
912
913Toggles whether to print warnings of name conflicts, identifier
914mutations, etc. Probably only generated by producers to let the user
915know when something won't translate very smoothly (e.g., MySQL "enum"
916fields into Oracle). Accepts a true or false value, returns the
917current value.
918
919=head2 B<translate>
920
921The B<translate> method calls the subroutines referenced by the
922B<parser> and B<producer> data members (described above). It accepts
923as arguments a number of things, in key => value format, including
924(potentially) a parser and a producer (they are passed directly to the
925B<parser> and B<producer> methods).
926
927Here is how the parameter list to B<translate> is parsed:
928
929=over
930
931=item *
932
9331 argument means it's the data to be parsed; which could be a string
ca251f03 934(filename) or a reference to a scalar (a string stored in memory), or a
0f3778d0 935reference to a hash, which is parsed as being more than one argument
936(see next section).
937
938 # Parse the file /path/to/datafile
939 my $output = $tr->translate("/path/to/datafile");
940
941 # Parse the data contained in the string $data
942 my $output = $tr->translate(\$data);
943
944=item *
945
946More than 1 argument means its a hash of things, and it might be
947setting a parser, producer, or datasource (this key is named
948"filename" or "file" if it's a file, or "data" for a SCALAR reference.
949
950 # As above, parse /path/to/datafile, but with different producers
951 for my $prod ("MySQL", "XML", "Sybase") {
952 print $tr->translate(
953 producer => $prod,
954 filename => "/path/to/datafile",
955 );
956 }
957
958 # The filename hash key could also be:
959 datasource => \$data,
960
961You get the idea.
962
963=back
964
965=head2 B<filename>, B<data>
966
967Using the B<filename> method, the filename of the data to be parsed
968can be set. This method can be used in conjunction with the B<data>
969method, below. If both the B<filename> and B<data> methods are
970invoked as mutators, the data set in the B<data> method is used.
971
972 $tr->filename("/my/data/files/create.sql");
973
974or:
975
976 my $create_script = do {
977 local $/;
978 open CREATE, "/my/data/files/create.sql" or die $!;
979 <CREATE>;
980 };
981 $tr->data(\$create_script);
982
983B<filename> takes a string, which is interpreted as a filename.
984B<data> takes a reference to a string, which is used as the data to be
985parsed. If a filename is set, then that file is opened and read when
986the B<translate> method is called, as long as the data instance
987variable is not set.
988
989=pod
990
991=head2 B<trace>
992
993Turns on/off the tracing option of Parse::RecDescent.
994
49e1eb70 995=pod
996
7a8e1f51 997=head1 AUTHORS
16dc9970 998
ca251f03 999Ken Y. Clark, E<lt>kclark@cpan.orgE<gt>,
1000darren chamberlain E<lt>darren@cpan.orgE<gt>,
1001Chris Mungall E<lt>cjm@fruitfly.orgE<gt>,
1002Allen Day E<lt>allenday@users.sourceforge.netE<gt>
dfb4c915 1003
ca10f295 1004=head1 COPYRIGHT
16dc9970 1005
ca10f295 1006This program is free software; you can redistribute it and/or modify
1007it under the terms of the GNU General Public License as published by
1008the Free Software Foundation; version 2.
dfb4c915 1009
ca10f295 1010This program is distributed in the hope that it will be useful, but
1011WITHOUT ANY WARRANTY; without even the implied warranty of
1012MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1013General Public License for more details.
16dc9970 1014
ca10f295 1015You should have received a copy of the GNU General Public License
1016along with this program; if not, write to the Free Software
1017Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
1018USA
16dc9970 1019
87bf8a3a 1020=head1 BUGS
1021
1022Please use http://rt.cpan.org/ for reporting bugs.
1023
16dc9970 1024=head1 SEE ALSO
1025
abfa405a 1026L<perl>,
1027L<SQL::Translator::Parser>,
1028L<SQL::Translator::Producer>,
1029L<Parse::RecDescent>
16dc9970 1030