+ # And lastly recursive mode
+ if ($params{recursive}) {
+ my ($id_token, @ids);
+ if ($params{batch}) {
+ $id_token = sprintf 'IN (%s)', join ', ', ('?') x @{ $params{batch} };
+ @ids = @{ $params{batch} };
+ } else {
+ $id_token = '= ?';
+ @ids = ($self->id);
+ }
+
+ # don't use rose retrieval here. too slow.
+ # instead use recursive sql to get all the linked record_links entrys, and retrieve the objects from there
+ my $query = <<"";
+ WITH RECURSIVE record_links_rec_${wanted}(id, from_table, from_id, to_table, to_id, depth, path, cycle) AS (
+ SELECT id, from_table, from_id, to_table, to_id,
+ 1, ARRAY[id], false
+ FROM record_links
+ WHERE ${myself}_id $id_token and ${myself}_table = ?
+ UNION ALL
+ SELECT rl.id, rl.from_table, rl.from_id, rl.to_table, rl.to_id,
+ rlr.depth + 1, path || rl.id, rl.id = ANY(path)
+ FROM record_links rl, record_links_rec_${wanted} rlr
+ WHERE rlr.${wanted}_id = rl.${myself}_id AND rlr.${wanted}_table = rl.${myself}_table AND NOT cycle
+ )
+ SELECT DISTINCT ON (${wanted}_table, ${wanted}_id)
+ id, from_table, from_id, to_table, to_id, path, depth FROM record_links_rec_${wanted}
+ WHERE NOT cycle
+ ORDER BY ${wanted}_table, ${wanted}_id, depth ASC;
+
+ my $links = selectall_hashref_query($::form, $::form->get_standard_dbh, $query, @ids, $self->meta->table);
+
+ if (!@$links) {
+ return $params{by_id} ? {} : [];
+ }
+
+ my $link_objs = SL::DB::Manager::RecordLink->get_all(query => [ id => [ map { $_->{id} } @$links ] ]);
+ my $objects = $get_objects->($link_objs);
+
+ my %links_by_id = map { $_->{id} => $_ } @$links;
+
+ if ($params{save_path}) {
+ for (@$objects) {
+ for my $record_link ('ARRAY' eq ref $_->{_record_link} ? @{ $_->{_record_link} } : $_->{_record_link}) {
+ my $link = $links_by_id{$record_link->id};
+ my $intermediate_links = SL::DB::Manager::RecordLink->get_all(query => [ id => $link->{path} ]);
+ $_->{_record_link_path} = $link->{path};
+ $_->{_record_link_obj_path} = $get_objects->($intermediate_links);
+ $_->{_record_link_depth} = $link->{depth};
+ }
+ }
+ }
+
+ if ($params{batch} && $params{by_id}) {
+ my %link_obj_by_id = map { $_->id => $_ } @$link_objs;
+ return +{
+ map {
+ my $id = $_;
+ $id => [
+ grep {
+ any {
+ $link_obj_by_id{
+ $links_by_id{$_->id}->{path}->[0]
+ }->$sub_myself_id == $id
+ } 'ARRAY' eq $_->{_record_link} ? @{ $_->{_record_link} } : $_->{_record_link}
+ } @$objects
+ ]
+ } @{ $params{batch} }
+ };
+ } else {
+ return $objects;
+ }
+ }