More cosmetic changes to make comments pretty, added ability to set
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator.pm
CommitLineData
16dc9970 1package SQL::Translator;
2
b346d8f1 3# ----------------------------------------------------------------------
4b6a6341 4# $Id: Translator.pm,v 1.37 2003-07-31 20:49:42 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';
4b6a6341 32$REVISION = sprintf "%d.%02d", q$Revision: 1.37 $ =~ /(\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# ----------------------------------------------------------------------
409sub schema {
410#
411# Returns the SQL::Translator::Schema object
412#
413 my $self = shift;
414
415 unless ( defined $self->{'schema'} ) {
416 $self->{'schema'} = SQL::Translator::Schema->new;
417 }
d529894e 418
45ee6be0 419 return $self->{'schema'};
420}
421
422# ----------------------------------------------------------------------
d529894e 423sub trace {
424 my $self = shift;
425 my $arg = shift;
426 if ( defined $arg ) {
427 $self->{'trace'} = $arg ? 1 : 0;
428 }
429 return $self->{'trace'} || 0;
430}
431
432# ----------------------------------------------------------------------
0f3778d0 433# translate([source], [\%args])
434#
435# translate does the actual translation. The main argument is the
436# source of the data to be translated, which can be a filename, scalar
437# reference, or glob reference.
438#
439# Alternatively, translate takes optional arguements, which are passed
440# to the appropriate places. Most notable of these arguments are
441# parser and producer, which can be used to set the parser and
442# producer, respectively. This is the applications last chance to set
443# these.
444#
445# translate returns a string.
446# ----------------------------------------------------------------------
ca251f03 447sub translate {
448 my $self = shift;
449 my ($args, $parser, $parser_type, $producer, $producer_type);
450 my ($parser_output, $producer_output);
ca10f295 451
7a8e1f51 452 # Parse arguments
9398955f 453 if (@_ == 1) {
7a8e1f51 454 # Passed a reference to a hash?
ca10f295 455 if (isa($_[0], 'HASH')) {
7a8e1f51 456 # yep, a hashref
49e1eb70 457 $self->debug("translate: Got a hashref\n");
ca10f295 458 $args = $_[0];
459 }
9398955f 460
0f3778d0 461 # Passed a GLOB reference, i.e., filehandle
462 elsif (isa($_[0], 'GLOB')) {
463 $self->debug("translate: Got a GLOB reference\n");
464 $self->data($_[0]);
465 }
466
7a8e1f51 467 # Passed a reference to a string containing the data
ca10f295 468 elsif (isa($_[0], 'SCALAR')) {
9398955f 469 # passed a ref to a string
49e1eb70 470 $self->debug("translate: Got a SCALAR reference (string)\n");
9398955f 471 $self->data($_[0]);
ca10f295 472 }
9398955f 473
7a8e1f51 474 # Not a reference; treat it as a filename
b346d8f1 475 elsif (! ref $_[0]) {
ca10f295 476 # Not a ref, it's a filename
49e1eb70 477 $self->debug("translate: Got a filename\n");
9398955f 478 $self->filename($_[0]);
ca10f295 479 }
9398955f 480
7a8e1f51 481 # Passed something else entirely.
b346d8f1 482 else {
483 # We're not impressed. Take your empty string and leave.
38254289 484 # return "";
485
7a8e1f51 486 # Actually, if data, parser, and producer are set, then we
487 # can continue. Too bad, because I like my comment
488 # (above)...
38254289 489 return "" unless ($self->data &&
490 $self->producer &&
491 $self->parser);
b346d8f1 492 }
16dc9970 493 }
494 else {
b346d8f1 495 # You must pass in a hash, or you get nothing.
496 return "" if @_ % 2;
ca10f295 497 $args = { @_ };
7a8e1f51 498 }
16dc9970 499
9398955f 500 # ----------------------------------------------------------------------
501 # Can specify the data to be transformed using "filename", "file",
7a8e1f51 502 # "data", or "datasource".
9398955f 503 # ----------------------------------------------------------------------
7a8e1f51 504 if (my $filename = ($args->{'filename'} || $args->{'file'})) {
9398955f 505 $self->filename($filename);
506 }
ca10f295 507
422298aa 508 if (my $data = ($args->{'data'} || $args->{'datasource'})) {
9398955f 509 $self->data($data);
16dc9970 510 }
ca10f295 511
9398955f 512 # ----------------------------------------------------------------
513 # Get the data.
514 # ----------------------------------------------------------------
515 my $data = $self->data;
5457eaf0 516 unless (ref($data) eq 'SCALAR' and length $$data) {
c2d3a526 517 return $self->error("Empty data file!");
9398955f 518 }
077ebf34 519
9398955f 520 # ----------------------------------------------------------------
ca10f295 521 # Local reference to the parser subroutine
9398955f 522 # ----------------------------------------------------------------
ca10f295 523 if ($parser = ($args->{'parser'} || $args->{'from'})) {
524 $self->parser($parser);
16dc9970 525 }
7a8e1f51 526 $parser = $self->parser;
527 $parser_type = $self->parser_type;
16dc9970 528
9398955f 529 # ----------------------------------------------------------------
ca10f295 530 # Local reference to the producer subroutine
9398955f 531 # ----------------------------------------------------------------
ca10f295 532 if ($producer = ($args->{'producer'} || $args->{'to'})) {
533 $self->producer($producer);
16dc9970 534 }
7a8e1f51 535 $producer = $self->producer;
536 $producer_type = $self->producer_type;
16dc9970 537
9398955f 538 # ----------------------------------------------------------------
7a8e1f51 539 # Execute the parser, then execute the producer with that output.
540 # Allowances are made for each piece to die, or fail to compile,
541 # since the referenced subroutines could be almost anything. In
542 # the future, each of these might happen in a Safe environment,
543 # depending on how paranoid we want to be.
9398955f 544 # ----------------------------------------------------------------
dbe45b7c 545 eval { $parser_output = $parser->($self, $$data) };
7a8e1f51 546 if ($@ || ! $parser_output) {
547 my $msg = sprintf "translate: Error with parser '%s': %s",
548 $parser_type, ($@) ? $@ : " no results";
c2d3a526 549 return $self->error($msg);
7a8e1f51 550 }
551
4b6a6341 552 if ($self->validate) {
3f4af30d 553 my $schema = $self->schema;
554 return $self->error('Invalid schema') unless $schema->is_valid;
555 }
556
557 eval { $producer_output = $producer->($self) };
7a8e1f51 558 if ($@ || ! $producer_output) {
559 my $msg = sprintf "translate: Error with producer '%s': %s",
560 $producer_type, ($@) ? $@ : " no results";
c2d3a526 561 return $self->error($msg);
7a8e1f51 562 }
563
564 return $producer_output;
16dc9970 565}
ca10f295 566
d529894e 567# ----------------------------------------------------------------------
0f3778d0 568# list_parsers()
569#
570# Hacky sort of method to list all available parsers. This has
571# several problems:
572#
573# - Only finds things in the SQL::Translator::Parser namespace
574#
575# - Only finds things that are located in the same directory
576# as SQL::Translator::Parser. Yeck.
577#
578# This method will fail in several very likely cases:
579#
580# - Parser modules in different namespaces
581#
582# - Parser modules in the SQL::Translator::Parser namespace that
583# have any XS componenets will be installed in
584# arch_lib/SQL/Translator.
585#
586# ----------------------------------------------------------------------
587sub list_parsers {
ca1f2237 588 return shift->_list("parser");
0f3778d0 589}
590
591# ----------------------------------------------------------------------
592# list_producers()
593#
594# See notes for list_parsers(), above; all the problems apply to
595# list_producers as well.
596# ----------------------------------------------------------------------
c0c4aef9 597sub list_producers {
ca1f2237 598 return shift->_list("producer");
0f3778d0 599}
600
c0c4aef9 601
0f3778d0 602# ======================================================================
603# Private Methods
604# ======================================================================
c0c4aef9 605
0f3778d0 606# ----------------------------------------------------------------------
607# _args($type, \%args);
608#
609# Gets or sets ${type}_args. Called by parser_args and producer_args.
610# ----------------------------------------------------------------------
611sub _args {
612 my $self = shift;
613 my $type = shift;
614 $type = "${type}_args" unless $type =~ /_args$/;
615
616 unless (defined $self->{$type} && isa($self->{$type}, 'HASH')) {
617 $self->{$type} = { };
618 }
619
620 if (@_) {
621 # If the first argument is an explicit undef (remember, we
622 # don't get here unless there is stuff in @_), then we clear
623 # out the producer_args hash.
624 if (! defined $_[0]) {
625 shift @_;
626 %{$self->{$type}} = ();
627 }
628
629 my $args = isa($_[0], 'HASH') ? shift : { @_ };
630 %{$self->{$type}} = (%{$self->{$type}}, %$args);
631 }
632
633 $self->{$type};
c0c4aef9 634}
635
d529894e 636# ----------------------------------------------------------------------
0f3778d0 637# _list($type)
638# ----------------------------------------------------------------------
639sub _list {
ca1f2237 640 my $self = shift;
641 my $type = shift || return ();
642 my $uctype = ucfirst lc $type;
643 my %found;
644
645 load("SQL::Translator::$uctype") or return ();
646 my $path = catfile "SQL", "Translator", $uctype;
647 for (@INC) {
648 my $dir = catfile $_, $path;
4b6a6341 649 $self->debug("_list_${type}s searching $dir\n");
ca1f2237 650 next unless -d $dir;
651
652 my $dh = IO::Dir->new($dir);
653 for (grep /\.pm$/, $dh->read) {
654 s/\.pm$//;
655 $found{ join "::", "SQL::Translator::$uctype", $_ } = 1;
656 }
657 }
c0c4aef9 658
ca1f2237 659 return keys %found;
c0c4aef9 660}
661
d529894e 662# ----------------------------------------------------------------------
0f3778d0 663# load($module)
664#
665# Loads a Perl module. Short circuits if a module is already loaded.
666# ----------------------------------------------------------------------
ca10f295 667sub load {
668 my $module = do { my $m = shift; $m =~ s[::][/]g; "$m.pm" };
669 return 1 if $INC{$module};
ca1f2237 670
5760246d 671 eval {
672 require $module;
673 $module->import(@_);
674 };
ca1f2237 675
676 return __PACKAGE__->error($@) if ($@);
ca10f295 677 return 1;
1fd8c91f 678}
16dc9970 679
67e5ff53 680# ----------------------------------------------------------------------
7d5bcab8 681sub format_table_name {
f9a0c3b5 682 my $self = shift;
683 my $sub = shift;
684 $self->{'_format_table_name'} = $sub if ref $sub eq 'CODE';
685 return $self->{'_format_table_name'}->( $sub, @_ )
686 if defined $self->{'_format_table_name'};
687 return $sub;
7d5bcab8 688}
689
67e5ff53 690# ----------------------------------------------------------------------
7d5bcab8 691sub format_package_name {
f9a0c3b5 692 my $self = shift;
693 my $sub = shift;
694 $self->{'_format_package_name'} = $sub if ref $sub eq 'CODE';
695 return $self->{'_format_package_name'}->( $sub, @_ )
696 if defined $self->{'_format_package_name'};
697 return $sub;
7d5bcab8 698}
699
67e5ff53 700# ----------------------------------------------------------------------
7d5bcab8 701sub format_fk_name {
f9a0c3b5 702 my $self = shift;
c703e51d 703
704 if ( ref $_[0] eq 'CODE' ) {
705 $self->{'_format_pk_name'} = shift;
706 }
707
708 if ( @_ ) {
709 if ( defined $self->{'_format_pk_name'} ) {
710 return $self->{'_format_pk_name'}->( @_ );
711 }
712 else {
713 return '';
714 }
715 }
716
717 return $self->{'_format_pk_name'};
718# my $sub = shift;
719# $self->{'_format_fk_name'} = $sub if ref $sub eq 'CODE';
720# return $self->{'_format_fk_name'}->( $sub, @_ )
721# if defined $self->{'_format_fk_name'};
722# return $sub;
7d5bcab8 723}
724
67e5ff53 725# ----------------------------------------------------------------------
7d5bcab8 726sub format_pk_name {
f9a0c3b5 727 my $self = shift;
8a990c91 728
729 if ( ref $_[0] eq 'CODE' ) {
730 $self->{'_format_pk_name'} = shift;
731 }
732
733 if ( @_ ) {
734 if ( defined $self->{'_format_pk_name'} ) {
735 return $self->{'_format_pk_name'}->( @_ );
736 }
737 else {
738 return '';
739 }
740 }
741
742 return $self->{'_format_pk_name'};
7d5bcab8 743}
744
d529894e 745# ----------------------------------------------------------------------
0f3778d0 746# isa($ref, $type)
747#
748# Calls UNIVERSAL::isa($ref, $type). I think UNIVERSAL::isa is ugly,
749# but I like function overhead.
750# ----------------------------------------------------------------------
751sub isa($$) {
752 my ($ref, $type) = @_;
753 return UNIVERSAL::isa($ref, $type);
754}
c2d3a526 755
3f4af30d 756# ----------------------------------------------------------------------
757sub validate {
3f4af30d 758 my ( $self, $arg ) = @_;
759 if ( defined $arg ) {
760 $self->{'validate'} = $arg ? 1 : 0;
761 }
762 return $self->{'validate'} || 0;
763}
764
16dc9970 7651;
16dc9970 766
389b318c 767# ----------------------------------------------------------------------
768# Who killed the pork chops?
769# What price bananas?
770# Are you my Angel?
771# Allen Ginsberg
772# ----------------------------------------------------------------------
773
774=pod
0f3778d0 775
776=head1 NAME
777
954f31f1 778SQL::Translator - manipulate structured data definitions (SQL and more)
0f3778d0 779
780=head1 SYNOPSIS
781
782 use SQL::Translator;
783
67e5ff53 784 my $translator = SQL::Translator->new(
785 # Print debug info
786 debug => 1,
787 # Print Parse::RecDescent trace
788 trace => 0,
789 # Don't include comments in output
790 no_comments => 0,
791 # Print name mutations, conflicts
792 show_warnings => 0,
793 # Add "drop table" statements
794 add_drop_table => 1,
795 # Validate schema object
796 validate => 1,
f9a0c3b5 797 # Make all table names CAPS in producers which support this option
67e5ff53 798 format_table_name => sub {my $tablename = shift; return uc($tablename)},
f9a0c3b5 799 # Null-op formatting, only here for documentation's sake
7d5bcab8 800 format_package_name => sub {return shift},
801 format_fk_name => sub {return shift},
802 format_pk_name => sub {return shift},
0f3778d0 803 );
804
805 my $output = $translator->translate(
389b318c 806 from => 'MySQL',
807 to => 'Oracle',
f9a0c3b5 808 # Or an arrayref of filenames, i.e. [ $file1, $file2, $file3 ]
809 filename => $file,
0f3778d0 810 ) or die $translator->error;
811
812 print $output;
813
814=head1 DESCRIPTION
815
29efc9fd 816SQL::Translator is a group of Perl modules that converts
817vendor-specific SQL table definitions into other formats, such as
818other vendor-specific SQL, ER diagrams, documentation (POD and HTML),
819XML, and Class::DBI classes. The main focus of SQL::Translator is
820SQL, but parsers exist for other structured data formats, including
821Excel spreadsheets and arbitrarily delimited text files. Through the
822separation of the code into parsers and producers with an object model
823in between, it's possible to combine any parser with any producer, to
824plug in custom parsers or producers, or to manipulate the parsed data
825via the built-in object model. Presently only the definition parts of
826SQL are handled (CREATE, ALTER), not the manipulation of data (INSERT,
827UPDATE, DELETE).
0f3778d0 828
829=head1 CONSTRUCTOR
830
5760246d 831The constructor is called C<new>, and accepts a optional hash of options.
0f3778d0 832Valid options are:
833
834=over 4
835
ca251f03 836=item *
837
838parser / from
839
840=item *
841
842parser_args
0f3778d0 843
ca251f03 844=item *
0f3778d0 845
ca251f03 846producer / to
0f3778d0 847
ca251f03 848=item *
0f3778d0 849
ca251f03 850producer_args
0f3778d0 851
ca251f03 852=item *
853
854filename / file
855
856=item *
857
858data
859
860=item *
0f3778d0 861
ca251f03 862debug
0f3778d0 863
389b318c 864=item *
865
866add_drop_table
867
868=item *
869
870no_comments
871
872=item *
873
874trace
875
876=item *
877
878validate
879
0f3778d0 880=back
881
882All options are, well, optional; these attributes can be set via
883instance methods. Internally, they are; no (non-syntactical)
884advantage is gained by passing options to the constructor.
885
886=head1 METHODS
887
5760246d 888=head2 add_drop_table
0f3778d0 889
890Toggles whether or not to add "DROP TABLE" statements just before the
891create definitions.
892
5760246d 893=head2 no_comments
0f3778d0 894
895Toggles whether to print comments in the output. Accepts a true or false
896value, returns the current value.
897
5760246d 898=head2 producer
0f3778d0 899
5760246d 900The C<producer> method is an accessor/mutator, used to retrieve or
0f3778d0 901define what subroutine is called to produce the output. A subroutine
902defined as a producer will be invoked as a function (I<not a method>)
ca251f03 903and passed 2 parameters: its container C<SQL::Translator> instance and a
0f3778d0 904data structure. It is expected that the function transform the data
ca251f03 905structure to a string. The C<SQL::Transformer> instance is provided for
0f3778d0 906informational purposes; for example, the type of the parser can be
5760246d 907retrieved using the C<parser_type> method, and the C<error> and
908C<debug> methods can be called when needed.
0f3778d0 909
ca251f03 910When defining a producer, one of several things can be passed in: A
5760246d 911module name (e.g., C<My::Groovy::Producer>), a module name relative to
912the C<SQL::Translator::Producer> namespace (e.g., C<MySQL>), a module
ca251f03 913name and function combination (C<My::Groovy::Producer::transmogrify>),
0f3778d0 914or a reference to an anonymous subroutine. If a full module name is
915passed in (for the purposes of this method, a string containing "::"
916is considered to be a module name), it is treated as a package, and a
ca251f03 917function called "produce" will be invoked: C<$modulename::produce>.
918If $modulename cannot be loaded, the final portion is stripped off and
0f3778d0 919treated as a function. In other words, if there is no file named
ca251f03 920F<My/Groovy/Producer/transmogrify.pm>, C<SQL::Translator> will attempt
5760246d 921to load F<My/Groovy/Producer.pm> and use C<transmogrify> as the name of
922the function, instead of the default C<produce>.
0f3778d0 923
924 my $tr = SQL::Translator->new;
925
926 # This will invoke My::Groovy::Producer::produce($tr, $data)
927 $tr->producer("My::Groovy::Producer");
928
929 # This will invoke SQL::Translator::Producer::Sybase::produce($tr, $data)
930 $tr->producer("Sybase");
931
932 # This will invoke My::Groovy::Producer::transmogrify($tr, $data),
933 # assuming that My::Groovy::Producer::transmogrify is not a module
934 # on disk.
935 $tr->producer("My::Groovy::Producer::transmogrify");
936
937 # This will invoke the referenced subroutine directly, as
938 # $subref->($tr, $data);
939 $tr->producer(\&my_producer);
940
5760246d 941There is also a method named C<producer_type>, which is a string
942containing the classname to which the above C<produce> function
0f3778d0 943belongs. In the case of anonymous subroutines, this method returns
944the string "CODE".
945
5760246d 946Finally, there is a method named C<producer_args>, which is both an
0f3778d0 947accessor and a mutator. Arbitrary data may be stored in name => value
948pairs for the producer subroutine to access:
949
950 sub My::Random::producer {
951 my ($tr, $data) = @_;
952 my $pr_args = $tr->producer_args();
953
954 # $pr_args is a hashref.
955
5760246d 956Extra data passed to the C<producer> method is passed to
957C<producer_args>:
0f3778d0 958
959 $tr->producer("xSV", delimiter => ',\s*');
960
961 # In SQL::Translator::Producer::xSV:
962 my $args = $tr->producer_args;
963 my $delimiter = $args->{'delimiter'}; # value is ,\s*
964
5760246d 965=head2 parser
0f3778d0 966
5760246d 967The C<parser> method defines or retrieves a subroutine that will be
0f3778d0 968called to perform the parsing. The basic idea is the same as that of
5760246d 969C<producer> (see above), except the default subroutine name is
ca251f03 970"parse", and will be invoked as C<$module_name::parse($tr, $data)>.
0f3778d0 971Also, the parser subroutine will be passed a string containing the
972entirety of the data to be parsed.
973
974 # Invokes SQL::Translator::Parser::MySQL::parse()
975 $tr->parser("MySQL");
976
977 # Invokes My::Groovy::Parser::parse()
978 $tr->parser("My::Groovy::Parser");
979
980 # Invoke an anonymous subroutine directly
981 $tr->parser(sub {
982 my $dumper = Data::Dumper->new([ $_[1] ], [ "SQL" ]);
983 $dumper->Purity(1)->Terse(1)->Deepcopy(1);
984 return $dumper->Dump;
985 });
986
5760246d 987There is also C<parser_type> and C<parser_args>, which perform
988analogously to C<producer_type> and C<producer_args>
0f3778d0 989
5760246d 990=head2 show_warnings
0f3778d0 991
992Toggles whether to print warnings of name conflicts, identifier
993mutations, etc. Probably only generated by producers to let the user
994know when something won't translate very smoothly (e.g., MySQL "enum"
995fields into Oracle). Accepts a true or false value, returns the
996current value.
997
5760246d 998=head2 translate
0f3778d0 999
5760246d 1000The C<translate> method calls the subroutines referenced by the
1001C<parser> and C<producer> data members (described above). It accepts
0f3778d0 1002as arguments a number of things, in key => value format, including
1003(potentially) a parser and a producer (they are passed directly to the
5760246d 1004C<parser> and C<producer> methods).
0f3778d0 1005
5760246d 1006Here is how the parameter list to C<translate> is parsed:
0f3778d0 1007
1008=over
1009
1010=item *
1011
10121 argument means it's the data to be parsed; which could be a string
ca251f03 1013(filename) or a reference to a scalar (a string stored in memory), or a
0f3778d0 1014reference to a hash, which is parsed as being more than one argument
1015(see next section).
1016
1017 # Parse the file /path/to/datafile
1018 my $output = $tr->translate("/path/to/datafile");
1019
1020 # Parse the data contained in the string $data
1021 my $output = $tr->translate(\$data);
1022
1023=item *
1024
1025More than 1 argument means its a hash of things, and it might be
1026setting a parser, producer, or datasource (this key is named
1027"filename" or "file" if it's a file, or "data" for a SCALAR reference.
1028
1029 # As above, parse /path/to/datafile, but with different producers
1030 for my $prod ("MySQL", "XML", "Sybase") {
1031 print $tr->translate(
1032 producer => $prod,
1033 filename => "/path/to/datafile",
1034 );
1035 }
1036
1037 # The filename hash key could also be:
1038 datasource => \$data,
1039
1040You get the idea.
1041
1042=back
1043
5760246d 1044=head2 filename, data
0f3778d0 1045
5760246d 1046Using the C<filename> method, the filename of the data to be parsed
1047can be set. This method can be used in conjunction with the C<data>
1048method, below. If both the C<filename> and C<data> methods are
1049invoked as mutators, the data set in the C<data> method is used.
0f3778d0 1050
1051 $tr->filename("/my/data/files/create.sql");
1052
1053or:
1054
1055 my $create_script = do {
1056 local $/;
1057 open CREATE, "/my/data/files/create.sql" or die $!;
1058 <CREATE>;
1059 };
1060 $tr->data(\$create_script);
1061
5760246d 1062C<filename> takes a string, which is interpreted as a filename.
1063C<data> takes a reference to a string, which is used as the data to be
0f3778d0 1064parsed. If a filename is set, then that file is opened and read when
5760246d 1065the C<translate> method is called, as long as the data instance
0f3778d0 1066variable is not set.
1067
45ee6be0 1068=head2 schema
1069
1070Returns the SQL::Translator::Schema object.
1071
5760246d 1072=head2 trace
0f3778d0 1073
1074Turns on/off the tracing option of Parse::RecDescent.
1075
389b318c 1076=head2 validate
1077
1078Whether or not to validate the schema object after parsing and before
1079producing.
1080
7a8e1f51 1081=head1 AUTHORS
16dc9970 1082
ca251f03 1083Ken Y. Clark, E<lt>kclark@cpan.orgE<gt>,
1084darren chamberlain E<lt>darren@cpan.orgE<gt>,
1085Chris Mungall E<lt>cjm@fruitfly.orgE<gt>,
389b318c 1086Allen Day E<lt>allenday@users.sourceforge.netE<gt>,
1087Sam Angiuoli E<lt>angiuoli@users.sourceforge.netE<gt>,
1088Ying Zhang E<lt>zyolive@yahoo.comE<gt>,
1089Mike Mellilo <mmelillo@users.sourceforge.net>.
dfb4c915 1090
ca10f295 1091=head1 COPYRIGHT
16dc9970 1092
ca10f295 1093This program is free software; you can redistribute it and/or modify
1094it under the terms of the GNU General Public License as published by
1095the Free Software Foundation; version 2.
dfb4c915 1096
ca10f295 1097This program is distributed in the hope that it will be useful, but
1098WITHOUT ANY WARRANTY; without even the implied warranty of
1099MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1100General Public License for more details.
16dc9970 1101
ca10f295 1102You should have received a copy of the GNU General Public License
1103along with this program; if not, write to the Free Software
1104Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
1105USA
16dc9970 1106
87bf8a3a 1107=head1 BUGS
1108
1109Please use http://rt.cpan.org/ for reporting bugs.
1110
16dc9970 1111=head1 SEE ALSO
1112
abfa405a 1113L<perl>,
1114L<SQL::Translator::Parser>,
1115L<SQL::Translator::Producer>,
389b318c 1116L<Parse::RecDescent>,
1117L<GD>,
1118L<GraphViz>,
1119L<Text::RecordParser>,
1120L<Class::DBI>
1121L<XML::Writer>.