234 lines
4.2 KiB
Go
234 lines
4.2 KiB
Go
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()
|
|
}
|
|
} |