Your first query
A tasks table and three queries; a sequence supplies the ids, RETURNING hands back the new row, and BOOLEAN and TIMESTAMP arrive as bool and time.Time.
24 examples, in learning order. DuckDB's driver needs cgo, so the stock sgl generates code only: migrate from your own program or a custom sgl build.
A tasks table and three queries; a sequence supplies the ids, RETURNING hands back the new row, and BOOLEAN and TIMESTAMP arrive as bool and time.Time.
A ferry timetable whose Params structs take their field names from inserted and compared columns, binding lines and named placeholders.
Ringed gulls and their sightings, where a nullable column, a LEFT JOIN and MAX give pointers while COALESCE and COUNT do not.
One landing of fish read back column by column, printing the Go type each DuckDB column type became, from unsigned and 128-bit integers to UUIDs.
Chip shop orders kept as JSON documents, read into the generated JSON type and searched with -> and ->>.
A chip shop menu with two DuckDB enum columns, read back as the named enum types Seagull generates and, through a SQL type override and sgl.column, as the shop's own Go types.
Fishing voyages with VARCHAR[] and INTEGER[] list columns read back as typed Go slices, searched with ANY and grouped with array_agg.
Beach huts found and booked by passing Go slices to IN lists, including an empty slice and a slice after a scalar.
One boat trip search run four ways, where each optional filter is a pointer field and a nil pointer switches its filter off.
Regatta entries listed in the order a caller picks from generated constants, with raw text adding no ORDER BY at all.
Rock pool finds read a page at a time, with a default and a maximum page size, then searched with an optional filter and a page.
Unclaimed lost property searched with filters, an order, a limit and a count chosen at run time, with unsafe columns, operators and directions refused.
Boats read with their harbour as a nested value through an INNER JOIN and their skipper as a nil-able pointer through a LEFT JOIN.
Chip shop orders collapsed from a LEFT JOIN into one row each, with their lines as a slice, by group_by.
Tide gauge readings ranged over one row at a time with a range-over-func iterator, once to the end and once stopping early.
Gulls ringed with INSERT ... ON CONFLICT DO NOTHING RETURNING and looked up by ring, both reporting a missing row as ok false.
A gull colony read through a recursive CTE, a CTE feeding RANK and SUM window functions, and a view, with types and nullability carried through each.
INSERT, UPDATE and DELETE with RETURNING, declared as one or many, hand back the rows they wrote, defaults and computed values included.
INSERT ... ON CONFLICT DO UPDATE adds to an existing row through excluded and returns the result; DO NOTHING with execrows reports whether the insert happened.
A batch query takes a slice of Params and writes it as multi-row INSERTs, 16383 four-column rows a statement to stay under 65535 bind variables.
RunInTx commits a transfer when its function returns nil and rolls it back on an error, and WithTx binds the queries to a transaction you begin yourself.
The migration files are embedded in the binary, and each start-up runs migrate.NewMigrator with the DuckDB backend and Up, which applies only what the database lacks.
Marina boats with STRUCT, MAP, LIST and UNION columns, written from typed Go structs, maps and slices, read back whole, and reached into with subscripts and map_keys for typed results.
A week of fish landings analysed with QUALIFY, FILTER, PIVOT, a scalar macro, a table macro and read_parquet over a price list the program writes with COPY TO.
Some ideas belong to other engines, and some need a feature DuckDB does not have. Each one says why, and where to read it instead.
Not written for DuckDB yet.
See it on SQLite →