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