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