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