Handle OOM stemming from mysqlnd_result_init in the same

function and up the stack.
This commit is contained in:
Andrey Hristov 2010-05-03 18:50:47 +00:00
parent d90f8560aa
commit 2b18a3ff93
2 changed files with 72 additions and 28 deletions

View file

@ -156,20 +156,35 @@ MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const s TSRMLS_DC)
SET_EMPTY_ERROR(stmt->conn->error_info); SET_EMPTY_ERROR(stmt->conn->error_info);
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_BUFFERED_SETS); MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_BUFFERED_SETS);
result = mysqlnd_result_init(stmt->result->field_count, stmt->persistent TSRMLS_CC); do {
result = mysqlnd_result_init(stmt->result->field_count, stmt->persistent TSRMLS_CC);
if (!result) {
SET_OOM_ERROR(stmt->conn->error_info);
break;
}
result->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE TSRMLS_CC); result->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE TSRMLS_CC);
if (!result->meta) {
SET_OOM_ERROR(stmt->conn->error_info);
break;
}
if ((result = result->m.store_result(result, conn, TRUE TSRMLS_CC))) { if ((result = result->m.store_result(result, conn, TRUE TSRMLS_CC))) {
stmt->upsert_status.affected_rows = result->stored_data->row_count; stmt->upsert_status.affected_rows = result->stored_data->row_count;
stmt->state = MYSQLND_STMT_PREPARED; stmt->state = MYSQLND_STMT_PREPARED;
result->type = MYSQLND_RES_PS_BUF; result->type = MYSQLND_RES_PS_BUF;
} else { } else {
stmt->error_info = conn->error_info; stmt->error_info = conn->error_info;
stmt->state = MYSQLND_STMT_PREPARED; stmt->state = MYSQLND_STMT_PREPARED;
break;
}
DBG_RETURN(result);
} while (0);
if (result) {
result->m.free_result(result, TRUE TSRMLS_CC);
} }
DBG_RETURN(NULL);
DBG_RETURN(result);
} }
/* }}} */ /* }}} */
@ -366,6 +381,10 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const
*/ */
if (stmt_to_prepare->field_count) { if (stmt_to_prepare->field_count) {
MYSQLND_RES * result = mysqlnd_result_init(stmt_to_prepare->field_count, stmt_to_prepare->persistent TSRMLS_CC); MYSQLND_RES * result = mysqlnd_result_init(stmt_to_prepare->field_count, stmt_to_prepare->persistent TSRMLS_CC);
if (!result) {
SET_OOM_ERROR(stmt->conn->error_info);
goto fail;
}
/* Allocate the result now as it is needed for the reading of metadata */ /* Allocate the result now as it is needed for the reading of metadata */
stmt_to_prepare->result = result; stmt_to_prepare->result = result;
@ -374,7 +393,8 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const
result->type = MYSQLND_RES_PS_BUF; result->type = MYSQLND_RES_PS_BUF;
if (FAIL == result->m.read_result_metadata(result, stmt_to_prepare->conn TSRMLS_CC) || if (FAIL == result->m.read_result_metadata(result, stmt_to_prepare->conn TSRMLS_CC) ||
FAIL == mysqlnd_stmt_prepare_read_eof(s_to_prepare TSRMLS_CC)) { FAIL == mysqlnd_stmt_prepare_read_eof(s_to_prepare TSRMLS_CC))
{
goto fail; goto fail;
} }
} }
@ -1655,15 +1675,32 @@ MYSQLND_METHOD(mysqlnd_stmt, result_metadata)(MYSQLND_STMT * const s TSRMLS_DC)
In the meantime we don't need a zval cache reference for this fake In the meantime we don't need a zval cache reference for this fake
result set, so we don't get one. result set, so we don't get one.
*/ */
result = mysqlnd_result_init(stmt->field_count, stmt->persistent TSRMLS_CC); do {
result->type = MYSQLND_RES_NORMAL; result = mysqlnd_result_init(stmt->field_count, stmt->persistent TSRMLS_CC);
result->m.fetch_row = result->m.fetch_row_normal_unbuffered; if (!result) {
result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED)); break;
result->unbuf->eof_reached = TRUE; }
result->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE TSRMLS_CC); result->type = MYSQLND_RES_NORMAL;
result->m.fetch_row = result->m.fetch_row_normal_unbuffered;
result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED));
if (!result->unbuf) {
break;
}
result->unbuf->eof_reached = TRUE;
result->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE TSRMLS_CC);
if (!result->meta) {
break;
}
DBG_INF_FMT("result=%p", result); DBG_INF_FMT("result=%p", result);
DBG_RETURN(result); DBG_RETURN(result);
} while (0);
SET_OOM_ERROR(stmt->conn->error_info);
if (result) {
result->m.free_result(result, TRUE TSRMLS_CC);
}
DBG_RETURN(NULL);
} }
/* }}} */ /* }}} */

View file

@ -353,6 +353,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC)
MYSQLND_STMT_DATA * stmt = s ? s->data:NULL; MYSQLND_STMT_DATA * stmt = s ? s->data:NULL;
enum_func_status ret; enum_func_status ret;
MYSQLND_PACKET_RSET_HEADER * rset_header; MYSQLND_PACKET_RSET_HEADER * rset_header;
MYSQLND_PACKET_EOF * fields_eof;
DBG_ENTER("mysqlnd_query_read_result_set_header"); DBG_ENTER("mysqlnd_query_read_result_set_header");
DBG_INF_FMT("stmt=%d", stmt? stmt->stmt_id:0); DBG_INF_FMT("stmt=%d", stmt? stmt->stmt_id:0);
@ -420,8 +421,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC)
ret = PASS; ret = PASS;
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_NON_RSET_QUERY); MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_NON_RSET_QUERY);
break; break;
default:{ /* Result set */ default: do { /* Result set */
MYSQLND_PACKET_EOF * fields_eof;
MYSQLND_RES * result; MYSQLND_RES * result;
enum_mysqlnd_collected_stats stat = STAT_LAST; enum_mysqlnd_collected_stats stat = STAT_LAST;
@ -464,7 +464,12 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC)
} }
result = stmt->result; result = stmt->result;
} }
if (!result) {
SET_OOM_ERROR(conn->error_info);
ret = FAIL;
break;
}
if (FAIL == (ret = result->m.read_result_metadata(result, conn TSRMLS_CC))) { if (FAIL == (ret = result->m.read_result_metadata(result, conn TSRMLS_CC))) {
/* For PS, we leave them in Prepared state */ /* For PS, we leave them in Prepared state */
if (!stmt && conn->current_result) { if (!stmt && conn->current_result) {
@ -517,11 +522,9 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC)
} }
MYSQLND_INC_CONN_STATISTIC(conn->stats, stat); MYSQLND_INC_CONN_STATISTIC(conn->stats, stat);
} }
} while (0);
PACKET_FREE(fields_eof); PACKET_FREE(fields_eof);
break; /* switch break */
break;
}
} }
} while (0); } while (0);
PACKET_FREE(rset_header); PACKET_FREE(rset_header);
@ -1546,6 +1549,10 @@ mysqlnd_result_init(unsigned int field_count, zend_bool persistent TSRMLS_DC)
DBG_ENTER("mysqlnd_result_init"); DBG_ENTER("mysqlnd_result_init");
DBG_INF_FMT("field_count=%u", field_count); DBG_INF_FMT("field_count=%u", field_count);
if (!ret) {
DBG_RETURN(NULL);
}
ret->persistent = persistent; ret->persistent = persistent;
ret->field_count = field_count; ret->field_count = field_count;