package SQL::Maker::Plugin::JoinSelect;
use 5.008001;
use strict;
use warnings;
our $VERSION = "0.03";
use Carp ();
our @EXPORT = qw/join_select/;
sub join_select {
my ($self, $base_table, $join_conditoins, $fields, $where, $opt) = @_;
my @join_conditions = @$join_conditoins;
my @joins;
while ( my ($table, $join_cond) = splice @join_conditions, 0, 2) {
my ($type, $cond) = ('inner',);
my $ref = ref $join_cond;
if (!$ref || $ref eq 'HASH') {
$cond = $join_cond;
}
elsif ($ref eq 'ARRAY') {
if (uc($join_cond->[0]) =~ /^(?:(?:(?:LEFT|RIGHT|FULL)(?: OUTER)?)|INNER|CROSS)$/) {
$type = $join_cond->[0];
$cond = $join_cond->[1];
}
else {
$cond = $join_cond;
}
}
else {
Carp::croak 'join condition is not valid';
}
push @joins, [$base_table => {
type => $type,
table => $table,
condition => $cond,
}];
}
my %opt = %{ $opt || {} };
push @{ $opt{joins} }, @joins;
$self->select(undef, $fields, $where, \%opt);
}
1;
__END__
=encoding utf-8
=head1 NAME
SQL::Maker::Plugin::JoinSelect - Plugin of SQL::Maker for making SQL contained `JOIN`
=head1 SYNOPSIS
use SQL::Maker;
SQL::Maker->load_plugin('JoinSelect');
my $builder = SQL::Maker->new(driver => 'SQLite', new_line => ' ');
my ($sql, @binds) = $builder->join_select(
user => [
item => 'user.id = item.user_id',
],
['*'],
{
'user.id' => 1,
},
);
print $sql; #=> 'SELECT * FROM "user" INNER JOIN "item" ON user.id = item.user_id WHERE ("user"."id" = ?)';
=head1 DESCRIPTION
SQL::Maker::Plugin::JoinSelect is Plugin of SQL::Maker for making SQL contained `JOIN`.
=head1 INTERFACE
=head2 Method
=head3 C<< ($sql, @binds) = $sql_maker->join_select($table, $join_conds, \@fields, \%where, \%opt) >>
C<$table>, C<\@fields>, C<\%where> and C<\%opt> are same as arguments of C<< $sql_maker->select >>.
C<$join_conds> is an ArrayRef containing sequenced pair of C<$table> and C<$join_cond> as follows.
[
'user_item' => {'user.id' => 'user_item.user_id'},
'item' => 'user_item.item_id => item.id',
...
]
Each C<$join_cond> can be ArrayRef, HashRef and String same as condition argument of L<SQL::Maker::Select>'s C<add_join> method.
Join type is 'inner' by default. If you want to specify join type, you can use ArrayRef like follows.
[
'item' => ['outer' => {'user.id' => 'item.user_id'}],
]
=head1 LICENSE
Copyright (C) Masayuki Matsuki.
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=head1 AUTHOR
Masayuki Matsuki E<lt>y.songmu@gmail.comE<gt>
=cut