xref: /PHP-5.4/ext/pdo_sqlite/sqlite_driver.c (revision c0d060f5)
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2014 The PHP Group                                |
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 
19 /* $Id$ */
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 
_pdo_sqlite_error(pdo_dbh_t * dbh,pdo_stmt_t * stmt,const char * file,int line TSRMLS_DC)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 
pdo_sqlite_fetch_error_func(pdo_dbh_t * dbh,pdo_stmt_t * stmt,zval * info TSRMLS_DC)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 
pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle * H TSRMLS_DC)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 	}
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 	}
153 }
154 
sqlite_handle_closer(pdo_dbh_t * dbh TSRMLS_DC)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 
sqlite_handle_preparer(pdo_dbh_t * dbh,const char * sql,long sql_len,pdo_stmt_t * stmt,zval * driver_options TSRMLS_DC)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 
sqlite_handle_doer(pdo_dbh_t * dbh,const char * sql,long sql_len TSRMLS_DC)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 
pdo_sqlite_last_insert_id(pdo_dbh_t * dbh,const char * name,unsigned int * len TSRMLS_DC)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 */
sqlite_handle_quoter(pdo_dbh_t * dbh,const char * unquoted,int unquotedlen,char ** quoted,int * quotedlen,enum pdo_param_type paramtype TSRMLS_DC)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 
sqlite_handle_begin(pdo_dbh_t * dbh TSRMLS_DC)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 
sqlite_handle_commit(pdo_dbh_t * dbh TSRMLS_DC)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 
sqlite_handle_rollback(pdo_dbh_t * dbh TSRMLS_DC)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 
pdo_sqlite_get_attribute(pdo_dbh_t * dbh,long attr,zval * return_value TSRMLS_DC)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 
pdo_sqlite_set_attr(pdo_dbh_t * dbh,long attr,zval * val TSRMLS_DC)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 
do_callback(struct pdo_sqlite_fci * fc,zval * cb,int argc,sqlite3_value ** argv,sqlite3_context * context,int is_agg TSRMLS_DC)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 
php_sqlite3_func_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)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 
php_sqlite3_func_step_callback(sqlite3_context * context,int argc,sqlite3_value ** argv)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 
php_sqlite3_func_final_callback(sqlite3_context * context)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 
php_sqlite3_collation_callback(void * context,int string1_len,const void * string1,int string2_len,const void * string2)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 
532 /* {{{ bool SQLite::sqliteCreateFunction(string name, mixed callback [, int argcount])
533    Registers a UDF with the sqlite db handle */
PHP_METHOD(SQLite,sqliteCreateFunction)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 
PHP_METHOD(SQLite,sqliteCreateAggregate)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 /* }}} */
665 
666 /* {{{ bool SQLite::sqliteCreateCollation(string name, mixed callback)
667    Registers a collation with the sqlite db handle */
PHP_METHOD(SQLite,sqliteCreateCollation)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 
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)
719 	PHP_ME(SQLite, sqliteCreateCollation, NULL, ZEND_ACC_PUBLIC)
720 	PHP_FE_END
721 };
722 
get_driver_methods(pdo_dbh_t * dbh,int kind TSRMLS_DC)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 
pdo_sqlite_request_shutdown(pdo_dbh_t * dbh TSRMLS_DC)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 
make_filename_safe(const char * filename TSRMLS_DC)761 static char *make_filename_safe(const char *filename TSRMLS_DC)
762 {
763 	if (*filename && memcmp(filename, ":memory:", sizeof(":memory:"))) {
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 
authorizer(void * autharg,int access_type,const char * arg3,const char * arg4,const char * arg5,const char * arg6)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 
pdo_sqlite_handle_factory(pdo_dbh_t * dbh,zval * driver_options TSRMLS_DC)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,
827 			"open_basedir prohibits opening %s",
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 
840 	if (PG(open_basedir) && *PG(open_basedir)) {
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  */
874