duckdb / duckdb-rs

Ergonomic bindings to duckdb for Rust
MIT License
428 stars 87 forks source link

Feature request - Decimal type in appender API #345

Open xulai1001 opened 2 weeks ago

xulai1001 commented 2 weeks ago

I was trying to insert Mysql rows to DuckDB with the code below: let mut app = appender(table_name)?; app.append_row(appender_params_from_iter(row_iter))?; The program ran into panic! on Decimal types: internal error: entered unreachable code: not supported In src/duckdb/appender/mod.rs line 85, the function 'bind_parameter' matched many kinds of ValueRef variants, except for Decimal. https://docs.rs/duckdb/latest/src/duckdb/appender/mod.rs.html#65-71

For now I may convert it to Double(f64)...

lpfy commented 4 days ago

Hi @xulai1001, just wondering have you figured out how to use Appender API for different data types in a row?

for example, something like the code below, obviously the code won't run as a Rust array can not contain different data types:

{
    conn.execute_batch("CREATE OR REPLACE TABLE foo (id INTEGER, msg TEXT);")?;
    let mut app = conn.appender("foo")?;
    let row_data = [[1, "msg 1"], [2, "msg 2"]]
    app.append_rows(row_data)?;
}

I tried tuple, but it won't work as well: let row_data = [(1, "msg 1"), (2, "msg 2")]

The documentation only specified appending a row for every columns with the same data type, and the rust DuckDB API didn't expose the entire C appender APi e.g. duckdb_appender_begin_row, duckdb_append_varchar_length etc.

xulai1001 commented 2 days ago

Hi @xulai1001, just wondering have you figured out how to use Appender API for different data types in a row?

{
    conn.execute_batch("CREATE OR REPLACE TABLE foo (id INTEGER, msg TEXT);")?;
    let mut app = conn.appender("foo")?;
    let row_data = [[1, "msg 1"], [2, "msg 2"]]
    app.append_rows(row_data)?;
}

Try using a Vec<Vec<duckdb::types::Value>> to hold the data? For example let row_data = [[Value::Int(1), Value::Text("msg_1")], ... ]; You may need a custom converter to duckdb Value variant.

Meanwhile, instead of append_rows() with a nested collection, using "for" loops may be easier.

for row in ... { app.append_row(row); }

lpfy commented 2 days ago

Hi @xulai1001, just wondering have you figured out how to use Appender API for different data types in a row?

{
    conn.execute_batch("CREATE OR REPLACE TABLE foo (id INTEGER, msg TEXT);")?;
    let mut app = conn.appender("foo")?;
    let row_data = [[1, "msg 1"], [2, "msg 2"]]
    app.append_rows(row_data)?;
}

Try using a Vec<Vec<duckdb::types::Value>> to hold the data? For example let row_data = [[Value::Int(1), Value::Text("msg_1")], ... ]; You may need a custom converter to duckdb Value variant.

Meanwhile, instead of append_rows() with a nested collection, using "for" loops may be easier.

for row in ... { app.append_row(row); }

Thanks!! "duckdb::types::Value" works perfectly!