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