File Coverage

dbdimp.c
Criterion Covered Total %
statement 424 507 83.6
branch 326 786 41.4
condition n/a
subroutine n/a
pod n/a
total 750 1293 58.0


line stmt bran cond sub pod time code
1             /* $Id: dbdimp.c,v 1.2 2004/08/09 13:17:59 matt Exp $ */
2              
3             #include "SQLiteXS.h"
4              
5 0 0         DBISTATE_DECLARE;
    0          
6              
7             #ifndef SvPV_nolen
8             #define SvPV_nolen(x) SvPV(x,PL_na)
9             #endif
10              
11             #ifndef call_method
12             #define call_method(x,y) perl_call_method(x,y)
13             #endif
14              
15             #ifndef call_sv
16             #define call_sv(x,y) perl_call_sv(x,y)
17             #endif
18              
19             #define sqlite2_error(h,xxh,rc,what) _sqlite2_error(__FILE__, __LINE__, h, xxh, rc, what)
20              
21             void
22 22           sqlite2_init(dbistate_t *dbistate)
23             {
24             dTHR;
25 22           DBIS = dbistate;
26 22           }
27              
28             static void
29 9           _sqlite2_error(char *file, int line, SV *h, imp_xxh_t *imp_xxh, int rc, char *what)
30             {
31             dTHR;
32              
33 9           SV *errstr = DBIc_ERRSTR(imp_xxh);
34 9           sv_setiv(DBIc_ERR(imp_xxh), (IV)rc);
35 9           sv_setpv(errstr, what);
36 9           sv_catpvf(errstr, "(%d) at %s line %d", rc, file, line);
37              
38 9 50         if (DBIS->debug >= 3) {
39 0           PerlIO_printf(DBILOGFP, "sqlite error %d recorded: %s at %s line %d\n",
40             rc, what, file, line);
41             }
42 9           }
43              
44             int
45 25           sqlite2_db_login(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *user, char *pass)
46             {
47             dTHR;
48             int retval;
49 25           char *errmsg = NULL;
50              
51 25 50         if (DBIS->debug >= 3) {
52 0           PerlIO_printf(DBILOGFP, " login '%s' (version %s, encoding %s)\n",
53             dbname, sqlite_version, sqlite_encoding);
54             }
55              
56 25 50         if ((imp_dbh->db = sqlite_open(dbname, 0, &errmsg)) == NULL) {
57 0           sqlite2_error(dbh, (imp_xxh_t*)imp_dbh, 1, errmsg);
58 0           sqlite_freemem(errmsg);
59 0           return FALSE;
60             }
61 25           DBIc_IMPSET_on(imp_dbh);
62              
63 25           imp_dbh->in_tran = FALSE;
64 25           imp_dbh->no_utf8_flag = FALSE;
65 25           imp_dbh->functions = newAV();
66 25           imp_dbh->aggregates = newAV();
67 25           imp_dbh->timeout = SQL_TIMEOUT;
68            
69 25           imp_dbh->handle_binary_nulls = FALSE;
70              
71 25           sqlite_busy_timeout(imp_dbh->db, SQL_TIMEOUT);
72              
73 25 50         if ((retval = sqlite_exec(imp_dbh->db, "PRAGMA empty_result_callbacks = ON",
74             NULL, NULL, &errmsg)
75 25           != SQLITE_OK))
76             {
77             /* warn("failed to set pragma: %s\n", errmsg); */
78 0           sqlite2_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg);
79 0           sqlite_freemem(errmsg);
80 0           return FALSE;
81             }
82              
83 25 50         if ((retval = sqlite_exec(imp_dbh->db, "PRAGMA show_datatypes = ON",
84             NULL, NULL, &errmsg)
85 25           != SQLITE_OK))
86             {
87             /* warn("failed to set pragma: %s\n", errmsg); */
88 0           sqlite2_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg);
89 0           sqlite_freemem(errmsg);
90 0           return FALSE;
91             }
92              
93 25 50         DBIc_ACTIVE_on(imp_dbh);
    50          
    50          
    50          
