These tests relied on now deprecated action that the raw data structure
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator.pm
CommitLineData
16dc9970 1package SQL::Translator;
2
b346d8f1 3# ----------------------------------------------------------------------
dbe45b7c 4# $Id: Translator.pm,v 1.27 2003-05-09 19:51:28 kycl4rk Exp $
b346d8f1 5# ----------------------------------------------------------------------
abfa405a 6# Copyright (C) 2003 Ken Y. Clark <kclark@cpan.org>,
7# darren chamberlain <darren@cpan.org>,
8# Chris Mungall <cjm@fruitfly.org>
1fd8c91f 9#
077ebf34 10# This program is free software; you can redistribute it and/or
11# modify it under the terms of the GNU General Public License as
12# published by the Free Software Foundation; version 2.
ca10f295 13#
077ebf34 14# This program is distributed in the hope that it will be useful, but
15# WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17# General Public License for more details.
ca10f295 18#
077ebf34 19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22# 02111-1307 USA
ca10f295 23# -------------------------------------------------------------------
24
16dc9970 25use strict;
d529894e 26use vars qw( $VERSION $REVISION $DEFAULT_SUB $DEBUG $ERROR );
49e1eb70 27use base 'Class::Base';
c2d3a526 28
d529894e 29$VERSION = '0.01';
dbe45b7c 30$REVISION = sprintf "%d.%02d", q$Revision: 1.27 $ =~ /(\d+)\.(\d+)/;
d529894e 31$DEBUG = 0 unless defined $DEBUG;
32$ERROR = "";
c2d3a526 33
34use Carp qw(carp);
16dc9970 35
c0c4aef9 36use File::Spec::Functions qw(catfile);
37use File::Basename qw(dirname);
38use IO::Dir;
45ee6be0 39use SQL::Translator::Schema;
c0c4aef9 40
b346d8f1 41# ----------------------------------------------------------------------
42# The default behavior is to "pass through" values (note that the
43# SQL::Translator instance is the first value ($_[0]), and the stuff
44# to be parsed is the second value ($_[1])
45# ----------------------------------------------------------------------
46$DEFAULT_SUB = sub { $_[1] } unless defined $DEFAULT_SUB;
16dc9970 47
b346d8f1 48# ----------------------------------------------------------------------
c2d3a526 49# init([ARGS])
b346d8f1 50# The constructor.
dfb4c915 51#
b346d8f1 52# new takes an optional hash of arguments. These arguments may
53# include a parser, specified with the keys "parser" or "from",
54# and a producer, specified with the keys "producer" or "to".
dfb4c915 55#
b346d8f1 56# The values that can be passed as the parser or producer are
57# given directly to the parser or producer methods, respectively.
58# See the appropriate method description below for details about
59# what each expects/accepts.
b346d8f1 60# ----------------------------------------------------------------------
c2d3a526 61sub init {
49e1eb70 62 my ( $self, $config ) = @_;
1fd8c91f 63
49e1eb70 64 #
b346d8f1 65 # Set the parser and producer.
ca10f295 66 #
b346d8f1 67 # If a 'parser' or 'from' parameter is passed in, use that as the
68 # parser; if a 'producer' or 'to' parameter is passed in, use that
69 # as the producer; both default to $DEFAULT_SUB.
49e1eb70 70 #
71 $self->parser ($config->{'parser'} || $config->{'from'} || $DEFAULT_SUB);
c2d3a526 72 $self->producer($config->{'producer'} || $config->{'to'} || $DEFAULT_SUB);
ca10f295 73
7d5bcab8 74 #
75 # Set up callbacks for formatting of pk,fk,table,package names in producer
76 #
77 $self->format_table_name($config->{'format_table_name'});
78 $self->format_package_name($config->{'format_package_name'});
79 $self->format_fk_name($config->{'format_fk_name'});
80 $self->format_pk_name($config->{'format_pk_name'});
81
49e1eb70 82 #
e2158c40 83 # Set the parser_args and producer_args
49e1eb70 84 #
85 for my $pargs ( qw[ parser_args producer_args ] ) {
86 $self->$pargs( $config->{$pargs} ) if defined $config->{ $pargs };
e2158c40 87 }
88
49e1eb70 89 #
9398955f 90 # Set the data source, if 'filename' or 'file' is provided.
49e1eb70 91 #
c2d3a526 92 $config->{'filename'} ||= $config->{'file'} || "";
49e1eb70 93 $self->filename( $config->{'filename'} ) if $config->{'filename'};
9398955f 94
49e1eb70 95 #
96 # Finally, if there is a 'data' parameter, use that in
97 # preference to filename and file
98 #
99 if ( my $data = $config->{'data'} ) {
100 $self->data( $data );
9398955f 101 }
102
d529894e 103 #
104 # Set various other options.
105 #
49e1eb70 106 $self->{'debug'} = defined $config->{'debug'} ? $config->{'debug'} : $DEBUG;
ca10f295 107
96844cae 108 $self->add_drop_table( $config->{'add_drop_table'} );
d529894e 109
110 $self->custom_translate( $config->{'xlate'} );
111
112 $self->no_comments( $config->{'no_comments'} );
113
96844cae 114 $self->show_warnings( $config->{'show_warnings'} );
115
116 $self->trace( $config->{'trace'} );
117
ca10f295 118 return $self;
dfb4c915 119}
1fd8c91f 120
0f3778d0 121# ----------------------------------------------------------------------
122# add_drop_table([$bool])
123# ----------------------------------------------------------------------
96844cae 124sub add_drop_table {
125 my $self = shift;
126 if ( defined (my $arg = shift) ) {
127 $self->{'add_drop_table'} = $arg ? 1 : 0;
128 }
129 return $self->{'add_drop_table'} || 0;
130}
131
132
0f3778d0 133# ----------------------------------------------------------------------
134# custom_translate([$bool])
135# ----------------------------------------------------------------------
d529894e 136sub custom_translate {
137 my $self = shift;
138 $self->{'custom_translate'} = shift if @_;
139 return $self->{'custom_translate'} || {};
140}
141
0f3778d0 142# ----------------------------------------------------------------------
143# no_comments([$bool])
144# ----------------------------------------------------------------------
d529894e 145sub no_comments {
146 my $self = shift;
147 my $arg = shift;
148 if ( defined $arg ) {
149 $self->{'no_comments'} = $arg ? 1 : 0;
150 }
151 return $self->{'no_comments'} || 0;
152}
153
e2158c40 154
0f3778d0 155# ----------------------------------------------------------------------
156# producer([$producer_spec])
157#
158# Get or set the producer for the current translator.
159# ----------------------------------------------------------------------
ca10f295 160sub producer {
1fd8c91f 161 my $self = shift;
b346d8f1 162
7a8e1f51 163 # producer as a mutator
ca10f295 164 if (@_) {
165 my $producer = shift;
b346d8f1 166
7a8e1f51 167 # Passed a module name (string containing "::")
ca10f295 168 if ($producer =~ /::/) {
077ebf34 169 my $func_name;
b346d8f1 170
7a8e1f51 171 # Module name was passed directly
b346d8f1 172 # We try to load the name; if it doesn't load, there's
173 # a possibility that it has a function name attached to
174 # it.
077ebf34 175 if (load($producer)) {
176 $func_name = "produce";
7a8e1f51 177 }
b346d8f1 178
7a8e1f51 179 # Module::function was passed
b346d8f1 180 else {
181 # Passed Module::Name::function; try to recover
077ebf34 182 my @func_parts = split /::/, $producer;
183 $func_name = pop @func_parts;
184 $producer = join "::", @func_parts;
b346d8f1 185
186 # If this doesn't work, then we have a legitimate
187 # problem.
077ebf34 188 load($producer) or die "Can't load $producer: $@";
7a8e1f51 189 }
077ebf34 190
7a8e1f51 191 # get code reference and assign
077ebf34 192 $self->{'producer'} = \&{ "$producer\::$func_name" };
193 $self->{'producer_type'} = $producer;
49e1eb70 194 $self->debug("Got producer: $producer\::$func_name\n");
7a8e1f51 195 }
b346d8f1 196
7a8e1f51 197 # passed an anonymous subroutine reference
b346d8f1 198 elsif (isa($producer, 'CODE')) {
ca10f295 199 $self->{'producer'} = $producer;
077ebf34 200 $self->{'producer_type'} = "CODE";
49e1eb70 201 $self->debug("Got producer: code ref\n");
7a8e1f51 202 }
b346d8f1 203
7a8e1f51 204 # passed a string containing no "::"; relative package name
b346d8f1 205 else {
ca10f295 206 my $Pp = sprintf "SQL::Translator::Producer::$producer";
207 load($Pp) or die "Can't load $Pp: $@";
077ebf34 208 $self->{'producer'} = \&{ "$Pp\::produce" };
209 $self->{'producer_type'} = $Pp;
49e1eb70 210 $self->debug("Got producer: $Pp\n");
7a8e1f51 211 }
b346d8f1 212
ca10f295 213 # At this point, $self->{'producer'} contains a subroutine
b346d8f1 214 # reference that is ready to run
e2158c40 215
7a8e1f51 216 # Anything left? If so, it's producer_args
217 $self->producer_args(@_) if (@_);
218 }
b346d8f1 219
ca10f295 220 return $self->{'producer'};
221};
077ebf34 222
7a8e1f51 223# ----------------------------------------------------------------------
0f3778d0 224# producer_type()
7a8e1f51 225#
e2158c40 226# producer_type is an accessor that allows producer subs to get
227# information about their origin. This is poptentially important;
ca251f03 228# since all producer subs are called as subroutine references, there is
e2158c40 229# no way for a producer to find out which package the sub lives in
230# originally, for example.
7a8e1f51 231# ----------------------------------------------------------------------
232sub producer_type { $_[0]->{'producer_type'} }
e2158c40 233
7a8e1f51 234# ----------------------------------------------------------------------
0f3778d0 235# producer_args([\%args])
7a8e1f51 236#
e2158c40 237# Arbitrary name => value pairs of paramters can be passed to a
238# producer using this method.
52b828e8 239#
0f3778d0 240# If the first argument passed in is undef, then the hash of arguments
241# is cleared; all subsequent elements are added to the hash of name,
242# value pairs stored as producer_args.
7a8e1f51 243# ----------------------------------------------------------------------
e2158c40 244sub producer_args {
245 my $self = shift;
0f3778d0 246 return $self->_args("producer", @_);
7a8e1f51 247}
ca10f295 248
0f3778d0 249# ----------------------------------------------------------------------
250# parser([$parser_spec])
251# ----------------------------------------------------------------------
ca10f295 252sub parser {
253 my $self = shift;
b346d8f1 254
7a8e1f51 255 # parser as a mutator
ca10f295 256 if (@_) {
257 my $parser = shift;
b346d8f1 258
7a8e1f51 259 # Passed a module name (string containing "::")
ca10f295 260 if ($parser =~ /::/) {
b346d8f1 261 my $func_name;
262
7a8e1f51 263 # Module name was passed directly
b346d8f1 264 # We try to load the name; if it doesn't load, there's
265 # a possibility that it has a function name attached to
266 # it.
267 if (load($parser)) {
268 $func_name = "parse";
7a8e1f51 269 }
b346d8f1 270
7a8e1f51 271 # Module::function was passed
b346d8f1 272 else {
273 # Passed Module::Name::function; try to recover
274 my @func_parts = split /::/, $parser;
275 $func_name = pop @func_parts;
276 $parser = join "::", @func_parts;
277
278 # If this doesn't work, then we have a legitimate
279 # problem.
280 load($parser) or die "Can't load $parser: $@";
7a8e1f51 281 }
b346d8f1 282
7a8e1f51 283 # get code reference and assign
b346d8f1 284 $self->{'parser'} = \&{ "$parser\::$func_name" };
077ebf34 285 $self->{'parser_type'} = $parser;
49e1eb70 286 $self->debug("Got parser: $parser\::$func_name\n");
7a8e1f51 287 }
b346d8f1 288
7a8e1f51 289 # passed an anonymous subroutine reference
49e1eb70 290 elsif ( isa( $parser, 'CODE' ) ) {
291 $self->{'parser'} = $parser;
077ebf34 292 $self->{'parser_type'} = "CODE";
49e1eb70 293 $self->debug("Got parser: code ref\n");
7a8e1f51 294 }
b346d8f1 295
7a8e1f51 296 # passed a string containing no "::"; relative package name
b346d8f1 297 else {
49e1eb70 298 my $Pp = "SQL::Translator::Parser::$parser";
299 load( $Pp ) or die "Can't load $Pp: $@";
300 $self->{'parser'} = \&{ "$Pp\::parse" };
077ebf34 301 $self->{'parser_type'} = $Pp;
49e1eb70 302 $self->debug("Got parser: $Pp\n");
7a8e1f51 303 }
b346d8f1 304
49e1eb70 305 #
b346d8f1 306 # At this point, $self->{'parser'} contains a subroutine
307 # reference that is ready to run
49e1eb70 308 #
309 $self->parser_args( @_ ) if (@_);
7a8e1f51 310 }
b346d8f1 311
ca10f295 312 return $self->{'parser'};
16dc9970 313}
1fd8c91f 314
d529894e 315# ----------------------------------------------------------------------
077ebf34 316sub parser_type { $_[0]->{'parser_type'} }
e2158c40 317
e2158c40 318sub parser_args {
319 my $self = shift;
0f3778d0 320 return $self->_args("parser", @_);
321}
96844cae 322
323sub show_warnings {
324 my $self = shift;
325 my $arg = shift;
326 if ( defined $arg ) {
327 $self->{'show_warnings'} = $arg ? 1 : 0;
328 }
329 return $self->{'show_warnings'} || 0;
330}
331
ca10f295 332
0f3778d0 333# filename - get or set the filename
334sub filename {
335 my $self = shift;
336 if (@_) {
337 my $filename = shift;
338 if (-d $filename) {
339 my $msg = "Cannot use directory '$filename' as input source";
340 return $self->error($msg);
95a2cfb6 341 } elsif (ref($filename) eq 'ARRAY') {
342 $self->{'filename'} = $filename;
343 $self->debug("Got array of files: ".join(', ',@$filename)."\n");
0f3778d0 344 } elsif (-f _ && -r _) {
345 $self->{'filename'} = $filename;
346 $self->debug("Got filename: '$self->{'filename'}'\n");
347 } else {
348 my $msg = "Cannot use '$filename' as input source: ".
349 "file does not exist or is not readable.";
350 return $self->error($msg);
351 }
352 }
ca10f295 353
0f3778d0 354 $self->{'filename'};
355}
ca10f295 356
0f3778d0 357# ----------------------------------------------------------------------
358# data([$data])
359#
360# if $self->{'data'} is not set, but $self->{'filename'} is, then
361# $self->{'filename'} is opened and read, with the results put into
362# $self->{'data'}.
363# ----------------------------------------------------------------------
364sub data {
365 my $self = shift;
ca10f295 366
0f3778d0 367 # Set $self->{'data'} based on what was passed in. We will
368 # accept a number of things; do our best to get it right.
369 if (@_) {
370 my $data = shift;
371 if (isa($data, "SCALAR")) {
372 $self->{'data'} = $data;
373 }
374 else {
375 if (isa($data, 'ARRAY')) {
376 $data = join '', @$data;
377 }
378 elsif (isa($data, 'GLOB')) {
379 local $/;
380 $data = <$data>;
381 }
382 elsif (! ref $data && @_) {
383 $data = join '', $data, @_;
384 }
385 $self->{'data'} = \$data;
386 }
387 }
9398955f 388
7a8e1f51 389 # If we have a filename but no data yet, populate.
9398955f 390 if (not $self->{'data'} and my $filename = $self->filename) {
49e1eb70 391 $self->debug("Opening '$filename' to get contents.\n");
9398955f 392 local *FH;
393 local $/;
394 my $data;
395
95a2cfb6 396 my @files = ref($filename) eq 'ARRAY' ? @$filename : ($filename);
9398955f 397
95a2cfb6 398 foreach my $file (@files) {
399 unless (open FH, $file) {
400 return $self->error("Can't read file '$file': $!");
401 }
9398955f 402
95a2cfb6 403 $data .= <FH>;
404
405 unless (close FH) {
406 return $self->error("Can't close file '$file': $!");
407 }
408 }
409
410 $self->{'data'} = \$data;
9398955f 411 }
9398955f 412
413 return $self->{'data'};
7a8e1f51 414}
9398955f 415
45ee6be0 416# ----------------------------------------------------------------------
417sub schema {
418#
419# Returns the SQL::Translator::Schema object
420#
421 my $self = shift;
422
423 unless ( defined $self->{'schema'} ) {
424 $self->{'schema'} = SQL::Translator::Schema->new;
425 }
d529894e 426
45ee6be0 427 return $self->{'schema'};
428}
429
430# ----------------------------------------------------------------------
d529894e 431sub trace {
432 my $self = shift;
433 my $arg = shift;
434 if ( defined $arg ) {
435 $self->{'trace'} = $arg ? 1 : 0;
436 }
437 return $self->{'trace'} || 0;
438}
439
440# ----------------------------------------------------------------------
0f3778d0 441# translate([source], [\%args])
442#
443# translate does the actual translation. The main argument is the
444# source of the data to be translated, which can be a filename, scalar
445# reference, or glob reference.
446#
447# Alternatively, translate takes optional arguements, which are passed
448# to the appropriate places. Most notable of these arguments are
449# parser and producer, which can be used to set the parser and
450# producer, respectively. This is the applications last chance to set
451# these.
452#
453# translate returns a string.
454# ----------------------------------------------------------------------
ca251f03 455sub translate {
456 my $self = shift;
457 my ($args, $parser, $parser_type, $producer, $producer_type);
458 my ($parser_output, $producer_output);
ca10f295 459
7a8e1f51 460 # Parse arguments
9398955f 461 if (@_ == 1) {
7a8e1f51 462 # Passed a reference to a hash?
ca10f295 463 if (isa($_[0], 'HASH')) {
7a8e1f51 464 # yep, a hashref
49e1eb70 465 $self->debug("translate: Got a hashref\n");
ca10f295 466 $args = $_[0];
467 }
9398955f 468
0f3778d0 469 # Passed a GLOB reference, i.e., filehandle
470 elsif (isa($_[0], 'GLOB')) {
471 $self->debug("translate: Got a GLOB reference\n");
472 $self->data($_[0]);
473 }
474
7a8e1f51 475 # Passed a reference to a string containing the data
ca10f295 476 elsif (isa($_[0], 'SCALAR')) {
9398955f 477 # passed a ref to a string
49e1eb70 478 $self->debug("translate: Got a SCALAR reference (string)\n");
9398955f 479 $self->data($_[0]);
ca10f295 480 }
9398955f 481
7a8e1f51 482 # Not a reference; treat it as a filename
b346d8f1 483 elsif (! ref $_[0]) {
ca10f295 484 # Not a ref, it's a filename
49e1eb70 485 $self->debug("translate: Got a filename\n");
9398955f 486 $self->filename($_[0]);
ca10f295 487 }
9398955f 488
7a8e1f51 489 # Passed something else entirely.
b346d8f1 490 else {
491 # We're not impressed. Take your empty string and leave.
38254289 492 # return "";
493
7a8e1f51 494 # Actually, if data, parser, and producer are set, then we
495 # can continue. Too bad, because I like my comment
496 # (above)...
38254289 497 return "" unless ($self->data &&
498 $self->producer &&
499 $self->parser);
b346d8f1 500 }
16dc9970 501 }
502 else {
b346d8f1 503 # You must pass in a hash, or you get nothing.
504 return "" if @_ % 2;
ca10f295 505 $args = { @_ };
7a8e1f51 506 }
16dc9970 507
9398955f 508 # ----------------------------------------------------------------------
509 # Can specify the data to be transformed using "filename", "file",
7a8e1f51 510 # "data", or "datasource".
9398955f 511 # ----------------------------------------------------------------------
7a8e1f51 512 if (my $filename = ($args->{'filename'} || $args->{'file'})) {
9398955f 513 $self->filename($filename);
514 }
ca10f295 515
422298aa 516 if (my $data = ($args->{'data'} || $args->{'datasource'})) {
9398955f 517 $self->data($data);
16dc9970 518 }
ca10f295 519
9398955f 520 # ----------------------------------------------------------------
521 # Get the data.
522 # ----------------------------------------------------------------
523 my $data = $self->data;
5457eaf0 524 unless (ref($data) eq 'SCALAR' and length $$data) {
c2d3a526 525 return $self->error("Empty data file!");
9398955f 526 }
077ebf34 527
9398955f 528 # ----------------------------------------------------------------
ca10f295 529 # Local reference to the parser subroutine
9398955f 530 # ----------------------------------------------------------------
ca10f295 531 if ($parser = ($args->{'parser'} || $args->{'from'})) {
532 $self->parser($parser);
16dc9970 533 }
7a8e1f51 534 $parser = $self->parser;
535 $parser_type = $self->parser_type;
16dc9970 536
9398955f 537 # ----------------------------------------------------------------
ca10f295 538 # Local reference to the producer subroutine
9398955f 539 # ----------------------------------------------------------------
ca10f295 540 if ($producer = ($args->{'producer'} || $args->{'to'})) {
541 $self->producer($producer);
16dc9970 542 }
7a8e1f51 543 $producer = $self->producer;
544 $producer_type = $self->producer_type;
16dc9970 545
9398955f 546 # ----------------------------------------------------------------
7a8e1f51 547 # Execute the parser, then execute the producer with that output.
548 # Allowances are made for each piece to die, or fail to compile,
549 # since the referenced subroutines could be almost anything. In
550 # the future, each of these might happen in a Safe environment,
551 # depending on how paranoid we want to be.
9398955f 552 # ----------------------------------------------------------------
dbe45b7c 553 eval { $parser_output = $parser->($self, $$data) };
7a8e1f51 554 if ($@ || ! $parser_output) {
555 my $msg = sprintf "translate: Error with parser '%s': %s",
556 $parser_type, ($@) ? $@ : " no results";
c2d3a526 557 return $self->error($msg);
7a8e1f51 558 }
559
dbe45b7c 560 eval { $producer_output = $producer->($self, $parser_output) };
7a8e1f51 561 if ($@ || ! $producer_output) {
562 my $msg = sprintf "translate: Error with producer '%s': %s",
563 $producer_type, ($@) ? $@ : " no results";
c2d3a526 564 return $self->error($msg);
7a8e1f51 565 }
566
567 return $producer_output;
16dc9970 568}
ca10f295 569
d529894e 570# ----------------------------------------------------------------------
0f3778d0 571# list_parsers()
572#
573# Hacky sort of method to list all available parsers. This has
574# several problems:
575#
576# - Only finds things in the SQL::Translator::Parser namespace
577#
578# - Only finds things that are located in the same directory
579# as SQL::Translator::Parser. Yeck.
580#
581# This method will fail in several very likely cases:
582#
583# - Parser modules in different namespaces
584#
585# - Parser modules in the SQL::Translator::Parser namespace that
586# have any XS componenets will be installed in
587# arch_lib/SQL/Translator.
588#
589# ----------------------------------------------------------------------
590sub list_parsers {
ca1f2237 591 return shift->_list("parser");
0f3778d0 592}
593
594# ----------------------------------------------------------------------
595# list_producers()
596#
597# See notes for list_parsers(), above; all the problems apply to
598# list_producers as well.
599# ----------------------------------------------------------------------
c0c4aef9 600sub list_producers {
ca1f2237 601 return shift->_list("producer");
0f3778d0 602}
603
c0c4aef9 604
0f3778d0 605# ======================================================================
606# Private Methods
607# ======================================================================
c0c4aef9 608
0f3778d0 609# ----------------------------------------------------------------------
610# _args($type, \%args);
611#
612# Gets or sets ${type}_args. Called by parser_args and producer_args.
613# ----------------------------------------------------------------------
614sub _args {
615 my $self = shift;
616 my $type = shift;
617 $type = "${type}_args" unless $type =~ /_args$/;
618
619 unless (defined $self->{$type} && isa($self->{$type}, 'HASH')) {
620 $self->{$type} = { };
621 }
622
623 if (@_) {
624 # If the first argument is an explicit undef (remember, we
625 # don't get here unless there is stuff in @_), then we clear
626 # out the producer_args hash.
627 if (! defined $_[0]) {
628 shift @_;
629 %{$self->{$type}} = ();
630 }
631
632 my $args = isa($_[0], 'HASH') ? shift : { @_ };
633 %{$self->{$type}} = (%{$self->{$type}}, %$args);
634 }
635
636 $self->{$type};
c0c4aef9 637}
638
0f3778d0 639
d529894e 640# ----------------------------------------------------------------------
0f3778d0 641# _list($type)
642# ----------------------------------------------------------------------
643sub _list {
ca1f2237 644 my $self = shift;
645 my $type = shift || return ();
646 my $uctype = ucfirst lc $type;
647 my %found;
648
649 load("SQL::Translator::$uctype") or return ();
650 my $path = catfile "SQL", "Translator", $uctype;
651 for (@INC) {
652 my $dir = catfile $_, $path;
653 $self->debug("_list_${type}s searching $dir");
654 next unless -d $dir;
655
656 my $dh = IO::Dir->new($dir);
657 for (grep /\.pm$/, $dh->read) {
658 s/\.pm$//;
659 $found{ join "::", "SQL::Translator::$uctype", $_ } = 1;
660 }
661 }
c0c4aef9 662
ca1f2237 663 return keys %found;
c0c4aef9 664}
665
d529894e 666# ----------------------------------------------------------------------
0f3778d0 667# load($module)
668#
669# Loads a Perl module. Short circuits if a module is already loaded.
670# ----------------------------------------------------------------------
ca10f295 671sub load {
672 my $module = do { my $m = shift; $m =~ s[::][/]g; "$m.pm" };
673 return 1 if $INC{$module};
ca1f2237 674
5760246d 675 eval {
676 require $module;
677 $module->import(@_);
678 };
ca1f2237 679
680 return __PACKAGE__->error($@) if ($@);
ca10f295 681 return 1;
1fd8c91f 682}
16dc9970 683
7d5bcab8 684sub format_table_name {
f9a0c3b5 685 my $self = shift;
686 my $sub = shift;
687 $self->{'_format_table_name'} = $sub if ref $sub eq 'CODE';
688 return $self->{'_format_table_name'}->( $sub, @_ )
689 if defined $self->{'_format_table_name'};
690 return $sub;
7d5bcab8 691}
692
693sub format_package_name {
f9a0c3b5 694 my $self = shift;
695 my $sub = shift;
696 $self->{'_format_package_name'} = $sub if ref $sub eq 'CODE';
697 return $self->{'_format_package_name'}->( $sub, @_ )
698 if defined $self->{'_format_package_name'};
699 return $sub;
7d5bcab8 700}
701
702sub format_fk_name {
f9a0c3b5 703 my $self = shift;
704 my $sub = shift;
705 $self->{'_format_fk_name'} = $sub if ref $sub eq 'CODE';
706 return $self->{'_format_fk_name'}->( $sub, @_ )
707 if defined $self->{'_format_fk_name'};
708 return $sub;
7d5bcab8 709}
710
711sub format_pk_name {
f9a0c3b5 712 my $self = shift;
713 my $sub = shift;
714 $self->{'_format_pk_name'} = $sub if ref $sub eq 'CODE';
715 return $self->{'_format_pk_name'}->( $sub, @_ )
716 if defined $self->{'_format_pk_name'};
717 return $sub;
7d5bcab8 718}
719
d529894e 720# ----------------------------------------------------------------------
0f3778d0 721# isa($ref, $type)
722#
723# Calls UNIVERSAL::isa($ref, $type). I think UNIVERSAL::isa is ugly,
724# but I like function overhead.
725# ----------------------------------------------------------------------
726sub isa($$) {
727 my ($ref, $type) = @_;
728 return UNIVERSAL::isa($ref, $type);
729}
c2d3a526 730
16dc9970 7311;
16dc9970 732#-----------------------------------------------------
733# Rescue the drowning and tie your shoestrings.
734# Henry David Thoreau
735#-----------------------------------------------------
736
0f3778d0 737__END__
738
739=head1 NAME
740
741SQL::Translator - convert schema from one database to another
742
743=head1 SYNOPSIS
744
745 use SQL::Translator;
746
747 my $translator = SQL::Translator->new(
87bf8a3a 748 debug => 1, # Print debug info
749 trace => 0, # Print Parse::RecDescent trace
750 no_comments => 0, # Don't include comments in output
751 show_warnings => 0, # Print name mutations, conflicts
752 add_drop_table => 1, # Add "drop table" statements
7d5bcab8 753
f9a0c3b5 754 # Make all table names CAPS in producers which support this option
7d5bcab8 755 format_table_name => sub {my $tablename = shift; return uc($tablename)},
f9a0c3b5 756
757 # Null-op formatting, only here for documentation's sake
7d5bcab8 758 format_package_name => sub {return shift},
759 format_fk_name => sub {return shift},
760 format_pk_name => sub {return shift},
0f3778d0 761 );
762
763 my $output = $translator->translate(
764 from => "MySQL",
765 to => "Oracle",
f9a0c3b5 766 # Or an arrayref of filenames, i.e. [ $file1, $file2, $file3 ]
767 filename => $file,
0f3778d0 768 ) or die $translator->error;
769
770 print $output;
771
772=head1 DESCRIPTION
773
774This module attempts to simplify the task of converting one database
775create syntax to another through the use of Parsers (which understand
776the source format) and Producers (which understand the destination
777format). The idea is that any Parser can be used with any Producer in
778the conversion process. So, if you wanted Postgres-to-Oracle, you
779would use the Postgres parser and the Oracle producer.
780
781=head1 CONSTRUCTOR
782
5760246d 783The constructor is called C<new>, and accepts a optional hash of options.
0f3778d0 784Valid options are:
785
786=over 4
787
ca251f03 788=item *
789
790parser / from
791
792=item *
793
794parser_args
0f3778d0 795
ca251f03 796=item *
0f3778d0 797
ca251f03 798producer / to
0f3778d0 799
ca251f03 800=item *
0f3778d0 801
ca251f03 802producer_args
0f3778d0 803
ca251f03 804=item *
805
806filename / file
807
808=item *
809
810data
811
812=item *
0f3778d0 813
ca251f03 814debug
0f3778d0 815
816=back
817
818All options are, well, optional; these attributes can be set via
819instance methods. Internally, they are; no (non-syntactical)
820advantage is gained by passing options to the constructor.
821
822=head1 METHODS
823
5760246d 824=head2 add_drop_table
0f3778d0 825
826Toggles whether or not to add "DROP TABLE" statements just before the
827create definitions.
828
5760246d 829=head2 custom_translate
0f3778d0 830
831Allows the user to override default translation of fields. For example,
832if a MySQL "text" field would normally be converted to a "long" for Oracle,
833the user could specify to change it to a "CLOB." Accepts a hashref where
834keys are the "from" value and values are the "to," returns the current
835value of the field.
836
5760246d 837=head2 no_comments
0f3778d0 838
839Toggles whether to print comments in the output. Accepts a true or false
840value, returns the current value.
841
5760246d 842=head2 producer
0f3778d0 843
5760246d 844The C<producer> method is an accessor/mutator, used to retrieve or
0f3778d0 845define what subroutine is called to produce the output. A subroutine
846defined as a producer will be invoked as a function (I<not a method>)
ca251f03 847and passed 2 parameters: its container C<SQL::Translator> instance and a
0f3778d0 848data structure. It is expected that the function transform the data
ca251f03 849structure to a string. The C<SQL::Transformer> instance is provided for
0f3778d0 850informational purposes; for example, the type of the parser can be
5760246d 851retrieved using the C<parser_type> method, and the C<error> and
852C<debug> methods can be called when needed.
0f3778d0 853
ca251f03 854When defining a producer, one of several things can be passed in: A
5760246d 855module name (e.g., C<My::Groovy::Producer>), a module name relative to
856the C<SQL::Translator::Producer> namespace (e.g., C<MySQL>), a module
ca251f03 857name and function combination (C<My::Groovy::Producer::transmogrify>),
0f3778d0 858or a reference to an anonymous subroutine. If a full module name is
859passed in (for the purposes of this method, a string containing "::"
860is considered to be a module name), it is treated as a package, and a
ca251f03 861function called "produce" will be invoked: C<$modulename::produce>.
862If $modulename cannot be loaded, the final portion is stripped off and
0f3778d0 863treated as a function. In other words, if there is no file named
ca251f03 864F<My/Groovy/Producer/transmogrify.pm>, C<SQL::Translator> will attempt
5760246d 865to load F<My/Groovy/Producer.pm> and use C<transmogrify> as the name of
866the function, instead of the default C<produce>.
0f3778d0 867
868 my $tr = SQL::Translator->new;
869
870 # This will invoke My::Groovy::Producer::produce($tr, $data)
871 $tr->producer("My::Groovy::Producer");
872
873 # This will invoke SQL::Translator::Producer::Sybase::produce($tr, $data)
874 $tr->producer("Sybase");
875
876 # This will invoke My::Groovy::Producer::transmogrify($tr, $data),
877 # assuming that My::Groovy::Producer::transmogrify is not a module
878 # on disk.
879 $tr->producer("My::Groovy::Producer::transmogrify");
880
881 # This will invoke the referenced subroutine directly, as
882 # $subref->($tr, $data);
883 $tr->producer(\&my_producer);
884
5760246d 885There is also a method named C<producer_type>, which is a string
886containing the classname to which the above C<produce> function
0f3778d0 887belongs. In the case of anonymous subroutines, this method returns
888the string "CODE".
889
5760246d 890Finally, there is a method named C<producer_args>, which is both an
0f3778d0 891accessor and a mutator. Arbitrary data may be stored in name => value
892pairs for the producer subroutine to access:
893
894 sub My::Random::producer {
895 my ($tr, $data) = @_;
896 my $pr_args = $tr->producer_args();
897
898 # $pr_args is a hashref.
899
5760246d 900Extra data passed to the C<producer> method is passed to
901C<producer_args>:
0f3778d0 902
903 $tr->producer("xSV", delimiter => ',\s*');
904
905 # In SQL::Translator::Producer::xSV:
906 my $args = $tr->producer_args;
907 my $delimiter = $args->{'delimiter'}; # value is ,\s*
908
5760246d 909=head2 parser
0f3778d0 910
5760246d 911The C<parser> method defines or retrieves a subroutine that will be
0f3778d0 912called to perform the parsing. The basic idea is the same as that of
5760246d 913C<producer> (see above), except the default subroutine name is
ca251f03 914"parse", and will be invoked as C<$module_name::parse($tr, $data)>.
0f3778d0 915Also, the parser subroutine will be passed a string containing the
916entirety of the data to be parsed.
917
918 # Invokes SQL::Translator::Parser::MySQL::parse()
919 $tr->parser("MySQL");
920
921 # Invokes My::Groovy::Parser::parse()
922 $tr->parser("My::Groovy::Parser");
923
924 # Invoke an anonymous subroutine directly
925 $tr->parser(sub {
926 my $dumper = Data::Dumper->new([ $_[1] ], [ "SQL" ]);
927 $dumper->Purity(1)->Terse(1)->Deepcopy(1);
928 return $dumper->Dump;
929 });
930
5760246d 931There is also C<parser_type> and C<parser_args>, which perform
932analogously to C<producer_type> and C<producer_args>
0f3778d0 933
5760246d 934=head2 show_warnings
0f3778d0 935
936Toggles whether to print warnings of name conflicts, identifier
937mutations, etc. Probably only generated by producers to let the user
938know when something won't translate very smoothly (e.g., MySQL "enum"
939fields into Oracle). Accepts a true or false value, returns the
940current value.
941
5760246d 942=head2 translate
0f3778d0 943
5760246d 944The C<translate> method calls the subroutines referenced by the
945C<parser> and C<producer> data members (described above). It accepts
0f3778d0 946as arguments a number of things, in key => value format, including
947(potentially) a parser and a producer (they are passed directly to the
5760246d 948C<parser> and C<producer> methods).
0f3778d0 949
5760246d 950Here is how the parameter list to C<translate> is parsed:
0f3778d0 951
952=over
953
954=item *
955
9561 argument means it's the data to be parsed; which could be a string
ca251f03 957(filename) or a reference to a scalar (a string stored in memory), or a
0f3778d0 958reference to a hash, which is parsed as being more than one argument
959(see next section).
960
961 # Parse the file /path/to/datafile
962 my $output = $tr->translate("/path/to/datafile");
963
964 # Parse the data contained in the string $data
965 my $output = $tr->translate(\$data);
966
967=item *
968
969More than 1 argument means its a hash of things, and it might be
970setting a parser, producer, or datasource (this key is named
971"filename" or "file" if it's a file, or "data" for a SCALAR reference.
972
973 # As above, parse /path/to/datafile, but with different producers
974 for my $prod ("MySQL", "XML", "Sybase") {
975 print $tr->translate(
976 producer => $prod,
977 filename => "/path/to/datafile",
978 );
979 }
980
981 # The filename hash key could also be:
982 datasource => \$data,
983
984You get the idea.
985
986=back
987
5760246d 988=head2 filename, data
0f3778d0 989
5760246d 990Using the C<filename> method, the filename of the data to be parsed
991can be set. This method can be used in conjunction with the C<data>
992method, below. If both the C<filename> and C<data> methods are
993invoked as mutators, the data set in the C<data> method is used.
0f3778d0 994
995 $tr->filename("/my/data/files/create.sql");
996
997or:
998
999 my $create_script = do {
1000 local $/;
1001 open CREATE, "/my/data/files/create.sql" or die $!;
1002 <CREATE>;
1003 };
1004 $tr->data(\$create_script);
1005
5760246d 1006C<filename> takes a string, which is interpreted as a filename.
1007C<data> takes a reference to a string, which is used as the data to be
0f3778d0 1008parsed. If a filename is set, then that file is opened and read when
5760246d 1009the C<translate> method is called, as long as the data instance
0f3778d0 1010variable is not set.
1011
1012=pod
1013
45ee6be0 1014=head2 schema
1015
1016Returns the SQL::Translator::Schema object.
1017
5760246d 1018=head2 trace
0f3778d0 1019
1020Turns on/off the tracing option of Parse::RecDescent.
1021
49e1eb70 1022=pod
1023
7a8e1f51 1024=head1 AUTHORS
16dc9970 1025
ca251f03 1026Ken Y. Clark, E<lt>kclark@cpan.orgE<gt>,
1027darren chamberlain E<lt>darren@cpan.orgE<gt>,
1028Chris Mungall E<lt>cjm@fruitfly.orgE<gt>,
1029Allen Day E<lt>allenday@users.sourceforge.netE<gt>
dfb4c915 1030
ca10f295 1031=head1 COPYRIGHT
16dc9970 1032
ca10f295 1033This program is free software; you can redistribute it and/or modify
1034it under the terms of the GNU General Public License as published by
1035the Free Software Foundation; version 2.
dfb4c915 1036
ca10f295 1037This program is distributed in the hope that it will be useful, but
1038WITHOUT ANY WARRANTY; without even the implied warranty of
1039MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1040General Public License for more details.
16dc9970 1041
ca10f295 1042You should have received a copy of the GNU General Public License
1043along with this program; if not, write to the Free Software
1044Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
1045USA
16dc9970 1046
87bf8a3a 1047=head1 BUGS
1048
1049Please use http://rt.cpan.org/ for reporting bugs.
1050
16dc9970 1051=head1 SEE ALSO
1052
abfa405a 1053L<perl>,
1054L<SQL::Translator::Parser>,
1055L<SQL::Translator::Producer>,
1056L<Parse::RecDescent>
16dc9970 1057