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