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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines