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