Database now ignores fields without db tags and with db:'-' tags.

master
Zed A. Shaw 3 weeks ago
parent a8a9141ede
commit 67b059b538
  1. 1
      common/api.go
  2. 3
      common/errors.go
  3. 7
      data/models.go
  4. 20
      features/admin/api.go
  5. 31
      features/admin/db.go
  6. 29
      features/survey/db.go
  7. 1
      migrations/20260805143821_surveys.sql

@ -67,6 +67,7 @@ func ReflectOnPost(typeOf reflect.Type, c *fiber.Ctx) (reflect.Value, error) {
if err != nil { if err != nil {
validationErrors := err.(validator.ValidationErrors) validationErrors := err.(validator.ValidationErrors)
// TODO: need to expand on the error reporting here
log.Println(validationErrors) log.Println(validationErrors)
return result_val, err return result_val, err
} }

@ -3,10 +3,12 @@ package common
import ( import (
"log" "log"
"fmt" "fmt"
"runtime/debug"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
func Fail(err error, format string, v ...any) error { func Fail(err error, format string, v ...any) error {
debug.PrintStack()
err_format := fmt.Sprintf("ERROR: %v; %s", err, format) err_format := fmt.Sprintf("ERROR: %v; %s", err, format)
log.Printf(err_format, v...) log.Printf(err_format, v...)
return err 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 { func ApiError(c *fiber.Ctx, format string, args ...any) error {
c.Status(500) c.Status(500)
debug.PrintStack()
log.Printf(format, args...) log.Printf(format, args...)
return c.JSON(fiber.Map{ return c.JSON(fiber.Map{

@ -19,9 +19,10 @@ type User struct {
type Question struct { type Question struct {
Id int64 `db:"id" validate:"numeric"` Id int64 `db:"id" validate:"numeric"`
SurveyId int64 `db:"survey_id" validate:"numeric"`
Question string `db:"question"` Question string `db:"question"`
Result int `db:"result"` Result int `db:"result"`
Answer bool // move to session Answer bool `json:"-" db:"-"` // move to session
} }
type Survey struct { type Survey struct {
@ -30,8 +31,8 @@ type Survey struct {
Description string `db:"description"` Description string `db:"description"`
CreatedOn string `db:"created_on"` CreatedOn string `db:"created_on"`
Respondents int `db:"respondents"` Respondents int `db:"respondents"`
State string `db:"state"` Active bool `db:"active"`
Questions []Question Questions []Question `json:"-" db:"-"`
} }
/* /*

@ -3,7 +3,6 @@ package features_admin
import ( import (
"maps" "maps"
"reflect" "reflect"
"fmt"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"MY/webapp/data" "MY/webapp/data"
. "MY/webapp/common" . "MY/webapp/common"
@ -66,23 +65,24 @@ func GetApiSelectOne(c *fiber.Ctx) error {
func PostApiUpdate(c *fiber.Ctx) error { func PostApiUpdate(c *fiber.Ctx) error {
_, err := AuthCheck(c, true) _, err := AuthCheck(c, true)
if err != nil { if err != nil {
return ApiError(c, "Auth required.") return ApiError(c, "Auth required: %v", err)
} }
table := c.Params("table") table := c.Params("table")
typeOf, ok := data.Models()[table] typeOf, ok := data.Models()[table]
if !ok { if !ok {
return ApiError(c, "Table does not exist") return ApiError(c, "Table %s does not exist", table)
} }
obj, err := ReflectOnPost(typeOf, c) obj, err := ReflectOnPost(typeOf, c)
if err != nil { 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()) id, err := Update(table, obj.Elem())
if err != nil { if err != nil {
return ApiError(c, "Update failed") return ApiError(c, "Update failed: %v", err)
} }
return c.JSON(fiber.Map{"table": table, "id": id}) return c.JSON(fiber.Map{"table": table, "id": id})
@ -97,12 +97,10 @@ func GetApiInsert(c *fiber.Ctx) error {
typeOf, ok := data.Models()[table] typeOf, ok := data.Models()[table]
if !ok { 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(reflect.New(typeOf).Interface())
return c.JSON(result.Interface())
} }
func PostApiInsert(c *fiber.Ctx) error { func PostApiInsert(c *fiber.Ctx) error {
@ -117,13 +115,13 @@ func PostApiInsert(c *fiber.Ctx) error {
obj, err := ReflectOnPost(typeOf, c) obj, err := ReflectOnPost(typeOf, c)
if err != nil { if err != nil {
return ApiError(c, "failed reflect") return ApiError(c, "Failed reflect: %v", err)
} }
id, _, err := Insert(table, obj.Elem()) id, _, err := Insert(table, obj.Elem())
if err != nil { if err != nil {
return ApiError(c, "failed insert") return ApiError(c, "Failed insert: %v", err)
} }
return c.JSON(fiber.Map{ "id": id, "table": table}) return c.JSON(fiber.Map{ "id": id, "table": table})

@ -9,6 +9,12 @@ import (
sq "github.com/Masterminds/squirrel" 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) { func Schema(table string) ([]string, error) {
the_type, ok := data.Models()[table] the_type, ok := data.Models()[table]
if !ok { return nil, errors.New("Invalid 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) fields := make([]string, 0, field_num)
for i := 0; i < field_num; i++ { for i := 0; i < field_num; i++ {
tag := the_type.Field(i).Name _, ok := GetDbTag(the_type, i)
fields = append(fields, tag)
if ok {
field_name := the_type.Field(i).Name
fields = append(fields, field_name)
}
} }
return fields, nil return fields, nil
@ -40,8 +50,11 @@ func SearchTable(search string, table string, limit uint64, page uint64) ([]any,
var or_clause sq.Or var or_clause sq.Or
for i := 0; i < field_num; i++ { for i := 0; i < field_num; i++ {
tag := the_type.Field(i).Tag.Get("db") tag, ok := GetDbTag(the_type, i)
or_clause = append(or_clause, sq.Like{tag: like})
if ok {
or_clause = append(or_clause, sq.Like{tag: like})
}
} }
builder = builder.Where(or_clause) builder = builder.Where(or_clause)
@ -119,10 +132,12 @@ func Insert(table string, value reflect.Value) (int64, int64, error) {
var columns []string var columns []string
var values []any var values []any
// TODO: I think I don't need this, look if squirrel can just insert
for i := 0; i < field_num; i++ { for i := 0; i < field_num; i++ {
field := value.Field(i) field := value.Field(i)
tag := type_of.Field(i).Tag.Get("db") tag, ok := GetDbTag(type_of, i)
if tag == "id" { continue }
if !ok || tag == "id" { continue }
columns = append(columns, tag) columns = append(columns, tag)
values = append(values, field.Interface()) 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++ { for i := 0; i < field_num; i++ {
field := value.Field(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 // skip update of id to avoid replacing it
if tag == "id" { continue } if !ok || tag == "id" { continue }
builder = builder.Set(tag, field.Interface()) builder = builder.Set(tag, field.Interface())
} }

@ -12,33 +12,6 @@ func QueryData() data.Survey {
Description: "The description.", Description: "The description.",
CreatedOn: "01/20/26", CreatedOn: "01/20/26",
Respondents: 200, Respondents: 200,
State: "Finished", Active: false,
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,
},
},
} }
} }

@ -2,6 +2,7 @@
-- +goose StatementBegin -- +goose StatementBegin
CREATE TABLE question ( CREATE TABLE question (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
survey_id INTEGER,
question TEXT UNIQUE NOT NULL, question TEXT UNIQUE NOT NULL,
result INTEGER DEFAULT 0); result INTEGER DEFAULT 0);

Loading…
Cancel
Save