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