Мне нужно извлечь одну строку из таблицы базы данных, используя DBIx :: Class, когда один из двух столбцов дескриптора подобен предоставленным данным.
Мой выбор SQL выглядит следующим образом:
select id from products where (code = 'VALUE' or description like '%VALUE%')
Таблица имеет уникальное ограничение, которое гарантирует, что для VALUE существует только одна строка.
Как я могу сформулировать этот SQL, используя DBIx :: Class?
Следующий код возвращает мне значение 1 , но не правильные данные:
my $param = 'VALUE';
my $res = $c->stash->{products_rs}->search(
-or => [
{ code => { '=', $param } },{ description => { 'like', '%'.$param.'%' } }
],
);
Я должен использовать метод find , чтобы вернуть одну строку, но тогда я не могу использовать предложение -or .
Есть предложения?
Привет, я вернулся. Я решил создать себе классы. Сначала класс схемы:
package prod::Schema;
use utf8;
use Moose;
use MooseX::MarkAsMethods autoclean => 1;
extends 'DBIx::Class::Schema';
__PACKAGE__->load_namespaces(
default_resultset_class => 'ResultSet',
);
__PACKAGE__->meta->make_immutable(inline_constructor => 0);
1;
Я использую базовый класс Result для своей таблицы:
package prod::Schema::Result;
use strict;
use warnings;
use base qw( DBIx::Class::Core );
__PACKAGE__->load_components(
"InflateColumn::DateTime",
"TimeStamp",
"EncodedColumn"
);
1;
Затем каждая таблица использует базовый класс ResultSet:
package prod::Schema::ResultSet;
use strict;
use warnings;
use base qw( DBIx::Class::ResultSet );
__PACKAGE__->load_components('Helper::ResultSet::OneRow');
1;
и сам класс Product:
package prod::Schema::Result::Products;
use strict;
use warnings;
use utf8;
use Moose;
use MooseX::NonMoose;
use MooseX::MarkAsMethods autoclean => 1;
extends 'prod::Schema::Result';
__PACKAGE__->table("prod.products");
__PACKAGE__->add_columns("id", {
data_type => "uuid",
default_value => \"uuid_generate_v4()",
is_nullable => 0,
size => 16,
}, "code", {
data_type => "varchar", is_nullable => 0, size => 2
}, "name", {
data_type => "varchar", is_nullable => 0, size => 128 },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->add_unique_constraint("uk_products_code", ["code"]);
__PACKAGE__->meta->make_immutable;
1;
Приложение использует этот класс модели:
package prod::Model::DB_T;
use strict;
use base 'Catalyst::Model::DBIC::Schema';
__PACKAGE__->config(
schema_class => 'prod::Schema',
connect_info => {
dsn => 'dbi:Pg:dbname=p12;host=localhost',
user => 'username',
password => 'password',
AutoCommit => q{1},
}
);
1;
Корень такой:
package prod::Controller::Root;
use Moose;
use namespace::autoclean;
use Data::Dumper;
BEGIN { extends 'Catalyst::Controller' }
__PACKAGE__->config(namespace => '');
sub index :Path :Args(0) {
my ($self, $c) = @_;
my $Products = $c->model('DB_T::Products');
my $product = $Products->search(
-or => [
{ code => { '=', 'x' } },{ name => { 'like', '%'.'X'.'%' } }
],
)->one_row;
my $str = ''.$product->name;
$c->response->body('product: '.$str);
}
sub default :Path {
my ($self, $c) = @_;
$c->response->body('Page not found');
$c->response->status(404);
}
sub end : ActionClass('RenderView') {}
__PACKAGE__->meta->make_immutable;
1;
Теперь я использую one_row из этого вспомогательного класса, я получаю желаемый результат, но оператор SQL остается открытым, пока я не закрою приложение.
@ Александр Хартмайер, ты сказал, что мне следует избегать этого. Но как? Что не так с этим кодом?