Smarty Pants Moose

Its back-fix code day here in the Moose-pen

In yesterday's post-ette I ranted on about how much of a smarty pants I was to use a 'param' in as the type for my 'message' part of a case statement. That was working fine until I blundered across this perfectly valid SQL


SELECT StockID, OnOrderQuantity,
   CASE
     WHEN Stock - OnOrderQuantity > 30 THEN  'Over Stocked'
     WHEN Stock - OnOrderQuantity > 0 AND Stock-OnOrderQuantity <=30 THEN 'Stocked'
     ELSE Stock - OnOrderQuantity
   END
FROM Stock;
The 'else' in this case is an 'expression' and if I prototyped this out like this

 whens => [
            {
                left       => { expression=>'-',
                                     left=>{name  => 'Stock'},
                                     right=>{name =>'OnOrderQuanity'} },
                right      => { value => '30' },
                operator   => '>',
                message => { value => 'Over Stocked' }
            },
            [
                {
                    left     => { expression=>'-',
                                     left=>{name  => 'Stock'},
                                     right=>{name =>'OnOrderQuanity'} },
                    right    => { value => '0' },
                    operator => '>',
                },
                {
                    condition  => 'and',
                    left       => { expression=>'-',
                                     left=>{name  => 'Stock'},
                                     right=>{name =>'OnOrderQuanity'} },
                    right      => { value => '30' },
                    operator   => '<=',
                    message => { value => 'Stocked' }
                },
            ],
            { message => { value => 'Stock - OnOrderQuantity' } },
        ]
and that final message would fail as it is a param not an expression, and my send sql would look like this

CASE
     WHEN Stock - OnOrderQuantity > ? THEN  ?
     WHEN Stock - OnOrderQuantity > ? AND Stock-OnOrderQuantity <=? THEN ?
     ELSE ?
   END
Which would not work as expected as what would be returned by that final 'else' is the steing 'Stock – OnOrderQuantity' not a value like -1 , -10 etc.

I need to be able to do this;


{ message => { expression=>'-',
left=>{name => 'Stock'},
right=>{name =>'OnOrderQuanity'}
}
},

Doing a little more playing about with SQL I see that my 'message' field can be any valid field even a another case statement. So a little revision is in order me thinks;

I think I need only that 'message' attribute a little to make this work and I will go with just this change for now


++has 'message' => (
has 'statement' => (
-- isa => 'Param',
++ isa => 'Expression|Param|Element|Function|Case',
is => 'rw',
# required => 1,
);

I only changed the name of the attribute and expanded its 'isa' to include all the differing types including a Case.

Next after this a quick change to the test case to account for that attributes name change and a run of the test and I get a full pass.

Now add in a bunch of test cases for those four new types I will not bore you with all of that code as things when fine until I had to add a 'Case' into the a 'statement' attribute


$case = Database::Accessor::Case->new(
{
whens => [
{
left => { name => 'Price', },
right => { value => '10' },
operator => '<',
statement => { name => 'price' }
},
{
statement => {
whens => [
{
left => { name => 'Price', },
right => { value => '10' },
operator => '<',
statement => { name => 'price' }
},
{ statement => { name => 'price' } }
]
}
}
]
}
);
$last = pop( @{ $case->whens } );
ok( ref( $last->statement ) eq 'Database::Accessor::Case',
"last statment is an Case" );

and got this result;

Attribute (name) is required at D:\GitHub\database-accessor\lib/Database/Accessor/Types.pm line 178# Looks like your test exited with 255 just after 13.

To fix this one I will have to extend that '_element_coerce' sub in my 'Database::Accessor::Types' class to include that new 'Case' class;

elsif ( exists( $hash->{value} ) || exists( $hash->{param} ) ) {
$object = Database::Accessor::Param->new( %{$hash} );
}
++ elsif ( exists( $hash->{whens} )) {
++ $object = Database::Accessor::Case->new( %{$hash} );
++ }
else {
$object = Database::Accessor::Element->new( %{$hash} );

and now I am getting a full pass even with a final test where I use all the classes in a 'case'

So maybe I am ready to move onto Driver::DBI??

_MG_3353a.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