From 67b059b53846e0de883b28b1b45af85c250e85b4 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Thu, 6 Aug 2026 11:50:58 -0400 Subject: [PATCH] Database now ignores fields without db tags and with db:'-' tags. --- common/api.go | 1 + common/errors.go | 3 +++ data/models.go | 7 +++--- features/admin/api.go | 20 ++++++++--------- features/admin/db.go | 31 ++++++++++++++++++++------- features/survey/db.go | 29 +------------------------ migrations/20260805143821_surveys.sql | 1 + 7 files changed, 42 insertions(+), 50 deletions(-) diff --git a/common/api.go b/common/api.go index a558d6b..6db48f9 100644 --- a/common/api.go +++ b/common/api.go @@ -67,6 +67,7 @@ func ReflectOnPost(typeOf reflect.Type, c *fiber.Ctx) (reflect.Value, error) { if err != nil { validationErrors := err.(validator.ValidationErrors) + // TODO: need to expand on the error reporting here log.Println(validationErrors) return result_val, err } diff --git a/common/errors.go b/common/errors.go index 5a18f03..a0e78e3 100644 --- a/common/errors.go +++ b/common/errors.go @@ -3,10 +3,12 @@ package common import ( "log" "fmt" + "runtime/debug" "github.com/gofiber/fiber/v2" ) func Fail(err error, format string, v ...any) error { + debug.PrintStack() err_format := fmt.Sprintf("ERROR: %v; %s", err, format) log.Printf(err_format, v...) return err @@ -15,6 +17,7 @@ func Fail(err error, format string, v ...any) error { func ApiError(c *fiber.Ctx, format string, args ...any) error { c.Status(500) + debug.PrintStack() log.Printf(format, args...) return c.JSON(fiber.Map{ diff --git a/data/models.go b/data/models.go index a2a3793..2e789f1 100644 --- a/data/models.go +++ b/data/models.go @@ -19,9 +19,10 @@ type User struct { type Question struct { Id int64 `db:"id" validate:"numeric"` + SurveyId int64 `db:"survey_id" validate:"numeric"` Question string `db:"question"` Result int `db:"result"` - Answer bool // move to session + Answer bool `json:"-" db:"-"` // move to session } type Survey struct { @@ -30,8 +31,8 @@ type Survey struct { Description string `db:"description"` CreatedOn string `db:"created_on"` Respondents int `db:"respondents"` - State string `db:"state"` - Questions []Question + Active bool `db:"active"` + Questions []Question `json:"-" db:"-"` } /* diff --git a/features/admin/api.go b/features/admin/api.go index bca9b08..ac7be0e 100644 --- a/features/admin/api.go +++ b/features/admin/api.go @@ -3,7 +3,6 @@ package features_admin import ( "maps" "reflect" - "fmt" "github.com/gofiber/fiber/v2" "MY/webapp/data" . "MY/webapp/common" @@ -66,23 +65,24 @@ func GetApiSelectOne(c *fiber.Ctx) error { func PostApiUpdate(c *fiber.Ctx) error { _, err := AuthCheck(c, true) if err != nil { - return ApiError(c, "Auth required.") + return ApiError(c, "Auth required: %v", err) } table := c.Params("table") typeOf, ok := data.Models()[table] + if !ok { - return ApiError(c, "Table does not exist") + return ApiError(c, "Table %s does not exist", table) } obj, err := ReflectOnPost(typeOf, c) if err != nil { - return ApiError(c, fmt.Sprintf("Invalid format: %v", err)) + return ApiError(c, "Invalid format: %v", err) } id, err := Update(table, obj.Elem()) if err != nil { - return ApiError(c, "Update failed") + return ApiError(c, "Update failed: %v", err) } return c.JSON(fiber.Map{"table": table, "id": id}) @@ -97,12 +97,10 @@ func GetApiInsert(c *fiber.Ctx) error { typeOf, ok := data.Models()[table] if !ok { - return ApiError(c, "admin table %s does not exist", table) + return ApiError(c, "Admin table %s does not exist", table) } - result := reflect.New(typeOf) - - return c.JSON(result.Interface()) + return c.JSON(reflect.New(typeOf).Interface()) } func PostApiInsert(c *fiber.Ctx) error { @@ -117,13 +115,13 @@ func PostApiInsert(c *fiber.Ctx) error { obj, err := ReflectOnPost(typeOf, c) if err != nil { - return ApiError(c, "failed reflect") + return ApiError(c, "Failed reflect: %v", err) } id, _, err := Insert(table, obj.Elem()) if err != nil { - return ApiError(c, "failed insert") + return ApiError(c, "Failed insert: %v", err) } return c.JSON(fiber.Map{ "id": id, "table": table}) diff --git a/features/admin/db.go b/features/admin/db.go index 2b3e080..f5eca55 100644 --- a/features/admin/db.go +++ b/features/admin/db.go @@ -9,6 +9,12 @@ import ( sq "github.com/Masterminds/squirrel" ) +func GetDbTag(type_of reflect.Type, i int) (string, bool) { + db_tag, ok := type_of.Field(i).Tag.Lookup("db") + + return db_tag, ok && db_tag != "-" +} + func Schema(table string) ([]string, error) { the_type, ok := data.Models()[table] if !ok { return nil, errors.New("Invalid table") } @@ -18,8 +24,12 @@ func Schema(table string) ([]string, error) { fields := make([]string, 0, field_num) for i := 0; i < field_num; i++ { - tag := the_type.Field(i).Name - fields = append(fields, tag) + _, ok := GetDbTag(the_type, i) + + if ok { + field_name := the_type.Field(i).Name + fields = append(fields, field_name) + } } return fields, nil @@ -40,8 +50,11 @@ func SearchTable(search string, table string, limit uint64, page uint64) ([]any, var or_clause sq.Or for i := 0; i < field_num; i++ { - tag := the_type.Field(i).Tag.Get("db") - or_clause = append(or_clause, sq.Like{tag: like}) + tag, ok := GetDbTag(the_type, i) + + if ok { + or_clause = append(or_clause, sq.Like{tag: like}) + } } builder = builder.Where(or_clause) @@ -119,10 +132,12 @@ func Insert(table string, value reflect.Value) (int64, int64, error) { var columns []string var values []any + // TODO: I think I don't need this, look if squirrel can just insert for i := 0; i < field_num; i++ { field := value.Field(i) - tag := type_of.Field(i).Tag.Get("db") - if tag == "id" { continue } + tag, ok := GetDbTag(type_of, i) + + if !ok || tag == "id" { continue } columns = append(columns, tag) values = append(values, field.Interface()) } @@ -152,10 +167,10 @@ func Update(table string, value reflect.Value) (int64, error) { for i := 0; i < field_num; i++ { field := value.Field(i) - tag := type_of.Field(i).Tag.Get("db") + tag, ok := GetDbTag(type_of, i) // skip update of id to avoid replacing it - if tag == "id" { continue } + if !ok || tag == "id" { continue } builder = builder.Set(tag, field.Interface()) } diff --git a/features/survey/db.go b/features/survey/db.go index 9b985f0..e56d44a 100644 --- a/features/survey/db.go +++ b/features/survey/db.go @@ -12,33 +12,6 @@ func QueryData() data.Survey { Description: "The description.", CreatedOn: "01/20/26", Respondents: 200, - State: "Finished", - Questions: []data.Question{ - { - Id: 1, - Question: "Do you like HTML?", - Answer: true, - // TODO: just for prototyping, needs to be a better model - Result: 20, - }, - { - Id: 2, - Question: "Do you like CSS?", - Answer: false, - Result: 11, - }, - { - Id: 3, - Question: "Do you like JavaScript?", - Answer: true, - Result: 43, - }, - { - Id: 4, - Question: "Are you a programmer?", - Answer: true, - Result: 28, - }, - }, + Active: false, } } diff --git a/migrations/20260805143821_surveys.sql b/migrations/20260805143821_surveys.sql index 1d23b61..39e6cfa 100644 --- a/migrations/20260805143821_surveys.sql +++ b/migrations/20260805143821_surveys.sql @@ -2,6 +2,7 @@ -- +goose StatementBegin CREATE TABLE question ( id INTEGER PRIMARY KEY, + survey_id INTEGER, question TEXT UNIQUE NOT NULL, result INTEGER DEFAULT 0);