Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | /* $Id: DBIXS.h,v 10.18 2001/06/04 17:13:25 timbo Exp $ |
2 | * | |
3 | * Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999 Tim Bunce England | |
4 | * | |
5 | * See COPYRIGHT section in DBI.pm for usage and distribution rights. | |
6 | */ | |
7 | ||
8 | /* DBI Interface Definitions for DBD Modules */ | |
9 | ||
10 | #ifndef DBIXS_VERSION /* prevent multiple inclusion */ | |
11 | ||
12 | #ifndef DBIS | |
13 | #define DBIS dbis /* default name for dbistate_t variable */ | |
14 | #endif | |
15 | ||
16 | /* first pull in the standard Perl header files for extensions */ | |
17 | #define PERL_POLLUTE | |
18 | #include <EXTERN.h> | |
19 | #include <perl.h> | |
20 | #include <XSUB.h> | |
21 | ||
22 | #ifdef debug /* causes problems with DBIS->debug */ | |
23 | #undef debug | |
24 | #endif | |
25 | ||
26 | /* Perl backwards compatibility definitions */ | |
27 | #include "dbipport.h" | |
28 | ||
29 | /* DBI SQL_* type definitions */ | |
30 | #include "dbi_sql.h" | |
31 | ||
32 | ||
33 | /* The DBIXS_VERSION value will be incremented whenever new code is | |
34 | * added to the interface (this file) or significant changes are made. | |
35 | * It's primary goal is to allow newer drivers to compile against an | |
36 | * older installed DBI. This is mainly an issue whilst the API grows | |
37 | * and learns from the needs of various drivers. See also the | |
38 | * DBISTATE_VERSION macro below. You can think of DBIXS_VERSION as | |
39 | * being a compile time check and DBISTATE_VERSION as a runtime check. | |
40 | */ | |
41 | #define DBIXS_VERSION 93 | |
42 | ||
43 | #ifdef NEED_DBIXS_VERSION | |
44 | #if NEED_DBIXS_VERSION > DBIXS_VERSION | |
45 | error You_need_to_upgrade_your_DBI_module_before_building_this_driver | |
46 | #endif | |
47 | #else | |
48 | #define NEED_DBIXS_VERSION DBIXS_VERSION | |
49 | #endif | |
50 | ||
51 | ||
52 | #if defined(USE_THREADS) && !defined(DBI_NO_THREADS) | |
53 | #define DBI_USE_THREADS | |
54 | #define DBI_LOCK MUTEX_LOCK(DBIS->mutex) | |
55 | #define DBI_UNLOCK MUTEX_UNLOCK(DBIS->mutex) | |
56 | #define dbi_mutex perl_mutex | |
57 | #define dbi_cond perl_cond | |
58 | #else | |
59 | #define DBI_LOCK | |
60 | #define DBI_UNLOCK | |
61 | #define dbi_mutex void | |
62 | #define dbi_cond void | |
63 | #endif | |
64 | ||
65 | ||
66 | /* forward declaration of 'DBI Handle Common Data', see below */ | |
67 | ||
68 | /* implementor needs to define actual struct { dbih_??c_t com; ... }*/ | |
69 | typedef struct imp_drh_st imp_drh_t; /* driver */ | |
70 | typedef struct imp_dbh_st imp_dbh_t; /* database */ | |
71 | typedef struct imp_sth_st imp_sth_t; /* statement */ | |
72 | typedef struct imp_fdh_st imp_fdh_t; /* field descriptor */ | |
73 | typedef struct imp_xxh_st imp_xxh_t; /* any (defined below) */ | |
74 | ||
75 | ||
76 | ||
77 | /* --- DBI Handle Common Data Structure (all handles have one) --- */ | |
78 | ||
79 | /* Handle types. Code currently assumes child = parent + 1. */ | |
80 | #define DBIt_DR 1 | |
81 | #define DBIt_DB 2 | |
82 | #define DBIt_ST 3 | |
83 | #define DBIt_FD 4 | |
84 | ||
85 | /* component structures */ | |
86 | ||
87 | typedef struct dbih_com_std_st { | |
88 | U32 flags; | |
89 | int call_depth; /* used by DBI to track nested calls (int) */ | |
90 | U16 type; /* DBIt_DR, DBIt_DB, DBIt_ST */ | |
91 | HV *my_h; /* copy of outer handle HV (not refcounted) */ | |
92 | HV *parent_h; /* parent inner handle (RV(HV)) (r.c.inc) */ | |
93 | imp_xxh_t *parent_com; /* parent com struct shortcut */ | |
94 | dbi_cond *thr_cond;/* condition for thread access (see dispatch) */ | |
95 | ||
96 | HV *imp_stash; /* who is the implementor for this handle */ | |
97 | SV *imp_data; /* optional implementors data (for perl imp's) */ | |
98 | ||
99 | I32 kids; /* count of db's for dr's, st's for db's etc */ | |
100 | I32 active_kids; /* kids which are currently DBIc_ACTIVE */ | |
101 | U32 thr_user; /* thread id currently using the handle */ | |
102 | void *spare2; | |
103 | } dbih_com_std_t; | |
104 | ||
105 | typedef struct dbih_com_attr_st { | |
106 | /* These are copies of the Hash values (ref.cnt.inc'd) */ | |
107 | /* Many of the hash values are themselves references */ | |
108 | SV *Debug; | |
109 | SV *State; /* Standard SQLSTATE, 5 char string */ | |
110 | SV *Err; /* Native engine error code */ | |
111 | SV *Errstr; /* Native engine error message */ | |
112 | SV *Handlers; | |
113 | U32 LongReadLen; /* auto read length for long/blob types */ | |
114 | I32 spare1; | |
115 | } dbih_com_attr_t; | |
116 | ||
117 | ||
118 | struct dbih_com_st { /* complete core structure (typedef'd above) */ | |
119 | dbih_com_std_t std; | |
120 | dbih_com_attr_t attr; | |
121 | }; | |
122 | ||
123 | /* This 'implementors' type the DBI defines by default as a way to */ | |
124 | /* refer to the imp_??h data of a handle without considering its type. */ | |
125 | struct imp_xxh_st { struct dbih_com_st com; }; | |
126 | ||
127 | /* Define handle-type specific structures for implementors to include */ | |
128 | /* at the start of their private structures. */ | |
129 | ||
130 | typedef struct { /* -- DRIVER -- */ | |
131 | dbih_com_std_t std; | |
132 | dbih_com_attr_t attr; | |
133 | HV *cached_kids; /* $drh->connect_cached(...) */ | |
134 | } dbih_drc_t; | |
135 | ||
136 | typedef struct { /* -- DATABASE -- */ | |
137 | dbih_com_std_t std; /* \__ standard structure */ | |
138 | dbih_com_attr_t attr; /* / plus... (nothing else right now) */ | |
139 | HV *cached_kids; /* $dbh->prepare_cached(...) */ | |
140 | } dbih_dbc_t; | |
141 | ||
142 | typedef struct { /* -- STATEMENT -- */ | |
143 | dbih_com_std_t std; /* \__ standard structure */ | |
144 | dbih_com_attr_t attr; /* / plus ... */ | |
145 | ||
146 | int num_params; /* number of placeholders */ | |
147 | int num_fields; /* NUM_OF_FIELDS, must be set */ | |
148 | AV *fields_svav; /* special row buffer (inc bind_cols) */ | |
149 | IV row_count; /* incremented by get_fbav() */ | |
150 | ||
151 | AV *fields_fdav; /* not used yet, may change */ | |
152 | ||
153 | I32 spare1; | |
154 | void *spare2; | |
155 | } dbih_stc_t; | |
156 | ||
157 | ||
158 | /* XXX THIS STRUCTURE SHOULD NOT BE USED */ | |
159 | typedef struct { /* -- FIELD DESCRIPTOR -- */ | |
160 | dbih_com_std_t std; /* standard structure (not fully setup) */ | |
161 | ||
162 | /* core attributes (from DescribeCol in ODBC) */ | |
163 | char *col_name; /* see dbih_make_fdsv */ | |
164 | I16 col_name_len; | |
165 | I16 col_sql_type; | |
166 | I16 col_precision; | |
167 | I16 col_scale; | |
168 | I16 col_nullable; | |
169 | ||
170 | /* additional attributes (from ColAttributes in ODBC) */ | |
171 | I32 col_length; | |
172 | I32 col_disp_size; | |
173 | ||
174 | I32 spare1; | |
175 | void *spare2; | |
176 | } dbih_fdc_t; | |
177 | ||
178 | ||
179 | #define _imp2com(p,f) ((p)->com.f) | |
180 | ||
181 | #define DBIc_FLAGS(imp) _imp2com(imp, std.flags) | |
182 | #define DBIc_TYPE(imp) _imp2com(imp, std.type) | |
183 | #define DBIc_CALL_DEPTH(imp) _imp2com(imp, std.call_depth) | |
184 | #define DBIc_MY_H(imp) _imp2com(imp, std.my_h) | |
185 | #define DBIc_PARENT_H(imp) _imp2com(imp, std.parent_h) | |
186 | #define DBIc_PARENT_COM(imp) _imp2com(imp, std.parent_com) | |
187 | #define DBIc_THR_COND(imp) _imp2com(imp, std.thr_cond) | |
188 | #define DBIc_THR_USER(imp) _imp2com(imp, std.thr_user) | |
189 | #define DBIc_THR_USER_NONE (0xFFFF) | |
190 | #define DBIc_IMP_STASH(imp) _imp2com(imp, std.imp_stash) | |
191 | #define DBIc_IMP_DATA(imp) _imp2com(imp, std.imp_data) | |
192 | #define DBIc_KIDS(imp) _imp2com(imp, std.kids) | |
193 | #define DBIc_ACTIVE_KIDS(imp) _imp2com(imp, std.active_kids) | |
194 | ||
195 | #define DBIc_DEBUG(imp) (_imp2com(imp, attr.Debug)) | |
196 | #define DBIc_DEBUGIV(imp) SvIV(DBIc_DEBUG(imp)) | |
197 | #define DBIc_STATE(imp) SvRV(_imp2com(imp, attr.State)) | |
198 | #define DBIc_ERR(imp) SvRV(_imp2com(imp, attr.Err)) | |
199 | #define DBIc_ERRSTR(imp) SvRV(_imp2com(imp, attr.Errstr)) | |
200 | #define DBIc_HANDLERS(imp) SvRV(_imp2com(imp, attr.Handlers)) | |
201 | #define DBIc_LongReadLen(imp) _imp2com(imp, attr.LongReadLen) | |
202 | #define DBIc_LongReadLen_init 80 /* may change */ | |
203 | ||
204 | /* handle sub-type specific fields */ | |
205 | /* dbh */ | |
206 | #define DBIc_CACHED_KIDS(imp) _imp2com(imp, cached_kids) | |
207 | /* sth */ | |
208 | #define DBIc_NUM_FIELDS(imp) _imp2com(imp, num_fields) | |
209 | #define DBIc_NUM_PARAMS(imp) _imp2com(imp, num_params) | |
210 | #define DBIc_NUM_PARAMS_AT_EXECUTE -9 /* see Driver.xst */ | |
211 | #define DBIc_ROW_COUNT(imp) _imp2com(imp, row_count) | |
212 | #define DBIc_FIELDS_AV(imp) _imp2com(imp, fields_svav) | |
213 | #define DBIc_FDESC_AV(imp) _imp2com(imp, fields_fdav) | |
214 | #define DBIc_FDESC(imp, i) ((imp_fdh_t*)(void*)SvPVX(AvARRAY(DBIc_FDESC_AV(imp))[i])) | |
215 | ||
216 | #define DBIcf_COMSET 0x0001 /* needs to be clear'd before free'd */ | |
217 | #define DBIcf_IMPSET 0x0002 /* has implementor data to be clear'd */ | |
218 | #define DBIcf_ACTIVE 0x0004 /* needs finish/disconnect before clear */ | |
219 | #define DBIcf_IADESTROY 0x0008 /* do DBIc_ACTIVE_off before DESTROY */ | |
220 | #define DBIcf_WARN 0x0010 /* warn about poor practice etc */ | |
221 | #define DBIcf_COMPAT 0x0020 /* compat/emulation mode (eg oraperl) */ | |
222 | ||
223 | #define DBIcf_ChopBlanks 0x0040 /* rtrim spaces from fetch char columns */ | |
224 | #define DBIcf_RaiseError 0x0080 /* throw exception (croak) on error */ | |
225 | #define DBIcf_PrintError 0x0100 /* warn() on error */ | |
226 | #define DBIcf_AutoCommit 0x0200 /* dbh only. used by drivers */ | |
227 | #define DBIcf_LongTruncOk 0x0400 /* truncation to LongReadLen is okay */ | |
228 | #define DBIcf_MultiThread 0x0800 /* allow multiple threads to enter */ | |
229 | #define DBIcf_Taint 0x1000 /* taint fetched data */ | |
230 | #define DBIcf_ShowErrorStatement 0x2000 /* include Statement in error */ | |
231 | ||
232 | #define DBIcf_INHERITMASK /* what NOT to pass on to children */ \ | |
233 | (U32)( DBIcf_COMSET | DBIcf_IMPSET | DBIcf_ACTIVE | DBIcf_IADESTROY \ | |
234 | /* These are for dbh only: */ \ | |
235 | | DBIcf_AutoCommit ) | |
236 | ||
237 | /* general purpose bit setting and testing macros */ | |
238 | #define DBIbf_is( bitset,flag) ((bitset) & (flag)) | |
239 | #define DBIbf_has(bitset,flag) DBIbf_is(bitset, flag) /* alias for _is */ | |
240 | #define DBIbf_on( bitset,flag) ((bitset) |= (flag)) | |
241 | #define DBIbf_off(bitset,flag) ((bitset) &= ~(flag)) | |
242 | #define DBIbf_set(bitset,flag,on) ((on) ? DBIbf_on(bitset, flag) : DBIbf_off(bitset,flag)) | |
243 | ||
244 | /* as above, but specifically for DBIc_FLAGS imp flags (except ACTIVE) */ | |
245 | #define DBIc_is(imp, flag) DBIbf_is( DBIc_FLAGS(imp), flag) | |
246 | #define DBIc_has(imp,flag) DBIc_is(imp, flag) /* alias for DBIc_is */ | |
247 | #define DBIc_on(imp, flag) DBIbf_on( DBIc_FLAGS(imp), flag) | |
248 | #define DBIc_off(imp,flag) DBIbf_off(DBIc_FLAGS(imp), flag) | |
249 | #define DBIc_set(imp,flag,on) DBIbf_set(DBIc_FLAGS(imp), flag, on) | |
250 | ||
251 | #define DBIc_COMSET(imp) DBIc_is(imp, DBIcf_COMSET) | |
252 | #define DBIc_COMSET_on(imp) DBIc_on(imp, DBIcf_COMSET) | |
253 | #define DBIc_COMSET_off(imp) DBIc_off(imp,DBIcf_COMSET) | |
254 | ||
255 | #define DBIc_IMPSET(imp) DBIc_is(imp, DBIcf_IMPSET) | |
256 | #define DBIc_IMPSET_on(imp) DBIc_on(imp, DBIcf_IMPSET) | |
257 | #define DBIc_IMPSET_off(imp) DBIc_off(imp,DBIcf_IMPSET) | |
258 | ||
259 | #define DBIc_ACTIVE(imp) (DBIc_FLAGS(imp) & DBIcf_ACTIVE) | |
260 | #define DBIc_ACTIVE_on(imp) /* adjust parent's active kid count */ \ | |
261 | do { \ | |
262 | imp_xxh_t *ph_com = DBIc_PARENT_COM(imp); \ | |
263 | if (!DBIc_ACTIVE(imp) && ph_com && !dirty \ | |
264 | && ++DBIc_ACTIVE_KIDS(ph_com) > DBIc_KIDS(ph_com)) \ | |
265 | croak("panic: DBI active kids (%d) > kids (%d)", \ | |
266 | DBIc_ACTIVE_KIDS(ph_com), DBIc_KIDS(ph_com)); \ | |
267 | DBIc_FLAGS(imp) |= DBIcf_ACTIVE; \ | |
268 | } while(0) | |
269 | #define DBIc_ACTIVE_off(imp) /* adjust parent's active kid count */ \ | |
270 | do { \ | |
271 | imp_xxh_t *ph_com = DBIc_PARENT_COM(imp); \ | |
272 | if (DBIc_ACTIVE(imp) && ph_com && !dirty \ | |
273 | && (--DBIc_ACTIVE_KIDS(ph_com) > DBIc_KIDS(ph_com) \ | |
274 | || DBIc_ACTIVE_KIDS(ph_com) < 0) ) \ | |
275 | croak("panic: DBI active kids (%d) < 0 or > kids (%d)", \ | |
276 | DBIc_ACTIVE_KIDS(ph_com), DBIc_KIDS(ph_com)); \ | |
277 | DBIc_FLAGS(imp) &= ~DBIcf_ACTIVE; \ | |
278 | } while(0) | |
279 | ||
280 | #define DBIc_IADESTROY(imp) (DBIc_FLAGS(imp) & DBIcf_IADESTROY) | |
281 | #define DBIc_IADESTROY_on(imp) (DBIc_FLAGS(imp) |= DBIcf_IADESTROY) | |
282 | #define DBIc_IADESTROY_off(imp) (DBIc_FLAGS(imp) &= ~DBIcf_IADESTROY) | |
283 | ||
284 | #define DBIc_WARN(imp) (DBIc_FLAGS(imp) & DBIcf_WARN) | |
285 | #define DBIc_WARN_on(imp) (DBIc_FLAGS(imp) |= DBIcf_WARN) | |
286 | #define DBIc_WARN_off(imp) (DBIc_FLAGS(imp) &= ~DBIcf_WARN) | |
287 | ||
288 | #define DBIc_COMPAT(imp) (DBIc_FLAGS(imp) & DBIcf_COMPAT) | |
289 | #define DBIc_COMPAT_on(imp) (DBIc_FLAGS(imp) |= DBIcf_COMPAT) | |
290 | #define DBIc_COMPAT_off(imp) (DBIc_FLAGS(imp) &= ~DBIcf_COMPAT) | |
291 | ||
292 | ||
293 | #ifdef IN_DBI_XS /* get Handle Common Data Structure */ | |
294 | #define DBIh_COM(h) (dbih_getcom(h)) | |
295 | #else | |
296 | #define DBIh_COM(h) (DBIS->getcom(h)) | |
297 | #define neatsvpv(sv,len) (DBIS->neat_svpv(sv,len)) | |
298 | #endif | |
299 | ||
300 | ||
301 | /* --- Implementors Private Data Support --- */ | |
302 | ||
303 | #define D_impdata(name,type,h) type *name = (type*)(DBIh_COM(h)) | |
304 | #define D_imp_drh(h) D_impdata(imp_drh, imp_drh_t, h) | |
305 | #define D_imp_dbh(h) D_impdata(imp_dbh, imp_dbh_t, h) | |
306 | #define D_imp_sth(h) D_impdata(imp_sth, imp_sth_t, h) | |
307 | #define D_imp_xxh(h) D_impdata(imp_xxh, imp_xxh_t, h) | |
308 | ||
309 | #define D_imp_from_child(name,type,child) \ | |
310 | type *name = (type*)(DBIc_PARENT_COM(child)) | |
311 | #define D_imp_drh_from_dbh D_imp_from_child(imp_drh, imp_drh_t, imp_dbh) | |
312 | #define D_imp_dbh_from_sth D_imp_from_child(imp_dbh, imp_dbh_t, imp_sth) | |
313 | ||
314 | #define DBI_IMP_SIZE(n,s) sv_setiv(perl_get_sv((n), GV_ADDMULTI), (s)) /* XXX */ | |
315 | ||
316 | ||
317 | /* --- Implementors Field Descriptor Support --- */ | |
318 | ||
319 | ||
320 | /* --- Event Support (VERY LIABLE TO CHANGE) --- */ | |
321 | ||
322 | #define DBIh_EVENTx(h,t,a1,a2) (DBIS->event((h), (t), (a1), (a2))) | |
323 | #define DBIh_EVENT0(h,t) DBIh_EVENTx((h), (t), &sv_undef, &sv_undef) | |
324 | #define DBIh_EVENT1(h,t, a1) DBIh_EVENTx((h), (t), (a1), &sv_undef) | |
325 | #define DBIh_EVENT2(h,t, a1,a2) DBIh_EVENTx((h), (t), (a1), (a2)) | |
326 | ||
327 | #define ERROR_event "ERROR" | |
328 | #define WARN_event "WARN" | |
329 | #define MSG_event "MESSAGE" | |
330 | #define DBEVENT_event "DBEVENT" | |
331 | #define UNKNOWN_event "UNKNOWN" | |
332 | ||
333 | ||
334 | /* --- Handy Macros --- */ | |
335 | ||
336 | #define DBIh_CLEAR_ERROR(imp_xxh) (void)( \ | |
337 | (void)SvOK_off(DBIc_ERR(imp_xxh)), \ | |
338 | (void)SvOK_off(DBIc_ERRSTR(imp_xxh)), \ | |
339 | (SvPOK(DBIc_STATE(imp_xxh)) ? SvCUR(DBIc_STATE(imp_xxh))=0 : 0) \ | |
340 | ) | |
341 | ||
342 | ||
343 | /* --- DBI State Structure --- */ | |
344 | ||
345 | typedef struct { | |
346 | ||
347 | #define DBISTATE_VERSION 94 /* Must change whenever dbistate_t does */ | |
348 | ||
349 | /* this must be the first member in structure */ | |
350 | void (*check_version) _((char *name, | |
351 | int dbis_cv, int dbis_cs, int need_dbixs_cv, | |
352 | int drc_s, int dbc_s, int stc_s, int fdc_s)); | |
353 | ||
354 | /* version and size are used to check for DBI/DBD version mis-match */ | |
355 | U16 version; /* version of this structure */ | |
356 | U16 size; | |
357 | U16 xs_version; /* version of the overall DBIXS / DBD interface */ | |
358 | U16 spare_pad; | |
359 | ||
360 | I32 debug; | |
361 | PerlIO *logfp; | |
362 | ||
363 | /* pointers to DBI functions which the DBD's will want to use */ | |
364 | char * (*neat_svpv) _((SV *sv, STRLEN maxlen)); | |
365 | imp_xxh_t * (*getcom) _((SV *h)); /* see DBIh_COM macro */ | |
366 | void (*clearcom) _((imp_xxh_t *imp_xxh)); | |
367 | SV * (*event) _((SV *h, char *name, SV*, SV*)); | |
368 | int (*set_attr_k) _((SV *h, SV *keysv, int dbikey, SV *valuesv)); | |
369 | SV * (*get_attr_k) _((SV *h, SV *keysv, int dbikey)); | |
370 | AV * (*get_fbav) _((imp_sth_t *imp_sth)); | |
371 | SV * (*make_fdsv) _((SV *sth, char *imp_class, STRLEN imp_size, char *col_name)); | |
372 | int (*bind_as_num) _((int sql_type, int p, int s, int *t, void *v)); | |
373 | int (*hash) _((char *string, long i)); | |
374 | AV * (*preparse) _((SV *sth, char *statement, U32 flags, U32 spare)); | |
375 | ||
376 | SV *neatsvpvlen; /* only show dbgpvlen chars when debugging pv's */ | |
377 | ||
378 | dbi_mutex *mutex; | |
379 | ||
380 | int (*logmsg) _((SV *h, imp_xxh_t *imp_xxh, char *fmt, ...)); | |
381 | void *pad[8]; | |
382 | } dbistate_t; | |
383 | ||
384 | /* macros for backwards compatibility */ | |
385 | #define set_attr(h, k, v) set_attr_k(h, k, 0, v) | |
386 | #define get_attr(h, k) get_attr_k(h, k, 0) | |
387 | ||
388 | #define DBISTATE_PERLNAME "DBI::_dbistate" | |
389 | #define DBISTATE_ADDRSV (perl_get_sv(DBISTATE_PERLNAME, 0x05)) | |
390 | #define DBILOGFP (DBIS->logfp) | |
391 | #ifdef IN_DBI_XS | |
392 | #define DBILOGMSG (dbih_logmsg) | |
393 | #else | |
394 | #define DBILOGMSG (DBIS->logmsg) | |
395 | #endif | |
396 | ||
397 | ||
398 | /* --- perl object (ActiveState) / multiplicity hooks and hoops --- */ | |
399 | /* note that USE_ITHREADS implies MULTIPLICITY */ | |
400 | #if defined(MULTIPLICITY) || defined(PERL_OBJECT) || defined(PERL_CAPI) | |
401 | ||
402 | # define DBISTATE_DECLARE | |
403 | # define DBISTATE_ASSIGN(st) | |
404 | # define DBISTATE_INIT | |
405 | static dbistate_t **get_dbistate() { | |
406 | return ((dbistate_t**)&SvIVX(DBISTATE_ADDRSV)); | |
407 | } | |
408 | # undef DBIS | |
409 | # define DBIS (*get_dbistate()) | |
410 | # define dbis (*get_dbistate()) /* temp for bad drivers using 'dbis' instead of 'DBIS' */ | |
411 | ||
412 | #else /* plain and simple non perl object / multiplicity case */ | |
413 | ||
414 | # define DBISTATE_DECLARE static dbistate_t *DBIS | |
415 | # define DBISTATE_ASSIGN(st) (DBIS = (st)) | |
416 | # define DBISTATE_INIT_DBIS DBISTATE_ASSIGN((dbistate_t*)SvIV(DBISTATE_ADDRSV)) | |
417 | # define DBISTATE_INIT { /* typically use in BOOT: of XS file */ \ | |
418 | DBISTATE_INIT_DBIS; \ | |
419 | if (DBIS == NULL) \ | |
420 | croak("Unable to get DBI state. DBI not loaded."); \ | |
421 | DBIS->check_version(__FILE__, DBISTATE_VERSION, sizeof(*DBIS), NEED_DBIXS_VERSION, \ | |
422 | sizeof(dbih_drc_t), sizeof(dbih_dbc_t), sizeof(dbih_stc_t), sizeof(dbih_fdc_t) \ | |
423 | ); \ | |
424 | } | |
425 | #endif | |
426 | ||
427 | ||
428 | /* --- Assorted Utility Macros --- */ | |
429 | ||
430 | #define DBD_ATTRIB_OK(attribs) /* is this a usable attrib value */ \ | |
431 | (attribs && SvROK(attribs) && SvTYPE(SvRV(attribs))==SVt_PVHV) | |
432 | ||
433 | /* If attribs value supplied then croak if it's not a hash ref. */ | |
434 | /* Also map undef to Null. Should always be called to pre-process the */ | |
435 | /* attribs value. One day we may add some extra magic in here. */ | |
436 | #define DBD_ATTRIBS_CHECK(func, h, attribs) \ | |
437 | if ((attribs) && SvOK(attribs)) { \ | |
438 | if (!SvROK(attribs) || SvTYPE(SvRV(attribs))!=SVt_PVHV) \ | |
439 | croak("%s->%s(...): attribute parameter '%s' is not a hash ref", \ | |
440 | SvPV(h,na), func, SvPV(attribs,na)); \ | |
441 | } else (attribs) = Nullsv | |
442 | ||
443 | #define DBD_ATTRIB_GET_SVP(attribs, key,klen) \ | |
444 | (DBD_ATTRIB_OK(attribs) \ | |
445 | ? hv_fetch((HV*)SvRV(attribs), key,klen, 0) \ | |
446 | : (SV **)Nullsv) | |
447 | ||
448 | #define DBD_ATTRIB_GET_BOOL(attribs, key,klen, svp, var) \ | |
449 | if ((svp=DBD_ATTRIB_GET_SVP(attribs, key,klen)) != NULL) \ | |
450 | var = SvTRUE(*svp) | |
451 | ||
452 | #define DBD_ATTRIB_GET_IV(attribs, key,klen, svp, var) \ | |
453 | if ((svp=DBD_ATTRIB_GET_SVP(attribs, key,klen)) != NULL) \ | |
454 | var = SvIV(*svp) | |
455 | ||
456 | #endif /* DBIXS_VERSION */ | |
457 | /* end of DBIXS.h */ |