Re: LIMIT clause in Class::DBI
by jeffa (Bishop) on Feb 17, 2004 at 16:34 UTC
|
I think you hit Class::DBI's major weakness. :(
Personally, i love Class::DBI, but when it comes to doing this stuff "professionally", i just stick with plain old DBI and selectall_arrayref or selectcol_arrayref and specify the optional Slice parameter. Observe:
my $sth = $dbh->selectall_arrayref('
select id,title,year from movie limit 2
',{Slice => {}});
print Dumper $sth;
__END__
$VAR1 = [
{
'title' => 'Alien',
'year' => '1979',
'id' => '78748'
},
{
'title' => 'Aliens',
'year' => '1986',
'id' => '90605'
}
];
Now you send $sth straight to an HTML::Template or TT template.
If you are wanting to further separate your SQL from your Perl, look into
Class::Phrasebook::SQL
UPDATE: yup, i shoulda named it $movies
| [reply] [d/l] |
|
|
Just a nitpick, but $sth is practically a reserved word when writing DBI apps. I'd call it something else, like $results.
| [reply] |
Re: LIMIT clause in Class::DBI
by freddo411 (Chaplain) on Feb 17, 2004 at 18:11 UTC
|
use Data::Page;
my $total_rows = $table->get_count_sql($sql_where_clause);
#
my $pager = Data::Page->new($total_rows,
$G::CF{rows_per_page},
$current_page_num);
# Now get only the needed chunk from the DB
my @results = $table->get_range_sql($sql_where_clause,
$pager->first,
$pager->last);
The supporting functions added to Class::DBI are on my scratchpad
The interesting bit was getting the SQL that would work with Oracle to provide a "limit" or an "offset" like MySQL. This ends up being ridiculously complicated:
Select
*
From (
SELECT
%s
,rownum R
FROM
(SELECT *
FROM %s
%s
)
)
WHERE R BETWEEN %s AND %s
Update:
Note that you need to be very careful about what you pass into the where clause. This code will allow bad things to happen if a tainted where clause is passed in.
-------------------------------------
Nothing is too wonderful to be true
-- Michael Faraday
| [reply] [d/l] [select] |
Re: LIMIT clause in Class::DBI
by larsen (Parson) on Feb 17, 2004 at 16:37 UTC
|
I've found Class::DBI::Extension on CPAN that should have what you're looking for. By the way, beware the Description:
THIS RELEASE IS FOR TEMPORARY DEVELOPMENT. Hope this will eventually be merged into Class::DBI and/or Class::DBI::mysql.
FWIW, I think it should be included in Class::DBI::mysql, or in Class::DBI provided some general implementation of the LIMIT idiom. | [reply] |
|
|
Regrettably, the code notes that it the SQL it implements is specific to MySQL. In Oracle, for example, you use a "where rownum < ?" to limit results. Thus the code is not terribly portable (yet). It would be nice to see that added.
| [reply] |
Re: LIMIT clause in Class::DBI
by cees (Curate) on Feb 17, 2004 at 18:01 UTC
|
It might be worthwhile having a look at Class::DBI::Pager. It handles this sort of thing for you, although I have a feeling that it doesn't use LIMITs on the select statements. So if your queries really are massive, it won't solve the problem you are facing. It does however simplify getting ranges of data when using Class::DBI.
- Cees
| [reply] |
Re: LIMIT clause in Class::DBI
by perrin (Chancellor) on Feb 17, 2004 at 20:26 UTC
|
I don't consider SQL generation to be the biggest benefit of Class::DBI. Mostly I just like having all of the drudgery of moving stuff between objects and the database handled for me. However, if you want this and you don't want to code the SQL yourself, it's pretty easy to subclass it and add this. Just take a look at the code. Also, search the Class::DBI mailing list because others have done this before. | [reply] |
|
|
I don't quite understand what you mean by "moving stuff between objects and the database" - I thought this requires generating an "UPDATE" SQL sentence.
| [reply] |
|
|
That is what I'm talking about -- selecting things from the database, doing all the DBI busywork, moving it into objects, providing accessors on those objects, tracking if I change anything, saving it back to the database if I have, doing lazy-loading of groups of data, iterating over lists of primary keys and inflating them to objects if I try to use them, having a centralized place to do validation before saves, having a centralized place to do caching, etc. All of these things are done for me by Class::DBI. If I had to write every line of SQL, it would still be valuable to me.
| [reply] |
Re: LIMIT clause in Class::DBI
by jdtoronto (Prior) on Feb 17, 2004 at 19:36 UTC
|
There is another alternative, you can use the underlying relationship between Class::DBI and Ima::DBI. As the docs for Class::DBI say:
For more complex queries you need to fall back on the underlying Ima::DBI query mechanism.
There is an example given of a query, using the MySQL 'LIMIT' function:
Music::Artist->set_sql(most_cds => qq{
SELECT artist.id, COUNT(cd.id) AS cds
FROM artist, cd
WHERE artist.id = cd.artist
GROUP BY artist.id
ORDER BY cds DESC
LIMIT 10
});
my @artists = Music::Artist->search_most_cds();
jdtoronto | [reply] [d/l] |