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: George Schlossnagle <george@omniti.com> |
16 : | Wez Furlong <wez@php.net> |
17 : +----------------------------------------------------------------------+
18 : */
19 :
20 : /* $Id: mysql_statement.c 272374 2008-12-31 11:17:49Z sebastian $ */
21 :
22 : #ifdef HAVE_CONFIG_H
23 : #include "config.h"
24 : #endif
25 :
26 : #include "php.h"
27 : #include "php_ini.h"
28 : #include "ext/standard/info.h"
29 : #include "pdo/php_pdo.h"
30 : #include "pdo/php_pdo_driver.h"
31 : #include "php_pdo_mysql.h"
32 : #include "php_pdo_mysql_int.h"
33 :
34 :
35 : static int pdo_mysql_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC)
36 145 : {
37 145 : pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data;
38 :
39 145 : if (S->result) {
40 : /* free the resource */
41 103 : mysql_free_result(S->result);
42 103 : S->result = NULL;
43 : }
44 145 : if (S->einfo.errmsg) {
45 2 : pefree(S->einfo.errmsg, stmt->dbh->is_persistent);
46 2 : S->einfo.errmsg = NULL;
47 : }
48 : #if HAVE_MYSQL_STMT_PREPARE
49 145 : if (S->stmt) {
50 5 : mysql_stmt_close(S->stmt);
51 5 : S->stmt = NULL;
52 : }
53 145 : if (S->params) {
54 0 : efree(S->params);
55 0 : efree(S->in_null);
56 0 : efree(S->in_length);
57 : }
58 145 : if (S->bound_result)
59 : {
60 : int i;
61 3 : for (i = 0; i < stmt->column_count; i++) {
62 2 : efree(S->bound_result[i].buffer);
63 : }
64 :
65 1 : efree(S->bound_result);
66 1 : efree(S->out_null);
67 1 : efree(S->out_length);
68 : }
69 : #endif
70 : #if HAVE_MYSQL_NEXT_RESULT
71 145 : if (S->H->server) {
72 290 : while (mysql_more_results(S->H->server)) {
73 : MYSQL_RES *res;
74 0 : if (mysql_next_result(S->H->server) != 0) {
75 0 : break;
76 : }
77 :
78 0 : res = mysql_store_result(S->H->server);
79 0 : if (res) {
80 0 : mysql_free_result(res);
81 : }
82 : }
83 : }
84 : #endif
85 145 : efree(S);
86 145 : return 1;
87 : }
88 :
89 : static int pdo_mysql_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
90 222 : {
91 222 : pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data;
92 222 : pdo_mysql_db_handle *H = S->H;
93 : my_ulonglong row_count;
94 : #if HAVE_MYSQL_STMT_PREPARE
95 : int i;
96 :
97 222 : if (S->stmt) {
98 : /* (re)bind the parameters */
99 5 : if (mysql_stmt_bind_param(S->stmt, S->params)) {
100 0 : pdo_mysql_error_stmt(stmt);
101 0 : return 0;
102 : }
103 :
104 5 : if (mysql_stmt_execute(S->stmt)) {
105 0 : pdo_mysql_error_stmt(stmt);
106 0 : return 0;
107 : }
108 :
109 5 : if (!S->result) {
110 : /* figure out the result set format, if any */
111 5 : S->result = mysql_stmt_result_metadata(S->stmt);
112 5 : if (S->result) {
113 1 : int calc_max_length = H->buffered && S->max_length == 1;
114 :
115 1 : S->fields = mysql_fetch_fields(S->result);
116 :
117 1 : if (S->bound_result) {
118 : int i;
119 0 : for (i = 0; i < stmt->column_count; i++) {
120 0 : efree(S->bound_result[i].buffer);
121 : }
122 0 : efree(S->bound_result);
123 0 : efree(S->out_null);
124 0 : efree(S->out_length);
125 : }
126 :
127 1 : stmt->column_count = (int)mysql_num_fields(S->result);
128 1 : S->bound_result = ecalloc(stmt->column_count, sizeof(MYSQL_BIND));
129 1 : S->out_null = ecalloc(stmt->column_count, sizeof(my_bool));
130 1 : S->out_length = ecalloc(stmt->column_count, sizeof(unsigned long));
131 :
132 : /* summon memory to hold the row */
133 3 : for (i = 0; i < stmt->column_count; i++) {
134 2 : if (calc_max_length && S->fields[i].type == FIELD_TYPE_BLOB) {
135 0 : my_bool on = 1;
136 0 : mysql_stmt_attr_set(S->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &on);
137 0 : calc_max_length = 0;
138 : }
139 2 : switch (S->fields[i].type) {
140 : case FIELD_TYPE_INT24:
141 0 : S->bound_result[i].buffer_length = MAX_MEDIUMINT_WIDTH;
142 0 : break;
143 : case FIELD_TYPE_LONG:
144 1 : S->bound_result[i].buffer_length = MAX_INT_WIDTH;
145 1 : break;
146 : case FIELD_TYPE_LONGLONG:
147 0 : S->bound_result[i].buffer_length = MAX_BIGINT_WIDTH;
148 0 : break;
149 : case FIELD_TYPE_TINY:
150 0 : S->bound_result[i].buffer_length = MAX_TINYINT_WIDTH;
151 0 : break;
152 : case FIELD_TYPE_SHORT:
153 0 : S->bound_result[i].buffer_length = MAX_SMALLINT_WIDTH;
154 0 : break;
155 : default:
156 1 : S->bound_result[i].buffer_length =
157 : S->fields[i].max_length? S->fields[i].max_length:
158 : S->fields[i].length;
159 : /* work-around for longtext and alike */
160 1 : if (S->bound_result[i].buffer_length > H->max_buffer_size) {
161 0 : S->bound_result[i].buffer_length = H->max_buffer_size;
162 : }
163 : }
164 : #if 0
165 : printf("%d: max_length=%d length=%d buffer_length=%d type=%d\n",
166 : i,
167 : S->fields[i].max_length,
168 : S->fields[i].length,
169 : S->bound_result[i].buffer_length,
170 : S->fields[i].type
171 : );
172 : #endif
173 :
174 : /* there are cases where the length reported by mysql is too short.
175 : * eg: when describing a table that contains an enum column. Since
176 : * we have no way of knowing the true length either, we'll bump up
177 : * our buffer size to a reasonable size, just in case */
178 2 : if (S->fields[i].max_length == 0 && S->bound_result[i].buffer_length < 128 && MYSQL_TYPE_VAR_STRING) {
179 2 : S->bound_result[i].buffer_length = 128;
180 : }
181 :
182 2 : S->out_length[i] = 0;
183 :
184 2 : S->bound_result[i].buffer = emalloc(S->bound_result[i].buffer_length);
185 2 : S->bound_result[i].is_null = &S->out_null[i];
186 2 : S->bound_result[i].length = &S->out_length[i];
187 2 : S->bound_result[i].buffer_type = MYSQL_TYPE_STRING;
188 : }
189 :
190 1 : if (mysql_stmt_bind_result(S->stmt, S->bound_result)) {
191 0 : pdo_mysql_error_stmt(stmt);
192 0 : return 0;
193 : }
194 :
195 : /* if buffered, pre-fetch all the data */
196 1 : if (H->buffered) {
197 1 : mysql_stmt_store_result(S->stmt);
198 : }
199 : }
200 : }
201 :
202 5 : row_count = mysql_stmt_affected_rows(S->stmt);
203 5 : if (row_count != (my_ulonglong)-1) {
204 5 : stmt->row_count = row_count;
205 : }
206 5 : return 1;
207 : }
208 : #endif
209 : /* ensure that we free any previous unfetched results */
210 217 : if (S->result) {
211 27 : mysql_free_result(S->result);
212 27 : S->result = NULL;
213 : }
214 :
215 217 : if (mysql_real_query(H->server, stmt->active_query_string, stmt->active_query_stringlen) != 0) {
216 2 : pdo_mysql_error_stmt(stmt);
217 2 : return 0;
218 : }
219 :
220 215 : row_count = mysql_affected_rows(H->server);
221 215 : if (row_count == (my_ulonglong)-1) {
222 : /* we either have a query that returned a result set or an error occured
223 : lets see if we have access to a result set */
224 158 : if (!H->buffered) {
225 0 : S->result = mysql_use_result(H->server);
226 : } else {
227 158 : S->result = mysql_store_result(H->server);
228 : }
229 158 : if (NULL == S->result) {
230 0 : pdo_mysql_error_stmt(stmt);
231 0 : return 0;
232 : }
233 :
234 158 : stmt->row_count = mysql_num_rows(S->result);
235 :
236 158 : if (!stmt->executed) {
237 131 : stmt->column_count = (int) mysql_num_fields(S->result);
238 131 : S->fields = mysql_fetch_fields(S->result);
239 : }
240 : } else {
241 : /* this was a DML or DDL query (INSERT, UPDATE, DELETE, ... */
242 57 : stmt->row_count = row_count;
243 : }
244 :
245 215 : return 1;
246 : }
247 :
248 : static int pdo_mysql_stmt_next_rowset(pdo_stmt_t *stmt TSRMLS_DC)
249 0 : {
250 : #if HAVE_MYSQL_NEXT_RESULT
251 0 : pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data;
252 0 : pdo_mysql_db_handle *H = S->H;
253 : my_ulonglong row_count;
254 : int ret;
255 :
256 : /* ensure that we free any previous unfetched results */
257 : #if HAVE_MYSQL_STMT_PREPARE
258 0 : if (S->stmt) {
259 0 : mysql_stmt_free_result(S->stmt);
260 : }
261 : #endif
262 0 : if (S->result) {
263 0 : mysql_free_result(S->result);
264 0 : S->result = NULL;
265 : }
266 :
267 0 : ret = mysql_next_result(H->server);
268 :
269 0 : if (ret > 0) {
270 0 : pdo_mysql_error_stmt(stmt);
271 0 : return 0;
272 0 : } else if (ret < 0) {
273 : /* No more results */
274 0 : return 0;
275 : } else {
276 0 : if (!H->buffered) {
277 0 : S->result = mysql_use_result(H->server);
278 0 : row_count = 0;
279 : } else {
280 0 : S->result = mysql_store_result(H->server);
281 0 : if ((my_ulonglong)-1 == (row_count = mysql_affected_rows(H->server))) {
282 0 : pdo_mysql_error_stmt(stmt);
283 0 : return 0;
284 : }
285 : }
286 :
287 0 : if (NULL == S->result) {
288 0 : return 0;
289 : }
290 :
291 0 : stmt->row_count = row_count;
292 0 : stmt->column_count = (int) mysql_num_fields(S->result);
293 0 : S->fields = mysql_fetch_fields(S->result);
294 0 : return 1;
295 : }
296 : #else
297 : strcpy(stmt->error_code, "HYC00");
298 : return 0;
299 : #endif
300 : }
301 :
302 :
303 : static int pdo_mysql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param,
304 : enum pdo_param_event event_type TSRMLS_DC)
305 928 : {
306 : #if HAVE_MYSQL_STMT_PREPARE
307 928 : pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data;
308 : MYSQL_BIND *b;
309 :
310 928 : if (S->stmt && param->is_param) {
311 0 : switch (event_type) {
312 : case PDO_PARAM_EVT_ALLOC:
313 : /* sanity check parameter number range */
314 0 : if (param->paramno < 0 || param->paramno >= S->num_params) {
315 0 : strcpy(stmt->error_code, "HY093");
316 0 : return 0;
317 : }
318 0 : b = &S->params[param->paramno];
319 0 : param->driver_data = b;
320 0 : b->is_null = &S->in_null[param->paramno];
321 0 : b->length = &S->in_length[param->paramno];
322 0 : return 1;
323 :
324 : case PDO_PARAM_EVT_EXEC_PRE:
325 0 : b = (MYSQL_BIND*)param->driver_data;
326 :
327 0 : *b->is_null = 0;
328 0 : if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_NULL ||
329 : Z_TYPE_P(param->parameter) == IS_NULL) {
330 0 : *b->is_null = 1;
331 0 : b->buffer_type = MYSQL_TYPE_STRING;
332 0 : b->buffer = NULL;
333 0 : b->buffer_length = 0;
334 0 : *b->length = 0;
335 0 : return 1;
336 : }
337 :
338 0 : switch (PDO_PARAM_TYPE(param->param_type)) {
339 : case PDO_PARAM_STMT:
340 0 : return 0;
341 : case PDO_PARAM_LOB:
342 0 : if (Z_TYPE_P(param->parameter) == IS_RESOURCE) {
343 : php_stream *stm;
344 0 : php_stream_from_zval_no_verify(stm, ¶m->parameter);
345 0 : if (stm) {
346 0 : SEPARATE_ZVAL_IF_NOT_REF(¶m->parameter);
347 0 : Z_TYPE_P(param->parameter) = IS_STRING;
348 0 : Z_STRLEN_P(param->parameter) = php_stream_copy_to_mem(stm,
349 : &Z_STRVAL_P(param->parameter), PHP_STREAM_COPY_ALL, 0);
350 : } else {
351 0 : pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a stream resource" TSRMLS_CC);
352 0 : return 0;
353 : }
354 : }
355 : /* fall through */
356 :
357 : default:
358 : ;
359 : }
360 :
361 0 : switch (Z_TYPE_P(param->parameter)) {
362 : case IS_STRING:
363 0 : b->buffer_type = MYSQL_TYPE_STRING;
364 0 : b->buffer = Z_STRVAL_P(param->parameter);
365 0 : b->buffer_length = Z_STRLEN_P(param->parameter);
366 0 : *b->length = Z_STRLEN_P(param->parameter);
367 0 : return 1;
368 :
369 : case IS_LONG:
370 0 : b->buffer_type = MYSQL_TYPE_LONG;
371 0 : b->buffer = &Z_LVAL_P(param->parameter);
372 0 : return 1;
373 :
374 : case IS_DOUBLE:
375 0 : b->buffer_type = MYSQL_TYPE_DOUBLE;
376 0 : b->buffer = &Z_DVAL_P(param->parameter);
377 0 : return 1;
378 :
379 : default:
380 0 : return 0;
381 : }
382 : }
383 : }
384 : #endif
385 928 : return 1;
386 : }
387 :
388 : static int pdo_mysql_stmt_fetch(pdo_stmt_t *stmt,
389 : enum pdo_fetch_orientation ori, long offset TSRMLS_DC)
390 370 : {
391 370 : pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data;
392 : #if HAVE_MYSQL_STMT_PREPARE
393 : int ret;
394 :
395 370 : if (S->stmt) {
396 5 : ret = mysql_stmt_fetch(S->stmt);
397 :
398 : #ifdef MYSQL_DATA_TRUNCATED
399 5 : if (ret == MYSQL_DATA_TRUNCATED) {
400 0 : ret = 0;
401 : }
402 : #endif
403 :
404 5 : if (ret) {
405 1 : if (ret != MYSQL_NO_DATA) {
406 0 : pdo_mysql_error_stmt(stmt);
407 : }
408 1 : return 0;
409 : }
410 :
411 4 : return 1;
412 : }
413 : #endif
414 :
415 365 : if (!S->result) {
416 0 : strcpy(stmt->error_code, "HY000");
417 0 : return 0;
418 : }
419 365 : if ((S->current_data = mysql_fetch_row(S->result)) == NULL) {
420 85 : if (mysql_errno(S->H->server)) {
421 0 : pdo_mysql_error_stmt(stmt);
422 : }
423 85 : return 0;
424 : }
425 280 : S->current_lengths = mysql_fetch_lengths(S->result);
426 280 : return 1;
427 : }
428 :
429 : static int pdo_mysql_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
430 197 : {
431 197 : pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data;
432 197 : struct pdo_column_data *cols = stmt->columns;
433 : unsigned int i;
434 :
435 197 : if (!S->result) {
436 0 : return 0;
437 : }
438 :
439 197 : if (colno >= stmt->column_count) {
440 : /* error invalid column */
441 0 : return 0;
442 : }
443 :
444 : /* fetch all on demand, this seems easiest
445 : ** if we've been here before bail out
446 : */
447 197 : if (cols[0].name) {
448 86 : return 1;
449 : }
450 308 : for (i=0; i < stmt->column_count; i++) {
451 : int namelen;
452 197 : namelen = strlen(S->fields[i].name);
453 197 : cols[i].precision = S->fields[i].decimals;
454 197 : cols[i].maxlen = S->fields[i].length;
455 197 : cols[i].namelen = namelen;
456 197 : cols[i].name = estrndup(S->fields[i].name, namelen);
457 197 : cols[i].param_type = PDO_PARAM_STR;
458 : }
459 111 : return 1;
460 : }
461 :
462 : static int pdo_mysql_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsigned long *len, int *caller_frees TSRMLS_DC)
463 555 : {
464 555 : pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data;
465 :
466 : #if HAVE_MYSQL_STMT_PREPARE
467 555 : if (!S->stmt) {
468 : #endif
469 547 : if (S->current_data == NULL || !S->result) {
470 0 : return 0;
471 : }
472 : #if HAVE_MYSQL_STMT_PREPARE
473 : }
474 : #endif
475 555 : if (colno >= stmt->column_count) {
476 : /* error invalid column */
477 0 : return 0;
478 : }
479 : #if HAVE_MYSQL_STMT_PREPARE
480 555 : if (S->stmt) {
481 8 : if (S->out_null[colno]) {
482 2 : *ptr = NULL;
483 2 : *len = 0;
484 2 : return 1;
485 : }
486 6 : *ptr = S->bound_result[colno].buffer;
487 6 : if (S->out_length[colno] > S->bound_result[colno].buffer_length) {
488 : /* mysql lied about the column width */
489 0 : strcpy(stmt->error_code, "01004"); /* truncated */
490 0 : S->out_length[colno] = S->bound_result[colno].buffer_length;
491 0 : *len = S->out_length[colno];
492 0 : return 0;
493 : }
494 6 : *len = S->out_length[colno];
495 6 : return 1;
496 : }
497 : #endif
498 547 : *ptr = S->current_data[colno];
499 547 : *len = S->current_lengths[colno];
500 547 : return 1;
501 : }
502 :
503 : static char *type_to_name_native(int type)
504 1 : {
505 : #define PDO_MYSQL_NATIVE_TYPE_NAME(x) case FIELD_TYPE_##x: return #x;
506 :
507 1 : switch (type) {
508 0 : PDO_MYSQL_NATIVE_TYPE_NAME(STRING)
509 0 : PDO_MYSQL_NATIVE_TYPE_NAME(VAR_STRING)
510 : #ifdef MYSQL_HAS_TINY
511 : PDO_MYSQL_NATIVE_TYPE_NAME(TINY)
512 : #endif
513 0 : PDO_MYSQL_NATIVE_TYPE_NAME(SHORT)
514 1 : PDO_MYSQL_NATIVE_TYPE_NAME(LONG)
515 0 : PDO_MYSQL_NATIVE_TYPE_NAME(LONGLONG)
516 0 : PDO_MYSQL_NATIVE_TYPE_NAME(INT24)
517 0 : PDO_MYSQL_NATIVE_TYPE_NAME(FLOAT)
518 0 : PDO_MYSQL_NATIVE_TYPE_NAME(DOUBLE)
519 0 : PDO_MYSQL_NATIVE_TYPE_NAME(DECIMAL)
520 : #ifdef FIELD_TYPE_NEWDECIMAL
521 0 : PDO_MYSQL_NATIVE_TYPE_NAME(NEWDECIMAL)
522 : #endif
523 : #ifdef FIELD_TYPE_GEOMETRY
524 0 : PDO_MYSQL_NATIVE_TYPE_NAME(GEOMETRY)
525 : #endif
526 0 : PDO_MYSQL_NATIVE_TYPE_NAME(TIMESTAMP)
527 : #ifdef MYSQL_HAS_YEAR
528 : PDO_MYSQL_NATIVE_TYPE_NAME(YEAR)
529 : #endif
530 0 : PDO_MYSQL_NATIVE_TYPE_NAME(SET)
531 0 : PDO_MYSQL_NATIVE_TYPE_NAME(ENUM)
532 0 : PDO_MYSQL_NATIVE_TYPE_NAME(DATE)
533 : #ifdef FIELD_TYPE_NEWDATE
534 0 : PDO_MYSQL_NATIVE_TYPE_NAME(NEWDATE)
535 : #endif
536 0 : PDO_MYSQL_NATIVE_TYPE_NAME(TIME)
537 0 : PDO_MYSQL_NATIVE_TYPE_NAME(DATETIME)
538 0 : PDO_MYSQL_NATIVE_TYPE_NAME(TINY_BLOB)
539 0 : PDO_MYSQL_NATIVE_TYPE_NAME(MEDIUM_BLOB)
540 0 : PDO_MYSQL_NATIVE_TYPE_NAME(LONG_BLOB)
541 0 : PDO_MYSQL_NATIVE_TYPE_NAME(BLOB)
542 0 : PDO_MYSQL_NATIVE_TYPE_NAME(NULL)
543 : default:
544 0 : return NULL;
545 : }
546 : }
547 :
548 : static int pdo_mysql_stmt_col_meta(pdo_stmt_t *stmt, long colno, zval *return_value TSRMLS_DC)
549 2 : {
550 2 : pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data;
551 : MYSQL_FIELD *F;
552 : zval *flags;
553 : char *str;
554 :
555 2 : if (!S->result) {
556 1 : return FAILURE;
557 : }
558 1 : if (colno >= stmt->column_count) {
559 : /* error invalid column */
560 0 : return FAILURE;
561 : }
562 :
563 1 : array_init(return_value);
564 1 : MAKE_STD_ZVAL(flags);
565 1 : array_init(flags);
566 :
567 1 : F = S->fields + colno;
568 :
569 1 : if (F->def) {
570 0 : add_assoc_string(return_value, "mysql:def", F->def, 1);
571 : }
572 1 : if (IS_NOT_NULL(F->flags)) {
573 1 : add_next_index_string(flags, "not_null", 1);
574 : }
575 1 : if (IS_PRI_KEY(F->flags)) {
576 0 : add_next_index_string(flags, "primary_key", 1);
577 : }
578 1 : if (F->flags & MULTIPLE_KEY_FLAG) {
579 0 : add_next_index_string(flags, "multiple_key", 1);
580 : }
581 1 : if (F->flags & UNIQUE_KEY_FLAG) {
582 0 : add_next_index_string(flags, "unique_key", 1);
583 : }
584 1 : if (IS_BLOB(F->flags)) {
585 0 : add_next_index_string(flags, "blob", 1);
586 : }
587 1 : str = type_to_name_native(F->type);
588 1 : if (str) {
589 1 : add_assoc_string(return_value, "native_type", str, 1);
590 : }
591 :
592 1 : add_assoc_zval(return_value, "flags", flags);
593 1 : add_assoc_string(return_value, "table",(F->table?F->table:""), 1);
594 1 : return SUCCESS;
595 : }
596 :
597 : static int pdo_mysql_stmt_cursor_closer(pdo_stmt_t *stmt TSRMLS_DC)
598 28 : {
599 28 : pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data;
600 :
601 28 : if (S->result) {
602 28 : mysql_free_result(S->result);
603 28 : S->result = NULL;
604 : }
605 : #if HAVE_MYSQL_STMT_PREPARE
606 28 : if (S->stmt) {
607 : int retval;
608 0 : if (!S->H->buffered) {
609 0 : retval = mysql_stmt_close(S->stmt);
610 0 : S->stmt = NULL;
611 : } else {
612 0 : retval = mysql_stmt_free_result(S->stmt);
613 : }
614 0 : return retval ? 0 : 1;
615 : }
616 : #endif
617 :
618 : #if HAVE_MYSQL_NEXT_RESULT
619 56 : while (mysql_more_results(S->H->server)) {
620 : MYSQL_RES *res;
621 0 : if (mysql_next_result(S->H->server) != 0) {
622 0 : break;
623 : }
624 0 : res = mysql_store_result(S->H->server);
625 0 : if (res) {
626 0 : mysql_free_result(res);
627 : }
628 : }
629 : #endif
630 28 : return 1;
631 : }
632 :
633 : struct pdo_stmt_methods mysql_stmt_methods = {
634 : pdo_mysql_stmt_dtor,
635 : pdo_mysql_stmt_execute,
636 : pdo_mysql_stmt_fetch,
637 : pdo_mysql_stmt_describe,
638 : pdo_mysql_stmt_get_col,
639 : pdo_mysql_stmt_param_hook,
640 : NULL, /* set_attr */
641 : NULL, /* get_attr */
642 : pdo_mysql_stmt_col_meta,
643 : pdo_mysql_stmt_next_rowset,
644 : pdo_mysql_stmt_cursor_closer
645 : };
646 :
647 : /*
648 : * Local variables:
649 : * tab-width: 4
650 : * c-basic-offset: 4
651 : * End:
652 : * vim600: noet sw=4 ts=4 fdm=marker
653 : * vim<600: noet sw=4 ts=4
654 : */
|