package gcsql import ( "database/sql" "reflect" "github.com/gochan-org/gochan/pkg/gcplugin/luautil" lua "github.com/yuin/gopher-lua" luar "layeh.com/gopher-luar" ) type lvalueScanner struct { val lua.LValue state *lua.LState } func (lvs *lvalueScanner) Scan(src any) error { typeof := reflect.TypeOf(src) if typeof != nil && typeof.String() == "[]uint8" { src = string(src.([]uint8)) } lvs.val = luar.New(lvs.state, src) return nil } func PreloadModule(l *lua.LState) int { t := l.NewTable() l.SetFuncs(t, map[string]lua.LGFunction{ "query_rows": func(l *lua.LState) int { queryStr := l.CheckString(1) queryArgsL := l.CheckAny(2) var queryArgs []any if queryArgsL.Type() != lua.LTNil { table := queryArgsL.(*lua.LTable) table.ForEach(func(_ lua.LValue, val lua.LValue) { arg := luautil.LValueToInterface(l, val) queryArgs = append(queryArgs, arg) }) } rows, err := Query(nil, queryStr, queryArgs...) l.Push(luar.New(l, rows)) l.Push(luar.New(l, err)) return 2 }, "execute_sql": func(l *lua.LState) int { execStr := l.CheckString(1) execArgsL := l.CheckAny(2) var execArgs []any if execArgsL.Type() != lua.LTNil { table := execArgsL.(*lua.LTable) table.ForEach(func(_, val lua.LValue) { arg := luautil.LValueToInterface(l, val) execArgs = append(execArgs, arg) }) } result, err := Exec(nil, execStr) l.Push(luar.New(l, result)) l.Push(luar.New(l, err)) return 2 }, "scan_rows": func(l *lua.LState) int { rows := l.CheckUserData(1).Value.(*sql.Rows) table := l.CheckTable(2) var scanners []any colNames, err := rows.Columns() if err != nil { l.Push(luar.New(l, err)) return 1 } for range colNames { scanners = append(scanners, &lvalueScanner{state: l}) } if err = rows.Scan(scanners...); err != nil { l.Push(luar.New(l, err)) return 1 } for i, name := range colNames { table.RawSetString(name, scanners[i].(*lvalueScanner).val) } l.Push(lua.LNil) return 1 }, }) l.Push(t) return 1 }