package main import ( "context" ) type Category struct { ID int64 `json:"id"` Name string `json:"name"` Subcategories []Subcategory `json:"subcategories"` } type Subcategory struct { ID int64 `json:"id"` Name string `json:"name"` CategoryId int64 `json:"categoryId"` } func getAllCategories() (categories []Category, ok bool) { db := getSQLConnection() defer db.Close() rows, err := db.Query("SELECT * FROM category;") if err != nil { //TODO: log this error return nil, false //panic(err) } defer rows.Close() for rows.Next() { var category Category if err = rows.Scan(&category.ID, &category.Name); err != nil { println(err.Error()) } subcategories, ok := getSubcategories(category.ID) if ok { category.Subcategories = subcategories } categories = append(categories, category) } return categories, true } func insertNewCategory(name string, subcategories []Subcategory) (recordID int64, ok bool) { db := getSQLConnection() defer db.Close() context := context.Background() transaction, err := db.BeginTx(context, nil) if err != nil { println(err.Error()) return 0, false } { statement, err := transaction.Prepare("INSERT INTO category (category_name) VALUES ($1) RETURNING category_id;") if err != nil { transaction.Rollback() println(err.Error()) return 0, false } defer statement.Close() statement.QueryRow(name).Scan(&recordID) if recordID == 0 { transaction.Rollback() println("Failed to get the last record ID") return 0, false } } if len(subcategories) == 0 { transaction.Commit() return recordID, true } { statement, err := transaction.Prepare("INSERT INTO subcategory(subcategory_name, category_id) VALUES($1, $2);") if err != nil { transaction.Rollback() println(err.Error()) return 0, false } defer statement.Close() for _, subcategory := range subcategories { _, err := statement.Exec(subcategory.Name, recordID) if err != nil { transaction.Rollback() println(err.Error()) return 0, false } } } transaction.Commit() return recordID, true } func deleteCategory(id int64) bool { db := getSQLConnection() defer db.Close() _, err := db.Exec("DELETE FROM category WHERE category_id = $1;", id) //TODO: log this if an error happened if err != nil { println(err.Error()) return false } return true } func deleteSubcategory(id int64) bool { db := getSQLConnection() defer db.Close() _, err := db.Exec("DELETE FROM subcategory WHERE subcategory_id = $1;", id) //TODO: log this if an error happened if err != nil { println(err.Error()) return false } return true } func getCategoryByID(id int64) (category Category, ok bool) { db := getSQLConnection() defer db.Close() if err := db.QueryRow("SELECT * FROM category WHERE category_id = $1;", id).Scan(&category.ID, &category.Name); err != nil { return category, false } subcategories, ok := getSubcategories(category.ID) if !ok { //TODO: do something about not getting the subcategories, for now ignore. return category, true } category.Subcategories = subcategories return category, true } func getSubcategories(categoryID int64) (subcategories []Subcategory, ok bool) { db := getSQLConnection() defer db.Close() rows, err := db.Query("SELECT * FROM subcategory WHERE category_id = $1;", categoryID) if err != nil { //TODO: log this error return nil, false //panic(err) } defer rows.Close() for rows.Next() { var subcategory Subcategory if err = rows.Scan(&subcategory.ID, &subcategory.Name, &subcategory.CategoryId); err != nil { println(err.Error()) } subcategories = append(subcategories, subcategory) } return subcategories, true } func insertSubcategory(name string, categoryID int64) (recordID int64, ok bool) { db := getSQLConnection() defer db.Close() err := db.QueryRow("INSERT INTO subcategory(subcategory_name, category_id) VALUES($1, $2) RETURNING subcategory_id;", name, categoryID).Scan(&recordID) if err != nil { //TODO: log this error println(err.Error()) return 0, false //panic(err) } return recordID, true }