ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/dinfo/dinfo.pm
Revision: 1.5
Committed: Fri Aug 29 14:15:59 2003 UTC (23 years, 1 month ago) by root
Branch: MAIN
Changes since 1.4: +74 -10 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 package dinfo;
2    
3     use Carp;
4 root 1.3 use PApp::SQL;
5 root 1.1
6 root 1.5 =head1 dinfo - THIS IS A PRIVATE MODULE, DON't COPY
7    
8     =cut
9    
10     BEGIN {
11     $VERSION = 0.1;
12     require XSLoader;
13     XSLoader::load __PACKAGE__, $VERSION;
14     }
15 root 1.1
16     sub new {
17     my ($class, $dsn, $user, $pass) = @_;
18    
19     my $self = bless {
20     dbh => (PApp::SQL::connect_cached "dinfo::", $dsn, $user, $pass),
21     }, $class;
22    
23     $self;
24 root 1.3 }
25    
26     =item $result = $dinfo->search (column => type => value, ...)
27    
28     Initiate a search on the given columns. C<type> can be one of C<exact>,
29     C<prefix>, C<like>, C<regexp> or C<match>, which specifies the sql-search
30     mode used. For C<nummer>-columns, only C<exact> and C<prefix> are
31     supported.
32    
33     Returns a C<dinfo::result> object.
34    
35     my $r = $dinfo->search(name => like => "Marc%");
36    
37     my $r = $dinfo->search(plz => exact => 76139, branche => match => "psychologe");
38    
39     Not all types are efficient on all columns.. check your indices! :)
40    
41     =cut
42    
43     my @cols = (
44     [ 1 => "name"],
45     [ 2 => "vorname"],
46     [ 3 => "zusatz1"],
47     [ 4 => "zusatz2"],
48     [ 5 => "zusatz3"],
49     [ 6 => "vorwahl"],
50     [ 7 => "strasse"],
51     [ 8 => "haus"],
52     [ 9 => "plz"],
53     [10 => "ort"],
54     [11 => "branche"],
55     );
56    
57     sub search {
58     my ($self, @pred) = @_;
59    
60     my @args;
61     my $select = "select\n nummer, " . (join ", ", map "$_->[1].data", @cols) . "\n"
62     . "from row\n". (join "", map " inner join $_->[1] on (row.$_->[1] = $_->[1].id)\n", @cols)
63     . "where (1=1)\n";
64    
65     while (@pred) {
66     my ($column, $type, $match) = splice @pred, 0, 3, ();
67     $select .= " and ";
68     if ($column eq "nummer") {
69     $select .= "($column between ? and ?)";
70     if ($type eq "exact") {
71     push @args,
72     (pack "H*", (substr "${match}000000000000", 0, 12) . sprintf "%x0", 12 - length $match),
73     (pack "H*", (substr "${match}000000000000", 0, 12) . sprintf "%xf", 12 - length $match);
74     } elsif ($type eq "prefix") {
75     push @args,
76     (pack "H*", (substr "${match}00000000000000", 0, 14)),
77     (pack "H*", (substr "${match}a0000000000000", 0, 14));
78     } else {
79     croak "illegal search type '$type', must be one of exact, prefix";
80     }
81     } else {
82     push @args, $match;
83     if ($type eq "exact") {
84     $select .= "($column.data = ?)";
85     } elsif ($type eq "like") {
86     $select .= "($column.data like ?)";
87     } elsif ($type eq "prefix") {
88     $select .= "($column.data like ?)";
89     $args[-1] .= "%";
90     } elsif ($type eq "regexp") {
91     $select .= "($column.data regexp ?)";
92     } elsif ($type eq "match") {
93     $select .= "(match $column.data against (?)";
94     } else {
95     croak "illegal search type '$type', must be one of exact, like, regexp or match";
96     }
97     }
98     }
99    
100 root 1.5 my $st = sql_exec $self->{dbh}, $select, @args
101     or die "sql_exec returned no statement handle";
102    
103     return bless {
104     dinfo => $self,
105     st => $st,
106     }, dinfo::result;
107     }
108    
109     =item my ($prefix, $local) = $dinfo->split_number($number)
110    
111     split a number into prefix and local part.
112    
113     =cut
114    
115     sub split_number {
116     my ($self, $number) = @_;
117    
118     for ($number) {
119     s/^/0/ unless /^0/;
120    
121     for (3..6) {
122     my $prefix = substr $number, 0, $_;
123     my $isprefix =
124     $cache{$prefix}
125     ||= sql_fetch $self->{dbh},
126     "select 1 + count(*) from vorwahl where data = ?",
127     $prefix;
128     return ($prefix, substr $number, $_)
129     if $isprefix == 2;
130     }
131 root 1.3
132     return ();
133     }
134 root 1.5 }
135    
136     =item my $hash = $dinfo->identify_number ($number)
137    
138     Try to find out as much as possible about the given number.
139    
140     =cut
141    
142     sub identify_number {
143     my ($self, $number) = @_;
144     my %r;
145     my ($prefix, $number) = $self->split_number ($number);
146    
147     if ($prefix) {
148     $r{vorwahl} = $prefix;
149    
150     while (1 < length $number) {
151     for ($number, "${number}0") {
152     my $result = $self->search (vorwahl => exact => $prefix,
153     nummer => exact => $_);
154     if ($result->rows > 1) {
155     return $result->fetch;
156     } elsif ($result->rows == 1) {
157     return $result->fetch;
158     }
159     }
160    
161     substr $number, -1, 1, "";
162     }
163     }
164    
165     #my @orte = sql_fetchall $self->{dbh},
166    
167     \%r;
168 root 1.3 }
169    
170     =head2 dinfo::result
171    
172     =item $count = $result->rows
173    
174     =cut
175    
176     sub dinfo::result::rows {
177     $_[0]{st}->rows;
178     }
179    
180     =item $hash = $result->fetch
181    
182     Fetch and return the next result row.
183    
184     =cut
185    
186     my %typ;
187    
188     sub dinfo::result::fetch {
189     my ($self) = @_;
190    
191     my $row = $self->{st}->fetchrow_arrayref;
192    
193     if ($row) {
194     my %r;
195    
196     $r{$_->[1]} = $row->[$_->[0]] for @cols;
197    
198     my $nummer = unpack "H*", $row->[0];
199    
200     my $len = hex substr $nummer, -2, 1;
201     my $typ = hex substr $nummer, -1, 1;
202    
203     $r{nummer} = substr $nummer, 0, 12 - $len;
204     $r{typ} = $typ{$typ}
205     ||= sql_fetch $self->{dinfo}{dbh},
206     "select data from typ where id = ?",
207     $typ;
208    
209     \%r;
210     } else {
211     return ();
212     }
213 root 1.1 }
214    
215 root 1.2 1;