1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 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: sqlite_statement.c 280873 2009-05-20 15:05:36Z iliaa $ */
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 :
34 : static int pdo_sqlite_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC)
35 148 : {
36 148 : pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
37 :
38 148 : if (S->stmt) {
39 147 : sqlite3_finalize(S->stmt);
40 147 : S->stmt = NULL;
41 : }
42 148 : efree(S);
43 148 : return 1;
44 : }
45 :
46 : static int pdo_sqlite_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
47 217 : {
48 217 : pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
49 :
50 217 : if (stmt->executed && !S->done) {
51 0 : sqlite3_reset(S->stmt);
52 : }
53 :
54 217 : S->done = 0;
55 217 : switch (sqlite3_step(S->stmt)) {
56 : case SQLITE_ROW:
57 147 : S->pre_fetched = 1;
58 147 : stmt->column_count = sqlite3_data_count(S->stmt);
59 147 : return 1;
60 :
61 : case SQLITE_DONE:
62 69 : stmt->column_count = sqlite3_column_count(S->stmt);
63 69 : stmt->row_count = sqlite3_changes(S->H->db);
64 69 : sqlite3_reset(S->stmt);
65 69 : S->done = 1;
66 69 : return 1;
67 :
68 : case SQLITE_ERROR:
69 1 : sqlite3_reset(S->stmt);
70 : case SQLITE_MISUSE:
71 : case SQLITE_BUSY:
72 : default:
73 1 : pdo_sqlite_error_stmt(stmt);
74 1 : return 0;
75 : }
76 : }
77 :
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 1000 : {
81 1000 : pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
82 :
83 1000 : switch (event_type) {
84 : case PDO_PARAM_EVT_EXEC_PRE:
85 189 : if (stmt->executed && !S->done) {
86 4 : sqlite3_reset(S->stmt);
87 4 : S->done = 1;
88 : }
89 :
90 189 : if (param->is_param) {
91 :
92 156 : if (param->paramno == -1) {
93 45 : param->paramno = sqlite3_bind_parameter_index(S->stmt, param->name) - 1;
94 : }
95 :
96 156 : switch (PDO_PARAM_TYPE(param->param_type)) {
97 : case PDO_PARAM_STMT:
98 0 : return 0;
99 :
100 : case PDO_PARAM_NULL:
101 0 : if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
102 0 : return 1;
103 : }
104 0 : pdo_sqlite_error_stmt(stmt);
105 0 : return 0;
106 :
107 : case PDO_PARAM_INT:
108 : case PDO_PARAM_BOOL:
109 3 : if (Z_TYPE_P(param->parameter) == IS_NULL) {
110 0 : if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
111 0 : return 1;
112 : }
113 : } else {
114 3 : convert_to_long(param->parameter);
115 3 : if (SQLITE_OK == sqlite3_bind_int(S->stmt, param->paramno + 1, Z_LVAL_P(param->parameter))) {
116 3 : return 1;
117 : }
118 : }
119 0 : pdo_sqlite_error_stmt(stmt);
120 0 : return 0;
121 :
122 : case PDO_PARAM_LOB:
123 1 : if (Z_TYPE_P(param->parameter) == IS_RESOURCE) {
124 : php_stream *stm;
125 1 : php_stream_from_zval_no_verify(stm, ¶m->parameter);
126 1 : if (stm) {
127 1 : SEPARATE_ZVAL(¶m->parameter);
128 1 : Z_TYPE_P(param->parameter) = IS_STRING;
129 1 : 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 0 : pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a stream resource" TSRMLS_CC);
133 0 : return 0;
134 : }
135 0 : } else if (Z_TYPE_P(param->parameter) == IS_NULL) {
136 0 : if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
137 0 : return 1;
138 : }
139 0 : pdo_sqlite_error_stmt(stmt);
140 0 : return 0;
141 : } else {
142 0 : convert_to_string(param->parameter);
143 : }
144 :
145 1 : 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 1 : return 1;
150 : }
151 0 : pdo_sqlite_error_stmt(stmt);
152 0 : return 0;
153 :
154 : case PDO_PARAM_STR:
155 : default:
156 152 : if (Z_TYPE_P(param->parameter) == IS_NULL) {
157 2 : if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
158 2 : return 1;
159 : }
160 : } else {
161 150 : convert_to_string(param->parameter);
162 150 : 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 149 : return 1;
167 : }
168 : }
169 1 : pdo_sqlite_error_stmt(stmt);
170 1 : return 0;
171 : }
172 : }
173 : break;
174 :
175 : default:
176 : ;
177 : }
178 844 : return 1;
179 : }
180 :
181 : static int pdo_sqlite_stmt_fetch(pdo_stmt_t *stmt,
182 : enum pdo_fetch_orientation ori, long offset TSRMLS_DC)
183 350 : {
184 350 : pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
185 : int i;
186 350 : if (!S->stmt) {
187 0 : return 0;
188 : }
189 350 : if (S->pre_fetched) {
190 138 : S->pre_fetched = 0;
191 138 : return 1;
192 : }
193 212 : if (S->done) {
194 2 : return 0;
195 : }
196 210 : i = sqlite3_step(S->stmt);
197 210 : switch (i) {
198 : case SQLITE_ROW:
199 133 : return 1;
200 :
201 : case SQLITE_DONE:
202 77 : S->done = 1;
203 77 : sqlite3_reset(S->stmt);
204 77 : return 0;
205 :
206 : case SQLITE_ERROR:
207 0 : sqlite3_reset(S->stmt);
208 : default:
209 0 : pdo_sqlite_error_stmt(stmt);
210 0 : return 0;
211 : }
212 : }
213 :
214 : static int pdo_sqlite_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
215 177 : {
216 177 : pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
217 :
218 177 : if(colno >= sqlite3_column_count(S->stmt)) {
219 : /* error invalid column */
220 0 : pdo_sqlite_error_stmt(stmt);
221 0 : return 0;
222 : }
223 :
224 177 : stmt->columns[colno].name = estrdup(sqlite3_column_name(S->stmt, colno));
225 177 : stmt->columns[colno].namelen = strlen(stmt->columns[colno].name);
226 177 : stmt->columns[colno].maxlen = 0xffffffff;
227 177 : stmt->columns[colno].precision = 0;
228 :
229 177 : 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 177 : stmt->columns[colno].param_type = PDO_PARAM_STR;
237 : break;
238 : }
239 :
240 177 : return 1;
241 : }
242 :
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 520 : {
245 520 : pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
246 520 : if (!S->stmt) {
247 0 : return 0;
248 : }
249 520 : if(colno >= sqlite3_data_count(S->stmt)) {
250 : /* error invalid column */
251 0 : pdo_sqlite_error_stmt(stmt);
252 0 : return 0;
253 : }
254 520 : switch (sqlite3_column_type(S->stmt, colno)) {
255 : case SQLITE_NULL:
256 7 : *ptr = NULL;
257 7 : *len = 0;
258 7 : return 1;
259 :
260 : case SQLITE_BLOB:
261 1 : *ptr = (char*)sqlite3_column_blob(S->stmt, colno);
262 1 : *len = sqlite3_column_bytes(S->stmt, colno);
263 1 : return 1;
264 :
265 : default:
266 512 : *ptr = (char*)sqlite3_column_text(S->stmt, colno);
267 512 : *len = sqlite3_column_bytes(S->stmt, colno);
268 512 : return 1;
269 : }
270 : }
271 :
272 : static int pdo_sqlite_stmt_col_meta(pdo_stmt_t *stmt, long colno, zval *return_value TSRMLS_DC)
273 2 : {
274 2 : pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
275 : const char *str;
276 : zval *flags;
277 :
278 2 : if (!S->stmt) {
279 0 : return FAILURE;
280 : }
281 2 : if(colno >= sqlite3_data_count(S->stmt)) {
282 : /* error invalid column */
283 0 : pdo_sqlite_error_stmt(stmt);
284 0 : return FAILURE;
285 : }
286 :
287 2 : array_init(return_value);
288 2 : MAKE_STD_ZVAL(flags);
289 2 : array_init(flags);
290 :
291 2 : switch (sqlite3_column_type(S->stmt, colno)) {
292 : case SQLITE_NULL:
293 0 : add_assoc_string(return_value, "native_type", "null", 1);
294 0 : break;
295 :
296 : case SQLITE_FLOAT:
297 0 : add_assoc_string(return_value, "native_type", "double", 1);
298 0 : break;
299 :
300 : case SQLITE_BLOB:
301 0 : add_next_index_string(flags, "blob", 1);
302 : case SQLITE_TEXT:
303 2 : add_assoc_string(return_value, "native_type", "string", 1);
304 2 : break;
305 :
306 : case SQLITE_INTEGER:
307 0 : add_assoc_string(return_value, "native_type", "integer", 1);
308 : break;
309 : }
310 :
311 2 : str = sqlite3_column_decltype(S->stmt, colno);
312 2 : if (str) {
313 2 : add_assoc_string(return_value, "sqlite:decl_type", (char *)str, 1);
314 : }
315 :
316 : #ifdef SQLITE_ENABLE_COLUMN_METADATA
317 2 : str = sqlite3_column_table_name(S->stmt, colno);
318 2 : if (str) {
319 2 : add_assoc_string(return_value, "table", (char *)str, 1);
320 : }
321 : #endif
322 :
323 2 : add_assoc_zval(return_value, "flags", flags);
324 :
325 2 : return SUCCESS;
326 : }
327 :
328 : static int pdo_sqlite_stmt_cursor_closer(pdo_stmt_t *stmt TSRMLS_DC)
329 28 : {
330 28 : pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
331 28 : sqlite3_reset(S->stmt);
332 28 : 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 : */
|