… | |
… | |
5 | /* import some stuff from DBIXS.h and DBI.xs */ |
5 | /* import some stuff from DBIXS.h and DBI.xs */ |
6 | #define DBIXS_VERSION 93 |
6 | #define DBIXS_VERSION 93 |
7 | #define DBI_MAGIC '~' |
7 | #define DBI_MAGIC '~' |
8 | |
8 | |
9 | #define DBISTATE_PERLNAME "DBI::_dbistate" |
9 | #define DBISTATE_PERLNAME "DBI::_dbistate" |
10 | #define DBISTATE_ADDRSV (perl_get_sv(DBISTATE_PERLNAME, 0x05)) |
10 | #define DBISTATE_ADDRSV (perl_get_sv (DBISTATE_PERLNAME, 0x05)) |
11 | #define DBIS_PUBLISHED_LVALUE (*(INT2PTR(dbistate_t**, &SvIVX(DBISTATE_ADDRSV)))) |
11 | #define DBIS_PUBLISHED_LVALUE (*(INT2PTR(dbistate_t**, &SvIVX(DBISTATE_ADDRSV)))) |
|
|
12 | |
|
|
13 | static SV *sql_varchar, *sql_integer, *sql_double; |
|
|
14 | static SV *tmp_iv; |
12 | |
15 | |
13 | struct dbistate_st { |
16 | struct dbistate_st { |
14 | #define DBISTATE_VERSION 94 /* Must change whenever dbistate_t does */ |
17 | #define DBISTATE_VERSION 94 /* Must change whenever dbistate_t does */ |
15 | /* this must be the first member in structure */ |
18 | /* this must be the first member in structure */ |
16 | void (*check_version) _((const char *name, |
19 | void (*check_version) _((const char *name, |
… | |
… | |
57 | |
60 | |
58 | static SV * |
61 | static SV * |
59 | sql_upgrade_utf8 (SV *sv) |
62 | sql_upgrade_utf8 (SV *sv) |
60 | { |
63 | { |
61 | #if CAN_UTF8 |
64 | #if CAN_UTF8 |
62 | if (SvPOK (sv)) |
65 | if (SvPOKp (sv)) |
63 | sv_utf8_upgrade (sv); |
66 | sv_utf8_upgrade (sv); |
64 | #endif |
67 | #endif |
65 | return sv; |
68 | return sv; |
66 | } |
69 | } |
67 | |
70 | |
68 | static SV * |
71 | static SV * |
69 | mortalcopy_and_maybe_force_utf8(int utf8, SV *sv) |
72 | mortalcopy_and_maybe_force_utf8(int utf8, SV *sv) |
70 | { |
73 | { |
71 | sv = sv_mortalcopy (sv); |
74 | sv = sv_mortalcopy (sv); |
72 | #if CAN_UTF8 |
75 | #if CAN_UTF8 |
73 | if (utf8 && SvPOK (sv)) |
76 | if (utf8 && SvPOKp (sv)) |
74 | SvUTF8_on (sv); |
77 | SvUTF8_on (sv); |
75 | #endif |
78 | #endif |
76 | return sv; |
79 | return sv; |
77 | } |
80 | } |
78 | |
81 | |
79 | #define maybe_upgrade_utf8(utf8,sv) ((utf8) ? sql_upgrade_utf8 (sv) : (sv)) |
82 | #define maybe_upgrade_utf8(utf8,sv) ((utf8) ? sql_upgrade_utf8 (sv) : (sv)) |
80 | |
83 | |
81 | #define is_dbh(sv) ((sv) && sv_isobject (sv) && sv_derived_from ((sv), "DBI::db")) |
84 | #define is_dbh(sv) ((sv) && sv_isobject (sv) && sv_derived_from ((sv), "DBI::db")) |
82 | |
85 | |
|
|
86 | typedef struct mc_node |
|
|
87 | { |
|
|
88 | struct mc_node *next; |
|
|
89 | HV *stash; |
|
|
90 | U32 gen; |
|
|
91 | |
|
|
92 | /* DBH */ |
|
|
93 | SV *prepare; |
|
|
94 | |
|
|
95 | /* STH */ |
|
|
96 | SV *execute; |
|
|
97 | SV *bind_param; |
|
|
98 | SV *bind_columns; |
|
|
99 | SV *fetchrow_arrayref; |
|
|
100 | SV *fetchall_arrayref; |
|
|
101 | SV *finish; |
|
|
102 | } mc_node; |
|
|
103 | |
|
|
104 | static mc_node *first; |
|
|
105 | |
|
|
106 | static mc_node * |
|
|
107 | mc_find (HV *stash) |
|
|
108 | { |
|
|
109 | mc_node *mc; |
|
|
110 | U32 gen = PL_sub_generation; |
|
|
111 | |
|
|
112 | #ifdef HvMROMETA |
|
|
113 | gen += HvMROMETA (stash)->cache_gen; |
|
|
114 | #endif |
|
|
115 | |
|
|
116 | for (mc = first; mc; mc = mc->next) |
|
|
117 | if (mc->stash == stash && mc->gen == gen) |
|
|
118 | return mc; |
|
|
119 | |
|
|
120 | if (!mc) |
|
|
121 | { |
|
|
122 | Newz (0, mc, 1, mc_node); |
|
|
123 | mc->stash = stash; |
|
|
124 | |
|
|
125 | mc->next = first; |
|
|
126 | first = mc; |
|
|
127 | } |
|
|
128 | else |
|
|
129 | { |
|
|
130 | mc->execute = |
|
|
131 | mc->bind_param = |
|
|
132 | mc->bind_columns = |
|
|
133 | mc->fetchrow_arrayref = |
|
|
134 | mc->fetchall_arrayref = |
|
|
135 | mc->finish = 0; |
|
|
136 | } |
|
|
137 | |
|
|
138 | mc->gen = gen; |
|
|
139 | |
|
|
140 | return mc; |
|
|
141 | } |
|
|
142 | |
|
|
143 | static void |
|
|
144 | mc_cache (mc_node *mc, SV **method, const char *name) |
|
|
145 | { |
|
|
146 | *method = (SV *)gv_fetchmethod_autoload (mc->stash, name, 0); |
|
|
147 | |
|
|
148 | if (!method) |
|
|
149 | croak ("%s: method not found in stash, pelase report.", name); |
|
|
150 | } |
|
|
151 | |
|
|
152 | #define mc_cache(mc, method) mc_cache ((mc), &((mc)->method), # method) |
|
|
153 | |
83 | typedef struct lru_node { |
154 | typedef struct lru_node |
|
|
155 | { |
84 | struct lru_node *next; |
156 | struct lru_node *next; |
85 | struct lru_node *prev; |
157 | struct lru_node *prev; |
86 | U32 hash; /* bit 31 is used to mark active nodes */ |
158 | |
|
|
159 | U32 hash; |
87 | SV *dbh; |
160 | SV *dbh; |
88 | SV *sql; |
161 | SV *sql; |
89 | |
162 | |
90 | SV *sth; |
163 | SV *sth; |
91 | imp_sth *sth_imp; |
164 | imp_sth *sth_imp; |
92 | #if 0 /* method cache */ |
165 | |
93 | GV *execute; |
166 | mc_node *mc; |
94 | GV *bind_columns; |
|
|
95 | GV *fetch; |
|
|
96 | GV *finish; |
|
|
97 | #endif |
|
|
98 | } lru_node; |
167 | } lru_node; |
99 | |
168 | |
100 | static lru_node lru_list; |
169 | static lru_node lru_list; |
101 | static int lru_size; |
170 | static int lru_size; |
102 | static int lru_maxsize; |
171 | static int lru_maxsize; |
103 | |
172 | |
104 | #define lru_init() lru_list.next = &lru_list; lru_list.prev = &lru_list /* other fields are zero */ |
173 | #define lru_init() lru_list.next = &lru_list; lru_list.prev = &lru_list /* other fields are zero */ |
105 | |
174 | |
106 | /* this is primitive, yet effective */ |
175 | /* this is primitive, yet effective */ |
107 | /* the returned value must never be zero (or bad things will happen) */ |
176 | /* the returned value must never be zero (or bad things will happen) */ |
108 | #define lru_hash \ |
177 | static U32 |
109 | do { \ |
178 | lru_hash (SV *dbh, SV *sql) |
110 | hash = (((U32)(long)dbh)>>4); \ |
179 | { |
111 | hash += *statement; \ |
180 | STRLEN i, l; |
112 | hash += len; \ |
181 | char *b = SvPV (sql, l); |
113 | } while (0) |
182 | U32 hash = 2166136261; |
|
|
183 | |
|
|
184 | hash = (hash ^ (U32)dbh) * 16777619U; |
|
|
185 | hash = (hash ^ l) * 16777619U; |
|
|
186 | |
|
|
187 | for (i = 7; i < l; i += i >> 2) |
|
|
188 | hash = (hash ^ b [i]) * 16777619U; |
|
|
189 | |
|
|
190 | return hash; |
|
|
191 | } |
114 | |
192 | |
115 | /* fetch and "use" */ |
193 | /* fetch and "use" */ |
116 | /* could be done using a single call (we could call prepare!) */ |
194 | static lru_node * |
117 | static SV * |
|
|
118 | lru_fetch (SV *dbh, SV *sql) |
195 | lru_fetch (SV *dbh, SV *sql) |
119 | { |
196 | { |
120 | lru_node *n; |
197 | lru_node *n; |
121 | |
|
|
122 | U32 hash; |
198 | U32 hash; |
123 | STRLEN len; |
|
|
124 | char *statement = SvPV (sql, len); |
|
|
125 | |
199 | |
126 | dbh = SvRV (dbh); |
200 | dbh = SvRV (dbh); |
127 | |
201 | hash = lru_hash (dbh, sql); |
128 | lru_hash; |
|
|
129 | |
202 | |
130 | n = &lru_list; |
203 | n = &lru_list; |
131 | do { |
204 | do { |
132 | n = n->next; |
205 | n = n->next; |
133 | |
206 | |
… | |
… | |
145 | n->next = lru_list.next; |
218 | n->next = lru_list.next; |
146 | n->prev = &lru_list; |
219 | n->prev = &lru_list; |
147 | lru_list.next->prev = n; |
220 | lru_list.next->prev = n; |
148 | lru_list.next = n; |
221 | lru_list.next = n; |
149 | |
222 | |
150 | return sv_2mortal (SvREFCNT_inc (n->sth)); |
223 | return n; |
151 | } |
224 | } |
152 | |
225 | |
153 | static void |
226 | static void |
154 | lru_trim (void) |
227 | lru_trim (void) |
155 | { |
228 | { |
… | |
… | |
172 | } |
245 | } |
173 | } |
246 | } |
174 | |
247 | |
175 | /* store a not-yet existing entry(!) */ |
248 | /* store a not-yet existing entry(!) */ |
176 | static void |
249 | static void |
177 | lru_store (SV *dbh, SV *sql, SV *sth) |
250 | lru_store (SV *dbh, SV *sql, SV *sth, mc_node *mc) |
178 | { |
251 | { |
179 | lru_node *n; |
252 | lru_node *n; |
180 | U32 hash; |
253 | U32 hash; |
181 | STRLEN len; |
|
|
182 | char *statement; |
|
|
183 | |
254 | |
184 | if (!lru_maxsize) |
255 | if (!lru_maxsize) |
185 | return; |
256 | return; |
186 | |
257 | |
187 | statement = SvPV (sql, len); |
|
|
188 | dbh = SvRV (dbh); |
258 | dbh = SvRV (dbh); |
189 | |
259 | hash = lru_hash (dbh, sql); |
190 | lru_hash; |
|
|
191 | |
260 | |
192 | lru_size++; |
261 | lru_size++; |
193 | lru_trim (); |
262 | lru_trim (); |
194 | |
263 | |
195 | New (0, n, 1, lru_node); |
264 | New (0, n, 1, lru_node); |
… | |
… | |
197 | n->hash = hash; |
266 | n->hash = hash; |
198 | n->dbh = dbh; SvREFCNT_inc (dbh); /* note: this is the dbi hash itself, not the reference */ |
267 | n->dbh = dbh; SvREFCNT_inc (dbh); /* note: this is the dbi hash itself, not the reference */ |
199 | n->sql = newSVsv (sql); |
268 | n->sql = newSVsv (sql); |
200 | n->sth = sth; SvREFCNT_inc (sth); |
269 | n->sth = sth; SvREFCNT_inc (sth); |
201 | n->sth_imp = sth_get_imp (sth); |
270 | n->sth_imp = sth_get_imp (sth); |
|
|
271 | n->mc = mc; |
202 | |
272 | |
203 | n->next = lru_list.next; |
273 | n->next = lru_list.next; |
204 | n->prev = &lru_list; |
274 | n->prev = &lru_list; |
205 | lru_list.next->prev = n; |
275 | lru_list.next->prev = n; |
206 | lru_list.next = n; |
276 | lru_list.next = n; |
… | |
… | |
216 | } |
286 | } |
217 | } |
287 | } |
218 | |
288 | |
219 | static GV *sql_exec; |
289 | static GV *sql_exec; |
220 | static GV *DBH; |
290 | static GV *DBH; |
221 | static SV *sv_prepare, *sv_execute, *sv_bind_columns, |
|
|
222 | *sv_fetchrow_arrayref, *sv_fetchall_arrayref, |
|
|
223 | *sv_finish; |
|
|
224 | |
291 | |
225 | #define newconstpv(str) newSVpvn ((str), sizeof (str)) |
292 | #define newconstpv(str) newSVpvn ((str), sizeof (str)) |
226 | |
293 | |
227 | MODULE = PApp::SQL PACKAGE = PApp::SQL |
294 | MODULE = PApp::SQL PACKAGE = PApp::SQL |
228 | |
295 | |
… | |
… | |
234 | |
301 | |
235 | /* this is actually wrong, we should call the check member, apparently */ |
302 | /* this is actually wrong, we should call the check member, apparently */ |
236 | assert (dbis->version == DBISTATE_VERSION); |
303 | assert (dbis->version == DBISTATE_VERSION); |
237 | assert (dbis->xs_version == DBIXS_VERSION); |
304 | assert (dbis->xs_version == DBIXS_VERSION); |
238 | |
305 | |
|
|
306 | tmp_iv = newSViv (0); |
|
|
307 | |
239 | sql_exec = gv_fetchpv ("PApp::SQL::sql_exec", TRUE, SVt_PV); |
308 | sql_exec = gv_fetchpv ("PApp::SQL::sql_exec", TRUE, SVt_PV); |
240 | DBH = gv_fetchpv ("PApp::SQL::DBH" , TRUE, SVt_PV); |
309 | DBH = gv_fetchpv ("PApp::SQL::DBH" , TRUE, SVt_PV); |
241 | |
|
|
242 | if (!sv_prepare) |
|
|
243 | { |
|
|
244 | sv_prepare = newconstpv ("prepare"); |
|
|
245 | sv_execute = newconstpv ("execute"); |
|
|
246 | sv_bind_columns = newconstpv ("bind_columns"); |
|
|
247 | sv_fetchrow_arrayref = newconstpv ("fetchrow_arrayref"); |
|
|
248 | sv_fetchall_arrayref = newconstpv ("fetchall_arrayref"); |
|
|
249 | sv_finish = newconstpv ("finish"); |
|
|
250 | } |
|
|
251 | |
310 | |
252 | /* apache might BOOT: twice :( */ |
311 | /* apache might BOOT: twice :( */ |
253 | if (lru_size) |
312 | if (lru_size) |
254 | lru_cachesize (0); |
313 | lru_cachesize (0); |
255 | |
314 | |
256 | lru_init (); |
315 | lru_init (); |
257 | lru_cachesize (50); |
316 | lru_cachesize (100); |
258 | } |
317 | } |
|
|
318 | |
|
|
319 | void |
|
|
320 | boot2 (SV *t_str, SV *t_int, SV *t_dbl) |
|
|
321 | CODE: |
|
|
322 | sql_varchar = newSVsv (t_str); |
|
|
323 | sql_integer = newSVsv (t_int); |
|
|
324 | sql_double = newSVsv (t_dbl); |
259 | |
325 | |
260 | int |
326 | int |
261 | cachesize(size = -1) |
327 | cachesize(size = -1) |
262 | int size |
328 | int size |
263 | CODE: |
329 | CODE: |
… | |
… | |
280 | { |
346 | { |
281 | if (items == 0) |
347 | if (items == 0) |
282 | croak ("Usage: sql_exec [database-handle,] [bind-var-refs,... ] \"sql-statement\", [arguments, ...]"); |
348 | croak ("Usage: sql_exec [database-handle,] [bind-var-refs,... ] \"sql-statement\", [arguments, ...]"); |
283 | else |
349 | else |
284 | { |
350 | { |
|
|
351 | int i; |
285 | int arg = 0; |
352 | int arg = 0; |
|
|
353 | int first_execution = 0; |
286 | int bind_first, bind_last; |
354 | int bind_first, bind_last; |
287 | int count; |
355 | int count; |
|
|
356 | lru_node *lru; |
288 | SV *dbh = ST(0); |
357 | SV *dbh = ST(0); |
289 | SV *sth; |
358 | SV *sth; |
290 | SV *sql; |
359 | SV *sql; |
291 | SV *execute; |
360 | SV *execute; |
|
|
361 | mc_node *mc; |
292 | STRLEN dc, dd; /* dummy */ |
362 | STRLEN dc, dd; /* dummy */ |
|
|
363 | I32 orig_stack = SP - PL_stack_base; |
293 | |
364 | |
294 | /* save our arguments against destruction through function calls */ |
365 | /* save our arguments against destruction through function calls */ |
295 | SP += items; |
366 | SP += items; |
296 | |
367 | |
297 | /* first check wether we should use an explicit db handle */ |
368 | /* first check wether we should use an explicit db handle */ |
… | |
… | |
337 | sv_catpv (neu, " limit 1"); |
408 | sv_catpv (neu, " limit 1"); |
338 | sql = neu; |
409 | sql = neu; |
339 | ix -= 4; /* sql_fetch */ |
410 | ix -= 4; /* sql_fetch */ |
340 | } |
411 | } |
341 | |
412 | |
|
|
413 | /* now prepare all parameters, by unmagicalising them and upgrading them */ |
|
|
414 | for (i = arg; i < items; ++i) |
|
|
415 | { |
|
|
416 | SV *sv = ST (i); |
|
|
417 | |
|
|
418 | /* we sv_mortalcopy magical values since DBI seems to have a memory |
|
|
419 | * leak when magical values are passed into execute(). |
|
|
420 | */ |
|
|
421 | if (SvMAGICAL (sv)) |
|
|
422 | ST (i) = sv = sv_mortalcopy (sv); |
|
|
423 | |
|
|
424 | if ((ix & 1) && SvPOKp (sv) && !SvUTF8 (sv)) |
|
|
425 | { |
|
|
426 | ST (i) = sv = sv_mortalcopy (sv); |
|
|
427 | sv_utf8_upgrade (sv); |
|
|
428 | } |
|
|
429 | } |
|
|
430 | |
342 | /* check cache for existing statement handle */ |
431 | /* check cache for existing statement handle */ |
|
|
432 | lru = SvCUR (sql) <= MAX_CACHED_STATEMENT_SIZE |
343 | sth = lru_fetch (dbh, sql); |
433 | ? lru_fetch (dbh, sql) |
|
|
434 | : 0; |
344 | if (!sth) |
435 | if (!lru) |
345 | { |
436 | { |
|
|
437 | mc = mc_find (SvSTASH (SvRV (dbh))); |
|
|
438 | |
|
|
439 | if (!mc->prepare) |
|
|
440 | mc_cache (mc, prepare); |
|
|
441 | |
346 | PUSHMARK (SP); |
442 | PUSHMARK (SP); |
347 | EXTEND (SP, 2); |
443 | EXTEND (SP, 2); |
348 | PUSHs (dbh); |
444 | PUSHs (dbh); |
349 | PUSHs (sql); |
445 | PUSHs (sql); |
350 | PUTBACK; |
446 | PUTBACK; |
351 | count = call_sv (sv_prepare, G_METHOD | G_SCALAR); |
447 | count = call_sv (mc->prepare, G_SCALAR); |
352 | SPAGAIN; |
448 | SPAGAIN; |
353 | |
449 | |
354 | if (count != 1) |
450 | if (count != 1) |
355 | croak ("sql_exec: unable to prepare() statement '%s': %s", |
451 | croak ("sql_exec: unable to prepare() statement '%s': %s", |
356 | SvPV (sql, dc), |
452 | SvPV (sql, dc), |
357 | SvPV (get_sv ("DBI::errstr", TRUE), dd)); |
453 | SvPV (get_sv ("DBI::errstr", TRUE), dd)); |
358 | |
454 | |
359 | sth = POPs; |
455 | sth = POPs; |
360 | |
456 | |
|
|
457 | mc = mc_find (SvSTASH (SvRV (sth))); |
|
|
458 | |
|
|
459 | if (!mc->bind_param) |
|
|
460 | { |
|
|
461 | mc_cache (mc, bind_param); |
|
|
462 | mc_cache (mc, execute); |
|
|
463 | mc_cache (mc, finish); |
|
|
464 | } |
|
|
465 | |
361 | if (SvLEN (sql) < MAX_CACHED_STATEMENT_SIZE) |
466 | if (SvCUR (sql) <= MAX_CACHED_STATEMENT_SIZE) |
362 | lru_store (dbh, sql, sth); |
467 | lru_store (dbh, sql, sth, mc); |
363 | } |
|
|
364 | |
468 | |
365 | PUSHMARK (SP); |
469 | /* on first execution we unfortunately need to use bind_param |
366 | EXTEND (SP, items - arg + 1); |
470 | * to mark any numeric parameters as such. |
367 | PUSHs (sth); |
|
|
368 | while (items > arg) |
|
|
369 | { |
|
|
370 | SV *sv = ST(arg); |
|
|
371 | /* we sv_mortalcopy magical values since DBI seems to have a memory |
|
|
372 | * leak when magical values are passed into execute(). |
|
|
373 | */ |
471 | */ |
374 | PUSHs (maybe_upgrade_utf8 (ix & 1, SvMAGICAL(sv) ? sv_mortalcopy(sv) : sv)); |
472 | SvIV_set (tmp_iv, 0); |
|
|
473 | |
|
|
474 | while (items > arg) |
|
|
475 | { |
|
|
476 | SV *sv = ST (arg); |
|
|
477 | /* we sv_mortalcopy magical values since DBI seems to have a memory |
|
|
478 | * leak when magical values are passed into execute(). |
|
|
479 | */ |
|
|
480 | |
|
|
481 | PUSHMARK (SP); |
|
|
482 | EXTEND (SP, 4); |
|
|
483 | PUSHs (sth); |
|
|
484 | SvIVX (tmp_iv)++; |
|
|
485 | PUSHs (tmp_iv); |
|
|
486 | PUSHs (sv); |
|
|
487 | |
|
|
488 | PUSHs ( |
|
|
489 | SvPOKp (sv) ? sql_varchar |
|
|
490 | : SvNOKp (sv) ? sql_double |
|
|
491 | : SvIOKp (sv) ? sql_integer |
|
|
492 | : sql_varchar |
|
|
493 | ); |
|
|
494 | |
|
|
495 | PUTBACK; |
|
|
496 | call_sv (mc->bind_param, G_VOID); |
|
|
497 | SPAGAIN; |
|
|
498 | |
375 | arg++; |
499 | arg++; |
|
|
500 | } |
|
|
501 | |
|
|
502 | /* now use execute without any arguments */ |
|
|
503 | PUSHMARK (SP); |
|
|
504 | EXTEND (SP, 1); |
|
|
505 | PUSHs (sth); |
|
|
506 | } |
|
|
507 | else |
|
|
508 | { |
|
|
509 | sth = sv_2mortal (SvREFCNT_inc (lru->sth)); |
|
|
510 | mc = lru->mc; |
|
|
511 | |
|
|
512 | /* we have previously executed this statement, so we |
|
|
513 | * use the cached types and use execute with arguments. |
|
|
514 | */ |
|
|
515 | |
|
|
516 | PUSHMARK (SP); |
|
|
517 | EXTEND (SP, items - arg + 1); |
|
|
518 | PUSHs (sth); |
|
|
519 | while (items > arg) |
|
|
520 | { |
|
|
521 | SV *sv = ST (arg); |
|
|
522 | PUSHs (ST (arg)); |
|
|
523 | arg++; |
|
|
524 | } |
376 | } |
525 | } |
377 | |
526 | |
378 | PUTBACK; |
527 | PUTBACK; |
379 | /* { static GV *execute; |
528 | /* { static GV *execute; |
380 | if (!execute) execute = gv_fetchmethod_autoload(SvSTASH(SvRV(sth)), "execute", 0); |
529 | if (!execute) execute = gv_fetchmethod_autoload(SvSTASH(SvRV(sth)), "execute", 0); |
381 | count = call_sv(GvCV(execute), G_SCALAR); |
530 | count = call_sv(GvCV(execute), G_SCALAR); |
382 | }*/ |
531 | }*/ |
383 | count = call_sv (sv_execute, G_METHOD | G_SCALAR); |
532 | count = call_sv (mc->execute, G_SCALAR); |
384 | SPAGAIN; |
533 | SPAGAIN; |
385 | |
534 | |
386 | if (count != 1) |
535 | if (count != 1) |
387 | croak ("sql_exec: execute() didn't return any value ('%s'): %s", |
536 | croak ("sql_exec: execute() didn't return any value ('%s'): %s", |
388 | SvPV (sql, dc), |
537 | SvPV (sql, dc), |
… | |
… | |
393 | if (!SvTRUE (execute)) |
542 | if (!SvTRUE (execute)) |
394 | croak ("sql_exec: unable to execute statement '%s' (%s)", |
543 | croak ("sql_exec: unable to execute statement '%s' (%s)", |
395 | SvPV (sql, dc), |
544 | SvPV (sql, dc), |
396 | SvPV (get_sv ("DBI::errstr", TRUE), dd)); |
545 | SvPV (get_sv ("DBI::errstr", TRUE), dd)); |
397 | |
546 | |
398 | sv_setsv (GvSV(sql_exec), execute); |
547 | sv_setsv (GvSV (sql_exec), execute); |
399 | |
548 | |
400 | if (bind_first != bind_last) |
549 | if (bind_first != bind_last) |
401 | { |
550 | { |
402 | PUSHMARK (SP); |
551 | PUSHMARK (SP); |
403 | EXTEND (SP, bind_last - bind_first + 2); |
552 | EXTEND (SP, bind_last - bind_first + 2); |
… | |
… | |
410 | PUSHs (ST(bind_first)); |
559 | PUSHs (ST(bind_first)); |
411 | bind_first++; |
560 | bind_first++; |
412 | } while (bind_first != bind_last); |
561 | } while (bind_first != bind_last); |
413 | |
562 | |
414 | PUTBACK; |
563 | PUTBACK; |
|
|
564 | |
|
|
565 | if (!mc->bind_columns) |
|
|
566 | mc_cache (mc, bind_columns); |
|
|
567 | |
415 | count = call_sv (sv_bind_columns, G_METHOD | G_SCALAR); |
568 | count = call_sv (mc->bind_columns, G_SCALAR); |
|
|
569 | |
416 | SPAGAIN; |
570 | SPAGAIN; |
417 | |
571 | |
418 | if (count != 1) |
572 | if (count != 1) |
419 | croak ("sql_exec: bind_columns() didn't return any value ('%s'): %s", |
573 | croak ("sql_exec: bind_columns() didn't return any value ('%s'): %s", |
420 | SvPV (sql, dc), |
574 | SvPV (sql, dc), |
… | |
… | |
426 | SvPV (get_sv ("DBI::errstr", TRUE), dd)); |
580 | SvPV (get_sv ("DBI::errstr", TRUE), dd)); |
427 | |
581 | |
428 | POPs; |
582 | POPs; |
429 | } |
583 | } |
430 | |
584 | |
431 | /* restore our arguments again */ |
|
|
432 | SP -= items; |
|
|
433 | |
|
|
434 | if ((ix & ~1) == 2) |
585 | if ((ix & ~1) == 2) |
435 | { /* sql_fetch */ |
586 | { /* sql_fetch */ |
436 | SV *row; |
587 | SV *row; |
437 | |
588 | |
438 | PUSHMARK (SP); |
589 | PUSHMARK (SP); |
439 | XPUSHs (sth); |
590 | XPUSHs (sth); |
440 | PUTBACK; |
591 | PUTBACK; |
|
|
592 | |
|
|
593 | if (!mc->fetchrow_arrayref) |
|
|
594 | mc_cache (mc, fetchrow_arrayref); |
|
|
595 | |
441 | count = call_sv (sv_fetchrow_arrayref, G_METHOD | G_SCALAR); |
596 | count = call_sv (mc->fetchrow_arrayref, G_SCALAR); |
442 | SPAGAIN; |
597 | SPAGAIN; |
443 | |
598 | |
444 | if (count != 1) |
599 | if (count != 1) |
445 | abort (); |
600 | abort (); |
446 | |
601 | |
447 | row = POPs; |
602 | row = POPs; |
|
|
603 | |
|
|
604 | SP = PL_stack_base + orig_stack; |
448 | |
605 | |
449 | if (SvROK (row)) |
606 | if (SvROK (row)) |
450 | { |
607 | { |
451 | AV *av; |
608 | AV *av; |
452 | |
609 | |
… | |
… | |
456 | /* no thing */ |
613 | /* no thing */ |
457 | break; |
614 | break; |
458 | case G_SCALAR: |
615 | case G_SCALAR: |
459 | /* the first element */ |
616 | /* the first element */ |
460 | XPUSHs (mortalcopy_and_maybe_force_utf8 (ix & 1, *av_fetch ((AV *)SvRV (row), 0, 1))); |
617 | XPUSHs (mortalcopy_and_maybe_force_utf8 (ix & 1, *av_fetch ((AV *)SvRV (row), 0, 1))); |
|
|
618 | count = 1; |
461 | break; |
619 | break; |
462 | case G_ARRAY: |
620 | case G_ARRAY: |
463 | av = (AV *)SvRV (row); |
621 | av = (AV *)SvRV (row); |
464 | count = AvFILL (av) + 1; |
622 | count = AvFILL (av) + 1; |
465 | EXTEND (SP, count); |
623 | EXTEND (SP, count); |
… | |
… | |
477 | SV *rows; |
635 | SV *rows; |
478 | |
636 | |
479 | PUSHMARK (SP); |
637 | PUSHMARK (SP); |
480 | XPUSHs (sth); |
638 | XPUSHs (sth); |
481 | PUTBACK; |
639 | PUTBACK; |
|
|
640 | |
|
|
641 | if (!mc->fetchall_arrayref) |
|
|
642 | mc_cache (mc, fetchall_arrayref); |
|
|
643 | |
482 | count = call_sv (sv_fetchall_arrayref, G_METHOD | G_SCALAR); |
644 | count = call_sv (mc->fetchall_arrayref, G_SCALAR); |
483 | SPAGAIN; |
645 | SPAGAIN; |
484 | |
646 | |
485 | if (count != 1) |
647 | if (count != 1) |
486 | abort (); |
648 | abort (); |
487 | |
649 | |
488 | rows = POPs; |
650 | rows = POPs; |
|
|
651 | |
|
|
652 | SP = PL_stack_base + orig_stack; |
489 | |
653 | |
490 | if (SvROK (rows)) |
654 | if (SvROK (rows)) |
491 | { |
655 | { |
492 | AV *av = (AV *)SvRV (rows); |
656 | AV *av = (AV *)SvRV (rows); |
493 | count = AvFILL (av) + 1; |
657 | count = AvFILL (av) + 1; |
… | |
… | |
505 | PUSHs (mortalcopy_and_maybe_force_utf8 (ix & 1, AvARRAY (av)[arg])); |
669 | PUSHs (mortalcopy_and_maybe_force_utf8 (ix & 1, AvARRAY (av)[arg])); |
506 | } |
670 | } |
507 | } |
671 | } |
508 | } |
672 | } |
509 | else |
673 | else |
|
|
674 | { |
|
|
675 | SP = PL_stack_base + orig_stack; |
510 | XPUSHs (sth); |
676 | XPUSHs (sth); |
|
|
677 | } |
511 | |
678 | |
512 | if (ix > 1 || GIMME_V == G_VOID) |
679 | if (ix > 1 || GIMME_V == G_VOID) |
513 | { |
680 | { |
|
|
681 | orig_stack = SP - PL_stack_base; |
|
|
682 | |
514 | PUSHMARK (SP); |
683 | PUSHMARK (SP); |
515 | XPUSHs (sth); |
684 | XPUSHs (sth); |
516 | PUTBACK; |
685 | PUTBACK; |
|
|
686 | |
|
|
687 | if (!mc->finish) |
|
|
688 | mc_cache (mc, finish); |
|
|
689 | |
517 | (void) call_sv (sv_finish, G_METHOD | G_DISCARD); |
690 | call_sv (mc->finish, G_DISCARD); |
518 | SPAGAIN; |
691 | SPAGAIN; |
|
|
692 | |
|
|
693 | SP = PL_stack_base + orig_stack; |
519 | } |
694 | } |
520 | } |
695 | } |
521 | } |
696 | } |
522 | |
697 | |
523 | |
698 | |