Alzabo

 view release on metacpan or  search on metacpan

lib/Alzabo/RDBMSRules.pm  view on Meta::CPAN

package Alzabo::RDBMSRules;

use strict;
use vars qw($VERSION);

use Alzabo::Exceptions ( abbr => [ 'recreate_table_exception' ] );

use Class::Factory::Util;
use Params::Validate qw( validate validate_pos );
Params::Validate::validation_options( on_fail => sub { Alzabo::Exception::Params->throw( error => join '', @_ ) } );

$VERSION = 2.0;

1;

sub new
{
    shift;
    my %p = @_;

    eval "use Alzabo::RDBMSRules::$p{rdbms};";
    Alzabo::Exception::Eval->throw( error => $@ ) if $@;
    return "Alzabo::RDBMSRules::$p{rdbms}"->new(@_);
}

sub available { __PACKAGE__->subclasses }

# validation

sub validate_schema_name
{
    shift()->_virtual;
}

sub validate_table_name
{
    shift()->_virtual;
}

sub validate_column_name
{
    shift()->_virtual;
}

sub validate_column_type
{
    shift()->_virtual;
}

sub validate_column_length
{
    shift()->_virtual;
}

sub validate_table_attribute
{
    shift()->_virtual;
}

sub validate_column_attribute
{
    shift()->_virtual;
}

sub validate_primary_key
{
    shift()->_virtual;
}

sub validate_sequenced_attribute
{
    shift()->_virtual;
}

sub validate_index
{
    shift()->_virtual;
}

sub type_is_numeric
{
    my $self = shift;

lib/Alzabo/RDBMSRules.pm  view on Meta::CPAN


    unless ($pk_changed)
    {
        foreach my $new_pk ( $p{new}->primary_key )
        {
            my $old_col = eval { $p{old}->column( $new_pk->name ) };

            next if $new_pk->former_name && $changed_name{ $new_pk->former_name };

            unless ( $old_col && $old_col->is_primary_key )
            {
                push @sql, $self->alter_primary_key_sql( new => $p{new},
                                                         old => $p{old} );

                last;
            }
        }
    }

    my $alter_attributes;
    foreach my $new_att ( $p{new}->attributes )
    {
        unless ( $p{old}->has_attribute( attribute => $new_att, case_sensitive => 1 ) )
        {
            $alter_attributes = 1;

            push @sql, $self->alter_table_attributes_sql( new => $p{new},
                                                          old => $p{old},
                                                        );

            last;
        }
    }

    unless ($alter_attributes)
    {
        foreach my $old_att ( $p{old}->attributes )
        {
            unless ( $p{new}->has_attribute( attribute => $old_att, case_sensitive => 1 ) )
            {
                $alter_attributes = 1;

                push @sql, $self->alter_table_attributes_sql( new => $p{new},
                                                              old => $p{old},
                                                            );

                last;
            }
        }
    }

    return @sql;
}


sub _virtual
{
    my $self = shift;

    my $sub = (caller(1))[3];
    Alzabo::Exception::VirtualMethod->throw( error =>
                                             "$sub is a virtual method and must be subclassed in " . ref $self );
}

__END__

=head1 NAME

Alzabo::RDBMSRules - Base class for Alzabo RDBMS rulesets

=head1 SYNOPSIS

  use Alzabo::RDBMSRules;

  my $rules = Alzabo::RDBMSRules( rules => 'MySQL' );

=head1 DESCRIPTION

This class is the base class for all C<Alzabo::RDBMSRules> modules.
To instantiate a subclass call this class's C<new()> method.  See the
L<SUBCLASSING Alzabo::RDBMSRules> section for information on how to
make a ruleset for the RDBMS of your choice.

=head1 METHODS

=head2 available

A list of names representing the available C<Alzabo::RDBMSRules>
subclasses.  Any one of these names would be appropriate as the
"rdbms" parameter for the L<C<< Alzabo::RDBMSRules->new()
>>|Alzabo::RDBMSRules/new> method.

=head2 new

The constructor always accepts one parameter, "rdbms", which is the
name of the RDBMS to be used.

Some subclasses may accept additional values.

The constructor returns a new C<Alzabo::RDBMSRules> object of the
appropriate subclass.

