ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/PApp-SQL/SQL.xs
(Generate patch)

Comparing PApp-SQL/SQL.xs (file contents):
Revision 1.19 by root, Sat Jan 19 07:38:52 2008 UTC vs.
Revision 1.31 by root, Thu Sep 9 13:57:41 2021 UTC

1#include "EXTERN.h" 1#include "EXTERN.h"
2#include "perl.h" 2#include "perl.h"
3#include "XSUB.h" 3#include "XSUB.h"
4
5/* import some stuff from DBIXS.h and DBI.xs */
6#define DBIXS_VERSION 93
7#define DBI_MAGIC '~'
8
9#define DBISTATE_PERLNAME "DBI::_dbistate"
10#define DBISTATE_ADDRSV (perl_get_sv (DBISTATE_PERLNAME, 0x05))
11#define DBIS_PUBLISHED_LVALUE (*(INT2PTR(dbistate_t**, &SvIVX(DBISTATE_ADDRSV))))
12
13static SV *sql_varchar, *sql_integer, *sql_double;
14static SV *tmp_iv;
15
16struct dbistate_st {
17#define DBISTATE_VERSION 94 /* Must change whenever dbistate_t does */
18 /* this must be the first member in structure */
19 void (*check_version) _((const char *name,
20 int dbis_cv, int dbis_cs, int need_dbixs_cv,
21 int drc_s, int dbc_s, int stc_s, int fdc_s));
22
23 /* version and size are used to check for DBI/DBD version mis-match */
24 U16 version; /* version of this structure */
25 U16 size;
26 U16 xs_version; /* version of the overall DBIXS / DBD interface */
27 U16 spare_pad;
28};
29typedef struct dbistate_st dbistate_t;
30
31#define DBIcf_ACTIVE 0x000004 /* needs finish/disconnect before clear */
32
33typedef U32 imp_sth;
34
35/* not strictly part of the API... */
36static imp_sth *
37sth_get_imp (SV *sth)
38{
39 MAGIC *mg = mg_find (SvRV (sth), PERL_MAGIC_tied);
40 sth = mg->mg_obj;
41 mg = mg_find (SvRV (sth), DBI_MAGIC);
42 return (imp_sth *)SvPVX (mg->mg_obj);
43}
44
45#define DBI_STH_ACTIVE(imp) (*(imp) & DBIcf_ACTIVE)
46
47/* end of import section */
4 48
5#if (PERL_VERSION < 5) || ((PERL_VERSION == 5) && (PERL_SUBVERSION <= 6)) 49#if (PERL_VERSION < 5) || ((PERL_VERSION == 5) && (PERL_SUBVERSION <= 6))
6# define get_sv perl_get_sv 50# define get_sv perl_get_sv
7# define call_method perl_call_method 51# define call_method perl_call_method
8# define call_sv perl_call_sv 52# define call_sv perl_call_sv
10 54
11#if (PERL_VERSION > 5) || ((PERL_VERSION == 5) && (PERL_SUBVERSION >= 6)) 55#if (PERL_VERSION > 5) || ((PERL_VERSION == 5) && (PERL_SUBVERSION >= 6))
12# define CAN_UTF8 1 56# define CAN_UTF8 1
13#endif 57#endif
14 58
15#define MAX_CACHED_STATEMENT_SIZE 8192 59#define MAX_CACHED_STATEMENT_SIZE 2048
16 60
17static SV * 61static SV *
18sql_upgrade_utf8 (SV *sv) 62sql_upgrade_utf8 (SV *sv)
19{ 63{
20#if CAN_UTF8 64#if CAN_UTF8
21 if (SvPOK (sv)) 65 if (SvPOKp (sv))
22 sv_utf8_upgrade (sv); 66 sv_utf8_upgrade (sv);
23#endif 67#endif
24 return sv; 68 return sv;
25} 69}
26 70
27static SV * 71static SV *
28mortalcopy_and_maybe_force_utf8(int utf8, SV *sv) 72mortalcopy_and_maybe_force_utf8(int utf8, SV *sv)
29{ 73{
30 sv = sv_mortalcopy (sv); 74 sv = sv_mortalcopy (sv);
31#if CAN_UTF8 75#if CAN_UTF8
32 if (utf8 && SvPOK (sv)) 76 if (utf8 && SvPOKp (sv))
33 SvUTF8_on (sv); 77 SvUTF8_on (sv);
34#endif 78#endif
35 return sv; 79 return sv;
36} 80}
37 81
38#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))
39 83
40#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"))
41 85
86typedef 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
104static mc_node *first;
105
106static mc_node *
107mc_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
143static void
144mc_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, please report.", name);
150}
151
152#define mc_cache(mc, method) mc_cache ((mc), &((mc)->method), # method)
153
42typedef struct lru_node { 154typedef struct lru_node
155{
43 struct lru_node *next; 156 struct lru_node *next;
44 struct lru_node *prev; 157 struct lru_node *prev;
158
45 U32 hash; 159 U32 hash;
46 SV *dbh; 160 SV *dbh;
47 SV *sql; 161 SV *sql;
48 162
49 SV *sth; 163 SV *sth;
50#if 0 /* method cache */ 164 imp_sth *sth_imp;
51 GV *execute; 165
52 GV *bind_columns; 166 mc_node *mc;
53 GV *fetch;
54 GV *finish;
55#endif
56} lru_node; 167} lru_node;
57 168
58static lru_node lru_list; 169static lru_node lru_list;
59static int lru_size; 170static int lru_size;
60static int lru_maxsize; 171static int lru_maxsize;
61 172
62#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 */
63 174
64/* this is primitive, yet effective */ 175/* this is primitive, yet effective */
65/* 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) */
66#define lru_hash do { \ 177static U32
67 hash = (((U32)(long)dbh)>>2); \ 178lru_hash (SV *dbh, SV *sql)
68 hash += *statement;\ 179{
69 hash += len; \ 180 /* use a variant of fnv1a */
70} while (0) 181 STRLEN i, l;
182 char *b = SvPV (sql, l);
183 U32 hash = 2166136261U;
184
185 hash = (hash ^ (U32)dbh) * 16777619U;
186 hash = (hash ^ l) * 16777619U;
187
188 /* start hashing at char 7, as this skips the "select " prefix */
189 /* also skip more and more octets */
190 for (i = 7; i < l; i += i >> 2)
191 hash = (hash ^ b [i]) * 16777619U;
192
193 return hash;
194}
71 195
72/* fetch and "use" */ 196/* fetch and "use" */
73/* could be done using a single call (we could call prepare!) */ 197static lru_node *
74static SV *lru_fetch(SV *dbh, SV *sql) 198lru_fetch (SV *dbh, SV *sql)
75{ 199{
76 lru_node *n; 200 lru_node *n;
77
78 U32 hash; 201 U32 hash;
79 STRLEN len;
80 char *statement = SvPV (sql, len);
81 202
82 dbh = SvRV (dbh); 203 dbh = SvRV (dbh);
83 204 hash = lru_hash (dbh, sql);
84 lru_hash;
85 205
86 n = &lru_list; 206 n = &lru_list;
87 do { 207 do {
88 n = n->next; 208 n = n->next;
209
89 if (!n->hash) 210 if (!n->hash)
90 return 0; 211 return 0;
91 } while (n->hash != hash 212 } while (n->hash != hash
213 || DBI_STH_ACTIVE (n->sth_imp)
92 || !sv_eq (n->sql, sql) 214 || !sv_eq (n->sql, sql)
93 || n->dbh != dbh); 215 || n->dbh != dbh);
94 216
95 /* found, so return to the start of the list */ 217 /* found, so return to the start of the list */
96 n->prev->next = n->next; 218 n->prev->next = n->next;
99 n->next = lru_list.next; 221 n->next = lru_list.next;
100 n->prev = &lru_list; 222 n->prev = &lru_list;
101 lru_list.next->prev = n; 223 lru_list.next->prev = n;
102 lru_list.next = n; 224 lru_list.next = n;
103 225
104 return n->sth; 226 return n;
105} 227}
106 228
107static void lru_nukeone(void) 229static void
230lru_trim (void)
231{
232 while (lru_size > lru_maxsize)
233 {
234 /* nuke at the end */
235 lru_node *n = lru_list.prev;
236
237 n = lru_list.prev;
238
239 lru_list.prev = n->prev;
240 n->prev->next = &lru_list;
241
242 SvREFCNT_dec (n->dbh);
243 SvREFCNT_dec (n->sql);
244 SvREFCNT_dec (n->sth);
245 Safefree (n);
246
247 lru_size--;
248 }
249}
250
251/* store a not-yet existing entry(!) */
252static void
253lru_store (SV *dbh, SV *sql, SV *sth, mc_node *mc)
108{ 254{
109 lru_node *n; 255 lru_node *n;
110 /* nuke at the end */ 256 U32 hash;
111 257
112 n = lru_list.prev; 258 if (!lru_maxsize)
113 259 return;
114 lru_list.prev = n->prev;
115 n->prev->next = &lru_list;
116
117 SvREFCNT_dec (n->dbh);
118 SvREFCNT_dec (n->sql);
119 SvREFCNT_dec (n->sth);
120 Safefree (n);
121 260
122 lru_size--;
123}
124
125/* store a not-yet existing entry(!) */
126static void lru_store(SV *dbh, SV *sql, SV *sth)
127{
128 lru_node *n;
129
130 U32 hash;
131 STRLEN len;
132 char *statement = SvPV (sql, len);
133
134 dbh = SvRV (dbh); 261 dbh = SvRV (dbh);
135 262 hash = lru_hash (dbh, sql);
136 lru_hash;
137 263
138 lru_size++; 264 lru_size++;
139 if (lru_size > lru_maxsize) 265 lru_trim ();
140 lru_nukeone ();
141 266
142 New (0, n, 1, lru_node); 267 New (0, n, 1, lru_node);
143 268
144 n->hash = hash; 269 n->hash = hash;
145 n->dbh = dbh; SvREFCNT_inc (dbh); /* note: this is the dbi hash itself, not the reference */ 270 n->dbh = dbh; SvREFCNT_inc (dbh); /* note: this is the dbi hash itself, not the reference */
146 n->sql = newSVsv (sql); 271 n->sql = newSVsv (sql);
147 n->sth = sth; SvREFCNT_inc (sth); 272 n->sth = sth; SvREFCNT_inc (sth);
273 n->sth_imp = sth_get_imp (sth);
274 n->mc = mc;
148 275
149 n->next = lru_list.next; 276 n->next = lru_list.next;
150 n->prev = &lru_list; 277 n->prev = &lru_list;
151 lru_list.next->prev = n; 278 lru_list.next->prev = n;
152 lru_list.next = n; 279 lru_list.next = n;
153} 280}
154 281
282static void
155static void lru_cachesize (int size) 283lru_cachesize (int size)
156{ 284{
157 if (size >= 0) 285 if (size >= 0)
158 { 286 {
159 lru_maxsize = size; 287 lru_maxsize = size;
160 while (lru_size > lru_maxsize) 288 lru_trim ();
161 lru_nukeone ();
162 } 289 }
163} 290}
164 291
165static GV *sql_exec; 292static GV *sql_exec;
166static GV *DBH; 293static GV *DBH;
167static SV *sv_prepare, *sv_execute, *sv_bind_columns,
168 *sv_fetchrow_arrayref, *sv_fetchall_arrayref,
169 *sv_finish;
170 294
171#define newconstpv(str) newSVpvn ((str), sizeof (str)) 295#define newconstpv(str) newSVpvn ((str), sizeof (str))
172 296
173MODULE = PApp::SQL PACKAGE = PApp::SQL 297MODULE = PApp::SQL PACKAGE = PApp::SQL
174 298
175PROTOTYPES: DISABLE 299PROTOTYPES: DISABLE
176 300
177BOOT: 301BOOT:
178{ 302{
303 struct dbistate_st *dbis = DBIS_PUBLISHED_LVALUE;
304
305 /* this is actually wrong, we should call the check member, apparently */
306 assert (dbis->version == DBISTATE_VERSION);
307 assert (dbis->xs_version == DBIXS_VERSION);
308
309 tmp_iv = newSViv (0);
310
179 sql_exec = gv_fetchpv ("PApp::SQL::sql_exec", TRUE, SVt_PV); 311 sql_exec = gv_fetchpv ("PApp::SQL::sql_exec", TRUE, SVt_PV);
180 DBH = gv_fetchpv ("PApp::SQL::DBH" , TRUE, SVt_PV); 312 DBH = gv_fetchpv ("PApp::SQL::DBH" , TRUE, SVt_PV);
181
182 if (!sv_prepare)
183 {
184 sv_prepare = newconstpv ("prepare");
185 sv_execute = newconstpv ("execute");
186 sv_bind_columns = newconstpv ("bind_columns");
187 sv_fetchrow_arrayref = newconstpv ("fetchrow_arrayref");
188 sv_fetchall_arrayref = newconstpv ("fetchall_arrayref");
189 sv_finish = newconstpv ("finish");
190 }
191 313
192 /* apache might BOOT: twice :( */ 314 /* apache might BOOT: twice :( */
193 if (lru_size) 315 if (lru_size)
194 lru_cachesize (0); 316 lru_cachesize (0);
195 317
196 lru_init; 318 lru_init ();
197 lru_cachesize (50); 319 lru_cachesize (100);
198} 320}
321
322void
323boot2 (SV *t_str, SV *t_int, SV *t_dbl)
324 CODE:
325 sql_varchar = newSVsv (t_str);
326 sql_integer = newSVsv (t_int);
327 sql_double = newSVsv (t_dbl);
199 328
200int 329int
201cachesize(size = -1) 330cachesize(size = -1)
202 int size 331 int size
203 CODE: 332 CODE:
208 337
209void 338void
210sql_exec(...) 339sql_exec(...)
211 ALIAS: 340 ALIAS:
212 sql_uexec = 1 341 sql_uexec = 1
213 sql_fetch = 2 342 sql_fetch = 2
214 sql_ufetch = 3 343 sql_ufetch = 3
215 sql_fetchall = 4 344 sql_fetchall = 4
216 sql_ufetchall = 5 345 sql_ufetchall = 5
217 sql_exists = 6 346 sql_exists = 6
218 sql_uexists = 7 347 sql_uexists = 7
220{ 349{
221 if (items == 0) 350 if (items == 0)
222 croak ("Usage: sql_exec [database-handle,] [bind-var-refs,... ] \"sql-statement\", [arguments, ...]"); 351 croak ("Usage: sql_exec [database-handle,] [bind-var-refs,... ] \"sql-statement\", [arguments, ...]");
223 else 352 else
224 { 353 {
354 int i;
225 int arg = 0; 355 int arg = 0;
226 int bind_first, bind_last; 356 int bind_first, bind_last;
227 int count; 357 int count;
358 lru_node *lru;
228 SV *dbh = ST(0); 359 SV *dbh = ST(0);
229 SV *sth; 360 SV *sth;
230 SV *sql; 361 SV *sql;
231 SV *execute; 362 SV *execute;
363 mc_node *mc;
232 STRLEN dc, dd; /* dummy */ 364 STRLEN dc, dd; /* dummy */
365 I32 orig_stack = SP - PL_stack_base;
233 366
234 /* save our arguments against destruction through function calls */ 367 /* save our arguments against destruction through function calls */
235 SP += items; 368 SP += items;
236 369
237 /* first check wether we should use an explicit db handle */ 370 /* first check wether we should use an explicit db handle */
239 { 372 {
240 /* the next line doesn't work - check why later maybe */ 373 /* the next line doesn't work - check why later maybe */
241 /* dbh = get_sv ("DBH", FALSE); 374 /* dbh = get_sv ("DBH", FALSE);
242 if (!is_dbh (dbh)) 375 if (!is_dbh (dbh))
243 {*/ 376 {*/
244 dbh = GvSV(DBH); 377 dbh = GvSV (DBH);
245 if (!is_dbh (dbh)) 378 if (!is_dbh (dbh))
246 croak ("sql_exec: no $DBH argument and no fallback in $PApp::SQL::DBH"); 379 croak ("sql_exec: no $DBH argument and no fallback in $PApp::SQL::DBH");
247 /*croak ("sql_exec: no $DBH found in current package or in PApp::SQL::"); 380 /*croak ("sql_exec: no $DBH found in current package or in PApp::SQL::");
248 }*/ 381 }*/
249 } 382 }
250 else 383 else
251 arg++; /* we consumed one argument */ 384 arg++; /* we consumed one argument */
385
386 /* be more Coro-friendly by keeping a copy, so different threads */
387 /* can replace their global handles */
388 dbh = sv_2mortal (newSVsv (dbh));
252 389
253 /* count the remaining references (for bind_columns) */ 390 /* count the remaining references (for bind_columns) */
254 bind_first = arg; 391 bind_first = arg;
255 while (items > arg && SvROK (ST(arg))) 392 while (items > arg && SvROK (ST(arg)))
256 arg++; 393 arg++;
273 sv_catpv (neu, " limit 1"); 410 sv_catpv (neu, " limit 1");
274 sql = neu; 411 sql = neu;
275 ix -= 4; /* sql_fetch */ 412 ix -= 4; /* sql_fetch */
276 } 413 }
277 414
415 /* now prepare all parameters, by unmagicalising them and upgrading them */
416 for (i = arg; i < items; ++i)
417 {
418 SV *sv = ST (i);
419
420 /* we sv_mortalcopy magical values since DBI seems to have a memory
421 * leak when magical values are passed into execute().
422 */
423 if (SvMAGICAL (sv))
424 ST (i) = sv = sv_mortalcopy (sv);
425
426 if ((ix & 1) && SvPOKp (sv) && !SvUTF8 (sv))
427 {
428 ST (i) = sv = sv_mortalcopy (sv);
429 sv_utf8_upgrade (sv);
430 }
431 }
432
278 /* check cache for existing statement handle */ 433 /* check cache for existing statement handle */
434 lru = SvCUR (sql) <= MAX_CACHED_STATEMENT_SIZE
279 sth = lru_fetch (dbh, sql); 435 ? lru_fetch (dbh, sql)
436 : 0;
280 if (!sth) 437 if (!lru)
281 { 438 {
439 mc = mc_find (SvSTASH (SvRV (dbh)));
440
441 if (!mc->prepare)
442 mc_cache (mc, prepare);
443
282 PUSHMARK (SP); 444 PUSHMARK (SP);
283 EXTEND (SP, 2); 445 EXTEND (SP, 2);
284 PUSHs (dbh); 446 PUSHs (dbh);
285 PUSHs (sql); 447 PUSHs (sql);
286 PUTBACK; 448 PUTBACK;
287 count = call_sv (sv_prepare, G_METHOD | G_SCALAR); 449 count = call_sv (mc->prepare, G_SCALAR);
288 SPAGAIN; 450 SPAGAIN;
289 451
290 if (count != 1) 452 if (count != 1)
291 croak ("sql_exec: unable to prepare() statement '%s': %s", 453 croak ("sql_exec: unable to prepare() statement '%s': %s",
292 SvPV (sql, dc), 454 SvPV (sql, dc),
293 SvPV (get_sv ("DBI::errstr", TRUE), dd)); 455 SvPV (get_sv ("DBI::errstr", TRUE), dd));
294 456
295 sth = POPs; 457 sth = POPs;
296 458
459 if (!SvROK (sth))
460 croak ("sql_exec: buggy DBD driver, prepare returned non-reference for '%s': %s",
461 SvPV (sql, dc),
462 SvPV (get_sv ("DBI::errstr", TRUE), dd));
463
464 mc = mc_find (SvSTASH (SvRV (sth)));
465
466 if (!mc->bind_param)
467 {
468 mc_cache (mc, bind_param);
469 mc_cache (mc, execute);
470 mc_cache (mc, finish);
471 }
472
297 if (SvLEN (sql) < MAX_CACHED_STATEMENT_SIZE) 473 if (SvCUR (sql) <= MAX_CACHED_STATEMENT_SIZE)
298 lru_store (dbh, sql, sth); 474 lru_store (dbh, sql, sth, mc);
475
476 /* on first execution we unfortunately need to use bind_param
477 * to mark any numeric parameters as such.
299 } 478 */
479 SvIV_set (tmp_iv, 0);
300 480
301 PUSHMARK (SP);
302 EXTEND (SP, items - arg + 1);
303 PUSHs (sth);
304 while (items > arg) 481 while (items > arg)
482 {
483 SV *sv = ST (arg);
484 /* we sv_mortalcopy magical values since DBI seems to have a memory
485 * leak when magical values are passed into execute().
486 */
487
488 PUSHMARK (SP);
489 EXTEND (SP, 4);
490 PUSHs (sth);
491 SvIVX (tmp_iv)++;
492 SvIOK_only (tmp_iv);
493 PUSHs (tmp_iv);
494 PUSHs (sv);
495
496 PUSHs (
497 SvPOKp (sv) ? sql_varchar
498 : SvNOKp (sv) ? sql_double
499 : SvIOKp (sv) ? sql_integer
500 : sql_varchar
501 );
502
503 PUTBACK;
504 call_sv (mc->bind_param, G_VOID);
505 SPAGAIN;
506
507 arg++;
508 }
509
510 /* now use execute without any arguments */
511 PUSHMARK (SP);
512 EXTEND (SP, 1);
513 PUSHs (sth);
514 }
515 else
305 { 516 {
306 SV *sv = ST(arg); 517 sth = sv_2mortal (SvREFCNT_inc (lru->sth));
307 /* we sv_mortalcopy magical values since DBI seems to have a memory 518 mc = lru->mc;
308 * leak when magical values are passed into execute(). 519
520 /* we have previously executed this statement, so we
521 * use the cached types and use execute with arguments.
309 */ 522 */
310 PUSHs (maybe_upgrade_utf8 (ix & 1, SvMAGICAL(sv) ? sv_mortalcopy(sv) : sv)); 523
524 PUSHMARK (SP);
525 EXTEND (SP, items - arg + 1);
526 PUSHs (sth);
527 while (items > arg)
528 {
529 SV *sv = ST (arg);
530 PUSHs (sv);
311 arg++; 531 arg++;
532 }
312 } 533 }
313 534
314 PUTBACK; 535 PUTBACK;
315 /* { static GV *execute; 536 /* { static GV *execute;
316 if (!execute) execute = gv_fetchmethod_autoload(SvSTASH(SvRV(sth)), "execute", 0); 537 if (!execute) execute = gv_fetchmethod_autoload(SvSTASH(SvRV(sth)), "execute", 0);
317 count = call_sv(GvCV(execute), G_SCALAR); 538 count = call_sv(GvCV(execute), G_SCALAR);
318 }*/ 539 }*/
319 count = call_sv (sv_execute, G_METHOD | G_SCALAR); 540 count = call_sv (mc->execute, G_SCALAR);
320 SPAGAIN; 541 SPAGAIN;
321 542
322 if (count != 1) 543 if (count != 1)
323 croak ("sql_exec: execute() didn't return any value ('%s'): %s", 544 croak ("sql_exec: execute() didn't return any value ('%s'): %s",
324 SvPV (sql, dc), 545 SvPV (sql, dc),
329 if (!SvTRUE (execute)) 550 if (!SvTRUE (execute))
330 croak ("sql_exec: unable to execute statement '%s' (%s)", 551 croak ("sql_exec: unable to execute statement '%s' (%s)",
331 SvPV (sql, dc), 552 SvPV (sql, dc),
332 SvPV (get_sv ("DBI::errstr", TRUE), dd)); 553 SvPV (get_sv ("DBI::errstr", TRUE), dd));
333 554
334 sv_setsv (GvSV(sql_exec), execute); 555 sv_setsv (GvSV (sql_exec), execute);
335 556
336 if (bind_first != bind_last) 557 if (bind_first != bind_last)
337 { 558 {
338 PUSHMARK (SP); 559 PUSHMARK (SP);
339 EXTEND (SP, bind_last - bind_first + 2); 560 EXTEND (SP, bind_last - bind_first + 2);
346 PUSHs (ST(bind_first)); 567 PUSHs (ST(bind_first));
347 bind_first++; 568 bind_first++;
348 } while (bind_first != bind_last); 569 } while (bind_first != bind_last);
349 570
350 PUTBACK; 571 PUTBACK;
572
573 if (!mc->bind_columns)
574 mc_cache (mc, bind_columns);
575
351 count = call_sv (sv_bind_columns, G_METHOD | G_SCALAR); 576 count = call_sv (mc->bind_columns, G_SCALAR);
577
352 SPAGAIN; 578 SPAGAIN;
353 579
354 if (count != 1) 580 if (count != 1)
355 croak ("sql_exec: bind_columns() didn't return any value ('%s'): %s", 581 croak ("sql_exec: bind_columns() didn't return any value ('%s'): %s",
356 SvPV (sql, dc), 582 SvPV (sql, dc),
362 SvPV (get_sv ("DBI::errstr", TRUE), dd)); 588 SvPV (get_sv ("DBI::errstr", TRUE), dd));
363 589
364 POPs; 590 POPs;
365 } 591 }
366 592
367 /* restore our arguments again */
368 SP -= items;
369
370 if ((ix & ~1) == 2) 593 if ((ix & ~1) == 2)
371 { /* sql_fetch */ 594 { /* sql_fetch */
372 SV *row; 595 SV *row;
373 596
374 PUSHMARK (SP); 597 PUSHMARK (SP);
375 XPUSHs (sth); 598 XPUSHs (sth);
376 PUTBACK; 599 PUTBACK;
600
601 if (!mc->fetchrow_arrayref)
602 mc_cache (mc, fetchrow_arrayref);
603
377 count = call_sv (sv_fetchrow_arrayref, G_METHOD | G_SCALAR); 604 count = call_sv (mc->fetchrow_arrayref, G_SCALAR);
378 SPAGAIN; 605 SPAGAIN;
379 606
380 if (count != 1) 607 if (count != 1)
381 abort (); 608 abort ();
382 609
383 row = POPs; 610 row = POPs;
611
612 SP = PL_stack_base + orig_stack;
384 613
385 if (SvROK (row)) 614 if (SvROK (row))
386 { 615 {
387 AV *av; 616 AV *av;
388 617
391 case G_VOID: 620 case G_VOID:
392 /* no thing */ 621 /* no thing */
393 break; 622 break;
394 case G_SCALAR: 623 case G_SCALAR:
395 /* the first element */ 624 /* the first element */
396 XPUSHs (mortalcopy_and_maybe_force_utf8 (ix & 1, *av_fetch ((AV *)SvRV (row), 0, 1))); 625 XPUSHs (mortalcopy_and_maybe_force_utf8 (ix & 1, AvARRAY ((AV *)SvRV (row))[0]));
626 count = 1;
397 break; 627 break;
398 case G_ARRAY: 628 case G_ARRAY:
399 av = (AV *)SvRV (row); 629 av = (AV *)SvRV (row);
400 count = AvFILL (av) + 1; 630 count = AvFILL (av) + 1;
401 EXTEND (SP, count); 631 EXTEND (SP, count);
413 SV *rows; 643 SV *rows;
414 644
415 PUSHMARK (SP); 645 PUSHMARK (SP);
416 XPUSHs (sth); 646 XPUSHs (sth);
417 PUTBACK; 647 PUTBACK;
648
649 if (!mc->fetchall_arrayref)
650 mc_cache (mc, fetchall_arrayref);
651
418 count = call_sv (sv_fetchall_arrayref, G_METHOD | G_SCALAR); 652 count = call_sv (mc->fetchall_arrayref, G_SCALAR);
419 SPAGAIN; 653 SPAGAIN;
420 654
421 if (count != 1) 655 if (count != 1)
422 abort (); 656 abort ();
423 657
424 rows = POPs; 658 rows = POPs;
659
660 SP = PL_stack_base + orig_stack;
425 661
426 if (SvROK (rows)) 662 if (SvROK (rows))
427 { 663 {
428 AV *av = (AV *)SvRV (rows); 664 AV *av = (AV *)SvRV (rows);
429 count = AvFILL (av) + 1; 665 count = AvFILL (av) + 1;
441 PUSHs (mortalcopy_and_maybe_force_utf8 (ix & 1, AvARRAY (av)[arg])); 677 PUSHs (mortalcopy_and_maybe_force_utf8 (ix & 1, AvARRAY (av)[arg]));
442 } 678 }
443 } 679 }
444 } 680 }
445 else 681 else
682 {
683 SP = PL_stack_base + orig_stack;
446 XPUSHs (sth); 684 XPUSHs (sth);
685 }
447 686
448 if (ix > 1 || GIMME_V == G_VOID) 687 if (ix > 1 || GIMME_V == G_VOID)
449 { 688 {
689 orig_stack = SP - PL_stack_base;
690
450 PUSHMARK (SP); 691 PUSHMARK (SP);
451 XPUSHs (sth); 692 XPUSHs (sth);
452 PUTBACK; 693 PUTBACK;
694
695 if (!mc->finish)
696 mc_cache (mc, finish);
697
453 (void) call_sv (sv_finish, G_METHOD | G_DISCARD); 698 call_sv (mc->finish, G_DISCARD);
454 SPAGAIN; 699 SPAGAIN;
700
701 SP = PL_stack_base + orig_stack;
455 } 702 }
456 } 703 }
457} 704}
458 705
459 706

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines