xref: /PHP-7.0/ext/pdo_sqlite/sqlite_statement.c (revision 478f119a)
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 7                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2017 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 
33 
pdo_sqlite_stmt_dtor(pdo_stmt_t * stmt)34 static int pdo_sqlite_stmt_dtor(pdo_stmt_t *stmt)
35 {
36 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
37 
38 	if (S->stmt) {
39 		sqlite3_finalize(S->stmt);
40 		S->stmt = NULL;
41 	}
42 	efree(S);
43 	return 1;
44 }
45 
pdo_sqlite_stmt_execute(pdo_stmt_t * stmt)46 static int pdo_sqlite_stmt_execute(pdo_stmt_t *stmt)
47 {
48 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
49 
50 	if (stmt->executed && !S->done) {
51 		sqlite3_reset(S->stmt);
52 	}
53 
54 	S->done = 0;
55 	switch (sqlite3_step(S->stmt)) {
56 		case SQLITE_ROW:
57 			S->pre_fetched = 1;
58 			stmt->column_count = sqlite3_data_count(S->stmt);
59 			return 1;
60 
61 		case SQLITE_DONE:
62 			stmt->column_count = sqlite3_column_count(S->stmt);
63 			stmt->row_count = sqlite3_changes(S->H->db);
64 			sqlite3_reset(S->stmt);
65 			S->done = 1;
66 			return 1;
67 
68 		case SQLITE_ERROR:
69 			sqlite3_reset(S->stmt);
70 		case SQLITE_MISUSE:
71 		case SQLITE_BUSY:
72 		default:
73 			pdo_sqlite_error_stmt(stmt);
74 			return 0;
75 	}
76 }
77 
pdo_sqlite_stmt_param_hook(pdo_stmt_t * stmt,struct pdo_bound_param_data * param,enum pdo_param_event event_type)78 static int pdo_sqlite_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param,
79 		enum pdo_param_event event_type)
80 {
81 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
82 	zval *parameter;
83 
84 	switch (event_type) {
85 		case PDO_PARAM_EVT_EXEC_PRE:
86 			if (stmt->executed && !S->done) {
87 				sqlite3_reset(S->stmt);
88 				S->done = 1;
89 			}
90 
91 			if (param->is_param) {
92 
93 				if (param->paramno == -1) {
94 					param->paramno = sqlite3_bind_parameter_index(S->stmt, ZSTR_VAL(param->name)) - 1;
95 				}
96 
97 				switch (PDO_PARAM_TYPE(param->param_type)) {
98 					case PDO_PARAM_STMT:
99 						return 0;
100 
101 					case PDO_PARAM_NULL:
102 						if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
103 							return 1;
104 						}
105 						pdo_sqlite_error_stmt(stmt);
106 						return 0;
107 
108 					case PDO_PARAM_INT:
109 					case PDO_PARAM_BOOL:
110 						if (Z_ISREF(param->parameter)) {
111 							parameter = Z_REFVAL(param->parameter);
112 						} else {
113 							parameter = &param->parameter;
114 						}
115 						if (Z_TYPE_P(parameter) == IS_NULL) {
116 							if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
117 								return 1;
118 							}
119 						} else {
120 							convert_to_long(parameter);
121 #if ZEND_LONG_MAX > 2147483647
122 							if (SQLITE_OK == sqlite3_bind_int64(S->stmt, param->paramno + 1, Z_LVAL_P(parameter))) {
123 								return 1;
124 							}
125 #else
126 							if (SQLITE_OK == sqlite3_bind_int(S->stmt, param->paramno + 1, Z_LVAL_P(parameter))) {
127 								return 1;
128 							}
129 #endif
130 						}
131 						pdo_sqlite_error_stmt(stmt);
132 						return 0;
133 
134 					case PDO_PARAM_LOB:
135 						if (Z_ISREF(param->parameter)) {
136 							parameter = Z_REFVAL(param->parameter);
137 						} else {
138 							parameter = &param->parameter;
139 						}
140 						if (Z_TYPE_P(parameter) == IS_RESOURCE) {
141 							php_stream *stm = NULL;
142 							php_stream_from_zval_no_verify(stm, parameter);
143 							if (stm) {
144 								zend_string *mem = php_stream_copy_to_mem(stm, PHP_STREAM_COPY_ALL, 0);
145 								zval_ptr_dtor(parameter);
146 								ZVAL_STR(parameter, mem ? mem : ZSTR_EMPTY_ALLOC());
147 							} else {
148 								pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a stream resource");
149 								return 0;
150 							}
151 						} else if (Z_TYPE_P(parameter) == IS_NULL) {
152 							if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
153 								return 1;
154 							}
155 							pdo_sqlite_error_stmt(stmt);
156 							return 0;
157 						} else {
158 							convert_to_string(parameter);
159 						}
160 
161 						if (SQLITE_OK == sqlite3_bind_blob(S->stmt, param->paramno + 1,
162 								Z_STRVAL_P(parameter),
163 								Z_STRLEN_P(parameter),
164 								SQLITE_STATIC)) {
165 							return 1;
166 						}
167 						return 0;
168 
169 					case PDO_PARAM_STR:
170 					default:
171 						if (Z_ISREF(param->parameter)) {
172 							parameter = Z_REFVAL(param->parameter);
173 						} else {
174 							parameter = &param->parameter;
175 						}
176 						if (Z_TYPE_P(parameter) == IS_NULL) {
177 							if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
178 								return 1;
179 							}
180 						} else {
181 							convert_to_string(parameter);
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 = 0xffffffff;
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,zend_ulong * len,int * caller_frees)264 static int pdo_sqlite_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong *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_data_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 SQLITE_ENABLE_COLUMN_METADATA
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 
355 struct pdo_stmt_methods sqlite_stmt_methods = {
356 	pdo_sqlite_stmt_dtor,
357 	pdo_sqlite_stmt_execute,
358 	pdo_sqlite_stmt_fetch,
359 	pdo_sqlite_stmt_describe,
360 	pdo_sqlite_stmt_get_col,
361 	pdo_sqlite_stmt_param_hook,
362 	NULL, /* set_attr */
363 	NULL, /* get_attr */
364 	pdo_sqlite_stmt_col_meta,
365 	NULL, /* next_rowset */
366 	pdo_sqlite_stmt_cursor_closer
367 };
368 
369 /*
370  * Local variables:
371  * tab-width: 4
372  * c-basic-offset: 4
373  * End:
374  * vim600: noet sw=4 ts=4 fdm=marker
375  * vim<600: noet sw=4 ts=4
376  */
377