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 | https://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 "ext/pdo/php_pdo.h"
25 #include "ext/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 ZEND_FALLTHROUGH;
67 case SQLITE_MISUSE:
68 case SQLITE_BUSY:
69 default:
70 pdo_sqlite_error_stmt(stmt);
71 return 0;
72 }
73 }
74
pdo_sqlite_stmt_param_hook(pdo_stmt_t * stmt,struct pdo_bound_param_data * param,enum pdo_param_event event_type)75 static int pdo_sqlite_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param,
76 enum pdo_param_event event_type)
77 {
78 pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
79 zval *parameter;
80
81 switch (event_type) {
82 case PDO_PARAM_EVT_EXEC_PRE:
83 if (stmt->executed && !S->done) {
84 sqlite3_reset(S->stmt);
85 S->done = 1;
86 }
87
88 if (param->is_param) {
89
90 if (param->paramno == -1) {
91 param->paramno = sqlite3_bind_parameter_index(S->stmt, ZSTR_VAL(param->name)) - 1;
92 }
93
94 switch (PDO_PARAM_TYPE(param->param_type)) {
95 case PDO_PARAM_STMT:
96 return 0;
97
98 case PDO_PARAM_NULL:
99 if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
100 return 1;
101 }
102 pdo_sqlite_error_stmt(stmt);
103 return 0;
104
105 case PDO_PARAM_INT:
106 case PDO_PARAM_BOOL:
107 if (Z_ISREF(param->parameter)) {
108 parameter = Z_REFVAL(param->parameter);
109 } else {
110 parameter = ¶m->parameter;
111 }
112 if (Z_TYPE_P(parameter) == IS_NULL) {
113 if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
114 return 1;
115 }
116 } else {
117 convert_to_long(parameter);
118 #if ZEND_LONG_MAX > 2147483647
119 if (SQLITE_OK == sqlite3_bind_int64(S->stmt, param->paramno + 1, Z_LVAL_P(parameter))) {
120 return 1;
121 }
122 #else
123 if (SQLITE_OK == sqlite3_bind_int(S->stmt, param->paramno + 1, Z_LVAL_P(parameter))) {
124 return 1;
125 }
126 #endif
127 }
128 pdo_sqlite_error_stmt(stmt);
129 return 0;
130
131 case PDO_PARAM_LOB:
132 if (Z_ISREF(param->parameter)) {
133 parameter = Z_REFVAL(param->parameter);
134 } else {
135 parameter = ¶m->parameter;
136 }
137 if (Z_TYPE_P(parameter) == IS_RESOURCE) {
138 php_stream *stm = NULL;
139 php_stream_from_zval_no_verify(stm, parameter);
140 if (stm) {
141 zend_string *mem = php_stream_copy_to_mem(stm, PHP_STREAM_COPY_ALL, 0);
142 zval_ptr_dtor(parameter);
143 ZVAL_STR(parameter, mem ? mem : ZSTR_EMPTY_ALLOC());
144 } else {
145 pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a stream resource");
146 return 0;
147 }
148 } else if (Z_TYPE_P(parameter) == IS_NULL) {
149 if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
150 return 1;
151 }
152 pdo_sqlite_error_stmt(stmt);
153 return 0;
154 } else {
155 if (!try_convert_to_string(parameter)) {
156 return 0;
157 }
158 }
159
160 if (SQLITE_OK == sqlite3_bind_blob(S->stmt, param->paramno + 1,
161 Z_STRVAL_P(parameter),
162 Z_STRLEN_P(parameter),
163 SQLITE_STATIC)) {
164 return 1;
165 }
166 return 0;
167
168 case PDO_PARAM_STR:
169 default:
170 if (Z_ISREF(param->parameter)) {
171 parameter = Z_REFVAL(param->parameter);
172 } else {
173 parameter = ¶m->parameter;
174 }
175 if (Z_TYPE_P(parameter) == IS_NULL) {
176 if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
177 return 1;
178 }
179 } else {
180 if (!try_convert_to_string(parameter)) {
181 return 0;
182 }
183 if (SQLITE_OK == sqlite3_bind_text(S->stmt, param->paramno + 1,
184 Z_STRVAL_P(parameter),
185 Z_STRLEN_P(parameter),
186 SQLITE_STATIC)) {
187 return 1;
188 }
189 }
190 pdo_sqlite_error_stmt(stmt);
191 return 0;
192 }
193 }
194 break;
195
196 default:
197 ;
198 }
199 return 1;
200 }
201
pdo_sqlite_stmt_fetch(pdo_stmt_t * stmt,enum pdo_fetch_orientation ori,zend_long offset)202 static int pdo_sqlite_stmt_fetch(pdo_stmt_t *stmt,
203 enum pdo_fetch_orientation ori, zend_long offset)
204 {
205 pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
206 int i;
207 if (!S->stmt) {
208 return 0;
209 }
210 if (S->pre_fetched) {
211 S->pre_fetched = 0;
212 return 1;
213 }
214 if (S->done) {
215 return 0;
216 }
217 i = sqlite3_step(S->stmt);
218 switch (i) {
219 case SQLITE_ROW:
220 return 1;
221
222 case SQLITE_DONE:
223 S->done = 1;
224 sqlite3_reset(S->stmt);
225 return 0;
226
227 case SQLITE_ERROR:
228 sqlite3_reset(S->stmt);
229 ZEND_FALLTHROUGH;
230 default:
231 pdo_sqlite_error_stmt(stmt);
232 return 0;
233 }
234 }
235
pdo_sqlite_stmt_describe(pdo_stmt_t * stmt,int colno)236 static int pdo_sqlite_stmt_describe(pdo_stmt_t *stmt, int colno)
237 {
238 pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
239 const char *str;
240
241 if(colno >= sqlite3_column_count(S->stmt)) {
242 /* error invalid column */
243 pdo_sqlite_error_stmt(stmt);
244 return 0;
245 }
246
247 str = sqlite3_column_name(S->stmt, colno);
248 stmt->columns[colno].name = zend_string_init(str, strlen(str), 0);
249 stmt->columns[colno].maxlen = SIZE_MAX;
250 stmt->columns[colno].precision = 0;
251
252 return 1;
253 }
254
pdo_sqlite_stmt_get_col(pdo_stmt_t * stmt,int colno,zval * result,enum pdo_param_type * type)255 static int pdo_sqlite_stmt_get_col(
256 pdo_stmt_t *stmt, int colno, zval *result, enum pdo_param_type *type)
257 {
258 pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
259 if (!S->stmt) {
260 return 0;
261 }
262 if(colno >= sqlite3_data_count(S->stmt)) {
263 /* error invalid column */
264 pdo_sqlite_error_stmt(stmt);
265 return 0;
266 }
267 switch (sqlite3_column_type(S->stmt, colno)) {
268 case SQLITE_NULL:
269 ZVAL_NULL(result);
270 return 1;
271
272 case SQLITE_INTEGER: {
273 int64_t i = sqlite3_column_int64(S->stmt, colno);
274 #if SIZEOF_ZEND_LONG < 8
275 if (i > ZEND_LONG_MAX || i < ZEND_LONG_MIN) {
276 ZVAL_STRINGL(result,
277 (char *) sqlite3_column_text(S->stmt, colno),
278 sqlite3_column_bytes(S->stmt, colno));
279 return 1;
280 }
281 #endif
282 ZVAL_LONG(result, i);
283 return 1;
284 }
285
286 case SQLITE_FLOAT:
287 ZVAL_DOUBLE(result, sqlite3_column_double(S->stmt, colno));
288 return 1;
289
290 case SQLITE_BLOB:
291 ZVAL_STRINGL_FAST(result,
292 sqlite3_column_blob(S->stmt, colno), sqlite3_column_bytes(S->stmt, colno));
293 return 1;
294
295 default:
296 ZVAL_STRINGL_FAST(result,
297 (char *) sqlite3_column_text(S->stmt, colno), sqlite3_column_bytes(S->stmt, colno));
298 return 1;
299 }
300 }
301
pdo_sqlite_stmt_col_meta(pdo_stmt_t * stmt,zend_long colno,zval * return_value)302 static int pdo_sqlite_stmt_col_meta(pdo_stmt_t *stmt, zend_long colno, zval *return_value)
303 {
304 pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
305 const char *str;
306 zval flags;
307
308 if (!S->stmt) {
309 return FAILURE;
310 }
311 if(colno >= sqlite3_column_count(S->stmt)) {
312 /* error invalid column */
313 pdo_sqlite_error_stmt(stmt);
314 return FAILURE;
315 }
316
317 array_init(return_value);
318 array_init(&flags);
319
320 switch (sqlite3_column_type(S->stmt, colno)) {
321 case SQLITE_NULL:
322 add_assoc_str(return_value, "native_type", ZSTR_KNOWN(ZEND_STR_NULL_LOWERCASE));
323 add_assoc_long(return_value, "pdo_type", PDO_PARAM_NULL);
324 break;
325
326 case SQLITE_FLOAT:
327 add_assoc_str(return_value, "native_type", ZSTR_KNOWN(ZEND_STR_DOUBLE));
328 add_assoc_long(return_value, "pdo_type", PDO_PARAM_STR);
329 break;
330
331 case SQLITE_BLOB:
332 add_next_index_string(&flags, "blob");
333 /* TODO Check this is correct */
334 ZEND_FALLTHROUGH;
335 case SQLITE_TEXT:
336 add_assoc_str(return_value, "native_type", ZSTR_KNOWN(ZEND_STR_STRING));
337 add_assoc_long(return_value, "pdo_type", PDO_PARAM_STR);
338 break;
339
340 case SQLITE_INTEGER:
341 add_assoc_str(return_value, "native_type", ZSTR_KNOWN(ZEND_STR_INTEGER));
342 add_assoc_long(return_value, "pdo_type", PDO_PARAM_INT);
343 break;
344 }
345
346 str = sqlite3_column_decltype(S->stmt, colno);
347 if (str) {
348 add_assoc_string(return_value, "sqlite:decl_type", (char *)str);
349 }
350
351 #ifdef HAVE_SQLITE3_COLUMN_TABLE_NAME
352 str = sqlite3_column_table_name(S->stmt, colno);
353 if (str) {
354 add_assoc_string(return_value, "table", (char *)str);
355 }
356 #endif
357
358 add_assoc_zval(return_value, "flags", &flags);
359
360 return SUCCESS;
361 }
362
pdo_sqlite_stmt_cursor_closer(pdo_stmt_t * stmt)363 static int pdo_sqlite_stmt_cursor_closer(pdo_stmt_t *stmt)
364 {
365 pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
366 sqlite3_reset(S->stmt);
367 return 1;
368 }
369
pdo_sqlite_stmt_get_attribute(pdo_stmt_t * stmt,zend_long attr,zval * val)370 static int pdo_sqlite_stmt_get_attribute(pdo_stmt_t *stmt, zend_long attr, zval *val)
371 {
372 pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
373
374 switch (attr) {
375 case PDO_SQLITE_ATTR_READONLY_STATEMENT:
376 ZVAL_FALSE(val);
377
378 #if SQLITE_VERSION_NUMBER >= 3007004
379 if (sqlite3_stmt_readonly(S->stmt)) {
380 ZVAL_TRUE(val);
381 }
382 #endif
383 break;
384
385 default:
386 return 0;
387 }
388
389 return 1;
390 }
391
392 const struct pdo_stmt_methods sqlite_stmt_methods = {
393 pdo_sqlite_stmt_dtor,
394 pdo_sqlite_stmt_execute,
395 pdo_sqlite_stmt_fetch,
396 pdo_sqlite_stmt_describe,
397 pdo_sqlite_stmt_get_col,
398 pdo_sqlite_stmt_param_hook,
399 NULL, /* set_attr */
400 pdo_sqlite_stmt_get_attribute, /* get_attr */
401 pdo_sqlite_stmt_col_meta,
402 NULL, /* next_rowset */
403 pdo_sqlite_stmt_cursor_closer
404 };
405