/*      fetch()              */
static VALUE stmt_fetch(VALUE obj)
{
    struct mysql_stmt* s = DATA_PTR(obj);
    VALUE ret;
    int i;
    int r;

    check_stmt_closed(obj);
    r = mysql_stmt_fetch(s->stmt);
    if (r == MYSQL_NO_DATA)
        return Qnil;
    if (r == 1)
        mysql_stmt_raise(s->stmt);

    ret = rb_ary_new2(s->result.n);
    for (i = 0; i < s->result.n; i++) {
        if (s->result.is_null[i])
            rb_ary_push(ret, Qnil);
        else {
            VALUE v;
            MYSQL_TIME *t;
            switch (s->result.bind[i].buffer_type) {
            case MYSQL_TYPE_LONG:
                v = INT2NUM(*(long*)s->result.bind[i].buffer);
                break;
            case MYSQL_TYPE_LONGLONG:
                v = rb_ll2inum(*(long long*)s->result.bind[i].buffer);
                break;
            case MYSQL_TYPE_DOUBLE:
                v = rb_float_new(*(double*)s->result.bind[i].buffer);
                break;
            case MYSQL_TYPE_TIMESTAMP:
            case MYSQL_TYPE_DATE:
            case MYSQL_TYPE_TIME:
            case MYSQL_TYPE_DATETIME:
                t = (MYSQL_TIME*)s->result.bind[i].buffer;
                v = rb_obj_alloc(cMysqlTime);
                rb_funcall(v, rb_intern("initialize"), 8,
                           INT2FIX(t->year), INT2FIX(t->month),
                           INT2FIX(t->day), INT2FIX(t->hour),
                           INT2FIX(t->minute), INT2FIX(t->second),
                           (t->neg ? Qtrue : Qfalse),
                           INT2FIX(t->second_part));
                break;
            case MYSQL_TYPE_STRING:
            case MYSQL_TYPE_BLOB:
                v = rb_tainted_str_new(s->result.bind[i].buffer, s->result.length[i]);
                break;
            default:
                rb_raise(rb_eTypeError, "unknown buffer_type: %d", s->result.bind[i].buffer_type);
            }
            rb_ary_push(ret, v);
        }
    }
    return ret;
}