package Fey::Role::SQL::HasWhereClause; BEGIN { $Fey::Role::SQL::HasWhereClause::VERSION = '0.40'; } use strict; use warnings; use namespace::autoclean; use Fey::Exceptions qw( param_error ); use Fey::SQL::Fragment::Where::Boolean; use Fey::SQL::Fragment::Where::Comparison; use Fey::SQL::Fragment::Where::SubgroupStart; use Fey::SQL::Fragment::Where::SubgroupEnd; use Fey::Types qw( ArrayRef ); use Moose::Role; has '_where' => ( traits => ['Array'], is => 'bare', isa => ArrayRef, default => sub { [] }, handles => { _add_where_element => 'push', _has_where_elements => 'count', _last_where_element => [ 'get', -1 ], _where => 'elements', }, init_arg => undef, ); sub where { my $self = shift; $self->_condition( 'where', @_ ); return $self; } # Just some sugar sub and { my $self = shift; return $self->where(@_); } { my %dispatch = ( 'and' => '_and', 'or' => '_or', '(' => '_subgroup_start', ')' => '_subgroup_end', ); sub _condition { my $self = shift; my $key = shift; if ( @_ == 1 ) { if ( my $meth = $dispatch{ lc $_[0] } ) { $self->$meth($key); return; } else { param_error qq|Cannot pass one argument to $key() unless it is one of "and", "or", "(", or ")".|; } } $self->_add_and_if_needed($key); my $add_method = '_add_' . $key . '_element'; $self->$add_method( Fey::SQL::Fragment::Where::Comparison->new( $self->auto_placeholders(), @_ ) ); } } sub _add_and_if_needed { my $self = shift; my $key = shift; my $has_method = '_has_' . $key . '_elements'; return unless $self->$has_method(); my $last_method = '_last_' . $key . '_element'; my $last = $self->$last_method(); return if $last->isa('Fey::SQL::Fragment::Where::Boolean'); return if $last->isa('Fey::SQL::Fragment::Where::SubgroupStart'); $self->_and($key); } sub _and { my $self = shift; my $key = shift; my $add_method = '_add_' . $key . '_element'; $self->$add_method( Fey::SQL::Fragment::Where::Boolean->new( comparison => 'AND' ) ); return $self; } sub _or { my $self = shift; my $key = shift; my $add_method = '_add_' . $key . '_element'; $self->$add_method( Fey::SQL::Fragment::Where::Boolean->new( comparison => 'OR' ) ); return $self; } sub _subgroup_start { my $self = shift; my $key = shift; $self->_add_and_if_needed($key); my $add_method = '_add_' . $key . '_element'; $self->$add_method( Fey::SQL::Fragment::Where::SubgroupStart->new() ); return $self; } sub _subgroup_end { my $self = shift; my $key = shift; my $add_method = '_add_' . $key . '_element'; $self->$add_method( Fey::SQL::Fragment::Where::SubgroupEnd->new() ); return $self; } sub where_clause { my $self = shift; my $dbh = shift; my $skip_where = shift; return unless $self->_has_where_elements(); my $sql = ''; $sql = 'WHERE ' unless $skip_where; return ( $sql . ( join ' ', map { $_->sql($dbh) } $self->_where() ) ); } sub bind_params { my $self = shift; return ( map { $_->bind_params() } grep { $_->can('bind_params') } $self->_where() ); } 1; # ABSTRACT: A role for queries which can include a WHERE clause =pod =head1 NAME Fey::Role::SQL::HasWhereClause - A role for queries which can include a WHERE clause =head1 VERSION version 0.40 =head1 SYNOPSIS use Moose; with 'Fey::Role::SQL::HasWhereClause'; =head1 DESCRIPTION Classes which do this role represent a query which can include a C clause. =head1 METHODS This role provides the following methods: =head2 $query->where(...) See the L for more details. =head2 $query->and(...) See the L for more details. =head2 $query->where_clause( $dbh, $skip_where ) Returns the C clause portion of the SQL statement as a string. The first argument, a database handle, is required. If the second argument is true, the string returned will not start with "WHERE", it will simply start with the where clause conditions. =head1 BUGS See L for details on how to report bugs. =head1 AUTHOR Dave Rolsky =head1 COPYRIGHT AND LICENSE This software is Copyright (c) 2011 by Dave Rolsky. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) =cut __END__