X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FSQL%2FTranslator.pm;h=5ca651dfef673a6cd5a5c897109a3515e396f9fe;hb=83551ff33440778f485074b606c2dff82287cabd;hp=7b0dc5882e6014d6267864eb689de0ef0c81a99b;hpb=b03926cdac036bdbcf69e478ca29e1121c814646;p=dbsrgits%2FSQL-Translator.git diff --git a/lib/SQL/Translator.pm b/lib/SQL/Translator.pm index 7b0dc58..5ca651d 100644 --- a/lib/SQL/Translator.pm +++ b/lib/SQL/Translator.pm @@ -1,413 +1,292 @@ 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 Moo; +our ( $DEFAULT_SUB, $DEBUG, $ERROR ); -use strict; -use vars qw( $VERSION $DEFAULT_SUB $DEBUG $ERROR ); -use base 'Class::Base'; - -require 5.004; - -$VERSION = '0.09003'; +our $VERSION = '0.11015'; $DEBUG = 0 unless defined $DEBUG; $ERROR = ""; -use Carp qw(carp); +use Carp qw(carp croak); use Data::Dumper; -use Class::Base; use File::Find; use File::Spec::Functions qw(catfile); use File::Basename qw(dirname); use IO::Dir; +use Sub::Quote qw(quote_sub); use SQL::Translator::Producer; use SQL::Translator::Schema; +use SQL::Translator::Utils qw(throw ex2err carp_ro); -# ---------------------------------------------------------------------- -# 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 ) = @_; - # - # Set the parser and producer. - # +with qw( + SQL::Translator::Role::Debug + SQL::Translator::Role::Error + SQL::Translator::Role::BuildArgs +); + +around BUILDARGS => sub { + my $orig = shift; + my $self = shift; + my $config = $self->$orig(@_); + # If a 'parser' or 'from' parameter is passed in, use that as the # parser; if a 'producer' or 'to' parameter is passed in, use that # as the producer; both default to $DEFAULT_SUB. - # - $self->parser ($config->{'parser'} || $config->{'from'} || $DEFAULT_SUB); - $self->producer($config->{'producer'} || $config->{'to'} || $DEFAULT_SUB); + $config->{parser} ||= $config->{from} if defined $config->{from}; + $config->{producer} ||= $config->{to} if defined $config->{to}; - # - # Set up callbacks for formatting of pk,fk,table,package names in producer - # MOVED TO PRODUCER ARGS - # - #$self->format_table_name($config->{'format_table_name'}); - #$self->format_package_name($config->{'format_package_name'}); - #$self->format_fk_name($config->{'format_fk_name'}); - #$self->format_pk_name($config->{'format_pk_name'}); + $config->{filename} ||= $config->{file} if defined $config->{file}; - # - # Set the parser_args and producer_args - # - for my $pargs ( qw[ parser_args producer_args ] ) { - $self->$pargs( $config->{$pargs} ) if defined $config->{ $pargs }; - } + my $quote; + if (defined $config->{quote_identifiers}) { + $quote = $config->{quote_identifiers}; - # - # Initialize the filters. - # - if ( $config->{filters} && ref $config->{filters} eq "ARRAY" ) { - $self->filters( @{$config->{filters}} ) - || return $self->error('Error inititializing filters: '.$self->error); + for (qw/quote_table_names quote_field_names/) { + carp "Ignoring deprecated parameter '$_', since 'quote_identifiers' is supplied" + if defined $config->{$_} + } } - - # - # Set the data source, if 'filename' or 'file' is provided. - # - $config->{'filename'} ||= $config->{'file'} || ""; - $self->filename( $config->{'filename'} ) if $config->{'filename'}; - - # - # Finally, if there is a 'data' parameter, use that in - # preference to filename and file - # - if ( my $data = $config->{'data'} ) { - $self->data( $data ); + # 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'}); - # - # Set various other options. - # - $self->{'debug'} = defined $config->{'debug'} ? $config->{'debug'} : $DEBUG; - - $self->add_drop_table( $config->{'add_drop_table'} ); - - $self->no_comments( $config->{'no_comments'} ); - - $self->show_warnings( $config->{'show_warnings'} ); - - $self->trace( $config->{'trace'} ); + $quote = $config->{'quote_table_names'} ? 1 : 0; + } - $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) ); + $config->{quote_identifiers} = $quote if defined $quote; - return $self; -} + return $config; +}; -# ---------------------------------------------------------------------- -# add_drop_table([$bool]) -# ---------------------------------------------------------------------- -sub add_drop_table { - my $self = shift; - if ( defined (my $arg = shift) ) { - $self->{'add_drop_table'} = $arg ? 1 : 0; +sub BUILD { + my ($self) = @_; + # Make sure all the tool-related stuff is set up + foreach my $tool (qw(producer parser)) { + $self->$tool($self->$tool); } - return $self->{'add_drop_table'} || 0; } -# ---------------------------------------------------------------------- -# no_comments([$bool]) -# ---------------------------------------------------------------------- -sub no_comments { - my $self = shift; - my $arg = shift; - if ( defined $arg ) { - $self->{'no_comments'} = $arg ? 1 : 0; - } - return $self->{'no_comments'} || 0; -} +has $_ => ( + is => 'rw', + default => quote_sub(q{ 0 }), + coerce => quote_sub(q{ $_[0] ? 1 : 0 }), +) foreach qw(add_drop_table no_comments show_warnings trace validate); +# quote_identifiers is on by default, use a 0-but-true as indicator +# so we can allow individual producers to change the default +has quote_identifiers => ( + is => 'rw', + default => quote_sub(q{ '0E0' }), + coerce => quote_sub(q{ $_[0] || 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; } -# ---------------------------------------------------------------------- -# 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; } -# ---------------------------------------------------------------------- -# producer([$producer_spec]) -# -# Get or set the producer for the current translator. -# ---------------------------------------------------------------------- -sub producer { +after quote_identifiers => sub { + if (@_ > 1) { + # synchronize for old code reaching directly into guts + $_[0]->{quote_table_names} + = $_[0]->{quote_field_names} + = $_[1] ? 1 : 0; + } +}; + +has producer => ( is => 'rw', default => sub { $DEFAULT_SUB } ); + +around producer => sub { + my $orig = shift; shift->_tool({ - name => 'producer', - path => "SQL::Translator::Producer", - default_sub => "produce", + orig => $orig, + name => 'producer', + path => "SQL::Translator::Producer", + default_sub => "produce", }, @_); -} +}; -# ---------------------------------------------------------------------- -# 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'} } +has producer_type => ( is => 'rwp', init_arg => undef ); -# ---------------------------------------------------------------------- -# 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", @_); } +around producer_type => carp_ro('producer_type'); -# ---------------------------------------------------------------------- -# parser([$parser_spec]) -# ---------------------------------------------------------------------- -sub parser { +has producer_args => ( is => 'rw', default => quote_sub(q{ +{} }) ); + +around producer_args => sub { + my $orig = shift; + shift->_args($orig, @_); +}; + +has parser => ( is => 'rw', default => sub { $DEFAULT_SUB } ); + +around parser => sub { + my $orig = shift; shift->_tool({ + orig => $orig, name => 'parser', path => "SQL::Translator::Parser", default_sub => "parse", }, @_); -} - -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} ||= []; - return @$filters unless @_; - - # Set. Convert args to list of [\&code,@args] - foreach (@_) { - my ($filt,@args) = ref($_) eq "ARRAY" ? @$_ : $_; - if ( isa($filt,"CODE") ) { - push @$filters, [$filt,@args]; - next; - } - else { - $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]; +}; + +has parser_type => ( is => 'rwp', init_arg => undef ); + +around parser_type => carp_ro('parser_type'); + +has parser_args => ( is => 'rw', default => quote_sub(q{ +{} }) ); + +around parser_args => sub { + my $orig = shift; + shift->_args($orig, @_); +}; + +has filters => ( + is => 'rw', + default => quote_sub(q{ [] }), + coerce => sub { + my @filters; + # Set. Convert args to list of [\&code,@args] + foreach (@{$_[0]||[]}) { + my ($filt,@args) = ref($_) eq "ARRAY" ? @$_ : $_; + if ( isa($filt,"CODE") ) { + push @filters, [$filt,@args]; + next; + } + else { + __PACKAGE__->debug("Adding $filt filter. Args:".Dumper(\@args)."\n"); + $filt = _load_sub("$filt\::filter", "SQL::Translator::Filter") + || throw(__PACKAGE__->error); + push @filters, [$filt,@args]; + } } - } - return @$filters; -} + return \@filters; + }, +); -# ---------------------------------------------------------------------- -sub show_warnings { +around filters => sub { + my $orig = shift; my $self = shift; - my $arg = shift; - if ( defined $arg ) { - $self->{'show_warnings'} = $arg ? 1 : 0; - } - return $self->{'show_warnings'} || 0; -} - + return @{$self->$orig([@{$self->$orig}, @_])} if @_; + return @{$self->$orig}; +}; -# filename - get or set the filename -sub filename { - my $self = shift; - if (@_) { +has filename => ( + is => 'rw', + isa => sub { my $filename = shift; if (-d $filename) { - my $msg = "Cannot use directory '$filename' as input source"; - return $self->error($msg); - } elsif (ref($filename) eq 'ARRAY') { - $self->{'filename'} = $filename; - $self->debug("Got array of files: ".join(', ',@$filename)."\n"); - } elsif (-f _ && -r _) { - $self->{'filename'} = $filename; - $self->debug("Got filename: '$self->{'filename'}'\n"); - } else { - my $msg = "Cannot use '$filename' as input source: ". - "file does not exist or is not readable."; - return $self->error($msg); + throw("Cannot use directory '$filename' as input source"); + } elsif (not -f _ && -r _) { + throw("Cannot use '$filename' as input source: ". + "file does not exist or is not readable."); } - } - - $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; - - # Set $self->{'data'} based on what was passed in. We will - # accept a number of things; do our best to get it right. - if (@_) { + }, +); + +around filename => \&ex2err; + +has data => ( + is => 'rw', + builder => 1, + lazy => 1, + coerce => sub { + # Set $self->data based on what was passed in. We will + # accept a number of things; do our best to get it right. my $data = shift; - if (isa($data, "SCALAR")) { - $self->{'data'} = $data; + if (isa($data, 'ARRAY')) { + $data = join '', @$data; } - else { - if (isa($data, 'ARRAY')) { - $data = join '', @$data; - } - elsif (isa($data, 'GLOB')) { - local $/; - $data = <$data>; - } - elsif (! ref $data && @_) { - $data = join '', $data, @_; - } - $self->{'data'} = \$data; + elsif (isa($data, 'GLOB')) { + seek ($data, 0, 0) if eof ($data); + local $/; + $data = <$data>; } + return isa($data, 'SCALAR') ? $data : \$data; + }, +); + +around data => sub { + my $orig = shift; + my $self = shift; + + if (@_ > 1 && !ref $_[0]) { + return $self->$orig(\join('', @_)); } + elsif (@_) { + return $self->$orig(@_); + } + return ex2err($orig, $self); +}; +sub _build_data { + my $self = shift; # If we have a filename but no data yet, populate. - if (not $self->{'data'} and my $filename = $self->filename) { + if (my $filename = $self->filename) { $self->debug("Opening '$filename' to get contents.\n"); - local *FH; local $/; my $data; my @files = ref($filename) eq 'ARRAY' ? @$filename : ($filename); foreach my $file (@files) { - unless (open FH, $file) { - return $self->error("Can't read file '$file': $!"); - } + open my $fh, '<', $file + or throw("Can't read file '$file': $!"); - $data .= ; + $data .= <$fh>; - unless (close FH) { - return $self->error("Can't close file '$file': $!"); - } + close $fh or throw("Can't close file '$file': $!"); } - $self->{'data'} = \$data; + return \$data; } - - return $self->{'data'}; } -# ---------------------------------------------------------------------- -sub reset { -# -# Deletes the existing Schema object so that future calls to translate -# don't append to the existing. -# - my $self = shift; - $self->{'schema'} = undef; - return 1; -} - -# ---------------------------------------------------------------------- -sub schema { -# -# Returns the SQL::Translator::Schema object -# - my $self = shift; +has schema => ( + is => 'lazy', + init_arg => undef, + clearer => 'reset', + predicate => '_has_schema', +); - unless ( defined $self->{'schema'} ) { - $self->{'schema'} = SQL::Translator::Schema->new( - translator => $self, - ); - } - - return $self->{'schema'}; -} +around schema => carp_ro('schema'); -# ---------------------------------------------------------------------- -sub trace { +around reset => sub { + my $orig = shift; my $self = shift; - my $arg = shift; - if ( defined $arg ) { - $self->{'trace'} = $arg ? 1 : 0; - } - return $self->{'trace'} || 0; -} + $self->$orig(@_); + return 1 +}; + +sub _build_schema { SQL::Translator::Schema->new(translator => shift) } -# ---------------------------------------------------------------------- -# 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); @@ -505,7 +384,7 @@ sub translate { # ---------------------------------------------------------------- # Run parser - unless ( defined $self->{'schema'} ) { + unless ( $self->_has_schema ) { eval { $parser_output = $parser->($self, $$data) }; if ($@ || ! $parser_output) { my $msg = sprintf "translate: Error with parser '%s': %s", @@ -550,36 +429,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"); } @@ -596,12 +449,7 @@ sub list_producers { # ---------------------------------------------------------------------- sub _args { my $self = shift; - my $type = shift; - $type = "${type}_args" unless $type =~ /_args$/; - - unless (defined $self->{$type} && isa($self->{$type}, 'HASH')) { - $self->{$type} = { }; - } + my $orig = shift; if (@_) { # If the first argument is an explicit undef (remember, we @@ -609,20 +457,20 @@ sub _args { # out the producer_args hash. if (! defined $_[0]) { shift @_; - %{$self->{$type}} = (); + $self->$orig({}); } my $args = isa($_[0], 'HASH') ? shift : { @_ }; - %{$self->{$type}} = (%{$self->{$type}}, %$args); + return $self->$orig({ %{$self->$orig}, %$args }); } - $self->{$type}; + return $self->$orig; } # ---------------------------------------------------------------------- # 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", # }, @_); @@ -630,16 +478,17 @@ sub _args { sub _tool { my ($self,$args) = (shift, shift); my $name = $args->{name}; + my $orig = $args->{orig}; return $self->{$name} unless @_; # get accessor 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; - $self->{"$name\_type"} = "CODE"; + $self->$orig($tool); + $self->${\"_set_${name}_type"}("CODE"); $self->debug("Got $name: code ref\n"); } @@ -665,8 +514,8 @@ sub _tool { # get code reference and assign my (undef,$module,undef) = $sub =~ m/((.*)::)?(\w+)$/; - $self->{$name} = $code; - $self->{"$name\_type"} = $sub eq "CODE" ? "CODE" : $module; + $self->$orig($code); + $self->${\"_set_$name\_type"}($sub eq "CODE" ? "CODE" : $module); $self->debug("Got $name: $sub\n"); } @@ -689,7 +538,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 +552,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 +615,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 +643,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,35 +680,18 @@ 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 ) { - $self->{'validate'} = $arg ? 1 : 0; - } - return $self->{'validate'} || 0; -} +# Must come after all 'has' declarations +around new => \&ex2err; 1; @@ -896,8 +724,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 +808,15 @@ add_drop_table =item * -quote_table_names +quote_identifiers + +=item * + +quote_table_names (DEPRECATED) =item * -quote_field_names +quote_field_names (DEPRECATED) =item * @@ -1009,18 +840,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 =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 =head2 no_comments @@ -1033,9 +868,9 @@ The C 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) and passed its container C instance, which it should -call the C method on, to get the C +call the C method on, to get the C generated by the parser. It is expected that the function transform the -schema structure to a string. The C instance is also useful +schema structure to a string. The C instance is also useful for informational purposes; for example, the type of the parser can be retrieved using the C method, and the C and C methods can be called when needed. @@ -1268,47 +1103,8 @@ Returns the version of the SQL::Translator release. =head1 AUTHORS -The following people have contributed to the SQLFairy project: - -=over 4 - -=item * Mark Addison - -=item * Sam Angiuoli - -=item * Anders Nor Berle - -=item * Dave Cash - -=item * Darren Chamberlain - -=item * Ken Y. Clark - -=item * Allen Day - -=item * Paul Harrington - -=item * Mikey Melillo - -=item * Chris Mungall - -=item * Ross Smith II - -=item * Gudmundur A. Thorisson - -=item * Chris To - -=item * Jason Williams - -=item * Ying Zhang - -=item * Daniel Ruoso - -=item * Ryan D Johnson - -=item * Jonathan Yu - -=back +See the included AUTHORS file: +L If you would like to contribute to the project, you can send patches to the developers mailing list: @@ -1321,19 +1117,12 @@ added to the project and what you'd like to contribute. =head1 COPYRIGHT -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. +Copyright 2012 the SQL::Translator authors, as listed in L. -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. +=head1 LICENSE -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 +This library is free software and may be distributed under the same terms as +Perl 5 itself. =head1 BUGS @@ -1341,7 +1130,7 @@ Please use L for reporting bugs. =head1 PRAISE -If you find this module useful, please use +If you find this module useful, please use L to rate it. =head1 SEE ALSO