package SQL::Translator;
-# ----------------------------------------------------------------------
-# $Id: Translator.pm,v 1.63 2004-12-13 16:32:07 grommit Exp $
-# ----------------------------------------------------------------------
-# Copyright (C) 2002-4 The SQLFairy Authors
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; version 2.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-# 02111-1307 USA
-# -------------------------------------------------------------------
-
use strict;
-use vars qw( $VERSION $REVISION $DEFAULT_SUB $DEBUG $ERROR );
+use vars qw( $VERSION $DEFAULT_SUB $DEBUG $ERROR );
use base 'Class::Base';
-require 5.004;
+require 5.005;
-$VERSION = '0.06';
-$REVISION = sprintf "%d.%02d", q$Revision: 1.63 $ =~ /(\d+)\.(\d+)/;
+$VERSION = '0.11007';
$DEBUG = 0 unless defined $DEBUG;
$ERROR = "";
use Carp qw(carp);
use Data::Dumper;
-use Class::Base;
use File::Find;
use File::Spec::Functions qw(catfile);
use File::Basename qw(dirname);
use IO::Dir;
+use SQL::Translator::Producer;
use SQL::Translator::Schema;
# ----------------------------------------------------------------------
$self->trace( $config->{'trace'} );
$self->validate( $config->{'validate'} );
+
+ $self->quote_table_names( (defined $config->{'quote_table_names'}
+ ? $config->{'quote_table_names'} : 1) );
+ $self->quote_field_names( (defined $config->{'quote_field_names'}
+ ? $config->{'quote_field_names'} : 1) );
return $self;
}
# ----------------------------------------------------------------------
+# quote_table_names([$bool])
+# ----------------------------------------------------------------------
+sub quote_table_names {
+ my $self = shift;
+ if ( defined (my $arg = shift) ) {
+ $self->{'quote_table_names'} = $arg ? 1 : 0;
+ }
+ return $self->{'quote_table_names'} || 0;
+}
+
+# ----------------------------------------------------------------------
+# quote_field_names([$bool])
+# ----------------------------------------------------------------------
+sub quote_field_names {
+ my $self = shift;
+ if ( defined (my $arg = shift) ) {
+ $self->{'quote_field_names'} = $arg ? 1 : 0;
+ }
+ return $self->{'quote_field_names'} || 0;
+}
+
+# ----------------------------------------------------------------------
# producer([$producer_spec])
#
# Get or set the producer for the current translator.
my $filters = $self->{filters} ||= [];
return @$filters unless @_;
- # Set. Convert args to list of [\&code,\%args]
+ # Set. Convert args to list of [\&code,@args]
foreach (@_) {
- $_ = [$_,{}] if not ref($_) eq "ARRAY";
- my ($name,$args) = @$_;
- if ( isa($name,"CODE") ) {
- push @$filters, $_;
+ my ($filt,@args) = ref($_) eq "ARRAY" ? @$_ : $_;
+ if ( isa($filt,"CODE") ) {
+ push @$filters, [$filt,@args];
next;
}
else {
- $self->debug("Adding $name filter. Args:".Dumper($args)."\n");
- my $code = _load_sub("$name\::filter", "SQL::Translator::Filter");
- return $self->error("ERROR:".$self->error) unless $code;
- push @$filters, [$code,$args];
+ $self->debug("Adding $filt filter. Args:".Dumper(\@args)."\n");
+ $filt = _load_sub("$filt\::filter", "SQL::Translator::Filter")
+ || return $self->error(__PACKAGE__->error);
+ push @$filters, [$filt,@args];
}
}
return @$filters;
$data = join '', @$data;
}
elsif (isa($data, 'GLOB')) {
+ seek ($data, 0, 0) if eof ($data);
local $/;
$data = <$data>;
}
sub translate {
my $self = shift;
my ($args, $parser, $parser_type, $producer, $producer_type);
- my ($parser_output, $producer_output);
+ my ($parser_output, $producer_output, @producer_output);
# Parse arguments
if (@_ == 1) {
my $filt_num = 0;
foreach ($self->filters) {
$filt_num++;
- my ($code,$args) = @$_;
- eval { $code->($self->schema, $args) };
+ my ($code,@args) = @$_;
+ eval { $code->($self->schema, @args) };
my $err = $@ || $self->error || 0;
return $self->error("Error with filter $filt_num : $err") if $err;
}
# Run producer
- eval { $producer_output = $producer->($self) };
- if ($@ || ! $producer_output) {
+ # Calling wantarray in the eval no work, wrong scope.
+ my $wantarray = wantarray ? 1 : 0;
+ eval {
+ if ($wantarray) {
+ @producer_output = $producer->($self);
+ } else {
+ $producer_output = $producer->($self);
+ }
+ };
+ if ($@ || !( $producer_output || @producer_output)) {
my $err = $@ || $self->error || "no results";
my $msg = "translate: Error with producer '$producer_type': $err";
return $self->error($msg);
}
- return $producer_output;
+ return wantarray ? @producer_output : $producer_output;
}
# ----------------------------------------------------------------------
# MODULE - is the name of the module to load.
#
# PATH - optional list of 'package paths' to look for the module in. e.g
-# If you called load(Bar => 'Foo', 'My::Modules') it will try to load the mod
-# Bar then Foo::Bar then My::Modules::Bar.
+# If you called load('Super::Foo' => 'My', 'Other') it will
+# try to load the mod Super::Foo then My::Super::Foo then Other::Super::Foo.
#
# Returns package name of the module actually loaded or false and sets error.
#
eval { require $file };
next if $@ =~ /Can't locate $file in \@INC/;
- eval { $file->import(@_) } unless $@;
- return __PACKAGE__->error("Error loading $name as $module : $@") if $@;
+ eval { $module->import() } unless $@;
+ return __PACKAGE__->error("Error loading $name as $module : $@")
+ if $@ && $@ !~ /"SQL::Translator::Producer" is not exported/;
return $module; # Module loaded ok
}
sub _load_sub {
my ($tool, @path) = @_;
- # Passed a module name or module and sub name
my (undef,$module,$func_name) = $tool =~ m/((.*)::)?(\w+)$/;
if ( my $module = load($module => @path) ) {
my $sub = "$module\::$func_name";
show_warnings => 0,
# Add "drop table" statements
add_drop_table => 1,
+ # to quote or not to quote, thats the question
+ quote_table_names => 1,
+ quote_field_names => 1,
# Validate schema object
validate => 1,
# Make all table names CAPS in producers which support this option
=item *
+quote_table_names
+
+=item *
+
+quote_field_names
+
+=item *
+
no_comments
=item *
Toggles whether or not to add "DROP TABLE" statements just before the
create definitions.
+=head2 quote_table_names
+
+Toggles whether or not to quote table names with " in DROP and CREATE
+statements. The default (true) is to quote them.
+
+=head2 quote_field_names
+
+Toggles whether or not to quote field names with " in most
+statements. The default (true), is to quote them.
+
=head2 no_comments
Toggles whether to print comments in the output. Accepts a true or false
Set or retreive the filters to run over the schema during the
translation, before the producer creates its output. Filters are sub
routines called, in order, with the schema object to filter as the 1st
-arg and a hashref of options as the 2nd. They are free to do whatever
-they want to the schema object, which will be handed to any following
-filters, then used by the producer.
+arg and a hash of options (passed as a list) for the rest of the args.
+They are free to do whatever they want to the schema object, which will be
+handed to any following filters, then used by the producer.
Filters are set as an array, which gives the order they run in.
Like parsers and producers, they can be defined by a module name, a
module name relative to the SQL::Translator::Filter namespace, a module
name and function name together or a reference to an anonymous subroutine.
When using a module name a function called C<filter> will be invoked in
-that package to do the work. To pass args to the filter set it as an array
-ref with the 1st value giving the filter and the rest being a hash of
-args.
+that package to do the work.
+
+To pass args to the filter set it as an array ref with the 1st value giving
+the filter (name or sub) and the rest its args. e.g.
$tr->filters(
sub {
my $schema = shift;
# Do stuff to schema here!
},
- [ "Foo", foo => "bar", hello => "world" ],
- [ "Filter3" ],
+ DropFKeys,
+ [ "Names", table => 'lc' ],
+ [ "Foo", foo => "bar", hello => "world" ],
+ [ "Filter5" ],
);
-Although you would normally set them in the constructor, which calls
+Although you normally set them in the constructor, which calls
through to filters. i.e.
my $translator = SQL::Translator->new(
...
filters => [
sub { ... },
- [ Foo, foo => "bar" ],
+ [ "Names", table => 'lc' ],
],
...
);
the end of the current list.
Returns the filters as a list of array refs, the 1st value being a
-reference to the filter sub routine and the 2nd a hashref its args.
+reference to the filter sub and the rest its args.
=head2 show_warnings
=head1 AUTHORS
-The following people have contributed to the SQLFairy project:
+Alexander Hartmaier <abraxxa@cpan.org>
-=over 4
+Allen Day <allenday@users.sourceforge.net>
-=item * Mark Addison <grommit@users.sourceforge.net>
+Anders Nor Berle <berle@cpan.org>
-=item * Sam Angiuoli <angiuoli@users.sourceforge.net>
+Andrew Moore <amoore@cpan.org>
-=item * Dave Cash <dave@gnofn.org>
+Ben Faga <faga@cshl.edu>
-=item * Darren Chamberlain <dlc@users.sourceforge.net>
+Chris Hilton <chilton@alterpoint.com>
-=item * Ken Y. Clark <kclark@cpan.org>
+Chris Mungall <cjm@fruitfly.org>
-=item * Allen Day <allenday@users.sourceforge.net>
+Chris To <christot@users.sourceforge.net>
-=item * Paul Harrington <phrrngtn@users.sourceforge.net>
+Daniel Ruoso <daniel@ruoso.com>
-=item * Mikey Melillo <mmelillo@users.sourceforge.net>
+Darren Chamberlain <dlc@users.sourceforge.net>
-=item * Chris Mungall <cjm@fruitfly.org>
+Dave Cash <dave@gnofn.org>
-=item * Ross Smith II <rossta@users.sf.net>
+Fabien Wernli <faxmodem@cpan.org>
-=item * Gudmundur A. Thorisson <mummi@cshl.org>
+Geoff Cant <geoff@catalyst.net.nz>
-=item * Chris To <christot@users.sourceforge.net>
+Gudmundur A. Thorisson <mummi@cshl.org>
-=item * Jason Williams <smdwilliams@users.sourceforge.net>
+Guillermo Roditi <groditi@cpan.org>
-=item * Ying Zhang <zyolive@yahoo.com>
+Jason Williams <smdwilliams@users.sourceforge.net>
-=back
+Jonathan Yu <jawnsy@cpan.org>
+
+John Goulah <jgoulah@cpan.org>
+
+Ken Youens-Clark <kclark@cpan.org>
+
+Kevin McClellan <kdmcclel@gmail.com>
+
+Mark Addison <grommit@users.sourceforge.net>
+
+Mikey Melillo <mmelillo@users.sourceforge.net>
+
+Moritz Onken <onken@netcubed.de>
+
+Paul Harrington <phrrngtn@users.sourceforge.net>
+
+Peter Rabbitson <ribasushi@cpan.org>
+
+Ross Smith II <rossta@users.sf.net>
+
+Ryan D Johnson <ryan@innerfence.com>
+
+Sam Angiuoli <angiuoli@users.sourceforge.net>
+
+Stephen Bennett <stephen@freenode.net>
+
+Stephen Clouse <stephenclouse@gmail.com>
+
+Wallace Reis <wreis@cpan.org>
+
+Ying Zhang <zyolive@yahoo.com>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2002-2011 the SQL::Translator L</AUTHORS> as listed
+above.
If you would like to contribute to the project, you can send patches
to the developers mailing list:
Or send us a message (with your Sourceforge username) asking to be
added to the project and what you'd like to contribute.
-
-=head1 COPYRIGHT
+=head1 LICENSE
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by