From 56ce9fb2ea15062cb8208af57a089b6303efd363 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 19 Sep 2024 20:40:27 +0530 Subject: [PATCH] fixed account query to change the updateAccount func --- db/query/account.sql | 37 ++++++++++++---- db/sqlc/account.sql.go | 95 +++++++++++++++++++++++++++++++++++------ db/sqlc/db.go | 2 +- db/sqlc/entry.sql.go | 2 +- db/sqlc/models.go | 2 +- db/sqlc/store.go | 35 +++++++++++++++ db/sqlc/transfer.sql.go | 2 +- 7 files changed, 148 insertions(+), 27 deletions(-) diff --git a/db/query/account.sql b/db/query/account.sql index 72c46b5..346d303 100644 --- a/db/query/account.sql +++ b/db/query/account.sql @@ -1,21 +1,40 @@ -- name: CreateAccount :one -insert into accounts( +INSERT INTO accounts ( owner, balance, currency -)values( -$1,$2,$3 +) VALUES ( + $1, $2, $3 ) RETURNING *; - -- name: GetAccount :one -select * from accounts where id=$1 limit 1; +SELECT * FROM accounts +WHERE id = $1 LIMIT 1; + +-- name: GetAccountForUpdate :one +SELECT * FROM accounts +WHERE id = $1 LIMIT 1 +FOR NO KEY UPDATE; -- name: ListAccounts :many -select * from accounts order by id limit $1 offset 2; +SELECT * FROM accounts +WHERE owner = $1 +ORDER BY id +LIMIT $2 +OFFSET $3; + +-- name: UpdateAccount :one +UPDATE accounts +SET balance = $2 +WHERE id = $1 +RETURNING *; --- name: UpdateAccount :exec -update accounts set balance= $2 where id =$1; +-- name: AddAccountBalance :one +UPDATE accounts +SET balance = balance + sqlc.arg(amount) +WHERE id = sqlc.arg(id) +RETURNING *; -- name: DeleteAccount :exec -delete from accounts where id = $1; \ No newline at end of file +DELETE FROM accounts +WHERE id = $1; \ No newline at end of file diff --git a/db/sqlc/account.sql.go b/db/sqlc/account.sql.go index 51c54ef..98057ab 100644 --- a/db/sqlc/account.sql.go +++ b/db/sqlc/account.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.26.0 +// sqlc v1.27.0 // source: account.sql package db @@ -9,13 +9,38 @@ import ( "context" ) +const addAccountBalance = `-- name: AddAccountBalance :one +UPDATE accounts +SET balance = balance + $1 +WHERE id = $2 +RETURNING id, owner, balance, currency, created_at +` + +type AddAccountBalanceParams struct { + Amount int64 `json:"amount"` + ID int64 `json:"id"` +} + +func (q *Queries) AddAccountBalance(ctx context.Context, arg AddAccountBalanceParams) (Account, error) { + row := q.db.QueryRowContext(ctx, addAccountBalance, arg.Amount, arg.ID) + var i Account + err := row.Scan( + &i.ID, + &i.Owner, + &i.Balance, + &i.Currency, + &i.CreatedAt, + ) + return i, err +} + const createAccount = `-- name: CreateAccount :one -insert into accounts( +INSERT INTO accounts ( owner, balance, currency -)values( -$1,$2,$3 +) VALUES ( + $1, $2, $3 ) RETURNING id, owner, balance, currency, created_at ` @@ -39,7 +64,8 @@ func (q *Queries) CreateAccount(ctx context.Context, arg CreateAccountParams) (A } const deleteAccount = `-- name: DeleteAccount :exec -delete from accounts where id = $1 +DELETE FROM accounts +WHERE id = $1 ` func (q *Queries) DeleteAccount(ctx context.Context, id int64) error { @@ -48,7 +74,8 @@ func (q *Queries) DeleteAccount(ctx context.Context, id int64) error { } const getAccount = `-- name: GetAccount :one -select id, owner, balance, currency, created_at from accounts where id=$1 limit 1 +SELECT id, owner, balance, currency, created_at FROM accounts +WHERE id = $1 LIMIT 1 ` func (q *Queries) GetAccount(ctx context.Context, id int64) (Account, error) { @@ -64,12 +91,41 @@ func (q *Queries) GetAccount(ctx context.Context, id int64) (Account, error) { return i, err } +const getAccountForUpdate = `-- name: GetAccountForUpdate :one +SELECT id, owner, balance, currency, created_at FROM accounts +WHERE id = $1 LIMIT 1 +FOR NO KEY UPDATE +` + +func (q *Queries) GetAccountForUpdate(ctx context.Context, id int64) (Account, error) { + row := q.db.QueryRowContext(ctx, getAccountForUpdate, id) + var i Account + err := row.Scan( + &i.ID, + &i.Owner, + &i.Balance, + &i.Currency, + &i.CreatedAt, + ) + return i, err +} + const listAccounts = `-- name: ListAccounts :many -select id, owner, balance, currency, created_at from accounts order by id limit $1 offset 2 +SELECT id, owner, balance, currency, created_at FROM accounts +WHERE owner = $1 +ORDER BY id +LIMIT $2 +OFFSET $3 ` -func (q *Queries) ListAccounts(ctx context.Context, limit int32) ([]Account, error) { - rows, err := q.db.QueryContext(ctx, listAccounts, limit) +type ListAccountsParams struct { + Owner string `json:"owner"` + Limit int32 `json:"limit"` + Offset int32 `json:"offset"` +} + +func (q *Queries) ListAccounts(ctx context.Context, arg ListAccountsParams) ([]Account, error) { + rows, err := q.db.QueryContext(ctx, listAccounts, arg.Owner, arg.Limit, arg.Offset) if err != nil { return nil, err } @@ -97,8 +153,11 @@ func (q *Queries) ListAccounts(ctx context.Context, limit int32) ([]Account, err return items, nil } -const updateAccount = `-- name: UpdateAccount :exec -update accounts set balance= $2 where id =$1 +const updateAccount = `-- name: UpdateAccount :one +UPDATE accounts +SET balance = $2 +WHERE id = $1 +RETURNING id, owner, balance, currency, created_at ` type UpdateAccountParams struct { @@ -106,7 +165,15 @@ type UpdateAccountParams struct { Balance int64 `json:"balance"` } -func (q *Queries) UpdateAccount(ctx context.Context, arg UpdateAccountParams) error { - _, err := q.db.ExecContext(ctx, updateAccount, arg.ID, arg.Balance) - return err +func (q *Queries) UpdateAccount(ctx context.Context, arg UpdateAccountParams) (Account, error) { + row := q.db.QueryRowContext(ctx, updateAccount, arg.ID, arg.Balance) + var i Account + err := row.Scan( + &i.ID, + &i.Owner, + &i.Balance, + &i.Currency, + &i.CreatedAt, + ) + return i, err } diff --git a/db/sqlc/db.go b/db/sqlc/db.go index 17d86e9..41b7a34 100644 --- a/db/sqlc/db.go +++ b/db/sqlc/db.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.26.0 +// sqlc v1.27.0 package db diff --git a/db/sqlc/entry.sql.go b/db/sqlc/entry.sql.go index ce71497..c751ceb 100644 --- a/db/sqlc/entry.sql.go +++ b/db/sqlc/entry.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.26.0 +// sqlc v1.27.0 // source: entry.sql package db diff --git a/db/sqlc/models.go b/db/sqlc/models.go index 2ec02f8..01ba9c0 100644 --- a/db/sqlc/models.go +++ b/db/sqlc/models.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.26.0 +// sqlc v1.27.0 package db diff --git a/db/sqlc/store.go b/db/sqlc/store.go index 961814e..d317cc9 100644 --- a/db/sqlc/store.go +++ b/db/sqlc/store.go @@ -60,6 +60,8 @@ func (store *Store) TransferTX(ctx context.Context, arg TransferTXParams) (Trans err := store.execTX(ctx, func(q *Queries) error { var err error + + // create transfer record result.Transfer, err = q.CreateTransfer(ctx, CreateTransferParams{ FromAccountID: arg.FromAccountID, ToAccountID: arg.ToAccountID, @@ -68,6 +70,8 @@ func (store *Store) TransferTX(ctx context.Context, arg TransferTXParams) (Trans if err != nil { return err } + + // substract money from 'Fromaccount/senders account' result.FromEntry, err = q.CreateEntry(ctx, CreateEntryParams{ AccountID: arg.FromAccountID, Amount: -arg.Amount, @@ -75,6 +79,8 @@ func (store *Store) TransferTX(ctx context.Context, arg TransferTXParams) (Trans if err != nil { return err } + + // Add money to 'ToAccount/reciever's account' result.ToEntry, err = q.CreateEntry(ctx, CreateEntryParams{ AccountID: arg.ToAccountID, Amount: arg.Amount, @@ -82,8 +88,37 @@ func (store *Store) TransferTX(ctx context.Context, arg TransferTXParams) (Trans if err != nil { return err } + // TODO: create update account and implement locking mechanism to handle deadlock + // transfer/move money from account 1 + account1, err := q.GetAccount(ctx, arg.FromAccountID) + if err != nil { + return nil + } + + result.FromAccount, err = q.UpdateAccount(ctx, UpdateAccountParams{ + ID: arg.FromAccountID, + Balance: account1.Balance - arg.Amount, + }) + if err != nil { + return err + } + + // add money to account 2 + account2, err := q.GetAccount(ctx, arg.FromAccountID) + if err != nil { + return nil + } + + result.ToAccount, err = q.UpdateAccount(ctx, UpdateAccountParams{ + ID: arg.ToAccountID, + Balance: account2.Balance + arg.Amount, + }) + if err != nil { + return err + } + return nil }) return result, err diff --git a/db/sqlc/transfer.sql.go b/db/sqlc/transfer.sql.go index 3b2a92a..59c6dfb 100644 --- a/db/sqlc/transfer.sql.go +++ b/db/sqlc/transfer.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.26.0 +// sqlc v1.27.0 // source: transfer.sql package db