Annotation of embedaddon/php/ext/pdo_sqlite/sqlite_driver.c, revision 1.1.1.3
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
1.1.1.3 ! misho 5: | Copyright (c) 1997-2013 The PHP Group |
1.1 misho 6: +----------------------------------------------------------------------+
7: | This source file is subject to version 3.01 of the PHP license, |
8: | that is bundled with this package in the file LICENSE, and is |
9: | available through the world-wide-web at the following url: |
10: | http://www.php.net/license/3_01.txt |
11: | If you did not receive a copy of the PHP license and are unable to |
12: | obtain it through the world-wide-web, please send a note to |
13: | license@php.net so we can mail you a copy immediately. |
14: +----------------------------------------------------------------------+
15: | Author: Wez Furlong <wez@php.net> |
16: +----------------------------------------------------------------------+
17: */
18:
1.1.1.2 misho 19: /* $Id$ */
1.1 misho 20:
21: #ifdef HAVE_CONFIG_H
22: #include "config.h"
23: #endif
24:
25: #include "php.h"
26: #include "php_ini.h"
27: #include "ext/standard/info.h"
28: #include "pdo/php_pdo.h"
29: #include "pdo/php_pdo_driver.h"
30: #include "php_pdo_sqlite.h"
31: #include "php_pdo_sqlite_int.h"
32: #include "zend_exceptions.h"
33:
34: int _pdo_sqlite_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int line TSRMLS_DC) /* {{{ */
35: {
36: pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
37: pdo_error_type *pdo_err = stmt ? &stmt->error_code : &dbh->error_code;
38: pdo_sqlite_error_info *einfo = &H->einfo;
39:
40: einfo->errcode = sqlite3_errcode(H->db);
41: einfo->file = file;
42: einfo->line = line;
43:
44: if (einfo->errcode != SQLITE_OK) {
45: if (einfo->errmsg) {
46: pefree(einfo->errmsg, dbh->is_persistent);
47: }
48: einfo->errmsg = pestrdup((char*)sqlite3_errmsg(H->db), dbh->is_persistent);
49: } else { /* no error */
50: strncpy(*pdo_err, PDO_ERR_NONE, sizeof(PDO_ERR_NONE));
51: return 0;
52: }
53: switch (einfo->errcode) {
54: case SQLITE_NOTFOUND:
55: strncpy(*pdo_err, "42S02", sizeof("42S02"));
56: break;
57:
58: case SQLITE_INTERRUPT:
59: strncpy(*pdo_err, "01002", sizeof("01002"));
60: break;
61:
62: case SQLITE_NOLFS:
63: strncpy(*pdo_err, "HYC00", sizeof("HYC00"));
64: break;
65:
66: case SQLITE_TOOBIG:
67: strncpy(*pdo_err, "22001", sizeof("22001"));
68: break;
69:
70: case SQLITE_CONSTRAINT:
71: strncpy(*pdo_err, "23000", sizeof("23000"));
72: break;
73:
74: case SQLITE_ERROR:
75: default:
76: strncpy(*pdo_err, "HY000", sizeof("HY000"));
77: break;
78: }
79:
80: if (!dbh->methods) {
81: zend_throw_exception_ex(php_pdo_get_exception(), einfo->errcode TSRMLS_CC, "SQLSTATE[%s] [%d] %s",
82: *pdo_err, einfo->errcode, einfo->errmsg);
83: }
84:
85: return einfo->errcode;
86: }
87: /* }}} */
88:
89: static int pdo_sqlite_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC)
90: {
91: pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
92: pdo_sqlite_error_info *einfo = &H->einfo;
93:
94: if (einfo->errcode) {
95: add_next_index_long(info, einfo->errcode);
96: add_next_index_string(info, einfo->errmsg, 1);
97: }
98:
99: return 1;
100: }
101:
102: static void pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle *H TSRMLS_DC)
103: {
104: struct pdo_sqlite_func *func;
105:
106: while (H->funcs) {
107: func = H->funcs;
108: H->funcs = func->next;
109:
110: if (H->db) {
111: /* delete the function from the handle */
112: sqlite3_create_function(H->db,
113: func->funcname,
114: func->argc,
115: SQLITE_UTF8,
116: func,
117: NULL, NULL, NULL);
118: }
119:
120: efree((char*)func->funcname);
121: if (func->func) {
122: zval_ptr_dtor(&func->func);
123: }
124: if (func->step) {
125: zval_ptr_dtor(&func->step);
126: }
127: if (func->fini) {
128: zval_ptr_dtor(&func->fini);
129: }
130: efree(func);
131: }
1.1.1.2 misho 132:
133: while (H->collations) {
134: struct pdo_sqlite_collation *collation;
135: collation = H->collations;
136: H->collations = collation->next;
137:
138: if (H->db) {
139: /* delete the collation from the handle */
140: sqlite3_create_collation(H->db,
141: collation->name,
142: SQLITE_UTF8,
143: collation,
144: NULL);
145: }
146:
147: efree((char*)collation->name);
148: if (collation->callback) {
149: zval_ptr_dtor(&collation->callback);
150: }
151: efree(collation);
152: }
1.1 misho 153: }
154:
155: static int sqlite_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
156: {
157: pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
158:
159: if (H) {
160: pdo_sqlite_error_info *einfo = &H->einfo;
161:
162: pdo_sqlite_cleanup_callbacks(H TSRMLS_CC);
163: if (H->db) {
164: sqlite3_close(H->db);
165: H->db = NULL;
166: }
167: if (einfo->errmsg) {
168: pefree(einfo->errmsg, dbh->is_persistent);
169: einfo->errmsg = NULL;
170: }
171: pefree(H, dbh->is_persistent);
172: dbh->driver_data = NULL;
173: }
174: return 0;
175: }
176: /* }}} */
177:
178: static int sqlite_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC)
179: {
180: pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
181: pdo_sqlite_stmt *S = ecalloc(1, sizeof(pdo_sqlite_stmt));
182: int i;
183: const char *tail;
184:
185: S->H = H;
186: stmt->driver_data = S;
187: stmt->methods = &sqlite_stmt_methods;
188: stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL|PDO_PLACEHOLDER_NAMED;
189:
190: if (PDO_CURSOR_FWDONLY != pdo_attr_lval(driver_options, PDO_ATTR_CURSOR, PDO_CURSOR_FWDONLY TSRMLS_CC)) {
191: H->einfo.errcode = SQLITE_ERROR;
192: pdo_sqlite_error(dbh);
193: return 0;
194: }
195:
196: i = sqlite3_prepare(H->db, sql, sql_len, &S->stmt, &tail);
197: if (i == SQLITE_OK) {
198: return 1;
199: }
200:
201: pdo_sqlite_error(dbh);
202:
203: return 0;
204: }
205:
206: static long sqlite_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC)
207: {
208: pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
209: char *errmsg = NULL;
210:
211: if (sqlite3_exec(H->db, sql, NULL, NULL, &errmsg) != SQLITE_OK) {
212: pdo_sqlite_error(dbh);
213: if (errmsg)
214: sqlite3_free(errmsg);
215:
216: return -1;
217: } else {
218: return sqlite3_changes(H->db);
219: }
220: }
221:
222: static char *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const char *name, unsigned int *len TSRMLS_DC)
223: {
224: pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
225: char *id;
226:
227: id = php_pdo_int64_to_str(sqlite3_last_insert_rowid(H->db) TSRMLS_CC);
228: *len = strlen(id);
229: return id;
230: }
231:
232: /* NB: doesn't handle binary strings... use prepared stmts for that */
233: static int sqlite_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen, enum pdo_param_type paramtype TSRMLS_DC)
234: {
235: *quoted = safe_emalloc(2, unquotedlen, 3);
236: sqlite3_snprintf(2*unquotedlen + 3, *quoted, "'%q'", unquoted);
237: *quotedlen = strlen(*quoted);
238: return 1;
239: }
240:
241: static int sqlite_handle_begin(pdo_dbh_t *dbh TSRMLS_DC)
242: {
243: pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
244: char *errmsg = NULL;
245:
246: if (sqlite3_exec(H->db, "BEGIN", NULL, NULL, &errmsg) != SQLITE_OK) {
247: pdo_sqlite_error(dbh);
248: if (errmsg)
249: sqlite3_free(errmsg);
250: return 0;
251: }
252: return 1;
253: }
254:
255: static int sqlite_handle_commit(pdo_dbh_t *dbh TSRMLS_DC)
256: {
257: pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
258: char *errmsg = NULL;
259:
260: if (sqlite3_exec(H->db, "COMMIT", NULL, NULL, &errmsg) != SQLITE_OK) {
261: pdo_sqlite_error(dbh);
262: if (errmsg)
263: sqlite3_free(errmsg);
264: return 0;
265: }
266: return 1;
267: }
268:
269: static int sqlite_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
270: {
271: pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
272: char *errmsg = NULL;
273:
274: if (sqlite3_exec(H->db, "ROLLBACK", NULL, NULL, &errmsg) != SQLITE_OK) {
275: pdo_sqlite_error(dbh);
276: if (errmsg)
277: sqlite3_free(errmsg);
278: return 0;
279: }
280: return 1;
281: }
282:
283: static int pdo_sqlite_get_attribute(pdo_dbh_t *dbh, long attr, zval *return_value TSRMLS_DC)
284: {
285: switch (attr) {
286: case PDO_ATTR_CLIENT_VERSION:
287: case PDO_ATTR_SERVER_VERSION:
288: ZVAL_STRING(return_value, (char *)sqlite3_libversion(), 1);
289: break;
290:
291: default:
292: return 0;
293: }
294:
295: return 1;
296: }
297:
298: static int pdo_sqlite_set_attr(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC)
299: {
300: pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
301:
302: switch (attr) {
303: case PDO_ATTR_TIMEOUT:
304: convert_to_long(val);
305: sqlite3_busy_timeout(H->db, Z_LVAL_P(val) * 1000);
306: return 1;
307: }
308: return 0;
309: }
310:
311: static int do_callback(struct pdo_sqlite_fci *fc, zval *cb,
312: int argc, sqlite3_value **argv, sqlite3_context *context,
313: int is_agg TSRMLS_DC)
314: {
315: zval ***zargs = NULL;
316: zval *retval = NULL;
317: int i;
318: int ret;
319: int fake_argc;
320: zval **agg_context = NULL;
321:
322: if (is_agg) {
323: is_agg = 2;
324: }
325:
326: fake_argc = argc + is_agg;
327:
328: fc->fci.size = sizeof(fc->fci);
329: fc->fci.function_table = EG(function_table);
330: fc->fci.function_name = cb;
331: fc->fci.symbol_table = NULL;
332: fc->fci.object_ptr = NULL;
333: fc->fci.retval_ptr_ptr = &retval;
334: fc->fci.param_count = fake_argc;
335:
336: /* build up the params */
337:
338: if (fake_argc) {
339: zargs = (zval ***)safe_emalloc(fake_argc, sizeof(zval **), 0);
340: }
341:
342: if (is_agg) {
343: /* summon the aggregation context */
344: agg_context = (zval**)sqlite3_aggregate_context(context, sizeof(zval*));
345: if (!*agg_context) {
346: MAKE_STD_ZVAL(*agg_context);
347: ZVAL_NULL(*agg_context);
348: }
349: zargs[0] = agg_context;
350:
351: zargs[1] = emalloc(sizeof(zval*));
352: MAKE_STD_ZVAL(*zargs[1]);
353: ZVAL_LONG(*zargs[1], sqlite3_aggregate_count(context));
354: }
355:
356: for (i = 0; i < argc; i++) {
357: zargs[i + is_agg] = emalloc(sizeof(zval *));
358: MAKE_STD_ZVAL(*zargs[i + is_agg]);
359:
360: /* get the value */
361: switch (sqlite3_value_type(argv[i])) {
362: case SQLITE_INTEGER:
363: ZVAL_LONG(*zargs[i + is_agg], sqlite3_value_int(argv[i]));
364: break;
365:
366: case SQLITE_FLOAT:
367: ZVAL_DOUBLE(*zargs[i + is_agg], sqlite3_value_double(argv[i]));
368: break;
369:
370: case SQLITE_NULL:
371: ZVAL_NULL(*zargs[i + is_agg]);
372: break;
373:
374: case SQLITE_BLOB:
375: case SQLITE3_TEXT:
376: default:
377: ZVAL_STRINGL(*zargs[i + is_agg], (char*)sqlite3_value_text(argv[i]),
378: sqlite3_value_bytes(argv[i]), 1);
379: break;
380: }
381: }
382:
383:
384: fc->fci.params = zargs;
385:
386:
387: if ((ret = zend_call_function(&fc->fci, &fc->fcc TSRMLS_CC)) == FAILURE) {
388: php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the callback");
389: }
390:
391: /* clean up the params */
392: if (zargs) {
393: for (i = is_agg; i < fake_argc; i++) {
394: zval_ptr_dtor(zargs[i]);
395: efree(zargs[i]);
396: }
397: if (is_agg) {
398: zval_ptr_dtor(zargs[1]);
399: efree(zargs[1]);
400: }
401: efree(zargs);
402: }
403:
404: if (!is_agg || !argv) {
405: /* only set the sqlite return value if we are a scalar function,
406: * or if we are finalizing an aggregate */
407: if (retval) {
408: switch (Z_TYPE_P(retval)) {
409: case IS_LONG:
410: sqlite3_result_int(context, Z_LVAL_P(retval));
411: break;
412:
413: case IS_NULL:
414: sqlite3_result_null(context);
415: break;
416:
417: case IS_DOUBLE:
418: sqlite3_result_double(context, Z_DVAL_P(retval));
419: break;
420:
421: default:
422: convert_to_string_ex(&retval);
423: sqlite3_result_text(context, Z_STRVAL_P(retval),
424: Z_STRLEN_P(retval), SQLITE_TRANSIENT);
425: break;
426: }
427: } else {
428: sqlite3_result_error(context, "failed to invoke callback", 0);
429: }
430:
431: if (agg_context) {
432: zval_ptr_dtor(agg_context);
433: }
434: } else {
435: /* we're stepping in an aggregate; the return value goes into
436: * the context */
437: if (agg_context) {
438: zval_ptr_dtor(agg_context);
439: }
440: if (retval) {
441: *agg_context = retval;
442: retval = NULL;
443: } else {
444: *agg_context = NULL;
445: }
446: }
447:
448: if (retval) {
449: zval_ptr_dtor(&retval);
450: }
451:
452: return ret;
453: }
454:
455: static void php_sqlite3_func_callback(sqlite3_context *context, int argc,
456: sqlite3_value **argv)
457: {
458: struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
459: TSRMLS_FETCH();
460:
461: do_callback(&func->afunc, func->func, argc, argv, context, 0 TSRMLS_CC);
462: }
463:
464: static void php_sqlite3_func_step_callback(sqlite3_context *context, int argc,
465: sqlite3_value **argv)
466: {
467: struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
468: TSRMLS_FETCH();
469:
470: do_callback(&func->astep, func->step, argc, argv, context, 1 TSRMLS_CC);
471: }
472:
473: static void php_sqlite3_func_final_callback(sqlite3_context *context)
474: {
475: struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
476: TSRMLS_FETCH();
477:
478: do_callback(&func->afini, func->fini, 0, NULL, context, 1 TSRMLS_CC);
479: }
480:
1.1.1.2 misho 481: static int php_sqlite3_collation_callback(void *context,
482: int string1_len, const void *string1,
483: int string2_len, const void *string2)
484: {
485: int ret;
486: zval *zstring1, *zstring2;
487: zval **zargs[2];
488: zval *retval = NULL;
489: struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context;
490: TSRMLS_FETCH();
491:
492: collation->fc.fci.size = sizeof(collation->fc.fci);
493: collation->fc.fci.function_table = EG(function_table);
494: collation->fc.fci.function_name = collation->callback;
495: collation->fc.fci.symbol_table = NULL;
496: collation->fc.fci.object_ptr = NULL;
497: collation->fc.fci.retval_ptr_ptr = &retval;
498:
499: // Prepare the arguments.
500: MAKE_STD_ZVAL(zstring1);
501: ZVAL_STRINGL(zstring1, (char *) string1, string1_len, 1);
502: zargs[0] = &zstring1;
503: MAKE_STD_ZVAL(zstring2);
504: ZVAL_STRINGL(zstring2, (char *) string2, string2_len, 1);
505: zargs[1] = &zstring2;
506: collation->fc.fci.param_count = 2;
507: collation->fc.fci.params = zargs;
508:
509: if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc TSRMLS_CC)) == FAILURE) {
510: php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the callback");
511: }
512: else if (retval) {
513: if (Z_TYPE_P(retval) != IS_LONG) {
514: convert_to_long_ex(&retval);
515: }
516: ret = 0;
517: if (Z_LVAL_P(retval) > 0) {
518: ret = 1;
519: }
520: else if (Z_LVAL_P(retval) < 0) {
521: ret = -1;
522: }
523: zval_ptr_dtor(&retval);
524: }
525:
526: zval_ptr_dtor(zargs[0]);
527: zval_ptr_dtor(zargs[1]);
528:
529: return ret;
530: }
531:
1.1 misho 532: /* {{{ bool SQLite::sqliteCreateFunction(string name, mixed callback [, int argcount])
533: Registers a UDF with the sqlite db handle */
534: static PHP_METHOD(SQLite, sqliteCreateFunction)
535: {
536: struct pdo_sqlite_func *func;
537: zval *callback;
538: char *func_name;
539: int func_name_len;
540: long argc = -1;
541: char *cbname = NULL;
542: pdo_dbh_t *dbh;
543: pdo_sqlite_db_handle *H;
544: int ret;
545:
546: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l",
547: &func_name, &func_name_len, &callback, &argc)) {
548: RETURN_FALSE;
549: }
550:
551: dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
552: PDO_CONSTRUCT_CHECK;
553:
554: if (!zend_is_callable(callback, 0, &cbname TSRMLS_CC)) {
555: php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname);
556: efree(cbname);
557: RETURN_FALSE;
558: }
559: efree(cbname);
560:
561: H = (pdo_sqlite_db_handle *)dbh->driver_data;
562:
563: func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
564:
565: ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
566: func, php_sqlite3_func_callback, NULL, NULL);
567: if (ret == SQLITE_OK) {
568: func->funcname = estrdup(func_name);
569:
570: MAKE_STD_ZVAL(func->func);
571: MAKE_COPY_ZVAL(&callback, func->func);
572:
573: func->argc = argc;
574:
575: func->next = H->funcs;
576: H->funcs = func;
577:
578: RETURN_TRUE;
579: }
580:
581: efree(func);
582: RETURN_FALSE;
583: }
584: /* }}} */
585:
586: /* {{{ bool SQLite::sqliteCreateAggregate(string name, mixed step, mixed fini [, int argcount])
587: Registers a UDF with the sqlite db handle */
588:
589: /* The step function should have the prototype:
590: mixed step(mixed $context, int $rownumber, $value [, $value2 [, ...]])
591:
592: $context will be null for the first row; on subsequent rows it will have
593: the value that was previously returned from the step function; you should
594: use this to maintain state for the aggregate.
595:
596: The fini function should have the prototype:
597: mixed fini(mixed $context, int $rownumber)
598:
599: $context will hold the return value from the very last call to the step function.
600: rownumber will hold the number of rows over which the aggregate was performed.
601: The return value of this function will be used as the return value for this
602: aggregate UDF.
603: */
604:
605: static PHP_METHOD(SQLite, sqliteCreateAggregate)
606: {
607: struct pdo_sqlite_func *func;
608: zval *step_callback, *fini_callback;
609: char *func_name;
610: int func_name_len;
611: long argc = -1;
612: char *cbname = NULL;
613: pdo_dbh_t *dbh;
614: pdo_sqlite_db_handle *H;
615: int ret;
616:
617: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szz|l",
618: &func_name, &func_name_len, &step_callback, &fini_callback, &argc)) {
619: RETURN_FALSE;
620: }
621:
622: dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
623: PDO_CONSTRUCT_CHECK;
624:
625: if (!zend_is_callable(step_callback, 0, &cbname TSRMLS_CC)) {
626: php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname);
627: efree(cbname);
628: RETURN_FALSE;
629: }
630: efree(cbname);
631: if (!zend_is_callable(fini_callback, 0, &cbname TSRMLS_CC)) {
632: php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname);
633: efree(cbname);
634: RETURN_FALSE;
635: }
636: efree(cbname);
637:
638: H = (pdo_sqlite_db_handle *)dbh->driver_data;
639:
640: func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
641:
642: ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
643: func, NULL, php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
644: if (ret == SQLITE_OK) {
645: func->funcname = estrdup(func_name);
646:
647: MAKE_STD_ZVAL(func->step);
648: MAKE_COPY_ZVAL(&step_callback, func->step);
649:
650: MAKE_STD_ZVAL(func->fini);
651: MAKE_COPY_ZVAL(&fini_callback, func->fini);
652:
653: func->argc = argc;
654:
655: func->next = H->funcs;
656: H->funcs = func;
657:
658: RETURN_TRUE;
659: }
660:
661: efree(func);
662: RETURN_FALSE;
663: }
664: /* }}} */
1.1.1.2 misho 665:
666: /* {{{ bool SQLite::sqliteCreateCollation(string name, mixed callback)
667: Registers a collation with the sqlite db handle */
668: static PHP_METHOD(SQLite, sqliteCreateCollation)
669: {
670: struct pdo_sqlite_collation *collation;
671: zval *callback;
672: char *collation_name;
673: int collation_name_len;
674: char *cbname = NULL;
675: pdo_dbh_t *dbh;
676: pdo_sqlite_db_handle *H;
677: int ret;
678:
679: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz",
680: &collation_name, &collation_name_len, &callback)) {
681: RETURN_FALSE;
682: }
683:
684: dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
685: PDO_CONSTRUCT_CHECK;
686:
687: if (!zend_is_callable(callback, 0, &cbname TSRMLS_CC)) {
688: php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname);
689: efree(cbname);
690: RETURN_FALSE;
691: }
692: efree(cbname);
693:
694: H = (pdo_sqlite_db_handle *)dbh->driver_data;
695:
696: collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));
697:
698: ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_collation_callback);
699: if (ret == SQLITE_OK) {
700: collation->name = estrdup(collation_name);
701:
702: MAKE_STD_ZVAL(collation->callback);
703: MAKE_COPY_ZVAL(&callback, collation->callback);
704:
705: collation->next = H->collations;
706: H->collations = collation;
707:
708: RETURN_TRUE;
709: }
710:
711: efree(collation);
712: RETURN_FALSE;
713: }
714: /* }}} */
715:
1.1 misho 716: static const zend_function_entry dbh_methods[] = {
717: PHP_ME(SQLite, sqliteCreateFunction, NULL, ZEND_ACC_PUBLIC)
718: PHP_ME(SQLite, sqliteCreateAggregate, NULL, ZEND_ACC_PUBLIC)
1.1.1.2 misho 719: PHP_ME(SQLite, sqliteCreateCollation, NULL, ZEND_ACC_PUBLIC)
1.1 misho 720: PHP_FE_END
721: };
722:
723: static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind TSRMLS_DC)
724: {
725: switch (kind) {
726: case PDO_DBH_DRIVER_METHOD_KIND_DBH:
727: return dbh_methods;
728:
729: default:
730: return NULL;
731: }
732: }
733:
734: static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh TSRMLS_DC)
735: {
736: pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
737: /* unregister functions, so that they don't linger for the next
738: * request */
739: if (H) {
740: pdo_sqlite_cleanup_callbacks(H TSRMLS_CC);
741: }
742: }
743:
744: static struct pdo_dbh_methods sqlite_methods = {
745: sqlite_handle_closer,
746: sqlite_handle_preparer,
747: sqlite_handle_doer,
748: sqlite_handle_quoter,
749: sqlite_handle_begin,
750: sqlite_handle_commit,
751: sqlite_handle_rollback,
752: pdo_sqlite_set_attr,
753: pdo_sqlite_last_insert_id,
754: pdo_sqlite_fetch_error_func,
755: pdo_sqlite_get_attribute,
756: NULL, /* check_liveness: not needed */
757: get_driver_methods,
758: pdo_sqlite_request_shutdown
759: };
760:
761: static char *make_filename_safe(const char *filename TSRMLS_DC)
762: {
1.1.1.3 ! misho 763: if (*filename && memcmp(filename, ":memory:", sizeof(":memory:"))) {
1.1 misho 764: char *fullpath = expand_filepath(filename, NULL TSRMLS_CC);
765:
766: if (!fullpath) {
767: return NULL;
768: }
769:
770: if (php_check_open_basedir(fullpath TSRMLS_CC)) {
771: efree(fullpath);
772: return NULL;
773: }
774: return fullpath;
775: }
776: return estrdup(filename);
777: }
778:
779: static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
780: const char *arg5, const char *arg6)
781: {
782: char *filename;
783: switch (access_type) {
784: case SQLITE_COPY: {
785: TSRMLS_FETCH();
786: filename = make_filename_safe(arg4 TSRMLS_CC);
787: if (!filename) {
788: return SQLITE_DENY;
789: }
790: efree(filename);
791: return SQLITE_OK;
792: }
793:
794: case SQLITE_ATTACH: {
795: TSRMLS_FETCH();
796: filename = make_filename_safe(arg3 TSRMLS_CC);
797: if (!filename) {
798: return SQLITE_DENY;
799: }
800: efree(filename);
801: return SQLITE_OK;
802: }
803:
804: default:
805: /* access allowed */
806: return SQLITE_OK;
807: }
808: }
809:
810: static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
811: {
812: pdo_sqlite_db_handle *H;
813: int i, ret = 0;
814: long timeout = 60;
815: char *filename;
816:
817: H = pecalloc(1, sizeof(pdo_sqlite_db_handle), dbh->is_persistent);
818:
819: H->einfo.errcode = 0;
820: H->einfo.errmsg = NULL;
821: dbh->driver_data = H;
822:
823: filename = make_filename_safe(dbh->data_source TSRMLS_CC);
824:
825: if (!filename) {
826: zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC,
1.1.1.2 misho 827: "open_basedir prohibits opening %s",
1.1 misho 828: dbh->data_source);
829: goto cleanup;
830: }
831:
832: i = sqlite3_open(filename, &H->db);
833: efree(filename);
834:
835: if (i != SQLITE_OK) {
836: pdo_sqlite_error(dbh);
837: goto cleanup;
838: }
839:
1.1.1.2 misho 840: if (PG(open_basedir) && *PG(open_basedir)) {
1.1 misho 841: sqlite3_set_authorizer(H->db, authorizer, NULL);
842: }
843:
844: if (driver_options) {
845: timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout TSRMLS_CC);
846: }
847: sqlite3_busy_timeout(H->db, timeout * 1000);
848:
849: dbh->alloc_own_columns = 1;
850: dbh->max_escaped_char_length = 2;
851:
852: ret = 1;
853:
854: cleanup:
855: dbh->methods = &sqlite_methods;
856:
857: return ret;
858: }
859: /* }}} */
860:
861: pdo_driver_t pdo_sqlite_driver = {
862: PDO_DRIVER_HEADER(sqlite),
863: pdo_sqlite_handle_factory
864: };
865:
866: /*
867: * Local variables:
868: * tab-width: 4
869: * c-basic-offset: 4
870: * End:
871: * vim600: noet sw=4 ts=4 fdm=marker
872: * vim<600: noet sw=4 ts=4
873: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>