marcboeker / go-duckdb

go-duckdb provides a database/sql driver for the DuckDB database engine.
MIT License
648 stars 97 forks source link

Appender couldn't append duckdb.Decimal #113

Closed olablt closed 1 year ago

olablt commented 1 year ago

I am new in golang with databases. Trying to use appender to append to table with auto incremented ID and decimal data. Currently I am storing my data in decimal.Decimal format and in this example converting these to duckdb.Decimal.

error:

couldn't append unsupported parameter 2 (type duckdb.Decimal)
exit status 1

program:

func main() {
    // CREATE CONNECTOR
    connector, err := duckdb.NewConnector("apps/duckdb/nt.db", nil)
    if err != nil {
        log.Fatal("Failed creating connector", err)
    }

    // OPEN DB
    db := sql.OpenDB(connector)
    defer db.Close()

    // CONNECT CONNECTOR
    conn, err := connector.Connect(context.Background())
    if err != nil {
        log.Fatal("Failed failed connecting", err)
    }
    defer conn.Close()

    // CREATE TABLE
    _, err = db.Query(`CREATE SEQUENCE IF NOT EXISTS seq_id START 1;`)
    if err != nil {
        log.Fatal(err)
    }
    _, err = db.Exec(`
        CREATE TABLE IF NOT EXISTS ticks (
        id BIGINT primary key DEFAULT nextval('seq_id'),
        time TIMESTAMP,
        price DECIMAL(20,10),
    )`)
    if err != nil {
        log.Fatal(err)
    }

    // RETRIEVE APPENDER TO ALREADY EXISTING TABLE
    appender, err := duckdb.NewAppenderFromConn(conn, "", "ticks")
    if err != nil {
        log.Fatal("Failed creating appender:", err)
    }
    defer appender.Close()

    // INSERT DATA
    time := time.Now()
    price, _ := decimal.NewFromString("123456789.123456789")
    err = appender.AppendRow(
        nil,  // ID is auto-incremented
        time, // time
        duckdb.Decimal{Value: price.BigInt(), Scale: uint8(-price.Exponent())}, // price
    )
    if err != nil {
        log.Fatal(err)
    }
}
marcboeker commented 1 year ago

Unfortunately there is no native C API function in DuckDB to append a decimal. But you could try using Float64 if that fits you precision needs.

val := duckdb.Decimal{Value: big.NewInt(123), Width: 3, Scale: 2}
err = appender.AppendRow(
  nil,         // ID is auto-incremented
  time,        // time
  val.Float64(), // price
)
floatdrop commented 5 months ago

Unfortunately there is no native C API function in DuckDB to append a decimal. But you could try using Float64 if that fits you precision needs.

I wonder, how appender even got created in first place. I get error earlier, when constructing appender:

database/sql/driver: could not create appender: unsupported data type: DECIMAL: column index: 2
exit status 1