#------------------------------------------------------------------------------
# DBO::Visitor::Check - check record for validity
#
# DESCRIPTION
# A visitor class that checks a record from a database table
# (represented as a hash mapping column name to value) for validity.
#
# AUTHOR
# Gareth Rees
#
# COPYRIGHT
# Copyright (c) 1999 Canon Research Centre Europe Ltd/
#
# $Id: Check.pm,v 1.3 1999/06/21 15:11:24 garethr Exp $
#------------------------------------------------------------------------------
use strict;
package DBO::Visitor::Check;
use base qw(DBO::Visitor);
use Class::Multimethods;
multimethod visit_table =>
qw(DBO::Visitor::Check DBO::Table DBO::Handle) =>
sub {
my ($vis, $table, $handle) = @_;
foreach my $col (@{$table->{columns}}) {
visit_column($vis, $col, $handle) or return 0;
}
return 1;
};
multimethod visit_column =>
qw(DBO::Visitor::Check DBO::Column::Base DBO::Handle) =>
sub {
my ($vis, $col, $handle) = @_;
if ($col->{not_null} and not defined $vis->{record}{$col->{name}}) {
$vis->{error} = DBO::Exception->new
(NULL_COLUMN => "You must supply a value for %s.", $col->{name});
return 0;
}
return 1;
};
multimethod visit_column =>
qw(DBO::Visitor::Check DBO::Column::Number DBO::Handle) =>
sub {
my ($vis, $col, $handle) = @_;
# visit_column($vis, superclass($col), $handle) or return 0;
call_next_method() or return 0;
my $value = $vis->{record}{$col->{name}};
if (defined $value and do { local $^W; $value + 0 ne $value }) {
$vis->{error} = DBO::Exception->new
(NUMERIC => "You must supply a number for %s.", $col->{name});
return 0;
}
return 1;
};
multimethod visit_column =>
qw(DBO::Visitor::Check DBO::Column::Integer DBO::Handle) =>
sub {
my ($vis, $col, $handle) = @_;
# visit_column($vis, superclass($col), $handle) or return 0;
call_next_method() or return 0;
my $value = $vis->{record}{$col->{name}};
if (defined $value and $value != int $value) {
$vis->{error} = DBO::Exception->new
(INTEGER => "You must supply an integer for %s.", $col->{name});
return 0;
}
return 1;
};
multimethod visit_column =>
qw(DBO::Visitor::Check DBO::Column::Unsigned DBO::Handle) =>
sub {
my ($vis, $col, $handle) = @_;
# visit_column($vis, superclass($col), $handle) or return 0;
call_next_method() or return 0;
my $value = $vis->{record}{$col->{name}};
if (defined $value and $value < 0) {
$vis->{error} = DBO::Exception->new
(UNSIGNED => "The value for %s must be non-negative.", $col->{name});
return 0;
}
return 1;
};
multimethod visit_column =>
qw(DBO::Visitor::Check DBO::Column::Option DBO::Handle) =>
sub {
my ($vis, $col, $handle) = @_;
# visit_column($vis, superclass($col), $handle) or return 0;
call_next_method() or return 0;
my $value = $vis->{record}{$col->{name}};
unless (grep { $_ eq $value } @{$col->{values}}) {
$vis->{error} = DBO::Exception->new
(OPTION => "The value for %s must be one of %s.",
$col->{name}, join ", ", @{$col->{values}});
return 0;
}
return 1;
};
multimethod visit_column =>
qw(DBO::Visitor::Check DBO::Column::ForeignKey DBO::Handle) =>
sub {
my ($vis, $col, $handle) = @_;
# visit_column($vis, superclass($col), $handle) or return 0;
call_next_method() or return 0;
my $value = $vis->{record}{$col->{name}};
# TODO: Fetch values from foreign table and check.
return 1;
};
multimethod visit_column =>
qw(DBO::Visitor::Check DBO::Column::Char DBO::Handle) =>
sub {
my ($vis, $col, $handle) = @_;
# visit_column($vis, superclass($col), $handle) or return 0;
call_next_method() or return 0;
my $value = $vis->{record}{$col->{name}};
if (defined $value and $col->{max_length} < length $value) {
$vis->{error} = DBO::Exception->new
(LENGTH => "The value for %s is %d characters long (must be at most %d characters long).",
$col->{name}, length $value, $col->{max_length});
return 0;
}
return 1;
};
multimethod visit_column =>
qw(DBO::Visitor::Check DBO::Column::Time DBO::Handle) =>
sub {
my ($vis, $col, $handle) = @_;
# visit_column($vis, superclass($col), $handle) or return 0;
call_next_method() or return 0;
my $value = $vis->{record}{$col->{name}};
if ($value !~ /^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d/) {
$vis->{error} = DBO::Exception->new
(TIME => "The value for %s must look like '1999-05-15 23:46:00'.",
$col->{name}, $value);
return 0;
}
return 1;
};
1;