Hello Monks,

My first encounter with DBIx::Class's subquery construct went so well (and my need of n subqueries so great) that I tried a programmatic way of creating nested subqueries, shared here.

Context is simply a tag search function using 3 tables. DB::TagDef (not shown) holds string to id, DB::Post has 0-n tags, and DB::TagCloud1 contains the join. Tag_ids are retrieved from DB::TagDef in ascending order of weight to ensure the smallest possible start set, getting progressively smaller.

sub recursive_subquery{ my($schema,$join_column,$key,$values) = @_; my ($value1) = shift(@$values); my $sub_query =$schema->search({ $key => $value1, }); for(@$values){ my $tmp_query = $schema->search({ $join_column => { -in => $sub_query->get_column($join_column)->as_query }, $key => $_, }); $sub_query = $tmp_query; } return $sub_query; }

And a short example of using it manually in Catalyst:

$c->stash->{rows} = $c->model('DB::Post')->search({ 'posts.post_id' => { -in => recursive_subquery( $c->model('DB::TagCloud1'), ,'post_id', 'tag_id',[ 16042, 190712, ])->get_column('post_id')->as_query }, });

As an aside, the performance of this highlighted the unhappy fact that mysql tends to evaluate sub queries from the outside-in, so you may want to reverse the weighting in that setup.