sulfericacid has asked for the wisdom of the Perl Monks concerning the following question:

I need some assistance again. I asked in the CB but it seemed like everyone had a different method of doing this and it seemed a lot more complicated than what could be described in the CB. I am NOT asking for source code, all I want is suggestions or places to look.

I am writing my version of the CB, my first problem is right now the script doesn't push off older messages, it'll post 1000 comments. How can I print only the latest 10 elements of a database? Databases are put together in the order they come in, right? If so, I won't need a timestamp, right?

Problem is I can't delete the older messages because I want to have a past history log of the past 24 hours. What exactly is a timestamp? I know how to find the localtime but I'm thinking a timestamp is something totally different (I already searched the wizard).

Ok, in short I want to know how I would get the latest 10 things from a database to print to the screen without deleting them because I want to have a past history, too.

Any suggestions but no real code would be very helpful. Thank you so much!

What I have so far is the basic system, you post your name and message and it saves to the DB.

#!/usr/bin/perl -w open( STDERR, ">>/home/sulfericacid/public_html/error.log" ) or die "Cannot open error log, weird...an error opening an error log +: $!"; use strict; use warnings; use POSIX; use CGI qw/:standard/; require SDBM_File; my %chat; my $chat = "list.dbm"; my $file = "iplog.txt"; tie %chat, 'SDBM_File', $chat, O_CREAT | O_RDWR, 0644; if ( !tied %chat ) { print "database unsuccessful $!.\n"; } print header, start_html; print "<table>"; foreach ( keys(%chat) ) { print "<tr><td>"; my ( $one, $two ) = split /::/, $chat{$_}; print "<font color=blue>$one:</font> $two"; print "</td></tr>"; } print "</table>"; print start_form(), table( Tr( td("Name: "), td( textfield( -name => 'name', -size => 40 ) ) ), Tr( td("Message: "), td( textfield( -name => 'message', -size => 150 ) ) ), Tr( td(), td(submit) ), ), end_form(), hr(); if ( param() ) { my $name = param('name'); my $message = param('message'); my $cnt; open( LOG, "$file" ); $cnt = <LOG>; close(LOG); $cnt++; open( LOG, "> $file" ); print LOG $cnt; close(LOG); my $info = join ( '::', $name, $message ); $chat{$cnt} = $info; }


"Age is nothing more than an inaccurate number bestowed upon us at birth as just another means for others to judge and classify us"

sulfericacid

Replies are listed 'Best First'.
Re: Retrieve last elements of a DB
by Abigail-II (Bishop) on Jun 24, 2003 at 02:17 UTC
    Uhm, no, in general, databases don't store things in their insertion order. Some implementations of some databases might do so under certain conditions, but any code that relies on this should be considered buggy, even if it sometimes happen to generate the desired output - it might not the next time.

    In general, if you have a database, and you want the data to be returned in a particular order, you must specify which order that is. If you want the "last" row or rows, you should reverse the order, which will reverse the order in which the rows are returned. So, if you want the last 20 lines, reverse the order, and finish your query after receiving 20 rows. These will be the last 20, in reverse order.

    Note that I'm talking about databases in general. Particular database may use insertion order when being queried. But your question was phrased in general terms.

    Abigail

Re: Retrieve last elements of a DB
by VSarkiss (Monsignor) on Jun 24, 2003 at 02:32 UTC

    Databases are put together in the order they come in, right?
    No, they're not. There's no guaranteed order in a relational database table, except what you impose, either with an order by clause in a query, or with a clustered index. But other than that, it's like the FAQ: "Why don't my hash elements come out in the order I inserted them?" Because it's not organized that way. Since you're using an SDBM file, you may be able to get away with it (I'm not sure), but in a RDBMS, you cannot.

    What exactly is a timestamp?
    In principle, a timestamp is an unambiguous, server-generated value that represents a distinct point in time. Not all database platforms support it. Furthermore, the term is frequently (ab)used to mean any column that holds the time of day.

    It looks like you're on the right track, and yes, if you want to do it right, you have to remember when a message got recorded. For a working example, you can see how the Chatterbox works. Go to Everything developer site and get the Emessage 0.9.1 nodeball.

Re: Retrieve last elements of a DB
by dws (Chancellor) on Jun 24, 2003 at 06:57 UTC
    Databases are put together in the order they come in, right? If so, I won't need a timestamp, right?

    The only safe way to retrieve the last N records inserted is to tag each record with a monotonically increasing sequence number that you can query against later. Your code does that (though your method of maintaining the sequence number needs some flock() protection).

    But for doing something like "delete everything older than 24 hours", you'll also need to associate a timestamp with each record. If you were storing your data in a relational table, you'd probably have a column to hold the insert time. But you're using DBM, which complicates things somewhat. You could do something like prepending a timestamp to each value, splitting the timestamp off when necessary. Then, a periodic "delete everything older than 24 hours" scan can work its way through the DBM by sorted key value, splitting off the timestamp from each record and deleting those records that have expired.