Added test number.
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator.pm
CommitLineData
16dc9970 1package SQL::Translator;
2
b346d8f1 3# ----------------------------------------------------------------------
23fb91d9 4# $Id: Translator.pm,v 1.39 2003-08-18 16:53:16 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';
23fb91d9 32$REVISION = sprintf "%d.%02d", q$Revision: 1.39 $ =~ /(\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 {
f9a0c3b5 695 my $self = shift;
696 my $sub = shift;
697 $self->{'_format_table_name'} = $sub if ref $sub eq 'CODE';
698 return $self->{'_format_table_name'}->( $sub, @_ )
699 if defined $self->{'_format_table_name'};
700 return $sub;
7d5bcab8 701}
702
67e5ff53 703# ----------------------------------------------------------------------
7d5bcab8 704sub format_package_name {
f9a0c3b5 705 my $self = shift;
706 my $sub = shift;
707 $self->{'_format_package_name'} = $sub if ref $sub eq 'CODE';
708 return $self->{'_format_package_name'}->( $sub, @_ )
709 if defined $self->{'_format_package_name'};
710 return $sub;
7d5bcab8 711}
712
67e5ff53 713# ----------------------------------------------------------------------
7d5bcab8 714sub format_fk_name {
f9a0c3b5 715 my $self = shift;
c703e51d 716
717 if ( ref $_[0] eq 'CODE' ) {
a57ce769 718 $self->{'_format_fk_name'} = shift;
c703e51d 719 }
720
721 if ( @_ ) {
a57ce769 722 if ( defined $self->{'_format_fk_name'} ) {
723 return $self->{'_format_fk_name'}->( @_ );
c703e51d 724 }
725 else {
726 return '';
727 }
728 }
729
a57ce769 730 return $self->{'_format_fk_name'};
7d5bcab8 731}
732
67e5ff53 733# ----------------------------------------------------------------------
7d5bcab8 734sub format_pk_name {
f9a0c3b5 735 my $self = shift;
8a990c91 736
737 if ( ref $_[0] eq 'CODE' ) {
738 $self->{'_format_pk_name'} = shift;
739 }
740
741 if ( @_ ) {
742 if ( defined $self->{'_format_pk_name'} ) {
743 return $self->{'_format_pk_name'}->( @_ );
744 }
745 else {
746 return '';
747 }
748 }
749
750 return $self->{'_format_pk_name'};
7d5bcab8 751}
752
d529894e 753# ----------------------------------------------------------------------
0f3778d0 754# isa($ref, $type)
755#
756# Calls UNIVERSAL::isa($ref, $type). I think UNIVERSAL::isa is ugly,
757# but I like function overhead.
758# ----------------------------------------------------------------------
759sub isa($$) {
760 my ($ref, $type) = @_;
761 return UNIVERSAL::isa($ref, $type);
762}
c2d3a526 763
3f4af30d 764# ----------------------------------------------------------------------
765sub validate {
3f4af30d 766 my ( $self, $arg ) = @_;
767 if ( defined $arg ) {
768 $self->{'validate'} = $arg ? 1 : 0;
769 }
770 return $self->{'validate'} || 0;
771}
772
16dc9970 7731;
16dc9970 774
389b318c 775# ----------------------------------------------------------------------
776# Who killed the pork chops?
777# What price bananas?
778# Are you my Angel?
779# Allen Ginsberg
780# ----------------------------------------------------------------------
781
782=pod
0f3778d0 783
784=head1 NAME
785
954f31f1 786SQL::Translator - manipulate structured data definitions (SQL and more)
0f3778d0 787
788=head1 SYNOPSIS
789
790 use SQL::Translator;
791
67e5ff53 792 my $translator = SQL::Translator->new(
793 # Print debug info
794 debug => 1,
795 # Print Parse::RecDescent trace
796 trace => 0,
797 # Don't include comments in output
798 no_comments => 0,
799 # Print name mutations, conflicts
800 show_warnings => 0,
801 # Add "drop table" statements
802 add_drop_table => 1,
803 # Validate schema object
804 validate => 1,
f9a0c3b5 805 # Make all table names CAPS in producers which support this option
67e5ff53 806 format_table_name => sub {my $tablename = shift; return uc($tablename)},
f9a0c3b5 807 # Null-op formatting, only here for documentation's sake
7d5bcab8 808 format_package_name => sub {return shift},
809 format_fk_name => sub {return shift},
810 format_pk_name => sub {return shift},
0f3778d0 811 );
812
813 my $output = $translator->translate(
389b318c 814 from => 'MySQL',
815 to => 'Oracle',
f9a0c3b5 816 # Or an arrayref of filenames, i.e. [ $file1, $file2, $file3 ]
817 filename => $file,
0f3778d0 818 ) or die $translator->error;
819
820 print $output;
821
822=head1 DESCRIPTION
823
29efc9fd 824SQL::Translator is a group of Perl modules that converts
825vendor-specific SQL table definitions into other formats, such as
826other vendor-specific SQL, ER diagrams, documentation (POD and HTML),
827XML, and Class::DBI classes. The main focus of SQL::Translator is
828SQL, but parsers exist for other structured data formats, including
829Excel spreadsheets and arbitrarily delimited text files. Through the
830separation of the code into parsers and producers with an object model
831in between, it's possible to combine any parser with any producer, to
832plug in custom parsers or producers, or to manipulate the parsed data
833via the built-in object model. Presently only the definition parts of
834SQL are handled (CREATE, ALTER), not the manipulation of data (INSERT,
835UPDATE, DELETE).
0f3778d0 836
837=head1 CONSTRUCTOR
838
5760246d 839The constructor is called C<new>, and accepts a optional hash of options.
0f3778d0 840Valid options are:
841
842=over 4
843
ca251f03 844=item *
845
846parser / from
847
848=item *
849
850parser_args
0f3778d0 851
ca251f03 852=item *
0f3778d0 853
ca251f03 854producer / to
0f3778d0 855
ca251f03 856=item *
0f3778d0 857
ca251f03 858producer_args
0f3778d0 859
ca251f03 860=item *
861
862filename / file
863
864=item *
865
866data
867
868=item *
0f3778d0 869
ca251f03 870debug
0f3778d0 871
389b318c 872=item *
873
874add_drop_table
875
876=item *
877
878no_comments
879
880=item *
881
882trace
883
884=item *
885
886validate
887
0f3778d0 888=back
889
890All options are, well, optional; these attributes can be set via
891instance methods. Internally, they are; no (non-syntactical)
892advantage is gained by passing options to the constructor.
893
894=head1 METHODS
895
5760246d 896=head2 add_drop_table
0f3778d0 897
898Toggles whether or not to add "DROP TABLE" statements just before the
899create definitions.
900
5760246d 901=head2 no_comments
0f3778d0 902
903Toggles whether to print comments in the output. Accepts a true or false
904value, returns the current value.
905
5760246d 906=head2 producer
0f3778d0 907
5760246d 908The C<producer> method is an accessor/mutator, used to retrieve or
0f3778d0 909define what subroutine is called to produce the output. A subroutine
910defined as a producer will be invoked as a function (I<not a method>)
ca251f03 911and passed 2 parameters: its container C<SQL::Translator> instance and a
0f3778d0 912data structure. It is expected that the function transform the data
ca251f03 913structure to a string. The C<SQL::Transformer> instance is provided for
0f3778d0 914informational purposes; for example, the type of the parser can be
5760246d 915retrieved using the C<parser_type> method, and the C<error> and
916C<debug> methods can be called when needed.
0f3778d0 917
ca251f03 918When defining a producer, one of several things can be passed in: A
5760246d 919module name (e.g., C<My::Groovy::Producer>), a module name relative to
920the C<SQL::Translator::Producer> namespace (e.g., C<MySQL>), a module
ca251f03 921name and function combination (C<My::Groovy::Producer::transmogrify>),
0f3778d0 922or a reference to an anonymous subroutine. If a full module name is
923passed in (for the purposes of this method, a string containing "::"
924is considered to be a module name), it is treated as a package, and a
ca251f03 925function called "produce" will be invoked: C<$modulename::produce>.
926If $modulename cannot be loaded, the final portion is stripped off and
0f3778d0 927treated as a function. In other words, if there is no file named
ca251f03 928F<My/Groovy/Producer/transmogrify.pm>, C<SQL::Translator> will attempt
5760246d 929to load F<My/Groovy/Producer.pm> and use C<transmogrify> as the name of
930the function, instead of the default C<produce>.
0f3778d0 931
932 my $tr = SQL::Translator->new;
933
934 # This will invoke My::Groovy::Producer::produce($tr, $data)
935 $tr->producer("My::Groovy::Producer");
936
937 # This will invoke SQL::Translator::Producer::Sybase::produce($tr, $data)
938 $tr->producer("Sybase");
939
940 # This will invoke My::Groovy::Producer::transmogrify($tr, $data),
941 # assuming that My::Groovy::Producer::transmogrify is not a module
942 # on disk.
943 $tr->producer("My::Groovy::Producer::transmogrify");
944
945 # This will invoke the referenced subroutine directly, as
946 # $subref->($tr, $data);
947 $tr->producer(\&my_producer);
948
5760246d 949There is also a method named C<producer_type>, which is a string
950containing the classname to which the above C<produce> function
0f3778d0 951belongs. In the case of anonymous subroutines, this method returns
952the string "CODE".
953
5760246d 954Finally, there is a method named C<producer_args>, which is both an
0f3778d0 955accessor and a mutator. Arbitrary data may be stored in name => value
956pairs for the producer subroutine to access:
957
958 sub My::Random::producer {
959 my ($tr, $data) = @_;
960 my $pr_args = $tr->producer_args();
961
962 # $pr_args is a hashref.
963
5760246d 964Extra data passed to the C<producer> method is passed to
965C<producer_args>:
0f3778d0 966
967 $tr->producer("xSV", delimiter => ',\s*');
968
969 # In SQL::Translator::Producer::xSV:
970 my $args = $tr->producer_args;
971 my $delimiter = $args->{'delimiter'}; # value is ,\s*
972
5760246d 973=head2 parser
0f3778d0 974
5760246d 975The C<parser> method defines or retrieves a subroutine that will be
0f3778d0 976called to perform the parsing. The basic idea is the same as that of
5760246d 977C<producer> (see above), except the default subroutine name is
ca251f03 978"parse", and will be invoked as C<$module_name::parse($tr, $data)>.
0f3778d0 979Also, the parser subroutine will be passed a string containing the
980entirety of the data to be parsed.
981
982 # Invokes SQL::Translator::Parser::MySQL::parse()
983 $tr->parser("MySQL");
984
985 # Invokes My::Groovy::Parser::parse()
986 $tr->parser("My::Groovy::Parser");
987
988 # Invoke an anonymous subroutine directly
989 $tr->parser(sub {
990 my $dumper = Data::Dumper->new([ $_[1] ], [ "SQL" ]);
991 $dumper->Purity(1)->Terse(1)->Deepcopy(1);
992 return $dumper->Dump;
993 });
994
5760246d 995There is also C<parser_type> and C<parser_args>, which perform
996analogously to C<producer_type> and C<producer_args>
0f3778d0 997
5760246d 998=head2 show_warnings
0f3778d0 999
1000Toggles whether to print warnings of name conflicts, identifier
1001mutations, etc. Probably only generated by producers to let the user
1002know when something won't translate very smoothly (e.g., MySQL "enum"
1003fields into Oracle). Accepts a true or false value, returns the
1004current value.
1005
5760246d 1006=head2 translate
0f3778d0 1007
5760246d 1008The C<translate> method calls the subroutines referenced by the
1009C<parser> and C<producer> data members (described above). It accepts
0f3778d0 1010as arguments a number of things, in key => value format, including
1011(potentially) a parser and a producer (they are passed directly to the
5760246d 1012C<parser> and C<producer> methods).
0f3778d0 1013
5760246d 1014Here is how the parameter list to C<translate> is parsed:
0f3778d0 1015
1016=over
1017
1018=item *
1019
10201 argument means it's the data to be parsed; which could be a string
ca251f03 1021(filename) or a reference to a scalar (a string stored in memory), or a
0f3778d0 1022reference to a hash, which is parsed as being more than one argument
1023(see next section).
1024
1025 # Parse the file /path/to/datafile
1026 my $output = $tr->translate("/path/to/datafile");
1027
1028 # Parse the data contained in the string $data
1029 my $output = $tr->translate(\$data);
1030
1031=item *
1032
1033More than 1 argument means its a hash of things, and it might be
1034setting a parser, producer, or datasource (this key is named
1035"filename" or "file" if it's a file, or "data" for a SCALAR reference.
1036
1037 # As above, parse /path/to/datafile, but with different producers
1038 for my $prod ("MySQL", "XML", "Sybase") {
1039 print $tr->translate(
1040 producer => $prod,
1041 filename => "/path/to/datafile",
1042 );
1043 }
1044
1045 # The filename hash key could also be:
1046 datasource => \$data,
1047
1048You get the idea.
1049
1050=back
1051
5760246d 1052=head2 filename, data
0f3778d0 1053
5760246d 1054Using the C<filename> method, the filename of the data to be parsed
1055can be set. This method can be used in conjunction with the C<data>
1056method, below. If both the C<filename> and C<data> methods are
1057invoked as mutators, the data set in the C<data> method is used.
0f3778d0 1058
1059 $tr->filename("/my/data/files/create.sql");
1060
1061or:
1062
1063 my $create_script = do {
1064 local $/;
1065 open CREATE, "/my/data/files/create.sql" or die $!;
1066 <CREATE>;
1067 };
1068 $tr->data(\$create_script);
1069
5760246d 1070C<filename> takes a string, which is interpreted as a filename.
1071C<data> takes a reference to a string, which is used as the data to be
0f3778d0 1072parsed. If a filename is set, then that file is opened and read when
5760246d 1073the C<translate> method is called, as long as the data instance
0f3778d0 1074variable is not set.
1075
45ee6be0 1076=head2 schema
1077
1078Returns the SQL::Translator::Schema object.
1079
5760246d 1080=head2 trace
0f3778d0 1081
1082Turns on/off the tracing option of Parse::RecDescent.
1083
389b318c 1084=head2 validate
1085
1086Whether or not to validate the schema object after parsing and before
1087producing.
1088
7a8e1f51 1089=head1 AUTHORS
16dc9970 1090
ca251f03 1091Ken Y. Clark, E<lt>kclark@cpan.orgE<gt>,
1092darren chamberlain E<lt>darren@cpan.orgE<gt>,
1093Chris Mungall E<lt>cjm@fruitfly.orgE<gt>,
389b318c 1094Allen Day E<lt>allenday@users.sourceforge.netE<gt>,
1095Sam Angiuoli E<lt>angiuoli@users.sourceforge.netE<gt>,
1096Ying Zhang E<lt>zyolive@yahoo.comE<gt>,
23fb91d9 1097Mike Mellilo E<lt>mmelillo@users.sourceforge.netE<gt>.
dfb4c915 1098
ca10f295 1099=head1 COPYRIGHT
16dc9970 1100
ca10f295 1101This program is free software; you can redistribute it and/or modify
1102it under the terms of the GNU General Public License as published by
1103the Free Software Foundation; version 2.
dfb4c915 1104
ca10f295 1105This program is distributed in the hope that it will be useful, but
1106WITHOUT ANY WARRANTY; without even the implied warranty of
1107MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1108General Public License for more details.
16dc9970 1109
ca10f295 1110You should have received a copy of the GNU General Public License
1111along with this program; if not, write to the Free Software
1112Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
1113USA
16dc9970 1114
87bf8a3a 1115=head1 BUGS
1116
1117Please use http://rt.cpan.org/ for reporting bugs.
1118
16dc9970 1119=head1 SEE ALSO
1120
abfa405a 1121L<perl>,
1122L<SQL::Translator::Parser>,
1123L<SQL::Translator::Producer>,
389b318c 1124L<Parse::RecDescent>,
1125L<GD>,
1126L<GraphViz>,
1127L<Text::RecordParser>,
1128L<Class::DBI>
1129L<XML::Writer>.