Skip to content

Commit f0ca42a

Browse files
Add solution for Challenge 13 (#721)
Co-authored-by: go-interview-practice-bot[bot] <230190823+go-interview-practice-bot[bot]@users.noreply.github.com>
1 parent 97db10d commit f0ca42a

File tree

1 file changed

+219
-0
lines changed

1 file changed

+219
-0
lines changed
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
package main
2+
3+
import (
4+
"database/sql"
5+
"errors"
6+
"fmt"
7+
8+
_ "github.com/mattn/go-sqlite3"
9+
)
10+
11+
// Product represents a product in the inventory system
12+
type Product struct {
13+
ID int64
14+
Name string
15+
Price float64
16+
Quantity int
17+
Category string
18+
}
19+
20+
// ProductStore manages product operations
21+
type ProductStore struct {
22+
db *sql.DB
23+
}
24+
25+
// NewProductStore creates a new ProductStore with the given database connection
26+
func NewProductStore(db *sql.DB) *ProductStore {
27+
return &ProductStore{db: db}
28+
}
29+
30+
// InitDB sets up a new SQLite database and creates the products table
31+
func InitDB(dbPath string) (*sql.DB, error) {
32+
// TODO: Open a SQLite database connection
33+
// TODO: Create the products table if it doesn't exist
34+
// The table should have columns: id, name, price, quantity, category
35+
36+
db, err := sql.Open("sqlite3", dbPath)
37+
if err != nil {
38+
return nil, err
39+
}
40+
41+
createTableQuery := ` CREATE TABLE IF NOT EXISTS products (
42+
id INTEGER PRIMARY KEY AUTOINCREMENT,
43+
name TEXT NOT NULL,
44+
price REAL NOT NULL,
45+
quantity INTEGER NOT NULL,
46+
category TEXT NOT NULL
47+
);`
48+
49+
_, err = db.Exec(createTableQuery)
50+
if err != nil {
51+
return nil, err
52+
}
53+
54+
return db, nil
55+
}
56+
57+
// CreateProduct adds a new product to the database
58+
func (ps *ProductStore) CreateProduct(product *Product) error {
59+
// TODO: Insert the product into the database
60+
// TODO: Update the product.ID with the database-generated ID
61+
stmt := `INSERT INTO products (name, price, quantity, category) VALUES(?, ?, ?, ?)`
62+
63+
dbResult, err := ps.db.Exec(stmt, product.Name, product.Price, product.Quantity, product.Category)
64+
if err != nil {
65+
return err
66+
}
67+
68+
id, err := dbResult.LastInsertId()
69+
if err != nil {
70+
return err
71+
}
72+
product.ID = id
73+
74+
return nil
75+
}
76+
77+
// GetProduct retrieves a product by ID
78+
func (ps *ProductStore) GetProduct(id int64) (*Product, error) {
79+
// TODO: Query the database for a product with the given ID
80+
// TODO: Return a Product struct populated with the data or an error if not found
81+
82+
stmt := `SELECT id, name, price, quantity, category FROM products WHERE id = ?`
83+
row := ps.db.QueryRow(stmt, id)
84+
85+
var product Product
86+
err := row.Scan(&product.ID, &product.Name, &product.Price, &product.Quantity, &product.Category)
87+
if err != nil {
88+
if err == sql.ErrNoRows {
89+
return nil, errors.New("product not found")
90+
}
91+
return nil, err
92+
}
93+
94+
return &product, nil
95+
96+
}
97+
98+
// UpdateProduct updates an existing product
99+
func (ps *ProductStore) UpdateProduct(product *Product) error {
100+
// TODO: Update the product in the database
101+
// TODO: Return an error if the product doesn't exist
102+
103+
p, err := ps.GetProduct(product.ID)
104+
if err != nil {
105+
return err
106+
}
107+
108+
p.ID = product.ID
109+
p.Name = product.Name
110+
p.Price = product.Price
111+
p.Quantity = product.Quantity
112+
p.Category = product.Category
113+
114+
stmt := `UPDATE products SET name = ?, price = ?, quantity = ?, category = ? WHERE id = ?`
115+
116+
_, err = ps.db.Exec(stmt, p.Name, p.Price, p.Quantity, p.Category, p.ID)
117+
if err != nil {
118+
return err
119+
}
120+
121+
return nil
122+
123+
}
124+
125+
// DeleteProduct removes a product by ID
126+
func (ps *ProductStore) DeleteProduct(id int64) error {
127+
// TODO: Delete the product from the database
128+
// TODO: Return an error if the product doesn't exist
129+
130+
stmt := `DELETE FROM products WHERE id = ?`
131+
132+
result, err := ps.db.Exec(stmt, id)
133+
if err != nil {
134+
return err
135+
}
136+
137+
rowsAffected, err := result.RowsAffected()
138+
if err != nil {
139+
return err
140+
}
141+
if rowsAffected == 0 {
142+
return errors.New("product not found")
143+
}
144+
145+
return nil
146+
147+
}
148+
149+
// ListProducts returns all products with optional filtering by category
150+
func (ps *ProductStore) ListProducts(category string) ([]*Product, error) {
151+
// TODO: Query the database for products
152+
// TODO: If category is not empty, filter by category
153+
// TODO: Return a slice of Product pointers
154+
stmt := `SELECT id, name, price, quantity, category FROM products
155+
WHERE (? = '' OR category = ?)`
156+
157+
var products []*Product
158+
159+
rows, err := ps.db.Query(stmt, category, category)
160+
if err != nil {
161+
return nil, err
162+
}
163+
164+
defer rows.Close()
165+
166+
for rows.Next() {
167+
var product Product
168+
err := rows.Scan(&product.ID, &product.Name, &product.Price, &product.Quantity, &product.Category)
169+
if err != nil {
170+
return nil, err
171+
}
172+
products = append(products, &product)
173+
}
174+
175+
return products, nil
176+
177+
}
178+
179+
// BatchUpdateInventory updates the quantity of multiple products in a single transaction
180+
func (ps *ProductStore) BatchUpdateInventory(updates map[int64]int) error {
181+
// TODO: Start a transaction
182+
// TODO: For each product ID in the updates map, update its quantity
183+
// TODO: If any update fails, roll back the transaction
184+
// TODO: Otherwise, commit the transaction
185+
186+
tx, err := ps.db.Begin()
187+
if err != nil {
188+
return err
189+
}
190+
191+
defer func() {
192+
if err != nil {
193+
tx.Rollback()
194+
}
195+
}()
196+
197+
stmt := `UPDATE products SET quantity = ? WHERE id = ?`
198+
199+
for productID, newQuantity := range updates {
200+
result, err := tx.Exec(stmt, newQuantity, productID)
201+
if err != nil {
202+
return err
203+
}
204+
205+
rowsAffected, err := result.RowsAffected()
206+
if err != nil {
207+
return err
208+
}
209+
if rowsAffected == 0 {
210+
return fmt.Errorf("product with ID %d not found", productID)
211+
}
212+
213+
}
214+
return tx.Commit()
215+
}
216+
217+
func main() {
218+
// Optional: you can write code here to test your implementation
219+
}

0 commit comments

Comments
 (0)