Compare commits

...

6 Commits
v0.0.6 ... main

Author SHA1 Message Date
2cbe41587e 升级异常机制 2025-12-12 21:51:15 +08:00
480250c04c update for gojs 2025-12-01 00:34:23 +08:00
20d283a270 update gojs 2025-11-30 23:03:03 +08:00
Star
3a991746ad update for ssgo/dao 2025-07-15 17:18:36 +08:00
195cbc6b59 update packages 2025-06-25 22:56:06 +08:00
Star
12fcb95b9d add querya 2025-01-14 14:28:26 +08:00
5 changed files with 161 additions and 50 deletions

133
db.go
View File

@ -2,9 +2,12 @@ package db
import ( import (
_ "embed" _ "embed"
"strings"
"apigo.cc/gojs" "apigo.cc/gojs"
"apigo.cc/gojs/goja" "apigo.cc/gojs/goja"
_ "github.com/go-sql-driver/mysql"
_ "github.com/jackc/pgx/v5/stdlib"
"github.com/ssgo/dao/dao" "github.com/ssgo/dao/dao"
"github.com/ssgo/db" "github.com/ssgo/db"
"github.com/ssgo/log" "github.com/ssgo/log"
@ -16,19 +19,32 @@ var dbTS string
//go:embed README.md //go:embed README.md
var dbMD string var dbMD string
var defaultDB = "default"
// var defaultDB = "default"
// var defaultDBLock = sync.RWMutex{}
func init() { func init() {
obj := map[string]any{ obj := map[string]any{
"get": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { "get": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1) args := gojs.MakeArgs(&argsIn, vm).Check(1)
conn := db.GetDB(args.Str(0), args.Logger)
// 检查sqlite文件访问是否超出沙盒 userPath
dsn := fixDsn(vm, args.Str(0))
conn := db.GetDB(dsn, args.Logger)
return vm.ToValue(makeDBObject(conn, nil)) return vm.ToValue(makeDBObject(conn, nil))
}, },
"setDefault": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { "setDefault": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args := gojs.MakeArgs(&argsIn, vm).Check(1) args := gojs.MakeArgs(&argsIn, vm).Check(1)
defaultDB = args.Str(0)
conn := db.GetDB(defaultDB, args.Logger) // 检查sqlite文件访问是否超出沙盒 userPath
dsn := fixDsn(vm, args.Str(0))
// defaultDBLock.Lock()
// defaultDB = dsn
// defaultDBLock.Unlock()
conn := db.GetDB(dsn, args.Logger)
args.This.ToObject(vm).Set("conn", conn) args.This.ToObject(vm).Set("conn", conn)
return nil return nil
}, },
@ -36,7 +52,7 @@ func init() {
gojs.Register("apigo.cc/gojs/db", gojs.Module{ gojs.Register("apigo.cc/gojs/db", gojs.Module{
ObjectMaker: func(vm *goja.Runtime) gojs.Map { ObjectMaker: func(vm *goja.Runtime) gojs.Map {
conn := db.GetDB(defaultDB, gojs.GetLogger(vm)) conn := db.GetDB("default", gojs.GetLogger(vm))
dbObj := makeDBObject(conn, nil) dbObj := makeDBObject(conn, nil)
for k, v := range obj { for k, v := range obj {
dbObj[k] = v dbObj[k] = v
@ -52,6 +68,20 @@ func init() {
}) })
} }
func fixDsn(vm *goja.Runtime, dsn string) string {
// 检查sqlite文件访问是否超出沙盒 userPath
rootPath := u.String(vm.GetData("userPath"))
if rootPath != "" && strings.HasPrefix(dsn, "sqlite") && strings.Contains(dsn, "://") {
filename := strings.SplitN(dsn, "://", 2)[1]
filename = strings.SplitN(dsn, "?", 2)[0]
fixedFilename := gojs.FixPath(vm, filename)
if fixedFilename != filename {
dsn = strings.Replace(dsn, filename, fixedFilename, 1)
}
}
return dsn
}
func makeDBObject(conn *db.DB, tx *db.Tx) map[string]any { func makeDBObject(conn *db.DB, tx *db.Tx) map[string]any {
obj := map[string]any{ obj := map[string]any{
"conn": conn, "conn": conn,
@ -67,7 +97,27 @@ func makeDBObject(conn *db.DB, tx *db.Tx) map[string]any {
if r.Error == nil { if r.Error == nil {
return vm.ToValue(makeQueryResult(r, r.MapResults())) return vm.ToValue(makeQueryResult(r, r.MapResults()))
} else { } else {
panic(vm.NewGoError(r.Error)) // panic(vm.NewGoError(r.Error))
vm.SetData("_lastError", r.Error)
gojs.GetLogger(vm).Error(r.Error.Error())
return nil
}
},
"querya": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args, conn, tx, _ := initDBArgs(argsIn, vm, 1)
var r *db.QueryResult
if tx != nil {
r = tx.Query(args.Str(0), args.Array(1)...)
} else {
r = conn.Query(args.Str(0), args.Array(1)...)
}
if r.Error == nil {
return vm.ToValue(makeQueryResult(r, r.SliceResults()))
} else {
// panic(vm.NewGoError(r.Error))
vm.SetData("_lastError", r.Error)
gojs.GetLogger(vm).Error(r.Error.Error())
return nil
} }
}, },
"query1": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { "query1": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
@ -81,7 +131,10 @@ func makeDBObject(conn *db.DB, tx *db.Tx) map[string]any {
if r.Error == nil { if r.Error == nil {
return vm.ToValue(makeQueryResult(r, r.MapOnR1())) return vm.ToValue(makeQueryResult(r, r.MapOnR1()))
} else { } else {
panic(vm.NewGoError(r.Error)) // panic(vm.NewGoError(r.Error))
vm.SetData("_lastError", r.Error)
gojs.GetLogger(vm).Error(r.Error.Error())
return nil
} }
}, },
"query1a": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { "query1a": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
@ -103,7 +156,10 @@ func makeDBObject(conn *db.DB, tx *db.Tx) map[string]any {
} }
return vm.ToValue(makeQueryResult(r, nil)) return vm.ToValue(makeQueryResult(r, nil))
} else { } else {
panic(vm.NewGoError(r.Error)) // panic(vm.NewGoError(r.Error))
vm.SetData("_lastError", r.Error)
gojs.GetLogger(vm).Error(r.Error.Error())
return nil
} }
}, },
"query11": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { "query11": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
@ -121,7 +177,10 @@ func makeDBObject(conn *db.DB, tx *db.Tx) map[string]any {
} }
return vm.ToValue(makeQueryResult(r, nil)) return vm.ToValue(makeQueryResult(r, nil))
} else { } else {
panic(vm.NewGoError(r.Error)) // panic(vm.NewGoError(r.Error))
vm.SetData("_lastError", r.Error)
gojs.GetLogger(vm).Error(r.Error.Error())
return nil
} }
}, },
"exec": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { "exec": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
@ -135,7 +194,10 @@ func makeDBObject(conn *db.DB, tx *db.Tx) map[string]any {
if r.Error == nil { if r.Error == nil {
return vm.ToValue(makeExecResult(r)) return vm.ToValue(makeExecResult(r))
} else { } else {
panic(vm.NewGoError(r.Error)) // panic(vm.NewGoError(r.Error))
vm.SetData("_lastError", r.Error)
gojs.GetLogger(vm).Error(r.Error.Error())
return vm.ToValue(false)
} }
}, },
"insert": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { "insert": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
@ -149,7 +211,10 @@ func makeDBObject(conn *db.DB, tx *db.Tx) map[string]any {
if r.Error == nil { if r.Error == nil {
return vm.ToValue(makeExecResult(r)) return vm.ToValue(makeExecResult(r))
} else { } else {
panic(vm.NewGoError(r.Error)) // panic(vm.NewGoError(r.Error))
vm.SetData("_lastError", r.Error)
gojs.GetLogger(vm).Error(r.Error.Error())
return vm.ToValue(false)
} }
}, },
"replace": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { "replace": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
@ -163,7 +228,10 @@ func makeDBObject(conn *db.DB, tx *db.Tx) map[string]any {
if r.Error == nil { if r.Error == nil {
return vm.ToValue(makeExecResult(r)) return vm.ToValue(makeExecResult(r))
} else { } else {
panic(vm.NewGoError(r.Error)) // panic(vm.NewGoError(r.Error))
vm.SetData("_lastError", r.Error)
gojs.GetLogger(vm).Error(r.Error.Error())
return vm.ToValue(false)
} }
}, },
"update": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { "update": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
@ -177,7 +245,10 @@ func makeDBObject(conn *db.DB, tx *db.Tx) map[string]any {
if r.Error == nil { if r.Error == nil {
return vm.ToValue(makeExecResult(r)) return vm.ToValue(makeExecResult(r))
} else { } else {
panic(vm.NewGoError(r.Error)) // panic(vm.NewGoError(r.Error))
vm.SetData("_lastError", r.Error)
gojs.GetLogger(vm).Error(r.Error.Error())
return vm.ToValue(false)
} }
}, },
"delete": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { "delete": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
@ -191,7 +262,10 @@ func makeDBObject(conn *db.DB, tx *db.Tx) map[string]any {
if r.Error == nil { if r.Error == nil {
return vm.ToValue(makeExecResult(r)) return vm.ToValue(makeExecResult(r))
} else { } else {
panic(vm.NewGoError(r.Error)) // panic(vm.NewGoError(r.Error))
vm.SetData("_lastError", r.Error)
gojs.GetLogger(vm).Error(r.Error.Error())
return vm.ToValue(false)
} }
}, },
"makeInKeys": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { "makeInKeys": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
@ -204,7 +278,7 @@ func makeDBObject(conn *db.DB, tx *db.Tx) map[string]any {
obj["make"] = func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { obj["make"] = func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args, conn, _, logger := initDBArgs(argsIn, vm, 1) args, conn, _, logger := initDBArgs(argsIn, vm, 1)
erDesc := args.Str(0) erDesc := args.Str(0)
tryFile := gojs.FindPath(vm, erDesc) tryFile := gojs.FixPath(vm, erDesc)
if u.FileExists(tryFile) { if u.FileExists(tryFile) {
erDesc = u.ReadFileN(tryFile) erDesc = u.ReadFileN(tryFile)
} }
@ -219,7 +293,10 @@ data t
`, logger); err == nil { `, logger); err == nil {
return nil return nil
} else { } else {
panic(vm.NewGoError(err)) // panic(vm.NewGoError(err))
vm.SetData("_lastError", err)
gojs.GetLogger(vm).Error(err.Error())
return vm.ToValue(false)
} }
} }
@ -227,20 +304,27 @@ data t
args, _, _, logger := initDBArgs(argsIn, vm, 1) args, _, _, logger := initDBArgs(argsIn, vm, 1)
outputFile := args.Str(0) outputFile := args.Str(0)
erDesc := args.Str(1) erDesc := args.Str(1)
tryFile := gojs.FindPath(vm, erDesc) dbType := args.Str(2)
if dbType == "" {
dbType = "mysql"
}
tryFile := gojs.FixPath(vm, erDesc)
if u.FileExists(tryFile) { if u.FileExists(tryFile) {
erDesc = u.ReadFileN(tryFile) erDesc = u.ReadFileN(tryFile)
} }
dao.MakeERFile(erDesc, "", outputFile, logger) dao.MakeERFile(dbType, erDesc, "", outputFile, logger)
return nil return vm.ToValue(true)
} }
obj["destroy"] = func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { obj["destroy"] = func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
_, conn, _, _ := initDBArgs(argsIn, vm, 0) _, conn, _, _ := initDBArgs(argsIn, vm, 0)
if err := conn.Destroy(); err == nil { if err := conn.Destroy(); err == nil {
return nil return vm.ToValue(true)
} else { } else {
panic(vm.NewGoError(err)) // panic(vm.NewGoError(err))
vm.SetData("_lastError", err)
gojs.GetLogger(vm).Error(err.Error())
return vm.ToValue(false)
} }
} }
@ -254,9 +338,12 @@ data t
obj["end"] = func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { obj["end"] = func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
args, _, tx, _ := initDBArgs(argsIn, vm, 1) args, _, tx, _ := initDBArgs(argsIn, vm, 1)
if err := tx.Finish(args.Bool(0)); err != nil { if err := tx.Finish(args.Bool(0)); err != nil {
panic(vm.NewGoError(err)) // panic(vm.NewGoError(err))
vm.SetData("_lastError", err)
gojs.GetLogger(vm).Error(err.Error())
return vm.ToValue(false)
} }
return nil return vm.ToValue(true)
} }
} }
return obj return obj

