From: Dobrica Pavlinusic Date: Sun, 23 Jan 2005 14:31:02 +0000 (+0000) Subject: renamed tag to finger to avoid confusion (I tried to exmplain why I use term X-Git-Url: http://git.rot13.org/?p=webpac;a=commitdiff_plain;h=815b43e56f6d7ddd7d1c2876c86226c6c2b6b369 renamed tag to finger to avoid confusion (I tried to exmplain why I use term tag and failed -- it too similar to tags used in import_xml) git-svn-id: file:///home/dpavlin/private/svn/webpac/trunk@642 13eb9ef6-21d5-0310-b721-a9d68796d827 --- diff --git a/WebPac.pm b/WebPac.pm index d6356a2..5cc5f89 100644 --- a/WebPac.pm +++ b/WebPac.pm @@ -12,7 +12,7 @@ use Text::Unaccent; use Data::Pageset; use lib '..'; -use index_DBI_tag; +use index_DBI_filter; use back2html; diff --git a/all2xml.pl b/all2xml.pl index e0beef7..ee41297 100755 --- a/all2xml.pl +++ b/all2xml.pl @@ -23,7 +23,7 @@ my $config; #use index_DBI; # default DBI module for index #use index_DBI_cache; # faster DBI module using memory cache -use index_DBI_tag; # tag support for indexes +use index_DBI_filter; # filter support for indexes my $index; my %opts; diff --git a/index_DBI_filter.pm b/index_DBI_filter.pm new file mode 100644 index 0000000..5ac3208 --- /dev/null +++ b/index_DBI_filter.pm @@ -0,0 +1,280 @@ +# +# this file implements index functions using DBI +# and huge amounts of memory for cache speedup +# +# this version doesn't support ident (which sould be location in +# library). But, that functionality is not used anyway... +# + +package index_DBI; +use strict qw(vars); +use vars qw($Count); +use HTML::Entities; +use URI::Escape; +use locale; +use Carp; + +use DBI; + +# bench time +my $bench_time = time(); + +my $debug = 1; + +sub bench { + my $self = shift; + my $msg = shift; + + print STDERR "last operation took ",time()-$bench_time," seconds...\n"; + $bench_time=time(); + print STDERR "$msg\n"; +} + +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->{dbd} = $dbd; + + $self->{dbh} = DBI->connect("DBI:$dbd:$dsn",$user,$passwd) || die $DBI::errstr; + $Count++; + + $self->bench("connected to $dbd as $user"); + + # force SQLite to support binary 0 in data (which shouldn't + # happend, but it did to me) + eval { + no warnings 'all'; + $self->{dbh}->{sqlite_handle_binary_nulls} = 1; + }; + + return $self; +} + +sub delete_and_create { + my $self = shift; + + my $index = shift || croak "need index name!"; + my $sql = shift || croak "need sql to create table!"; + + print STDERR "## delete_and_create($index)\n" if ($debug); + + my $sql_delete = "delete from $index"; + my $sth = $self->{dbh}->prepare($sql_delete) || confess "can't prepare: $sql_delete"; + + if ($sth->execute()) { + print STDERR "## deleted rows from table $index\n" if ($debug); + } else { + # can't delete from table, assume it doesn't exists! + $self->{dbh}->rollback; + $self->{dbh}->do($sql) || confess "SQL: $sql ".$self->{dbh}->errstr(); + print STDERR "## creating table $index\n" if ($debug); + $self->{dbh}->begin_work; + } +} + +sub insert { + my $self = shift; + + my $field = shift; + my $index_data = shift || print STDERR "\$index->insert($field,NULL,...)"; + my $display = shift || $index_data; + my $filter = shift; + + if (! $index_data) { + print STDERR "\$index->insert() -- no value to insert\n"; + return; + } + + $index_data =~ s#&(\w)(acute|cedil|circ|grave|ring|slash|tilde|uml);#$1#gi; + + # strip spaces + $index_data =~ s#^\s+##; + $index_data =~ s#\s+$##; + $index_data =~ s#\s\s+# #g; + + my $uc = uc($index_data); + + if (! $self->{c}->{$uc}->{$field}) { +#print stderr "in index: $index_data\n"; + $self->{c}->{$uc}->{$field}->{item} = $index_data; + $self->{c}->{$uc}->{$field}->{display} = $display; + } + + $self->{c}->{$uc}->{$field}->{count}++; + $self->{c}->{$uc}->{$field}->{filter}->{$filter}++ if ($filter); +} + +sub count { + my $self = shift; + + my $field = shift; + my $where = shift; + + my $sql = "select count(*) from index where name = ? and upper(item) like upper(?)||'%'"; + + my $sth = $self->{dbh}->prepare($sql) || die $self->{dbh}->errstr(); + $sth->execute($field,$where) || die "sql: $sql; ".$self->{dbh}->errstr(); + + my ($total) = $sth->fetchrow_array(); + + # no results, count all + if (! $total) { + my $sql = "select count(*) from index wheere name = ?"; + + my $sth = $self->{dbh}->prepare($sql) || die $self->{dbh}->errstr(); + $sth->execute($field) || die "sql: $sql; ".$self->{dbh}->errstr(); + $total = $sth->fetchrow_array(); + + } + + return $total || 1; +} + + +sub fetch { + my $self = shift; + + my $field = shift; + my $where = shift; + + my $offset = shift || 0; + my $rows = shift || 10; + my $from_ord = 0; + + my @sql_args; + + my $sql = qq{ + select item,display,count + from index + where name = ? + and ord > ? + order by ord + limit ? offset ? + }; + + if ($where) { + my $sql2 = "select ord from index where name = ? and upper(item) like upper(?)||'%'"; + my $sth = $self->{dbh}->prepare($sql2) || die "sql2: $sql2; ".$self->{dbh}->errstr(); + + $sth->execute($field, $where) || die "sql2: $sql2; ".$self->{dbh}->errstr(); + if (my $row = $sth->fetchrow_hashref) { + $from_ord += $row->{ord} - 1; + } else { + # if no match is found when searching from beginning + # of word in index, try substring match anywhere + $sql2 = "select ord from index where name = ? and upper(item) like '% '||upper(?)||'%'"; + $sth = $self->{dbh}->prepare($sql2) || die "sql2: $sql2; ".$self->{dbh}->errstr(); + $sth->execute($field, $where) || die "sql2: $sql2; ".$self->{dbh}->errstr(); + if (my $row = $sth->fetchrow_hashref) { + $from_ord += $row->{ord} - 1; + } + } + } + + my $sth = $self->{dbh}->prepare($sql) || die "prepare: $sql; ".$self->{dbh}->errstr(); + $sth->execute($field,$from_ord,$rows,$offset) || die "execute: $sql; ".$self->{dbh}->errstr(); + my @arr; + while (my $row = $sth->fetchrow_hashref) { + $row->{item} = HTML::Entities::encode($row->{item},' <>&"'); + $row->{display} = HTML::Entities::encode($row->{display},'<>&"'); + $row->{item} =~ s#&(\w)(acute|cedil|circ|grave|ring|slash|tilde|uml);#$1#gi; + $row->{display} =~ s#&(\w)(acute|cedil|circ|grave|ring|slash|tilde|uml);#&$1$2;#gi; + push @arr,$row; + } + return @arr; +} + +sub close { + my $self = shift; + + return if (! $self->{dbh}); + + $self->{dbh}->begin_work || die $self->{dbh}->errstr(); + + $self->delete_and_create('index', qq{ + create table index ( + name varchar(255), + ord int, + item text, + display text, + count int, + primary key (name,ord) + ); + }); + + $self->delete_and_create('filters', qq{ + create table filters ( + filter varchar(255), + ord int, + count int, + primary key (filter,ord) + ); + }); + + $self->bench("getting all entries"); + my @items = keys %{$self->{c}}; + $self->bench("got ".($#items+1)." items, now sorting"); + @items = sort @items; + + my $sql = "insert into index (name,ord,item,display,count) values (?,?,?,?,?)"; + my $sth_index = $self->{dbh}->prepare($sql) || confess "$sql: ".$self->{dbh}->errstr(); + + $sql = "insert into filters (filter, ord, count) values (?,?,?)"; + my $sth_filter = $self->{dbh}->prepare($sql) || confess "$sql: ".$self->{dbh}->errstr(); + + my $ord = 0; + foreach my $key (@items) { + + foreach my $field (keys %{$self->{c}->{$key}}) { + # store items + $sth_index->execute( + $field, + ++$ord, + $self->{c}->{$key}->{$field}->{item}, + $self->{c}->{$key}->{$field}->{display}, + $self->{c}->{$key}->{$field}->{count}, + ); + + # store filters + next unless ($self->{c}->{$key}->{$field}->{filter}); + + foreach my $filter (keys %{$self->{c}->{$key}->{$field}->{filter}}) { + $sth_filter->execute( $filter, $ord, $self->{c}->{$key}->{$field}->{filter}->{$filter} ); + } + } + + + } + + $self->{dbh}->commit || die $self->{dbh}->errstr(); + + $self->bench("vacuuming"); + + if ($self->{dbd} =~ m/(Pg|SQLite)/) { + $self->{dbh}->do(qq{vacuum}) || carp "vacumming failed. It shouldn't if you are using PostgreSQL or SQLite: ".$self->{dbh}->errstr(); + } + + $self->bench("disconnecting from database"); + + $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; diff --git a/index_DBI_tag.pm b/index_DBI_tag.pm deleted file mode 100644 index 0220b71..0000000 --- a/index_DBI_tag.pm +++ /dev/null @@ -1,278 +0,0 @@ -# -# this file implements index functions using DBI -# and huge amounts of memory for cache speedup -# -# this version doesn't support ident (which sould be location in -# library). But, that functionality is not used anyway... -# - -package index_DBI; -use strict qw(vars); -use vars qw($Count); -use HTML::Entities; -use URI::Escape; -use locale; -use Carp; - -use DBI; - -# bench time -my $bench_time = time(); - -my $debug = 1; - -sub bench { - my $self = shift; - my $msg = shift; - - print STDERR "last operation took ",time()-$bench_time," seconds...\n"; - $bench_time=time(); - print STDERR "$msg\n"; -} - -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->{dbd} = $dbd; - - $self->{dbh} = DBI->connect("DBI:$dbd:$dsn",$user,$passwd) || die $DBI::errstr; - $Count++; - - $self->bench("connected to $dbd as $user"); - - # force SQLite to support binary 0 in data (which shouldn't - # happend, but it did to me) - eval { - no warnings 'all'; - $self->{dbh}->{sqlite_handle_binary_nulls} = 1; - }; - - return $self; -} - -sub delete_and_create { - my $self = shift; - - my $index = shift || croak "need index name!"; - my $sql = shift || croak "need sql to create table!"; - - print STDERR "## delete_and_create($index)\n" if ($debug); - - my $sql_delete = "delete from $index"; - my $sth = $self->{dbh}->prepare($sql_delete) || confess "can't prepare: $sql_delete"; - - unless ($sth->execute()) { - # can't delete from table, assume it doesn't exists! - $self->{dbh}->rollback; - $self->{dbh}->do($sql) || confess "SQL: $sql ".$self->{dbh}->errstr(); - print STDERR "## creating table $index\n" if ($debug); - $self->{dbh}->begin_work; - } -} - -sub insert { - my $self = shift; - - my $field = shift; - my $index_data = shift || print STDERR "\$index->insert($field,NULL,...)"; - my $display = shift || $index_data; - my $tag = shift; - - if (! $index_data) { - print STDERR "\$index->insert() -- no value to insert\n"; - return; - } - - $index_data =~ s#&(\w)(acute|cedil|circ|grave|ring|slash|tilde|uml);#$1#gi; - - # strip spaces - $index_data =~ s#^\s+##; - $index_data =~ s#\s+$##; - $index_data =~ s#\s\s+# #g; - - my $uc = uc($index_data); - - if (! $self->{c}->{$uc}->{$field}) { -#print stderr "in index: $index_data\n"; - $self->{c}->{$uc}->{$field}->{item} = $index_data; - $self->{c}->{$uc}->{$field}->{display} = $display; - } - - $self->{c}->{$uc}->{$field}->{count}++; - $self->{c}->{$uc}->{$field}->{tag}->{$tag}++ if ($tag); -} - -sub count { - my $self = shift; - - my $field = shift; - my $where = shift; - - my $sql = "select count(*) from index where name = ? and upper(item) like upper(?)||'%'"; - - my $sth = $self->{dbh}->prepare($sql) || die $self->{dbh}->errstr(); - $sth->execute($field,$where) || die "sql: $sql; ".$self->{dbh}->errstr(); - - my ($total) = $sth->fetchrow_array(); - - # no results, count all - if (! $total) { - my $sql = "select count(*) from index wheere name = ?"; - - my $sth = $self->{dbh}->prepare($sql) || die $self->{dbh}->errstr(); - $sth->execute($field) || die "sql: $sql; ".$self->{dbh}->errstr(); - $total = $sth->fetchrow_array(); - - } - - return $total || 1; -} - - -sub fetch { - my $self = shift; - - my $field = shift; - my $where = shift; - - my $offset = shift || 0; - my $rows = shift || 10; - my $from_ord = 0; - - my @sql_args; - - my $sql = qq{ - select item,display,count - from index - where name = ? - and ord > ? - order by ord - limit ? offset ? - }; - - if ($where) { - my $sql2 = "select ord from index where name = ? and upper(item) like upper(?)||'%'"; - my $sth = $self->{dbh}->prepare($sql2) || die "sql2: $sql2; ".$self->{dbh}->errstr(); - - $sth->execute($field, $where) || die "sql2: $sql2; ".$self->{dbh}->errstr(); - if (my $row = $sth->fetchrow_hashref) { - $from_ord += $row->{ord} - 1; - } else { - # if no match is found when searching from beginning - # of word in index, try substring match anywhere - $sql2 = "select ord from index where name = ? and upper(item) like '% '||upper(?)||'%'"; - $sth = $self->{dbh}->prepare($sql2) || die "sql2: $sql2; ".$self->{dbh}->errstr(); - $sth->execute($field, $where) || die "sql2: $sql2; ".$self->{dbh}->errstr(); - if (my $row = $sth->fetchrow_hashref) { - $from_ord += $row->{ord} - 1; - } - } - } - - my $sth = $self->{dbh}->prepare($sql) || die "prepare: $sql; ".$self->{dbh}->errstr(); - $sth->execute($field,$from_ord,$rows,$offset) || die "execute: $sql; ".$self->{dbh}->errstr(); - my @arr; - while (my $row = $sth->fetchrow_hashref) { - $row->{item} = HTML::Entities::encode($row->{item},' <>&"'); - $row->{display} = HTML::Entities::encode($row->{display},'<>&"'); - $row->{item} =~ s#&(\w)(acute|cedil|circ|grave|ring|slash|tilde|uml);#$1#gi; - $row->{display} =~ s#&(\w)(acute|cedil|circ|grave|ring|slash|tilde|uml);#&$1$2;#gi; - push @arr,$row; - } - return @arr; -} - -sub close { - my $self = shift; - - return if (! $self->{dbh}); - - $self->{dbh}->begin_work || die $self->{dbh}->errstr(); - - $self->delete_and_create('index', qq{ - create table index ( - name varchar(255), - ord int, - item text, - display text, - count int, - primary key (name,ord) - ); - }); - - $self->delete_and_create('tags', qq{ - create table tags ( - tag varchar(255), - ord int, - count int, - primary key (tag,ord) - ); - }); - - $self->bench("getting all entries"); - my @items = keys %{$self->{c}}; - $self->bench("got ".($#items+1)." items, now sorting"); - @items = sort @items; - - my $sql = "insert into index (name,ord,item,display,count) values (?,?,?,?,?)"; - my $sth_index = $self->{dbh}->prepare($sql) || confess "$sql: ".$self->{dbh}->errstr(); - - $sql = "insert into tags (tag, ord, count) values (?,?,?)"; - my $sth_tag = $self->{dbh}->prepare($sql) || confess "$sql: ".$self->{dbh}->errstr(); - - my $ord = 0; - foreach my $key (@items) { - - foreach my $field (keys %{$self->{c}->{$key}}) { - # store items - $sth_index->execute( - $field, - ++$ord, - $self->{c}->{$key}->{$field}->{item}, - $self->{c}->{$key}->{$field}->{display}, - $self->{c}->{$key}->{$field}->{count}, - ); - - # store tags - next unless ($self->{c}->{$key}->{$field}->{tag}); - - foreach my $tag (keys %{$self->{c}->{$key}->{$field}->{tag}}) { - $sth_tag->execute( $tag, $ord, $self->{c}->{$key}->{$field}->{tag}->{$tag} ); - } - } - - - } - - $self->{dbh}->commit || die $self->{dbh}->errstr(); - - $self->bench("vacuuming"); - - if ($self->{dbd} =~ m/(Pg|SQLite)/) { - $self->{dbh}->do(qq{vacuum}) || carp "vacumming failed. It shouldn't if you are using PostgreSQL or SQLite: ".$self->{dbh}->errstr(); - } - - $self->bench("disconnecting from database"); - - $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;