Skip to content
This repository was archived by the owner on Oct 20, 2025. It is now read-only.

Conversation

@taniabogatsch
Copy link
Collaborator

Propagates the changes in duckdb/duckdb#18738 to go-duckdb.

Here is a code snippet on how to do an UPSERT. For more details, check out the new TestAppenderUpsert test.

   // The query appender appends to a custom (intermediate) table, which you can use in a query (like any actual table).
	
// Create the types of your "appender table" (here, `INT` and `UNION`) by using go-duckdb's exported `TypeInfo` functionality.
	intType, err := NewTypeInfo(TYPE_INTEGER)
	varcharType, err := NewTypeInfo(TYPE_VARCHAR)
	memberTypes := []TypeInfo{intType, varcharType}
	memberNames := []string{"num", "str"}
	unionType, err := NewUnionInfo(memberTypes, memberNames)

// Our query - here, we want to do an `UPSERT` on `id`, which is a primary key.
	query = `INSERT INTO test SELECT id, u FROM my_append_tbl ON CONFLICT DO UPDATE SET u = EXCLUDED.u;`
// Our column types - the types you pass to `AppendRow` must be cast-able to this slice.
columnTypes = []TypeInfo{intType, unionType}
// Our optional column names - use this if you use custom column names in your query.
// Same for `my_append_tbl` - you only need this, if you use a custom table name in your query.
columnNames := []string{"id", "u"}

// Create the appender and use it as you would the 'normal' appender.
	aUpsert := NewQueryAppender(&conn, query, columnTypes, "my_append_tbl", columnNames)
	// Append and upsert (flush) two rows.
	err = aUpsert.AppendRow(2, Union{Value: "str2", Tag: "str"})
	err = aUpsert.AppendRow(0, Union{Value: 43, Tag: "num"})
	err = aUpsert.Close()

@taniabogatsch taniabogatsch added the feature / enhancement Code improvements or a new feature label Sep 18, 2025
Copy link
Collaborator

@mlafeldt mlafeldt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM in general 👍 We could improve validation and testing of edge cases though.

@taniabogatsch
Copy link
Collaborator Author

taniabogatsch commented Sep 22, 2025

Thanks for the review, I'll push more testing!

And a design question: Should we have two new API functions (or an additional parameter) to distinguish between the user providing the column types (as we do now), or us inferring them from the first call to AppendRow?

The pro of the first (current) approach is that you can fix in your column types, and then pass values that can be auto-cast (on the Go side) to these. The pro of the second approach is a slimmer API side, and more flexibility for the user. Basically assuming we can take any input types, and create the appender table from them, and let DuckDB's auto-casting do the job for us. And I think to infer the types, we can use existing code from parameter binding, for example.

@mlafeldt
Copy link
Collaborator

Having a second function is a good idea IMO. I'm not familiar with the inference options, but inferTypeId and createValueByReflection look promising.

@taniabogatsch
Copy link
Collaborator Author

I'll move this to draft until we've merged all required changes to infer types. Related PR: #552

@taniabogatsch taniabogatsch marked this pull request as draft September 28, 2025 12:51
# Conflicts:
#	statement_test.go
#	type.go
#	types.go
#	value.go
@taniabogatsch
Copy link
Collaborator Author

I've hit a bit of a "blocker" with type inference here, if no type info slice is provided - if there are NULL values, then we don't really have a way to infer any type. So, my fallback was to use the table description. However, the C API side of that currently only returns the column name... Which means waiting another release cycle, as we need to push duckdb_table_description_get_column_type to the C API 🥲 but, we can move forward and push this PR with an Appender that requires the column types to be provided for now, and then expand on that later. I'll push more tests and then this should be ready to go in.

@taniabogatsch taniabogatsch marked this pull request as ready for review September 30, 2025 07:47
@taniabogatsch taniabogatsch merged commit 09c691f into marcboeker:main Sep 30, 2025
17 checks passed
@taniabogatsch taniabogatsch deleted the query-appender branch September 30, 2025 08:03
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

feature / enhancement Code improvements or a new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants