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