Как получить доступ к конкретному возвращаемому значению из функции CDBI::Search?

Я использую DB::CDBI класс для доступа к базе данных в нашем приложении. Наш проект находится в объектно-ориентированном Perl.

package LT::LanguageImport;
use strict;
use warnings;
use base 'Misk5::CDBI';

__PACKAGE__->table( 'english_text_translation' );
__PACKAGE__->columns( Primary => qw/english language translation/ );
__PACKAGE__->columns( Essential => qw/english language translation/ );
__PACKAGE__->has_a( english => 'LT::EnglishLanguage' );

В одном из таких сценариев я должен проверить, существует ли строка в таблице. Я использую встроенный API поиска в вызове CDBI.

sub find_translation {
    my $translation_exists_r_not = $class->search(
        english     => $english,
        language    => $language,
        translation => $translation
    );
    return;
}

$translation_exists_r_not получает ожидаемые значения в зависимости от входных данных, приведенных в поиске. Если строка существует, то _data обновляется с подробностями строки.

$translation_exists_r_not = bless({
        '_data' => [
            {
                'language'    => 'polish',
                'translation' => 'Admin',
                'english'     => 'admin'
            }
        ],
        '_place'  => 0,
        '_mapper' => [],
        '_class'  => 'LT::LanguageImport'
    },
    'Class::DBI::Iterator'
);

Если строка не существует, то я получаю возвращаемое значение, как это.

$translation_exists_r_not = bless({
        '_data'   => [],
        '_place'  => 0,
        '_mapper' => [],
        '_class'  => 'LT::LanguageImport'
    },
    'Class::DBI::Iterator'
);

Я хочу вернуть значение translation из этого саба find_translation в зависимости от результата поиска. Я не могу получить лучшее условие для этого.

Я пытался скопировать _data в массив, но я не уверен, что делать дальше. Как _data будет пустой arrayref и другим условием будет иметь хеш-ссылку внутри arrayref.

my @Arr = $translation_exists_r_not->{'_data'};

2 ответа

Решение

CDBI-х search Метод вернет итератор, поскольку может быть возвращено несколько строк в зависимости от ваших критериев.

Если вы знаете, что может быть только одна строка, соответствующая вашим критериям, вы хотите использовать retrieve метод, то есть:

if (my $translation_exists_r_not = $class->retrieve(
    english     => $english,
    language    => $language,
    translation => $translation
)){
    return [$translation_exists_r_not->translation,
            'Misk5::TranslationAlreadyExists']
}
else {
    return [ '', undef ]
}

И если из вашего поиска могут быть возвращены несколько строк, и вас интересует только правдивость, то опять же, не копайтесь в CDBI::Iterator, а используйте его методы:

my $translation_exists_r_not = $class->search(
    english     => $english,
    language    => $language,
    translation => $translation
); # returns an iterator
if ($translation_exists_r_not){
    my $first = $translation_exists_r_not->first;
    return [ $first->translation, 'Misk5::TranslationAlreadyExists' ]
}

Посмотри на perldoc Class::DBI а также perldoc Class::DBI::Iterator, CDBI имеет отличную документацию.

Я думаю, что я получил решение. Спасибо тому, кто пытался это решить.

my @req_array      = %$translation_exists_r_not->{_data};
my $length_of_data = '9';
foreach my $elem (@req_array) {
    $length_of_data = @{$elem};
}

Теперь проверьте длину массива.

if ($length_of_data == 0) {
    $error = '';
    $result = [undef, $error];
}

Теперь проверьте, если это так.

if ($length_of_data == 1) {
    my @result_array = @{%$translation_exists_r_not->{_data}};
    my $translation  = $result_array[0]{'translation'};
    $error = 'Misk5::TranslationAlreadyExists';
    $result = [$translation, $error];
}
return @$result;
Другие вопросы по тегам