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