# HG changeset patch # User Matthew Wild # Date 1340988337 -3600 # Node ID 7c968f66bccdf963ce9f7504ef2badcc265bb36d # Parent aab3ed7d93fe9b10b75e302c787737999a8b4a5f MySQL: Avoid allocating the full column size to receive results, for variable-length types check result size before allocation (thanks Florob) diff -r aab3ed7d93fe -r 7c968f66bccd dbd/mysql/statement.c --- a/dbd/mysql/statement.c Fri Dec 24 00:34:04 2010 +0000 +++ b/dbd/mysql/statement.c Fri Jun 29 17:45:37 2012 +0100 @@ -286,8 +286,9 @@ } static int statement_fetch_impl(lua_State *L, statement_t *statement, int named_columns) { - int column_count; + int column_count, fetch_result_ok; MYSQL_BIND *bind = NULL; + unsigned long *real_length = NULL; const char *error_message = NULL; if (!statement->stmt) { @@ -306,6 +307,8 @@ int i; MYSQL_FIELD *fields; + real_length = calloc(column_count, sizeof(unsigned long)); + bind = malloc(sizeof(MYSQL_BIND) * column_count); memset(bind, 0, sizeof(MYSQL_BIND) * column_count); @@ -313,12 +316,19 @@ for (i = 0; i < column_count; i++) { unsigned int length = mysql_buffer_size(&fields[i]); - char *buffer = (char *)malloc(length); - memset(buffer, 0, length); + if (length > sizeof(MYSQL_TIME)) { + bind[i].buffer = NULL; + bind[i].buffer_length = 0; + } else { + char *buffer = (char *)malloc(length); + memset(buffer, 0, length); + + bind[i].buffer = buffer; + bind[i].buffer_length = length; + } bind[i].buffer_type = fields[i].type; - bind[i].buffer = buffer; - bind[i].buffer_length = length; + bind[i].length = &real_length[i]; } if (mysql_stmt_bind_result(statement->stmt, bind)) { @@ -326,7 +336,8 @@ goto cleanup; } - if (!mysql_stmt_fetch(statement->stmt)) { + fetch_result_ok = mysql_stmt_fetch(statement->stmt); + if (fetch_result_ok == 0 || fetch_result_ok == MYSQL_DATA_TRUNCATED) { int d = 1; lua_newtable(L); @@ -334,6 +345,15 @@ lua_push_type_t lua_push = mysql_to_lua_push(fields[i].type); const char *name = fields[i].name; + if (bind[i].buffer == NULL) { + char *buffer = (char *)malloc(real_length[i]); + memset(buffer, 0, real_length[i]); + + bind[i].buffer = buffer; + bind[i].buffer_length = real_length[i]; + mysql_stmt_fetch_column(statement->stmt, bind, i, 0); + } + if (lua_push == LUA_PUSH_NIL) { if (named_columns) { LUA_PUSH_ATTRIB_NIL(name); @@ -425,6 +445,8 @@ } cleanup: + free(real_length); + if (bind) { int i;