use strict;
use 5.010;
package FusqlFS::Backend::MySQL::Table::Struct;
use FusqlFS::Version;
our $VERSION = $FusqlFS::Version::VERSION;
use base 'FusqlFS::Artifact';
=head1 NAME
FusqlFS::Backend::MySQL::Table::Struct
=head1 SYNOPSIS
Synopsis
=head1 DESCRIPTION
Description
=cut
sub init
{
my $self = shift;
$self->{list_expr} = 'SHOW COLUMNS FROM `%s`';
$self->{get_expr} = 'SHOW FULL COLUMNS FROM `%s` LIKE "%s"';
$self->{get_create_expr} = 'SHOW CREATE TABLE `%s`';
$self->{create_expr} = 'ALTER TABLE `%s` ADD COLUMN `%s` INT NOT NULL DEFAULT 0';
$self->{rename_expr} = 'ALTER TABLE `%s` CHANGE COLUMN `%s` `%s` %s';
$self->{store_expr} = 'ALTER TABLE `%s` MODIFY COLUMN `%s` %s';
$self->{drop_expr} = 'ALTER TABLE `%s` DROP COLUMN `%s`';
}
sub build_column_def
{
my $data = shift;
return sprintf('%s %s %s NULL DEFAULT %s %s %s',
$data->{type},
$data->{collation}? 'COLLATE '.$data->{collation}: '',
$data->{null}? '': 'NOT',
defined $data->{default}? $data->{default}: 'NULL',
$data->{extra},
$data->{comment}? "COMMENT '$data->{comment}'": '');
}
=begin testing list
is $_tobj->list('unknown'), undef, 'Unknown table';
cmp_set $_tobj->list('fusqlfs_table'), ['id', 'create.sql'], 'Test table listable';
=end testing
=cut
sub list
{
my $self = shift;
my ($table) = @_;
my $list = $self->all_col($self->{list_expr}, [$table]);
return unless $list && @$list;
push @$list, 'create.sql';
return $list
}
=begin testing get
is $_tobj->get('fusqlfs_table', 'unknown'), undef, 'Unknown field';
is $_tobj->get('fusqlfs_table', 'id'), q{---
collation: ~
comment: ''
default: ~
extra: auto_increment
key: PRI
null: 0
privileges:
- select
- insert
- update
- references
type: int(11)
}, 'Known field';
=end testing
=cut
sub get
{
my $self = shift;
my ($table, $name) = @_;
if ($name eq 'create.sql')
{
return $self->one_row($self->{get_create_expr}, [$table])->{'Create Table'};
}
my $result = $self->one_row($self->{get_expr}, [$table, $name]);
if ($result)
{
$result = { map { lc($_) => $result->{$_} } grep { $_ ne 'Field' } keys %$result };
$result->{privileges} = [ split /,/, $result->{privileges} ];
$result->{null} = $result->{null} eq 'YES'? 1: 0;
return $self->dump($result);
}
return;
}
=begin testing drop after rename
isnt $_tobj->drop('fusqlfs_table', 'new_field'), undef, 'Field is dropped';
is $_tobj->get('fusqlfs_table', 'new_field'), undef, 'Field is not gettable';
is_deeply $_tobj->list('fusqlfs_table'), ['id'], 'Field is not listable';
=end testing
=cut
sub drop
{
my $self = shift;
my ($table, $name) = @_;
$self->do($self->{drop_expr}, [$table, $name]);
}
=begin testing create after get list
isnt $_tobj->create('fusqlfs_table', 'field'), undef, 'Create field';
is $_tobj->get('fusqlfs_table', 'field'), $new_field, 'New field exists';
is_deeply $_tobj->list('fusqlfs_table'), ['id', 'field'], 'New field is listable';
=end testing
=cut
sub create
{
my $self = shift;
my ($table, $name) = @_;
$self->do($self->{create_expr}, [$table, $name]);
}
=begin testing rename after store
isnt $_tobj->rename('fusqlfs_table', 'field', 'new_field'), undef, 'Field renamed';
is $_tobj->get('fusqlfs_table', 'field'), undef, 'New field is unaccessible by old name';
is $_tobj->get('fusqlfs_table', 'new_field'), $new_field, 'New field exists';
is_deeply $_tobj->list('fusqlfs_table'), ['id', 'new_field'], 'New field is listable';
=end testing
=cut
sub rename
{
my $self = shift;
my ($table, $name, $newname) = @_;
my $field = $self->one_row($self->{get_expr}, [$table, $name]);
return unless $field;
my $fielddef = build_column_def({ map { lc($_) => $field->{$_} } keys %$field });
$self->do($self->{rename_expr}, [$table, $name, $newname, $fielddef]);
}
=begin testing store after create
$new_field =~ s/type: int\(11\)/type: varchar(255)/;
$new_field =~ s/default: 0/default: ~/;
$new_field =~ s/collation: ~/collation: utf8_general_ci/;
$new_field =~ s/null: 0/null: 1/;
isnt $_tobj->store('fusqlfs_table', 'field', $new_field), undef, 'Field changed';
is $_tobj->get('fusqlfs_table', 'field'), $new_field, 'Field changed correctly';
=end testing
=cut
sub store
{
my $self = shift;
my ($table, $name, $data) = @_;
$data = $self->validate($data, {
type => '',
null => qr/^\d$/,
extra => '',
collation => '',
default => '',
comment => '',
}) or return;
my $fielddef = build_column_def($data);
$self->do($self->{store_expr}, [$table, $name, $fielddef]);
}
1;
__END__
=begin testing SETUP
#!class FusqlFS::Backend::MySQL::Table::Test
my $new_field = q{---
collation: ~
comment: ''
default: 0
extra: ''
key: ''
null: 0
privileges:
- select
- insert
- update
- references
type: int(11)
};
=end testing
=cut