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