Bug #22001 | Prepared Statements unusable with unbuffered queries, mysql_stmt_refetch needed | ||
---|---|---|---|
Submitted: | 4 Sep 2006 16:07 | ||
Reporter: | Domas Mituzas | Email Updates: | |
Status: | Verified | Impact on me: | |
Category: | MySQL Server: Prepared statements | Severity: | S4 (Feature request) |
Version: | 5.0, 5.1, etc | OS: | |
Assigned to: | CPU Architecture: | Any |
[4 Sep 2006 16:07]
Domas Mituzas
[4 Sep 2006 16:51]
Andrey Hristov
I propose adding a function - mysql_stmt_refetch ===== libmysql.c 1.258 vs edited ===== --- 1.258/libmysql/libmysql.c 2006-09-04 18:49:29 +02:00 +++ edited/libmysql.c 2006-09-04 18:18:10 +02:00 @@ -4556,6 +4556,36 @@ int STDCALL mysql_stmt_fetch(MYSQL_STMT } else { + stmt->last_row= row; + /* This is to know in mysql_stmt_fetch_column that data was fetched */ + stmt->state= MYSQL_STMT_FETCH_DONE; + } + DBUG_RETURN(rc); +} + + +/* + Fetch and return row data to bound buffers, if any +*/ + +int STDCALL mysql_stmt_refetch(MYSQL_STMT *stmt) +{ + int rc; + uchar *row; + DBUG_ENTER("mysql_stmt_refetch"); + + if (!stmt->last_row) + DBUG_RETURN(0); + + if (((rc= stmt_fetch_row(stmt, stmt->last_row)) && + rc != MYSQL_DATA_TRUNCATED)) + { + stmt->state= MYSQL_STMT_PREPARE_DONE; /* XXX: this is buggy */ + stmt->read_row_func= (rc == MYSQL_NO_DATA) ? + stmt_read_row_no_data : stmt_read_row_no_result_set; + } + else + { /* This is to know in mysql_stmt_fetch_column that data was fetched */ stmt->state= MYSQL_STMT_FETCH_DONE; } ===== mysql.h 1.164 vs edited ===== --- 1.164/include/mysql.h 2006-09-04 18:50:11 +02:00 +++ edited/mysql.h 2006-09-04 15:54:58 +02:00 @@ -718,6 +718,7 @@ typedef struct st_mysql_stmt metadata fields when doing mysql_stmt_store_result. */ my_bool update_max_length; + unsigned char *last_row; } MYSQL_STMT; enum enum_stmt_attr_type @@ -780,6 +781,7 @@ int STDCALL mysql_stmt_prepare(MYSQL_STM unsigned long length); int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt); int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt); +int STDCALL mysql_stmt_refetch(MYSQL_STMT *stmt); int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind, unsigned int column, unsigned long offset);
[4 Sep 2006 16:54]
Andrey Hristov
After the call to mysql_stmt_fetch() which had failed with truncation error, the length of the column has been updated in the BIND structure. Hence, one can realloc the buffer and call mysql_stmt_refetch() like: if (ret == MYSQL_DATA_TRUNCATED) { for (i = 0; i < stmt->result.var_cnt; i++) { if (stmt->stmt->bind[i].error && stmt->stmt->bind[i].buffer_length) { stmt->result.buf[i].val= erealloc(stmt->result.buf[i].val, stmt->result.buf[i].buflen); } } if (MYSQL_DATA_TRUNCATED == mysql_stmt_refetch(stmt->stmt)) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "Serious extension error. Please contact the developers"); RETURN_FALSE; } }