ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/PApp-SQL/SQL.pm
Revision: 1.4
Committed: Sun Nov 26 21:04:22 2000 UTC (23 years, 5 months ago) by root
Branch: MAIN
Changes since 1.3: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 =head1 NAME
2
3 PApp::SQL - absolutely easy yet fast and powerful sql access
4
5 =head1 SYNOPSIS
6
7 use PApp::SQL;
8 # to be written
9
10 =head1 DESCRIPTION
11
12 This module provides you with easy-to-use functions to execute sql
13 commands (using DBI). Despite being easy to use, they are also quite
14 efficient and allow you to write faster programs in less lines of code.
15
16 =over 4
17
18 =cut
19
20 package PApp::SQL;
21
22 use DBI;
23
24 #use PApp::Exception; # not yet used
25
26 BEGIN {
27 use base Exporter;
28
29 $VERSION = 0.11;
30 @EXPORT = qw(
31 sql_exec sql_fetch sql_fetchall sql_exists sql_insertid $sql_exec
32 );
33 @EXPORT_OK = qw(
34 connect_cached
35 );
36
37 require XSLoader;
38 XSLoader::load PApp::SQL, $VERSION;
39 }
40
41 our $sql_exec; # last result of sql_exec's execute call
42 our $DBH; # the default database handle
43 our $database; # the current SQL::Database object, if applicable
44
45 our %dbcache;
46
47 =item $dbh = connect_cached $id, $dsn, $user, $pass, $flags, $connect
48
49 (not exported by by default)
50
51 Connect to the database given by C<($dsn,$user,$pass)>, while using the
52 flags from C<$flags>. These are just the same arguments as given to
53 C<DBI->connect>.
54
55 The database handle will be cached under the unique id C<$id>. If the same
56 id is requested later, the cached handle will be checked (using ping), and
57 the connection will be re-established if necessary (be sure to prefix your
58 application or module name to the id to make it "more" unique. Things like
59 __PACKAGE__ . __LINE__ work fine as well).
60
61 If specified, C<$connect> is a callback (e.g. a coderef) that will be
62 called each time a new connection is being established, with the new
63 C<$dbh> as first argument.
64
65 Examples:
66
67 # try your luck opening the papp database without access info
68 $dbh = connect_cached __FILE__, "DBI:mysql:papp";
69
70 =cut
71
72 sub connect_cached {
73 my ($id, $dsn, $user, $pass, $flags, $connect) = @_;
74 # the following line is duplicated in PApp::SQL::Database::new
75 $id = "$id\0$dsn\0$user\0$pass";
76 unless ($dbcache{$id} && $dbcache{$id}->ping) {
77 #warn "connecting to ($dsn|$user|$pass|$flags)\n";#d#
78 # first, nuke our cache (sooory ;)
79 cachesize cachesize 0;
80 # then connect anew
81 $dbcache{$id} =
82 eval { DBI->connect($dsn, $user, $pass, $flags) }
83 || eval { DBI->connect($dsn, $user, $pass, $flags) }
84 || die "$DBI::errstr\n";
85 $connect->($dbcache{$id}) if $connect;
86 }
87 $dbcache{$id};
88 }
89
90 =item $sth = sql_exec [dbh,] [bind-vals...,] "sql-statement", [arguments...]
91
92 C<sql_exec> is the most important and most-used function in this module.
93
94 Runs the given sql command with the given parameters and returns the
95 statement handle. The command and the statement handle will be cached
96 (with the database handle and the sql string as key), so prepare will be
97 called only once for each distinct sql call (please keep in mind that the
98 returned statement will always be the same, so, if you call C<sql_exec>
99 with the same dbh and sql-statement twice (e.g. in a subroutine you
100 called), the statement handle for the first call mustn't be used.
101
102 The database handle (the first argument) is optional. If it is missing,
103 C<sql_exec> first tries to use the variable C<$DBH> in the current (=
104 calling) package and, if that fails, it tries to use database handle in
105 C<$PApp::SQL::DBH>, which you can set before calling these functions.
106
107 The actual return value from the C<$sth->execute> call is stored in the
108 package-global (and exported) variable C<$sql_exec>.
109
110 If any error occurs C<sql_exec> will throw an exception.
111
112 Examples:
113
114 # easy one
115 my $st = sql_exec "select name, id from table where id = ?", $id;
116 while (my ($name, $id) = $st->fetchrow_array) { ... };
117
118 # the fastest way to use dbi, using bind_columns
119 my $st = sql_exec \my($name, $id),
120 "select name, id from table where id = ?",
121 $id;
122 while ($st->fetch) { ...}
123
124 # now use a different dastabase:
125 sql_exec $dbh, "update file set name = ?", "oops.txt";
126
127
128 =item sql_fetch <see sql_exec>
129
130 Execute a sql-statement and fetch the first row of results. Depending on
131 the caller context the row will be returned as a list (array context), or
132 just the first columns. In table form:
133
134 CONTEXT RESULT
135 void ()
136 scalar first column
137 list array
138
139 C<sql_fetch> is quite efficient in conjunction with bind variables:
140
141 sql_fetch \my($name, $amount),
142 "select name, amount from table where id name = ?",
143 "Toytest";
144
145 But of course the normal way to call it is simply:
146
147 my($name, $amount) = sql_fetch "select ...", args...
148
149 ... and it's still quite fast unless you fetch large amounts of data.
150
151 =item sql_fetchall <see sql_exec>
152
153 Similarly to C<sql_fetch>, but all result rows will be fetched (this is
154 of course inefficient for large results!). The context is ignored (only
155 list context makes sense), but the result still depends on the number of
156 columns in the result:
157
158 COLUMNS RESULT
159 0 ()
160 1 (row1, row2, row3...)
161 many ([row1], [row2], [row3]...)
162
163 Examples (all of which are inefficient):
164
165 for (sql_fetchall "select id from table") { ... }
166
167 my @names = sql_fetchall "select name from user";
168
169 for (sql_fetchall "select name, age, place from user") {
170 my ($name, $age, $place) = @$_;
171 }
172
173 =item sql_exists "<table> where ...", args...
174
175 Check wether the result of the sql-statement "select xxx from
176 $first_argument" would be empty or not (that is, imagine the string
177 "select from" were prepended to your statement (it isn't)). Should work
178 with every database but can be quite slow, except on mysql, where this
179 should be quite fast.
180
181 Examples:
182
183 print "user 7 exists!\n"
184 if sql_exists "user where id = ?", 7;
185
186 die "duplicate key"
187 if sql_exists "user where name = ? and pass = ?", "stefan", "geheim";
188
189 =cut
190
191 =item $lastid = sql_insertid $sth
192
193 Returns the last automatically created key value (e.g. for mysql
194 AUTO_INCREMENT or sybase IDENTITY fields). It must be executed directly
195 after executing the insert statement that created it.
196
197 =cut
198
199 sub sql_insertid($) {
200 my $sth = shift or die "sql_insertid requires a statement handle";
201 my $dbh = $sth->{Database};
202 my $driver = $dbh->{Driver}{Name};
203
204 $driver eq "mysql" and return $sth->{mysql_insertid};
205 $driver eq "Sybase" and return sql_fetch($dbh, 'SELECT @@IDENTITY');
206 $driver eq "Informix" and return $sth->{ix_sqlerrd}[1];
207
208 die "sql_insertid does not spport the dbd driver '$driver', please see PApp::SQL::sql_insertid";
209 }
210
211 =item [old-size] = cachesize [new-size]
212
213 Returns (and possibly changes) the LRU cache size used by C<sql_exec>. The
214 default is somewhere around 50 (= the 50 last recently used statements
215 will be cached). It shouldn't be too large, since a simple linear listed
216 is used for the cache at the moment (which, for small (<100) cache sizes
217 is actually quite fast).
218
219 The function always returns the cache size in effect I<before> the call,
220 so, to nuke the cache (for example, when a database connection has died
221 or you want to garbage collect old database/statement handles), this
222 construct can be used:
223
224 PApp::SQL::cachesize PApp::SQL::cachesize 0;
225
226 =cut
227
228 =item reinitialize [not exported]
229
230 Clears any internal caches (statement cache, database handle cache).
231
232 =cut
233
234 sub reinitialize {
235 cachesize cachesize 0;
236 for (values %dbcache) {
237 eval { $_->disconnect };
238 }
239 undef %dbcache;
240 }
241
242 =back
243
244 =cut
245
246 package PApp::SQL::Database;
247
248 =head2 THE DATABASE CLASS
249
250 Again (sigh) the problem of persistency. What do you do when you have to serialize on object
251 that contains (or should contain) a database handle? Short answer: you don't. Long answer:
252 you can embed the necessary information to recreate the dbh when needed.
253
254 The C<PApp::SQL::Database> class does that, in a relatively efficient
255 fashion: the overhead is currently a single method call per access (you
256 can cache the real dbh if you want).
257
258 =over 4
259
260 =item $db = new <same arguments as C<connect_cached>>
261
262 The C<new> call takes the same arguments as C<connect_cached> (obviously,
263 if you supply a connect callback it better is serializable, see
264 L<PApp::Callback>!) and returns a serializable database class. No database
265 handle is actually being created.
266
267 =item $db->dbh
268
269 Return the database handle as fast as possible (usually just a hash lookup).
270
271 =item $db->checked_dbh
272
273 Return the database handle, but first check that the database is still
274 available and re-open the connection if necessary.
275
276 =cut
277
278 sub new($$;@) {
279 my $class = shift;
280 my ($id, $dsn, $user, $pass, $flags, $connect) = @_;
281 # the following line is duplicated in PApp::SQL::Database::new
282 my $id2 = "$id\0$dsn\0$user\0$pass";
283 bless [$id2, $flags, $connect], $class;
284 }
285
286 # the following two functions better be fast!
287 sub dbh($) {
288 $dbcache{$_[0][0]} || $_[0]->checked_dbh;
289 }
290
291 sub checked_dbh($) {
292 my $dbh = $dbcache{$_[0][0]};
293 $dbh && $dbh->ping
294 ? $dbh
295 : PApp::SQL::connect_cached((split /\x00/, $_[0][0]), $_[0][1], $_[0][2]);
296 }
297
298 =item $db->dsn
299
300 Return the DSN (L<DBI>) fo the database object (e.g. for error messages).
301
302 =cut
303
304 sub dsn($) {
305 my $self = shift;
306 $self->[1][1];
307 }
308
309 =back
310
311 =cut
312
313 reinitialize;
314
315 1;
316
317 =head1 BUGS
318
319 As of this writing, sql_fetch and sql_fetchall are not very well tested
320 (they were just re-written in C).
321
322 sql_exists could be faster (it is written very ugly to not change the
323 current package).
324
325 =head1 SEE ALSO
326
327 L<PApp>.
328
329 =head1 AUTHOR
330
331 Marc Lehmann <pcg@goof.com>
332 http://www.goof.com/pcg/marc/
333
334 =cut
335