xref: /PHP-5.5/ext/pdo_sqlite/sqlite_statement.c (revision 73c1be26)
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2015 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 TSRMLS_DC)34 static int pdo_sqlite_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC)
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 TSRMLS_DC)46 static int pdo_sqlite_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
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 TSRMLS_DC)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 TSRMLS_DC)
80 {
81 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
82 
83 	switch (event_type) {
84 		case PDO_PARAM_EVT_EXEC_PRE:
85 			if (stmt->executed && !S->done) {
86 				sqlite3_reset(S->stmt);
87 				S->done = 1;
88 			}
89 
90 			if (param->is_param) {
91 
92 				if (param->paramno == -1) {
93 					param->paramno = sqlite3_bind_parameter_index(S->stmt, param->name) - 1;
94 				}
95 
96 				switch (PDO_PARAM_TYPE(param->param_type)) {
97 					case PDO_PARAM_STMT:
98 						return 0;
99 
100 					case PDO_PARAM_NULL:
101 						if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
102 							return 1;
103 						}
104 						pdo_sqlite_error_stmt(stmt);
105 						return 0;
106 
107 					case PDO_PARAM_INT:
108 					case PDO_PARAM_BOOL:
109 						if (Z_TYPE_P(param->parameter) == IS_NULL) {
110 							if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
111 								return 1;
112 							}
113 						} else {
114 							convert_to_long(param->parameter);
115 #if LONG_MAX > 2147483647
116 							if (SQLITE_OK == sqlite3_bind_int64(S->stmt, param->paramno + 1, Z_LVAL_P(param->parameter))) {
117 								return 1;
118 							}
119 #else
120 							if (SQLITE_OK == sqlite3_bind_int(S->stmt, param->paramno + 1, Z_LVAL_P(param->parameter))) {
121 								return 1;
122 							}
123 #endif
124 						}
125 						pdo_sqlite_error_stmt(stmt);
126 						return 0;
127 
128 					case PDO_PARAM_LOB:
129 						if (Z_TYPE_P(param->parameter) == IS_RESOURCE) {
130 							php_stream *stm;
131 							php_stream_from_zval_no_verify(stm, &param->parameter);
132 							if (stm) {
133 								SEPARATE_ZVAL(&param->parameter);
134 								Z_TYPE_P(param->parameter) = IS_STRING;
135 								Z_STRLEN_P(param->parameter) = php_stream_copy_to_mem(stm,
136 									&Z_STRVAL_P(param->parameter), PHP_STREAM_COPY_ALL, 0);
137 							} else {
138 								pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a stream resource" TSRMLS_CC);
139 								return 0;
140 							}
141 						} else if (Z_TYPE_P(param->parameter) == IS_NULL) {
142 							if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
143 								return 1;
144 							}
145 							pdo_sqlite_error_stmt(stmt);
146 							return 0;
147 						} else {
148 							convert_to_string(param->parameter);
149 						}
150 
151 						if (SQLITE_OK == sqlite3_bind_blob(S->stmt, param->paramno + 1,
152 								Z_STRVAL_P(param->parameter),
153 								Z_STRLEN_P(param->parameter),
154 								SQLITE_STATIC)) {
155 							return 1;
156 						}
157 						pdo_sqlite_error_stmt(stmt);
158 						return 0;
159 
160 					case PDO_PARAM_STR:
161 					default:
162 						if (Z_TYPE_P(param->parameter) == IS_NULL) {
163 							if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
164 								return 1;
165 							}
166 						} else {
167 							convert_to_string(param->parameter);
168 							if(SQLITE_OK == sqlite3_bind_text(S->stmt, param->paramno + 1,
169 									Z_STRVAL_P(param->parameter),
170 									Z_STRLEN_P(param->parameter),
171 									SQLITE_STATIC)) {
172 								return 1;
173 							}
174 						}
175 						pdo_sqlite_error_stmt(stmt);
176 						return 0;
177 				}
178 			}
179 			break;
180 
181 		default:
182 			;
183 	}
184 	return 1;
185 }
186 
pdo_sqlite_stmt_fetch(pdo_stmt_t * stmt,enum pdo_fetch_orientation ori,long offset TSRMLS_DC)187 static int pdo_sqlite_stmt_fetch(pdo_stmt_t *stmt,
188 	enum pdo_fetch_orientation ori, long offset TSRMLS_DC)
189 {
190 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
191 	int i;
192 	if (!S->stmt) {
193 		return 0;
194 	}
195 	if (S->pre_fetched) {
196 		S->pre_fetched = 0;
197 		return 1;
198 	}
199 	if (S->done) {
200 		return 0;
201 	}
202 	i = sqlite3_step(S->stmt);
203 	switch (i) {
204 		case SQLITE_ROW:
205 			return 1;
206 
207 		case SQLITE_DONE:
208 			S->done = 1;
209 			sqlite3_reset(S->stmt);
210 			return 0;
211 
212 		case SQLITE_ERROR:
213 			sqlite3_reset(S->stmt);
214 		default:
215 			pdo_sqlite_error_stmt(stmt);
216 			return 0;
217 	}
218 }
219 
pdo_sqlite_stmt_describe(pdo_stmt_t * stmt,int colno TSRMLS_DC)220 static int pdo_sqlite_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
221 {
222 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
223 
224 	if(colno >= sqlite3_column_count(S->stmt)) {
225 		/* error invalid column */
226 		pdo_sqlite_error_stmt(stmt);
227 		return 0;
228 	}
229 
230 	stmt->columns[colno].name = estrdup(sqlite3_column_name(S->stmt, colno));
231 	stmt->columns[colno].namelen = strlen(stmt->columns[colno].name);
232 	stmt->columns[colno].maxlen = 0xffffffff;
233 	stmt->columns[colno].precision = 0;
234 
235 	switch (sqlite3_column_type(S->stmt, colno)) {
236 		case SQLITE_INTEGER:
237 		case SQLITE_FLOAT:
238 		case SQLITE3_TEXT:
239 		case SQLITE_BLOB:
240 		case SQLITE_NULL:
241 		default:
242 			stmt->columns[colno].param_type = PDO_PARAM_STR;
243 			break;
244 	}
245 
246 	return 1;
247 }
248 
pdo_sqlite_stmt_get_col(pdo_stmt_t * stmt,int colno,char ** ptr,unsigned long * len,int * caller_frees TSRMLS_DC)249 static int pdo_sqlite_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsigned long *len, int *caller_frees TSRMLS_DC)
250 {
251 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
252 	if (!S->stmt) {
253 		return 0;
254 	}
255 	if(colno >= sqlite3_data_count(S->stmt)) {
256 		/* error invalid column */
257 		pdo_sqlite_error_stmt(stmt);
258 		return 0;
259 	}
260 	switch (sqlite3_column_type(S->stmt, colno)) {
261 		case SQLITE_NULL:
262 			*ptr = NULL;
263 			*len = 0;
264 			return 1;
265 
266 		case SQLITE_BLOB:
267 			*ptr = (char*)sqlite3_column_blob(S->stmt, colno);
268 			*len = sqlite3_column_bytes(S->stmt, colno);
269 			return 1;
270 
271 		default:
272 			*ptr = (char*)sqlite3_column_text(S->stmt, colno);
273 			*len = sqlite3_column_bytes(S->stmt, colno);
274 			return 1;
275 	}
276 }
277 
pdo_sqlite_stmt_col_meta(pdo_stmt_t * stmt,long colno,zval * return_value TSRMLS_DC)278 static int pdo_sqlite_stmt_col_meta(pdo_stmt_t *stmt, long colno, zval *return_value TSRMLS_DC)
279 {
280 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
281 	const char *str;
282 	zval *flags;
283 
284 	if (!S->stmt) {
285 		return FAILURE;
286 	}
287 	if(colno >= sqlite3_data_count(S->stmt)) {
288 		/* error invalid column */
289 		pdo_sqlite_error_stmt(stmt);
290 		return FAILURE;
291 	}
292 
293 	array_init(return_value);
294 	MAKE_STD_ZVAL(flags);
295 	array_init(flags);
296 
297 	switch (sqlite3_column_type(S->stmt, colno)) {
298 		case SQLITE_NULL:
299 			add_assoc_string(return_value, "native_type", "null", 1);
300 			break;
301 
302 		case SQLITE_FLOAT:
303 			add_assoc_string(return_value, "native_type", "double", 1);
304 			break;
305 
306 		case SQLITE_BLOB:
307 			add_next_index_string(flags, "blob", 1);
308 		case SQLITE_TEXT:
309 			add_assoc_string(return_value, "native_type", "string", 1);
310 			break;
311 
312 		case SQLITE_INTEGER:
313 			add_assoc_string(return_value, "native_type", "integer", 1);
314 			break;
315 	}
316 
317 	str = sqlite3_column_decltype(S->stmt, colno);
318 	if (str) {
319 		add_assoc_string(return_value, "sqlite:decl_type", (char *)str, 1);
320 	}
321 
322 #ifdef SQLITE_ENABLE_COLUMN_METADATA
323 	str = sqlite3_column_table_name(S->stmt, colno);
324 	if (str) {
325 		add_assoc_string(return_value, "table", (char *)str, 1);
326 	}
327 #endif
328 
329 	add_assoc_zval(return_value, "flags", flags);
330 
331 	return SUCCESS;
332 }
333 
pdo_sqlite_stmt_cursor_closer(pdo_stmt_t * stmt TSRMLS_DC)334 static int pdo_sqlite_stmt_cursor_closer(pdo_stmt_t *stmt TSRMLS_DC)
335 {
336 	pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
337 	sqlite3_reset(S->stmt);
338 	return 1;
339 }
340 
341 struct pdo_stmt_methods sqlite_stmt_methods = {
342 	pdo_sqlite_stmt_dtor,
343 	pdo_sqlite_stmt_execute,
344 	pdo_sqlite_stmt_fetch,
345 	pdo_sqlite_stmt_describe,
346 	pdo_sqlite_stmt_get_col,
347 	pdo_sqlite_stmt_param_hook,
348 	NULL, /* set_attr */
349 	NULL, /* get_attr */
350 	pdo_sqlite_stmt_col_meta,
351 	NULL, /* next_rowset */
352 	pdo_sqlite_stmt_cursor_closer
353 };
354 
355 /*
356  * Local variables:
357  * tab-width: 4
358  * c-basic-offset: 4
359  * End:
360  * vim600: noet sw=4 ts=4 fdm=marker
361  * vim<600: noet sw=4 ts=4
362  */
363