aboutsummaryrefslogtreecommitdiff
path: root/query.go
diff options
context:
space:
mode:
authorStefan Majewsky <majewsky@gmx.net>2026-04-16 21:18:04 +0200
committerStefan Majewsky <majewsky@gmx.net>2026-04-16 21:18:04 +0200
commitd964c2be59a73e6b21ce1a8031fe913588bddf66 (patch)
treed252f968b9b825591854352a073f1d4f1135269b /query.go
parenta646924f1f474aeb5acd3d753cfcb2379dca5210 (diff)
downloadgo-oblast-d964c2be59a73e6b21ce1a8031fe913588bddf66.tar.gz
add Store.Update()
Diffstat (limited to 'query.go')
-rw-r--r--query.go54
1 files changed, 53 insertions, 1 deletions
diff --git a/query.go b/query.go
index 88c2987..41d61c7 100644
--- a/query.go
+++ b/query.go
@@ -105,7 +105,59 @@ func (s Store[R]) Insert(db Handle, records ...R) (returnedRecords []R, returned
return records, nil
}
-// TODO: Store.Update
+// Update executes an SQL UPDATE statement for each of the provided records, updating all non-primary-key columns with the values in the records.
+// Returns [MissingRecordError] if any of the records does not exist in the database, that is, if for any of the records, the database contains no row with the same primary key values.
+//
+// Returns an error if [NewStore] was called without the [TableNameIs] or [PrimaryKeyIs] options, which are both required to generate a query for this method.
+func (s Store[R]) Update(db Handle, records ...R) (returnedError error) {
+ if s.plan.Update.Query == "" {
+ return errors.New("cannot execute Update() because query could not be autogenerated")
+ }
+
+ var (
+ argumentIndexes = s.plan.Update.ArgumentIndexes
+ argumentSlots = make([]any, len(argumentIndexes))
+ )
+
+ var stmt *sql.Stmt
+ if len(records) >= PrepareThreshold {
+ var err error
+ stmt, err = db.Prepare(s.plan.Update.Query)
+ if err != nil {
+ return fmt.Errorf("during Prepare(): %w", err)
+ }
+ defer func() {
+ returnedError = mergeCloseError("Stmt", returnedError, stmt.Close())
+ }()
+ }
+
+ for idx, r := range records {
+ v := reflect.ValueOf(&r).Elem()
+ for idx, index := range argumentIndexes {
+ argumentSlots[idx] = v.FieldByIndex(index).Addr().Interface()
+ }
+ var (
+ result sql.Result
+ err error
+ )
+ if stmt == nil {
+ result, err = db.Exec(s.plan.Update.Query, argumentSlots...)
+ } else {
+ result, err = stmt.Exec(argumentSlots...)
+ }
+ if err != nil {
+ return fmt.Errorf("during Exec() for record with idx = %d: %w", idx, err)
+ }
+ rowsAffected, err := result.RowsAffected()
+ if err != nil {
+ return fmt.Errorf("during RowsAffected() for record with idx = %d: %w", idx, err)
+ }
+ if rowsAffected == 0 {
+ return MissingRecordError[R]{r, s.plan}
+ }
+ }
+ return nil
+}
// Delete executes an SQL DELETE statement for each of the provided records, using their primary keys to locate the respective table rows.
//