Moose Fix Bracket And AND

It is fix a bracket and AND day in the Moose-pen

I did a little more checking of my tests in '58_parenthes.t' and it would appear that my changes from yesterday's post did not actually do the trick as the second test is failing and the 'Condition' part of the has is in error;


conditions => [
{
left => {
name => 'First_1',
view => 'People'
},
right => { value => 'test->3' },
operator => '=',
open_parentheses => 1,
close_parentheses => 0,
condition => 'AND',
},
{
condition => 'AND',
left => {
name => 'First_2',
view => 'People'
},
right => { value => 'test->4' },
operator => '=',

}
]

as there is no ' close_parentheses' on the second condition in the array so into the code I go as obviously I am skipping over something to do with conditions.

After adding in a little warn here and there I determined that the bug is in the '_check_element' sub at this point;


}
elsif (ref($element) eq 'Database::Accessor::Condition'){
$self->_check_element($element->predicates->right);
$self->_check_element($element->predicates->left);
}
else {
return
unless(does_role($element,"Database::Accessor::Roles::Comparators"));
$self->_inc_parens()
if ( $element->open_parentheses() );
$self->_dec_parens()
if ( $element->close_parentheses() );

I will have to do that parentheses check at the point just after the elsif on 'Database::Accessor::Condition'. The check is the same in both cases so I will just do a little re-factoring into yet another 'private' sub;

First I add in the new sub;


private_method _check_parentheses => sub {
my $self = shift;
my ($element) = @_;
$self->_inc_parens()
if ( $element->open_parentheses() );
$self->_dec_parens()
if ( $element->close_parentheses() );
};

then adjust the '_check_element' sub

elsif (ref($element) eq 'Database::Accessor::Condition'){
++ $self->_check_parentheses($element->predicates);
$self->_check_element($element->predicates->right);
$self->_check_element($element->predicates->left);
}
else {
return
unless(does_role($element,"Database::Accessor::Roles::Comparators"));
++ $self->_check_parentheses($element);
$self->_check_element($element->right);
$self->_check_element($element->left);
}

rerun my test and I get;

ok 1 - Balanced parentheses
ok 2 - Caught unbalanced parentheses


so that is now passing part one done. However I have yet to add in the code to add in the default 'AND' at the end of a list of predicates. That is another item I want to get done today, onto that then.

The old code;


 $predicate->condition(Database::Accessor::Constants::AND)
                      if ( $predicate_count and !$predicate->condition() );

was I think too simple add in an AND if not present and there are more than one predicate present as now I am looping though all sorts of elements. I will have to put my thinking Moose on for this one.

The first thinking point is that only a 'conditional' operation will require a check and I really only have four attributes that fall into that category, 'conditions' and 'dynamic_conditions', obliviously, and the 'conditions' attribute of 'gather' and 'dynamic_gather' which are all of the 'ArrayRefofConditions' type. I at least have something to look for.

That lead me to here


foreach my $condition (@items) {
if (ref($condition) eq 'ARRAY'){
map( $self->_check_element($_),@{$condition});

}
else {

I though it would be that simple just to add it in there but there are other attributes that 'array-refs' like 'sorts' and 'elements' and I have two cases where the '$conditions' is an array-refs of conditions. I am also using re-coursing so I cannot just use the '$prediccate_count' as before.

I will need a private Database::Accessor attribute to keep track of that for me and I can do that with this;


has _has_conditions => (
traits => ['Counter'],
is => 'rw',
default => 0,
isa => 'Int',
handles => {
_inc_conditions => 'inc',
_dec_conditions => 'dec',
_reset_conditions => 'reset'
}
);

Next I will have to change my code a little where I do my iteration over my '@items'

foreach my $condition (@items) {
++ $self->_inc_conditions()
++ if (ref($condition) eq 'Database::Accessor::Condition');
if (ref($condition) eq 'ARRAY'){
++ $self->_reset_conditions();
++ $self->_inc_conditions()
if (scalar(@{$condition}) >=2 and ref($condition->[0]) eq 'Database::Accessor::Condition');
map( $self->_check_element($_),@{$condition});

}
else {
$self->_check_element($condition);
}
}


First I check an see if the current $condition is an 'Database::Accessor::Condition' and if it I then increment my '_has_conditions' counter, This will work for any static or dynamic 'conditions' I may have as they are the first ones in the '@items'.

Eventually as I iterate over '@items' I will hit the 'conditions' array-refs for links and gathers if this is the case I will first have to '_reset_conditions' and then '_inc_conditions' if there are more than two items in the array and the first item is a 'Database::Accessor::Condition'.

Finally in the '_check_element' sub I do the check for the 'AND' like this;


elsif (ref($element) eq 'Database::Accessor::Condition'){
$element->predicates->condition(Database::Accessor::Constants::AND)
if ( $self->_has_conditions and !$element->predicates->condition() );
$self->_check_parentheses($element->predicates);

and now when I run my test I get


...
ok 4 - Caught parentheses
ok 5 - And added to last condition predicate
ok 6 - Balanced parentheses


Now onto greater things.
IMG_5226a.jpg

Leave a comment

About byterock

user-pic Long time Perl guy, a few CPAN mods allot of work on DBD::Oracle and a few YAPC presentations