gdb: add RETURNING clause support for INSERT/UPDATE/DELETE operations
Is your feature request related to a problem?
Option Yes
Describe the solution you'd like
Add generic RETURNING clause support for INSERT/UPDATE/DELETE operations in gdb, allowing users to retrieve data from modified rows in a single database round-trip.
Proposed API
// Basic RETURNING with specific fields result, err := db.Model("users").Data(data).Returning("id", "created_at").Insert()
// RETURNING all fields result, err := db.Model("users").Data(data).ReturningAll().Insert()
// Access returned records via type assertion if rr, ok := result.(gdb.ReturningResult); ok { records := rr.GetRecords() // records contains the returned rows }
// Convenience methods with automatic scanning var user User err := db.Model("users").Data(data).InsertAndScan(&user)
var users []User err := db.Model("users").Data(data).Where("status", "active").UpdateAndScan(&users)
var deleted User err := db.Model("users").Where("id", 1).DeleteAndScan(&deleted)
Database Support
| Database | Support Level |
|---|---|
| PostgreSQL | Full support for INSERT/UPDATE/DELETE |
| SQLite | Supported since version 3.35.0 (2021-03-12) |
| SQL Server | Via OUTPUT clause |
| MariaDB | Supported since 10.5.0 |
| DaMeng | Full support |
| MySQL | Not supported (silently ignored) |
Implementation Details
- New Interface: ReturningResult extending sql.Result with GetRecords() method
- Context Injection: Pass RETURNING fields via context to drivers
- Driver Support: Implement in pgsql, sqlite, dm drivers
- Convenience Methods: InsertAndScan, UpdateAndScan, DeleteAndScan
Describe alternatives you've considered
- Separate SELECT after INSERT: Requires two database round-trips and potential race conditions
- LastInsertId only: Limited to auto-increment IDs, doesn't support other generated columns (timestamps, UUIDs, etc.)
- Database triggers: Complex to maintain and not portable across databases
Additional
This feature is commonly needed when:
- Getting auto-generated IDs after batch inserts
- Retrieving database-generated timestamps (created_at, updated_at)
- Capturing deleted records for audit logging
- Getting computed column values after updates
Related implementations:
- https://www.postgresql.org/docs/current/dml-returning.html
- https://www.sqlite.org/lang_returning.html