Skip to content

sql.Valuer is ignored for a subtype of map #49

@glenjamin

Description

@glenjamin

At first I thought this was specific to JSON handling, but I've since realised what's actually going on.

Given a type like this

type somethingCustom map[string]int

func (s somethingCustom) Value() (driver.Value, error) {
	return json.Marshal(s)
}

The check in CheckNamedValue will consider this to have Kind() of reflect.Map, and return nil instead of ErrSkip.

This results in Value() never being called.

Is it reasonable to prefer Value() over the default type encoding rules? I had a quick search and found a very similar issue on the Spanner driver: googleapis/go-sql-spanner#135

Here's a full reproducing example

package main

import (
	"context"
	"database/sql"
	"database/sql/driver"
	"encoding/json"
	"fmt"

	_ "github.com/duckdb/duckdb-go/v2"
)

func main() {
	ctx := context.Background()

	db, err := sql.Open("duckdb", "")
	noError(err)

	_, err = db.ExecContext(ctx, `CREATE TABLE data(x JSON);`)
	noError(err)

	_, err = db.ExecContext(ctx,
		`INSERT INTO data(x) VALUES ($1);`,
		somethingCustom{"a": 1},
	)
	noError(err)

	row := db.QueryRowContext(ctx, `SELECT * FROM data;`)
	noError(row.Err())
	var x any
	noError(row.Scan(&x))

	fmt.Printf("%#v", x)
}

type somethingCustom map[string]int

func (s somethingCustom) Value() (driver.Value, error) {
	return json.Marshal(s)
}

func noError(err error) {
	if err != nil {
		panic(err)
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions