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