94              
95 25           return TRUE;
96             }
97              
98             int
99 0           sqlite2_busy_timeout ( SV *dbh, int timeout )
100             {
101 0           D_imp_dbh(dbh);
102 0 0         if (timeout) {
103 0           imp_dbh->timeout = timeout;
104 0           sqlite_busy_timeout(imp_dbh->db, timeout);
105             }
106 0           return imp_dbh->timeout;
107             }
108              
109             int
110 25           sqlite2_db_disconnect (SV *dbh, imp_dbh_t *imp_dbh)
111             {
112             dTHR;
113 25 50         DBIc_ACTIVE_off(imp_dbh);
    50          
    100          
    50          
    50          
114              
115 25 100         if (DBIc_is(imp_dbh, DBIcf_AutoCommit) == FALSE) {
116 2           sqlite2_db_rollback(dbh, imp_dbh);
117             }
118              
119 25           sqlite_close(imp_dbh->db);
120 25           imp_dbh->db = NULL;
121              
122 25           av_undef(imp_dbh->functions);
123 25           imp_dbh->functions = (AV *)NULL;
124              
125 25           av_undef(imp_dbh->aggregates);
126 25           imp_dbh->aggregates = (AV *)NULL;
127              
128 25           return TRUE;
129             }
130              
131             void
132 25           sqlite2_db_destroy (SV *dbh, imp_dbh_t *imp_dbh)
133             {
134             dTHR;
135 25 50         if (DBIc_ACTIVE(imp_dbh)) {
136 0           sqlite2_db_disconnect(dbh, imp_dbh);
137             }
138 25           DBIc_IMPSET_off(imp_dbh);
139 25           }
140              
141             int
142 5           sqlite2_db_rollback(SV *dbh, imp_dbh_t *imp_dbh)
143             {
144             dTHR;
145             int retval;
146             char *errmsg;
147              
148 5 100         if (imp_dbh->in_tran) {
149 4 50         if ((retval = sqlite_exec(imp_dbh->db, "ROLLBACK TRANSACTION",
150             NULL, NULL, &errmsg)
151 4           != SQLITE_OK))
152             {
153 0           sqlite2_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg);
154 0           sqlite_freemem(errmsg);
155 0           return FALSE;
156             }
157 4           imp_dbh->in_tran = FALSE;
158             }
159              
160 5           return TRUE;
161             }
162              
163             int
164 3           sqlite2_db_commit(SV *dbh, imp_dbh_t *imp_dbh)
165             {
166             dTHR;
167             int retval;
168             char *errmsg;
169              
170 3 100         if (DBIc_is(imp_dbh, DBIcf_AutoCommit)) {
171 1           warn("commit ineffective with AutoCommit");
172 1           return TRUE;
173             }
174              
175 2 50         if (imp_dbh->in_tran) {
176 2 50         if ((retval = sqlite_exec(imp_dbh->db, "COMMIT TRANSACTION",
177             NULL, NULL, &errmsg)
178 2           != SQLITE_OK))
179             {
180 0           sqlite2_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg);
181 0           sqlite_freemem(errmsg);
182 0           return FALSE;
183             }
184 2           imp_dbh->in_tran = FALSE;
185             }
186 3           return TRUE;
187             }
188              
189             int
190 21           sqlite2_discon_all(SV *drh, imp_drh_t *imp_drh)
191             {
192             dTHR;
193 21           return FALSE; /* no way to do this */
194             }
195              
196             void
197 149           sqlite2_st_parse_sql(imp_sth_t *imp_sth, char *statement)
198             {
199 149           D_imp_dbh_from_sth;
200 149           bool in_literal = FALSE;
201             SV *chunk;
202 149           int num_params = 0;
203              
204 149           chunk = NEWSV(0, strlen(statement));
205 149           sv_setpv(chunk, "");
206              
207             /* warn("parsing: %s\n", statement); */
208              
209 7388 100         while (*statement) {
210             /* warn("parse: %c => %s\n", *statement, SvPV_nolen(chunk)); */
211 7239 100         if (*statement == '\'') {
212 136 100         if (in_literal) {
213             /* either end of literal, or escape */
214 68 100         if (statement[1] && statement[1] == '\'') {
    50          
215 0           statement++;
216 0           sv_catpvn(chunk, "''", 2);
217             }
218             else {
219 68           sv_catpvn(chunk, "'", 1);
220 68           in_literal = FALSE;
221             }
222             }
223             else {
224 68           in_literal = TRUE;
225 136           sv_catpvn(chunk, "'", 1);
226             }
227             }
228 7103 100         else if (*statement == '?') {
229 6 50         if (in_literal) {
230 0           sv_catpvn(chunk, "?", 1);
231             }
232             else {
233 6           num_params++;
234 6           if (!imp_dbh->no_utf8_flag) {
235             /* sv_utf8_encode(chunk); */
236             }
237 6           av_push(imp_sth->sql, chunk);
238 6           chunk = NEWSV(0, 20);
239 6           sv_setpvn(chunk, "", 0);
240             }
241             }
242             else {
243 7097           sv_catpvn(chunk, statement, 1);
244             }
245 7239           statement++;
246             }
247 149           av_push(imp_sth->sql, chunk);
248 149           DBIc_NUM_PARAMS(imp_sth) = num_params;
249 149           }
250              
251             int
252 149           sqlite2_st_prepare (SV *sth, imp_sth_t *imp_sth,
253             char *statement, SV *attribs)
254             {
255             dTHR;
256 149           D_imp_dbh_from_sth;
257              
258 149 50         if (!DBIc_ACTIVE(imp_dbh)) {
259 0           die("prepare on an inactive database handle");
260             }
261              
262             /* warn("prepare statement\n"); */
263 149           imp_sth->nrow = 0;
264 149           imp_sth->ncols = 0;
265 149           imp_sth->params = newAV();
266 149           imp_sth->sql = newAV();
267 149           imp_sth->results = 0;
268 149           imp_sth->coldata = 0;
269 149           imp_sth->retval = SQLITE_OK;
270 149           sqlite2_st_parse_sql(imp_sth, statement);
271              
272 149           return TRUE;
273             }
274              
275             char *
276 22           sqlite2_quote(imp_dbh_t *imp_dbh, SV *val)
277             {
278             STRLEN len;
279 22 100         char *cval = SvPV(val, len);
280 22           SV *ret = sv_2mortal(NEWSV(0, SvCUR(val) + 2));
281 22           sv_setpvn(ret, "", 0);
282              
283 32903 100         while (len) {
284 32881           switch (*cval) {
285             case '\'':
286 128           sv_catpvn(ret, "''", 2);
287 128           break;
288             case 0:
289 128 50         if (imp_dbh->handle_binary_nulls) {
290 128           sv_catpvn(ret, "\\0", 2);
291 128           break;
292             }
293             else {
294 0           die("attempt to quote binary null without sqlite_handle_binary_nulls on");
295             }
296             case '\\':
297 128 50         if (imp_dbh->handle_binary_nulls) {
298 128           sv_catpvn(ret, "\\\\", 2);
299 128           break;
300             }
301             default:
302 32497           sv_catpvn(ret, cval, 1);
303             }
304 32881           *cval++; len--;
305             }
306 22 50         return SvPV_nolen(ret);
307             }
308              
309             char *
310 103           sqlite2_decode(imp_dbh_t *imp_dbh, char *input, size_t *len)
311             {
312             char *ret;
313             char *swit;
314              
315 103           New(1, ret, *len, char);
316 103           swit = ret;
317              
318 33797 100         while (*input) {
319 33694 100         switch (*input) {
320             case '\\':
321 256 50         if (imp_dbh->handle_binary_nulls && input[1] && input[1] == '0') {
    50          
    100          
322 128           *swit++ = '\0';
323 128           *input++;
324 128           (*len)--;
325 128           break;
326             }
327 128 50         else if (imp_dbh->handle_binary_nulls && input[1] && input[1] == '\\') {
    50          
    50          
328 128           *swit++ = '\\';
329 128           *input++;
330 128           (*len)--;
331 128           break;
332             }
333             default:
334 33438           *swit++ = *input;
335             }
336 33694           *input++;
337             }
338 103           return ret;
339             }
340              
341             int
342 225           _sqlite2_fetch_row (imp_sth_t *imp_sth)
343             {
344             while (1)
345             {
346 225 50         if (imp_sth->vm)
347 225           imp_sth->retval = sqlite_step(imp_sth->vm,
348 225           &(imp_sth->ncols), (const char ***)&(imp_sth->results), (const char ***)&(imp_sth->coldata));
349 225 50         if (imp_sth->retval == SQLITE_BUSY) {
350 0           break; /* We should never get "busy" here because we set sqlite_timeout, so assume error */
351             }
352 225           break;
353             }
354             /* warn("step got: %d\nCol1: %s\n", imp_sth->retval, imp_sth->coldata[0]); */
355 225           return imp_sth->retval;
356             }
357              
358             int
359 160           sqlite2_st_execute (SV *sth, imp_sth_t *imp_sth)
360             {
361             dTHR;
362 160           D_imp_dbh_from_sth;
363             SV *sql;
364 160           I32 pos = 0;
365             char *errmsg;
366 160           int num_params = DBIc_NUM_PARAMS(imp_sth);
367             I32 i;
368             int retval;
369              
370             /* warn("execute\n"); */
371              
372 160 100         if (DBIc_ACTIVE(imp_sth)) {
373 2           sqlite2_st_finish(sth, imp_sth);
374             }
375              
376 160           sql = sv_2mortal(newSVsv(AvARRAY(imp_sth->sql)[pos++]));
377              
378 183 100         for (i = 0; i < num_params; i++) {
379 23           SV *value = av_shift(imp_sth->params);
380 23 50         if (value && SvOK(value)) {
    100          
    50          
    50          
381             /* warn("binding param: %s\n", SvPV_nolen(value); */
382 22           sv_catpvn(sql, "'", 1);
383 22           sv_catpv(sql, sqlite2_quote(imp_dbh, value));
384 22           sv_catpvn(sql, "'", 1);
385             /* warn("inserting string length: %d\n", SvCUR(sql)); */
386             }
387             else {
388             /* warn("binding NULL\n"); */
389 1           sv_catpvn(sql, "NULL", 4);
390             }
391 23 50         if (value) {
392 23           SvREFCNT_dec(value);
393             }
394 23           sv_catsv(sql, AvARRAY(imp_sth->sql)[pos++]);
395             }
396             /* warn("Executing: %s;\n", SvPV_nolen(sql)); */
397              
398 160 100         if ( (!DBIc_is(imp_dbh, DBIcf_AutoCommit)) && (!imp_dbh->in_tran) ) {
    100          
399 6 50         if ((retval = sqlite_exec(imp_dbh->db, "BEGIN TRANSACTION",
400             NULL, NULL, &errmsg)
401 6           != SQLITE_OK))
402             {
403 0           sqlite2_error(sth, (imp_xxh_t*)imp_sth, retval, errmsg);
404 0           sqlite_freemem(errmsg);
405 0           return -2;
406             }
407 6           imp_dbh->in_tran = TRUE;
408             }
409              
410 160           imp_sth->results = NULL;
411 160 50         if ((retval = sqlite_compile(imp_dbh->db, SvPV_nolen(sql), 0, &(imp_sth->vm), &errmsg)
    100          
412 160           != SQLITE_OK))
413             {
414 7           sqlite2_error(sth, (imp_xxh_t*)imp_sth, retval, errmsg);
415 7           sqlite_freemem(errmsg);
416 7           return -2;
417             }
418            
419 153 100         if (_sqlite2_fetch_row(imp_sth) == SQLITE_ERROR) {
420 2           sqlite_finalize(imp_sth->vm, &errmsg);
421 2           sqlite2_error(sth, (imp_xxh_t*)imp_sth, imp_sth->retval, errmsg);
422 2           sqlite_freemem(errmsg);
423 2           return -2;
424             }
425            
426 151           DBIc_NUM_FIELDS(imp_sth) = imp_sth->ncols;
427 151           imp_sth->nrow = -1;
428            
429             /* warn("Execute returned %d cols\n", imp_sth->ncols); */
430 151 100         if (imp_sth->ncols == 0) {
431 83           sqlite_finalize(imp_sth->vm, 0);
432 83           imp_sth->nrow = sqlite_changes(imp_dbh->db);
433 83           DBIc_IMPSET_on(imp_sth);
434 83           return imp_sth->nrow;
435             }
436            
437 68 50         DBIc_ACTIVE_on(imp_sth);
    50          
    50          
    50          
438             /* warn("exec ok - %d rows, %d cols\n", imp_sth->nrow, imp_sth->ncols); */
439 68           DBIc_IMPSET_on(imp_sth);
440 160           return 0;
441             }
442              
443             int
444 75           sqlite2_st_rows (SV *sth, imp_sth_t *imp_sth)
445             {
446 75           return imp_sth->nrow;
447             }
448              
449             int
450 23           sqlite2_bind_ph (SV *sth, imp_sth_t *imp_sth,
451             SV *param, SV *value, IV sql_type, SV *attribs,
452             int is_inout, IV maxlen)
453             {
454 23 50         if (is_inout) {
455 0           croak("InOut bind params not implemented");
456             }
457             /* warn("bind: %s => %s\n", SvPV_nolen(param), SvPV_nolen(value)); */
458 23 100         if (sql_type >= SQL_NUMERIC && sql_type <= SQL_DOUBLE) {
    50          
459 2 50         return av_store(imp_sth->params, SvIV(param) - 1, newSVnv(SvNV(value))) ? 1 : 0;
    50          
460             }
461             else {
462 21 50         return av_store(imp_sth->params, SvIV(param) - 1, SvREFCNT_inc(value)) ? 1 : 0;
463             }
464             }
465              
466             AV *
467 93           sqlite2_st_fetch (SV *sth, imp_sth_t *imp_sth)
468             {
469             AV *av;
470 93           D_imp_dbh_from_sth;
471 93           int numFields = DBIc_NUM_FIELDS(imp_sth);
472 93           int chopBlanks = DBIc_is(imp_sth, DBIcf_ChopBlanks);
473             int i;
474              
475             /* warn("current_entry == %d\nnumFields == %d\nnrow == %d",
476             current_entry, numFields, imp_sth->nrow); */
477              
478 93 100         if (!DBIc_ACTIVE(imp_sth)) { /* [cpan #16451] */
479 2           return Nullav;
480             }
481              
482 91 100         if ((imp_sth->retval == SQLITE_DONE) || (imp_sth->retval == SQLITE_ERROR)) {
    50          
483 19           sqlite2_st_finish(sth, imp_sth);
484 19           return Nullav;
485             }
486            
487 72 100         if (imp_sth->nrow == -1) {
488 56           imp_sth->nrow++;
489             }
490 72           imp_sth->nrow++;
491            
492 72           av = DBIS->get_fbav(imp_sth);
493 224 100         for (i = 0; i < numFields; i++) {
494 152           char *val = imp_sth->results[i];
495             /* warn("fetching: %d == %s\n", i, val); */
496 152 100         if (val != NULL) {
497 103           size_t len = strlen(val);
498             char *decoded;
499 103 100         if (chopBlanks) {
500 6           val = savepv(val);
501 8 100         while(len > 0 && val[len-1] == ' ') {
    100          
502 2           len--;
503             }
504 6           val[len] = '\0';
505             }
506 103           decoded = sqlite2_decode(imp_dbh, val, &len);
507 103           sv_setpvn(AvARRAY(av)[i], decoded, len);
508 103           Safefree(decoded);
509 103 100         if (chopBlanks) Safefree(val);
510              
511             /* if (!imp_dbh->no_utf8_flag) {
512             sv_utf8_encode(AvARRAY(av)[i]);
513             } */
514             }
515             else {
516 49           sv_setsv(AvARRAY(av)[i], &PL_sv_undef);
517             }
518             }
519 72           _sqlite2_fetch_row(imp_sth);
520 72           return av;
521             }
522              
523             int
524 68           sqlite2_st_finish (SV *sth, imp_sth_t *imp_sth)
525             {
526             /* warn("finish statement\n"); */
527 68 50         if (DBIc_ACTIVE(imp_sth)) {
528             char *errmsg;
529 68 50         DBIc_ACTIVE_off(imp_sth);
    50          
    50          
    50          
    50          
530 68 50         if ((imp_sth->retval = sqlite_finalize(imp_sth->vm, &errmsg) == SQLITE_ERROR)) {
531 0           warn("finalize failed! %s\n", errmsg);
532 0           sqlite2_error(sth, (imp_xxh_t*)imp_sth, imp_sth->retval, errmsg);
533 0           sqlite_freemem(errmsg);
534 68           return FALSE;
535             }
536             }
537 68           return TRUE;
538             }
539              
540             void
541 139           sqlite2_st_destroy (SV *sth, imp_sth_t *imp_sth)
542             {
543             /* warn("destroy statement\n"); */
544 139 50         if (DBIc_ACTIVE(imp_sth)) {
545 0           sqlite2_st_finish(sth, imp_sth);
546             }
547 139           SvREFCNT_dec((SV*)imp_sth->sql);
548 139           SvREFCNT_dec((SV*)imp_sth->params);
549 139           DBIc_IMPSET_off(imp_sth);
550 139           }
551              
552             int
553 0           sqlite2_st_blob_read (SV *sth, imp_sth_t *imp_sth,
554             int field, long offset, long len, SV *destrv, long destoffset)
555             {
556 0           return 0;
557             }
558              
559             int
560 108           sqlite2_db_STORE_attrib (SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv)
561             {
562             dTHR;
563 108 50         char *key = SvPV_nolen(keysv);
564             char *errmsg;
565             int retval;
566              
567 108 100         if (strEQ(key, "AutoCommit")) {
568 27 50         if (SvTRUE(valuesv)) {
    50          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
569             /* commit tran? */
570 25 100         if ( (!DBIc_is(imp_dbh, DBIcf_AutoCommit)) && (imp_dbh->in_tran) ) {
    50          
571 0 0         if ((retval = sqlite_exec(imp_dbh->db, "COMMIT TRANSACTION",
572             NULL, NULL, &errmsg)
573 0           != SQLITE_OK))
574             {
575 0           sqlite2_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg);
576 0           sqlite_freemem(errmsg);
577 0           return TRUE;
578             }
579 0           imp_dbh->in_tran = FALSE;
580             }
581             }
582 27 50         DBIc_set(imp_dbh, DBIcf_AutoCommit, SvTRUE(valuesv));
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
583 27           return TRUE;
584             }
585 81 50         else if (strEQ(key, "sqlite_no_utf8_flag") || strEQ(key, "NoUTF8Flag")) {
    50          
586 0           warn("NoUTF8Flag is deprecated due to perl unicode weirdness\n");
587 0 0         if (SvTRUE(valuesv)) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
588 0           imp_dbh->no_utf8_flag = TRUE;
589             }
590             else {
591 0           imp_dbh->no_utf8_flag = FALSE;
592             }
593 0           return TRUE;
594             }
595 81 100         else if (strEQ(key, "sqlite_handle_binary_nulls")) {
596 1 50         if (SvTRUE(valuesv)) {
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
597 1           imp_dbh->handle_binary_nulls = TRUE;
598             }
599             else {
600 0           imp_dbh->handle_binary_nulls = FALSE;
601             }
602 1           return TRUE;
603             }
604 108           return FALSE;
605             }
606              
607             SV *
608 8           sqlite2_db_FETCH_attrib (SV *dbh, imp_dbh_t *imp_dbh, SV *keysv)
609             {
610             dTHR;
611 8 50         char *key = SvPV_nolen(keysv);
612              
613 8 50         if (strEQ(key, "sqlite_no_utf8_flag") || strEQ(key, "NoUTF8Flag")) {
    50          
614 0           return newSViv(imp_dbh->no_utf8_flag ? 1 : 0);
615             }
616 8 100         if (strEQ(key, "sqlite_version")) {
617 2           return newSVpv(sqlite_version, strlen(sqlite_version));
618             }
619 6 100         if (strEQ(key, "sqlite_encoding")) {
620 2           return newSVpv(sqlite_encoding, strlen(sqlite_encoding));
621             }
622 4           return NULL;
623             }
624              
625             int
626 8           sqlite2_st_STORE_attrib (SV *sth, imp_sth_t *imp_sth, SV *keysv, SV *valuesv)
627             {
628 8 50         char *key = SvPV_nolen(keysv);
629 8           return FALSE;
630             }
631              
632             SV *
633 22           sqlite2_st_FETCH_attrib (SV *sth, imp_sth_t *imp_sth, SV *keysv)
634             {
635 22 50         char *key = SvPV_nolen(keysv);
636 22           SV *retsv = NULL;
637             int i;
638              
639 22 100         if (!imp_sth->coldata) {
640 1           return retsv;
641             }
642              
643 21           i = DBIc_NUM_FIELDS(imp_sth);
644              
645 21 100         if (strEQ(key, "NAME")) {
646 17           AV *av = newAV();
647 17           av_extend(av, i);
648 17           retsv = sv_2mortal(newRV(sv_2mortal((SV*)av)));
649 106 100         while (--i >= 0) {
650 89           char *fieldname = imp_sth->coldata[i];
651 89           int len = strlen(fieldname);
652             char *dot;
653             /* RT#26775: DISTINCT(t.name) returns "(t.name)" */
654 89 50         if (fieldname[0] == '(' && fieldname[len-1] == ')') {
    0          
655 0           fieldname[len-1] = '\0';
656 0           fieldname++;
657             }
658 89           dot = instr(fieldname, ".");
659             /* warn("Name [%d]: %s\n", i, fieldname); */
660 89 100         if (dot) /* drop table name from field name */
661 1           fieldname = ++dot;
662 89           av_store(av, i, newSVpv(fieldname, 0));
663             }
664             }
665 4 50         else if (strEQ(key, "PRECISION")) {
666 0           AV *av = newAV();
667 0           retsv = sv_2mortal(newRV(sv_2mortal((SV*)av)));
668             }
669 4 100         else if (strEQ(key, "TYPE")) {
670 1           int i_base = i;
671 1           AV *av = newAV();
672 1           av_extend(av, i);
673 1           retsv = sv_2mortal(newRV(sv_2mortal((SV*)av)));
674 1           i = i * 2;
675 3 100         while (--i >= i_base) {
676 2           char *fieldname = imp_sth->coldata[i];
677             /* warn("Type [%d]: %s\n", i, fieldname); */
678 2           char *dot = instr(fieldname, ".");
679 2 50         if (dot) /* drop table name from field name */
680 0           fieldname = ++dot;
681 2           av_store(av, i - i_base, newSVpv(fieldname, 0));
682             }
683             }
684 3 50         else if (strEQ(key, "NULLABLE")) {
685 0           AV *av = newAV();
686 0           retsv = sv_2mortal(newRV(sv_2mortal((SV*)av)));
687             }
688 3 50         else if (strEQ(key, "SCALE")) {
689 0           AV *av = newAV();
690 0           retsv = sv_2mortal(newRV(sv_2mortal((SV*)av)));
691             }
692 3 50         else if (strEQ(key, "NUM_OF_FIELDS")) {
693 3           retsv = sv_2mortal(newSViv(i));
694             }
695              
696 21           return retsv;
697             }
698              
699             static void
700 25           sqlite2_db_set_result(sqlite_func *context, SV *result, int is_error )
701             {
702             STRLEN len;
703             char *s;
704            
705 25 100         if ( is_error ) {
706 1 50         s = SvPV(result, len);
707 1           sqlite_set_result_error( context, s, len );
708 1           return;
709             }
710              
711 24 100         if ( !SvOK(result) ) {
    50          
    50          
712 3           sqlite_set_result_string( context, NULL, -1 );
713 21 100         } else if ( SvIOK(result) ) {
714 16 50         IV iv = SvIV(result);
715 16 50         if (iv > I32_MAX || iv < I32_MIN) { /* sqlite cannot handle 64bit int */
    50          
716 0           double nv = (double)iv;
717 0           sqlite_set_result_double( context, nv );
718             }
719             else
720 16           sqlite_set_result_int( context, iv );
721 5 100         } else if ( SvNOK(result) ) {
722 2 50         sqlite_set_result_double( context, SvNV(result) );
723             } else {
724 3 50         s = SvPV(result, len);
725 24           sqlite_set_result_string( context, s, len );
726             }
727             }
728              
729             static void
730 19           sqlite2_db_func_dispatcher(sqlite_func *context, int argc, const char **argv)
731             {
732 19           dSP;
733             int count;
734             int i;
735             SV *func;
736            
737 19           func = sqlite_user_data(context);
738            
739 19           ENTER;
740 19           SAVETMPS;
741            
742 19 50         PUSHMARK(SP);
743 39 100         for ( i=0; i < argc; i++ ) {
744             SV *arg;
745            
746 20 100         if ( !argv[i] ) {
747 2           arg = &PL_sv_undef;
748             } else {
749 18           arg = sv_2mortal( newSVpv(argv[i], 0));
750             }
751            
752 20 50         XPUSHs(arg);
753             }
754 19           PUTBACK;
755              
756 19           count = call_sv(func, G_SCALAR|G_EVAL);
757            
758 19           SPAGAIN;
759              
760             /* Check for an error */
761 19 50         if (SvTRUE(ERRSV) ) {
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    0          
    0          
    100          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
762 1 50         sqlite2_db_set_result( context, ERRSV, 1);
763 1           POPs;
764 18 50         } else if ( count != 1 ) {
765 0           SV *err = sv_2mortal(newSVpvf( "function should return 1 argument, got %d",
766             count ));
767              
768 0           sqlite2_db_set_result( context, err, 1);
769             /* Clear the stack */
770 0 0         for ( i=0; i < count; i++ ) {
771 0           POPs;
772             }
773             } else {
774 18           sqlite2_db_set_result( context, POPs, 0 );
775             }
776            
777 19           PUTBACK;
778            
779 19 50         FREETMPS;
780 19           LEAVE;
781 19           }
782              
783             void
784 11           sqlite2_db_create_function( SV *dbh, const char *name, int argc, SV *func )
785             {
786 11           D_imp_dbh(dbh);
787             int rv;
788            
789             /* Copy the function reference */
790 11           SV *func_sv = newSVsv(func);
791 11           av_push( imp_dbh->functions, func_sv );
792              
793 11           rv = sqlite_create_function( imp_dbh->db, name, argc,
794             sqlite2_db_func_dispatcher, func_sv );
795 11 50         if ( rv != SQLITE_OK )
796             {
797 0           croak( "sqlite_create_function failed with error %s",
798             sqlite_error_string(rv) );
799             }
800 11           }
801              
802             typedef struct aggrInfo aggrInfo;
803             struct aggrInfo {
804             SV *aggr_inst;
805             SV *err;
806             int inited;
807             };
808              
809             static void
810 10           sqlite2_db_aggr_new_dispatcher( sqlite_func *context, aggrInfo *aggr_info )
811             {
812 10           dSP;
813 10           SV *pkg = NULL;
814 10           int count = 0;
815              
816 10           aggr_info->err = NULL;
817 10           aggr_info->aggr_inst = NULL;
818            
819 10           pkg = sqlite_user_data(context);
820 10 50         if ( !pkg )
821 0           return;
822              
823 10           ENTER;
824 10           SAVETMPS;
825            
826 10 50         PUSHMARK(SP);
827 10 50         XPUSHs( sv_2mortal( newSVsv(pkg) ) );
828 10           PUTBACK;
829              
830 10           count = call_method ("new", G_EVAL|G_SCALAR);
831 10           SPAGAIN;
832              
833 10           aggr_info->inited = 1;
834              
835 10 50         if ( SvTRUE( ERRSV ) ) {
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    0          
    0          
    100          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
836 2 50         aggr_info->err = newSVpvf ("error during aggregator's new(): %s",
837 2 50         SvPV_nolen (ERRSV));
    50          
    0          
838 1           POPs;
839 9 50         } else if ( count != 1 ) {
840             int i;
841            
842 0           aggr_info->err = newSVpvf( "new() should return one value, got %d",
843             count );
844             /* Clear the stack */
845 0 0         for ( i=0; i < count; i++ ) {
846 0           POPs;
847             }
848             } else {
849 9           SV *aggr = POPs;
850 9 100         if ( SvROK(aggr) ) {
851 8           aggr_info->aggr_inst = newSVsv(aggr);
852             } else{
853 1           aggr_info->err = newSVpvf( "new() should return a blessed reference" );
854             }
855             }
856              
857 10           PUTBACK;
858              
859 10 50         FREETMPS;
860 10           LEAVE;
861              
862 10           return;
863             }
864              
865             static void
866 24           sqlite2_db_aggr_step_dispatcher (sqlite_func *context,
867             int argc, const char **argv)
868             {
869 24           dSP;
870             int i;
871             aggrInfo *aggr;
872              
873 24           aggr = sqlite_aggregate_context (context, sizeof (aggrInfo));
874 24 50         if ( !aggr )
875 0           return;
876            
877 24           ENTER;
878 24           SAVETMPS;
879            
880             /* initialize on first step */
881 24 100         if ( !aggr->inited ) {
882 10           sqlite2_db_aggr_new_dispatcher( context, aggr );
883             }
884              
885 24 100         if ( aggr->err || !aggr->aggr_inst )
    50          
886             goto cleanup;
887              
888 16 50         PUSHMARK(SP);
889 16 50         XPUSHs( sv_2mortal( newSVsv( aggr->aggr_inst ) ));
890 22 100         for ( i=0; i < argc; i++ ) {
891             SV *arg;
892            
893 6 100         if ( !argv[i] ) {
894 2           arg = &PL_sv_undef;
895             } else {
896 4           arg = sv_2mortal( newSVpv(argv[i], 0));
897             }
898              
899 6 50         XPUSHs(arg);
900             }
901 16           PUTBACK;
902              
903 16           call_method ("step", G_SCALAR|G_EVAL|G_DISCARD);
904              
905             /* Check for an error */
906 16 50         if (SvTRUE(ERRSV) ) {
    50          
    50          
    50          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    100          
907 2 50         aggr->err = newSVpvf( "error during aggregator's step(): %s",
908 2 50         SvPV_nolen(ERRSV));
    50          
    0          
909 1           POPs;
910             }
911              
912             cleanup:
913 24 100         FREETMPS;
914 24           LEAVE;
915             }
916              
917             static void
918 16           sqlite2_db_aggr_finalize_dispatcher( sqlite_func *context )
919             {
920 16           dSP;
921             aggrInfo *aggr, myAggr;
922 16           int count = 0;
923              
924 16           aggr = sqlite_aggregate_context (context, sizeof (aggrInfo));
925            
926 16           ENTER;
927 16           SAVETMPS;
928            
929 16 50         if ( !aggr ) {
930             /* SQLite seems to refuse to create a context structure
931             from finalize() */
932 0           aggr = &myAggr;
933 0           aggr->aggr_inst = NULL;
934 0           aggr->err = NULL;
935 0           sqlite2_db_aggr_new_dispatcher (context, aggr);
936             }
937              
938 16 100         if ( ! aggr->err && aggr->aggr_inst ) {
    100          
939 7 50         PUSHMARK(SP);
940 7 50         XPUSHs( sv_2mortal( newSVsv( aggr->aggr_inst )) );
941 7           PUTBACK;
942              
943 7           count = call_method( "finalize", G_SCALAR|G_EVAL );
944 7           SPAGAIN;
945              
946 7 50         if ( SvTRUE(ERRSV) ) {
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    0          
    0          
    100          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
947 2 50         aggr->err = newSVpvf ("error during aggregator's finalize(): %s",
948 2 50         SvPV_nolen(ERRSV) ) ;
    50          
    0          
949 1           POPs;
950 6 50         } else if ( count != 1 ) {
951             int i;
952 0           aggr->err = newSVpvf( "finalize() should return 1 value, got %d",
953             count );
954             /* Clear the stack */
955 0 0         for ( i=0; i
956 0           POPs;
957             }
958             } else {
959 6           sqlite2_db_set_result( context, POPs, 0 );
960             }
961 7           PUTBACK;
962             }
963            
964 16 100         if ( aggr->err ) {
965 4 50         warn( "DBD::SQLite: error in aggregator cannot be reported to SQLite: %s", SvPV_nolen( aggr->err ) );
966            
967             /* sqlite2_db_set_result( context, aggr->err, 1 ); */
968 4           SvREFCNT_dec( aggr->err );
969 4           aggr->err = NULL;
970             }
971            
972 16 100         if ( aggr->aggr_inst ) {
973 8           SvREFCNT_dec( aggr->aggr_inst );
974 8           aggr->aggr_inst = NULL;
975             }
976            
977 16 100         FREETMPS;
978 16           LEAVE;
979 16           }
980              
981             void
982 6           sqlite2_db_create_aggregate( SV *dbh, const char *name, int argc, SV *aggr_pkg )
983             {
984 6           D_imp_dbh(dbh);
985             int rv;
986            
987             /* Copy the aggregate reference */
988 6           SV *aggr_pkg_copy = newSVsv(aggr_pkg);
989 6           av_push( imp_dbh->aggregates, aggr_pkg_copy );
990              
991 6           rv = sqlite_create_aggregate( imp_dbh->db, name, argc,
992             sqlite2_db_aggr_step_dispatcher,
993             sqlite2_db_aggr_finalize_dispatcher,
994             aggr_pkg_copy );
995            
996 6 50         if ( rv != SQLITE_OK )
997             {
998 0           croak( "sqlite_create_aggregate failed with error %s",
999             sqlite_error_string(rv) );
1000             }
1001 6           }
1002              
1003             /* end */