Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | .\" Automatically generated by Pod::Man v1.34, Pod::Parser v1.13 |
2 | .\" | |
3 | .\" Standard preamble: | |
4 | .\" ======================================================================== | |
5 | .de Sh \" Subsection heading | |
6 | .br | |
7 | .if t .Sp | |
8 | .ne 5 | |
9 | .PP | |
10 | \fB\\$1\fR | |
11 | .PP | |
12 | .. | |
13 | .de Sp \" Vertical space (when we can't use .PP) | |
14 | .if t .sp .5v | |
15 | .if n .sp | |
16 | .. | |
17 | .de Vb \" Begin verbatim text | |
18 | .ft CW | |
19 | .nf | |
20 | .ne \\$1 | |
21 | .. | |
22 | .de Ve \" End verbatim text | |
23 | .ft R | |
24 | .fi | |
25 | .. | |
26 | .\" Set up some character translations and predefined strings. \*(-- will | |
27 | .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left | |
28 | .\" double quote, and \*(R" will give a right double quote. | will give a | |
29 | .\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to | |
30 | .\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' | |
31 | .\" expand to `' in nroff, nothing in troff, for use with C<>. | |
32 | .tr \(*W-|\(bv\*(Tr | |
33 | .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' | |
34 | .ie n \{\ | |
35 | . ds -- \(*W- | |
36 | . ds PI pi | |
37 | . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch | |
38 | . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch | |
39 | . ds L" "" | |
40 | . ds R" "" | |
41 | . ds C` "" | |
42 | . ds C' "" | |
43 | 'br\} | |
44 | .el\{\ | |
45 | . ds -- \|\(em\| | |
46 | . ds PI \(*p | |
47 | . ds L" `` | |
48 | . ds R" '' | |
49 | 'br\} | |
50 | .\" | |
51 | .\" If the F register is turned on, we'll generate index entries on stderr for | |
52 | .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index | |
53 | .\" entries marked with X<> in POD. Of course, you'll have to process the | |
54 | .\" output yourself in some meaningful fashion. | |
55 | .if \nF \{\ | |
56 | . de IX | |
57 | . tm Index:\\$1\t\\n%\t"\\$2" | |
58 | .. | |
59 | . nr % 0 | |
60 | . rr F | |
61 | .\} | |
62 | .\" | |
63 | .\" For nroff, turn off justification. Always turn off hyphenation; it makes | |
64 | .\" way too many mistakes in technical documents. | |
65 | .hy 0 | |
66 | .if n .na | |
67 | .\" | |
68 | .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). | |
69 | .\" Fear. Run. Save yourself. No user-serviceable parts. | |
70 | . \" fudge factors for nroff and troff | |
71 | .if n \{\ | |
72 | . ds #H 0 | |
73 | . ds #V .8m | |
74 | . ds #F .3m | |
75 | . ds #[ \f1 | |
76 | . ds #] \fP | |
77 | .\} | |
78 | .if t \{\ | |
79 | . ds #H ((1u-(\\\\n(.fu%2u))*.13m) | |
80 | . ds #V .6m | |
81 | . ds #F 0 | |
82 | . ds #[ \& | |
83 | . ds #] \& | |
84 | .\} | |
85 | . \" simple accents for nroff and troff | |
86 | .if n \{\ | |
87 | . ds ' \& | |
88 | . ds ` \& | |
89 | . ds ^ \& | |
90 | . ds , \& | |
91 | . ds ~ ~ | |
92 | . ds / | |
93 | .\} | |
94 | .if t \{\ | |
95 | . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" | |
96 | . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' | |
97 | . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' | |
98 | . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' | |
99 | . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' | |
100 | . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' | |
101 | .\} | |
102 | . \" troff and (daisy-wheel) nroff accents | |
103 | .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' | |
104 | .ds 8 \h'\*(#H'\(*b\h'-\*(#H' | |
105 | .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] | |
106 | .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' | |
107 | .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' | |
108 | .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] | |
109 | .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] | |
110 | .ds ae a\h'-(\w'a'u*4/10)'e | |
111 | .ds Ae A\h'-(\w'A'u*4/10)'E | |
112 | . \" corrections for vroff | |
113 | .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' | |
114 | .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' | |
115 | . \" for low resolution devices (crt and lpr) | |
116 | .if \n(.H>23 .if \n(.V>19 \ | |
117 | \{\ | |
118 | . ds : e | |
119 | . ds 8 ss | |
120 | . ds o a | |
121 | . ds d- d\h'-1'\(ga | |
122 | . ds D- D\h'-1'\(hy | |
123 | . ds th \o'bp' | |
124 | . ds Th \o'LP' | |
125 | . ds ae ae | |
126 | . ds Ae AE | |
127 | .\} | |
128 | .rm #[ #] #H #V #F C | |
129 | .\" ======================================================================== | |
130 | .\" | |
131 | .IX Title "DBI::DBD 3" | |
132 | .TH DBI::DBD 3 "2002-10-01" "perl v5.8.0" "User Contributed Perl Documentation" | |
133 | .SH "NAME" | |
134 | DBI::DBD \- DBD Driver Writer's Guide | |
135 | .SH "SYNOPSIS" | |
136 | .IX Header "SYNOPSIS" | |
137 | .Vb 1 | |
138 | \& perldoc DBI::DBD | |
139 | .Ve | |
140 | .SH "VERSION and VOLATILITY" | |
141 | .IX Header "VERSION and VOLATILITY" | |
142 | .Vb 2 | |
143 | \& $Revision: 10.9 $ | |
144 | \& $Date: 2001/05/29 23:25:55 $ | |
145 | .Ve | |
146 | .PP | |
147 | This document is a minimal draft which is in need of further work. | |
148 | .PP | |
149 | The changes will occur both because the \s-1DBI\s0 specification is changing | |
150 | and hence the requirements on \s-1DBD\s0 drivers change, and because feedback | |
151 | from people reading this document will suggest improvements to it. | |
152 | .PP | |
153 | Please read the \s-1DBI\s0 documentation first and fully, including the \s-1DBI\s0 \s-1FAQ\s0. | |
154 | The reread the \s-1DBI\s0 specification again as you're reading this. It'll help. | |
155 | .PP | |
156 | This document is a patchwork of contributions from various authors. | |
157 | More contributions (preferably as patches) are very welcome. | |
158 | .SH "DESCRIPTION" | |
159 | .IX Header "DESCRIPTION" | |
160 | This document is primarily intended to help people writing new | |
161 | database drivers for the Perl Database Interface (Perl \s-1DBI\s0). | |
162 | It may also help others interested in discovering why the internals of | |
163 | a \s-1DBD\s0 driver are written the way they are. | |
164 | .PP | |
165 | This is a guide. Few (if any) of the statements in it are completely | |
166 | authoritative under all possible circumstances. This means you will | |
167 | need to use judgement in applying the guidelines in this document. | |
168 | If in \fIany\fR doubt at all, please do contact the dbi-dev mailing list | |
169 | (details given below) where Tim Bunce and other driver authors can help. | |
170 | .PP | |
171 | The primary web-site for locating \s-1DBI\s0 software and information is | |
172 | .PP | |
173 | .Vb 1 | |
174 | \& http://www.symbolstone.org/technology/perl/DBI | |
175 | .Ve | |
176 | .PP | |
177 | There are 2 main and one auxilliary mailing lists for people working | |
178 | with \s-1DBI\s0. The primary lists are dbi\-users@isc.org for general users | |
179 | of \s-1DBI\s0 and \s-1DBD\s0 drivers, and dbi\-dev@isc.org mainly for \s-1DBD\s0 driver | |
180 | writers (don't join the dbi-dev list unless you have a good reason). | |
181 | The auxilliary list is dbi\-announce@isc.org for announcing new | |
182 | releases of \s-1DBI\s0 or \s-1DBD\s0 drivers. | |
183 | .PP | |
184 | You can join these lists by accessing the web-site | |
185 | <http://www.isc.org/dbi\-lists.html>. | |
186 | The lists are closed so you cannot send email to any of the lists | |
187 | unless you join the list first. | |
188 | .PP | |
189 | You should also consider monitoring the comp.lang.perl.* newsgroups. | |
190 | .SH "BOOK" | |
191 | .IX Header "BOOK" | |
192 | The definitive book on Perl \s-1DBI\s0 is 'Programming the Perl \s-1DBI:\s0 Database | |
193 | programming with Perl' by Alligator Descartes and Tim Bunce, published | |
194 | by O'Reilly Associates, February 2000, \s-1ISBN\s0 1\-56592\-699\-4. Buy it now | |
195 | if you have not already done so. | |
196 | .SH "REGISTERING A NEW DRIVER" | |
197 | .IX Header "REGISTERING A NEW DRIVER" | |
198 | Before writing a new driver, it is in your interests to find out | |
199 | whether there already is a driver for your database. If there is such | |
200 | a driver, it would be much easier to make use of it than to write your | |
201 | own! | |
202 | .Sh "Locating drivers" | |
203 | .IX Subsection "Locating drivers" | |
204 | The primary web-site for locating Perl software is | |
205 | <http://www.perl.com/CPAN>. | |
206 | You should look under the various modules listings for the software | |
207 | you are after. | |
208 | Two of the main pages you should look at are: | |
209 | .PP | |
210 | .Vb 1 | |
211 | \& http://www.perl.org/CPAN/modules/by-category/07_Database_Interfaces/DBI | |
212 | .Ve | |
213 | .PP | |
214 | .Vb 1 | |
215 | \& http://www.perl.org/CPAN/modules/by-category/07_Database_Interfaces/DBD | |
216 | .Ve | |
217 | .PP | |
218 | See the \s-1DBI\s0 docs for information on \s-1DBI\s0 web sites and mailing lists. | |
219 | .Sh "Registering a new driver" | |
220 | .IX Subsection "Registering a new driver" | |
221 | Before going through any official registration process, you will need | |
222 | to establish that there is no driver already in the works. | |
223 | You'll do that by asking the \s-1DBI\s0 mailing lists whether there is such a | |
224 | driver available, or whether anybody is working on one. | |
225 | .SH "CREATING A NEW DRIVER USING PURE PERL" | |
226 | .IX Header "CREATING A NEW DRIVER USING PURE PERL" | |
227 | Writing a pure Perl driver is surprisingly simple. However, there are | |
228 | some problems one should be aware of. The best option is of course | |
229 | picking up an existing driver and carefully modifying one method | |
230 | after the other. | |
231 | .PP | |
232 | As an example we take a look at the \fIDBD::File\fR driver, a driver for | |
233 | accessing plain files as tables, which is part of the \fI\s-1DBD::CSV\s0\fR | |
234 | package. In what follows I assume the name \f(CW\*(C`Driver\*(C'\fR for your new | |
235 | package: The least thing we have to implement are the files | |
236 | \&\f(CW\*(C`Makefile.PL\*(C'\fR and \f(CW\*(C`Driver.pm\*(C'\fR. | |
237 | .Sh "Makefile.PL" | |
238 | .IX Subsection "Makefile.PL" | |
239 | You typically start with writing \f(CW\*(C`Makefile.PL\*(C'\fR, a Makefile generator. | |
240 | The contents of this file are described in detail in the MakeMaker | |
241 | man pages, it's definitely a good idea if you start reading them. | |
242 | At least you should know about the variables \fI\s-1CONFIGURE\s0\fR, \fI\s-1DEFINED\s0\fR, | |
243 | \&\fI\s-1DIR\s0\fR, \fI\s-1EXE_FILES\s0\fR, \fI\s-1INC\s0\fR, \fI\s-1LIBS\s0\fR, \fI\s-1LINKTYPE\s0\fR, \fI\s-1NAME\s0\fR, \fI\s-1OPTIMIZE\s0\fR, | |
244 | \&\fI\s-1PL_FILES\s0\fR, \fI\s-1VERSION\s0\fR, \fI\s-1VERSION_FROM\s0\fR, \fIclean\fR, \fIdepend\fR, \fIrealclean\fR | |
245 | from the \f(CW\*(C`ExtUtils::MakeMaker\*(C'\fR man page: These are used in almost any | |
246 | Makefile.PL. Additionally read the section on \fIOverriding MakeMaker Methods\fR | |
247 | and the descriptions of the \fIdistcheck\fR, \fIdisttest\fR and \fIdist\fR targets: | |
248 | They will definitely be useful for you. | |
249 | .PP | |
250 | Of special importance for \s-1DBI\s0 drivers is the \fIpostamble\fR method from | |
251 | the \f(CW\*(C`ExtUtils::MM_Unix\*(C'\fR man page. And for Emacs users I recommend | |
252 | the \fIlibscan\fR method. | |
253 | .PP | |
254 | Now an example, I use the word \f(CW\*(C`Driver\*(C'\fR wherever you should insert | |
255 | your drivers name: | |
256 | .PP | |
257 | .Vb 1 | |
258 | \& # -*- perl -*- | |
259 | .Ve | |
260 | .PP | |
261 | .Vb 3 | |
262 | \& use DBI 1.03; | |
263 | \& use DBI::DBD; | |
264 | \& use ExtUtils::MakeMaker; | |
265 | .Ve | |
266 | .PP | |
267 | .Vb 8 | |
268 | \& ExtUtils::MakeMaker::WriteMakefile( | |
269 | \& 'NAME' => 'DBD::Driver', | |
270 | \& 'VERSION_FROM' => 'Driver.pm', | |
271 | \& 'INC' => $DBI_INC_DIR, | |
272 | \& 'dist' => { 'SUFFIX' => '.gz', | |
273 | \& 'COMPRESS' => 'gzip -9f' }, | |
274 | \& 'realclean' => '*.xsi' | |
275 | \& ); | |
276 | .Ve | |
277 | .PP | |
278 | .Vb 6 | |
279 | \& package MY; | |
280 | \& sub postamble { dbd_postamble(@_); } | |
281 | \& sub libscan { | |
282 | \& my($self, $path) = @_; | |
283 | \& ($path =~ /\e~$/) ? undef : $path; | |
284 | \& } | |
285 | .Ve | |
286 | .PP | |
287 | See also \fIExtUtils::MakeMaker\fR\|(3). \fIExtUtils::MM_Unix\fR\|(3). | |
288 | .Sh "\s-1README\s0 file" | |
289 | .IX Subsection "README file" | |
290 | The \s-1README\s0 file should describe what the driver is for, the | |
291 | pre-requisites for the build process, the actual build process, and how | |
292 | to report errors. Users will find ways of breaking the driver build and | |
293 | test process which you would never even dreamed to be possible in your | |
294 | nightmares. :\-) Therefore, you need to write this document defensively | |
295 | and precisely. Also, it is in your interests to ensure that your tests | |
296 | work as widely as possible. As always, use the \s-1README\s0 from one of the | |
297 | established drivers as a basis for your own. | |
298 | .Sh "\s-1MANIFEST\s0" | |
299 | .IX Subsection "MANIFEST" | |
300 | The \s-1MANIFEST\s0 will be used by the Makefile'd dist target to build the | |
301 | distribution tar file that is uploaded to \s-1CPAN\s0. It should list every | |
302 | file that you want to include in your distribution, one per line. | |
303 | .Sh "lib/Bundle/DBD/Driver.pm" | |
304 | .IX Subsection "lib/Bundle/DBD/Driver.pm" | |
305 | The \s-1CPAN\s0 module provides an extremely powerful bundle mechanism that | |
306 | allows you to specify pre-requisites for your driver. | |
307 | The primary pre-requisite is Bundle::DBI; you may want or need to add | |
308 | some more. | |
309 | With the bundle set up correctly, the user can type: | |
310 | .PP | |
311 | .Vb 1 | |
312 | \& perl -MCPAN -e 'install Bundle::DBD::Driver' | |
313 | .Ve | |
314 | .PP | |
315 | and Perl will download, compile, test and install all the Perl modules | |
316 | needed to build your driver. | |
317 | .PP | |
318 | A suitable skeleton for this file is shown below. | |
319 | The prerequisite modules are listed in the \s-1CONTENTS\s0 section, with the | |
320 | official name of the module followed by a dash and an informal name or | |
321 | description. | |
322 | Listing Bundle::DBI as the main pre-requisite simplifies life. | |
323 | Don't forget to list your driver. | |
324 | Note that unless the \s-1DBMS\s0 is itself a Perl module, you cannot list it | |
325 | as a pre-requisite in this file. | |
326 | You are strongly advised to keep the version of the bundle in sync | |
327 | with the version of your driver. | |
328 | You might want to add configuration management, copyright, and | |
329 | licencing information at the top. | |
330 | .PP | |
331 | .Vb 1 | |
332 | \& package Bundle::DBD::Driver; | |
333 | .Ve | |
334 | .PP | |
335 | .Vb 1 | |
336 | \& $VERSION = '0.01'; | |
337 | .Ve | |
338 | .PP | |
339 | .Vb 1 | |
340 | \& 1; | |
341 | .Ve | |
342 | .PP | |
343 | .Vb 1 | |
344 | \& __END__ | |
345 | .Ve | |
346 | .PP | |
347 | .Vb 1 | |
348 | \& =head1 NAME | |
349 | .Ve | |
350 | .PP | |
351 | .Vb 1 | |
352 | \& Bundle::DBD::Driver - A bundle to install all DBD::Driver related modules | |
353 | .Ve | |
354 | .PP | |
355 | .Vb 1 | |
356 | \& =head1 SYNOPSIS | |
357 | .Ve | |
358 | .PP | |
359 | .Vb 1 | |
360 | \& C<perl -MCPAN -e 'install Bundle::DBD::Driver'> | |
361 | .Ve | |
362 | .PP | |
363 | .Vb 1 | |
364 | \& =head1 CONTENTS | |
365 | .Ve | |
366 | .PP | |
367 | .Vb 1 | |
368 | \& Bundle::DBI - Bundle for DBI by TIMB (Tim Bunce) | |
369 | .Ve | |
370 | .PP | |
371 | .Vb 1 | |
372 | \& DBD::Driver - DBD::Driver by YOU (Your Name) | |
373 | .Ve | |
374 | .PP | |
375 | .Vb 1 | |
376 | \& =head1 DESCRIPTION | |
377 | .Ve | |
378 | .PP | |
379 | .Vb 3 | |
380 | \& This bundle includes all the modules used by the Perl Database | |
381 | \& Interface (DBI) driver for Driver (DBD::Driver), assuming the | |
382 | \& use of DBI version 1.13 or later, created by Tim Bunce. | |
383 | .Ve | |
384 | .PP | |
385 | .Vb 4 | |
386 | \& If you've not previously used the CPAN module to install any | |
387 | \& bundles, you will be interrogated during its setup phase. | |
388 | \& But when you've done it once, it remembers what you told it. | |
389 | \& You could start by running: | |
390 | .Ve | |
391 | .PP | |
392 | .Vb 1 | |
393 | \& C<perl -MCPAN -e 'install Bundle::CPAN'> | |
394 | .Ve | |
395 | .PP | |
396 | .Vb 1 | |
397 | \& =head1 SEE ALSO | |
398 | .Ve | |
399 | .PP | |
400 | .Vb 1 | |
401 | \& Bundle::DBI | |
402 | .Ve | |
403 | .PP | |
404 | .Vb 1 | |
405 | \& =head1 AUTHOR | |
406 | .Ve | |
407 | .PP | |
408 | .Vb 1 | |
409 | \& Your Name E<lt>F<you@yourdomain.com>E<gt> | |
410 | .Ve | |
411 | .PP | |
412 | .Vb 1 | |
413 | \& =head1 THANKS | |
414 | .Ve | |
415 | .PP | |
416 | .Vb 5 | |
417 | \& This bundle was created by ripping off Bundle::libnet created by | |
418 | \& Graham Barr E<lt>F<gbarr@ti.com>E<gt>, and radically simplified | |
419 | \& with some information from Jochen Wiedmann E<lt>F<joe@ispsoft.de>E<gt>. | |
420 | \& The template was then included in the DBI::DBD documentation by | |
421 | \& Jonathan Leffler E<lt>F<jleffler@informix.com>E<gt>. | |
422 | .Ve | |
423 | .PP | |
424 | .Vb 1 | |
425 | \& =cut | |
426 | .Ve | |
427 | .Sh "Driver.pm" | |
428 | .IX Subsection "Driver.pm" | |
429 | The Driver.pm file defines the Perl module DBD::Driver for your driver. | |
430 | It will define a package DBD::Driver along with some version information, | |
431 | some variable definitions, and a function \fIdriver()\fR which will have a more | |
432 | or less standard structure. | |
433 | .PP | |
434 | It will also define a package DBD::Driver::dr (with methods \fIconnect()\fR, | |
435 | \&\fIdata_sources()\fR and \fIdisconnect_all()\fR), and a package DBD::Driver::db | |
436 | (which will define a function \fIprepare()\fR etc), and a package DBD::Driver::st | |
437 | with methods \fIexecute()\fR, \fIfetch()\fR and the like. | |
438 | .PP | |
439 | The Driver.pm file will also contain the documentation specific to | |
440 | DBD::Driver in the format used by perldoc. | |
441 | .PP | |
442 | Now let's take a closer look at an excerpt of File.pm as an example. | |
443 | We ignore things that are common to any module (even non\-DBI(D) modules) | |
444 | or really specific for the DBD::File package. | |
445 | .IP "The header" 2 | |
446 | .IX Item "The header" | |
447 | .Vb 1 | |
448 | \& package DBD::File; | |
449 | .Ve | |
450 | .Sp | |
451 | .Vb 2 | |
452 | \& use strict; | |
453 | \& use vars qw($err $errstr $state $drh); | |
454 | .Ve | |
455 | .Sp | |
456 | .Vb 3 | |
457 | \& $err = 0; # holds error code for DBI::err | |
458 | \& $errstr = ""; # holds error string for DBI::errstr | |
459 | \& $sqlstate = ""; # holds SQL state for DBI::state | |
460 | .Ve | |
461 | .Sp | |
462 | These variables are used for storing error states and messages. | |
463 | However, it is crucial to understand that you must not modify | |
464 | them directly; instead use the \fIevent\fR method, see below. | |
465 | .Sp | |
466 | .Vb 1 | |
467 | \& $drh = undef; # holds driver handle once initialized | |
468 | .Ve | |
469 | .Sp | |
470 | This is where the driver handle will be stored, once created. Note, | |
471 | that you may assume, there's only one handle for your driver. | |
472 | .IP "The driver constructor" 2 | |
473 | .IX Item "The driver constructor" | |
474 | .Vb 3 | |
475 | \& sub driver { | |
476 | \& return $drh if $drh; # already created - return same one | |
477 | \& my($class, $attr) = @_; | |
478 | .Ve | |
479 | .Sp | |
480 | .Vb 1 | |
481 | \& $class .= "::dr"; | |
482 | .Ve | |
483 | .Sp | |
484 | .Vb 9 | |
485 | \& # not a 'my' since we use it above to prevent multiple drivers | |
486 | \& $drh = DBI::_new_drh($class, { | |
487 | \& 'Name' => 'File', | |
488 | \& 'Version' => $VERSION, | |
489 | \& 'Err' => \e$DBD::File::err, | |
490 | \& 'Errstr' => \e$DBD::File::errstr, | |
491 | \& 'State' => \e$DBD::File::state, | |
492 | \& 'Attribution' => 'DBD::File by Jochen Wiedmann', | |
493 | \& }); | |
494 | .Ve | |
495 | .Sp | |
496 | .Vb 2 | |
497 | \& return $drh; | |
498 | \& } | |
499 | .Ve | |
500 | .Sp | |
501 | The \fIdriver\fR method is the driver handle constructor. It's a | |
502 | reasonable example of how \s-1DBI\s0 implements its handles. There are three | |
503 | kinds: \fBdriver handles\fR (typically stored in \f(CW$drh\fR, from now on | |
504 | called \f(CW\*(C`drh\*(C'\fR), \fBdatabase handles\fR (from now on called \f(CW\*(C`dbh\*(C'\fR or | |
505 | \&\f(CW$dbh\fR) and \fBstatement handles\fR, (from now on called \f(CW\*(C`sth\*(C'\fR or | |
506 | \&\f(CW$sth\fR). | |
507 | .Sp | |
508 | The prototype of DBI::_new_drh is | |
509 | .Sp | |
510 | .Vb 1 | |
511 | \& $drh = DBI::_new_drh($class, $attr1, $attr2); | |
512 | .Ve | |
513 | .Sp | |
514 | with the following arguments: | |
515 | .RS 2 | |
516 | .IP "\fI$class\fR" 4 | |
517 | .IX Item "$class" | |
518 | is typically your drivers class, e.g., \*(L"DBD::File::dr\*(R", passed as first | |
519 | argument to the \fIdriver\fR method. | |
520 | .IP "\fI$attr1\fR" 4 | |
521 | .IX Item "$attr1" | |
522 | is a hash ref to attributes like \fIName\fR, \fIVersion\fR, \fIErr\fR, \fIErrstr\fR | |
523 | \&\fIState\fR and \fIAttributrion\fR. These are processed and used by \s-1DBI\s0, you | |
524 | better not make any assumptions on them nor should you add private | |
525 | attributes here. | |
526 | .IP "\fI$attr2\fR" 4 | |
527 | .IX Item "$attr2" | |
528 | This is another (optional) hash ref with your private attributes. \s-1DBI\s0 | |
529 | will leave them alone. | |
530 | .RE | |
531 | .RS 2 | |
532 | .Sp | |
533 | The \fIDBI::new_drh\fR method and the \fIdriver\fR method | |
534 | both return \f(CW\*(C`undef\*(C'\fR for failure (in which case you must look at | |
535 | \&\f(CW$DBI::err\fR and \f(CW$DBI::errstr\fR, because you have no driver handle). | |
536 | .RE | |
537 | .IP "The database handle constructor" 2 | |
538 | .IX Item "The database handle constructor" | |
539 | The next lines of code look as follows: | |
540 | .Sp | |
541 | .Vb 1 | |
542 | \& package DBD::Driver::dr; # ====== DRIVER ====== | |
543 | .Ve | |
544 | .Sp | |
545 | .Vb 1 | |
546 | \& $DBD::Driver::dr::imp_data_size = 0; | |
547 | .Ve | |
548 | .Sp | |
549 | Note that no \f(CW@ISA\fR is needed here, or for the other DBD::Driver::* | |
550 | classes, because the \s-1DBI\s0 takes care of that for you when the driver is | |
551 | loaded. | |
552 | .Sp | |
553 | The database handle constructor is a driver method, thus we have | |
554 | to change the namespace. | |
555 | .Sp | |
556 | .Vb 2 | |
557 | \& sub connect { | |
558 | \& my($drh, $dbname, $user, $auth, $attr)= @_; | |
559 | .Ve | |
560 | .Sp | |
561 | .Vb 4 | |
562 | \& # Some database specific verifications, default settings | |
563 | \& # and the like following here. This should only include | |
564 | \& # syntax checks or similar stuff where it's legal to | |
565 | \& # 'die' in case of errors. | |
566 | .Ve | |
567 | .Sp | |
568 | .Vb 6 | |
569 | \& # create a 'blank' dbh (call superclass constructor) | |
570 | \& my $dbh = DBI::_new_dbh($drh, { | |
571 | \& 'Name' => $dbname, | |
572 | \& 'USER' => $user, | |
573 | \& 'CURRENT_USER' => $user, | |
574 | \& }); | |
575 | .Ve | |
576 | .Sp | |
577 | .Vb 2 | |
578 | \& # Process attributes from the DSN; we assume ODBC syntax | |
579 | \& # here, that is, the DSN looks like var1=val1;...;varN=valN | |
580 | .Ve | |
581 | .Sp | |
582 | .Vb 9 | |
583 | \& my $var; | |
584 | \& foreach $var (split(/;/, $dbname)) { | |
585 | \& if ($var =~ /(.*?)=(,*)/) { | |
586 | \& # Not !!! $dbh->{$var} = $val; | |
587 | \& $dbh->STORE($var, $val); | |
588 | \& } | |
589 | \& } | |
590 | \& $dbh; | |
591 | \& } | |
592 | .Ve | |
593 | .Sp | |
594 | This is mostly the same as in the \fIdriver handle constructor\fR above. | |
595 | The arguments are described in the \s-1DBI\s0 man page. See \s-1\fIDBI\s0\fR\|(3). | |
596 | The constructor is called, returning a database handle. The constructors | |
597 | prototype is | |
598 | .Sp | |
599 | .Vb 1 | |
600 | \& $dbh = DBI::_new_dbh($drh, $attr1, $attr2); | |
601 | .Ve | |
602 | .Sp | |
603 | with the same arguments as in the \fIdriver handle constructor\fR, the | |
604 | exception being \f(CW$class\fR replaced by \f(CW$drh\fR. | |
605 | .Sp | |
606 | Note the use of the \fI\s-1STORE\s0\fR method for setting the dbh attributes. | |
607 | That's because within the driver code, the handle object you have is | |
608 | the 'inner' handle of a tied hash, not the outer handle that the | |
609 | users of your driver have. | |
610 | .Sp | |
611 | Because you have the inner handle, tie magic doesn't get invoked | |
612 | when you get or set values in the hash. This is often very handy for | |
613 | speed when you want to get or set simple non-special driver-specific | |
614 | attributes. | |
615 | .Sp | |
616 | However, some attribute values, such as those handled by the \s-1DBI\s0 | |
617 | like PrintError, don't actually exist in the hash and must be | |
618 | read via \f(CW$h\fR\->\s-1FETCH\s0($attrib) and set via \f(CW$h\fR\->\s-1STORE\s0($attrib, \f(CW$value\fR). | |
619 | If in any doubt, use these methods. | |
620 | .IP "Error handling" 2 | |
621 | .IX Item "Error handling" | |
622 | It is quite likely that something fails in the connect method. With | |
623 | DBD::File for example, you might catch an error when setting the | |
624 | current directory to something not existant by using the f_dir | |
625 | attribute. | |
626 | .Sp | |
627 | To report an error, you use the \f(CW\*(C`DBI::set_err\*(C'\fR function/method: | |
628 | .Sp | |
629 | .Vb 1 | |
630 | \& $h->DBI::set_err($errcode, $errmsg); | |
631 | .Ve | |
632 | .Sp | |
633 | This will ensure that the error is recorded correctly and that | |
634 | RaiseError and PrintError etc are handled correctly. Typically you'll | |
635 | always use the method instance, aka your method's first argument. | |
636 | .Sp | |
637 | As set_err always returns undef your error handling code can | |
638 | usually be simplified to something like this: | |
639 | .Sp | |
640 | .Vb 1 | |
641 | \& return $h->DBI::set_err($errcode, $errmsg) if ...; | |
642 | .Ve | |
643 | .IP "Other driver handle methods" 2 | |
644 | .IX Item "Other driver handle methods" | |
645 | may follow here. In particular you should consider a \fIdata_sources\fR | |
646 | method, and a (possibly empty) \fIdisconnect_all\fR method. See \s-1\fIDBI\s0\fR\|(3). | |
647 | .IP "The statement handle constructor" 2 | |
648 | .IX Item "The statement handle constructor" | |
649 | There's nothing much new in the statement handle constructor. | |
650 | .Sp | |
651 | .Vb 1 | |
652 | \& package DBD::Driver::db; # ====== DATABASE ====== | |
653 | .Ve | |
654 | .Sp | |
655 | .Vb 1 | |
656 | \& $DBD::Driver::db::imp_data_size = 0; | |
657 | .Ve | |
658 | .Sp | |
659 | .Vb 2 | |
660 | \& sub prepare { | |
661 | \& my($dbh, $statement, @attribs)= @_; | |
662 | .Ve | |
663 | .Sp | |
664 | .Vb 4 | |
665 | \& # create a 'blank' sth | |
666 | \& my $sth = DBI::_new_sth($dbh, { | |
667 | \& 'Statement' => $statement, | |
668 | \& }); | |
669 | .Ve | |
670 | .Sp | |
671 | .Vb 3 | |
672 | \& # Setup module specific data | |
673 | \& $sth->STORE('driver_params', []); | |
674 | \& $sth->STORE('NUM_OF_PARAMS', ($statement =~ tr/?//)); | |
675 | .Ve | |
676 | .Sp | |
677 | .Vb 2 | |
678 | \& $sth; | |
679 | \& } | |
680 | .Ve | |
681 | .Sp | |
682 | This is still the same: Check the arguments and call the super class | |
683 | constructor \fIDBI::_new_sth\fR. Note the prefix \fIdriver_\fR in the | |
684 | attribute names: It is required that your private attributes | |
685 | are lowercased and use such a prefix. See the \s-1DBI\s0 manual. | |
686 | .Sp | |
687 | Note that we parse the statement here in order to setup the attribute | |
688 | \&\fI\s-1NUM_OF_PARAMS\s0\fR. We could as well do this in the \fIexecute\fR method | |
689 | below, the \s-1DBI\s0 specs explicitly allow to defer this. However, one | |
690 | could not call \fIbind_param\fR in that case. | |
691 | .IP "Transaction handling" 2 | |
692 | .IX Item "Transaction handling" | |
693 | Pure Perl drivers will rarely support transactions. Thus you're \fIcommit\fR | |
694 | and \fIrollback\fR methods will typically be quite simple: | |
695 | .Sp | |
696 | .Vb 7 | |
697 | \& sub commit { | |
698 | \& my($dbh) = @_; | |
699 | \& if ($dbh->FETCH('Warn')) { | |
700 | \& warn("Commit ineffective while AutoCommit is on"); | |
701 | \& } | |
702 | \& 1; | |
703 | \& } | |
704 | .Ve | |
705 | .Sp | |
706 | .Vb 7 | |
707 | \& sub rollback { | |
708 | \& my($dbh) = @_; | |
709 | \& if ($dbh->FETCH('Warn')) { | |
710 | \& warn("Rollback ineffective while AutoCommit is on"); | |
711 | \& } | |
712 | \& 0; | |
713 | \& } | |
714 | .Ve | |
715 | .IP "The \s-1STORE\s0 and \s-1FETCH\s0 methods" 2 | |
716 | .IX Item "The STORE and FETCH methods" | |
717 | These methods (that we have already used, see above) are called for | |
718 | you, whenever the user does a | |
719 | .Sp | |
720 | .Vb 1 | |
721 | \& $dbh->{$attr} = $val; | |
722 | .Ve | |
723 | .Sp | |
724 | or, respectively, | |
725 | .Sp | |
726 | .Vb 1 | |
727 | \& $val = $dbh->{$attr}; | |
728 | .Ve | |
729 | .Sp | |
730 | See \fIperltie\fR\|(1) for details on tied hash refs to understand why these | |
731 | methods are required. | |
732 | .Sp | |
733 | The \s-1DBI\s0 will handle most attributes for you, in particular attributes | |
734 | like \fIRaiseError\fR or \fIPrintError\fR. All you have to do handle your | |
735 | driver's private attributes and any attributes, like AutoCommit, that | |
736 | the \s-1DBI\s0 can't handle for you. A good example might look like this: | |
737 | .Sp | |
738 | .Vb 18 | |
739 | \& sub STORE { | |
740 | \& my($dbh, $attr, $val) = @_; | |
741 | \& if ($attr eq 'AutoCommit') { | |
742 | \& # AutoCommit is currently the only standard attribute we have | |
743 | \& # to consider. | |
744 | \& if (!$val) { die "Can't disable AutoCommit"; } | |
745 | \& return 1; | |
746 | \& } | |
747 | \& if ($attr =~ /^driver_/) { | |
748 | \& # Handle only our private attributes here | |
749 | \& # Note that we could trigger arbitrary actions. | |
750 | \& # Ideally we should catch unknown attributes. | |
751 | \& $dbh->{$attr} = $val; # Yes, we are allowed to do this, | |
752 | \& return 1; # but only for our private attributes | |
753 | \& } | |
754 | \& # Else pass up to DBI to handle for us | |
755 | \& $dbh->SUPER::STORE($attr, $val); | |
756 | \& } | |
757 | .Ve | |
758 | .Sp | |
759 | .Vb 12 | |
760 | \& sub FETCH { | |
761 | \& my($dbh, $attr) = @_; | |
762 | \& if ($attr eq 'AutoCommit') { return 1; } | |
763 | \& if ($attr =~ /^driver_/) { | |
764 | \& # Handle only our private attributes here | |
765 | \& # Note that we could trigger arbitrary actions. | |
766 | \& return $dbh->{$attr}; # Yes, we are allowed to do this, | |
767 | \& # but only for our private attributes | |
768 | \& } | |
769 | \& # Else pass up to DBI to handle | |
770 | \& $dbh->SUPER::FETCH($attr); | |
771 | \& } | |
772 | .Ve | |
773 | .Sp | |
774 | The \s-1DBI\s0 will actually store and fetch driver-specific attributes (with all | |
775 | lowercase names) without warning or error, so there's actually no need to | |
776 | implement driver-specific any code in your \s-1FETCH\s0 and \s-1STORE\s0 methods unless | |
777 | you need extra logic/checks, beyond getting or setting the value. | |
778 | .IP "Other database handle methods" 2 | |
779 | .IX Item "Other database handle methods" | |
780 | may follow here. In particular you should consider a (possibly empty) | |
781 | \&\fIdisconnect\fR method, a \fIquote\fR method (if \s-1DBI\s0's default isn't good | |
782 | for you). | |
783 | .IP "The execute method" 2 | |
784 | .IX Item "The execute method" | |
785 | This is perhaps the most difficult method because we have to consider | |
786 | parameter bindings here. We present a simplified implementation by | |
787 | using the \fIdriver_params\fR attribute from above: | |
788 | .Sp | |
789 | .Vb 1 | |
790 | \& package DBD::Driver::st; | |
791 | .Ve | |
792 | .Sp | |
793 | .Vb 1 | |
794 | \& $DBD::Driver::st::imp_data_size = 0; | |
795 | .Ve | |
796 | .Sp | |
797 | .Vb 11 | |
798 | \& sub bind_param { | |
799 | \& my($sth, $pNum, $val, $attr) = @_; | |
800 | \& my $type = (ref $attr) ? $attr->{TYPE} : $attr; | |
801 | \& if ($type) { | |
802 | \& my $dbh = $sth->{Database}; | |
803 | \& $val = $dbh->quote($sth, $type); | |
804 | \& } | |
805 | \& my $params = $sth->FETCH('driver_params'); | |
806 | \& $params->[$pNum-1] = $val; | |
807 | \& 1; | |
808 | \& } | |
809 | .Ve | |
810 | .Sp | |
811 | .Vb 17 | |
812 | \& sub execute { | |
813 | \& my($sth, @bind_values) = @_; | |
814 | \& my $params = (@bind_values) ? | |
815 | \& \e@bind_values : $sth->FETCH('driver_params'); | |
816 | \& my $numParam = $sth->FETCH('NUM_OF_PARAMS'); | |
817 | \& if (@$params != $numParam) { ... } | |
818 | \& my $statement = $sth->{'Statement'}; | |
819 | \& for (my $i = 0; $i < $numParam; $i++) { | |
820 | \& $statement =~ s/?/$params->[$i]/e; | |
821 | \& } | |
822 | \& # Do anything ... we assume that an array ref of rows is | |
823 | \& # created and store it: | |
824 | \& $sth->{'driver_data'} = $data; | |
825 | \& $sth->{'driver_rows'} = @$data; # number of rows | |
826 | \& $sth->STORE('NUM_OF_FIELDS') = $numFields; | |
827 | \& @$data || '0E0'; | |
828 | \& } | |
829 | .Ve | |
830 | .Sp | |
831 | Things you should note here: We setup the \s-1NUM_OF_FIELDS\s0 attribute | |
832 | here, because this is essential for \fIbind_columns\fR to work. And | |
833 | we use attribute \fI$sth\-\fR{'Statement'}> which we have created | |
834 | within \fIprepare\fR. The attribute \fI$sth\-\fR{'Database'}>, which is | |
835 | nothing else than the \fIdbh\fR, was automatically created by \s-1DBI\s0. | |
836 | .Sp | |
837 | Finally note that we return the string '0E0' instead of the number | |
838 | 0, so that | |
839 | .Sp | |
840 | .Vb 1 | |
841 | \& if (!$sth->execute()) { die $sth->errstr } | |
842 | .Ve | |
843 | .Sp | |
844 | works. | |
845 | .IP "Fetching data" 2 | |
846 | .IX Item "Fetching data" | |
847 | We need not implement the methods \fIfetchrow_array\fR, \fIfetchall_arrayref\fR, | |
848 | \&... because these are already part of \s-1DBI\s0. All we need is the method | |
849 | \&\fIfetchrow_arrayref\fR: | |
850 | .Sp | |
851 | .Vb 11 | |
852 | \& sub fetchrow_arrayref { | |
853 | \& my($sth) = @_; | |
854 | \& my $data = $sth->FETCH('driver_data'); | |
855 | \& my $row = shift @$data; | |
856 | \& if (!$row) { return undef; } | |
857 | \& if ($sth->FETCH('ChopBlanks')) { | |
858 | \& map { $_ =~ s/\es+$//; } @$row; | |
859 | \& } | |
860 | \& return $sth->_set_fbav($row); | |
861 | \& } | |
862 | \& *fetch = \e&fetchrow_arrayref; # required alias for fetchrow_arrayref | |
863 | .Ve | |
864 | .Sp | |
865 | .Vb 1 | |
866 | \& sub rows { my($sth) = @_; $sth->FETCH('driver_rows'); } | |
867 | .Ve | |
868 | .Sp | |
869 | Note the use of the method \fI_set_fbav\fR: This is required so that | |
870 | \&\fIbind_col\fR and \fIbind_columns\fR work. | |
871 | .Sp | |
872 | Fixing the broken implementation for correct handling of quoted | |
873 | question marks is left as an exercise to the reader. :\-) | |
874 | .IP "Statement attributes" 2 | |
875 | .IX Item "Statement attributes" | |
876 | The main difference between dbh and sth attributes is, that you | |
877 | should implement a lot of attributes here that are required by | |
878 | the \s-1DBI:\s0 For example \fI\s-1NAME\s0\fR, \fI\s-1NULLABLE\s0\fR, \fI\s-1TYPE\s0\fR, ... | |
879 | .Sp | |
880 | Besides that the \s-1STORE\s0 and \s-1FETCH\s0 methods are mainly the same | |
881 | as above for dbh's. | |
882 | .IP "Other statement methods" 2 | |
883 | .IX Item "Other statement methods" | |
884 | A trivial \f(CW\*(C`finish\*(C'\fR method to discard the stored data and do | |
885 | \&\f(CW$sth\fR\->SUPER::finish; | |
886 | .Sp | |
887 | A \f(CW\*(C`table_info\*(C'\fR method to return details of available tables. | |
888 | .Sp | |
889 | A \f(CW\*(C`type_info_all\*(C'\fR method to return details of supported types. | |
890 | .Sp | |
891 | And perhaps some other methods that are not part of the \s-1DBI\s0 specs, in | |
892 | particular make metadata available. Considering Tim's last articles do | |
893 | yourself a favour and follow the \s-1ODBC\s0 driver. | |
894 | .Sh "Tests" | |
895 | .IX Subsection "Tests" | |
896 | The test process should conform as closely as possibly to the Perl | |
897 | standard test harness. | |
898 | .PP | |
899 | In particular, most of the tests should be run in the t sub\-directory, | |
900 | and should simply produce an 'ok' when run under 'make test'. | |
901 | For details on how this is done, see the Camel book and the section in | |
902 | Chapter 7, \*(L"The Standard Perl Library\*(R" on Test::Harness. | |
903 | .PP | |
904 | The tests may need to adapt to the type of database which is being | |
905 | used for testing, and to the privileges of the user testing the | |
906 | driver. | |
907 | .PP | |
908 | The DBD::Informix test code has to adapt in a number of places to the | |
909 | type of database to which it is connected as different Informix | |
910 | databases have different capabilities. | |
911 | .PP | |
912 | .Vb 1 | |
913 | \& [...More info TBS...] | |
914 | .Ve | |
915 | .SH "CREATING A NEW DRIVER USING C/XS" | |
916 | .IX Header "CREATING A NEW DRIVER USING C/XS" | |
917 | Creating a new C/XS driver from scratch will always be a daunting task. | |
918 | You can and should greatly simplify your task by taking a good | |
919 | reference driver implementation and modifying that to match the | |
920 | database product for which you are writing a driver. | |
921 | .PP | |
922 | The de facto reference driver has been the one for DBD::Oracle, written | |
923 | by Tim Bunce who is also the author of the \s-1DBI\s0 package. The DBD::Oracle | |
924 | module is a good example of a driver implemented around a C\-level \s-1API\s0. | |
925 | .PP | |
926 | Nowadays it it seems better to base on \s-1DBD::ODBC\s0, another driver | |
927 | maintained by Tim and Jeff Urlwin, because it offers a lot of metadata | |
928 | and seems to become the guideline for the future development. (Also as | |
929 | DBD::Oracle digs deeper into the Oracle 8 \s-1OCI\s0 interface it'll get even | |
930 | more hairly than it is now.) | |
931 | .PP | |
932 | The DBD::Informix driver is a good reference for a driver implemented | |
933 | using 'embedded \s-1SQL\s0'. DBD::Ingres may also be worth a look. | |
934 | .PP | |
935 | .Vb 1 | |
936 | \& [...More info TBS...] | |
937 | .Ve | |
938 | .Sh "\s-1REQUIREMENTS\s0 \s-1ON\s0 A \s-1DRIVER\s0" | |
939 | .IX Subsection "REQUIREMENTS ON A DRIVER" | |
940 | T.B.S. | |
941 | .Sh "\s-1CODE\s0 \s-1TO\s0 \s-1BE\s0 \s-1WRITTEN\s0" | |
942 | .IX Subsection "CODE TO BE WRITTEN" | |
943 | A minimal driver will typically contain 9 files plus some tests. | |
944 | Assuming that your driver is called DBD::Driver, these files are: | |
945 | .IP "Driver.pm" 4 | |
946 | .IX Item "Driver.pm" | |
947 | .PD 0 | |
948 | .IP "Driver.xs" 4 | |
949 | .IX Item "Driver.xs" | |
950 | .IP "Driver.h" 4 | |
951 | .IX Item "Driver.h" | |
952 | .IP "dbdimp.h" 4 | |
953 | .IX Item "dbdimp.h" | |
954 | .IP "dbdimp.c" 4 | |
955 | .IX Item "dbdimp.c" | |
956 | .IP "Makefile.PL" 4 | |
957 | .IX Item "Makefile.PL" | |
958 | .IP "\s-1README\s0" 4 | |
959 | .IX Item "README" | |
960 | .IP "\s-1MANIFEST\s0" 4 | |
961 | .IX Item "MANIFEST" | |
962 | .IP "lib/Bundle/DBD/Driver.pm" 4 | |
963 | .IX Item "lib/Bundle/DBD/Driver.pm" | |
964 | .PD | |
965 | .Sh "Driver.pm" | |
966 | .IX Subsection "Driver.pm" | |
967 | The Driver.pm file is the same as for Pure Perl modules, see above. | |
968 | However, there are some subtile differences: | |
969 | .IP "\(bu" 8 | |
970 | The variables \f(CW$DBD::File::dr\fR|db|st::imp_data_size are not defined | |
971 | here, but in the \s-1XS\s0 code, because they declare the size of certain | |
972 | C structures. | |
973 | .IP "\(bu" 8 | |
974 | Some methods are typically moved to the \s-1XS\s0 code, in particular | |
975 | \&\fIprepare\fR, \fIexecute\fR, \fIdisconnect\fR, \fIdisconnect_all\fR and the \s-1STORE\s0 | |
976 | and \s-1FETCH\s0 methods. | |
977 | .IP "\(bu" 8 | |
978 | Other methods are still part of \f(CW\*(C`Driver.pm\*(C'\fR, but have callbacks in | |
979 | the \s-1XS\s0 code. | |
980 | .PP | |
981 | Now let's take a closer look at an excerpt of Oracle.pm (around version | |
982 | 0.54, prior to Oracle 8 support) as an example. We ignore things that | |
983 | are already discussed for Pure Perl drivers or really Oracle specific. | |
984 | .IP "The database handle constructor" 2 | |
985 | .IX Item "The database handle constructor" | |
986 | .Vb 2 | |
987 | \& sub connect { | |
988 | \& my($drh, $dbname, $user, $auth)= @_; | |
989 | .Ve | |
990 | .Sp | |
991 | .Vb 4 | |
992 | \& # Some database specific verifications, default settings | |
993 | \& # and the like following here. This should only include | |
994 | \& # syntax checks or similar stuff where it's legal to | |
995 | \& # 'die' in case of errors. | |
996 | .Ve | |
997 | .Sp | |
998 | .Vb 5 | |
999 | \& # create a 'blank' dbh (call superclass constructor) | |
1000 | \& my $dbh = DBI::_new_dbh($drh, { | |
1001 | \& 'Name' => $dbname, | |
1002 | \& 'USER' => $user, 'CURRENT_USER' => $user, | |
1003 | \& }); | |
1004 | .Ve | |
1005 | .Sp | |
1006 | .Vb 4 | |
1007 | \& # Call Oracle OCI orlon func in Oracle.xs file | |
1008 | \& # and populate internal handle data. | |
1009 | \& DBD::Oracle::db::_login($dbh, $dbname, $user, $auth) | |
1010 | \& or return undef; | |
1011 | .Ve | |
1012 | .Sp | |
1013 | .Vb 2 | |
1014 | \& $dbh; | |
1015 | \& } | |
1016 | .Ve | |
1017 | .Sp | |
1018 | This is mostly the same as in the Pure Perl case, the exception being | |
1019 | the use of the private \fI_login\fR callback: This will really connect to | |
1020 | the database. It is implemented in Driver.xst (you should not implement | |
1021 | it) and calls \fIdbd_db_login\fR from \fIdbdimp.c\fR. See below for details. | |
1022 | .Sp | |
1023 | Since the DBI::_new_xxh methods can't fail in normal situations, we | |
1024 | don't both checking \f(CW$dbh\fR before calling _login. | |
1025 | .IP "The statement handle constructor" 2 | |
1026 | .IX Item "The statement handle constructor" | |
1027 | There's nothing much new in the statement handle constructor. Like | |
1028 | the \fIconnect\fR method it now has a C callback: | |
1029 | .Sp | |
1030 | .Vb 2 | |
1031 | \& package DBD::Oracle::db; # ====== DATABASE ====== | |
1032 | \& use strict; | |
1033 | .Ve | |
1034 | .Sp | |
1035 | .Vb 2 | |
1036 | \& sub prepare { | |
1037 | \& my($dbh, $statement, @attribs)= @_; | |
1038 | .Ve | |
1039 | .Sp | |
1040 | .Vb 4 | |
1041 | \& # create a 'blank' sth | |
1042 | \& my $sth = DBI::_new_sth($dbh, { | |
1043 | \& 'Statement' => $statement, | |
1044 | \& }); | |
1045 | .Ve | |
1046 | .Sp | |
1047 | .Vb 3 | |
1048 | \& # Call Oracle OCI oparse func in Oracle.xs file. | |
1049 | \& # (This will actually also call oopen for you.) | |
1050 | \& # and populate internal handle data. | |
1051 | .Ve | |
1052 | .Sp | |
1053 | .Vb 2 | |
1054 | \& DBD::Oracle::st::_prepare($sth, $statement, @attribs) | |
1055 | \& or return undef; | |
1056 | .Ve | |
1057 | .Sp | |
1058 | .Vb 2 | |
1059 | \& $sth; | |
1060 | \& } | |
1061 | .Ve | |
1062 | .Sh "Driver.xs" | |
1063 | .IX Subsection "Driver.xs" | |
1064 | Driver.xs should look something like this: | |
1065 | .PP | |
1066 | .Vb 1 | |
1067 | \& #include "Driver.h" | |
1068 | .Ve | |
1069 | .PP | |
1070 | .Vb 1 | |
1071 | \& DBISTATE_DECLARE; | |
1072 | .Ve | |
1073 | .PP | |
1074 | .Vb 1 | |
1075 | \& INCLUDE: Driver.xsi | |
1076 | .Ve | |
1077 | .PP | |
1078 | .Vb 1 | |
1079 | \& MODULE = DBD::Driver PACKAGE = DBD::Driver::db | |
1080 | .Ve | |
1081 | .PP | |
1082 | .Vb 3 | |
1083 | \& /* Non-standard dbh XS methods following here, if any. */ | |
1084 | \& /* Currently this includes things like _list_tables from */ | |
1085 | \& /* DBD::mSQL and DBD::mysql. */ | |
1086 | .Ve | |
1087 | .PP | |
1088 | .Vb 1 | |
1089 | \& MODULE = DBD::Driver PACKAGE = DBD::Driver::st | |
1090 | .Ve | |
1091 | .PP | |
1092 | .Vb 3 | |
1093 | \& /* Non-standard sth XS methods following here, if any. */ | |
1094 | \& /* In particular this includes things like _list_fields from */ | |
1095 | \& /* DBD::mSQL and DBD::mysql for accessing metadata. */ | |
1096 | .Ve | |
1097 | .PP | |
1098 | Note especially the include of \fIDriver.xsi\fR here: \s-1DBI\s0 inserts stub | |
1099 | functions for almost all private methods here which will typically | |
1100 | do much work for you. Wherever you really have to implement something, | |
1101 | it will call a private function in \fIdbdimp.c\fR: This is what you have | |
1102 | to implement. | |
1103 | .Sh "Driver.h" | |
1104 | .IX Subsection "Driver.h" | |
1105 | Driver.h should look like this: | |
1106 | .PP | |
1107 | .Vb 1 | |
1108 | \& #define NEED_DBIXS_VERSION 93 | |
1109 | .Ve | |
1110 | .PP | |
1111 | .Vb 1 | |
1112 | \& #include <DBIXS.h> /* installed by the DBI module */ | |
1113 | .Ve | |
1114 | .PP | |
1115 | .Vb 1 | |
1116 | \& #include "dbdimp.h" | |
1117 | .Ve | |
1118 | .PP | |
1119 | .Vb 1 | |
1120 | \& #include <dbd_xsh.h> /* installed by the DBI module */ | |
1121 | .Ve | |
1122 | .Sh "Implementation header dbdimp.h" | |
1123 | .IX Subsection "Implementation header dbdimp.h" | |
1124 | This header file has two jobs: | |
1125 | .PP | |
1126 | First it defines data structures for your private part of the handles. | |
1127 | .PP | |
1128 | Second it defines macros that rename the generic names like | |
1129 | \&\fIdbd_db_login\fR to database specific names like \fIora_db_login\fR. This | |
1130 | avoids name clashes and enables use of different drivers when you work | |
1131 | with a statically linked perl. | |
1132 | .PP | |
1133 | It also will have the important task of disabling \s-1XS\s0 methods that you | |
1134 | don't want to implement. | |
1135 | .PP | |
1136 | Finally, the macros will also be used to select alternate | |
1137 | implementations of some functions. For example, the currently defined | |
1138 | \&\f(CW\*(C`dbd_db_login\*(C'\fR function is not passed the attribute hash. In future, | |
1139 | if a dbd_db_login6 macro is defined (for a function with 6 arguments), | |
1140 | it will be used instead with the attribute hash passed at the sixth | |
1141 | argument. | |
1142 | .PP | |
1143 | People liked to just pick Oracle's dbdimp.c and use the same names, | |
1144 | structures and types. I strongly recommend against that: At first | |
1145 | glance this saves time, but your implementation will be less readable. | |
1146 | It was just a hell when I had to separate \s-1DBI\s0 specific parts, Oracle | |
1147 | specific parts, mSQL specific parts and mysql specific parts in | |
1148 | DBD::mysql's \fIdbdimp.h\fR and \fIdbdimp.c\fR. (DBD::mysql was a port of | |
1149 | DBD::mSQL which was based on DBD::Oracle.) This part of the driver | |
1150 | is \fIyour exclusive part\fR. Rewrite it from scratch, so it will be | |
1151 | clean and short, in other words: A better piece of code. (Of course | |
1152 | have an eye at other people's work.) | |
1153 | .PP | |
1154 | .Vb 2 | |
1155 | \& struct imp_drh_st { | |
1156 | \& dbih_drc_t com; /* MUST be first element in structure */ | |
1157 | .Ve | |
1158 | .PP | |
1159 | .Vb 2 | |
1160 | \& /* Insert your driver handle attributes here */ | |
1161 | \& }; | |
1162 | .Ve | |
1163 | .PP | |
1164 | .Vb 2 | |
1165 | \& struct imp_dbh_st { | |
1166 | \& dbih_dbc_t com; /* MUST be first element in structure */ | |
1167 | .Ve | |
1168 | .PP | |
1169 | .Vb 2 | |
1170 | \& /* Insert your database handle attributes here */ | |
1171 | \& }; | |
1172 | .Ve | |
1173 | .PP | |
1174 | .Vb 2 | |
1175 | \& struct imp_sth_st { | |
1176 | \& dbih_stc_t com; /* MUST be first element in structure */ | |
1177 | .Ve | |
1178 | .PP | |
1179 | .Vb 2 | |
1180 | \& /* Insert your statement handle attributes here */ | |
1181 | \& }; | |
1182 | .Ve | |
1183 | .PP | |
1184 | .Vb 6 | |
1185 | \& /* Rename functions for avoiding name clashes; prototypes are */ | |
1186 | \& /* in dbd_xst.h */ | |
1187 | \& #define dbd_init ora_init | |
1188 | \& #define dbd_db_login ora_db_login | |
1189 | \& #define dbd_db_do ora_db_do | |
1190 | \& ... many more here ... | |
1191 | .Ve | |
1192 | .PP | |
1193 | This structures implement your private part of the handles. You \fIhave\fR | |
1194 | to use the name \fIimp_dbh_dr|db|st\fR and the first field \fImust\fR be of | |
1195 | type \fIdbih_drc|dbc|stc_t\fR. You should never access this fields directly, | |
1196 | except of using the \fIDBIc_xxx\fR macros below. | |
1197 | .Sh "Implementation source dbdimp.c" | |
1198 | .IX Subsection "Implementation source dbdimp.c" | |
1199 | This is the main implementation file. I will drop a short note on any | |
1200 | function here that's used in the \fIDriver.xsi\fR template and thus \fBhas\fR | |
1201 | to be implemented. Of course you can add private or better static | |
1202 | functions here. | |
1203 | .PP | |
1204 | Note that most people are still using Kernighan & Ritchie syntax here. | |
1205 | I personally don't like this and especially in this documentation it | |
1206 | cannot be of harm, so let's use \s-1ANSI\s0. Finally Tim Bunce has announced | |
1207 | interest in moving the \s-1DBI\s0 sources to \s-1ANSI\s0 as well. | |
1208 | .IP "Initialization" 2 | |
1209 | .IX Item "Initialization" | |
1210 | .Vb 1 | |
1211 | \& #include "Driver.h" | |
1212 | .Ve | |
1213 | .Sp | |
1214 | .Vb 1 | |
1215 | \& DBISTATE_DECLARE; | |
1216 | .Ve | |
1217 | .Sp | |
1218 | .Vb 3 | |
1219 | \& void dbd_init(dbistate_t* dbistate) { | |
1220 | \& DBIS = dbistate; /* Initialize the DBI macros */ | |
1221 | \& } | |
1222 | .Ve | |
1223 | .Sp | |
1224 | dbd_init will be called when your driver is first loaded. These | |
1225 | statements are needed for use of the \s-1DBI\s0 macros. They will include your | |
1226 | private header file \fIdbdimp.h\fR in turn. | |
1227 | .IP "do_error" 2 | |
1228 | .IX Item "do_error" | |
1229 | You need a function to handle recording of errors. You can call it | |
1230 | whatever you like, but we'll call it \f(CW\*(C`do_error\*(C'\fR here. | |
1231 | .Sp | |
1232 | .Vb 1 | |
1233 | \& void do_error(SV* h, int rc, char* what) { | |
1234 | .Ve | |
1235 | .Sp | |
1236 | Note that \fIh\fR is a generic handle, may it be a driver handle, a | |
1237 | database or a statement handle. | |
1238 | .Sp | |
1239 | .Vb 1 | |
1240 | \& D_imp_xxh(h); | |
1241 | .Ve | |
1242 | .Sp | |
1243 | This macro will declare and initialize a variable \fIimp_xxh\fR with | |
1244 | a pointer to your private handle pointer. You may cast this to | |
1245 | to \fIimp_drh_t\fR, \fIimp_dbh_t\fR or \fIimp_sth_t\fR. | |
1246 | .Sp | |
1247 | .Vb 4 | |
1248 | \& SV *errstr = DBIc_ERRSTR(imp_xxh); | |
1249 | \& sv_setiv(DBIc_ERR(imp_xxh), (IV)rc); /* set err early */ | |
1250 | \& sv_setpv(errstr, what); | |
1251 | \& DBIh_EVENT2(h, ERROR_event, DBIc_ERR(imp_xxh), errstr); | |
1252 | .Ve | |
1253 | .Sp | |
1254 | Note the use of the macros DBIc_ERRSTR and DBIc_ERR for accessing the | |
1255 | handles error string and error code. | |
1256 | .Sp | |
1257 | The macro DBIh_EVENT2 will ensure that the attributes \fIRaiseError\fR | |
1258 | and \fIPrintError\fR work: That's all what you have to deal with them. :\-) | |
1259 | .Sp | |
1260 | .Vb 3 | |
1261 | \& if (dbis->debug >= 2) | |
1262 | \& fprintf(DBILOGFP, "%s error %d recorded: %s\en", | |
1263 | \& what, rc, SvPV(errstr,na)); | |
1264 | .Ve | |
1265 | .Sp | |
1266 | That's the first time we see how debug/trace logging works within a \s-1DBI\s0 | |
1267 | driver. Make use of this as often as you can! | |
1268 | .IP "dbd_db_login" 2 | |
1269 | .IX Item "dbd_db_login" | |
1270 | .Vb 2 | |
1271 | \& int dbd_db_login(SV* dbh, imp_dbh_t* imp_dbh, char* dbname, | |
1272 | \& char* user, char* auth) { | |
1273 | .Ve | |
1274 | .Sp | |
1275 | This function will really connect to the database. The argument \fIdbh\fR | |
1276 | is the database handle. \fIimp_dbh\fR is the pointer to the handles private | |
1277 | data, as is \fIimp_xxx\fR in \fIdo_error\fR above. The arguments \fIdsn\fR, | |
1278 | \&\fIuser\fR and \fIauth\fR correspond to the arguments of the driver handles | |
1279 | \&\fIconnect\fR method. | |
1280 | .Sp | |
1281 | You will quite often use database specific attributes here, that are | |
1282 | specified in the \s-1DSN\s0. I recommend you parse the \s-1DSN\s0 within the | |
1283 | \&\fIconnect\fR method and pass them as handle attributes to \fIdbd_db_login\fR. | |
1284 | Here's how you fetch them, as an example we use \fIhostname\fR and \fIport\fR | |
1285 | attributes: | |
1286 | .Sp | |
1287 | .Vb 8 | |
1288 | \& /* This code assumes that the *second* attribute parameter to | |
1289 | \& * DBI::_new_dbh was used to store an hash with login attributes | |
1290 | \& */ | |
1291 | \& SV* imp_data = DBIc_IMP_DATA(dbh); | |
1292 | \& HV* hv; | |
1293 | \& SV** svp; | |
1294 | \& char* hostname; | |
1295 | \& char* port; | |
1296 | .Ve | |
1297 | .Sp | |
1298 | .Vb 16 | |
1299 | \& if (!SvTRUE(imp_data) || !SvROK(imp_data) || | |
1300 | \& SvTYPE(hv = (HV*) SvRV(imp_data)) != SVt_PVHV) { | |
1301 | \& croak("Implementation dependent data invalid: Not a hash ref.\en"); | |
1302 | \& } | |
1303 | \& if ((svp = hv_fetch(hv, "hostname", strlen("hostname"), FALSE)) && | |
1304 | \& SvTRUE(*svp)) { | |
1305 | \& hostname = SvPV(*svp, na); | |
1306 | \& } else { | |
1307 | \& hostname = "localhost"; | |
1308 | \& } | |
1309 | \& if ((svp = hv_fetch(hv, "port", strlen("port"), FALSE)) && | |
1310 | \& SvTRUE(*svp)) { | |
1311 | \& port = SvPV(*svp, na); /* May be a service name */ | |
1312 | \& } else { | |
1313 | \& port = DEFAULT_PORT; | |
1314 | \& } | |
1315 | .Ve | |
1316 | .Sp | |
1317 | Now you should really connect to the database. If you are successful | |
1318 | (or even if you fail, but you have allocated some resources), you should | |
1319 | use the following macros: | |
1320 | .Sp | |
1321 | .Vb 1 | |
1322 | \& DBIc_IMPSET_on(imp_dbh); | |
1323 | .Ve | |
1324 | .Sp | |
1325 | This indicates that the driver (implementor) has allocated resources in | |
1326 | the imp_dbh structure and that the implementors private dbd_db_destroy | |
1327 | function should be called when the handle is destroyed. | |
1328 | .Sp | |
1329 | .Vb 1 | |
1330 | \& DBIc_ACTIVE_on(imp_dbh); | |
1331 | .Ve | |
1332 | .Sp | |
1333 | This indicates that the handle has an active connection to the server | |
1334 | and that the dbd_db_disconnect function should be called before the | |
1335 | handle is destroyed. | |
1336 | .Sp | |
1337 | The dbd_db_login function should return \s-1TRUE\s0 for success, \s-1FALSE\s0 otherwise. | |
1338 | .IP "dbd_db_commit" 2 | |
1339 | .IX Item "dbd_db_commit" | |
1340 | .PD 0 | |
1341 | .IP "dbd_db_rollback" 2 | |
1342 | .IX Item "dbd_db_rollback" | |
1343 | .PD | |
1344 | .Vb 2 | |
1345 | \& int dbd_db_commit( SV* dbh, imp_dbh_t* imp_dbh ); | |
1346 | \& int dbd_db_rollback( SV* dbh, imp_dbh_t* imp_dbh ); | |
1347 | .Ve | |
1348 | .Sp | |
1349 | These are used for commit and rollback. They should return \s-1TRUE\s0 for | |
1350 | success, \s-1FALSE\s0 for error. | |
1351 | .Sp | |
1352 | The arguments \fIdbh\fR and \fIimp_dbh\fR are like above, I will omit | |
1353 | describing them in what follows, as they appear always. | |
1354 | .IP "dbd_db_disconnect" 2 | |
1355 | .IX Item "dbd_db_disconnect" | |
1356 | This is your private part of the \fIdisconnect\fR method. Any dbh with | |
1357 | the \fI\s-1ACTIVE\s0\fR flag on must be disconnected. (Note that you have to set | |
1358 | it in \fIdbd_db_connect\fR above.) | |
1359 | .Sp | |
1360 | .Vb 1 | |
1361 | \& int dbd_db_disconnect(SV* dbh, imp_dbh_t* imp_dbh); | |
1362 | .Ve | |
1363 | .Sp | |
1364 | The database handle will return \s-1TRUE\s0 for success, \s-1FALSE\s0 otherwise. | |
1365 | In any case it should do a | |
1366 | .Sp | |
1367 | .Vb 1 | |
1368 | \& DBIc_ACTIVE_off(imp_dbh); | |
1369 | .Ve | |
1370 | .Sp | |
1371 | before returning so \s-1DBI\s0 knows that \fIdbd_db_disconnect\fR was executed. | |
1372 | .IP "dbd_db_discon_all" 2 | |
1373 | .IX Item "dbd_db_discon_all" | |
1374 | .Vb 1 | |
1375 | \& int dbd_discon_all (SV *drh, imp_drh_t *imp_drh) { | |
1376 | .Ve | |
1377 | .Sp | |
1378 | This function may be called at shutdown time. It should make | |
1379 | best-efforts to disconnect all database handles \- if possible. Some | |
1380 | databases don't support that, in which case you can do nothing | |
1381 | but return 'success'. | |
1382 | .Sp | |
1383 | You guess what the return codes are? (Hint: See the last functions | |
1384 | above ... :\-) | |
1385 | .IP "dbd_db_destroy" 2 | |
1386 | .IX Item "dbd_db_destroy" | |
1387 | This is your private part of the database handle destructor. Any dbh with | |
1388 | the \fI\s-1IMPSET\s0\fR flag on must be destroyed, so that you can safely free | |
1389 | resources. (Note that you have to set it in \fIdbd_db_connect\fR above.) | |
1390 | .Sp | |
1391 | .Vb 3 | |
1392 | \& void dbd_db_destroy(SV* dbh, imp_dbh_t* imp_dbh) { | |
1393 | \& DBIc_IMPSET_off(imp_dbh); | |
1394 | \& } | |
1395 | .Ve | |
1396 | .Sp | |
1397 | The \s-1DBI\s0 Driver.xst code will have called dbd_db_disconnect for you, | |
1398 | if the handle is still 'active', before calling dbd_db_destroy. | |
1399 | .Sp | |
1400 | Before returning the function must switch \s-1IMPSET\s0 to off, so \s-1DBI\s0 knows | |
1401 | that the destructor was called. | |
1402 | .IP "dbd_db_STORE_attrib" 2 | |
1403 | .IX Item "dbd_db_STORE_attrib" | |
1404 | This function handles | |
1405 | .Sp | |
1406 | .Vb 1 | |
1407 | \& $dbh->{$key} = $value; | |
1408 | .Ve | |
1409 | .Sp | |
1410 | its prototype is | |
1411 | .Sp | |
1412 | .Vb 2 | |
1413 | \& int dbd_db_STORE_attrib(SV* dbh, imp_dbh_t* imp_dbh, SV* keysv, | |
1414 | \& SV* valuesv); | |
1415 | .Ve | |
1416 | .Sp | |
1417 | You do not handle all attributes, in contrary you should not handle | |
1418 | \&\s-1DBI\s0 attributes here: Leave this to \s-1DBI\s0. (There's one exception, | |
1419 | \&\fIAutoCommit\fR, which you should care about.) | |
1420 | .Sp | |
1421 | The return value is \s-1TRUE\s0, if you have handled the attribute or \s-1FALSE\s0 | |
1422 | otherwise. If you are handling an attribute and something fails, you | |
1423 | should call \fIdo_error\fR, so \s-1DBI\s0 can raise exceptions, if desired. | |
1424 | If \fIdo_error\fR returns, however, you have a problem: The user will | |
1425 | never know about the error, because he typically will not check | |
1426 | \&\f(CW\*(C`$dbh\->errstr\*(C'\fR. | |
1427 | .Sp | |
1428 | I cannot recommend a general way of going on, if \fIdo_error\fR returns, | |
1429 | but there are examples where even the \s-1DBI\s0 specification expects that | |
1430 | you \fIcroak()\fR. (See the \fIAutoCommit\fR method in \s-1\fIDBI\s0\fR\|(3).) | |
1431 | .Sp | |
1432 | If you have to store attributes, you should either use your private | |
1433 | data structure imp_xxx, the handle hash (via (HV*)SvRV(dbh)), or use | |
1434 | the private imp_data. | |
1435 | .Sp | |
1436 | The first is best for internal C values like integers or pointers and | |
1437 | where speed is important within the driver. The handle hash is best for | |
1438 | values the user may want to get/set via driver-specific attributes. | |
1439 | The private imp_data is an additional \s-1SV\s0 attached to the handle. You | |
1440 | could think of it as an unnamed handle attribute. It's not normally used. | |
1441 | .IP "dbd_db_FETCH_attrib" 2 | |
1442 | .IX Item "dbd_db_FETCH_attrib" | |
1443 | This is the counterpart of dbd_db_STORE_attrib, needed for | |
1444 | .Sp | |
1445 | .Vb 1 | |
1446 | \& $value = $dbh->{$key}; | |
1447 | .Ve | |
1448 | .Sp | |
1449 | Its prototype is: | |
1450 | .Sp | |
1451 | .Vb 1 | |
1452 | \& SV* dbd_db_FETCH_attrib(SV* dbh, imp_dbh_t* imp_dbh, SV* keysv) { | |
1453 | .Ve | |
1454 | .Sp | |
1455 | Unlike all previous methods this returns an \s-1SV\s0 with the value. Note | |
1456 | that you should normally execute sv_2mortal, if you return a nonconstant | |
1457 | value. (Constant values are \f(CW&sv_undef\fR, \f(CW&sv_no\fR and \f(CW&sv_yes\fR.) | |
1458 | .Sp | |
1459 | Note, that \s-1DBI\s0 implements a caching algorithm for attribute values. | |
1460 | If you think, that an attribute may be fetched, you store it in the | |
1461 | dbh itself: | |
1462 | .Sp | |
1463 | .Vb 2 | |
1464 | \& if (cacheit) /* cache value for later DBI 'quick' fetch? */ | |
1465 | \& hv_store((HV*)SvRV(dbh), key, kl, cachesv, 0); | |
1466 | .Ve | |
1467 | .IP "dbd_st_prepare" 2 | |
1468 | .IX Item "dbd_st_prepare" | |
1469 | This is the private part of the \fIprepare\fR method. Note that you | |
1470 | \&\fBmust not\fR really execute the statement here. You may, for example, | |
1471 | preparse and validate the statement or do similar things. | |
1472 | .Sp | |
1473 | .Vb 2 | |
1474 | \& int dbd_st_prepare(SV* sth, imp_sth_t* imp_sth, char* statement, | |
1475 | \& SV* attribs); | |
1476 | .Ve | |
1477 | .Sp | |
1478 | A typical, simple possibility is just to store the statement in the | |
1479 | imp_data hash ref and use it in dbd_st_execute. If you can, you should | |
1480 | setup attributes like \s-1NUM_OF_FIELDS\s0, \s-1NAME\s0, ... here, but \s-1DBI\s0 | |
1481 | doesn't require that. However, if you do, document it. | |
1482 | .Sp | |
1483 | In any case you should set the \s-1IMPSET\s0 flag, as you did in | |
1484 | \&\fIdbd_db_connect\fR above: | |
1485 | .Sp | |
1486 | .Vb 1 | |
1487 | \& DBIc_IMPSET_on(imp_sth); | |
1488 | .Ve | |
1489 | .IP "dbd_st_execute" 2 | |
1490 | .IX Item "dbd_st_execute" | |
1491 | This is where a statement will really be executed. | |
1492 | .Sp | |
1493 | .Vb 1 | |
1494 | \& int dbd_st_execute(SV* sth, imp_sth_t* imp_sth); | |
1495 | .Ve | |
1496 | .Sp | |
1497 | Note, that you must be aware, that a statement may be executed repeatedly. | |
1498 | Also, you should not expect, that \fIfinish\fR will be called between | |
1499 | two executions. | |
1500 | .Sp | |
1501 | If your driver supports binding of parameters (he should!), but the | |
1502 | database doesn't, you must probably do it here. This can be done as | |
1503 | follows: | |
1504 | .Sp | |
1505 | .Vb 7 | |
1506 | \& char* statement = dbd_st_get_statement(sth, imp_sth); | |
1507 | \& /* Its your drivers task to implement this function. It */ | |
1508 | \& /* must restore the statement passed to preparse. */ | |
1509 | \& /* See use of imp_data above for an example of how to do */ | |
1510 | \& /* this. */ | |
1511 | \& int numParam = DBIc_NUM_PARAMS(imp_sth); | |
1512 | \& int i; | |
1513 | .Ve | |
1514 | .Sp | |
1515 | .Vb 10 | |
1516 | \& for (i = 0; i < numParam; i++) { | |
1517 | \& char* value = dbd_db_get_param(sth, imp_sth, i); | |
1518 | \& /* Its your drivers task to implement dbd_db_get_param, */ | |
1519 | \& /* it must be setup as a counterpart of dbd_bind_ph. */ | |
1520 | \& /* Look for '?' and replace it with 'value'. Difficult */ | |
1521 | \& /* task, note that you may have question marks inside */ | |
1522 | \& /* quotes and the like ... :-( */ | |
1523 | \& /* See DBD::mysql for an example. (Don't look too deep into */ | |
1524 | \& /* the example, you will notice where I was lazy ...) */ | |
1525 | \& } | |
1526 | .Ve | |
1527 | .Sp | |
1528 | The next thing is you really execute the statement. Note that you must | |
1529 | prepare the attributes \s-1NUM_OF_FIELDS\s0, \s-1NAME\s0, ... when the statement is | |
1530 | successfully executed if you have not already done so: They may be used even before a potential | |
1531 | \&\fIfetchrow\fR. In particular you have to tell \s-1DBI\s0 the number of fields, | |
1532 | that the statement has, because it will be used by \s-1DBI\s0 internally. | |
1533 | Thus the function will typically ends with: | |
1534 | .Sp | |
1535 | .Vb 4 | |
1536 | \& if (isSelectStatement) { | |
1537 | \& DBIc_NUM_FIELDS(imp_sth) = numFields; | |
1538 | \& DBIc_ACTIVE_on(imp_sth); | |
1539 | \& } | |
1540 | .Ve | |
1541 | .Sp | |
1542 | It is important that the \s-1ACTIVE\s0 flag only be set for select statements. | |
1543 | See \fIdbd_st_preparse\fR and \fIdbd_db_connect\fR above for more explanations. | |
1544 | .IP "dbd_st_fetch" 2 | |
1545 | .IX Item "dbd_st_fetch" | |
1546 | This function fetches a row of data. The row is stored in in an array, | |
1547 | of \s-1SV\s0's that \s-1DBI\s0 prepares for you. This has two advantages: It is fast | |
1548 | (you even reuse the \s-1SV\s0's, so they don't have to be created after the | |
1549 | first fetchrow) and it guarantees, that \s-1DBI\s0 handles \fIbind_cols\fR for | |
1550 | you. | |
1551 | .Sp | |
1552 | What you do is the following: | |
1553 | .Sp | |
1554 | .Vb 6 | |
1555 | \& AV* av; | |
1556 | \& int numFields = DBIc_NUM_FIELDS(imp_sth); /* Correct, if NUM_FIELDS | |
1557 | \& is constant for this statement. There are drivers where this is | |
1558 | \& not the case! */ | |
1559 | \& int chopBlanks = DBIc_is(imp_sth, DBIcf_ChopBlanks); | |
1560 | \& int i; | |
1561 | .Ve | |
1562 | .Sp | |
1563 | .Vb 17 | |
1564 | \& if (!fetch_new_row_of_data(...)) { | |
1565 | \& ... /* check for error or end-of-data */ | |
1566 | \& DBIc_ACTIVE_off(imp_sth); /* turn off Active flag automatically */ | |
1567 | \& return Nullav; | |
1568 | \& } | |
1569 | \& /* get the fbav (field buffer array value) for this row */ | |
1570 | \& /* it is very important to only call this after you know */ | |
1571 | \& /* that you have a row of data to return. */ | |
1572 | \& av = DBIS->get_fbav(imp_sth); | |
1573 | \& for (i = 0; i < numFields; i++) { | |
1574 | \& SV* sv = fetch_a_field(..., i); | |
1575 | \& if (chopBlanks && SvOK(sv) && type_is_blank_padded(field_type[i])) { | |
1576 | \& /* Remove white space from end (only) of sv */ | |
1577 | \& } | |
1578 | \& sv_setsv(AvARRAY(av)[i], sv); /* Note: (re)use! */ | |
1579 | \& } | |
1580 | \& return av; | |
1581 | .Ve | |
1582 | .Sp | |
1583 | There's no need to use a fetch_a_field function returning an SV*. | |
1584 | It's more common to use your database \s-1API\s0 functions to fetch the | |
1585 | data as character strings and use code like this: | |
1586 | .Sp | |
1587 | .Vb 1 | |
1588 | \& sv_setpvn(AvARRAY(av)[i], char_ptr, char_count); | |
1589 | .Ve | |
1590 | .Sp | |
1591 | \&\s-1NULL\s0 values must be returned as undef. You can use code like this: | |
1592 | .Sp | |
1593 | .Vb 1 | |
1594 | \& SvOK_off(AvARRAY(av)[i]); | |
1595 | .Ve | |
1596 | .Sp | |
1597 | The function returns the \s-1AV\s0 prepared by \s-1DBI\s0 for success or \f(CW\*(C`Nullav\*(C'\fR | |
1598 | otherwise. | |
1599 | .IP "dbd_st_finish" 2 | |
1600 | .IX Item "dbd_st_finish" | |
1601 | This function can be called if the user wishes to indicate that no | |
1602 | more rows will be fetched even if the server has more rows to offer. | |
1603 | See the \s-1DBI\s0 docs for more background details. | |
1604 | .Sp | |
1605 | All it \fIneeds\fR to do is turn off the Active flag for the sth. | |
1606 | It will only be called by Driver.xst code, if the driver has set | |
1607 | \&\s-1ACTIVE\s0 to on for the sth. | |
1608 | .Sp | |
1609 | Minimal example (the \s-1DBI\s0 default method just does this): | |
1610 | .Sp | |
1611 | .Vb 4 | |
1612 | \& int dbd_st_finish(SV* sth, imp_sth_t* imp_sth) { | |
1613 | \& DBIc_ACTIVE_off(imp_sth); | |
1614 | \& return 1; | |
1615 | \& } | |
1616 | .Ve | |
1617 | .Sp | |
1618 | The function returns \s-1TRUE\s0 for success, \s-1FALSE\s0 otherwise. | |
1619 | .IP "dbd_st_destroy" 2 | |
1620 | .IX Item "dbd_st_destroy" | |
1621 | This function is the private part of the statement handle destructor. | |
1622 | .Sp | |
1623 | .Vb 4 | |
1624 | \& void dbd_st_destroy(SV* sth, imp_sth_t* imp_sth); | |
1625 | \& ... /* any clean-up that's needed */ | |
1626 | \& DBIc_IMPSET_off(imp_sth); /* let DBI know we've done it */ | |
1627 | \& } | |
1628 | .Ve | |
1629 | .Sp | |
1630 | The \s-1DBI\s0 Driver.xst code will call dbd_st_finish for you, if the sth has | |
1631 | the \s-1ACTIVE\s0 flag set, before calling dbd_st_destroy. | |
1632 | .IP "dbd_st_STORE_attrib" 2 | |
1633 | .IX Item "dbd_st_STORE_attrib" | |
1634 | .PD 0 | |
1635 | .IP "dbd_st_FETCH_attrib" 2 | |
1636 | .IX Item "dbd_st_FETCH_attrib" | |
1637 | .PD | |
1638 | These functions correspond to dbd_db_STORE|FETCH attrib above, except | |
1639 | that they are for statement handles. See above. | |
1640 | .Sp | |
1641 | .Vb 3 | |
1642 | \& int dbd_st_STORE_attrib(SV* sth, imp_sth_t* imp_sth, SV* keysv, | |
1643 | \& SV* valuesv); | |
1644 | \& SV* dbd_st_FETCH_attrib(SV* sth, imp_sth_t* imp_sth, SV* keysv); | |
1645 | .Ve | |
1646 | .IP "dbd_bind_ph" 2 | |
1647 | .IX Item "dbd_bind_ph" | |
1648 | This function is internally used by the \fIbind_param\fR method, the | |
1649 | \&\fIbind_param_inout\fR method and by the \s-1DBI\s0 Driver.xst code if \f(CW\*(C`execute\*(C'\fR | |
1650 | is called with any bind parameters. | |
1651 | .Sp | |
1652 | .Vb 3 | |
1653 | \& int dbd_bind_ph (SV *sth, imp_sth_t *imp_sth, SV *param, | |
1654 | \& SV *value, IV sql_type, SV *attribs, | |
1655 | \& int is_inout, IV maxlen); | |
1656 | .Ve | |
1657 | .Sp | |
1658 | The \fIparam\fR argument holds an \s-1IV\s0 with the parameter number (1, 2, ...). | |
1659 | The \fIvalue\fR argument is the parameter value and \fIsql_type\fR is its type. | |
1660 | .Sp | |
1661 | If your driver does not support bind_param_inout then you should | |
1662 | ignore \fImaxlen\fR and croak if \fIis_inout\fR is \s-1TRUE\s0. | |
1663 | .Sp | |
1664 | If your driver \fIdoes\fR support bind_param_inout then you should | |
1665 | note that \fIvalue\fR is the \s-1SV\s0 \fIafter\fR dereferencing the reference | |
1666 | passed to bind_param_inout. | |
1667 | .Sp | |
1668 | In drivers of simple databases the function will, for example, store | |
1669 | the value in a parameter array and use it later in \fIdbd_st_execute\fR. | |
1670 | See the \fIDBD::mysql\fR driver for an example. | |
1671 | .Sh "Implementing bind_param_inout support" | |
1672 | .IX Subsection "Implementing bind_param_inout support" | |
1673 | To provide support for parameters bound by reference rather than by | |
1674 | value, the driver must do a number of things. First, and most | |
1675 | importantly, it must note the references and stash them in its own | |
1676 | driver structure. Secondly, when a value is bound to a column, the | |
1677 | driver must discard any previous reference bound to the column. On | |
1678 | each execute, the driver must evaluate the references and internally | |
1679 | bind the values resulting from the references. This is only applicable | |
1680 | if the user writes: | |
1681 | .PP | |
1682 | .Vb 1 | |
1683 | \& $sth->execute; | |
1684 | .Ve | |
1685 | .PP | |
1686 | If the user writes: | |
1687 | .PP | |
1688 | .Vb 1 | |
1689 | \& $sth->execute(@values); | |
1690 | .Ve | |
1691 | .PP | |
1692 | then \s-1DBI\s0 automatically calls the binding code for each element of | |
1693 | \&\f(CW@values\fR. These calls are indistinguishable from explicit user calls to | |
1694 | bind_param. | |
1695 | .Sh "Makefile.PL" | |
1696 | .IX Subsection "Makefile.PL" | |
1697 | This is exactly as in the Pure Perl case. To be honest, the above | |
1698 | Makefile.PL contains some things that are superfluous for Pure Perl | |
1699 | drivers. :\-) | |
1700 | .SH "METHODS WHICH DO NOT NEED TO BE WRITTEN" | |
1701 | .IX Header "METHODS WHICH DO NOT NEED TO BE WRITTEN" | |
1702 | The \s-1DBI\s0 code implements the majority of the methods which are | |
1703 | accessed using the notation \s-1DBI\-\s0>\fIfunction()\fR, the only exceptions being | |
1704 | \&\s-1DBI\-\s0>\fIconnect()\fR and \s-1DBI\-\s0>\fIdata_sources()\fR which require support from the | |
1705 | driver. | |
1706 | .PP | |
1707 | The \s-1DBI\s0 code implements the following documented driver, database and | |
1708 | statement functions which do not need to be written by the \s-1DBD\s0 driver | |
1709 | writer. | |
1710 | .IP "$dbh\->\fIdo()\fR" 4 | |
1711 | .IX Item "$dbh->do()" | |
1712 | The default implementation of this function prepares, executes and | |
1713 | destroys the statement. This can be replaced if there is a better | |
1714 | way to implement this, such as \s-1EXECUTE\s0 \s-1IMMEDIATE\s0 which can | |
1715 | sometimes be used if there are no parameters. | |
1716 | .IP "$h\->\fIerrstr()\fR" 4 | |
1717 | .IX Item "$h->errstr()" | |
1718 | .PD 0 | |
1719 | .IP "$h\->\fIerr()\fR" 4 | |
1720 | .IX Item "$h->err()" | |
1721 | .IP "$h\->\fIstate()\fR" 4 | |
1722 | .IX Item "$h->state()" | |
1723 | .IP "$h\->\fItrace()\fR" 4 | |
1724 | .IX Item "$h->trace()" | |
1725 | .PD | |
1726 | The \s-1DBD\s0 driver does not need to worry about these routines at all. | |
1727 | .IP "$h\->{ChopBlanks}" 4 | |
1728 | .IX Item "$h->{ChopBlanks}" | |
1729 | This attribute needs to be honured during fetch operations, but does | |
1730 | not need to be handled by the attribute handling code. | |
1731 | .IP "$h\->{RaiseError}" 4 | |
1732 | .IX Item "$h->{RaiseError}" | |
1733 | The \s-1DBD\s0 driver does not need to worry about this attribute at all. | |
1734 | .IP "$h\->{PrintError}" 4 | |
1735 | .IX Item "$h->{PrintError}" | |
1736 | The \s-1DBD\s0 driver does not need to worry about this attribute at all. | |
1737 | .IP "$sth\->\fIbind_col()\fR" 4 | |
1738 | .IX Item "$sth->bind_col()" | |
1739 | Assuming the driver uses the \s-1DBIS\-\s0>\fIget_fbav()\fR function (C drivers, | |
1740 | see below), or the \f(CW$sth\fR\->_set_fbav($data) method (Perl drivers) | |
1741 | the driver does not need to do anything about this routine. | |
1742 | .IP "$sth\->\fIbind_columns()\fR" 4 | |
1743 | .IX Item "$sth->bind_columns()" | |
1744 | Regardless of whether the driver uses \s-1DBIS\-\s0>\fIget_fbav()\fR, the driver | |
1745 | does not need to do anything about this routine as it simply | |
1746 | iteratively calls \f(CW$sth\fR\->\fIbind_col()\fR. | |
1747 | .PP | |
1748 | The \s-1DBI\s0 code implements a default implementation of the following | |
1749 | functions which do not need to be written by the \s-1DBD\s0 driver writer | |
1750 | unless the default implementation is incorrect for the Driver. | |
1751 | .IP "$dbh\->\fIquote()\fR" 4 | |
1752 | .IX Item "$dbh->quote()" | |
1753 | This should only be written if the database does not accept the \s-1ANSI\s0 | |
1754 | \&\s-1SQL\s0 standard for quoting strings, with the string enclosed in single | |
1755 | quotes and any embedded single quotes replaced by two consecutive | |
1756 | single quotes. | |
1757 | .Sp | |
1758 | For the two argument form of quote, you need to implement the | |
1759 | \&\f(CW\*(C`type_info\*(C'\fR method to provide the information that quote needs. | |
1760 | .IP "$dbh\->\fIping()\fR" 4 | |
1761 | .IX Item "$dbh->ping()" | |
1762 | This should be implemented as a simple efficient way to determine | |
1763 | whether the connection to the database is still alive. Typically | |
1764 | code like this: | |
1765 | .Sp | |
1766 | .Vb 9 | |
1767 | \& sub ping { | |
1768 | \& my $dbh = shift; | |
1769 | \& $sth = $dbh->prepare_cached(q{ | |
1770 | \& select * from A_TABLE_NAME where 1=0 | |
1771 | \& }) or return 0; | |
1772 | \& $sth->execute or return 0; | |
1773 | \& $sth->finish; | |
1774 | \& return 1; | |
1775 | \& } | |
1776 | .Ve | |
1777 | .Sp | |
1778 | where A_TABLE_NAME is the name of a table that always exists (such as a | |
1779 | database system catalogue). | |
1780 | .SH "WRITING AN EMULATION LAYER FOR AN OLD PERL INTERFACE" | |
1781 | .IX Header "WRITING AN EMULATION LAYER FOR AN OLD PERL INTERFACE" | |
1782 | Study Oraperl.pm (supplied with DBD::Oracle) and Ingperl.pm (supplied | |
1783 | with DBD::Ingres) and the corresponding dbdimp.c files for ideas. | |
1784 | .PP | |
1785 | Note that the emulation code sets \f(CW$dbh\fR\->{CompatMode} = 1; for each | |
1786 | connection so that the internals of the driver can implement behaviour | |
1787 | compatible with the old interface when dealing with those handles. | |
1788 | .Sh "Setting emulation perl variables" | |
1789 | .IX Subsection "Setting emulation perl variables" | |
1790 | For example, ingperl has a \f(CW$sql_rowcount\fR variable. Rather than try | |
1791 | to manually update this in Ingperl.pm it can be done faster in C code. | |
1792 | In \fIdbd_init()\fR: | |
1793 | .PP | |
1794 | .Vb 1 | |
1795 | \& sql_rowcount = perl_get_sv("Ingperl::sql_rowcount", GV_ADDMULTI); | |
1796 | .Ve | |
1797 | .PP | |
1798 | In the relevant places do: | |
1799 | .PP | |
1800 | .Vb 2 | |
1801 | \& if (DBIc_COMPAT(imp_sth)) /* only do this for compatibility mode handles */ | |
1802 | \& sv_setiv(sql_rowcount, the_row_count); | |
1803 | .Ve | |
1804 | .SH "OTHER MISCELLANEOUS INFORMATION" | |
1805 | .IX Header "OTHER MISCELLANEOUS INFORMATION" | |
1806 | .Sh "The imp_xyz_t types" | |
1807 | .IX Subsection "The imp_xyz_t types" | |
1808 | Any handle has a corresponding C structure filled with private data. | |
1809 | Some of this data is reserved for use by \s-1DBI\s0 (except for using the | |
1810 | DBIc macros below), some is for you. See the description of the | |
1811 | \&\fIdbdimp.h\fR file above for examples. The most functions in dbdimp.c | |
1812 | are passed both the handle \f(CW\*(C`xyz\*(C'\fR and a pointer to \f(CW\*(C`imp_xyz\*(C'\fR. In | |
1813 | rare cases, however, you may use the following macros: | |
1814 | .IP "D_imp_dbh(dbh)" 2 | |
1815 | .IX Item "D_imp_dbh(dbh)" | |
1816 | Given a function argument \fIdbh\fR, declare a variable \fIimp_dbh\fR and | |
1817 | initialize it with a pointer to the handles private data. Note: This | |
1818 | must be a part of the function header, because it declares a variable. | |
1819 | .IP "D_imp_sth(sth)" 2 | |
1820 | .IX Item "D_imp_sth(sth)" | |
1821 | Likewise for statement handles. | |
1822 | .IP "D_imp_xxx(h)" 2 | |
1823 | .IX Item "D_imp_xxx(h)" | |
1824 | Given any handle, declare a variable \fIimp_xxx\fR and initialize it | |
1825 | with a pointer to the handles private data. It is safe, for example, | |
1826 | to cast \fIimp_xxx\fR to \f(CW\*(C`imp_dbh_t*\*(C'\fR, if DBIc_TYPE(imp_xxx) == DBIt_DB. | |
1827 | (You can also call sv_derived_from(h, \*(L"DBI::db\*(R"), but that's much | |
1828 | slower.) | |
1829 | .IP "D_imp_sth_from_dbh" 2 | |
1830 | .IX Item "D_imp_sth_from_dbh" | |
1831 | Given a imp_sth, declare a variable \fIimp_dbh\fR and initialize it with a | |
1832 | pointer to the parent database handles implementors structure. | |
1833 | .Sh "Using DBIc_IMPSET_on" | |
1834 | .IX Subsection "Using DBIc_IMPSET_on" | |
1835 | The driver code which initializes a handle should use \fIDBIc_IMPSET_on()\fR | |
1836 | as soon as its state is such that the cleanup code must be called. | |
1837 | When this happens is determined by your driver code. | |
1838 | .PP | |
1839 | Failure to call this can lead to corruption of data structures. | |
1840 | For example, DBD::Informix maintains a linked list of database handles | |
1841 | in the driver, and within each handle, a linked list of statements. | |
1842 | Once a statement is added to the linked list, it is crucial that it is | |
1843 | cleaned up (removed from the list). | |
1844 | When \fIDBIc_IMPSET_on()\fR was being called too late, it was able to cause | |
1845 | all sorts of problems. | |
1846 | .Sh "Using \fIDBIc_is()\fP, \fIDBIc_has()\fP, \fIDBIc_on()\fP and \fIDBIc_off()\fP" | |
1847 | .IX Subsection "Using DBIc_is(), DBIc_has(), DBIc_on() and DBIc_off()" | |
1848 | Once upon a long time ago, the only way of handling the internal \s-1DBI\s0 | |
1849 | boolean flags/attributes was through macros such as: | |
1850 | .PP | |
1851 | .Vb 2 | |
1852 | \& DBIc_WARN DBIc_WARN_on DBIc_WARN_off | |
1853 | \& DBIc_COMPAT DBIc_COMPAT_on DBIc_COMPAT_off | |
1854 | .Ve | |
1855 | .PP | |
1856 | Each of these took an imp_xxh pointer as an argument. | |
1857 | .PP | |
1858 | Since then, new attributes have been added such as ChopBlanks, | |
1859 | RaiseError and PrintError, and these do not have the full set of | |
1860 | macros. | |
1861 | The approved method for handling these is now the four macros: | |
1862 | .PP | |
1863 | .Vb 4 | |
1864 | \& DBIc_is(imp, flag) | |
1865 | \& DBIc_has(imp, flag) an alias for DBIc_is | |
1866 | \& DBIc_on(imp, flag) | |
1867 | \& DBIc_off(imp, flag) | |
1868 | .Ve | |
1869 | .PP | |
1870 | Consequently, the DBIc_XXXXX family of macros is now mostly deprecated | |
1871 | and new drivers should avoid using them, even though the older drivers | |
1872 | will probably continue to do so for quite a while yet. However... | |
1873 | .PP | |
1874 | There is an \fIimportant exception\fR to that. The \s-1ACTIVE\s0 and \s-1IMPSET\s0 | |
1875 | flags should be set via the DBIc_ACTIVE_on and DBIc_IMPSET_on macros, | |
1876 | and unset via the DBIc_ACTIVE_off and DBIc_IMPSET_off macros. | |
1877 | .Sh "Using \s-1DBIS\-\s0>\fIget_fbav()\fP" | |
1878 | .IX Subsection "Using DBIS->get_fbav()" | |
1879 | The \f(CW$sth\fR\->\fIbind_col()\fR and \f(CW$sth\fR\->\fIbind_columns()\fR documented in the \s-1DBI\s0 | |
1880 | specification do not have to be implemented by the driver writer | |
1881 | becuase \s-1DBI\s0 takes care of the details for you. | |
1882 | However, the key to ensuring that bound columns work is to call the | |
1883 | function \s-1DBIS\-\s0>\fIget_fbav()\fR in the code which fetches a row of data. | |
1884 | This returns an \s-1AV\s0, and each element of the \s-1AV\s0 contains the \s-1SV\s0 which | |
1885 | should be set to contain the returned data. | |
1886 | .PP | |
1887 | The above is for C drivers only. The Perl equivalent is the | |
1888 | \&\f(CW$sth\fR\->_set_fbav($data) method, as described in the part on Pure | |
1889 | Perl drivers. | |
1890 | .SH "SUBCLASSING DBI DRIVERS" | |
1891 | .IX Header "SUBCLASSING DBI DRIVERS" | |
1892 | This is definitely an open subject. It can be done, as demonstrated by | |
1893 | the \fIDBD::File\fR driver, but it is not as simple as one might think. | |
1894 | .PP | |
1895 | (Note that this topic is different from subclassing the \s-1DBI\s0. For an | |
1896 | example of that, see the t/subclass.t file supplied with the \s-1DBI\s0.) | |
1897 | .PP | |
1898 | The main problem is that the dbh's and sth's that your \fIconnect\fR and | |
1899 | \&\fIprepare\fR methods return are not instances of your \fIDBD::Driver::db\fR | |
1900 | or \fIDBD::Driver::st\fR packages, they are not even derived from it. | |
1901 | Instead they are instances of the \fIDBI::db\fR or \fIDBI::st\fR classes or | |
1902 | a derived subclass. Thus, if you write a method \fImymethod\fR and do a | |
1903 | .PP | |
1904 | .Vb 1 | |
1905 | \& $dbh->mymethod() | |
1906 | .Ve | |
1907 | .PP | |
1908 | then the autoloader will search for that method in the package \fIDBI::db\fR. | |
1909 | Of course you can instead to a | |
1910 | .PP | |
1911 | .Vb 1 | |
1912 | \& $dbh->func('mymethod') | |
1913 | .Ve | |
1914 | .PP | |
1915 | and that will indeed work, even if \fImymethod\fR is inherited, but not | |
1916 | without additional work. Setting \f(CW@ISA\fR is not sufficient. | |
1917 | .Sh "Overwriting methods" | |
1918 | .IX Subsection "Overwriting methods" | |
1919 | The first problem is, that the \fIconnect\fR method has no idea of | |
1920 | subclasses. For example, you cannot implement base class and subclass | |
1921 | in the same file: The \fIinstall_driver\fR method wants to do a | |
1922 | .PP | |
1923 | .Vb 1 | |
1924 | \& require DBD::Driver; | |
1925 | .Ve | |
1926 | .PP | |
1927 | In particular, your subclass \fBhas\fR to be a separate driver, from | |
1928 | the view of \s-1DBI\s0, and you cannot share driver handles. | |
1929 | .PP | |
1930 | Of course that's not much of a problem. You should even be able | |
1931 | to inherit the base classes \fIconnect\fR method. But you cannot | |
1932 | simply overwrite the method, unless you do something like this, | |
1933 | quoted from \fI\s-1DBD::CSV\s0\fR: | |
1934 | .PP | |
1935 | .Vb 2 | |
1936 | \& sub connect ($$;$$$) { | |
1937 | \& my($drh, $dbname, $user, $auth, $attr) = @_; | |
1938 | .Ve | |
1939 | .PP | |
1940 | .Vb 4 | |
1941 | \& my $this = $drh->DBD::File::dr::connect($dbname, $user, $auth, $attr); | |
1942 | \& if (!exists($this->{csv_tables})) { | |
1943 | \& $this->{csv_tables} = {}; | |
1944 | \& } | |
1945 | .Ve | |
1946 | .PP | |
1947 | .Vb 2 | |
1948 | \& $this; | |
1949 | \& } | |
1950 | .Ve | |
1951 | .PP | |
1952 | Note that we cannot do a | |
1953 | .PP | |
1954 | .Vb 1 | |
1955 | \& $srh->SUPER::connect($dbname, $user, $auth, $attr); | |
1956 | .Ve | |
1957 | .PP | |
1958 | as we would usually do in a an \s-1OO\s0 environment, because \f(CW$drh\fR is an instance | |
1959 | of \fIDBI::dr\fR. And note, that the \fIconnect\fR method of \fIDBD::File\fR is | |
1960 | able to handle subclass attributes. See the description of Pure Perl | |
1961 | drivers above. | |
1962 | .PP | |
1963 | It is essential that you always call superclass method in the above | |
1964 | manner. However, that should do. | |
1965 | .Sh "Attribute handling" | |
1966 | .IX Subsection "Attribute handling" | |
1967 | Fortunately the \s-1DBI\s0 specs allow a simple, but still performant way of | |
1968 | handling attributes. The idea is based on the convention that any | |
1969 | driver uses a prefix \fIdriver_\fR for its private methods. Thus it's | |
1970 | always clear whether to pass attributes to the super class or not. | |
1971 | For example, consider this \s-1STORE\s0 method from the \fI\s-1DBD::CSV\s0\fR class: | |
1972 | .PP | |
1973 | .Vb 8 | |
1974 | \& sub STORE { | |
1975 | \& my($dbh, $attr, $val) = @_; | |
1976 | \& if ($attr !~ /^driver_/) { | |
1977 | \& return $dbh->DBD::File::db::STORE($attr, $val); | |
1978 | \& } | |
1979 | \& if ($attr eq 'driver_foo') { | |
1980 | \& ... | |
1981 | \& } | |
1982 | .Ve | |
1983 | .SH "ACKNOWLEDGEMENTS" | |
1984 | .IX Header "ACKNOWLEDGEMENTS" | |
1985 | Tim Bunce \- for writing \s-1DBI\s0 and managing the \s-1DBI\s0 specification and the | |
1986 | DBD::Oracle driver. | |
1987 | .SH "AUTHORS" | |
1988 | .IX Header "AUTHORS" | |
1989 | Jonathan Leffler <jleffler@informix.com>, | |
1990 | Jochen Wiedmann <joe@ispsoft.de>, | |
1991 | and Tim Bunce. |