|  |  |  | package admin
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import (
 | 
					
						
							|  |  |  |   "reflect"
 | 
					
						
							|  |  |  |   "fmt"
 | 
					
						
							|  |  |  |   "MY/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
 | 
					
						
							|  |  |  | }
 |