ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/PApp-SQL/SQL.pm
Revision: 1.10
Committed: Mon Feb 5 14:05:08 2001 UTC (23 years, 3 months ago) by root
Branch: MAIN
Changes since 1.9: +61 -20 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
9 my $st = sql_exec $DBH, "select ... where a = ?", $a;
10
11 local $DBH = <database handle>;
12 my $st = sql_exec \my($bind_a, $bind_b), "select a,b ...";
13 my $st = sql_insertid
14 sql_exec "insert into ... values (?, ?)", $v1, $v2;
15 my $a = sql_fetch "select a from ...";
16 sql_fetch \my($a, $b), "select a,b ...";
17
18 sql_exists "name from table where name like 'a%'"
19 or die "a* required but not existent";
20
21 my $db = new PApp::SQL::Database "", "DBI:mysql:test", "user", "pass";
22 local $PApp::SQL::DBH = $db->checked_dbh; # does 'ping'
23
24 sql_exec $db->dbh, "select ...";
25
26 =head1 DESCRIPTION
27
28 This module provides you with easy-to-use functions to execute sql
29 commands (using DBI). Despite being easy to use, they are also quite
30 efficient and allow you to write faster programs in less lines of code. It
31 should work with anything from perl-5.004_01 onwards, but I only support
32 5.005+.
33
34 If the descriptions here seem terse or if you always wanted to know
35 what PApp is then have a look at the PApp module which uses this module
36 extensively but also provides you with a lot more gimmicks to play around
37 with to help you create cool applications ;)
38
39 =cut
40
41 package PApp::SQL;
42
43 use DBI ();
44
45 BEGIN {
46 use base qw(Exporter DynaLoader);
47
48 $VERSION = 0.12;
49 @EXPORT = qw(
50 sql_exec sql_fetch sql_fetchall sql_exists sql_insertid $sql_exec
51 );
52 @EXPORT_OK = qw(
53 connect_cached
54 );
55
56 bootstrap PApp::SQL $VERSION;
57 }
58
59 our $sql_exec; # last result of sql_exec's execute call
60 our $DBH; # the default database handle
61 our $Database; # the current SQL::Database object, if applicable
62
63 our %dbcache;
64
65 =head2 GLOBAL VARIABLES
66
67 =over 4
68
69 =item $sql_exec
70
71 Since the C<sql_exec> family of functions return a statement handle there
72 must eb another way to test the return value of the C<execute> call. This
73 global variable contains the result of the most recent call to C<execute>
74 done by this module.
75
76 =item $PApp::SQL::DBH
77
78 The default database handle used by this module if no C<$DBH> was
79 specified as argument and no C<$DBH> is found in the current package. See
80 C<sql_exec> for a discussion.
81
82 =item $PApp::SQL::Database
83
84 The current default C<PApp::SQL::Database>-object. Future versions might
85 automatically fall back on this database and create database handles from
86 it if neccessary. At the moment this is not used by this module but might
87 be nice as a placeholder for the database object that corresponds to
88 $PApp::SQL::DBH.
89
90 =back
91
92 =head2 FUNCTIONS
93
94 =over 4
95
96 =item $dbh = connect_cached $id, $dsn, $user, $pass, $flags, $connect
97
98 (not exported by by default)
99
100 Connect to the database given by C<($dsn,$user,$pass)>, while using the
101 flags from C<$flags>. These are just the same arguments as given to
102 C<DBI->connect>.
103
104 The database handle will be cached under the unique id
105 C<$id|$dsn|$user|$pass>. If the same id is requested later, the
106 cached handle will be checked (using ping), and the connection will
107 be re-established if necessary (be sure to prefix your application or
108 module name to the id to make it "more" unique. Things like __PACKAGE__ .
109 __LINE__ work fine as well).
110
111 The reason C<$id> is necessary is that you might specify special connect
112 arguments or special flags, or you might want to configure your $DBH
113 differently than maybe other applications requesting the same database
114 connection. If none of this is becessary for your application you can
115 leave $id empty (i.e. "").
116
117 If specified, C<$connect> is a callback (e.g. a coderef) that will be
118 called each time a new connection is being established, with the new
119 C<$dbh> as first argument.
120
121 Examples:
122
123 # try your luck opening the papp database without access info
124 $dbh = connect_cached __FILE__, "DBI:mysql:papp";
125
126 =cut
127
128 sub connect_cached {
129 my ($id, $dsn, $user, $pass, $flags, $connect) = @_;
130 # the following line is duplicated in PApp::SQL::Database::new
131 $id = "$id\0$dsn\0$user\0$pass";
132 unless ($dbcache{$id} && $dbcache{$id}->ping) {
133 #warn "connecting to ($dsn|$user|$pass|$flags)\n";#d#
134 # first, nuke our statement cache (sooory ;)
135 cachesize cachesize 0;
136 # then connect anew
137 $dbcache{$id} =
138 eval { DBI->connect($dsn, $user, $pass, $flags) }
139 || eval { DBI->connect($dsn, $user, $pass, $flags) }
140 || die "unable to connect to database $dsn: $DBI::errstr\n";
141 $connect->($dbcache{$id}) if $connect;
142 }
143 $dbcache{$id};
144 }
145
146 =item $sth = sql_exec [dbh,] [bind-vals...,] "sql-statement", [arguments...]
147
148 C<sql_exec> is the most important and most-used function in this module.
149
150 Runs the given sql command with the given parameters and returns the
151 statement handle. The command and the statement handle will be cached
152 (with the database handle and the sql string as key), so prepare will be
153 called only once for each distinct sql call (please keep in mind that the
154 returned statement will always be the same, so, if you call C<sql_exec>
155 with the same dbh and sql-statement twice (e.g. in a subroutine you
156 called), the statement handle for the first call mustn't be used.
157
158 The database handle (the first argument) is optional. If it is missing,
159 C<sql_exec> first tries to use the variable C<$DBH> in the current (=
160 calling) package and, if that fails, it tries to use database handle in
161 C<$PApp::SQL::DBH>, which you can set before calling these functions.
162
163 The actual return value from the C<$sth->execute> call is stored in the
164 package-global (and exported) variable C<$sql_exec>.
165
166 If any error occurs C<sql_exec> will throw an exception.
167
168 Examples:
169
170 # easy one
171 my $st = sql_exec "select name, id from table where id = ?", $id;
172 while (my ($name, $id) = $st->fetchrow_array) { ... };
173
174 # the fastest way to use dbi, using bind_columns
175 my $st = sql_exec \my($name, $id),
176 "select name, id from table where id = ?",
177 $id;
178 while ($st->fetch) { ...}
179
180 # now use a different dastabase:
181 sql_exec $dbh, "update file set name = ?", "oops.txt";
182
183
184 =item sql_fetch <see sql_exec>
185
186 Execute a sql-statement and fetch the first row of results. Depending on
187 the caller context the row will be returned as a list (array context), or
188 just the first columns. In table form:
189
190 CONTEXT RESULT
191 void ()
192 scalar first column
193 list array
194
195 C<sql_fetch> is quite efficient in conjunction with bind variables:
196
197 sql_fetch \my($name, $amount),
198 "select name, amount from table where id name = ?",
199 "Toytest";
200
201 But of course the normal way to call it is simply:
202
203 my($name, $amount) = sql_fetch "select ...", args...
204
205 ... and it's still quite fast unless you fetch large amounts of data.
206
207 =item sql_fetchall <see sql_exec>
208
209 Similarly to C<sql_fetch>, but all result rows will be fetched (this is
210 of course inefficient for large results!). The context is ignored (only
211 list context makes sense), but the result still depends on the number of
212 columns in the result:
213
214 COLUMNS RESULT
215 0 ()
216 1 (row1, row2, row3...)
217 many ([row1], [row2], [row3]...)
218
219 Examples (all of which are inefficient):
220
221 for (sql_fetchall "select id from table") { ... }
222
223 my @names = sql_fetchall "select name from user";
224
225 for (sql_fetchall "select name, age, place from user") {
226 my ($name, $age, $place) = @$_;
227 }
228
229 =item sql_exists "<table> where ...", args...
230
231 Check wether the result of the sql-statement "select xxx from
232 $first_argument" would be empty or not (that is, imagine the string
233 "select from" were prepended to your statement (it isn't)). Should work
234 with every database but can be quite slow, except on mysql, where this
235 should be quite fast.
236
237 Examples:
238
239 print "user 7 exists!\n"
240 if sql_exists "user where id = ?", 7;
241
242 die "duplicate key"
243 if sql_exists "user where name = ? and pass = ?", "stefan", "geheim";
244
245 =cut
246
247 =item $lastid = sql_insertid $sth
248
249 Returns the last automatically created key value. It must be executed
250 directly after executing the insert statement that created it. This is
251 what is actually returned for various databases. If your database is
252 missing, please send me an e-mail on how to implement this ;)
253
254 mysql: first C<AUTO_INCREMENT> column set to NULL
255 postgres: C<oid> column (is there a way to get the last SERIAL?)
256 sybase: C<IDENTITY> column of the last insert (slow)
257 informix: C<SERIAL> or C<SERIAL8> column of the last insert
258
259 Except for sybase, this does not require a server access.
260
261 =cut
262
263 sub sql_insertid($) {
264 my $sth = shift or die "sql_insertid requires a statement handle";
265 my $dbh = $sth->{Database};
266 my $driver = $dbh->{Driver}{Name};
267
268 $driver eq "mysql" and return $sth->{mysql_insertid};
269 $driver eq "Pg" and return $sth->{pg_oid_status};
270 $driver eq "Sybase" and return sql_fetch($dbh, 'SELECT @@IDENTITY');
271 $driver eq "Informix" and return $sth->{ix_sqlerrd}[1];
272
273 die "sql_insertid does not spport the dbd driver '$driver', please see PApp::SQL::sql_insertid";
274 }
275
276 =item [old-size] = cachesize [new-size]
277
278 Returns (and possibly changes) the LRU cache size used by C<sql_exec>. The
279 default is somewhere around 50 (= the 50 last recently used statements
280 will be cached). It shouldn't be too large, since a simple linear listed
281 is used for the cache at the moment (which, for small (<100) cache sizes
282 is actually quite fast).
283
284 The function always returns the cache size in effect I<before> the call,
285 so, to nuke the cache (for example, when a database connection has died
286 or you want to garbage collect old database/statement handles), this
287 construct can be used:
288
289 PApp::SQL::cachesize PApp::SQL::cachesize 0;
290
291 =cut
292
293 =item reinitialize [not exported]
294
295 Clears any internal caches (statement cache, database handle
296 cache). Should be called after C<fork> and other accidents that invalidate
297 database handles.
298
299 =cut
300
301 sub reinitialize {
302 cachesize cachesize 0;
303 for (values %dbcache) {
304 eval { $_->disconnect };
305 }
306 undef %dbcache;
307 }
308
309 =back
310
311 =cut
312
313 reinitialize;
314
315 package PApp::SQL::Database;
316
317 =head2 THE DATABASE CLASS
318
319 Again (sigh) the problem of persistency. What do you do when you have to serialize on object
320 that contains (or should contain) a database handle? Short answer: you don't. Long answer:
321 you can embed the necessary information to recreate the dbh when needed.
322
323 The C<PApp::SQL::Database> class does that, in a relatively efficient
324 fashion: the overhead is currently a single method call per access (you
325 can cache the real dbh if you want).
326
327 =over 4
328
329 =item $db = new <same arguments as C<connect_cached>>
330
331 The C<new> call takes the same arguments as C<connect_cached> (obviously,
332 if you supply a connect callback it better is serializable, see
333 L<PApp::Callback>!) and returns a serializable database class. No database
334 handle is actually being created.
335
336 =item $db->dbh
337
338 Return the database handle as fast as possible (usually just a hash lookup).
339
340 =item $db->checked_dbh
341
342 Return the database handle, but first check that the database is still
343 available and re-open the connection if necessary.
344
345 =cut
346
347 sub new($$;@) {
348 my $class = shift;
349 my ($id, $dsn, $user, $pass, $flags, $connect) = @_;
350 # the following line is duplicated in PApp::SQL::Database::new
351 my $id2 = "$id\0$dsn\0$user\0$pass";
352 bless [$id2, $flags, $connect], $class;
353 }
354
355 # the following two functions better be fast!
356 sub dbh($) {
357 $dbcache{$_[0][0]} || $_[0]->checked_dbh;
358 }
359
360 sub checked_dbh($) {
361 my $dbh = $dbcache{$_[0][0]};
362 $dbh && $dbh->ping
363 ? $dbh
364 : PApp::SQL::connect_cached((split /\x00/, $_[0][0]), $_[0][1], $_[0][2]);
365 }
366
367 =item $db->dsn
368
369 Return the DSN (L<DBI>) fo the database object (e.g. for error messages).
370
371 =cut
372
373 sub dsn($) {
374 my $self = shift;
375 (split /\x00/, $self->[0])[1];
376 }
377
378 =back
379
380 =cut
381
382 1;
383
384 =head1 SEE ALSO
385
386 L<PApp>.
387
388 =head1 AUTHOR
389
390 Marc Lehmann <pcg@goof.com>
391 http://www.goof.com/pcg/marc/
392
393 =cut
394