/*
 * call-seq:
 *    conn.insert_table( table, values )
 *
 * Inserts contents of the _values_ Array into the _table_.
 */
static VALUE
pgconn_insert_table(obj, table, values)
    VALUE obj, table, values;
{
    PGconn *conn = get_pgconn(obj);
    PGresult *result;
    VALUE s, buffer;
    int i, j;
    int res = 0;

    Check_Type(table, T_STRING);
    Check_Type(values, T_ARRAY);
    i = RARRAY(values)->len;
    while (i--) {
        if (TYPE(RARRAY(RARRAY(values)->ptr[i])) != T_ARRAY) {
            rb_raise(rb_ePGError, "second arg must contain some kind of arrays.");
        }
    }
    
    buffer = rb_str_new(0, RSTRING_LEN(table) + 17 + 1);
    /* starts query */
    snprintf(RSTRING_PTR(buffer), RSTRING_LEN(buffer), "copy %s from stdin ", StringValuePtr(table));
    
    result = PQexec(conn, StringValuePtr(buffer));
    if (!result){
        rb_raise(rb_ePGError, PQerrorMessage(conn));
    }
    PQclear(result);

    for (i = 0; i < RARRAY(values)->len; i++) {
        struct RArray *row = RARRAY(RARRAY(values)->ptr[i]);
        buffer = rb_tainted_str_new(0,0);
        for (j = 0; j < row->len; j++) {
            if (j > 0) rb_str_cat(buffer, "\t", 1);
            if (NIL_P(row->ptr[j])) {
                rb_str_cat(buffer, "\\N",2);
            } else {
                s = rb_obj_as_string(row->ptr[j]);
                rb_funcall(s,pg_gsub_bang_id,2,
                                        rb_str_new("([\\t\\n\\\\])", 10),pg_escape_str);
                rb_str_cat(buffer, StringValuePtr(s), RSTRING_LEN(s));
            }
        }
        rb_str_cat(buffer, "\n\0", 2);
        /* sends data */
        PQputline(conn, StringValuePtr(buffer));
    }
    PQputline(conn, "\\.\n");
    res = PQendcopy(conn);

    return obj;
}