diff --git a/isucari/webapp/go/categories.go b/isucari/webapp/go/categories.go new file mode 100644 index 0000000..00a2fa5 --- /dev/null +++ b/isucari/webapp/go/categories.go @@ -0,0 +1,58 @@ +package main + +import ( + "database/sql" + "log" + + "github.com/jmoiron/sqlx" +) + +var allCategories []Category +var categoryByID map[int]Category +var childCategories map[int][]int + +func loadCategories() { + err := dbx.Select(&allCategories, "SELECT * FROM categories") + if err != nil { + log.Fatal(err) + } + + categoryByID = make(map[int]Category, len(allCategories)) + childCategories = make(map[int][]int) + for _, c := range allCategories { + categoryByID[c.ID] = c + } + + for _, c := range categoryByID { + if c.ParentID > 0 { + c.ParentCategoryName = categoryByID[c.ParentID].CategoryName + } + categoryByID[c.ID] = c + + var children []int + for _, child := range categoryByID { + if child.ParentID == c.ID { + children = append(children, child.ID) + } + } + if len(children) > 0 { + childCategories[c.ID] = children + } + } +} + +func getCategoryByID(_ sqlx.Queryer, id int) (Category, error) { + c, ok := categoryByID[id] + if !ok { + return Category{}, sql.ErrNoRows + } + return c, nil +} + +func getChildCategories(parent int) []int { + return childCategories[parent] +} + +func getAllCategories() []Category { + return allCategories +} diff --git a/isucari/webapp/go/main.go b/isucari/webapp/go/main.go index 44617cc..381acde 100755 --- a/isucari/webapp/go/main.go +++ b/isucari/webapp/go/main.go @@ -336,6 +336,8 @@ func main() { db.SetMaxIdleConns(512) db.SetMaxOpenConns(512) + loadCategories() + mux := goji.NewMux() // API @@ -424,18 +426,6 @@ func getUserSimpleByID(q sqlx.Queryer, userID int64) (userSimple UserSimple, err return userSimple, err } -func getCategoryByID(q sqlx.Queryer, categoryID int) (category Category, err error) { - err = sqlx.Get(q, &category, "SELECT * FROM `categories` WHERE `id` = ?", categoryID) - if category.ParentID != 0 { - parentCategory, err := getCategoryByID(q, category.ParentID) - if err != nil { - return category, err - } - category.ParentCategoryName = parentCategory.CategoryName - } - return category, err -} - func getConfigByName(ctx context.Context, name string) (string, error) { config := Config{} err := dbx.GetContext(ctx, &config, "SELECT * FROM `configs` WHERE `name` = ?", name) @@ -627,13 +617,7 @@ func getNewCategoryItems(w http.ResponseWriter, r *http.Request) { return } - var categoryIDs []int - err = dbx.SelectContext(r.Context(), &categoryIDs, "SELECT id FROM `categories` WHERE parent_id=?", rootCategory.ID) - if err != nil { - log.Print(err) - outputErrorMsg(w, http.StatusInternalServerError, "db error") - return - } + categoryIDs := getChildCategories(rootCategory.ID) query := r.URL.Query() itemIDStr := query.Get("item_id") @@ -702,19 +686,12 @@ func getNewCategoryItems(w http.ResponseWriter, r *http.Request) { userIdUnique := make(map[int64]struct{}) var userIds []interface{} - categoryIdsUnique := make(map[int]struct{}) - var categoryIds []interface{} for _, i := range items { id := i.SellerID if _, ok := userIdUnique[id]; !ok { userIds = append(userIds, id) userIdUnique[id] = struct{}{} } - catID := i.CategoryID - if _, ok := categoryIdsUnique[catID]; !ok { - categoryIds = append(categoryIds, catID) - categoryIdsUnique[catID] = struct{}{} - } } var users map[int64]UserSimple if len(userIds) > 0 { @@ -740,32 +717,6 @@ func getNewCategoryItems(w http.ResponseWriter, r *http.Request) { } } } - var categories map[int]Category - if len(categoryIds) > 0 { - query, args, err := sqlx.In("SELECT * FROM `categories` WHERE `id` IN (?)", categoryIds) - if err != nil { - log.Print(err) - outputErrorMsg(w, http.StatusInternalServerError, "db error") - return - } - var s []Category - err = dbx.SelectContext(r.Context(), &s, query, args...) - if err != nil { - log.Print(err) - outputErrorMsg(w, http.StatusInternalServerError, "db error") - return - } - categories = make(map[int]Category, len(s)) - for _, c := range s { - if c.ParentID > 0 { - p, err := getCategoryByID(dbx, c.ParentID) - if err == nil { - c.ParentCategoryName = p.CategoryName - } - } - categories[c.ID] = c - } - } itemSimples := []ItemSimple{} for _, item := range items { @@ -774,7 +725,7 @@ func getNewCategoryItems(w http.ResponseWriter, r *http.Request) { outputErrorMsg(w, http.StatusNotFound, "seller not found") return } - category, ok := categories[item.CategoryID] + category, ok := categoryByID[item.CategoryID] if !ok { outputErrorMsg(w, http.StatusNotFound, "category not found") return @@ -997,8 +948,6 @@ func getTransactions(w http.ResponseWriter, r *http.Request) { itemIDs := make([]interface{}, 0, len(items)) userIdUnique := make(map[int64]struct{}) var userIds []interface{} - categoryIdsUnique := make(map[int]struct{}) - var categoryIds []interface{} for _, i := range items { itemIDs = append(itemIDs, i.ID) id := i.SellerID @@ -1011,11 +960,6 @@ func getTransactions(w http.ResponseWriter, r *http.Request) { userIds = append(userIds, id) userIdUnique[id] = struct{}{} } - catID := i.CategoryID - if _, ok := categoryIdsUnique[catID]; !ok { - categoryIds = append(categoryIds, catID) - categoryIdsUnique[catID] = struct{}{} - } } var users map[int64]UserSimple if len(userIds) > 0 { @@ -1043,34 +987,6 @@ func getTransactions(w http.ResponseWriter, r *http.Request) { } } } - var categories map[int]Category - if len(categoryIds) > 0 { - query, args, err := sqlx.In("SELECT * FROM `categories` WHERE `id` IN (?)", categoryIds) - if err != nil { - log.Print(err) - outputErrorMsg(w, http.StatusInternalServerError, "db error") - tx.Rollback() - return - } - var s []Category - err = tx.SelectContext(r.Context(), &s, query, args...) - if err != nil { - log.Print(err) - outputErrorMsg(w, http.StatusInternalServerError, "db error") - tx.Rollback() - return - } - categories = make(map[int]Category, len(s)) - for _, c := range s { - if c.ParentID > 0 { - p, err := getCategoryByID(tx, c.ParentID) - if err == nil { - c.ParentCategoryName = p.CategoryName - } - } - categories[c.ID] = c - } - } var transactionEvidences map[int64]TransactionEvidence if len(itemIDs) > 0 { query, args, err := sqlx.In("SELECT c.item_id AS item_id, c.status AS status, s.reserve_id AS reserve_id FROM `transaction_evidences` c LEFT JOIN shippings s ON s.transaction_evidence_id = c.id WHERE c.`item_id` IN (?) ", itemIDs) @@ -1137,7 +1053,7 @@ func getTransactions(w http.ResponseWriter, r *http.Request) { tx.Rollback() return } - category, ok := categories[item.CategoryID] + category, ok := categoryByID[item.CategoryID] if !ok { outputErrorMsg(w, http.StatusNotFound, "category not found") tx.Rollback() @@ -2354,15 +2270,7 @@ func getSettings(w http.ResponseWriter, r *http.Request) { ress.PaymentServiceURL = getPaymentServiceURL(r.Context()) - categories := []Category{} - - err := dbx.SelectContext(r.Context(), &categories, "SELECT * FROM `categories`") - if err != nil { - log.Print(err) - outputErrorMsg(w, http.StatusInternalServerError, "db error") - return - } - ress.Categories = categories + ress.Categories = getAllCategories() w.Header().Set("Content-Type", "application/json;charset=utf-8") json.NewEncoder(w).Encode(ress)