Skip to content

release: v0.20.1 - #67

Merged
kolkov merged 5 commits into
mainfrom
fix/v0.20.1
Oct 27, 2026
Merged

kolkov merged 5 commits into
mainfrom
fix/v0.20.1

Conversation

@kolkov

@kolkov kolkov commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

Release v0.20.1. Full list: CHANGELOG [0.20.1].

Fixes #47

  • Batch upsert from structs: db.BatchInsert(table, nil).ValuesStructs(rows).OnConflict(...).DoUpdateAll() builds one multi-row INSERT … ON CONFLICT (ON DUPLICATE KEY UPDATE on MySQL) from a slice of structs, read like BatchInsertStruct. Reachable through Executor.BatchInsert; BatchInsertStruct is built on it.
  • Bind-parameter limit: a batch with more parameters than one statement takes (65535 on PostgreSQL and MySQL, 32766 on SQLite) is an error before anything is sent, naming the rows per statement that fit. Relica does not split the batch or open a transaction on its own; the docs show the explicit way (slices inside Transactional). In a transaction on MySQL/PostgreSQL the driver may interpolate, so the check is left to it there.
  • Fixes: BatchInsertStruct with rows of two struct types wrote NULL, and an empty autoid field was inserted as "" — both are errors now. The audit script's Where check (V4) missed Update/Delete with a non-literal table. AGENTS.md batch examples did not compile.

Verification (local): build, vet, gofmt, unit tests, golangci-lint (root and test/), linux/darwin builds, audit_test.sh, SQLite integration suite; the new batch tests also on PostgreSQL and MySQL, including a batch exactly at the limit and one row over it. Each fix came with a test that failed on v0.20.0.

…not a literal

V4 matched only Update("t")/Delete("t"), so db.Delete(table).Execute() in a
loop over table names (gode's schema reset) or Update(tableName(x)) went
unreported and the v0.20.0 error surfaced at run time. The table argument may
now be a literal, a variable or one call; Delete(ctx, id) and Model(m).Delete()
still do not match. Fixture cases first (failed on the old audit: V4 4, want 6);
gawk and mawk PASS. plugin.json 0.20.1 for the [Unreleased] section.
…d-parameter limit is a build error (#47)

BatchInsertQuery.ValuesStructs(rows) adds rows from a slice of structs of one
type, read like BatchInsertStruct, so OnConflict/DoUpdate/DoUpdateAll/DoNothing
work for structs; reachable through Executor.BatchInsert. With nil columns the
columns come from the struct and it is the only row source; with listed columns
exactly those are read and a listed primary key must not be zero.
BatchInsertStruct is built on it.

A batch with more bind parameters than one statement takes (65535 on
PostgreSQL/MySQL, 32766 on SQLite) is an error before anything is sent, naming
the rows per statement that fit. Relica does not split it or open a
transaction: a query builder sends what the code says (design debated with two
reviews; auto-chunking with a hidden transaction/savepoint was rejected). In a
transaction on MySQL/PostgreSQL the driver may interpolate, so the check is
left to it there.

Also fixed: rows of two struct types wrote NULL; an empty autoid field was
inserted as an empty string; AGENTS.md batch examples did not compile.
Tests: unit (fail on v0.20.0 for the limit and mixed types), integration on
PostgreSQL, MySQL, SQLite incl. the exact limit and split batches in
Transactional.
…toid check covers named string types

Review of 46c8bb5: the docs said a nil-column ValuesStructs must be the only
row source, but Values/ValuesMap were still accepted after it, and derived
columns are sorted, so a positional row landed in the wrong columns. The empty
autoid check matched only a plain string; Model generates IDs for any string
kind (type NodeID string), so the batch guard now does the same. Tests failed
before the fix. Godoc warns that DoUpdateAll with a carried primary key and a
non-key conflict target overwrites the key; the limit error text is ASCII.
argValue passes such a field as a pointer to a copy, so the check missed it;
it now looks through the pointer. Test failed before the fix.
CHANGELOG [Unreleased] -> [0.20.1] - 2026-10-27; ROADMAP current state.
@codecov

codecov Bot commented Oct 27, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.40000% with 12 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/core/struct_ops.go 91.66% 4 Missing and 4 partials ⚠️
db.go 0.00% 3 Missing ⚠️
internal/core/builder.go 96.15% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@kolkov
kolkov merged commit d9bd550 into main Oct 27, 2026
12 checks passed
@kolkov
kolkov deleted the fix/v0.20.1 branch October 27, 2026 08:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: BatchUpsert / BatchUpsertStruct for multi-row INSERT ON CONFLICT

1 participant