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
}