server/database/productTag.go

173 lines
4.6 KiB
Go

/**
* file: database/productTag.go
* author: Theo Technicguy
* license: Apache 2.0
*
* Product tags database table connector
*/
package database
import (
"database/sql"
"git.licolas.net/hoffman/server/types"
)
const (
sqlDropProductTags = "DROP TABLE ProductTag;"
sqlCreateProductTags = `CREATE TABLE ProductTag (
TagID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
Name VARCHAR(64) UNIQUE NOT NULL,
Color INT
);`
sqlSelectAllProductTags = "SELECT * FROM ProductTag;"
sqlSelectProductTagById = "SELECT * FROM ProductTag WHERE TagID = ?;"
sqlSelectProductTagByName = "SELECT * FROM ProductTag WHERE Name = ?;"
sqlSelectProductTagsLikeName = "SELECT * FROM ProductTag WHERE Name LIKE %%?%%;"
sqlInsertProductTag = "INSERT INTO ProductTag (Name, Color) VALUES (?, ?);"
sqlUpdateProductTag = "UPDATE ProductTag SET Name = ?, Color = ? WHERE TagID = ?;"
sqlDeleteProductTag = "DELETE FROM ProductTag WHERE TagID = ?"
)
func (r *R) scanProductTags(tx *sql.Tx, query string, args ...any) ([]*types.Tag, error) {
logger.Trace().Bool("transaction", tx != nil).Str("query", query).Any("args", args).Msg("excuting query and scanning tags")
if tx == nil {
var err error
tx, err = r.db.Begin()
if err != nil {
return nil, err
}
defer tx.Rollback()
}
rows, err := tx.Query(query, args...)
if err != nil {
return nil, err
}
defer rows.Close()
var tags []*types.Tag = []*types.Tag{}
for rows.Next() {
var tag types.Tag
if err := rows.Scan(&tag.Id, &tag.Name, &tag.Color); err != nil {
return nil, err
}
logger.Trace().Any("tag", tag).Msg("adding found tag")
tags = append(tags, &tag)
}
logger.Trace().Int("tags", len(tags)).Msg("done querying and scanning tags")
return tags, nil
}
func (r *R) scanUniqueProductTag(tx *sql.Tx, query string, args ...any) (tag *types.Tag, err error) {
logger.Trace().Bool("transaction", tx != nil).Str("query", query).Any("args", args).Msg("excuting query and scanning one tag")
tags, err := r.scanProductTags(tx, query, args...)
if err != nil {
return nil, err
}
switch len(tags) {
case 0:
tag, err = new(types.Tag), nil
case 1:
tag, err = tags[0], nil
default:
tag, err = nil, ErrNonUniqueIdentifier
}
logger.Trace().Any("tag", tag).Msg("found tag")
return
}
func (r *R) DropProductTagTable() error {
logger.Info().Msg("dropping product tag table")
_, err := r.db.Exec(sqlDropProductTags)
return err
}
func (r *R) CreateProductTagTable() error {
logger.Info().Msg("creating product tag table")
_, err := r.db.Exec(sqlCreateProductTags)
return err
}
func (r *R) SelectAllProductTags() ([]*types.Tag, error) {
logger.Trace().Msg("selecting all tags")
return r.scanProductTags(nil, sqlSelectAllProductTags)
}
func (r *R) SelectProductTagById(id uint) (*types.Tag, error) {
logger.Trace().Uint("id", id).Msg("selecting tag by id")
return r.scanUniqueProductTag(nil, sqlSelectProductTagById, id)
}
func (r *R) SelectProductTagByName(name string) (*types.Tag, error) {
logger.Trace().Str("name", name).Msg("selecting tag by name")
return r.scanUniqueProductTag(nil, sqlSelectProductTagByName, name)
}
func (r *R) SelectProductTagsLikeName(name string) ([]*types.Tag, error) {
logger.Trace().Str("name", name).Msg("selecting tag like name")
return r.scanProductTags(nil, sqlSelectProductTagsLikeName, name)
}
func (r *R) InsertProductTag(tag *types.Tag) error {
logger.Trace().Any("tag", tag).Msg("inserting new tag")
result, err := r.db.Exec(sqlInsertProductTag, tag.Name, tag.Color)
if err != nil {
return err
}
id, err := result.LastInsertId()
if err != nil {
return err
}
tag.Id = uint(id)
logger.Trace().Uint("new-id", tag.Id).Msg("new tag id")
return nil
}
func (r *R) UpdateProductTag(tag *types.Tag) (*types.Tag, error) {
logger.Trace().Any("tag", tag).Msg("updating tag")
if _, err := r.db.Exec(sqlUpdateProductTag, tag.Name, tag.Color, tag.Id); err != nil {
return nil, err
}
return r.scanUniqueProductTag(nil, sqlSelectProductTagById, tag.Id)
}
func (r *R) DeleteProductTag(id uint) (*types.Tag, error) {
logger := logger.With().Uint("tag-id", id).Logger()
logger.Trace().Msg("deleting tag")
tx, err := r.db.Begin()
if err != nil {
return nil, err
}
defer tx.Rollback()
logger.Trace().Msg("selecting tag")
tags, err := r.scanProductTags(tx, sqlSelectProductTagById, id)
if err != nil {
return nil, err
}
logger.Trace().Msg("deleting taggings")
if _, err := tx.Exec(sqlDeleteTagProductTagging, id); err != nil {
return nil, err
}
logger.Trace().Msg("deleting tag")
if _, err := tx.Exec(sqlDeleteProductTag, id); err != nil {
return nil, err
}
return tags[0], tx.Commit()
}