Added Schema and some more dependencies
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator.pm
CommitLineData
16dc9970 1package SQL::Translator;
2
b346d8f1 3# ----------------------------------------------------------------------
f9a0c3b5 4# $Id: Translator.pm,v 1.24 2003-04-24 16:15:58 kycl4rk 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';
f9a0c3b5 30$REVISION = sprintf "%d.%02d", q$Revision: 1.24 $ =~ /(\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
ca10f295 660 eval { require $module };
ca1f2237 661
662 return __PACKAGE__->error($@) if ($@);
ca10f295 663 return 1;
1fd8c91f 664}
16dc9970 665
7d5bcab8 666sub format_table_name {
f9a0c3b5 667 my $self = shift;
668 my $sub = shift;
669 $self->{'_format_table_name'} = $sub if ref $sub eq 'CODE';
670 return $self->{'_format_table_name'}->( $sub, @_ )
671 if defined $self->{'_format_table_name'};
672 return $sub;
7d5bcab8 673}
674
675sub format_package_name {
f9a0c3b5 676 my $self = shift;
677 my $sub = shift;
678 $self->{'_format_package_name'} = $sub if ref $sub eq 'CODE';
679 return $self->{'_format_package_name'}->( $sub, @_ )
680 if defined $self->{'_format_package_name'};
681 return $sub;
7d5bcab8 682}
683
684sub format_fk_name {
f9a0c3b5 685 my $self = shift;
686 my $sub = shift;
687 $self->{'_format_fk_name'} = $sub if ref $sub eq 'CODE';
688 return $self->{'_format_fk_name'}->( $sub, @_ )
689 if defined $self->{'_format_fk_name'};
690 return $sub;
7d5bcab8 691}
692
693sub format_pk_name {
f9a0c3b5 694 my $self = shift;
695 my $sub = shift;
696 $self->{'_format_pk_name'} = $sub if ref $sub eq 'CODE';
697 return $self->{'_format_pk_name'}->( $sub, @_ )
698 if defined $self->{'_format_pk_name'};
699 return $sub;
7d5bcab8 700}
701
d529894e 702# ----------------------------------------------------------------------
0f3778d0 703# isa($ref, $type)
704#
705# Calls UNIVERSAL::isa($ref, $type). I think UNIVERSAL::isa is ugly,
706# but I like function overhead.
707# ----------------------------------------------------------------------
708sub isa($$) {
709 my ($ref, $type) = @_;
710 return UNIVERSAL::isa($ref, $type);
711}
c2d3a526 712
16dc9970 7131;
16dc9970 714#-----------------------------------------------------
715# Rescue the drowning and tie your shoestrings.
716# Henry David Thoreau
717#-----------------------------------------------------
718
0f3778d0 719__END__
720
721=head1 NAME
722
723SQL::Translator - convert schema from one database to another
724
725=head1 SYNOPSIS
726
727 use SQL::Translator;
728
729 my $translator = SQL::Translator->new(
87bf8a3a 730 debug => 1, # Print debug info
731 trace => 0, # Print Parse::RecDescent trace
732 no_comments => 0, # Don't include comments in output
733 show_warnings => 0, # Print name mutations, conflicts
734 add_drop_table => 1, # Add "drop table" statements
7d5bcab8 735
f9a0c3b5 736 # Make all table names CAPS in producers which support this option
7d5bcab8 737 format_table_name => sub {my $tablename = shift; return uc($tablename)},
f9a0c3b5 738
739 # Null-op formatting, only here for documentation's sake
7d5bcab8 740 format_package_name => sub {return shift},
741 format_fk_name => sub {return shift},
742 format_pk_name => sub {return shift},
0f3778d0 743 );
744
745 my $output = $translator->translate(
746 from => "MySQL",
747 to => "Oracle",
f9a0c3b5 748 # Or an arrayref of filenames, i.e. [ $file1, $file2, $file3 ]
749 filename => $file,
0f3778d0 750 ) or die $translator->error;
751
752 print $output;
753
754=head1 DESCRIPTION
755
756This module attempts to simplify the task of converting one database
757create syntax to another through the use of Parsers (which understand
758the source format) and Producers (which understand the destination
759format). The idea is that any Parser can be used with any Producer in
760the conversion process. So, if you wanted Postgres-to-Oracle, you
761would use the Postgres parser and the Oracle producer.
762
763=head1 CONSTRUCTOR
764
765The constructor is called B<new>, and accepts a optional hash of options.
766Valid options are:
767
768=over 4
769
ca251f03 770=item *
771
772parser / from
773
774=item *
775
776parser_args
0f3778d0 777
ca251f03 778=item *
0f3778d0 779
ca251f03 780producer / to
0f3778d0 781
ca251f03 782=item *
0f3778d0 783
ca251f03 784producer_args
0f3778d0 785
ca251f03 786=item *
787
788filename / file
789
790=item *
791
792data
793
794=item *
0f3778d0 795
ca251f03 796debug
0f3778d0 797
798=back
799
800All options are, well, optional; these attributes can be set via
801instance methods. Internally, they are; no (non-syntactical)
802advantage is gained by passing options to the constructor.
803
804=head1 METHODS
805
806=head2 B<add_drop_table>
807
808Toggles whether or not to add "DROP TABLE" statements just before the
809create definitions.
810
811=head2 B<custom_translate>
812
813Allows the user to override default translation of fields. For example,
814if a MySQL "text" field would normally be converted to a "long" for Oracle,
815the user could specify to change it to a "CLOB." Accepts a hashref where
816keys are the "from" value and values are the "to," returns the current
817value of the field.
818
819=head2 B<no_comments>
820
821Toggles whether to print comments in the output. Accepts a true or false
822value, returns the current value.
823
824=head2 B<producer>
825
826The B<producer> method is an accessor/mutator, used to retrieve or
827define what subroutine is called to produce the output. A subroutine
828defined as a producer will be invoked as a function (I<not a method>)
ca251f03 829and passed 2 parameters: its container C<SQL::Translator> instance and a
0f3778d0 830data structure. It is expected that the function transform the data
ca251f03 831structure to a string. The C<SQL::Transformer> instance is provided for
0f3778d0 832informational purposes; for example, the type of the parser can be
833retrieved using the B<parser_type> method, and the B<error> and
834B<debug> methods can be called when needed.
835
ca251f03 836When defining a producer, one of several things can be passed in: A
837module name (e.g., C<My::Groovy::Producer>, a module name relative to
838the C<SQL::Translator::Producer> namespace (e.g., MySQL), a module
839name and function combination (C<My::Groovy::Producer::transmogrify>),
0f3778d0 840or a reference to an anonymous subroutine. If a full module name is
841passed in (for the purposes of this method, a string containing "::"
842is considered to be a module name), it is treated as a package, and a
ca251f03 843function called "produce" will be invoked: C<$modulename::produce>.
844If $modulename cannot be loaded, the final portion is stripped off and
0f3778d0 845treated as a function. In other words, if there is no file named
ca251f03 846F<My/Groovy/Producer/transmogrify.pm>, C<SQL::Translator> will attempt
847to load F<My/Groovy/Producer.pm> and use transmogrify as the name of
848the function, instead of the default "produce".
0f3778d0 849
850 my $tr = SQL::Translator->new;
851
852 # This will invoke My::Groovy::Producer::produce($tr, $data)
853 $tr->producer("My::Groovy::Producer");
854
855 # This will invoke SQL::Translator::Producer::Sybase::produce($tr, $data)
856 $tr->producer("Sybase");
857
858 # This will invoke My::Groovy::Producer::transmogrify($tr, $data),
859 # assuming that My::Groovy::Producer::transmogrify is not a module
860 # on disk.
861 $tr->producer("My::Groovy::Producer::transmogrify");
862
863 # This will invoke the referenced subroutine directly, as
864 # $subref->($tr, $data);
865 $tr->producer(\&my_producer);
866
867There is also a method named B<producer_type>, which is a string
868containing the classname to which the above B<produce> function
869belongs. In the case of anonymous subroutines, this method returns
870the string "CODE".
871
872Finally, there is a method named B<producer_args>, which is both an
873accessor and a mutator. Arbitrary data may be stored in name => value
874pairs for the producer subroutine to access:
875
876 sub My::Random::producer {
877 my ($tr, $data) = @_;
878 my $pr_args = $tr->producer_args();
879
880 # $pr_args is a hashref.
881
882Extra data passed to the B<producer> method is passed to
883B<producer_args>:
884
885 $tr->producer("xSV", delimiter => ',\s*');
886
887 # In SQL::Translator::Producer::xSV:
888 my $args = $tr->producer_args;
889 my $delimiter = $args->{'delimiter'}; # value is ,\s*
890
891=head2 B<parser>
892
893The B<parser> method defines or retrieves a subroutine that will be
894called to perform the parsing. The basic idea is the same as that of
895B<producer> (see above), except the default subroutine name is
ca251f03 896"parse", and will be invoked as C<$module_name::parse($tr, $data)>.
0f3778d0 897Also, the parser subroutine will be passed a string containing the
898entirety of the data to be parsed.
899
900 # Invokes SQL::Translator::Parser::MySQL::parse()
901 $tr->parser("MySQL");
902
903 # Invokes My::Groovy::Parser::parse()
904 $tr->parser("My::Groovy::Parser");
905
906 # Invoke an anonymous subroutine directly
907 $tr->parser(sub {
908 my $dumper = Data::Dumper->new([ $_[1] ], [ "SQL" ]);
909 $dumper->Purity(1)->Terse(1)->Deepcopy(1);
910 return $dumper->Dump;
911 });
912
913There is also B<parser_type> and B<parser_args>, which perform
914analogously to B<producer_type> and B<producer_args>
915
916=head2 B<show_warnings>
917
918Toggles whether to print warnings of name conflicts, identifier
919mutations, etc. Probably only generated by producers to let the user
920know when something won't translate very smoothly (e.g., MySQL "enum"
921fields into Oracle). Accepts a true or false value, returns the
922current value.
923
924=head2 B<translate>
925
926The B<translate> method calls the subroutines referenced by the
927B<parser> and B<producer> data members (described above). It accepts
928as arguments a number of things, in key => value format, including
929(potentially) a parser and a producer (they are passed directly to the
930B<parser> and B<producer> methods).
931
932Here is how the parameter list to B<translate> is parsed:
933
934=over
935
936=item *
937
9381 argument means it's the data to be parsed; which could be a string
ca251f03 939(filename) or a reference to a scalar (a string stored in memory), or a
0f3778d0 940reference to a hash, which is parsed as being more than one argument
941(see next section).
942
943 # Parse the file /path/to/datafile
944 my $output = $tr->translate("/path/to/datafile");
945
946 # Parse the data contained in the string $data
947 my $output = $tr->translate(\$data);
948
949=item *
950
951More than 1 argument means its a hash of things, and it might be
952setting a parser, producer, or datasource (this key is named
953"filename" or "file" if it's a file, or "data" for a SCALAR reference.
954
955 # As above, parse /path/to/datafile, but with different producers
956 for my $prod ("MySQL", "XML", "Sybase") {
957 print $tr->translate(
958 producer => $prod,
959 filename => "/path/to/datafile",
960 );
961 }
962
963 # The filename hash key could also be:
964 datasource => \$data,
965
966You get the idea.
967
968=back
969
970=head2 B<filename>, B<data>
971
972Using the B<filename> method, the filename of the data to be parsed
973can be set. This method can be used in conjunction with the B<data>
974method, below. If both the B<filename> and B<data> methods are
975invoked as mutators, the data set in the B<data> method is used.
976
977 $tr->filename("/my/data/files/create.sql");
978
979or:
980
981 my $create_script = do {
982 local $/;
983 open CREATE, "/my/data/files/create.sql" or die $!;
984 <CREATE>;
985 };
986 $tr->data(\$create_script);
987
988B<filename> takes a string, which is interpreted as a filename.
989B<data> takes a reference to a string, which is used as the data to be
990parsed. If a filename is set, then that file is opened and read when
991the B<translate> method is called, as long as the data instance
992variable is not set.
993
994=pod
995
996=head2 B<trace>
997
998Turns on/off the tracing option of Parse::RecDescent.
999
49e1eb70 1000=pod
1001
7a8e1f51 1002=head1 AUTHORS
16dc9970 1003
ca251f03 1004Ken Y. Clark, E<lt>kclark@cpan.orgE<gt>,
1005darren chamberlain E<lt>darren@cpan.orgE<gt>,
1006Chris Mungall E<lt>cjm@fruitfly.orgE<gt>,
1007Allen Day E<lt>allenday@users.sourceforge.netE<gt>
dfb4c915 1008
ca10f295 1009=head1 COPYRIGHT
16dc9970 1010
ca10f295 1011This program is free software; you can redistribute it and/or modify
1012it under the terms of the GNU General Public License as published by
1013the Free Software Foundation; version 2.
dfb4c915 1014
ca10f295 1015This program is distributed in the hope that it will be useful, but
1016WITHOUT ANY WARRANTY; without even the implied warranty of
1017MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1018General Public License for more details.
16dc9970 1019
ca10f295 1020You should have received a copy of the GNU General Public License
1021along with this program; if not, write to the Free Software
1022Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
1023USA
16dc9970 1024
87bf8a3a 1025=head1 BUGS
1026
1027Please use http://rt.cpan.org/ for reporting bugs.
1028
16dc9970 1029=head1 SEE ALSO
1030
abfa405a 1031L<perl>,
1032L<SQL::Translator::Parser>,
1033L<SQL::Translator::Producer>,
1034L<Parse::RecDescent>
16dc9970 1035