started models

This commit is contained in:
drevil 2023-07-04 23:36:21 -04:00
parent ed7ee74924
commit 7542f56906
2 changed files with 235 additions and 1 deletions

View File

@ -436,7 +436,7 @@ func deleteComic(id int) error {
return err
}
func main() {
func mains() {
var err error
errlog = log.New(log.Writer(), "[ERROR] ", log.Flags())

234
models.go Normal file
View File

@ -0,0 +1,234 @@
package main
import (
"fmt"
"errors"
"strings"
"reflect"
"database/sql"
)
var columnTypeMap map[string]string = map[string]string {
"int" : "INTEGER",
"string" : "TEXT",
"datetime" : "DATETIME",
}
type ModelManager struct {
db *sql.DB
}
func (mm *ModelManager) OpenDB(path string) error {
var err error
mm.db, err = sql.Open("sqlite3", path)
return err
}
func (mm *ModelManager) CloseDB() error {
return mm.db.Close()
}
func (mm *ModelManager) Model(s interface{}) *Model {
model := &Model{
name : getStructName(s),
manager : mm,
}
tpe := reflect.ValueOf(s).Elem()
model.fields = make([]reflect.StructField, tpe.NumField())
model.fieldInterfaces = make([]interface{}, tpe.NumField())
model.value = tpe
for i := 0; i < tpe.NumField(); i ++ {
model.fields[i] = tpe.Type().Field(i)
model.fieldInterfaces[i] = tpe.Field(i).Interface()
}
return model
}
type Model struct {
idColumn string
idInterface interface{}
name string
fields []reflect.StructField
fieldInterfaces []interface{}
value reflect.Value
manager *ModelManager
}
func (m *Model) buildSquema() string {
s := 0
has_key := false
squema := "CREATE TABLE IF NOT EXISTS " + m.name + " (\n"
for i, f := range m.fields {
if !f.IsExported() {
continue
}
s++
t, ok := columnTypeMap[f.Type.String()]
if !ok {
continue
}
cn := getColumnName(f.Name)
squema += "\t" + cn + " " + t
p, _ := f.Tag.Lookup("primary_key")
if p == "true" && !has_key {
has_key = true
m.idColumn = cn
m.idInterface = m.value.Field(i).Interface()
squema += " PRIMARY KEY"
}
p, _ = f.Tag.Lookup("can_null")
if p != "true" {
squema += " NOT NULL"
}
if i < len(m.fields)-1 {
squema += ","
}
squema += "\n"
}
squema += ");"
m.fields = m.fields[:s]
if !has_key {
m.idColumn = "id"
}
return squema
}
func (m *Model) Create() error {
_, err := m.manager.db.Exec(m.buildSquema())
return err
}
func (m *Model) Insert() error {
columns := ""
inputs := ""
for i, f := range m.fields {
columns += getColumnName(f.Name)
inputs += "?"
if i < len(m.fields)-1 {
columns += ","
inputs += ","
}
}
exp := fmt.Sprintf("INSERT INTO %s(%s) VALUES(%s)", m.name, columns, inputs)
_, err := m.manager.db.Exec(exp, m.fieldInterfaces...)
return err
}
func (m *Model) Update() error {
inputs := ""
fields := make([]interface{}, len(m.fields))
for i, f := range m.fields {
if m.idColumn == f.Name {
continue
}
fields[i] = m.value.Field(i).Interface()
inputs += getColumnName(f.Name) + " = ?"
if i < len(m.fields)-1 {
inputs += ","
}
}
fields = append(fields, m.idInterface)
exp := fmt.Sprintf("UPDATE %s SET %s WHERE %s = ?", m.name, inputs, m.idColumn)
_, err := m.manager.db.Exec(exp, fields...)
return err
}
func (m *Model) FindBy(column string, by interface{}) (*QueryResults, error) {
r := &QueryResults{}
rows, err := m.manager.db.Query("SELECT * FROM " + m.name + " WHERE ? = ?;", column, by)
r.rows = rows
if err != nil {
return nil, err
}
if !r.rows.Next() {
return nil, errors.New("no such entry found")
}
return r, nil
}
func (m *Model) FindByID(id interface{}) (*QueryResults, error) {
return m.FindBy(m.idColumn, id)
}
func (m *Model) ReadResults(r *QueryResults) bool {
r.rows.Scan(m.fieldInterfaces...)
return r.rows.Next()
}
type QueryResults struct {
rows * sql.Rows
}
func (r *QueryResults) Close() error {
return r.rows.Close()
}
func getStructName(s interface{}) string {
n := ""
if t := reflect.TypeOf(s); t.Kind() == reflect.Ptr {
n = t.Elem().Name()
} else {
n = t.Name()
}
return strings.ToLower(n)
}
func getColumnName(column string) string {
return strings.ToLower(column)
}
type Test struct {
This string `primary_key:"true" `
Iss int `can_null:"true"`
ATest string `primary_key:"true" `
}
func main() {
mm := &ModelManager{}
test := Test{
ATest : "fingers crossed",
}
test.This = "sdssd"
m := mm.Model(&test)
mm.OpenDB("db.sqlite")
defer mm.CloseDB()
m.Create()
m.Insert()
test.ATest = "LOOaaaaaaaaaaaOL"
m.Update()
a := Test{}
ma := mm.Model(&a)
fmt.Println(m.idColumn)
res, err := ma.FindByID("sdssd")
panic(err)
if res != nil {
defer res.Close()
}
}