package admin import ( "reflect" "fmt" "zedshaw.games/webapp/data" _ "github.com/mattn/go-sqlite3" sq "github.com/Masterminds/squirrel" ) func SearchTable(search string, table string, the_type reflect.Type, limit uint64, page uint64) ([]any, error) { var results []any like := fmt.Sprint("%", search, "%") builder := sq.Select("*"). Limit(limit). Offset(limit * page). From(table) field_num := the_type.NumField() 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}) } builder = builder.Where(or_clause) sql_query, args, err := builder.ToSql() fmt.Println("-------------- SQL QUERY:", sql_query); if err != nil { return results, err } // BUG: refactor this to share a common func with SelectTable rows, err := data.DB.Queryx(sql_query, args...) if err != nil { return results, err } defer rows.Close() for rows.Next() { the_data := reflect.New(the_type).Interface() err = rows.StructScan(the_data) if err != nil { return results, err } results = append(results, the_data) } return results, rows.Err() } func SelectTable(table string, the_type reflect.Type, limit uint64, page uint64) ([]any, error) { var results []any sql_query, args, err := sq.Select("*").Limit(limit).Offset(limit * page).From(table).ToSql() if err != nil { return results, err } rows, err := data.DB.Queryx(sql_query, args...) if err != nil { return results, err } defer rows.Close() for rows.Next() { the_data := reflect.New(the_type).Interface() err = rows.StructScan(the_data) if err != nil { return results, err } results = append(results, the_data) } return results, rows.Err() } func Get(table string, the_type reflect.Type, id int64) (reflect.Value, error) { sql_query, args, err := sq.Select("*").From(table).Where(sq.Eq{"id": id}).ToSql() if err != nil { return reflect.New(nil), err } the_data := reflect.New(the_type) err = data.DB.Get(the_data.Interface(), sql_query, args...) // BUG: not sure if Elem or returning the reflect.New is better return the_data.Elem(), err } func Delete(table string, id int64) error { sql_query, args, err := sq.Delete(table).Where(sq.Eq{"id": id}).ToSql() if err != nil { return err } _, err = data.DB.Exec(sql_query, args...) return err } func Insert(table string, value reflect.Value) (int64, int64, error) { type_of := value.Type() field_num := value.NumField() var columns []string var values []any for i := 0; i < field_num; i++ { field := value.Field(i) tag := type_of.Field(i).Tag.Get("db") if tag == "id" { continue } columns = append(columns, tag) values = append(values, field.Interface()) } builder := sq.Insert(table).Columns(columns...).Values(values...) sql_query, args, err := builder.ToSql() result, err := data.DB.Exec(sql_query, args...) id, err := result.LastInsertId() if err != nil { return -1, -1, err } count, err := result.RowsAffected() if err != nil { return id, -1, err } return id, count, err } func Update(table string, value reflect.Value) error { builder := sq.Update(table) type_of := value.Type() field_num := value.NumField() for i := 0; i < field_num; i++ { field := value.Field(i) tag := type_of.Field(i).Tag.Get("db") // skip update of id to avoid replacing it if tag == "id" { continue } builder = builder.Set(tag, field.Interface()) } builder = builder.Where(sq.Eq{"id": value.FieldByName("Id").Interface()}) sql_query, args, err := builder.ToSql() fmt.Println("UPDATE QUERY", sql_query, args) if err != nil { return err} _, err = data.DB.Exec(sql_query, args...) return err }