-4

You have the following table called Pets:

name     age     pet
------------------------
Carol     25     null
Stean     23     cat
Mel       24     dog
Rich      24     rabbit

In a MySQL database on the server mydbserver with the user of 'user' with a password of 'password'.

Do the following:

1) Create a Class::DBI connection to this database with the above credentials ( DBI.pm ).

2) Create a Class for the table Pets ( Pet.pm )

3) Create a program that prints all the names of people in the Pets table and what kind (if any ) of pet he/she has sorted by name then age.

Here is the code I wrote.....

#!/usr/bin/perl      
package Pet::DBI;
use DBI;
use strict;
use base 'Class::DBI';
Pet::DBI->set_db('Main','dbi:mysql:dname', 'user', 'password') 

or die $DBI::errstr "\n";
1;

package Pet::Pets;
use base 'Pet::DBI';
use strict;
use warning;
Pet::Pets->table('Pets');
Pet::Pets->columns(All => qw/name age pet/);
1;

use Pet::Pets;
my @pets = Pet::Pets->retrieve_all; 
for (sort {$a->name cmp $b->name} || {$a->age <=> $b->age}  @Pets) {
print "Name:".$_->name ' => '."Age". $_->age"\n";
}

1;
Schwern
  • 153,029
  • 25
  • 195
  • 336
  • 3
    If at all possible, consider [DBIx::Class](https://metacpan.org/pod/DBIx::Class). Class::DBI is no longer maintained and isn't a very good ORM by modern standards. I should know, [I wrote it](https://metacpan.org/pod/release/MSCHWERN/Class-DBI-0.02/lib/Class/DBI.pm). Also, is this homework? If it is, please let the teacher know the author says to stop using Class::DBI. :) Finally, the Class::DBI documentation already contains [an example of doing exactly this](https://metacpan.org/pod/Class::DBI#How-to-set-it-up). – Schwern Mar 17 '15 at 02:22
  • Thanks, unfortunately they are insisting on using Class::DBI and not DBIx::Class as the app used it. – user_falafel Mar 17 '15 at 02:50
  • I would like to know the answer to the 3 question. I got the first 2 questions. – user_falafel Mar 17 '15 at 02:54
  • Who are "they"? And why are they insisting on using supported software? That doesn't sound like good advice? – Dave Cross Mar 24 '15 at 10:43
  • @Dave Cross I agree but what do you think about sorting using Class::dbi ? – user_falafel Mar 25 '15 at 19:52
  • I think two things. I think that a) Schwern has already given you a good answer and b) a teaching environment should not be teaching obsolete software. – Dave Cross Mar 26 '15 at 11:26

1 Answers1

1

It's basically correct, but there's a number of small problems.

It's not necessary to load DBI, Class::DBI will take care of that for you.

You should be using connection instead of set_db("Main", ...). set_db comes from Ima::DBI and it's not polite (or necessary) to peek under the hood like that.

Although this isn't directly documented in Class::DBI (it should be), its inherited from Ima::DBI, there's no need to check for DBI errors. RaiseError is on and if the connection fails it will throw an error.

You have a typo, use warning; instead of use warnings;.

Unless you have stitched three files together for the post, if the code is all in one file the 1; statements do nothing. use Pet::Pets will not work because there is no Pet/Pets.pm file. You don't have to use a class which is already in the same file.

In general, avoid using $_ if you don't have to, too many things can quietly use or change it. Instead, give the for loop a proper variable like for my $person.

sort only takes one block, but you're basically correct. It should be sort { ($a->name cmp $b->name) || ($a->age <=> $b->age) } @Pets

To avoid reading the whole, potentially very large, table into memory, the sorting should really be done in the database with an ORDER BY name ASC, age ASC and then retrieved a row at a time using an iterator. Unfortunately, retrieve_all does not support any options. You can use retrieve_from_sql to add arbitrary SQL to the end of the basic SELECT. my $all_people = Pet::Pets->retrieve_from_sql("ORDER BY name ASC, age ASC"); Then your data will already be sorted and can be read a row at a time. while( my $person = $all_people->next ) { ... }

You're missing a . in "Age". $_->age"\n".

Null values in a database come back as undef. You'll want to check if $_->pet is defined and if not use some other string like "no pet" or just a blank "".

You're printing the person's age, the question asks for their pet.

Otherwise, it should work.

But really, tell whomever gave you this homework to stop telling people to use Class::DBI. They can email me if they like, schwern@pobox.com.

Schwern
  • 153,029
  • 25
  • 195
  • 336
  • Thanks Schwern, the sorting question confuses me how can you sort the name of the pet owner and then sort the same with the age? Wouldn't one take precedence over the other and lose the order? Also the entity using it is a great fan of your class::dbi ! – user_falafel Mar 17 '15 at 03:43
  • @user_falafel I see the mistake in your sort call now. You have it basically correct, but the syntax is wrong. I've edited my answer. If the entity is a huge fan, then they'll please honor my request to stop teaching people to use it. It's no longer a useful real world ORM, its no longer maintained, and teaches some bad habits. Case in point, loading the whole table into memory because there is no way to pass in sorting options to retrieve_all. – Schwern Mar 17 '15 at 03:48
  • I figured out a better way to retrieve all rows with an ORDER BY. – Schwern Mar 17 '15 at 04:09
  • I did use the order by ASC on name using an iterator and the next method but they didn't like the answer and wanted me to not use an iterator. So, I decided to use an array , retrieve and store all the rows and then sort the object in ASC and print them. – user_falafel Mar 17 '15 at 05:58
  • @user_falafel You had it right. `retrieve_all` should basically never be used, and iterators used whenever possible. Unless you know you're going to only get a limited data set back, like with a LIMIT clause, you should never fetch all the rows from a database at once. It risks consuming all your memory and leaves you open to a DOS attack. They're teaching you bad practices on an obsolete ORM, I hope you're not paying them much. I'd be interested to see the course materials and critique them. – Schwern Mar 17 '15 at 07:32
  • Agreed, they are using obsolete ORM for production in a teaching / education environment. I FLUNKED this test according to them.Thanks for your feedback! – user_falafel Mar 17 '15 at 09:36