Aniki
view release on metacpan or search on metacpan
lib/Aniki.pm view on Meta::CPAN
my ($self, $table_name, $prefetch, $rows) = @_;
return unless @$rows;
$prefetch = [$prefetch] if ref $prefetch eq 'HASH';
my $relationships = $self->schema->get_table($table_name)->get_relationships;
for my $key (@$prefetch) {
if (ref $key && ref $key eq 'HASH') {
my %prefetch = %$key;
for my $key (keys %prefetch) {
$self->_fetch_and_attach_relay_data($relationships, $rows, $key, $prefetch{$key});
}
}
else {
$self->_fetch_and_attach_relay_data($relationships, $rows, $key, []);
}
}
}
sub _fetch_and_attach_relay_data {
my ($self, $relationships, $rows, $key, $prefetch) = @_;
my $relationship = $relationships->get($key);
unless ($relationship) {
croak "'$key' is not defined as relationship. (maybe possible typo?)";
}
$relationship->fetcher->execute($self, $rows, $prefetch);
}
sub select_named {
my ($self, $sql, $bind, $opt) = @_;
return $self->select_by_sql(bind_named($sql, $bind), $opt);
}
sub select_by_sql {
my ($self, $sql, $bind, $opt) = @_;
$opt //= {};
local $self->{suppress_row_objects} = 1 if $opt->{suppress_row_objects};
local $self->{suppress_result_objects} = 1 if $opt->{suppress_result_objects};
my $table_name = exists $opt->{table_name} ? $opt->{table_name} : $self->_guess_table_name($sql);
my $columns = exists $opt->{columns} ? $opt->{columns} : undef;
my $prefetch = exists $opt->{prefetch} ? $opt->{prefetch} : [];
$prefetch = [$prefetch] if ref $prefetch eq 'HASH';
my $prefetch_enabled_fg = @$prefetch && !$self->suppress_row_objects && defined wantarray;
if ($prefetch_enabled_fg) {
my $txn; $txn = $self->txn_scope(caller => [caller]) unless $self->in_txn;
my $sth = $self->execute($sql, @$bind);
my $result = $self->_fetch_by_sth($sth, $table_name, $columns);
$self->fetch_and_attach_relay_data($table_name, $prefetch, $result->rows);
$txn->rollback if defined $txn; ## for read only
return $result;
}
my $sth = $self->execute($sql, @$bind);
# When the return value is never used, should not create object
# case example: use `FOR UPDATE` query for global locking
unless (defined wantarray) {
$sth->finish();
return;
}
return $self->_fetch_by_sth($sth, $table_name, $columns);
}
sub _fetch_by_sth {
my ($self, $sth, $table_name, $columns) = @_;
$columns //= $sth->{NAME};
$columns = $sth->{NAME} if $columns == $WILDCARD_COLUMNS;
my @rows;
my %row;
$sth->bind_columns(\@row{@$columns});
push @rows => {%row} while $sth->fetch;
$sth->finish;
if ($self->suppress_result_objects) {
return \@rows if $self->suppress_row_objects;
my $row_class = $self->guess_row_class($table_name);
return [
map {
$row_class->new(
table_name => $table_name,
handler => $self,
row_data => $_,
)
} @rows
];
}
my $result_class = $self->guess_result_class($table_name);
return $result_class->new(
table_name => $table_name,
handler => $self,
row_datas => \@rows,
suppress_row_objects => $self->suppress_row_objects,
);
}
sub execute {
my ($self, $sql, @bind) = @_;
$sql = $self->handler->trace_query_set_comment($sql);
my $sth = $self->use_prepare_cached ? $self->dbh->prepare_cached($sql) : $self->dbh->prepare($sql);
$self->_bind_to_sth($sth, \@bind);
eval {
$sth->execute();
};
if ($@) {
$self->handle_error($sql, \@bind, $@);
}
return $sth;
}
( run in 1.444 second using v1.01-cache-2.11-cpan-df04353d9ac )