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