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 280872 2009-05-20 15:03:16Z 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 133 : {
36 133 : pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
37 :
38 133 : if (S->stmt) {
39 132 : sqlite3_finalize(S->stmt);
40 132 : S->stmt = NULL;
41 : }
42 133 : efree(S);
43 133 : return 1;
44 : }
45 :
46 : static int pdo_sqlite_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
47 208 : {
48 208 : pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
49 :
50 208 : if (stmt->executed && !S->done) {
51 0 : sqlite3_reset(S->stmt);
52 : }
53 :
54 208 : S->done = 0;
55 208 : switch (sqlite3_step(S->stmt)) {
56 : case SQLITE_ROW:
57 138 : S->pre_fetched = 1;
58 138 : stmt->column_count = sqlite3_data_count(S->stmt);
59 138 : 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_LOB:
108 1 : if (Z_TYPE_P(param->parameter) == IS_RESOURCE) {
109 : php_stream *stm;
110 1 : php_stream_from_zval_no_verify(stm, ¶m->parameter);
111 1 : if (stm) {
112 1 : SEPARATE_ZVAL(¶m->parameter);
113 1 : Z_TYPE_P(param->parameter) = IS_STRING;
114 1 : Z_STRLEN_P(param->parameter) = php_stream_copy_to_mem(stm,
115 : &Z_STRVAL_P(param->parameter), PHP_STREAM_COPY_ALL, 0);
116 : } else {
117 0 : pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a stream resource" TSRMLS_CC);
118 0 : return 0;
119 : }
120 : }
121 : /* fall through */
122 :
123 : case PDO_PARAM_STR:
124 : default:
125 156 : if (Z_TYPE_P(param->parameter) == IS_NULL) {
126 2 : if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
127 2 : return 1;
128 : }
129 : } else {
130 154 : convert_to_string(param->parameter);
131 154 : if(SQLITE_OK == sqlite3_bind_text(S->stmt, param->paramno + 1,
132 : Z_STRVAL_P(param->parameter),
133 : Z_STRLEN_P(param->parameter),
134 : SQLITE_STATIC)) {
135 153 : return 1;
136 : }
137 : }
138 1 : pdo_sqlite_error_stmt(stmt);
139 1 : return 0;
140 : }
141 : }
142 : break;
143 :
144 : default:
145 : ;
146 : }
147 844 : return 1;
148 : }
149 :
150 : static int pdo_sqlite_stmt_fetch(pdo_stmt_t *stmt,
151 : enum pdo_fetch_orientation ori, long offset TSRMLS_DC)
152 341 : {
153 341 : pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
154 : int i;
155 341 : if (!S->stmt) {
156 0 : return 0;
157 : }
158 341 : if (S->pre_fetched) {
159 130 : S->pre_fetched = 0;
160 130 : return 1;
161 : }
162 211 : if (S->done) {
163 2 : return 0;
164 : }
165 209 : i = sqlite3_step(S->stmt);
166 209 : switch (i) {
167 : case SQLITE_ROW:
168 133 : return 1;
169 :
170 : case SQLITE_DONE:
171 76 : S->done = 1;
172 76 : sqlite3_reset(S->stmt);
173 76 : return 0;
174 :
175 : case SQLITE_ERROR:
176 0 : sqlite3_reset(S->stmt);
177 : default:
178 0 : pdo_sqlite_error_stmt(stmt);
179 0 : return 0;
180 : }
181 : }
182 :
183 : static int pdo_sqlite_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
184 167 : {
185 167 : pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
186 :
187 167 : if(colno >= sqlite3_column_count(S->stmt)) {
188 : /* error invalid column */
189 0 : pdo_sqlite_error_stmt(stmt);
190 0 : return 0;
191 : }
192 :
193 167 : stmt->columns[colno].name = estrdup(sqlite3_column_name(S->stmt, colno));
194 167 : stmt->columns[colno].namelen = strlen(stmt->columns[colno].name);
195 167 : stmt->columns[colno].maxlen = 0xffffffff;
196 167 : stmt->columns[colno].precision = 0;
197 :
198 167 : switch (sqlite3_column_type(S->stmt, colno)) {
199 : case SQLITE_INTEGER:
200 : case SQLITE_FLOAT:
201 : case SQLITE3_TEXT:
202 : case SQLITE_BLOB:
203 : case SQLITE_NULL:
204 : default:
205 167 : stmt->columns[colno].param_type = PDO_PARAM_STR;
206 : break;
207 : }
208 :
209 167 : return 1;
210 : }
211 :
212 : static int pdo_sqlite_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsigned long *len, int *caller_frees TSRMLS_DC)
213 519 : {
214 519 : pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
215 519 : if (!S->stmt) {
216 0 : return 0;
217 : }
218 519 : if(colno >= sqlite3_data_count(S->stmt)) {
219 : /* error invalid column */
220 0 : pdo_sqlite_error_stmt(stmt);
221 0 : return 0;
222 : }
223 519 : switch (sqlite3_column_type(S->stmt, colno)) {
224 : case SQLITE_NULL:
225 7 : *ptr = NULL;
226 7 : *len = 0;
227 7 : return 1;
228 :
229 : case SQLITE_BLOB:
230 0 : *ptr = (char*)sqlite3_column_blob(S->stmt, colno);
231 0 : *len = sqlite3_column_bytes(S->stmt, colno);
232 0 : return 1;
233 :
234 : default:
235 512 : *ptr = (char*)sqlite3_column_text(S->stmt, colno);
236 512 : *len = sqlite3_column_bytes(S->stmt, colno);
237 512 : return 1;
238 : }
239 : }
240 :
241 : static int pdo_sqlite_stmt_col_meta(pdo_stmt_t *stmt, long colno, zval *return_value TSRMLS_DC)
242 0 : {
243 0 : pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
244 : char *str;
245 : zval *flags;
246 :
247 0 : if (!S->stmt) {
248 0 : return FAILURE;
249 : }
250 0 : if(colno >= sqlite3_data_count(S->stmt)) {
251 : /* error invalid column */
252 0 : pdo_sqlite_error_stmt(stmt);
253 0 : return FAILURE;
254 : }
255 :
256 0 : array_init(return_value);
257 0 : MAKE_STD_ZVAL(flags);
258 0 : array_init(flags);
259 :
260 0 : switch (sqlite3_column_type(S->stmt, colno)) {
261 : case SQLITE_NULL:
262 0 : add_assoc_string(return_value, "native_type", "null", 1);
263 0 : break;
264 :
265 : case SQLITE_FLOAT:
266 0 : add_assoc_string(return_value, "native_type", "double", 1);
267 0 : break;
268 :
269 : case SQLITE_BLOB:
270 0 : add_next_index_string(flags, "blob", 1);
271 : case SQLITE_TEXT:
272 0 : add_assoc_string(return_value, "native_type", "string", 1);
273 0 : break;
274 :
275 : case SQLITE_INTEGER:
276 0 : add_assoc_string(return_value, "native_type", "integer", 1);
277 : break;
278 : }
279 :
280 0 : str = (char*)sqlite3_column_decltype(S->stmt, colno);
281 0 : if (str) {
282 0 : add_assoc_string(return_value, "sqlite:decl_type", str, 1);
283 : }
284 :
285 0 : add_assoc_zval(return_value, "flags", flags);
286 :
287 0 : return SUCCESS;
288 : }
289 :
290 : static int pdo_sqlite_stmt_cursor_closer(pdo_stmt_t *stmt TSRMLS_DC)
291 28 : {
292 28 : pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
293 28 : sqlite3_reset(S->stmt);
294 28 : return 1;
295 : }
296 :
297 : struct pdo_stmt_methods sqlite_stmt_methods = {
298 : pdo_sqlite_stmt_dtor,
299 : pdo_sqlite_stmt_execute,
300 : pdo_sqlite_stmt_fetch,
301 : pdo_sqlite_stmt_describe,
302 : pdo_sqlite_stmt_get_col,
303 : pdo_sqlite_stmt_param_hook,
304 : NULL, /* set_attr */
305 : NULL, /* get_attr */
306 : pdo_sqlite_stmt_col_meta,
307 : NULL, /* next_rowset */
308 : pdo_sqlite_stmt_cursor_closer
309 : };
310 :
311 : /*
312 : * Local variables:
313 : * tab-width: 4
314 : * c-basic-offset: 4
315 : * End:
316 : * vim600: noet sw=4 ts=4 fdm=marker
317 : * vim<600: noet sw=4 ts=4
318 : */
|