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.2 by root, Tue Oct 24 04:21:45 2000 UTC vs.
Revision 1.6 by root, Sun Apr 22 17:03:28 2001 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#if (PERL_VERSION < 5) || ((PERL_VERSION == 5) && (PERL_SUBVERSION <= 6))
6# define get_sv perl_get_sv
7# define call_method perl_call_method
8# define call_sv perl_call_sv
9#endif
10
11#if (PERL_VERSION < 5) || ((PERL_VERSION == 5) && (PERL_SUBVERSION <= 5))
12# define CAN_UTF8 1
13#endif
14
15static SV *
16sql_upgrade_utf8 (SV *sv)
17{
18#if CAN_UTF8
19 if (SvPOK (sv))
20 sv_utf8_upgrade (sv);
21#endif
22 return sv;
23}
24
25static SV *
26sql_force_utf8 (SV *sv)
27{
28#if CAN_UTF8
29 if (SvPOK (sv))
30 SvUTF8_on (sv);
31#endif
32 return sv;
33}
34
35#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))
4 37
5#define is_dbh(sv) ((sv) && sv_isobject (sv) && sv_derived_from ((sv), "DBI::db")) 38#define is_dbh(sv) ((sv) && sv_isobject (sv) && sv_derived_from ((sv), "DBI::db"))
6 39
7typedef struct lru_node { 40typedef struct lru_node {
8 struct lru_node *next; 41 struct lru_node *next;
14 SV *sth; 47 SV *sth;
15#if 0 /* method cache */ 48#if 0 /* method cache */
16 GV *execute; 49 GV *execute;
17 GV *bind_columns; 50 GV *bind_columns;
18 GV *fetch; 51 GV *fetch;
52 GV *finish;
19#endif 53#endif
20} lru_node; 54} lru_node;
21 55
22static lru_node lru_list; 56static lru_node lru_list;
23static int lru_size; 57static int lru_size;
132 } 166 }
133} 167}
134 168
135static GV *sql_exec; 169static GV *sql_exec;
136static GV *DBH; 170static GV *DBH;
171static SV *sv_prepare, *sv_execute, *sv_bind_columns,
172 *sv_fetchrow_arrayref, *sv_fetchall_arrayref,
173 *sv_finish;
174
175#define newconstpv(str) newSVpvn ((str), sizeof (str))
137 176
138MODULE = PApp::SQL PACKAGE = PApp::SQL 177MODULE = PApp::SQL PACKAGE = PApp::SQL
139 178
140PROTOTYPES: DISABLE 179PROTOTYPES: DISABLE
141 180
142BOOT: 181BOOT:
143{ 182{
144 sql_exec = gv_fetchpv ("PApp::SQL::sql_exec", TRUE, SVt_PV); 183 sql_exec = gv_fetchpv ("PApp::SQL::sql_exec", TRUE, SVt_PV);
145 DBH = gv_fetchpv ("PApp::SQL::DBH" , TRUE, SVt_PV); 184 DBH = gv_fetchpv ("PApp::SQL::DBH" , TRUE, SVt_PV);
185
186 if (!sv_prepare)
187 {
188 sv_prepare = newconstpv ("prepare");
189 sv_execute = newconstpv ("execute");
190 sv_bind_columns = newconstpv ("bind_columns");
191 sv_fetchrow_arrayref = newconstpv ("fetchrow_arrayref");
192 sv_fetchall_arrayref = newconstpv ("fetchall_arrayref");
193 sv_finish = newconstpv ("finish");
194 }
146 195
147 /* apache might BOOT: twice :( */ 196 /* apache might BOOT: twice :( */
148 if (lru_size) 197 if (lru_size)
149 lru_cachesize (0); 198 lru_cachesize (0);
150 199
162 RETVAL 211 RETVAL
163 212
164void 213void
165sql_exec(...) 214sql_exec(...)
166 ALIAS: 215 ALIAS:
216 sql_uexec = 1
167 sql_fetch = 1 217 sql_fetch = 2
218 sql_ufetch = 3
168 sql_fetchall = 2 219 sql_fetchall = 4
220 sql_ufetchall = 5
169 sql_exists = 4 221 sql_exists = 6
222 sql_uexists = 7
170 PPCODE: 223 PPCODE:
171{ 224{
172 if (items == 0) 225 if (items == 0)
173 croak ("Usage: sql_exec [database-handle,] [bind-var-refs,... ] \"sql-statement\", [arguments, ...]"); 226 croak ("Usage: sql_exec [database-handle,] [bind-var-refs,... ] \"sql-statement\", [arguments, ...]");
174 else 227 else
178 int count; 231 int count;
179 SV *dbh = ST(0); 232 SV *dbh = ST(0);
180 SV *sth; 233 SV *sth;
181 SV *sql; 234 SV *sql;
182 SV *execute; 235 SV *execute;
236 STRLEN dc;
183 237
184 /* save our arguments against destruction through function calls */ 238 /* save our arguments against destruction through function calls */
185 SP += items; 239 SP += items;
186 240
187 /* first check wether we should use an explicit db handle */ 241 /* first check wether we should use an explicit db handle */
212 if (!SvPOK (ST(arg))) 266 if (!SvPOK (ST(arg)))
213 croak ("sql_exec: sql-statement must be a string"); 267 croak ("sql_exec: sql-statement must be a string");
214 268
215 sql = ST(arg); arg++; 269 sql = ST(arg); arg++;
216 270
217 if (ix == 4) 271 if ((ix & ~1) == 6)
218 { 272 {
219 SV *neu = sv_2mortal (newSVpv ("select count(*) > 0 from ", 0)); 273 SV *neu = sv_2mortal (newSVpv ("select count(*) > 0 from ", 0));
220 sv_catsv (neu, sql); 274 sv_catsv (neu, sql);
221 sv_catpv (neu, " limit 1"); 275 sv_catpv (neu, " limit 1");
222 sql = neu; 276 sql = neu;
223 ix = 1; /* sql_fetch */ 277 ix -= 6; /* sql_fetch */
224 } 278 }
225 279
226 /* check cache for existing statement handle (NYI) */ 280 /* check cache for existing statement handle */
227 sth = lru_fetch (dbh, sql); 281 sth = lru_fetch (dbh, sql);
228 if (!sth) 282 if (!sth)
229 { 283 {
230 PUSHMARK (SP); 284 PUSHMARK (SP);
231 EXTEND (SP, 2); 285 EXTEND (SP, 2);
232 PUSHs (dbh); 286 PUSHs (dbh);
233 PUSHs (sql); 287 PUSHs (sql);
234 PUTBACK; 288 PUTBACK;
235 count = call_method ("prepare", G_SCALAR); 289 count = call_sv (sv_prepare, G_METHOD | G_SCALAR);
236 SPAGAIN; 290 SPAGAIN;
237 291
238 if (count != 1) 292 if (count != 1)
239 croak ("sql_exec: unable to prepare() statement '%s': %s", 293 croak ("sql_exec: unable to prepare() statement '%s': %s",
240 SvPV_nolen (sql), 294 SvPV (sql, dc),
241 SvPV_nolen (get_sv ("DBI::errstr", TRUE))); 295 SvPV (get_sv ("DBI::errstr", TRUE), dc));
242 296
243 sth = POPs; 297 sth = POPs;
244 298
245 lru_store (dbh, sql, sth); 299 lru_store (dbh, sql, sth);
246 } 300 }
248 PUSHMARK (SP); 302 PUSHMARK (SP);
249 EXTEND (SP, items - arg + 1); 303 EXTEND (SP, items - arg + 1);
250 PUSHs (sth); 304 PUSHs (sth);
251 while (items > arg) 305 while (items > arg)
252 { 306 {
253 PUSHs (ST(arg)); 307 PUSHs (maybe_upgrade_utf8 (ix & 1, ST(arg)));
254 arg++; 308 arg++;
255 } 309 }
256 310
257 PUTBACK; 311 PUTBACK;
258 /* { static GV *execute; 312 /* { static GV *execute;
259 if (!execute) execute = gv_fetchmethod_autoload(SvSTASH(SvRV(sth)), "execute", 0); 313 if (!execute) execute = gv_fetchmethod_autoload(SvSTASH(SvRV(sth)), "execute", 0);
260 count = call_sv(GvCV(execute), G_SCALAR); 314 count = call_sv(GvCV(execute), G_SCALAR);
261 }*/ 315 }*/
262 count = call_method ("execute", G_SCALAR); 316 count = call_sv (sv_execute, G_METHOD | G_SCALAR);
263 SPAGAIN; 317 SPAGAIN;
264 318
265 if (count != 1) 319 if (count != 1)
266 croak ("sql_exec: execute() didn't return any value ('%s'): %s", 320 croak ("sql_exec: execute() didn't return any value ('%s'): %s",
267 SvPV_nolen (sql), 321 SvPV (sql, dc),
268 SvPV_nolen (get_sv ("DBI::errstr", TRUE))); 322 SvPV (get_sv ("DBI::errstr", TRUE), dc));
269 323
270 execute = POPs; 324 execute = POPs;
271 325
272 if (!SvTRUE (execute)) 326 if (!SvTRUE (execute))
273 croak ("sql_exec: unable to execute statement '%s' (%s)", 327 croak ("sql_exec: unable to execute statement '%s' (%s)",
274 SvPV_nolen (sql), 328 SvPV (sql, dc),
275 SvPV_nolen (get_sv ("DBI::errstr", TRUE))); 329 SvPV (get_sv ("DBI::errstr", TRUE), dc));
276 330
277 sv_setsv (GvSV(sql_exec), execute); 331 sv_setsv (GvSV(sql_exec), execute);
278 332
279 if (bind_first != bind_last) 333 if (bind_first != bind_last)
280 { 334 {
285 PUSHs (ST(bind_first)); 339 PUSHs (ST(bind_first));
286 bind_first++; 340 bind_first++;
287 } while (bind_first != bind_last); 341 } while (bind_first != bind_last);
288 342
289 PUTBACK; 343 PUTBACK;
290 count = call_method ("bind_columns", G_SCALAR); 344 count = call_sv (sv_bind_columns, G_METHOD | G_SCALAR);
291 SPAGAIN; 345 SPAGAIN;
292 346
293 if (count != 1) 347 if (count != 1)
294 croak ("sql_exec: bind_columns() didn't return any value ('%s'): %s", 348 croak ("sql_exec: bind_columns() didn't return any value ('%s'): %s",
295 SvPV_nolen (sql), 349 SvPV (sql, dc),
296 SvPV_nolen (get_sv ("DBI::errstr", TRUE))); 350 SvPV (get_sv ("DBI::errstr", TRUE), dc));
297 351
298 if (!SvOK (POPs)) 352 if (!SvOK (POPs))
299 croak ("sql_exec: bind_columns() didn't return a true ('%s'): %s", 353 croak ("sql_exec: bind_columns() didn't return a true ('%s'): %s",
300 SvPV_nolen (sql), 354 SvPV (sql, dc),
301 SvPV_nolen (get_sv ("DBI::errstr", TRUE))); 355 SvPV (get_sv ("DBI::errstr", TRUE), dc));
302 } 356 }
303 357
304 /* free our arguments from the stack */ 358 /* free our arguments from the stack */
305 SP -= items; 359 SP -= items;
306 360
307 if (ix == 1) 361 if ((ix & ~1) == 2)
308 { /* sql_fetch */ 362 { /* sql_fetch */
309 SV *row; 363 SV *row;
310 364
311 PUSHMARK (SP); 365 PUSHMARK (SP);
312 XPUSHs (sth); 366 XPUSHs (sth);
313 PUTBACK; 367 PUTBACK;
314 count = call_method ("fetchrow_arrayref", G_SCALAR); 368 count = call_sv (sv_fetchrow_arrayref, G_METHOD | G_SCALAR);
315 SPAGAIN; 369 SPAGAIN;
316 370
317 if (count != 1) 371 if (count != 1)
318 abort (); 372 abort ();
319 373
328 case G_VOID: 382 case G_VOID:
329 /* no thing */ 383 /* no thing */
330 break; 384 break;
331 case G_SCALAR: 385 case G_SCALAR:
332 /* the first element */ 386 /* the first element */
333 XPUSHs (*av_fetch ((AV *)SvRV (row), 0, 1)); 387 XPUSHs (maybe_force_utf8 (ix & 1, *av_fetch ((AV *)SvRV (row), 0, 1)));
334 break; 388 break;
335 case G_ARRAY: 389 case G_ARRAY:
336 av = (AV *)SvRV (row); 390 av = (AV *)SvRV (row);
337 count = AvFILL (av) + 1; 391 count = AvFILL (av) + 1;
338 EXTEND (SP, count); 392 EXTEND (SP, count);
339 for (arg = 0; arg < count; arg++) 393 for (arg = 0; arg < count; arg++)
340 PUSHs (AvARRAY (av)[arg]); 394 PUSHs (maybe_force_utf8 (ix & 1, AvARRAY (av)[arg]));
341 395
342 break; 396 break;
343 default: 397 default:
344 abort (); 398 abort ();
345 } 399 }
346 } 400 }
347 } 401 }
348 else if (ix == 2) 402 else if ((ix & ~1) == 4)
349 { /* sql_fetchall */ 403 { /* sql_fetchall */
350 SV *rows; 404 SV *rows;
351 405
352 PUSHMARK (SP); 406 PUSHMARK (SP);
353 XPUSHs (sth); 407 XPUSHs (sth);
354 PUTBACK; 408 PUTBACK;
355 count = call_method ("fetchall_arrayref", G_SCALAR); 409 count = call_sv (sv_fetchall_arrayref, G_METHOD | G_SCALAR);
356 SPAGAIN; 410 SPAGAIN;
357 411
358 if (count != 1) 412 if (count != 1)
359 abort (); 413 abort ();
360 414
365 AV *av = (AV *)SvRV (rows); 419 AV *av = (AV *)SvRV (rows);
366 count = AvFILL (av) + 1; 420 count = AvFILL (av) + 1;
367 421
368 if (count) 422 if (count)
369 { 423 {
370 int columns = AvFILL ((AV *)SvRV (AvARRAY(av)[0])) + 1; /* columns? */ 424 int columns = AvFILL ((AV *) SvRV (AvARRAY (av)[0])) + 1; /* columns? */
371 425
372 EXTEND (SP, count); 426 EXTEND (SP, count);
373 if (columns == 1) 427 if (columns == 1)
374 for (arg = 0; arg < count; arg++) 428 for (arg = 0; arg < count; arg++)
375 PUSHs (AvARRAY ((AV *)SvRV (AvARRAY (av)[arg]))[0]); 429 PUSHs (maybe_force_utf8 (ix & 1, AvARRAY ((AV *)SvRV (AvARRAY (av)[arg]))[0]));
376 else 430 else
377 for (arg = 0; arg < count; arg++) 431 for (arg = 0; arg < count; arg++)
378 PUSHs (AvARRAY (av)[arg]); 432 PUSHs (maybe_force_utf8 (ix & 1, AvARRAY (av)[arg]));
379 } 433 }
380 } 434 }
381 } 435 }
382 else 436 else
383 XPUSHs (sth); 437 XPUSHs (sth);
384 438
385 if (ix || GIMME_V == G_VOID) 439 if (ix > 1 || GIMME_V == G_VOID)
386 { 440 {
387 PUSHMARK (SP); 441 PUSHMARK (SP);
388 XPUSHs (sth); 442 XPUSHs (sth);
389 PUTBACK; 443 PUTBACK;
390 (void) call_method ("finish", G_DISCARD); 444 (void) call_sv (sv_finish, G_METHOD | G_DISCARD);
391 SPAGAIN; 445 SPAGAIN;
392 } 446 }
393 } 447 }
394} 448}
395 449

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines