marcboeker / go-duckdb

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

Does DuckDB support ability to do insert into a table with MAP column type #137

Closed sharad-breadfin closed 8 months ago

sharad-breadfin commented 9 months ago

https://duckdb.org/docs/archive/0.6.1/sql/data_types/map

This wiki page has some information for how to create a table with MAP column and query it. I didn't see an example of inserting a row that has map column in it. Does DuckDB have "write" support for MAP column?

marcboeker commented 9 months ago

@sharad-breadfin Which error do you encounter when attempting to insert data into a table containing a map column?

sharad-breadfin commented 9 months ago

Apologies. I should have provided more information in original post.

Error seen is:

converting argument $4 type: unsupported type map[string]string, a map

Here is code snippets:

type ChangeEvent struct {
    TableName           string             `parquet:"name=table_name, type=BYTE_ARRAY, convertedtype=UTF8, encoding=PLAIN_DICTIONARY"`
    CommitTimestamp     int64              `parquet:"name=commit_timestamp, type=INT64, encoding=PLAIN"`
    TransactionId       int64              `parquet:"name=transaction_id, type=INT64, encoding=PLAIN"`        // TODO how to write UINT32 to parquet?
    Changes             *map[string]string `parquet:"name=changes, type=MAP, convertedtype=MAP, keytype=BYTE_ARRAY, keyconvertedtype=UTF8, valuetype=BYTE_ARRAY"`
}

db, _err := sql.Open("duckdb", "?access_mode=READ_WRITE")
_, _err = db.Exec("CREATE TABLE change_events(" +
        "table_name VARCHAR, " +
        "commit_timestamp INT64, " +
        "transaction_id INT64, " +
        "changes MAP(VARCHAR, VARCHAR)" +
        ")")

tx, _err := db.BeginTx(ctx, nil)
_, err = tx.ExecContext(ctx, "INSERT INTO change_events"+
        "("+
        "table_name, "+
        "commit_timestamp, "+
        "transaction_id,"+
        "changes"+
        ")"+
        "VALUES (?,?,?,?)",
        changeEvent.TableName,
        changeEvent.CommitTimestamp,
        changeEvent.TransactionId,
        &changeEvent.Changes,
    )
if err != nil {
        tx.Rollback()
        return fmt.Errorf("%w", err)
    }

parquet schema:

D describe select * from 'varchar.parquet';
┌───────────────────────┬───────────────────────┬─────────┬─────────┬─────────┬─────────┐
│      column_name      │      column_type      │  null   │   key   │ default │  extra  │
│        varchar        │        varchar        │ varchar │ varchar │ varchar │ varchar │
├───────────────────────┼───────────────────────┼─────────┼─────────┼─────────┼─────────┤
│ table_name            │ VARCHAR               │ YES     │         │         │         │
│ commit_timestamp      │ BIGINT                │ YES     │         │         │         │
│ transaction_id        │ BIGINT                │ YES     │         │         │         │
│ changes               │ MAP(VARCHAR, VARCHAR) │ YES     │         │         │         │
├───────────────────────┴───────────────────────┴─────────┴─────────┴─────────┴─────────┤
│ 4 rows                                                                      6 columns │
└───────────────────────────────────────────────────────────────────────────────────────┘
marcboeker commented 9 months ago

@sharad-breadfin Map serialization is not currently available, as I'm still figuring out how to bind a map using the C-API. I will provide an update as soon as I have figured it out.

marcboeker commented 9 months ago

Update: Seems not possible ATM using the C-API See: https://github.com/duckdb/duckdb/discussions/9365

You can serialize the map as JSON and store them in a VARCHAR/BLOB as a workaround.