๐ ๏ธ UpsertBuilder Developer Guide¶
UPSERT (INSERT ON CONFLICT) builder with conflict resolution and dialect safety.
The UpsertBuilder composes SQL INSERT ... ON CONFLICT DO UPDATE/NOTHING statements using a fluent API over an internal InsertBuilder. It ensures safe dialect-specific identifier handling and consistent structure across SQL dialects.
โ Supported Features¶
- INSERT clause via embedded
InsertBuilder - ON CONFLICT clause with configurable conflict columns
- DO UPDATE SET clause using
Assignment{Column, Expr} - DO NOTHING fallback support
- RETURNING clause support
- Dialect-specific identifier quoting via
QuoteIdentifier
๐งฑ Fluent API¶
builder.NewUpsert().
Into("users").
Columns("id", "email").
Values(1, "john@example.com").
OnConflict("id").
DoUpdateSet(
builder.Assignment{Column: "email", Expr: "EXCLUDED.email"},
).
Returning("id").
UseDialect("postgres")
Produces:
INSERT INTO "users" ("id", "email")
VALUES (?, ?)
ON CONFLICT ("id")
DO UPDATE SET "email" = EXCLUDED.email
RETURNING "id"
๐ Dialect Quoting Strategy¶
We enforce identifier-safe quoting using dialect.QuoteIdentifier(name string).
- โ Use for column and table names.
- โ Avoid using raw string formatting for identifiers.
For literal values (used only in debug logs or test output), use:
dialect.QuoteLiteral(value any)
โ ๏ธ This method is NOT SQL-injection safe and MUST NOT be used in query generation.
๐ง Internal Helpers¶
Assignmentstruct is used to define DO UPDATE SET clauses.UseDialect(...)sets the dialect for identifier formatting.WithDialect(...)is deprecated โ useUseDialect(...)instead.
๐ก Naming Convention¶
As a project-wide guideline, we enforce:
- โ
Use of descriptive names (e.g.,
QuoteIdentifier,QuoteLiteral) - โ Avoid abbreviations like
QuoteIdentorEscapeVal
This improves readability, onboarding, and cross-dialect compatibility.
๐ Related Builders¶
โ Summary¶
The UpsertBuilder ensures:
- Dialect-safe identifier usage
- Flexible
ON CONFLICTresolution - Compatibility with Postgres'
RETURNING - Modern and consistent Go API design
Use it when your INSERT logic may result in duplicates and should either update or skip based on conflict rules.¶
๐ง Method Reference (Summary)¶
| Method | Description |
|---|---|
UseDialect |
Sets dialect for escaping identifiers |
Into |
Sets the target table |
Columns |
Declares insert columns |
Values |
Adds value rows for insertion |
OnConflict |
Defines conflict detection columns |
DoUpdateSet |
Assigns updates to apply on conflict |
Returning |
Specifies which columns to return |
Build() |
Compiles the full UPSERT SQL with placeholders |
| --- |
๐งช Test Coverage¶
โ 100% tested, including deprecated behavior.
| Area | Coverage |
|---|---|
Into, Columns, Values |
โ |
OnConflict, DoUpdateSet |
โ |
RETURNING clause |
โ |
Dialect injection (UseDialect) |
โ |
Deprecated WithDialect |
โ |
| Validation rules | โ |
| Clause ordering | โ |
| Dialect-specific quoting | โ |
โ All builder methods and clause behaviors are tested. Even deprecated features like
WithDialect(...)are covered for backward compatibility.