Condiment Moose
It is catch up day here in the Moose-Pen.
I was just about to add in the next operator on my, the 'Like' command but before I did that I added a few more tests for the 'in' operator and with this test;
{ caption => 'in right must not be an hash ref',
type => 'exception',
key => 'conditions',
conditions => [
{
left => { name => 'cost' },
right => { name => 'cost' } ,
operator => 'IN',
},
],
retrieve =>
{ message => 'right can only be a Database::Accessor or an Array Ref' },
},
for the fail I got a a fail;
not ok 1 - retrieve in right must not be an hash ref
so I better fix that.
After some playing about I made this quick change
die("$message '".$predicate->operator."' right can only be a Database::Accessor or an Array Ref!")
-- unless ( ref( $predicate->right()) ne "ARRAY"
++ if ( ref( $predicate->right()) ne "ARRAY"
or ref($predicate->right()) ne "Database::Accessor" );
but all that change accomplished was a 'die' at the frist 'In' tests with;
Database::Accessor::Driver::DBI::Error->Operator 'IN' right can only be a
Database::Accessor or an Array Ref! at D:\GitHub\database-accessor-driver-
dbi\lib/Database/Accessor/Driver/DBI.pm line 330.
Which I think I had before. Looking at what I had entered on the test that is actually a valid, if useless, SQL which should evaluate to
WHERE people.cost in (people.cost)
what would be invalid is any variation on this SQL
WHERE people.cost in (people.cost,SELECT cost FROM somplace)
So what I should check for here is a 'select' statement (DA) in an array of params or elements. So first change my test a little
right => { name => 'cost',
value =>Test::Utils::in_da_sql() },
…
retrieve =>
{ message => 'Array Ref can not contain a Database::Accessor' },
and my new logic in Driver::DBI;
if ( ref( $predicate->right()) eq "ARRAY") {
foreach my $param (@{ $predicate->right()}){
die("$message '".$predicate->operator."' Array Ref can not contain a
Database::Accessor")
if (ref($param) eq "Database::Accessor::Param"
and ref($param->value) eq "Database::Accessor");
}
}
and I get a pass
77 ok in right must not be and array ref with a DA and params
but this is also valid SQL though again I have never used it;
WHERE people.cost in (SELECT cost FROM somplace,
SELECT price from Somplace)
So I what I can't have is a mixed array the above has to be fixed to;
if ( ref( $predicate->right()) eq "ARRAY") {
my $not_count = 0;
foreach my $param (@{ $predicate->right()}){
$not_count++
if (ref($param) eq "Database::Accessor::Param"
and ref($param->value) eq "Database::Accessor");
}
die("$message '".$predicate->operator."' Array Ref can not contain a Database::Accessor")
if ($not_count and scalar(@{ $predicate->right()}) != $not_count);
}
and that does the trick;
...
ok 77 - retrieve in right must not be and array ref with a DA and params
While I am here I think I will improve on this;
elsif ($predicate->operator eq Database::Accessor::Driver::DBI::SQL::IS_NULL) {
$clause .= join(" ",$self->_field_sql($predicate->left,1)
,Database::Accessor::Driver::DBI::SQL::IS
,Database::Accessor::Driver::DBI::SQL::NULL
);
}
elsif ($predicate->operator eq
Database::Accessor::Driver::DBI::SQL::IS_NOT_NULL) {
$clause .= join(" ",$self->_field_sql($predicate->left,1)
,Database::Accessor::Driver::DBI::SQL::IS
,Database::Accessor::Driver::DBI::SQL::NOT
,Database::Accessor::Driver::DBI::SQL::NULL
);
}
…
and change it to just one if using an 'or' and just use the '$predicate->operator' in place of the two or three constants;
elsif ($predicate->operator eq Database::Accessor::Driver::DBI::SQL::IS_NULL
or $predicate->operator eq
Database::Accessor::Driver::DBI::SQL::IS_NOT_NULL) {
$clause .= join(" ",$self->_field_sql($predicate->left,1)
,$predicate->operator
);
}
and on retest I still get 100% pass. Not much forward progression today but cleaner code.
Leave a comment