Fix silly syntax error, introduced in 0c04c5a22
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator.pm
index 5004931..423c1a5 100644 (file)
@@ -1,34 +1,17 @@
 package SQL::Translator;
 
-# ----------------------------------------------------------------------
-# Copyright (C) 2002-2009 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 $DEFAULT_SUB $DEBUG $ERROR );
+use warnings;
+our ( $DEFAULT_SUB, $DEBUG, $ERROR );
 use base 'Class::Base';
 
 require 5.005;
 
-$VERSION  = '0.11007';
+our $VERSION  = '0.11010';
 $DEBUG    = 0 unless defined $DEBUG;
 $ERROR    = "";
 
-use Carp qw(carp);
+use Carp qw(carp croak);
 
 use Data::Dumper;
 use File::Find;
@@ -38,26 +21,8 @@ use IO::Dir;
 use SQL::Translator::Producer;
 use SQL::Translator::Schema;
 
-# ----------------------------------------------------------------------
-# The default behavior is to "pass through" values (note that the
-# SQL::Translator instance is the first value ($_[0]), and the stuff
-# to be parsed is the second value ($_[1])
-# ----------------------------------------------------------------------
 $DEFAULT_SUB = sub { $_[0]->schema } unless defined $DEFAULT_SUB;
 
-# ----------------------------------------------------------------------
-# init([ARGS])
-#   The constructor.
-#
-#   new takes an optional hash of arguments.  These arguments may
-#   include a parser, specified with the keys "parser" or "from",
-#   and a producer, specified with the keys "producer" or "to".
-#
-#   The values that can be passed as the parser or producer are
-#   given directly to the parser or producer methods, respectively.
-#   See the appropriate method description below for details about
-#   what each expects/accepts.
-# ----------------------------------------------------------------------
 sub init {
     my ( $self, $config ) = @_;
     #
@@ -122,18 +87,51 @@ sub init {
     $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) );
+
+    my $quote;
+    if (defined $config->{quote_identifiers}) {
+      $quote = $config->{quote_identifiers};
+
+      for (qw/quote_table_names quote_field_names/) {
+        carp "Ignoring deprecated parameter '$_', since 'quote_identifiers' is supplied"
+          if defined $config->{$_}
+      }
+    }
+    # Legacy one set the other is not
+    elsif (
+      defined $config->{'quote_table_names'}
+        xor
+      defined $config->{'quote_field_names'}
+    ) {
+      if (defined $config->{'quote_table_names'}) {
+        carp "Explicitly disabling the deprecated 'quote_table_names' implies disabling 'quote_identifiers' which in turn implies disabling 'quote_field_names'"
+          unless $config->{'quote_table_names'};
+        $quote = $config->{'quote_table_names'} ? 1 : 0;
+      }
+      else {
+        carp "Explicitly disabling the deprecated 'quote_field_names' implies disabling 'quote_identifiers' which in turn implies disabling 'quote_table_names'"
+          unless $config->{'quote_field_names'};
+        $quote = $config->{'quote_field_names'} ? 1 : 0;
+      }
+    }
+    # Legacy both are set
+    elsif(defined $config->{'quote_table_names'}) {
+      croak 'Setting quote_table_names and quote_field_names to conflicting values is no longer supported'
+        if ($config->{'quote_table_names'} xor $config->{'quote_field_names'});
+
+      $quote = $config->{'quote_table_names'} ? 1 : 0;
+    }
+    # none are set - on by default, use a 0-but-true as indicator
+    # so we can allow individual producers to change the default
+    else {
+      $quote = '0E0';
+    }
+
+    $self->quote_identifiers($quote);
 
     return $self;
 }
 