Throws: L<C<Alzabo::Exception::Eval>|Alzabo::Exceptions>

=head2 schema_sql (C<Alzabo::Create::Schema> object)

Returns a list of SQL statements which would create the given schema.

=head2 index_sql (C<Alzabo::Create::Index> object)

Returns a list of SQL statements to create the specified index.

=head2 drop_table_sql (C<Alzabo::Create::Table> object)

Returns a list of SQL statements to drop the specified table.

=head2 drop_index_sql (C<Alzabo::Create::Index> object)

Returns a list of SQL statements to drop the specified index.

=head2 schema_sql_diff

lib/Alzabo/RDBMSRules.pm  view on Meta::CPAN

being chosen from a list.  MySQL's ENUM and SET types are examples of
such types.

=item * index_column_prefixes

MySQL supports the notion of column prefixes in indexes, allowing you
to index only a portion of a large text column.

=item * fulltext_indexes

This should be self-explanatory.

=item * functional_indexes

Indexes on functions, as supported by PostgreSQL.

=back

=head2 validate_schema_name (C<Alzabo::Schema> object)

Throws an L<C<Alzabo::Exception::RDBMSRules>|Alzabo::Exceptions> if
the schema's name is not valid.

=head2 validate_table_name (C<Alzabo::Create::Table> object)

Throws an L<C<Alzabo::Exception::RDBMSRules>|Alzabo::Exceptions> if
the table's name is not valid.

=head2 validate_column_name (C<Alzabo::Create::Column> object)

Throws an L<C<Alzabo::Exception::RDBMSRules>|Alzabo::Exceptions> if
the column's name is not valid.

=head2 validate_column_type ($type_as_string)

Throws an L<C<Alzabo::Exception::RDBMSRules>|Alzabo::Exceptions> if
the type is not valid.

This method returns a canonized version of the type.

=head2 validate_column_length (C<Alzabo::Create::Column> object)

Throws an L<C<Alzabo::Exception::RDBMSRules>|Alzabo::Exceptions> if
the length or precision is not valid for the given column.

=head2 validate_column_attribute

This method takes two parameters:

=over 4

=item * column => C<Alzabo::Create::Column> object

=item * attribute => $attribute

=back

This method is a bit different from the others in that it takes an
existing column object and a B<potential> attribute.

It throws an L<C<Alzabo::Exception::RDBMSRules>|Alzabo::Exceptions> if
the attribute is is not valid for the column.

=head2 validate_primary_key (C<Alzabo::Create::Column> object)

Throws an L<C<Alzabo::Exception::RDBMSRules>|Alzabo::Exceptions> if
the column is not a valid primary key for its table.

=head2 validate_sequenced_attribute (C<Alzabo::Create::Column> object)

Throws an L<C<Alzabo::Exception::RDBMSRules>|Alzabo::Exceptions> if
the column cannot be sequenced.

=head2 validate_index (C<Alzabo::Create::Index> object)

Throws an L<C<Alzabo::Exception::RDBMSRules>|Alzabo::Exceptions> if
the index is not valid.

=head2 table_sql (C<Alzabo::Create::Table> object)

Returns an array of SQL statements to create the specified table.

=head2 column_sql (C<Alzabo::Create::Column> object)

Returns an array of SQL statements to create the specified column.

=head2 foreign_key_sql (C<Alzabo::Create::ForeignKey> object)

Returns an array of SQL statements to create the specified foreign
key.

=head2 drop_column_sql (C<Alzabo::Create::Column> object)

Returns an array of SQL statements to drop the specified column.

=head2 drop_foreign_key_sql (C<Alzabo::Create::ForeignKey> object)

Returns an array of SQL statements to drop the specified foreign key.

=head2 column_sql_add (C<Alzabo::Create::Column> object)

Returns an array of SQL statements to add the specified column.

=head2 column_sql_diff

This method takes two parameters:

=over 4

=item * new => C<Alzabo::Create::Column> object

=item * old => C<Alzabo::Create::Column> object

=back

This method compares the two table objects and returns an array of
SQL statements which turn the "old" table into the "new" one.

=head2 index_sql_diff

This method takes two parameters:



( run in 0.569 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )