From: Dobrica Pavlinusic Date: Fri, 4 Jul 2003 18:23:00 +0000 (+0000) Subject: uses memory as cache X-Git-Url: http://git.rot13.org/?p=webpac;a=commitdiff_plain;h=5b1f4ecfdae5de328c3b9bb961f119b64df19a0b uses memory as cache git-svn-id: file:///home/dpavlin/private/svn/webpac/trunk@60 13eb9ef6-21d5-0310-b721-a9d68796d827 --- diff --git a/index_DBI_cache.pm b/index_DBI_cache.pm new file mode 100644 index 0000000..9613f61 --- /dev/null +++ b/index_DBI_cache.pm @@ -0,0 +1,218 @@ +# +# this file implements index functions using DBI +# and huge amounts of memory for cache speedup +# + +package index_DBI; +use strict qw(vars); +use vars qw($Count); +use HTML::Entities; + +use DBI; + +my %Table; # index tables which where visited in this run +my %sth_cache; # cache prepared statements + +# cache var +my $c_table; +my $c_count; + +sub new { + my $class = shift; + my $self = {}; + bless($self, $class); + + my $dbd = shift || die "need dbi_dbd= in [global] section of configuration file"; + my $dsn = shift || die "need dbi_dsn= in [global] section of configuration file"; + my $user = shift || die "need dbi_user= in [global] section of configuration file"; + my $passwd = shift || die "need dbi_passwd= in [global] section of configuration file"; + + $self->{dbh} = DBI->connect("DBI:$dbd:$dsn",$user,$passwd) || die $DBI::errstr; + # begin transaction + $self->{dbh}->begin_work || die $self->{dbh}->errstr(); + + $Count++; + + return $self; +} + +sub delete_and_create { + my $self = shift; + + my $field = shift; + +#print "#### delete_and_create($field)\n"; + + $self->{dbh}->commit; + + my $sql = "select count(*) from $field"; + my $sth = $self->{dbh}->prepare($sql) || die $self->{dbh}->errstr(); +# FIX: this is not a good way to check if table exists! + if ($sth->execute() && $sth->fetchrow_hashref) { + my $sql = "drop table $field"; + $self->{dbh}->begin_work; + my $sth = $self->{dbh}->do($sql) || die "SQL: $sql ".$self->{dbh}->errstr(); + $self->{dbh}->commit; + } + $sql = "create table $field ( + item varchar(255), + ident varchar(255), + count int, + ord int, + primary key (item,ident) + )"; + + $self->{dbh}->begin_work; + $sth = $self->{dbh}->do($sql); # || warn "SQL: $sql ".$self->{dbh}->errstr(); + $self->{dbh}->commit; + + $self->{dbh}->begin_work; +} + +sub insert { + my $self = shift; + + my $field = shift; + my $index_data = shift || print STDERR "\$index->insert($field,NULL,...)"; + my $ident = shift || ''; # e.g. library id + + if (! $index_data) { + print STDERR "\$index->insert() -- no value to insert\n"; + return; + } + + if (! $Table{$field}) { + $self->delete_and_create($field); + + my $sql = "select item from $field where upper(item)=upper(?)"; + $sth_cache{$field."select"} = $self->{dbh}->prepare($sql) || die $self->{dbh}->errstr(); + + $sql = "insert into $field (item,ident,count) values (?,?,?)"; + $sth_cache{$field."insert"} = $self->{dbh}->prepare($sql) || die $self->{dbh}->errstr(); + + $sql = "update $field set count = count + 1 where item = ? and ident = ?"; + $sth_cache{$field."update"} = $self->{dbh}->prepare($sql) || die $self->{dbh}->errstr(); + } + $Table{$field}++; + + #$sth_cache{$field."select"}->execute($index_data) || die "cache: $field select; ".$self->{dbh}->errstr(); + $index_data = substr($index_data,0,255); + my $uc = uc($index_data); + if (! $c_table->{$field}->{$ident}->{$uc}) { + $sth_cache{$field."insert"}->execute($index_data,$ident,0) || die "cache: $field insert; ".$self->{dbh}->errstr(); +#print stderr "in index: $index_data\n"; + $c_table->{$field}->{$ident}->{$uc} = $index_data; + $c_count->{$field}->{$ident}->{$uc} = 1; + } else { + $c_count->{$field}->{$ident}->{$uc}++; + } +} + +sub check { + my $self = shift; + + my $field = shift; + + my $sql = "select count(*) from $field"; + + my $sth = $self->{dbh}->prepare($sql) || die $self->{dbh}->errstr(); + $sth->execute() || die "sql: $sql; ".$self->{dbh}->errstr(); + + my ($total) = $sth->fetchrow_array(); + + return $total; +} + + +sub fetch { + my $self = shift; + + my $field = shift; + my $what = shift || 'item'; # 'item,ident' + my $where = shift; + + my $from_ord = shift || 0; + my $rows = shift || 10; + + my @sql_args; + + my $sql = "select $what,ord from $field"; + + if ($where) { + my $sql2 = " select ord from $field where upper($what) like upper(?)||'%'"; + my $sth = $self->{dbh}->prepare($sql2) || die "sql2: $sql2; ".$self->{dbh}->errstr(); + + $sth->execute($where) || die "sql2: $sql2; ".$self->{dbh}->errstr(); + if (my $row = $sth->fetchrow_hashref) { + $from_ord += $row->{ord} - 1; + } + } + $sql .= " order by ord limit $rows offset $from_ord"; + + my $sth = $self->{dbh}->prepare($sql) || die "prepare: $sql; ".$self->{dbh}->errstr(); + $sth->execute() || die "execute: $sql; ".$self->{dbh}->errstr(); + my @arr; + while (my $row = $sth->fetchrow_hashref) { + $row->{item} = HTML::Entities::encode($row->{item},'<>&"'); + push @arr,$row; + } + return @arr; +} + +sub close { + my $self = shift; + + + # re-create ord column (sorted order) in table + sub create_ord { + + my $table = shift; + + $self->{dbh}->begin_work || die $self->{dbh}->errstr(); + + my $sql = "select oid from $table order by upper(item)"; + my $sth = $self->{dbh}->prepare($sql) || die "sql: $sql; ".$self->{dbh}->errstr(); + $sql = "update $table set ord=? where oid=?"; + my $sth_update = $self->{dbh}->prepare($sql) || die "sql: $sql; ".$self->{dbh}->errstr(); + $sth->execute() || die "sql: $sql; ".$self->{dbh}->errstr(); + my $ord = 1; + while (my $row = $sth->fetchrow_hashref) { + $sth_update->execute($ord++,$row->{oid}); + } + + $self->{dbh}->commit || die $self->{dbh}->errstr(); + } + #--- end of sub + + if ($self->{dbh}) { + + # commit + $self->{dbh}->commit || die $self->{dbh}->errstr(); + + foreach my $table (keys %Table) { +# FIX +print STDERR "creating ord for $table...\n"; + create_ord($table); + undef $sth_cache{$table."select"}; + undef $sth_cache{$table."insert"}; + undef $sth_cache{$table."update"}; +# XXX +# $sth_cache{$field."update"}->execute($index_data,$ident) || die "cache: $field update; ".$self->{dbh}->errstr(); + } + + $self->{dbh}->disconnect; + undef $self->{dbh}; + } +} + +END { + $Count--; + print STDERR "index_DBI fatal error: \$index->close() not called... $Count references left!\n" if ($Count > 0); + # FIX: debug output +# print STDERR "usage\ttable\n"; +# foreach (keys %Table) { +# print STDERR $Table{$_},"\t$_\n"; +# } +} + +1;