-# ----------------------------------------------------------------------
-# add_drop_table([$bool])
-# ----------------------------------------------------------------------
 sub add_drop_table {
     my $self = shift;
     if ( defined (my $arg = shift) ) {
@@ -142,9 +140,6 @@ sub add_drop_table {
     return $self->{'add_drop_table'} || 0;
 }
 
-# ----------------------------------------------------------------------
-# no_comments([$bool])
-# ----------------------------------------------------------------------
 sub no_comments {
     my $self = shift;
     my $arg  = shift;
@@ -154,34 +149,28 @@ sub no_comments {
     return $self->{'no_comments'} || 0;
 }
 
-
-# ----------------------------------------------------------------------
-# 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;
+    (@_ > 1 and ($_[1] xor $_[0]->{quote_identifiers}) )
+        ? croak 'Using quote_table_names as a setter is no longer supported'
+        : $_[0]->{quote_identifiers} ? 1 : 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;
+    (@_ > 1 and ($_[1] xor $_[0]->{quote_identifiers}) )
+        ? croak 'Using quote_field_names as a setter is no longer supported'
+        : $_[0]->{quote_identifiers} ? 1 : 0
+}
+
+sub quote_identifiers {
+    @_ > 1
+        ? # synchronize for old code reaching directly into guts
+            $_[0]->{quote_table_names}
+             = $_[0]->{quote_field_names}
+              = $_[0]->{quote_identifiers}
+               = $_[1] ? $_[1] : 0
+        : $_[0]->{quote_identifiers}
 }
 
-# ----------------------------------------------------------------------
-# producer([$producer_spec])
-#
-# Get or set the producer for the current translator.
-# ----------------------------------------------------------------------
 sub producer {
     shift->_tool({
             name => 'producer',
@@ -190,32 +179,10 @@ sub producer {
     }, @_);
 }
 
-# ----------------------------------------------------------------------
-# producer_type()
-#
-# producer_type is an accessor that allows producer subs to get
-# information about their origin.  This is poptentially important;
-# since all producer subs are called as subroutine references, there is
-# no way for a producer to find out which package the sub lives in
-# originally, for example.
-# ----------------------------------------------------------------------
 sub producer_type { $_[0]->{'producer_type'} }
 
-# ----------------------------------------------------------------------
-# producer_args([\%args])
-#
-# Arbitrary name => value pairs of paramters can be passed to a
-# producer using this method.
-#
-# If the first argument passed in is undef, then the hash of arguments
-# is cleared; all subsequent elements are added to the hash of name,
-# value pairs stored as producer_args.
-# ----------------------------------------------------------------------
 sub producer_args { shift->_args("producer", @_); }
 
-# ----------------------------------------------------------------------
-# parser([$parser_spec])
-# ----------------------------------------------------------------------
 sub parser {
     shift->_tool({
         name => 'parser',
@@ -228,17 +195,6 @@ sub parser_type { $_[0]->{'parser_type'}; }
 
 sub parser_args { shift->_args("parser", @_); }
 
-# ----------------------------------------------------------------------
-# e.g.
-#   $sqlt->filters => [
-#       sub { },
-#       [ "NormalizeNames", field => "lc", tabel => "ucfirst" ],
-#       [
-#           "DataTypeMap",
-#           "TEXT" => "BIGTEXT",
-#       ],
-#   ],
-# ----------------------------------------------------------------------
 sub filters {
     my $self = shift;
     my $filters = $self->{filters} ||= [];
@@ -261,7 +217,6 @@ sub filters {
     return @$filters;
 }
 
-# ----------------------------------------------------------------------
 sub show_warnings {
     my $self = shift;
     my $arg  = shift;
@@ -272,7 +227,6 @@ sub show_warnings {
 }
 
 
-# filename - get or set the filename
 sub filename {
     my $self = shift;
     if (@_) {
@@ -296,13 +250,6 @@ sub filename {
     $self->{'filename'};
 }
 
-# ----------------------------------------------------------------------
-# data([$data])
-#
-# if $self->{'data'} is not set, but $self->{'filename'} is, then
-# $self->{'filename'} is opened and read, with the results put into
-# $self->{'data'}.
-# ----------------------------------------------------------------------
 sub data {
     my $self = shift;
 
@@ -356,7 +303,6 @@ sub data {
     return $self->{'data'};
 }
 
-# ----------------------------------------------------------------------
 sub reset {
 #
 # Deletes the existing Schema object so that future calls to translate
@@ -367,7 +313,6 @@ sub reset {
     return 1;
 }
 
-# ----------------------------------------------------------------------
 sub schema {
 #
 # Returns the SQL::Translator::Schema object
@@ -383,7 +328,6 @@ sub schema {
     return $self->{'schema'};
 }
 
-# ----------------------------------------------------------------------
 sub trace {
     my $self = shift;
     my $arg  = shift;
@@ -393,21 +337,6 @@ sub trace {
     return $self->{'trace'} || 0;
 }
 
-# ----------------------------------------------------------------------
-# translate([source], [\%args])
-#
-# translate does the actual translation.  The main argument is the
-# source of the data to be translated, which can be a filename, scalar
-# reference, or glob reference.
-#
-# Alternatively, translate takes optional arguements, which are passed
-# to the appropriate places.  Most notable of these arguments are
-# parser and producer, which can be used to set the parser and
-# producer, respectively.  This is the applications last chance to set
-# these.
-#
-# translate returns a string.
-# ----------------------------------------------------------------------
 sub translate {
     my $self = shift;
     my ($args, $parser, $parser_type, $producer, $producer_type);
@@ -550,36 +479,10 @@ sub translate {
     return wantarray ? @producer_output : $producer_output;
 }
 
-# ----------------------------------------------------------------------
-# list_parsers()
-#
-# Hacky sort of method to list all available parsers.  This has
-# several problems:
-#
-#   - Only finds things in the SQL::Translator::Parser namespace
-#
-#   - Only finds things that are located in the same directory
-#     as SQL::Translator::Parser.  Yeck.
-#
-# This method will fail in several very likely cases:
-#
-#   - Parser modules in different namespaces
-#
-#   - Parser modules in the SQL::Translator::Parser namespace that
-#     have any XS componenets will be installed in
-#     arch_lib/SQL/Translator.
-#
-# ----------------------------------------------------------------------
 sub list_parsers {
     return shift->_list("parser");
 }
 
-# ----------------------------------------------------------------------
-# list_producers()
-#
-# See notes for list_parsers(), above; all the problems apply to
-# list_producers as well.
-# ----------------------------------------------------------------------
 sub list_producers {
     return shift->_list("producer");
 }
@@ -621,8 +524,8 @@ sub _args {
 
 # ----------------------------------------------------------------------
 # Does the get/set work for parser and producer. e.g.
-# return $self->_tool({ 
-#   name => 'producer', 
+# return $self->_tool({
+#   name => 'producer',
 #   path => "SQL::Translator::Producer",
 #   default_sub => "produce",
 # }, @_);
@@ -635,7 +538,7 @@ sub _tool {
     my $path = $args->{path};
     my $default_sub = $args->{default_sub};
     my $tool = shift;
-   
+
     # passed an anonymous subroutine reference
     if (isa($tool, 'CODE')) {
         $self->{$name} = $tool;
@@ -689,7 +592,7 @@ sub _list {
     my $uctype = ucfirst lc $type;
 
     #
-    # First find all the directories where SQL::Translator 
+    # First find all the directories where SQL::Translator
     # parsers or producers (the "type") appear to live.
     #
     load("SQL::Translator::$uctype") or return ();
@@ -703,13 +606,13 @@ sub _list {
     }
 
     #
-    # Now use File::File::find to look recursively in those 
+    # Now use File::File::find to look recursively in those
     # directories for all the *.pm files, then present them
     # with the slashes turned into dashes.
     #
     my %found;
-    find( 
-        sub { 
+    find(
+        sub {
             if ( -f && m/\.pm$/ ) {
                 my $mod      =  $_;
                    $mod      =~ s/\.pm$//;
@@ -766,7 +669,7 @@ sub load {
         return $module if $INC{$file}; # Already loaded
 
         eval { require $file };
-        next if $@ =~ /Can't locate $file in \@INC/; 
+        next if $@ =~ /Can't locate $file in \@INC/;
         eval { $module->import() } unless $@;
         return __PACKAGE__->error("Error loading $name as $module : $@")
         if $@ && $@ !~ /"SQL::Translator::Producer" is not exported/;
@@ -794,22 +697,18 @@ sub _load_sub {
     return undef;
 }
 
-# ----------------------------------------------------------------------
 sub format_table_name {
     return shift->_format_name('_format_table_name', @_);
 }
 
-# ----------------------------------------------------------------------
 sub format_package_name {
     return shift->_format_name('_format_package_name', @_);
 }
 
-# ----------------------------------------------------------------------
 sub format_fk_name {
     return shift->_format_name('_format_fk_name', @_);
 }
 
-# ----------------------------------------------------------------------
 sub format_pk_name {
     return shift->_format_name('_format_pk_name', @_);
 }
@@ -835,28 +734,16 @@ sub _format_name {
     return @args ? $self->{$field}->(@args) : $self->{$field};
 }
 
-# ----------------------------------------------------------------------
-# isa($ref, $type)
-#
-# Calls UNIVERSAL::isa($ref, $type).  I think UNIVERSAL::isa is ugly,
-# but I like function overhead.
-# ----------------------------------------------------------------------
 sub isa($$) {
     my ($ref, $type) = @_;
     return UNIVERSAL::isa($ref, $type);
 }
 
-# ----------------------------------------------------------------------
-# version
-#
-# Returns the $VERSION of the main SQL::Translator package.
-# ----------------------------------------------------------------------
 sub version {
     my $self = shift;
     return $VERSION;
 }
 
-# ----------------------------------------------------------------------
 sub validate {
     my ( $self, $arg ) = @_;
     if ( defined $arg ) {
@@ -896,8 +783,7 @@ SQL::Translator - manipulate structured data definitions (SQL and more)
       # 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,
+      quote_identifiers     => 1,
       # Validate schema object
       validate            => 1,
       # Make all table names CAPS in producers which support this option
@@ -981,11 +867,15 @@ add_drop_table
 
 =item *
 
-quote_table_names
+quote_identifiers
 
 =item *
 
-quote_field_names
+quote_table_names (DEPRECATED)
+
+=item *
+
+quote_field_names (DEPRECATED)
 
 =item *
 
@@ -1009,18 +899,22 @@ advantage is gained by passing options to the constructor.
 
 =head2 add_drop_table
 
-Toggles whether or not to add "DROP TABLE" statements just before the 
+Toggles whether or not to add "DROP TABLE" statements just before the
 create definitions.
 
+=head2 quote_identifiers
+
+Toggles whether or not to quote identifiers (table, column, constraint, etc.)
+with a quoting mechanism suitable for the chosen Producer. The default (true)
+is to quote them.
+
 =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.
+DEPRECATED - A legacy proxy to L</quote_identifiers>
 
 =head2 quote_field_names
 
-Toggles whether or not to quote field names with " in most
-statements. The default (true), is to quote them.
+DEPRECATED - A legacy proxy to L</quote_identifiers>
 
 =head2 no_comments
 
@@ -1033,9 +927,9 @@ The C<producer> method is an accessor/mutator, used to retrieve or
 define what subroutine is called to produce the output.  A subroutine
 defined as a producer will be invoked as a function (I<not a method>)
 and passed its container C<SQL::Translator> instance, which it should
-call the C<schema> method on, to get the C<SQL::Translator::Schema> 
+call the C<schema> method on, to get the C<SQL::Translator::Schema>
 generated by the parser.  It is expected that the function transform the
-schema structure to a string.  The C<SQL::Translator> instance is also useful 
+schema structure to a string.  The C<SQL::Translator> instance is also useful
 for informational purposes; for example, the type of the parser can be
 retrieved using the C<parser_type> method, and the C<error> and
 C<debug> methods can be called when needed.
@@ -1302,7 +1196,7 @@ Please use L<http://rt.cpan.org/> for reporting bugs.
 
 =head1 PRAISE
 
-If you find this module useful, please use 
+If you find this module useful, please use
 L<http://cpanratings.perl.org/rate/?distribution=SQL-Translator> to rate it.
 
 =head1 SEE ALSO