2024-01-25 16:07:48 +08:00
package db
import (
2024-01-25 16:17:41 +08:00
"apigo.cloud/git/apigo/plugin"
2024-01-25 16:07:48 +08:00
"fmt"
"github.com/ssgo/db"
"github.com/ssgo/log"
"github.com/ssgo/u"
2024-03-09 13:43:14 +08:00
"strings"
"sync"
2024-01-25 16:07:48 +08:00
)
type DB struct {
2024-03-09 13:43:14 +08:00
name string
pool * db . DB
logger * log . Logger
2024-01-25 16:07:48 +08:00
}
type Tx struct {
conn * db . Tx
}
2024-03-09 13:43:14 +08:00
type ExecResult struct {
Id int64
Changes int64
Version uint64
Sql string
SqlArgs [ ] interface { }
}
type QueryResult struct {
Result [ ] map [ string ] interface { }
Sql string
SqlArgs [ ] interface { }
}
2024-01-25 16:07:48 +08:00
var dbPool = map [ string ] * db . DB { }
2024-03-09 13:43:14 +08:00
var defaultDBURL = ""
var dbURLs = map [ string ] string { }
2024-01-25 16:07:48 +08:00
var defaultDB * db . DB
2024-03-09 13:43:14 +08:00
var dbPoolLock = sync . RWMutex { }
2024-01-25 16:07:48 +08:00
func init ( ) {
plugin . Register ( plugin . Plugin {
Id : "db" ,
Name : "数据库操作" ,
ConfigSample : ` default : mysql : //root:<**encrypted_password**>@127.0.0.1:3306/1?maxIdles=0&maxLifeTime=0&maxOpens=0&logSlow=1s # set default db connection pool, used by db.xxx
configs :
conn1 : sqlite3 : //conn1.db # set a named connection pool, used by db.get('conn1').xxx
conn2 : mysql : //root:@127.0.0.1:3306/1?sslCa=<**encrypted**>&sslCert=<**encrypted**>&sslKey=<**encrypted**>&sslSkipVerify=true # set ssl connection pool for mysql
conn3 : mysql : //root:@127.0.0.1:3306/1?timeout=90s&readTimeout=5s&writeTimeout=3s&charset=utf8mb4,utf8 # set more option for mysql
` ,
Init : func ( conf map [ string ] interface { } ) {
if conf [ "default" ] != nil {
2024-03-09 13:43:14 +08:00
defaultDBURL = u . String ( conf [ "default" ] )
tmpDB := db . GetDB ( defaultDBURL , nil )
dbPoolLock . Lock ( )
defaultDB = tmpDB
dbPoolLock . Unlock ( )
2024-01-25 16:07:48 +08:00
}
if conf [ "configs" ] != nil {
confs := map [ string ] string { }
u . Convert ( conf [ "configs" ] , & confs )
for name , url := range confs {
2024-03-09 13:43:14 +08:00
tmpDB := db . GetDB ( url , nil )
dbPoolLock . Lock ( )
dbURLs [ name ] = url
dbPool [ name ] = tmpDB
dbPoolLock . Unlock ( )
2024-01-25 16:07:48 +08:00
}
}
} ,
Objects : map [ string ] interface { } {
"fetch" : GetDB ,
} ,
// 实现直接使用db.xxx操作默认的数据库
2024-03-09 13:43:14 +08:00
JsCode : ` let _db = db
2024-01-25 16:07:48 +08:00
db = _db . fetch ( )
db . fetch = _db . fetch
` ,
} )
}
// GetDB 获得数据库连接
// GetDB name 连接配置名称,如果不提供名称则使用默认连接
// GetDB return 数据库连接,对象内置连接池操作,完成后无需手动关闭连接
func GetDB ( name * string , logger * log . Logger ) * DB {
2024-03-09 13:43:14 +08:00
if logger == nil {
logger = log . DefaultLogger
}
2024-01-25 16:07:48 +08:00
if name == nil || * name == "" {
2024-03-09 13:43:14 +08:00
if defaultDB == nil {
tmpDB := db . GetDB ( defaultDBURL , nil )
dbPoolLock . Lock ( )
defaultDB = tmpDB
dbPoolLock . Unlock ( )
}
return & DB {
name : "" ,
pool : defaultDB . CopyByLogger ( logger ) ,
logger : logger ,
}
} else {
dbPoolLock . RLock ( )
tmpDB := dbPool [ * name ]
dbPoolLock . RUnlock ( )
if tmpDB == nil {
tmpDB = db . GetDB ( dbURLs [ * name ] , nil )
dbPoolLock . Lock ( )
dbPool [ * name ] = tmpDB
dbPoolLock . Unlock ( )
2024-01-25 16:07:48 +08:00
}
2024-03-09 13:43:14 +08:00
return & DB {
name : * name ,
pool : tmpDB . CopyByLogger ( logger ) ,
logger : logger ,
}
}
}
// Destroy 关闭连接池
func ( db * DB ) Destroy ( ) error {
err := db . pool . Destroy ( )
dbPoolLock . Lock ( )
if db . name == "" {
defaultDB = nil
2024-01-25 16:07:48 +08:00
} else {
2024-03-09 13:43:14 +08:00
dbPool [ db . name ] = nil
}
dbPoolLock . Unlock ( )
return err
}
// InKeys 根据长度生成SQL中 IN "(?,?,...)" 引号中的部分
// InKeys return IN后面的Key变量的SQL
func InKeys ( numArgs int ) string {
a := make ( [ ] string , numArgs )
for i := 0 ; i < numArgs ; i ++ {
a [ i ] = "?"
}
return fmt . Sprintf ( "(%s)" , strings . Join ( a , "," ) )
}
// Make 创建表格,如果表格已经存在则更新表结构
// Make return 已执行的SQL列表
func ( db * DB ) Make ( groups [ ] ERGroup ) ( [ ] string , error ) {
outSql := make ( [ ] string , 0 )
for _ , group := range groups {
for _ , table := range group . Tables {
fmt . Println ( "=====TB" , table . Name )
sql , err := MakeTable ( db . pool , & table , db . logger )
outSql = append ( outSql , strings . Join ( sql , "\n" ) )
if err != nil {
return outSql , err
2024-01-25 16:07:48 +08:00
}
}
}
2024-03-09 13:43:14 +08:00
return outSql , nil
}
// MakeER 创建ER图
func ( db * DB ) MakeER ( groups [ ] ERGroup , outputFile * string , tplFile * string ) error {
return MakeER ( groups , outputFile , tplFile , db . logger )
}
// MakeDao 创建实体对象
// MakeDao outputPath 实体文件输出目录,为空时输出到当前目录下以数据库为目录名
func ( db * DB ) MakeDao ( outputPath * string , conf * DaoConfig ) error {
if outputPath == nil || * outputPath == "" {
defaultOutput := db . pool . Config . DB
outputPath = & defaultOutput
2024-01-25 16:07:48 +08:00
}
2024-03-09 13:43:14 +08:00
return MakeDao ( * outputPath , db . pool , conf , db . logger )
2024-01-25 16:07:48 +08:00
}
// Begin 开始事务
// Begin return 事务对象, 事务中的操作都在事务对象上操作, 请务必在返回的事务对象上执行commit或rollback
func ( db * DB ) Begin ( ) * Tx {
return db . Begin ( )
}
// Exec 执行SQL
// * requestSql SQL语句
// * args SQL语句中问号变量的值, 按顺序放在请求参数中
// Exec return 如果是INSERT到含有自增字段的表中返回插入的自增ID, 否则返回影响的行数
2024-03-09 13:43:14 +08:00
func ( db * DB ) Exec ( requestSql string , args ... interface { } ) ( ExecResult , error ) {
2024-01-25 16:07:48 +08:00
r := db . pool . Exec ( requestSql , args ... )
2024-03-09 13:43:14 +08:00
out := ExecResult { }
lSql := strings . ToLower ( requestSql )
if strings . Contains ( lSql , "insert into" ) || strings . Contains ( lSql , "replace into" ) {
out . Id = r . Id ( )
2024-01-25 16:07:48 +08:00
}
2024-03-09 13:43:14 +08:00
out . Changes = r . Changes ( )
out . Sql = * r . Sql
out . SqlArgs = r . Args
2024-01-25 16:07:48 +08:00
return out , r . Error
}
// Query 查询
// Query return 返回查询到的数据,对象数组格式
2024-03-09 13:43:14 +08:00
func ( db * DB ) Query ( requestSql string , args ... interface { } ) ( QueryResult , error ) {
2024-01-25 16:07:48 +08:00
r := db . pool . Query ( requestSql , args ... )
2024-03-09 13:43:14 +08:00
return QueryResult {
Result : r . MapResults ( ) ,
Sql : * r . Sql ,
SqlArgs : r . Args ,
} , r . Error
2024-01-25 16:07:48 +08:00
}
// Query1 查询
// Query1 return 返回查询到的第一行数据,对象格式
func ( db * DB ) Query1 ( requestSql string , args ... interface { } ) ( map [ string ] interface { } , error ) {
r := db . pool . Query ( requestSql , args ... )
results := r . MapResults ( )
if len ( results ) > 0 {
return results [ 0 ] , r . Error
} else {
2024-03-09 13:43:14 +08:00
return nil , r . Error
2024-01-25 16:07:48 +08:00
}
}
// Query11 查询
// Query11 return 返回查询到的第一行第一列数据,字段类型对应的格式
func ( db * DB ) Query11 ( requestSql string , args ... interface { } ) ( interface { } , error ) {
r := db . pool . Query ( requestSql , args ... )
results := r . SliceResults ( )
if len ( results ) > 0 {
if len ( results [ 0 ] ) > 0 {
return results [ 0 ] [ 0 ] , r . Error
} else {
return nil , r . Error
}
} else {
return nil , r . Error
}
}
// Query1a 查询
// Query1a return 返回查询到的第一列数据,数组格式
func ( db * DB ) Query1a ( requestSql string , args ... interface { } ) ( [ ] interface { } , error ) {
r := db . pool . Query ( requestSql , args ... )
results := r . SliceResults ( )
a := make ( [ ] interface { } , 0 )
for _ , row := range results {
if len ( results [ 0 ] ) > 0 {
a = append ( a , row [ 0 ] )
}
}
return a , r . Error
}
// Insert 插入数据
// * table 表名
// * data 数据对象( Key-Value格式)
// Insert return 如果是INSERT到含有自增字段的表中返回插入的自增ID, 否则返回影响的行数
2024-03-09 13:43:14 +08:00
func ( db * DB ) Insert ( table string , data map [ string ] interface { } ) ( ExecResult , error ) {
2024-01-25 16:07:48 +08:00
r := db . pool . Insert ( table , data )
2024-03-09 13:43:14 +08:00
return ExecResult {
Id : r . Id ( ) ,
Changes : r . Changes ( ) ,
Sql : * r . Sql ,
SqlArgs : r . Args ,
} , r . Error
2024-01-25 16:07:48 +08:00
}
// Replace 替换数据
// Replace return 如果是REPLACE到含有自增字段的表中返回插入的自增ID, 否则返回影响的行数
2024-03-09 13:43:14 +08:00
func ( db * DB ) Replace ( table string , data map [ string ] interface { } ) ( ExecResult , error ) {
2024-01-25 16:07:48 +08:00
r := db . pool . Replace ( table , data )
out := r . Id ( )
if out == 0 {
out = r . Changes ( )
}
2024-03-09 13:43:14 +08:00
return ExecResult {
Id : r . Id ( ) ,
Changes : r . Changes ( ) ,
Sql : * r . Sql ,
SqlArgs : r . Args ,
} , r . Error
2024-01-25 16:07:48 +08:00
}
// Update 更新数据
// * wheres 条件( SQL中WHERE后面的部分)
// Update return 返回影响的行数
2024-03-09 13:43:14 +08:00
func ( db * DB ) Update ( table string , data map [ string ] interface { } , wheres string , args ... interface { } ) ( ExecResult , error ) {
2024-01-25 16:07:48 +08:00
r := db . pool . Update ( table , data , wheres , args ... )
2024-03-09 13:43:14 +08:00
return ExecResult {
Changes : r . Changes ( ) ,
Sql : * r . Sql ,
SqlArgs : r . Args ,
} , r . Error
2024-01-25 16:07:48 +08:00
}
// Delete 删除数据
// Delete return 返回影响的行数
2024-03-09 13:43:14 +08:00
func ( db * DB ) Delete ( table string , wheres string , args ... interface { } ) ( ExecResult , error ) {
2024-01-25 16:07:48 +08:00
r := db . pool . Delete ( table , wheres , args ... )
2024-03-09 13:43:14 +08:00
return ExecResult {
Changes : r . Changes ( ) ,
Sql : * r . Sql ,
SqlArgs : r . Args ,
} , r . Error
2024-01-25 16:07:48 +08:00
}
// MakeId 生成指定字段不唯一的ID
// MakeId idField ID字段
// MakeId idSize ID长度
// MakeId return 新的ID
func ( db * DB ) MakeId ( table string , idField string , idSize uint ) ( string , error ) {
var id string
var err error
2024-03-09 13:43:14 +08:00
for i := 0 ; i < 100 ; i ++ {
2024-01-25 16:07:48 +08:00
if idSize > 20 {
id = u . UniqueId ( )
} else if idSize > 14 {
id = u . UniqueId ( ) [ 0 : idSize ]
} else if idSize > 12 {
id = u . ShortUniqueId ( ) [ 0 : idSize ]
} else if idSize > 10 {
id = u . Id12 ( ) [ 0 : idSize ]
} else if idSize > 8 {
id = u . Id10 ( ) [ 0 : idSize ]
} else if idSize >= 6 {
id = u . Id8 ( ) [ 0 : idSize ]
} else {
id = u . Id6 ( )
}
r := db . pool . Query ( fmt . Sprintf ( "SELECT COUNT(*) FROM `%s` WHERE `%s`=?" , table , idField ) , id )
err = r . Error
if r . IntOnR1C1 ( ) == 0 {
break
}
}
return id , err
}
// Commit 提交事务
func ( tx * Tx ) Commit ( ) error {
return tx . conn . Commit ( )
}
// Rollback 回滚事务
func ( tx * Tx ) Rollback ( ) error {
return tx . conn . Rollback ( )
}
// Finish 根据传入的成功标识提交或回滚事务
// Finish ok 事务是否执行成功
func ( tx * Tx ) Finish ( ok bool ) error {
return tx . conn . Finish ( ok )
}
// CheckFinished 检查事务是否已经提交或回滚,如果事务没有结束则执行回滚操作
func ( tx * Tx ) CheckFinished ( ) error {
return tx . conn . CheckFinished ( )
}
2024-03-09 13:43:14 +08:00
func ( tx * Tx ) Exec ( requestSql string , args ... interface { } ) ( ExecResult , error ) {
2024-01-25 16:07:48 +08:00
r := tx . conn . Exec ( requestSql , args ... )
2024-03-09 13:43:14 +08:00
out := ExecResult { }
lSql := strings . ToLower ( requestSql )
if strings . Contains ( lSql , "insert into" ) || strings . Contains ( lSql , "replace into" ) {
out . Id = r . Id ( )
}
out . Changes = r . Changes ( )
out . Sql = * r . Sql
out . SqlArgs = r . Args
return out , r . Error
2024-01-25 16:07:48 +08:00
}
2024-03-09 13:43:14 +08:00
func ( tx * Tx ) Query ( requestSql string , args ... interface { } ) ( QueryResult , error ) {
2024-01-25 16:07:48 +08:00
r := tx . conn . Query ( requestSql , args ... )
2024-03-09 13:43:14 +08:00
return QueryResult {
Result : r . MapResults ( ) ,
Sql : * r . Sql ,
SqlArgs : r . Args ,
} , r . Error
2024-01-25 16:07:48 +08:00
}
func ( tx * Tx ) Query1 ( requestSql string , args ... interface { } ) ( map [ string ] interface { } , error ) {
r := tx . conn . Query ( requestSql , args ... )
results := r . MapResults ( )
if len ( results ) > 0 {
return results [ 0 ] , r . Error
} else {
2024-03-09 13:43:14 +08:00
return nil , r . Error
2024-01-25 16:07:48 +08:00
}
}
func ( tx * Tx ) Query11 ( requestSql string , args ... interface { } ) ( interface { } , error ) {
r := tx . conn . Query ( requestSql , args ... )
results := r . SliceResults ( )
if len ( results ) > 0 {
if len ( results [ 0 ] ) > 0 {
return results [ 0 ] [ 0 ] , r . Error
} else {
return nil , r . Error
}
} else {
return nil , r . Error
}
}
func ( tx * Tx ) Query1a ( requestSql string , args ... interface { } ) ( [ ] interface { } , error ) {
r := tx . conn . Query ( requestSql , args ... )
results := r . SliceResults ( )
a := make ( [ ] interface { } , 0 )
for _ , row := range results {
if len ( results [ 0 ] ) > 0 {
a = append ( a , row [ 0 ] )
}
}
return a , r . Error
}
2024-03-09 13:43:14 +08:00
func ( tx * Tx ) Insert ( table string , data map [ string ] interface { } ) ( ExecResult , error ) {
2024-01-25 16:07:48 +08:00
r := tx . conn . Insert ( table , data )
2024-03-09 13:43:14 +08:00
return ExecResult {
Id : r . Id ( ) ,
Changes : r . Changes ( ) ,
Sql : * r . Sql ,
SqlArgs : r . Args ,
} , r . Error
2024-01-25 16:07:48 +08:00
}
2024-03-09 13:43:14 +08:00
func ( tx * Tx ) Replace ( table string , data map [ string ] interface { } ) ( ExecResult , error ) {
2024-01-25 16:07:48 +08:00
r := tx . conn . Replace ( table , data )
2024-03-09 13:43:14 +08:00
return ExecResult {
Id : r . Id ( ) ,
Changes : r . Changes ( ) ,
Sql : * r . Sql ,
SqlArgs : r . Args ,
} , r . Error
2024-01-25 16:07:48 +08:00
}
2024-03-09 13:43:14 +08:00
func ( tx * Tx ) Update ( table string , data map [ string ] interface { } , wheres string , args ... interface { } ) ( ExecResult , error ) {
2024-01-25 16:07:48 +08:00
r := tx . conn . Update ( table , data , wheres , args ... )
2024-03-09 13:43:14 +08:00
return ExecResult {
Changes : r . Changes ( ) ,
Sql : * r . Sql ,
SqlArgs : r . Args ,
} , r . Error
2024-01-25 16:07:48 +08:00
}
2024-03-09 13:43:14 +08:00
func ( tx * Tx ) Delete ( table string , wheres string , args ... interface { } ) ( ExecResult , error ) {
2024-01-25 16:07:48 +08:00
r := tx . conn . Delete ( table , wheres , args ... )
2024-03-09 13:43:14 +08:00
return ExecResult {
Changes : r . Changes ( ) ,
Sql : * r . Sql ,
SqlArgs : r . Args ,
} , r . Error
2024-01-25 16:07:48 +08:00
}