12
db.ts
View File

@ -7,6 +7,7 @@ export default {
makeER, makeER,
query, query,
query1, query1,
query1a,
query11, query11,
exec, exec,
insert, insert,
@ -21,9 +22,11 @@ export default {
function get(dbName: string): DB { return null as any } function get(dbName: string): DB { return null as any }
function setDefault(dbName: string): void { } function setDefault(dbName: string): void { }
function make(descFileOrContent: string): Object[] { return null as any } function make(descFileOrContent: string): Object[] { return null as any }
function makeER(outputFile: string, descFileOrContent: string): void { } function makeER(outputFile: string, descFileOrContent: string, dbType: string = 'mysql'): void { }
function query(sql: string, ...args: any): QueryResult { return null as any } function query(sql: string, ...args: any): QueryResult { return null as any }
function querya(sql: string, ...args: any): QueryResultA { return null as any }
function query1(sql: string, ...args: any): QueryResult1 { return null as any } function query1(sql: string, ...args: any): QueryResult1 { return null as any }
function query1a(sql: string, ...args: any): QueryResult1A { return null as any }
function query11(sql: string, ...args: any): QueryResult11 { return null as any } function query11(sql: string, ...args: any): QueryResult11 { return null as any }
function exec(sql: string, ...args: any): ExecResult { return null as any } function exec(sql: string, ...args: any): ExecResult { return null as any }
function insert(table: string, data: Object): ExecResult { return null as any } function insert(table: string, data: Object): ExecResult { return null as any }
@ -38,6 +41,7 @@ interface DB {
make(descFileOrContent: string): Object[] make(descFileOrContent: string): Object[]
query(sql: string, ...args: any): QueryResult query(sql: string, ...args: any): QueryResult
query1(sql: string, ...args: any): QueryResult1 query1(sql: string, ...args: any): QueryResult1
query1a(sql: string, ...args: any): QueryResult1A
query11(sql: string, ...args: any): QueryResult11 query11(sql: string, ...args: any): QueryResult11
exec(sql: string, ...args: any): ExecResult exec(sql: string, ...args: any): ExecResult
insert(table: string, data: Object): ExecResult insert(table: string, data: Object): ExecResult
@ -69,6 +73,12 @@ interface QueryResult {
result: Object[] result: Object[]
} }
interface QueryResultA {
sql: string
args: any[]
result: any[][]
}
interface QueryResult1 { interface QueryResult1 {
sql: string sql: string
args: any[] args: any[]

View File

@ -6,13 +6,14 @@ import (
"testing" "testing"
"apigo.cc/gojs" "apigo.cc/gojs"
_ "apigo.cc/gojs/console"
_ "apigo.cc/gojs/db" _ "apigo.cc/gojs/db"
"github.com/ssgo/u" "github.com/ssgo/u"
_ "modernc.org/sqlite" _ "modernc.org/sqlite"
) )
func Test(t *testing.T) { func Test(t *testing.T) {
// gojs.ExportForDev() gojs.ExportForDev()
defer os.Remove("test.db") defer os.Remove("test.db")
r, err := gojs.RunFile("db_test.js", "Tom") r, err := gojs.RunFile("db_test.js", "Tom")
if err != nil { if err != nil {

View File

@ -1,4 +1,5 @@
import db from 'apigo.cc/gojs/db' import db from 'apigo.cc/gojs/db'
import co from 'apigo.cc/gojs/console'
function main(testUserName) { function main(testUserName) {
db.setDefault('sqlite://test.db') db.setDefault('sqlite://test.db')
@ -15,5 +16,15 @@ function main(testUserName) {
`) `)
db.insert('User', { name: testUserName }) db.insert('User', { name: testUserName })
let user = db.query1('SELECT * FROM User').result let user = db.query1('SELECT * FROM User').result
let r = db.query1('SELECT * FROM User WHERE name = ?', testUserName)
co.info(r)
// db.delete('User', "name=?", testUserName)
db.insert('_deleted', { table: 'User', id: r.result.id })
r = db.query('SELECT * FROM _deleted')
co.info(r)
return user return user
} }

52
go.mod
View File

@ -1,43 +1,45 @@
module apigo.cc/gojs/db module apigo.cc/gojs/db
go 1.22.0 go 1.24.0
toolchain go1.22.5
require ( require (
apigo.cc/gojs v0.0.9 apigo.cc/gojs v0.0.32
github.com/ssgo/dao v0.1.5 apigo.cc/gojs/console v0.0.4
github.com/ssgo/db v1.7.11 github.com/go-sql-driver/mysql v1.9.3
github.com/ssgo/log v1.7.7 github.com/jackc/pgx/v5 v5.7.6
github.com/ssgo/u v1.7.13 github.com/ssgo/dao v0.1.13
modernc.org/sqlite v1.34.2 github.com/ssgo/db v1.7.13
github.com/ssgo/log v1.7.10
github.com/ssgo/u v1.7.23
modernc.org/sqlite v1.40.1
) )
require ( require (
filippo.io/edwards25519 v1.1.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect
github.com/dlclark/regexp2 v1.11.4 // indirect github.com/dlclark/regexp2 v1.11.5 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect
github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-sourcemap/sourcemap v2.1.4+incompatible // indirect github.com/go-sourcemap/sourcemap v2.1.4+incompatible // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/google/pprof v0.0.0-20250903194437-c28834ac2320 // indirect
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/ssgo/config v1.7.9 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/ssgo/config v1.7.10 // indirect
github.com/ssgo/standard v1.7.7 // indirect github.com/ssgo/standard v1.7.7 // indirect
github.com/ssgo/tool v0.4.27 // indirect github.com/ssgo/tool v0.4.29 // indirect
golang.org/x/exp v0.0.0-20241210194714-1829a127f884 // indirect golang.org/x/crypto v0.37.0 // indirect
golang.org/x/sys v0.28.0 // indirect golang.org/x/exp v0.0.0-20250711185948-6ae5c78190dc // indirect
golang.org/x/text v0.21.0 // indirect golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.39.0 // indirect
golang.org/x/text v0.32.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
modernc.org/gc/v3 v3.0.0-20241213165251-3bc300f6d0c9 // indirect modernc.org/libc v1.66.10 // indirect
modernc.org/libc v1.61.4 // indirect modernc.org/mathutil v1.7.1 // indirect
modernc.org/mathutil v1.6.0 // indirect modernc.org/memory v1.11.0 // indirect
modernc.org/memory v1.8.0 // indirect
modernc.org/strutil v1.2.0 // indirect
modernc.org/token v1.1.0 // indirect
) )