/*      prepare(query)       */
static VALUE stmt_prepare(VALUE obj, VALUE query)
{
    struct mysql_stmt* s = DATA_PTR(obj);
    int n;
    int i;
    MYSQL_FIELD *field;

    free_mysqlstmt_memory(s);
    check_stmt_closed(obj);
    Check_Type(query, T_STRING);
    if (mysql_stmt_prepare(s->stmt, RSTRING_PTR(query), RSTRING_LEN(query)))
        mysql_stmt_raise(s->stmt);

    n = mysql_stmt_param_count(s->stmt);
    s->param.n = n;
    s->param.bind = xmalloc(sizeof(s->param.bind[0]) * n);
    s->param.length = xmalloc(sizeof(s->param.length[0]) * n);
    s->param.buffer = xmalloc(sizeof(s->param.buffer[0]) * n);

    s->res = mysql_stmt_result_metadata(s->stmt);
    if (s->res) {
        n = s->result.n = mysql_num_fields(s->res);
        s->result.bind = xmalloc(sizeof(s->result.bind[0]) * n);
        s->result.is_null = xmalloc(sizeof(s->result.is_null[0]) * n);
        s->result.length = xmalloc(sizeof(s->result.length[0]) * n);
        field = mysql_fetch_fields(s->res);
        memset(s->result.bind, 0, sizeof(s->result.bind[0]) * n);
        for (i = 0; i < n; i++) {
            s->result.bind[i].buffer_type = field[i].type;
#if MYSQL_VERSION_ID < 50003
            if (field[i].type == MYSQL_TYPE_DECIMAL)
                s->result.bind[i].buffer_type = MYSQL_TYPE_STRING;
#endif
            s->result.bind[i].is_null = &(s->result.is_null[i]);
            s->result.bind[i].length = &(s->result.length[i]);
            s->result.bind[i].is_unsigned = ((field[i].flags & UNSIGNED_FLAG) != 0);
        }
    } else {
        if (mysql_stmt_errno(s->stmt))
            mysql_stmt_raise(s->stmt);
    }

    return obj;
}