xref: /PHP-7.3/ext/pdo_sqlite/sqlite_statement.c (revision e6160e99)
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 7                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2018 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 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22 
23 #include "php.h"
24 #include "php_ini.h"
25 #include "ext/standard/info.h"
26 #include "pdo/php_pdo.h"
27 #include "pdo/php_pdo_driver.h"
28 #include "php_pdo_sqlite.h"
29 #include "php_pdo_sqlite_int.h"
30 
31 
pdo_sqlite_stmt_dtor(pdo_stmt_t * stmt)32 static int pdo_sqlite_stmt_dtor(pdo_stmt_t *stmt)
33 {
34 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
35 
36 	if (S->stmt) {
37 		sqlite3_finalize(S->stmt);
38 		S->stmt = NULL;
39 	}
40 	efree(S);
41 	return 1;
42 }
43 
44 /**
45  * Change the column count on the statement.
46  *
47  * Since PHP 7.2 sqlite3_prepare_v2 is used which auto recompile prepared statement on schema change.
48  * Instead of raise an error on schema change, the result set will change, and the statement's columns must be updated.
49  *
50  * See bug #78192
51  */
pdo_sqlite_stmt_set_column_count(pdo_stmt_t * stmt,int new_count)52 static void pdo_sqlite_stmt_set_column_count(pdo_stmt_t *stmt, int new_count)
53 {
54 	/* Columns not yet "described" */
55 	if (!stmt->columns) {
56 		stmt->column_count = new_count;
57 
58 		return;
59 	}
60 
61 	/*
62 	 * The column count has not changed : no need to reload columns description
63 	 * Note: Do not handle attribute name change, without column count change
64 	 */
65 	if (new_count == stmt->column_count) {
66 		return;
67 	}
68 
69 	/* Free previous columns to force reload description */
70 	int i;
71 
72 	for (i = 0; i < stmt->column_count; i++) {
73 		if (stmt->columns[i].name) {
74 			zend_string_release(stmt->columns[i].name);
75 			stmt->columns[i].name = NULL;
76 		}
77 	}
78 
79 	efree(stmt->columns);
80 	stmt->columns = NULL;
81 	stmt->column_count = new_count;
82 }
83 
pdo_sqlite_stmt_execute(pdo_stmt_t * stmt)84 static int pdo_sqlite_stmt_execute(pdo_stmt_t *stmt)
85 {
86 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
87 
88 	if (stmt->executed && !S->done) {
89 		sqlite3_reset(S->stmt);
90 	}
91 
92 	S->done = 0;
93 	switch (sqlite3_step(S->stmt)) {
94 		case SQLITE_ROW:
95 			S->pre_fetched = 1;
96 			pdo_sqlite_stmt_set_column_count(stmt, sqlite3_data_count(S->stmt));
97 			return 1;
98 
99 		case SQLITE_DONE:
100 			pdo_sqlite_stmt_set_column_count(stmt, sqlite3_column_count(S->stmt));
101 			stmt->row_count = sqlite3_changes(S->H->db);
102 			sqlite3_reset(S->stmt);
103 			S->done = 1;
104 			return 1;
105 
106 		case SQLITE_ERROR:
107 			sqlite3_reset(S->stmt);
108 		case SQLITE_MISUSE:
109 		case SQLITE_BUSY:
110 		default:
111 			pdo_sqlite_error_stmt(stmt);
112 			return 0;
113 	}
114 }
115 
pdo_sqlite_stmt_param_hook(pdo_stmt_t * stmt,struct pdo_bound_param_data * param,enum pdo_param_event event_type)116 static int pdo_sqlite_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param,
117 		enum pdo_param_event event_type)
118 {
119 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
120 	zval *parameter;
121 
122 	switch (event_type) {
123 		case PDO_PARAM_EVT_EXEC_PRE:
124 			if (stmt->executed && !S->done) {
125 				sqlite3_reset(S->stmt);
126 				S->done = 1;
127 			}
128 
129 			if (param->is_param) {
130 
131 				if (param->paramno == -1) {
132 					param->paramno = sqlite3_bind_parameter_index(S->stmt, ZSTR_VAL(param->name)) - 1;
133 				}
134 
135 				switch (PDO_PARAM_TYPE(param->param_type)) {
136 					case PDO_PARAM_STMT:
137 						return 0;
138 
139 					case PDO_PARAM_NULL:
140 						if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
141 							return 1;
142 						}
143 						pdo_sqlite_error_stmt(stmt);
144 						return 0;
145 
146 					case PDO_PARAM_INT:
147 					case PDO_PARAM_BOOL:
148 						if (Z_ISREF(param->parameter)) {
149 							parameter = Z_REFVAL(param->parameter);
150 						} else {
151 							parameter = &param->parameter;
152 						}
153 						if (Z_TYPE_P(parameter) == IS_NULL) {
154 							if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
155 								return 1;
156 							}
157 						} else {
158 							convert_to_long(parameter);
159 #if ZEND_LONG_MAX > 2147483647
160 							if (SQLITE_OK == sqlite3_bind_int64(S->stmt, param->paramno + 1, Z_LVAL_P(parameter))) {
161 								return 1;
162 							}
163 #else
164 							if (SQLITE_OK == sqlite3_bind_int(S->stmt, param->paramno + 1, Z_LVAL_P(parameter))) {
165 								return 1;
166 							}
167 #endif
168 						}
169 						pdo_sqlite_error_stmt(stmt);
170 						return 0;
171 
172 					case PDO_PARAM_LOB:
173 						if (Z_ISREF(param->parameter)) {
174 							parameter = Z_REFVAL(param->parameter);
175 						} else {
176 							parameter = &param->parameter;
177 						}
178 						if (Z_TYPE_P(parameter) == IS_RESOURCE) {
179 							php_stream *stm = NULL;
180 							php_stream_from_zval_no_verify(stm, parameter);
181 							if (stm) {
182 								zend_string *mem = php_stream_copy_to_mem(stm, PHP_STREAM_COPY_ALL, 0);
183 								zval_ptr_dtor(parameter);
184 								ZVAL_STR(parameter, mem ? mem : ZSTR_EMPTY_ALLOC());
185 							} else {
186 								pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a stream resource");
187 								return 0;
188 							}
189 						} else if (Z_TYPE_P(parameter) == IS_NULL) {
190 							if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
191 								return 1;
192 							}
193 							pdo_sqlite_error_stmt(stmt);
194 							return 0;
195 						} else {
196 							convert_to_string(parameter);
197 						}
198 
199 						if (SQLITE_OK == sqlite3_bind_blob(S->stmt, param->paramno + 1,
200 								Z_STRVAL_P(parameter),
201 								Z_STRLEN_P(parameter),
202 								SQLITE_STATIC)) {
203 							return 1;
204 						}
205 						return 0;
206 
207 					case PDO_PARAM_STR:
208 					default:
209 						if (Z_ISREF(param->parameter)) {
210 							parameter = Z_REFVAL(param->parameter);
211 						} else {
212 							parameter = &param->parameter;
213 						}
214 						if (Z_TYPE_P(parameter) == IS_NULL) {
215 							if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
216 								return 1;
217 							}
218 						} else {
219 							convert_to_string(parameter);
220 							if (SQLITE_OK == sqlite3_bind_text(S->stmt, param->paramno + 1,
221 									Z_STRVAL_P(parameter),
222 									Z_STRLEN_P(parameter),
223 									SQLITE_STATIC)) {
224 								return 1;
225 							}
226 						}
227 						pdo_sqlite_error_stmt(stmt);
228 						return 0;
229 				}
230 			}
231 			break;
232 
233 		default:
234 			;
235 	}
236 	return 1;
237 }
238 
pdo_sqlite_stmt_fetch(pdo_stmt_t * stmt,enum pdo_fetch_orientation ori,zend_long offset)239 static int pdo_sqlite_stmt_fetch(pdo_stmt_t *stmt,
240 	enum pdo_fetch_orientation ori, zend_long offset)
241 {
242 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
243 	int i;
244 	if (!S->stmt) {
245 		return 0;
246 	}
247 	if (S->pre_fetched) {
248 		S->pre_fetched = 0;
249 		return 1;
250 	}
251 	if (S->done) {
252 		return 0;
253 	}
254 	i = sqlite3_step(S->stmt);
255 	switch (i) {
256 		case SQLITE_ROW:
257 			return 1;
258 
259 		case SQLITE_DONE:
260 			S->done = 1;
261 			sqlite3_reset(S->stmt);
262 			return 0;
263 
264 		case SQLITE_ERROR:
265 			sqlite3_reset(S->stmt);
266 		default:
267 			pdo_sqlite_error_stmt(stmt);
268 			return 0;
269 	}
270 }
271 
pdo_sqlite_stmt_describe(pdo_stmt_t * stmt,int colno)272 static int pdo_sqlite_stmt_describe(pdo_stmt_t *stmt, int colno)
273 {
274 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
275 	const char *str;
276 
277 	if(colno >= sqlite3_column_count(S->stmt)) {
278 		/* error invalid column */
279 		pdo_sqlite_error_stmt(stmt);
280 		return 0;
281 	}
282 
283 	str = sqlite3_column_name(S->stmt, colno);
284 	stmt->columns[colno].name = zend_string_init(str, strlen(str), 0);
285 	stmt->columns[colno].maxlen = SIZE_MAX;
286 	stmt->columns[colno].precision = 0;
287 
288 	switch (sqlite3_column_type(S->stmt, colno)) {
289 		case SQLITE_INTEGER:
290 		case SQLITE_FLOAT:
291 		case SQLITE3_TEXT:
292 		case SQLITE_BLOB:
293 		case SQLITE_NULL:
294 		default:
295 			stmt->columns[colno].param_type = PDO_PARAM_STR;
296 			break;
297 	}
298 
299 	return 1;
300 }
301 
pdo_sqlite_stmt_get_col(pdo_stmt_t * stmt,int colno,char ** ptr,zend_ulong * len,int * caller_frees)302 static int pdo_sqlite_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong *len, int *caller_frees)
303 {
304 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
305 	if (!S->stmt) {
306 		return 0;
307 	}
308 	if(colno >= sqlite3_data_count(S->stmt)) {
309 		/* error invalid column */
310 		pdo_sqlite_error_stmt(stmt);
311 		return 0;
312 	}
313 	switch (sqlite3_column_type(S->stmt, colno)) {
314 		case SQLITE_NULL:
315 			*ptr = NULL;
316 			*len = 0;
317 			return 1;
318 
319 		case SQLITE_BLOB:
320 			*ptr = (char*)sqlite3_column_blob(S->stmt, colno);
321 			*len = sqlite3_column_bytes(S->stmt, colno);
322 			return 1;
323 
324 		default:
325 			*ptr = (char*)sqlite3_column_text(S->stmt, colno);
326 			*len = sqlite3_column_bytes(S->stmt, colno);
327 			return 1;
328 	}
329 }
330 
pdo_sqlite_stmt_col_meta(pdo_stmt_t * stmt,zend_long colno,zval * return_value)331 static int pdo_sqlite_stmt_col_meta(pdo_stmt_t *stmt, zend_long colno, zval *return_value)
332 {
333 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
334 	const char *str;
335 	zval flags;
336 
337 	if (!S->stmt) {
338 		return FAILURE;
339 	}
340 	if(colno >= sqlite3_column_count(S->stmt)) {
341 		/* error invalid column */
342 		pdo_sqlite_error_stmt(stmt);
343 		return FAILURE;
344 	}
345 
346 	array_init(return_value);
347 	array_init(&flags);
348 
349 	switch (sqlite3_column_type(S->stmt, colno)) {
350 		case SQLITE_NULL:
351 			add_assoc_string(return_value, "native_type", "null");
352 			break;
353 
354 		case SQLITE_FLOAT:
355 			add_assoc_string(return_value, "native_type", "double");
356 			break;
357 
358 		case SQLITE_BLOB:
359 			add_next_index_string(&flags, "blob");
360 		case SQLITE_TEXT:
361 			add_assoc_string(return_value, "native_type", "string");
362 			break;
363 
364 		case SQLITE_INTEGER:
365 			add_assoc_string(return_value, "native_type", "integer");
366 			break;
367 	}
368 
369 	str = sqlite3_column_decltype(S->stmt, colno);
370 	if (str) {
371 		add_assoc_string(return_value, "sqlite:decl_type", (char *)str);
372 	}
373 
374 #ifdef SQLITE_ENABLE_COLUMN_METADATA
375 	str = sqlite3_column_table_name(S->stmt, colno);
376 	if (str) {
377 		add_assoc_string(return_value, "table", (char *)str);
378 	}
379 #endif
380 
381 	add_assoc_zval(return_value, "flags", &flags);
382 
383 	return SUCCESS;
384 }
385 
pdo_sqlite_stmt_cursor_closer(pdo_stmt_t * stmt)386 static int pdo_sqlite_stmt_cursor_closer(pdo_stmt_t *stmt)
387 {
388 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
389 	sqlite3_reset(S->stmt);
390 	return 1;
391 }
392 
393 const struct pdo_stmt_methods sqlite_stmt_methods = {
394 	pdo_sqlite_stmt_dtor,
395 	pdo_sqlite_stmt_execute,
396 	pdo_sqlite_stmt_fetch,
397 	pdo_sqlite_stmt_describe,
398 	pdo_sqlite_stmt_get_col,
399 	pdo_sqlite_stmt_param_hook,
400 	NULL, /* set_attr */
401 	NULL, /* get_attr */
402 	pdo_sqlite_stmt_col_meta,
403 	NULL, /* next_rowset */
404 	pdo_sqlite_stmt_cursor_closer
405 };
406 
407 /*
408  * Local variables:
409  * tab-width: 4
410  * c-basic-offset: 4
411  * End:
412  * vim600: noet sw=4 ts=4 fdm=marker
413  * vim<600: noet sw=4 ts=4
414  */
415