xref: /PHP-8.0/ext/pdo_sqlite/sqlite_statement.c (revision bfa69d27)
1 /*
2   +----------------------------------------------------------------------+
3   | Copyright (c) The PHP Group                                          |
4   +----------------------------------------------------------------------+
5   | This source file is subject to version 3.01 of the PHP license,      |
6   | that is bundled with this package in the file LICENSE, and is        |
7   | available through the world-wide-web at the following url:           |
8   | http://www.php.net/license/3_01.txt                                  |
9   | If you did not receive a copy of the PHP license and are unable to   |
10   | obtain it through the world-wide-web, please send a note to          |
11   | license@php.net so we can mail you a copy immediately.               |
12   +----------------------------------------------------------------------+
13   | Author: Wez Furlong <wez@php.net>                                    |
14   +----------------------------------------------------------------------+
15 */
16 
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20 
21 #include "php.h"
22 #include "php_ini.h"
23 #include "ext/standard/info.h"
24 #include "pdo/php_pdo.h"
25 #include "pdo/php_pdo_driver.h"
26 #include "php_pdo_sqlite.h"
27 #include "php_pdo_sqlite_int.h"
28 
29 
pdo_sqlite_stmt_dtor(pdo_stmt_t * stmt)30 static int pdo_sqlite_stmt_dtor(pdo_stmt_t *stmt)
31 {
32 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
33 
34 	if (S->stmt) {
35 		sqlite3_finalize(S->stmt);
36 		S->stmt = NULL;
37 	}
38 	efree(S);
39 	return 1;
40 }
41 
pdo_sqlite_stmt_execute(pdo_stmt_t * stmt)42 static int pdo_sqlite_stmt_execute(pdo_stmt_t *stmt)
43 {
44 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
45 
46 	if (stmt->executed && !S->done) {
47 		sqlite3_reset(S->stmt);
48 	}
49 
50 	S->done = 0;
51 	switch (sqlite3_step(S->stmt)) {
52 		case SQLITE_ROW:
53 			S->pre_fetched = 1;
54 			php_pdo_stmt_set_column_count(stmt, sqlite3_data_count(S->stmt));
55 			return 1;
56 
57 		case SQLITE_DONE:
58 			php_pdo_stmt_set_column_count(stmt, sqlite3_column_count(S->stmt));
59 			stmt->row_count = sqlite3_changes(S->H->db);
60 			sqlite3_reset(S->stmt);
61 			S->done = 1;
62 			return 1;
63 
64 		case SQLITE_ERROR:
65 			sqlite3_reset(S->stmt);
66 		case SQLITE_MISUSE:
67 		case SQLITE_BUSY:
68 		default:
69 			pdo_sqlite_error_stmt(stmt);
70 			return 0;
71 	}
72 }
73 
pdo_sqlite_stmt_param_hook(pdo_stmt_t * stmt,struct pdo_bound_param_data * param,enum pdo_param_event event_type)74 static int pdo_sqlite_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param,
75 		enum pdo_param_event event_type)
76 {
77 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
78 	zval *parameter;
79 
80 	switch (event_type) {
81 		case PDO_PARAM_EVT_EXEC_PRE:
82 			if (stmt->executed && !S->done) {
83 				sqlite3_reset(S->stmt);
84 				S->done = 1;
85 			}
86 
87 			if (param->is_param) {
88 
89 				if (param->paramno == -1) {
90 					param->paramno = sqlite3_bind_parameter_index(S->stmt, ZSTR_VAL(param->name)) - 1;
91 				}
92 
93 				switch (PDO_PARAM_TYPE(param->param_type)) {
94 					case PDO_PARAM_STMT:
95 						return 0;
96 
97 					case PDO_PARAM_NULL:
98 						if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
99 							return 1;
100 						}
101 						pdo_sqlite_error_stmt(stmt);
102 						return 0;
103 
104 					case PDO_PARAM_INT:
105 					case PDO_PARAM_BOOL:
106 						if (Z_ISREF(param->parameter)) {
107 							parameter = Z_REFVAL(param->parameter);
108 						} else {
109 							parameter = &param->parameter;
110 						}
111 						if (Z_TYPE_P(parameter) == IS_NULL) {
112 							if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
113 								return 1;
114 							}
115 						} else {
116 							convert_to_long(parameter);
117 #if ZEND_LONG_MAX > 2147483647
118 							if (SQLITE_OK == sqlite3_bind_int64(S->stmt, param->paramno + 1, Z_LVAL_P(parameter))) {
119 								return 1;
120 							}
121 #else
122 							if (SQLITE_OK == sqlite3_bind_int(S->stmt, param->paramno + 1, Z_LVAL_P(parameter))) {
123 								return 1;
124 							}
125 #endif
126 						}
127 						pdo_sqlite_error_stmt(stmt);
128 						return 0;
129 
130 					case PDO_PARAM_LOB:
131 						if (Z_ISREF(param->parameter)) {
132 							parameter = Z_REFVAL(param->parameter);
133 						} else {
134 							parameter = &param->parameter;
135 						}
136 						if (Z_TYPE_P(parameter) == IS_RESOURCE) {
137 							php_stream *stm = NULL;
138 							php_stream_from_zval_no_verify(stm, parameter);
139 							if (stm) {
140 								zend_string *mem = php_stream_copy_to_mem(stm, PHP_STREAM_COPY_ALL, 0);
141 								zval_ptr_dtor(parameter);
142 								ZVAL_STR(parameter, mem ? mem : ZSTR_EMPTY_ALLOC());
143 							} else {
144 								pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a stream resource");
145 								return 0;
146 							}
147 						} else if (Z_TYPE_P(parameter) == IS_NULL) {
148 							if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
149 								return 1;
150 							}
151 							pdo_sqlite_error_stmt(stmt);
152 							return 0;
153 						} else {
154 							if (!try_convert_to_string(parameter)) {
155 								return 0;
156 							}
157 						}
158 
159 						if (SQLITE_OK == sqlite3_bind_blob(S->stmt, param->paramno + 1,
160 								Z_STRVAL_P(parameter),
161 								Z_STRLEN_P(parameter),
162 								SQLITE_STATIC)) {
163 							return 1;
164 						}
165 						return 0;
166 
167 					case PDO_PARAM_STR:
168 					default:
169 						if (Z_ISREF(param->parameter)) {
170 							parameter = Z_REFVAL(param->parameter);
171 						} else {
172 							parameter = &param->parameter;
173 						}
174 						if (Z_TYPE_P(parameter) == IS_NULL) {
175 							if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
176 								return 1;
177 							}
178 						} else {
179 							if (!try_convert_to_string(parameter)) {
180 								return 0;
181 							}
182 							if (SQLITE_OK == sqlite3_bind_text(S->stmt, param->paramno + 1,
183 									Z_STRVAL_P(parameter),
184 									Z_STRLEN_P(parameter),
185 									SQLITE_STATIC)) {
186 								return 1;
187 							}
188 						}
189 						pdo_sqlite_error_stmt(stmt);
190 						return 0;
191 				}
192 			}
193 			break;
194 
195 		default:
196 			;
197 	}
198 	return 1;
199 }
200 
pdo_sqlite_stmt_fetch(pdo_stmt_t * stmt,enum pdo_fetch_orientation ori,zend_long offset)201 static int pdo_sqlite_stmt_fetch(pdo_stmt_t *stmt,
202 	enum pdo_fetch_orientation ori, zend_long offset)
203 {
204 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
205 	int i;
206 	if (!S->stmt) {
207 		return 0;
208 	}
209 	if (S->pre_fetched) {
210 		S->pre_fetched = 0;
211 		return 1;
212 	}
213 	if (S->done) {
214 		return 0;
215 	}
216 	i = sqlite3_step(S->stmt);
217 	switch (i) {
218 		case SQLITE_ROW:
219 			return 1;
220 
221 		case SQLITE_DONE:
222 			S->done = 1;
223 			sqlite3_reset(S->stmt);
224 			return 0;
225 
226 		case SQLITE_ERROR:
227 			sqlite3_reset(S->stmt);
228 		default:
229 			pdo_sqlite_error_stmt(stmt);
230 			return 0;
231 	}
232 }
233 
pdo_sqlite_stmt_describe(pdo_stmt_t * stmt,int colno)234 static int pdo_sqlite_stmt_describe(pdo_stmt_t *stmt, int colno)
235 {
236 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
237 	const char *str;
238 
239 	if(colno >= sqlite3_column_count(S->stmt)) {
240 		/* error invalid column */
241 		pdo_sqlite_error_stmt(stmt);
242 		return 0;
243 	}
244 
245 	str = sqlite3_column_name(S->stmt, colno);
246 	stmt->columns[colno].name = zend_string_init(str, strlen(str), 0);
247 	stmt->columns[colno].maxlen = SIZE_MAX;
248 	stmt->columns[colno].precision = 0;
249 
250 	switch (sqlite3_column_type(S->stmt, colno)) {
251 		case SQLITE_INTEGER:
252 		case SQLITE_FLOAT:
253 		case SQLITE3_TEXT:
254 		case SQLITE_BLOB:
255 		case SQLITE_NULL:
256 		default:
257 			stmt->columns[colno].param_type = PDO_PARAM_STR;
258 			break;
259 	}
260 
261 	return 1;
262 }
263 
pdo_sqlite_stmt_get_col(pdo_stmt_t * stmt,int colno,char ** ptr,size_t * len,int * caller_frees)264 static int pdo_sqlite_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, size_t *len, int *caller_frees)
265 {
266 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
267 	if (!S->stmt) {
268 		return 0;
269 	}
270 	if(colno >= sqlite3_data_count(S->stmt)) {
271 		/* error invalid column */
272 		pdo_sqlite_error_stmt(stmt);
273 		return 0;
274 	}
275 	switch (sqlite3_column_type(S->stmt, colno)) {
276 		case SQLITE_NULL:
277 			*ptr = NULL;
278 			*len = 0;
279 			return 1;
280 
281 		case SQLITE_BLOB:
282 			*ptr = (char*)sqlite3_column_blob(S->stmt, colno);
283 			*len = sqlite3_column_bytes(S->stmt, colno);
284 			return 1;
285 
286 		default:
287 			*ptr = (char*)sqlite3_column_text(S->stmt, colno);
288 			*len = sqlite3_column_bytes(S->stmt, colno);
289 			return 1;
290 	}
291 }
292 
pdo_sqlite_stmt_col_meta(pdo_stmt_t * stmt,zend_long colno,zval * return_value)293 static int pdo_sqlite_stmt_col_meta(pdo_stmt_t *stmt, zend_long colno, zval *return_value)
294 {
295 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
296 	const char *str;
297 	zval flags;
298 
299 	if (!S->stmt) {
300 		return FAILURE;
301 	}
302 	if(colno >= sqlite3_column_count(S->stmt)) {
303 		/* error invalid column */
304 		pdo_sqlite_error_stmt(stmt);
305 		return FAILURE;
306 	}
307 
308 	array_init(return_value);
309 	array_init(&flags);
310 
311 	switch (sqlite3_column_type(S->stmt, colno)) {
312 		case SQLITE_NULL:
313 			add_assoc_string(return_value, "native_type", "null");
314 			break;
315 
316 		case SQLITE_FLOAT:
317 			add_assoc_string(return_value, "native_type", "double");
318 			break;
319 
320 		case SQLITE_BLOB:
321 			add_next_index_string(&flags, "blob");
322 		case SQLITE_TEXT:
323 			add_assoc_string(return_value, "native_type", "string");
324 			break;
325 
326 		case SQLITE_INTEGER:
327 			add_assoc_string(return_value, "native_type", "integer");
328 			break;
329 	}
330 
331 	str = sqlite3_column_decltype(S->stmt, colno);
332 	if (str) {
333 		add_assoc_string(return_value, "sqlite:decl_type", (char *)str);
334 	}
335 
336 #ifdef HAVE_SQLITE3_COLUMN_TABLE_NAME
337 	str = sqlite3_column_table_name(S->stmt, colno);
338 	if (str) {
339 		add_assoc_string(return_value, "table", (char *)str);
340 	}
341 #endif
342 
343 	add_assoc_zval(return_value, "flags", &flags);
344 
345 	return SUCCESS;
346 }
347 
pdo_sqlite_stmt_cursor_closer(pdo_stmt_t * stmt)348 static int pdo_sqlite_stmt_cursor_closer(pdo_stmt_t *stmt)
349 {
350 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
351 	sqlite3_reset(S->stmt);
352 	return 1;
353 }
354 
pdo_sqlite_stmt_get_attribute(pdo_stmt_t * stmt,zend_long attr,zval * val)355 static int pdo_sqlite_stmt_get_attribute(pdo_stmt_t *stmt, zend_long attr, zval *val)
356 {
357 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
358 
359 	switch (attr) {
360 		case PDO_SQLITE_ATTR_READONLY_STATEMENT:
361 			ZVAL_FALSE(val);
362 
363 #if SQLITE_VERSION_NUMBER >= 3007004
364 				if (sqlite3_stmt_readonly(S->stmt)) {
365 					ZVAL_TRUE(val);
366 				}
367 #endif
368 			break;
369 
370 		default:
371 			return 0;
372 	}
373 
374 	return 1;
375 }
376 
377 const struct pdo_stmt_methods sqlite_stmt_methods = {
378 	pdo_sqlite_stmt_dtor,
379 	pdo_sqlite_stmt_execute,
380 	pdo_sqlite_stmt_fetch,
381 	pdo_sqlite_stmt_describe,
382 	pdo_sqlite_stmt_get_col,
383 	pdo_sqlite_stmt_param_hook,
384 	NULL, /* set_attr */
385 	pdo_sqlite_stmt_get_attribute, /* get_attr */
386 	pdo_sqlite_stmt_col_meta,
387 	NULL, /* next_rowset */
388 	pdo_sqlite_stmt_cursor_closer
389 };
390