1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | http://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Wez Furlong <wez@php.net> |
14 +----------------------------------------------------------------------+
15 */
16
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20
21 #include "php.h"
22 #include "php_ini.h"
23 #include "ext/standard/info.h"
24 #include "pdo/php_pdo.h"
25 #include "pdo/php_pdo_driver.h"
26 #include "php_pdo_sqlite.h"
27 #include "php_pdo_sqlite_int.h"
28
29
pdo_sqlite_stmt_dtor(pdo_stmt_t * stmt)30 static int pdo_sqlite_stmt_dtor(pdo_stmt_t *stmt)
31 {
32 pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
33
34 if (S->stmt) {
35 sqlite3_finalize(S->stmt);
36 S->stmt = NULL;
37 }
38 efree(S);
39 return 1;
40 }
41
pdo_sqlite_stmt_execute(pdo_stmt_t * stmt)42 static int pdo_sqlite_stmt_execute(pdo_stmt_t *stmt)
43 {
44 pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
45
46 if (stmt->executed && !S->done) {
47 sqlite3_reset(S->stmt);
48 }
49
50 S->done = 0;
51 switch (sqlite3_step(S->stmt)) {
52 case SQLITE_ROW:
53 S->pre_fetched = 1;
54 php_pdo_stmt_set_column_count(stmt, sqlite3_data_count(S->stmt));
55 return 1;
56
57 case SQLITE_DONE:
58 php_pdo_stmt_set_column_count(stmt, sqlite3_column_count(S->stmt));
59 stmt->row_count = sqlite3_changes(S->H->db);
60 sqlite3_reset(S->stmt);
61 S->done = 1;
62 return 1;
63
64 case SQLITE_ERROR:
65 sqlite3_reset(S->stmt);
66 case SQLITE_MISUSE:
67 case SQLITE_BUSY:
68 default:
69 pdo_sqlite_error_stmt(stmt);
70 return 0;
71 }
72 }
73
pdo_sqlite_stmt_param_hook(pdo_stmt_t * stmt,struct pdo_bound_param_data * param,enum pdo_param_event event_type)74 static int pdo_sqlite_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param,
75 enum pdo_param_event event_type)
76 {
77 pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
78 zval *parameter;
79
80 switch (event_type) {
81 case PDO_PARAM_EVT_EXEC_PRE:
82 if (stmt->executed && !S->done) {
83 sqlite3_reset(S->stmt);
84 S->done = 1;
85 }
86
87 if (param->is_param) {
88
89 if (param->paramno == -1) {
90 param->paramno = sqlite3_bind_parameter_index(S->stmt, ZSTR_VAL(param->name)) - 1;
91 }
92
93 switch (PDO_PARAM_TYPE(param->param_type)) {
94 case PDO_PARAM_STMT:
95 return 0;
96
97 case PDO_PARAM_NULL:
98 if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
99 return 1;
100 }
101 pdo_sqlite_error_stmt(stmt);
102 return 0;
103
104 case PDO_PARAM_INT:
105 case PDO_PARAM_BOOL:
106 if (Z_ISREF(param->parameter)) {
107 parameter = Z_REFVAL(param->parameter);
108 } else {
109 parameter = ¶m->parameter;
110 }
111 if (Z_TYPE_P(parameter) == IS_NULL) {
112 if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
113 return 1;
114 }
115 } else {
116 convert_to_long(parameter);
117 #if ZEND_LONG_MAX > 2147483647
118 if (SQLITE_OK == sqlite3_bind_int64(S->stmt, param->paramno + 1, Z_LVAL_P(parameter))) {
119 return 1;
120 }
121 #else
122 if (SQLITE_OK == sqlite3_bind_int(S->stmt, param->paramno + 1, Z_LVAL_P(parameter))) {
123 return 1;
124 }
125 #endif
126 }
127 pdo_sqlite_error_stmt(stmt);
128 return 0;
129
130 case PDO_PARAM_LOB:
131 if (Z_ISREF(param->parameter)) {
132 parameter = Z_REFVAL(param->parameter);
133 } else {
134 parameter = ¶m->parameter;
135 }
136 if (Z_TYPE_P(parameter) == IS_RESOURCE) {
137 php_stream *stm = NULL;
138 php_stream_from_zval_no_verify(stm, parameter);
139 if (stm) {
140 zend_string *mem = php_stream_copy_to_mem(stm, PHP_STREAM_COPY_ALL, 0);
141 zval_ptr_dtor(parameter);
142 ZVAL_STR(parameter, mem ? mem : ZSTR_EMPTY_ALLOC());
143 } else {
144 pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a stream resource");
145 return 0;
146 }
147 } else if (Z_TYPE_P(parameter) == IS_NULL) {
148 if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
149 return 1;
150 }
151 pdo_sqlite_error_stmt(stmt);
152 return 0;
153 } else {
154 if (!try_convert_to_string(parameter)) {
155 return 0;
156 }
157 }
158
159 if (SQLITE_OK == sqlite3_bind_blob(S->stmt, param->paramno + 1,
160 Z_STRVAL_P(parameter),
161 Z_STRLEN_P(parameter),
162 SQLITE_STATIC)) {
163 return 1;
164 }
165 return 0;
166
167 case PDO_PARAM_STR:
168 default:
169 if (Z_ISREF(param->parameter)) {
170 parameter = Z_REFVAL(param->parameter);
171 } else {
172 parameter = ¶m->parameter;
173 }
174 if (Z_TYPE_P(parameter) == IS_NULL) {
175 if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
176 return 1;
177 }
178 } else {
179 if (!try_convert_to_string(parameter)) {
180 return 0;
181 }
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 = SIZE_MAX;
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,size_t * len,int * caller_frees)264 static int pdo_sqlite_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, size_t *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_column_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 HAVE_SQLITE3_COLUMN_TABLE_NAME
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
pdo_sqlite_stmt_get_attribute(pdo_stmt_t * stmt,zend_long attr,zval * val)355 static int pdo_sqlite_stmt_get_attribute(pdo_stmt_t *stmt, zend_long attr, zval *val)
356 {
357 pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
358
359 switch (attr) {
360 case PDO_SQLITE_ATTR_READONLY_STATEMENT:
361 ZVAL_FALSE(val);
362
363 #if SQLITE_VERSION_NUMBER >= 3007004
364 if (sqlite3_stmt_readonly(S->stmt)) {
365 ZVAL_TRUE(val);
366 }
367 #endif
368 break;
369
370 default:
371 return 0;
372 }
373
374 return 1;
375 }
376
377 const struct pdo_stmt_methods sqlite_stmt_methods = {
378 pdo_sqlite_stmt_dtor,
379 pdo_sqlite_stmt_execute,
380 pdo_sqlite_stmt_fetch,
381 pdo_sqlite_stmt_describe,
382 pdo_sqlite_stmt_get_col,
383 pdo_sqlite_stmt_param_hook,
384 NULL, /* set_attr */
385 pdo_sqlite_stmt_get_attribute, /* get_attr */
386 pdo_sqlite_stmt_col_meta,
387 NULL, /* next_rowset */
388 pdo_sqlite_stmt_cursor_closer
389 };
390