Skip to content

Commit

Permalink
List Products DB calls reduced. TotalRecords variable added to Produc…
Browse files Browse the repository at this point in the history
…t structure for help in same. Changes made accordingly to Filters and Search API,so this is highly unstable version. In Response.go StatusBadRequest changed to status.
  • Loading branch information
santoshkavhar committed Oct 9, 2020
1 parent eb7518c commit 72f8370
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 31 deletions.
2 changes: 1 addition & 1 deletion db/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
)

type Storer interface {
ListProducts(context.Context, int, int) (int, []Product, error)
ListProducts(context.Context, int, int) ([]Product, error)
FilteredProducts(context.Context, Filter, string, string) (int, []Product, error)
SearchProductsByText(context.Context, string, string, string) (int, []Product, error)
CreateProduct(context.Context, Product, []*multipart.FileHeader) (Product, error)
Expand Down
3 changes: 1 addition & 2 deletions db/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,13 +193,12 @@ func (s *pgStore) SearchProductsByText(ctx context.Context, text string, limitSt

// countResult set should have only 1 record
// It counts the number of records with the search results.
for countResult.Next() {
if countResult.Next() {
err = countResult.Scan(&totalRecords)
if err != nil {
logger.WithField("err", err.Error()).Error("Error fetching count of getSearchCount from database")
return 0, []Product{}, err
}
break
}

offset, _ := strconv.Atoi(offsetStr)
Expand Down
44 changes: 26 additions & 18 deletions db/product.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ import (
)

const (
getProductCount = `SELECT count(id) from Products ;`
getProductQuery = `SELECT * FROM products p INNER JOIN category c ON p.cid = c.cid ORDER BY p.id LIMIT $1 OFFSET $2 ;`
getProductCount = `SELECT count(id) from Products ;`
getProductQuery = `SELECT count(*) OVER() AS total,* FROM products p
INNER JOIN category c ON p.cid = c.cid ORDER BY p.id LIMIT $1 OFFSET $2 ;`
//SELECT * FROM products p INNER JOIN category c ON p.cid = c.cid ORDER BY p.id LIMIT $1 OFFSET $2 ;`
getProductByIDQuery = `SELECT * FROM products p INNER JOIN category c ON p.cid = c.cid WHERE p.id=$1`
insertProductQuery = `INSERT INTO products ( name, description,
price, discount, tax, quantity, cid, brand, color, size, image_urls) VALUES (
Expand All @@ -28,7 +30,8 @@ const (
deleteProductIdQuery = `DELETE FROM products WHERE id = $1 RETURNING image_urls`
//updateProductStockQuery = `UPDATE products SET quantity= $1 where id = $2 `
updateProductStockQuery = `UPDATE products SET quantity= (quantity - $1) where id = $2
RETURNING *, (SELECT cname from category where cid=(SELECT cid FROM products where id = $2))`
RETURNING *,(SELECT cname from category where cid=
(SELECT cid FROM products where id = $2))`
updateProductQuery = `UPDATE products SET name= :name, description=:description, price=:price,
discount=:discount, tax=:tax, quantity=:quantity, cid=:cid, brand=:brand,
color=:color, size=:size, image_urls=:image_urls WHERE id = :id
Expand All @@ -49,6 +52,7 @@ type Product struct {
Color string `db:"color" json:"color,*" schema:"color,*"`
Size string `db:"size" json:"size,*" schema:"size,*"`
URLs pq.StringArray `db:"image_urls" json:"image_urls,*" schema:"images"`
TotalRecords int `db:"total" json:"-"`
}

// Pagination helps to return UI side with number of pages given a limitStr and pageStr number from Query Parameters
Expand Down Expand Up @@ -179,30 +183,34 @@ func (s *pgStore) GetProductByID(ctx context.Context, id int) (Product, error) {
// @Description Get limited number of Products of particular pageStr
// @Params req.Context , limitStr, pageStr
// @Returns Count of Records, error if any
func (s *pgStore) ListProducts(ctx context.Context, limit int, offset int) (int, []Product, error) {
func (s *pgStore) ListProducts(ctx context.Context, limit int, offset int) ([]Product, error) {

var totalRecords int
var products []Product

err := s.db.QueryRow(getProductCount).Scan(&totalRecords)
result, err := s.db.Queryx(getProductQuery, limit, offset)
if err != nil {
logger.WithField("err", err.Error()).Error("Error fetching Count of Products from database")
return 0, []Product{}, err
logger.WithField("err", err.Error()).Error("Error fetching Products from database")
return []Product{}, err
}
for result.Next() {
var product Product
err = result.StructScan(&product)
if err != nil {
logger.WithField("err", err.Error()).Error("Error scanning Products from database")
return []Product{}, err
}
products = append(products, product)
}
//fmt.Println(products)

if totalRecords-1 < offset {
err = fmt.Errorf("Page out of Range!")
if len(products) > 0 && products[0].TotalRecords-1 >= offset {
return products, nil
} else {
err = fmt.Errorf("Page out of Range or No Records Present!")
logger.WithField("err", err.Error()).Error("Error Offset is greater than total records")
return 0, []Product{}, err

return []Product{}, err
}

err = s.db.Select(&products, getProductQuery, limit, offset)
if err != nil {
logger.WithField("err", err.Error()).Error("Error fetching Product Ids from database")
return 0, []Product{}, err
}
return totalRecords, products, nil
}

func (s *pgStore) CreateProduct(ctx context.Context, product Product, images []*multipart.FileHeader) (Product, error) {
Expand Down
15 changes: 9 additions & 6 deletions service/filters_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,27 +174,30 @@ func getProductBySearchHandler(deps Dependencies) http.HandlerFunc {
offsetStr := strconv.Itoa(offset)
if text == "" {
// Behave same as List All Products and return
totalRecords, products, err = deps.Store.ListProducts(req.Context(), limit, offset)
if err != nil {
logger.WithField("err", err.Error()).Error("Error Fetching Product details or Page out of range")
Message := "Couldn't find any Product records or Page out of range"
products, err = deps.Store.ListProducts(req.Context(), limit, offset)

if err != nil || products[0].TotalRecords == 0 {
logger.WithField("err", err.Error()).Error("Error Couldn't find any Product records or Page out of range")
Message := "Couldn't find any Products records or Page out of range"
responseMsg(rw, http.StatusBadRequest, Message)
return
}
goto Skip
}

totalRecords, products, err = deps.Store.SearchProductsByText(req.Context(), text, limitStr, offsetStr)
if err != nil {
if err != nil || totalRecords == 0 {
logger.WithField("err", err.Error()).Error("Error Couldn't find any matching search records or Page out of range")
Message := "Couldn't find any matching search records or Page out of range"
responseMsg(rw, http.StatusBadRequest, Message)
return
} else {
products[0].TotalRecords = totalRecords
}

Skip:
var pagination db.Pagination
pagination.TotalPages = int(math.Ceil(float64(totalRecords) / float64(limit)))
pagination.TotalPages = int(math.Ceil(float64(products[0].TotalRecords) / float64(limit)))
pagination.Products = products
response(rw, http.StatusOK, pagination)
return
Expand Down
7 changes: 4 additions & 3 deletions service/product_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,17 @@ func listProductsHandler(deps Dependencies) http.HandlerFunc {
return
}
offset := (page - 1) * limit
totalRecords, products, err := deps.Store.ListProducts(req.Context(), limit, offset)
if err != nil {
products, err := deps.Store.ListProducts(req.Context(), limit, offset)

if err != nil || products[0].TotalRecords == 0 {
logger.WithField("err", err.Error()).Error("Error Couldn't find any Product records or Page out of range")
Message := "Couldn't find any Products records or Page out of range"
responseMsg(rw, http.StatusInternalServerError, Message)
return
}

var pagination db.Pagination
pagination.TotalPages = int(math.Ceil(float64(totalRecords) / float64(limit)))
pagination.TotalPages = int(math.Ceil(float64(products[0].TotalRecords) / float64(limit)))
pagination.Products = products
response(rw, http.StatusOK, pagination)
return
Expand Down
2 changes: 1 addition & 1 deletion service/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type messageObject struct {
}

func responseMsg(rw http.ResponseWriter, status int, msgbody string) {
response(rw, http.StatusBadRequest, errorResponse{
response(rw, status, errorResponse{
Error: messageObject{
Message: msgbody,
},
Expand Down

0 comments on commit 72f8370

Please sign in to comment.