From a689f34765066533c5db95d456d998ffd797acab Mon Sep 17 00:00:00 2001 From: wxkj Date: Wed, 8 Aug 2018 09:09:28 +0800 Subject: [PATCH 1/9] =?UTF-8?q?add=20=E6=94=AF=E6=8C=81sqlite?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/.DS_Store | Bin 0 -> 6148 bytes g/database/.DS_Store | Bin 0 -> 6148 bytes g/database/gdb/gdb.go | 380 ++++++++++++++++++----------------- g/database/gdb/gdb_sqlite.go | 52 +++++ 4 files changed, 245 insertions(+), 187 deletions(-) create mode 100644 g/.DS_Store create mode 100644 g/database/.DS_Store create mode 100644 g/database/gdb/gdb_sqlite.go diff --git a/g/.DS_Store b/g/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..64a783f01ecf75f2b96841131cf3537fbd794989 GIT binary patch literal 6148 zcmeHKJ8Hu~5S_7A2;8W2xmU;y7NeX%7f6gvn&5z)q*mo~FWe@@3kQ++>S++KFzy~D5g zuWyH!xc5GhSt>vUr~nn90#x8v3Rv%j^{YTeDnJFOz(oQ3J`}iNO`HS$(}Cb40I);a z4QrnzfW;EPnm7j{1Jj@agQ_`VXwZ=_SyvP1z@Urf@S*u+%?U;Q>A1gmxo8b!qykjn zR)J+~2kZZj@E_*?TM~CvfC~I81+*Kdaf4UN-rBsJ_1Xe|f?LfO+ze}{Ab2|ldOOC( f+VR?pqORB)=QVK-bUN}*2l8jYbfHm!zgFNIWJwii literal 0 HcmV?d00001 diff --git a/g/database/.DS_Store b/g/database/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..f8c118ae143a200454b2bba70e3105950d76f110 GIT binary patch literal 6148 zcmeH~Jr2S!425mzfW*>~F$)La1`&c2Z~+9BSSm3f_8gt(pM}DVD)cPbU+mOs`-Y|# z5#2wBok%YtE4Wd%7AB_1mvWOqF2mzGUhenNN^Xm!72v&0_H&z{0#twsPys4H1!kl` z9^|X_jGl>)LItS6JQT3+LxCG>vIYIqf#4$m*rDu(wa*e@u>x3=Er<$CqZN!+^)bZi z-VT<$t|nVB+C_8t(7dzS6a&*}7cEF&S{)2jfC@|$SVrF4`G16eoBt;*OsN1B_%j8x zJDd)Cyi}g8AFpTib5?EL;GkcQ@b(jc#E#+(+ztE17GO=bASy8a2)GOkRN$uyyZ|fX B5n2EM literal 0 HcmV?d00001 diff --git a/g/database/gdb/gdb.go b/g/database/gdb/gdb.go index 8c44a28f9..964741a97 100644 --- a/g/database/gdb/gdb.go +++ b/g/database/gdb/gdb.go @@ -8,120 +8,119 @@ package gdb import ( - "fmt" - "errors" - "database/sql" - "gitee.com/johng/gf/g/util/grand" - _ "github.com/lib/pq" - _ "github.com/go-sql-driver/mysql" - "gitee.com/johng/gf/g/container/gtype" - "gitee.com/johng/gf/g/container/gring" - "gitee.com/johng/gf/g/os/gcache" - "gitee.com/johng/gf/g/container/gmap" - "time" + "database/sql" + "errors" + "fmt" + "time" + + "gitee.com/johng/gf/g/container/gmap" + "gitee.com/johng/gf/g/container/gring" + "gitee.com/johng/gf/g/container/gtype" + "gitee.com/johng/gf/g/os/gcache" + "gitee.com/johng/gf/g/util/grand" + _ "github.com/go-sql-driver/mysql" + _ "github.com/lib/pq" ) const ( - OPTION_INSERT = 0 - OPTION_REPLACE = 1 - OPTION_SAVE = 2 - OPTION_IGNORE = 3 + OPTION_INSERT = 0 + OPTION_REPLACE = 1 + OPTION_SAVE = 2 + OPTION_IGNORE = 3 ) // 数据库操作接口 type Link interface { - // 打开数据库连接,建立数据库操作对象 - Open (c *ConfigNode) (*sql.DB, error) + // 打开数据库连接,建立数据库操作对象 + Open(c *ConfigNode) (*sql.DB, error) - // SQL操作方法 - Query(q string, args ...interface{}) (*sql.Rows, error) - Exec(q string, args ...interface{}) (sql.Result, error) - Prepare(q string) (*sql.Stmt, error) + // SQL操作方法 + Query(q string, args ...interface{}) (*sql.Rows, error) + Exec(q string, args ...interface{}) (sql.Result, error) + Prepare(q string) (*sql.Stmt, error) - // 数据库查询 - GetAll(q string, args ...interface{}) (Result, error) - GetOne(q string, args ...interface{}) (Record, error) - GetValue(q string, args ...interface{}) (Value, error) + // 数据库查询 + GetAll(q string, args ...interface{}) (Result, error) + GetOne(q string, args ...interface{}) (Record, error) + GetValue(q string, args ...interface{}) (Value, error) - // Ping - PingMaster() error - PingSlave() error + // Ping + PingMaster() error + PingSlave() error - // 连接属性设置 - SetMaxIdleConns(n int) - SetMaxOpenConns(n int) - SetConnMaxLifetime(d time.Duration) + // 连接属性设置 + SetMaxIdleConns(n int) + SetMaxOpenConns(n int) + SetConnMaxLifetime(d time.Duration) - // 开启事务操作 - Begin() (*Tx, error) + // 开启事务操作 + Begin() (*Tx, error) - // 数据表插入/更新/保存操作 - Insert(table string, data Map) (sql.Result, error) - Replace(table string, data Map) (sql.Result, error) - Save(table string, data Map) (sql.Result, error) + // 数据表插入/更新/保存操作 + Insert(table string, data Map) (sql.Result, error) + Replace(table string, data Map) (sql.Result, error) + Save(table string, data Map) (sql.Result, error) - // 数据表插入/更新/保存操作(批量) - BatchInsert(table string, list List, batch int) (sql.Result, error) - BatchReplace(table string, list List, batch int) (sql.Result, error) - BatchSave(table string, list List, batch int) (sql.Result, error) + // 数据表插入/更新/保存操作(批量) + BatchInsert(table string, list List, batch int) (sql.Result, error) + BatchReplace(table string, list List, batch int) (sql.Result, error) + BatchSave(table string, list List, batch int) (sql.Result, error) - // 数据修改/删除 - Update(table string, data interface{}, condition interface{}, args ...interface{}) (sql.Result, error) - Delete(table string, condition interface{}, args ...interface{}) (sql.Result, error) + // 数据修改/删除 + Update(table string, data interface{}, condition interface{}, args ...interface{}) (sql.Result, error) + Delete(table string, condition interface{}, args ...interface{}) (sql.Result, error) - // 创建链式操作对象(Table为From的别名) - Table(tables string) (*Model) - From(tables string) (*Model) + // 创建链式操作对象(Table为From的别名) + Table(tables string) *Model + From(tables string) *Model - // 关闭数据库操作对象 - Close() error + // 关闭数据库操作对象 + Close() error - // 内部方法 - insert(table string, data Map, option uint8) (sql.Result, error) - batchInsert(table string, list List, batch int, option uint8) (sql.Result, error) + // 内部方法 + insert(table string, data Map, option uint8) (sql.Result, error) + batchInsert(table string, list List, batch int, option uint8) (sql.Result, error) - getQuoteCharLeft () string - getQuoteCharRight () string - handleSqlBeforeExec(q *string) *string + getQuoteCharLeft() string + getQuoteCharRight() string + handleSqlBeforeExec(q *string) *string } // 数据库链接对象 type Db struct { - link Link // 底层数据库类型管理对象 - master *sql.DB // 实例化数据库链接(master) - slave *sql.DB // 实例化数据库链接(slave,可能会与master相同) - charl string // SQL安全符号(左) - charr string // SQL安全符号(右) - debug *gtype.Bool // (默认关闭)是否开启调试模式,当开启时会启用一些调试特性 - sqls *gring.Ring // (debug=true时有效)已执行的SQL列表 - cache *gcache.Cache // 查询缓存,需要注意的是,事务查询不支持缓存 + link Link // 底层数据库类型管理对象 + master *sql.DB // 实例化数据库链接(master) + slave *sql.DB // 实例化数据库链接(slave,可能会与master相同) + charl string // SQL安全符号(左) + charr string // SQL安全符号(右) + debug *gtype.Bool // (默认关闭)是否开启调试模式,当开启时会启用一些调试特性 + sqls *gring.Ring // (debug=true时有效)已执行的SQL列表 + cache *gcache.Cache // 查询缓存,需要注意的是,事务查询不支持缓存 } // 执行的SQL对象 type Sql struct { - Sql string // SQL语句(可能带有预处理占位符) - Args []interface{} // 预处理参数值列表 - Error error // 执行结果(nil为成功) - Cost int64 // 执行时间消耗(毫秒) - Func string // 执行方法名称 + Sql string // SQL语句(可能带有预处理占位符) + Args []interface{} // 预处理参数值列表 + Error error // 执行结果(nil为成功) + Cost int64 // 执行时间消耗(毫秒) + Func string // 执行方法名称 } // 返回数据表记录值 -type Value []byte +type Value []byte // 返回数据表记录Map -type Record map[string]Value +type Record map[string]Value // 返回数据表记录List -type Result []Record - +type Result []Record // 关联数组,绑定一条数据表记录(使用别名) -type Map = map[string]interface{} +type Map = map[string]interface{} // 关联数组列表(索引从0开始的数组),绑定多条记录(使用别名) -type List = []Map - +type List = []Map // MySQL接口对象 var linkMysql = &dbmysql{} @@ -129,45 +128,49 @@ var linkMysql = &dbmysql{} // PostgreSQL接口对象 var linkPgsql = &dbpgsql{} +//Sqlite接口对象 +//@author wxkj +var linkSqlite = &dbsqlite{} + // 数据库查询缓存对象map,使用数据库连接名称作为键名,键值为查询缓存对象 -var dbCaches = gmap.NewStringInterfaceMap() +var dbCaches = gmap.NewStringInterfaceMap() // 使用默认/指定分组配置进行连接,数据库集群配置项:default -func New(groupName...string) (*Db, error) { - name := config.d - if len(groupName) > 0 { - name = groupName[0] - } - config.RLock() - defer config.RUnlock() +func New(groupName ...string) (*Db, error) { + name := config.d + if len(groupName) > 0 { + name = groupName[0] + } + config.RLock() + defer config.RUnlock() - if len(config.c) < 1 { - return nil, errors.New("empty database configuration") - } - if list, ok := config.c[name]; ok { - // 将master, slave集群列表拆分出来 - masterList := make(ConfigGroup, 0) - slaveList := make(ConfigGroup, 0) - for i := 0; i < len(list); i++ { - if list[i].Role == "slave" { - slaveList = append(slaveList, list[i]) - } else { - // 默认配置项的角色为master - masterList = append(masterList, list[i]) - } - } - if len(masterList) < 1 { - return nil, errors.New("at least one master node configuration's need to make sense") - } - masterNode := getConfigNodeByPriority(masterList) - var slaveNode *ConfigNode - if len(slaveList) > 0 { - slaveNode = getConfigNodeByPriority(slaveList) - } - return newDb(masterNode, slaveNode, name) - } else { - return nil, errors.New(fmt.Sprintf("empty database configuration for item name '%s'", name)) - } + if len(config.c) < 1 { + return nil, errors.New("empty database configuration") + } + if list, ok := config.c[name]; ok { + // 将master, slave集群列表拆分出来 + masterList := make(ConfigGroup, 0) + slaveList := make(ConfigGroup, 0) + for i := 0; i < len(list); i++ { + if list[i].Role == "slave" { + slaveList = append(slaveList, list[i]) + } else { + // 默认配置项的角色为master + masterList = append(masterList, list[i]) + } + } + if len(masterList) < 1 { + return nil, errors.New("at least one master node configuration's need to make sense") + } + masterNode := getConfigNodeByPriority(masterList) + var slaveNode *ConfigNode + if len(slaveList) > 0 { + slaveNode = getConfigNodeByPriority(slaveList) + } + return newDb(masterNode, slaveNode, name) + } else { + return nil, errors.New(fmt.Sprintf("empty database configuration for item name '%s'", name)) + } } // 按照负载均衡算法(优先级配置)从数据库集群中选择一个配置节点出来使用 @@ -176,84 +179,87 @@ func New(groupName...string) (*Db, error) { // 2、那么节点1的权重范围为[0, 99],节点2的权重范围为[100, 199],比例为1:1; // 3、假如计算出的随机数为99; // 4、那么选择的配置为节点1; -func getConfigNodeByPriority (cg ConfigGroup) *ConfigNode { - if len(cg) < 2 { - return &cg[0] - } - var total int - for i := 0; i < len(cg); i++ { - total += cg[i].Priority * 100 - } - // 不能取到末尾的边界点 - r := grand.Rand(0, total) - if r > 0 { - r -= 1 - } - min := 0 - max := 0 - for i := 0; i < len(cg); i++ { - max = min + cg[i].Priority * 100 - //fmt.Printf("r: %d, min: %d, max: %d\n", r, min, max) - if r >= min && r < max { - return &cg[i] - } else { - min = max - } - } - return nil +func getConfigNodeByPriority(cg ConfigGroup) *ConfigNode { + if len(cg) < 2 { + return &cg[0] + } + var total int + for i := 0; i < len(cg); i++ { + total += cg[i].Priority * 100 + } + // 不能取到末尾的边界点 + r := grand.Rand(0, total) + if r > 0 { + r -= 1 + } + min := 0 + max := 0 + for i := 0; i < len(cg); i++ { + max = min + cg[i].Priority*100 + //fmt.Printf("r: %d, min: %d, max: %d\n", r, min, max) + if r >= min && r < max { + return &cg[i] + } else { + min = max + } + } + return nil } // 创建数据库链接对象 -func newDb (masterNode *ConfigNode, slaveNode *ConfigNode, groupName string) (*Db, error) { - var link Link - switch masterNode.Type { - case "mysql": link = linkMysql - case "pgsql": link = linkPgsql - default: - return nil, errors.New(fmt.Sprintf("unsupported db type '%s'", masterNode.Type)) - } - master, err := link.Open(masterNode) - if err != nil { - return nil, err - } - slave := master - if slaveNode != nil { - slave, err = link.Open(slaveNode) - if err != nil { - return nil, err - } - } - db := &Db { - link : link, - master : master, - slave : slave, - charl : link.getQuoteCharLeft(), - charr : link.getQuoteCharRight(), - debug : gtype.NewBool(), - } - // 设置连接属性,master和slave必须是一致的,所以这里使用的是master的属性设置 - if masterNode.MaxIdleConnCount > 0 { - db.SetMaxIdleConns(masterNode.MaxIdleConnCount) - } - if masterNode.MaxOpenConnCount > 0 { - db.SetMaxOpenConns(masterNode.MaxOpenConnCount) - } - if masterNode.MaxConnLifetime > 0 { - db.SetConnMaxLifetime(time.Duration(masterNode.MaxConnLifetime)*time.Second) - } - if v := dbCaches.Get(groupName); v == nil { - dbCaches.LockFunc(func(m map[string]interface{}) { - if v, ok := m[groupName]; !ok { - db.cache = gcache.New() - m[groupName] = db.cache - } else { - db.cache = v.(*gcache.Cache) - } - }) - } else { - db.cache = v.(*gcache.Cache) - } +func newDb(masterNode *ConfigNode, slaveNode *ConfigNode, groupName string) (*Db, error) { + var link Link + switch masterNode.Type { + case "mysql": + link = linkMysql + case "pgsql": + link = linkPgsql + case "sqlite": + link = linkSqlite + default: + return nil, errors.New(fmt.Sprintf("unsupported db type '%s'", masterNode.Type)) + } + master, err := link.Open(masterNode) + if err != nil { + return nil, err + } + slave := master + if slaveNode != nil { + slave, err = link.Open(slaveNode) + if err != nil { + return nil, err + } + } + db := &Db{ + link: link, + master: master, + slave: slave, + charl: link.getQuoteCharLeft(), + charr: link.getQuoteCharRight(), + debug: gtype.NewBool(), + } + // 设置连接属性,master和slave必须是一致的,所以这里使用的是master的属性设置 + if masterNode.MaxIdleConnCount > 0 { + db.SetMaxIdleConns(masterNode.MaxIdleConnCount) + } + if masterNode.MaxOpenConnCount > 0 { + db.SetMaxOpenConns(masterNode.MaxOpenConnCount) + } + if masterNode.MaxConnLifetime > 0 { + db.SetConnMaxLifetime(time.Duration(masterNode.MaxConnLifetime) * time.Second) + } + if v := dbCaches.Get(groupName); v == nil { + dbCaches.LockFunc(func(m map[string]interface{}) { + if v, ok := m[groupName]; !ok { + db.cache = gcache.New() + m[groupName] = db.cache + } else { + db.cache = v.(*gcache.Cache) + } + }) + } else { + db.cache = v.(*gcache.Cache) + } - return db, nil + return db, nil } - diff --git a/g/database/gdb/gdb_sqlite.go b/g/database/gdb/gdb_sqlite.go new file mode 100644 index 000000000..def1a5f5e --- /dev/null +++ b/g/database/gdb/gdb_sqlite.go @@ -0,0 +1,52 @@ +// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://gitee.com/johng/gf. +//@author wxkj + +package gdb + +import ( + "database/sql" + "os" +) + +// 数据库链接对象 +type dbsqlite struct { + Db +} + +func (db *dbsqlite) Open(c *ConfigNode) (*sql.DB, error) { + var source string + if c.Linkinfo != "" { + source = c.Linkinfo + } else { + path, err := os.Getwd() + if err != nil { + return nil, err + } + //先这样吧 + source = path + c.Host + c.Name + } + if db, err := sql.Open("sqlite3", source); err == nil { + return db, nil + } else { + return nil, err + } +} + +// 获得关键字操作符 - 左 +func (db *dbsqlite) getQuoteCharLeft() string { + return "`" +} + +// 获得关键字操作符 - 右 +func (db *dbsqlite) getQuoteCharRight() string { + return "`" +} + +// 在执行sql之前对sql进行进一步处理 +func (db *dbsqlite) handleSqlBeforeExec(q *string) *string { + return q +} From 15e7a9b8a852ba2a5970a76820f14fce9c40bf65 Mon Sep 17 00:00:00 2001 From: wxkj Date: Wed, 8 Aug 2018 13:37:08 +0800 Subject: [PATCH 2/9] update --- g/database/gdb/gdb.go | 7 +++---- g/database/gdb/gdb_sqlite.go | 11 +++++------ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/g/database/gdb/gdb.go b/g/database/gdb/gdb.go index 964741a97..9c33cddb4 100644 --- a/g/database/gdb/gdb.go +++ b/g/database/gdb/gdb.go @@ -11,8 +11,6 @@ import ( "database/sql" "errors" "fmt" - "time" - "gitee.com/johng/gf/g/container/gmap" "gitee.com/johng/gf/g/container/gring" "gitee.com/johng/gf/g/container/gtype" @@ -20,6 +18,7 @@ import ( "gitee.com/johng/gf/g/util/grand" _ "github.com/go-sql-driver/mysql" _ "github.com/lib/pq" + "time" ) const ( @@ -128,8 +127,8 @@ var linkMysql = &dbmysql{} // PostgreSQL接口对象 var linkPgsql = &dbpgsql{} -//Sqlite接口对象 -//@author wxkj +// Sqlite接口对象 +//@author wxkj var linkSqlite = &dbsqlite{} // 数据库查询缓存对象map,使用数据库连接名称作为键名,键值为查询缓存对象 diff --git a/g/database/gdb/gdb_sqlite.go b/g/database/gdb/gdb_sqlite.go index def1a5f5e..443f2ea27 100644 --- a/g/database/gdb/gdb_sqlite.go +++ b/g/database/gdb/gdb_sqlite.go @@ -9,7 +9,6 @@ package gdb import ( "database/sql" - "os" ) // 数据库链接对象 @@ -22,12 +21,12 @@ func (db *dbsqlite) Open(c *ConfigNode) (*sql.DB, error) { if c.Linkinfo != "" { source = c.Linkinfo } else { - path, err := os.Getwd() - if err != nil { - return nil, err - } + //path, err := os.Getwd() + //if err != nil { + // return nil, err + //} //先这样吧 - source = path + c.Host + c.Name + source = c.Name } if db, err := sql.Open("sqlite3", source); err == nil { return db, nil From 1ac39cd2e087c727594e523187684b704fe37bbd Mon Sep 17 00:00:00 2001 From: wxkj Date: Wed, 8 Aug 2018 13:53:24 +0800 Subject: [PATCH 3/9] rm .DS_Store --- .gitignore | 1 + g/.DS_Store | Bin 6148 -> 0 bytes g/database/.DS_Store | Bin 6148 -> 0 bytes g/database/gdb/gdb.go | 9 +++------ 4 files changed, 4 insertions(+), 6 deletions(-) delete mode 100644 g/.DS_Store delete mode 100644 g/database/.DS_Store diff --git a/.gitignore b/.gitignore index 213eb4ae1..638a8dbb0 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ gitpush.sh pkg/ bin/ cbuild +*/.DS_Store diff --git a/g/.DS_Store b/g/.DS_Store deleted file mode 100644 index 64a783f01ecf75f2b96841131cf3537fbd794989..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKJ8Hu~5S_7A2;8W2xmU;y7NeX%7f6gvn&5z)q*mo~FWe@@3kQ++>S++KFzy~D5g zuWyH!xc5GhSt>vUr~nn90#x8v3Rv%j^{YTeDnJFOz(oQ3J`}iNO`HS$(}Cb40I);a z4QrnzfW;EPnm7j{1Jj@agQ_`VXwZ=_SyvP1z@Urf@S*u+%?U;Q>A1gmxo8b!qykjn zR)J+~2kZZj@E_*?TM~CvfC~I81+*Kdaf4UN-rBsJ_1Xe|f?LfO+ze}{Ab2|ldOOC( f+VR?pqORB)=QVK-bUN}*2l8jYbfHm!zgFNIWJwii diff --git a/g/database/.DS_Store b/g/database/.DS_Store deleted file mode 100644 index f8c118ae143a200454b2bba70e3105950d76f110..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~Jr2S!425mzfW*>~F$)La1`&c2Z~+9BSSm3f_8gt(pM}DVD)cPbU+mOs`-Y|# z5#2wBok%YtE4Wd%7AB_1mvWOqF2mzGUhenNN^Xm!72v&0_H&z{0#twsPys4H1!kl` z9^|X_jGl>)LItS6JQT3+LxCG>vIYIqf#4$m*rDu(wa*e@u>x3=Er<$CqZN!+^)bZi z-VT<$t|nVB+C_8t(7dzS6a&*}7cEF&S{)2jfC@|$SVrF4`G16eoBt;*OsN1B_%j8x zJDd)Cyi}g8AFpTib5?EL;GkcQ@b(jc#E#+(+ztE17GO=bASy8a2)GOkRN$uyyZ|fX B5n2EM diff --git a/g/database/gdb/gdb.go b/g/database/gdb/gdb.go index 9c33cddb4..d473308dc 100644 --- a/g/database/gdb/gdb.go +++ b/g/database/gdb/gdb.go @@ -209,12 +209,9 @@ func getConfigNodeByPriority(cg ConfigGroup) *ConfigNode { func newDb(masterNode *ConfigNode, slaveNode *ConfigNode, groupName string) (*Db, error) { var link Link switch masterNode.Type { - case "mysql": - link = linkMysql - case "pgsql": - link = linkPgsql - case "sqlite": - link = linkSqlite + case "mysql":link = linkMysql + case "pgsql":link = linkPgsql + case "sqlite":link = linkSqlite default: return nil, errors.New(fmt.Sprintf("unsupported db type '%s'", masterNode.Type)) } From cc0bcbf144402b1f74aaf4dd78735cf770ea18ef Mon Sep 17 00:00:00 2001 From: wxkj Date: Wed, 8 Aug 2018 14:02:23 +0800 Subject: [PATCH 4/9] update --- g/database/gdb/gdb.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/g/database/gdb/gdb.go b/g/database/gdb/gdb.go index d473308dc..5f8e6d10b 100644 --- a/g/database/gdb/gdb.go +++ b/g/database/gdb/gdb.go @@ -127,7 +127,7 @@ var linkMysql = &dbmysql{} // PostgreSQL接口对象 var linkPgsql = &dbpgsql{} -// Sqlite接口对象 +//Sqlite接口对象 //@author wxkj var linkSqlite = &dbsqlite{} @@ -209,9 +209,12 @@ func getConfigNodeByPriority(cg ConfigGroup) *ConfigNode { func newDb(masterNode *ConfigNode, slaveNode *ConfigNode, groupName string) (*Db, error) { var link Link switch masterNode.Type { - case "mysql":link = linkMysql - case "pgsql":link = linkPgsql - case "sqlite":link = linkSqlite + case "mysql": + link = linkMysql + case "pgsql": + link = linkPgsql + case "sqlite": + link = linkSqlite default: return nil, errors.New(fmt.Sprintf("unsupported db type '%s'", masterNode.Type)) } From e6d1a89d9f525cbec7c8c75ced9ccc1996927e2e Mon Sep 17 00:00:00 2001 From: john Date: Wed, 8 Aug 2018 19:03:48 +0800 Subject: [PATCH 5/9] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8E=A7=E5=88=B6?= =?UTF-8?q?=E5=99=A8=E5=92=8C=E6=89=A7=E8=A1=8C=E5=AF=B9=E8=B1=A1=E7=BB=91?= =?UTF-8?q?=E5=AE=9A'/'=E8=B7=AF=E7=94=B1=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/net/ghttp/ghttp_server_service_controller.go | 6 ++++++ g/net/ghttp/ghttp_server_service_object.go | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/g/net/ghttp/ghttp_server_service_controller.go b/g/net/ghttp/ghttp_server_service_controller.go index 825edbd57..336da858f 100644 --- a/g/net/ghttp/ghttp_server_service_controller.go +++ b/g/net/ghttp/ghttp_server_service_controller.go @@ -40,6 +40,9 @@ func (s *Server)BindController(pattern string, c Controller, methods...string) e p := key if strings.EqualFold(p[len(p) - 6:], "/index") { p = p[0 : len(p) - 6] + if len(p) == 0 { + p = "/" + } } m[p] = &handlerItem { ctype : v.Elem().Type(), @@ -75,6 +78,9 @@ func (s *Server)BindControllerMethod(pattern string, c Controller, methods strin p := key if strings.EqualFold(p[len(p) - 6:], "/index") { p = p[0 : len(p) - 6] + if len(p) == 0 { + p = "/" + } } m[p] = &handlerItem { ctype : t, diff --git a/g/net/ghttp/ghttp_server_service_object.go b/g/net/ghttp/ghttp_server_service_object.go index e3467b0be..52ebea54f 100644 --- a/g/net/ghttp/ghttp_server_service_object.go +++ b/g/net/ghttp/ghttp_server_service_object.go @@ -36,6 +36,9 @@ func (s *Server)BindObject(pattern string, obj interface{}, methods...string) er p := key if strings.EqualFold(p[len(p) - 6:], "/index") { p = p[0 : len(p) - 6] + if len(p) == 0 { + p = "/" + } } m[p] = &handlerItem { ctype : nil, @@ -71,6 +74,9 @@ func (s *Server)BindObjectMethod(pattern string, obj interface{}, methods string p := key if strings.EqualFold(p[len(p) - 6:], "/index") { p = p[0 : len(p) - 6] + if len(p) == 0 { + p = "/" + } } m[p] = &handlerItem { ctype : nil, From 44cd5275d59e536cf1712d467aeb642d764a08c3 Mon Sep 17 00:00:00 2001 From: john Date: Wed, 8 Aug 2018 20:09:52 +0800 Subject: [PATCH 6/9] =?UTF-8?q?=E6=96=B0=E5=A2=9Esqlite=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/database/gdb/gdb.go | 28 ++++++++++++++-------------- g/database/gdb/gdb_pgsql.go | 4 +++- g/database/gdb/gdb_sqlite.go | 10 ++++------ g/database/gdb/gdb_transaction.go | 7 +++---- 4 files changed, 24 insertions(+), 25 deletions(-) diff --git a/g/database/gdb/gdb.go b/g/database/gdb/gdb.go index 5f8e6d10b..22b899add 100644 --- a/g/database/gdb/gdb.go +++ b/g/database/gdb/gdb.go @@ -5,20 +5,20 @@ // You can obtain one at https://gitee.com/johng/gf. // 数据库ORM. +// 默认内置支持MySQL, 其他数据库需要手动import对应的数据库引擎第三方包. package gdb import ( - "database/sql" - "errors" "fmt" + "time" + "errors" + "database/sql" "gitee.com/johng/gf/g/container/gmap" "gitee.com/johng/gf/g/container/gring" "gitee.com/johng/gf/g/container/gtype" "gitee.com/johng/gf/g/os/gcache" "gitee.com/johng/gf/g/util/grand" _ "github.com/go-sql-driver/mysql" - _ "github.com/lib/pq" - "time" ) const ( @@ -127,8 +127,8 @@ var linkMysql = &dbmysql{} // PostgreSQL接口对象 var linkPgsql = &dbpgsql{} -//Sqlite接口对象 -//@author wxkj +// Sqlite接口对象 +// @author wxkj var linkSqlite = &dbsqlite{} // 数据库查询缓存对象map,使用数据库连接名称作为键名,键值为查询缓存对象 @@ -209,14 +209,14 @@ func getConfigNodeByPriority(cg ConfigGroup) *ConfigNode { func newDb(masterNode *ConfigNode, slaveNode *ConfigNode, groupName string) (*Db, error) { var link Link switch masterNode.Type { - case "mysql": - link = linkMysql - case "pgsql": - link = linkPgsql - case "sqlite": - link = linkSqlite - default: - return nil, errors.New(fmt.Sprintf("unsupported db type '%s'", masterNode.Type)) + case "mysql": + link = linkMysql + case "pgsql": + link = linkPgsql + case "sqlite": + link = linkSqlite + default: + return nil, errors.New(fmt.Sprintf("unsupported db type '%s'", masterNode.Type)) } master, err := link.Open(masterNode) if err != nil { diff --git a/g/database/gdb/gdb_pgsql.go b/g/database/gdb/gdb_pgsql.go index bf4bf903b..7164ff513 100644 --- a/g/database/gdb/gdb_pgsql.go +++ b/g/database/gdb/gdb_pgsql.go @@ -13,7 +13,9 @@ import ( "database/sql" ) -// postgresql的适配 +// PostgreSQL的适配. +// 使用时需要import: +// _ "github.com/lib/pq" // @todo 需要完善replace和save的操作覆盖 // 数据库链接对象 diff --git a/g/database/gdb/gdb_sqlite.go b/g/database/gdb/gdb_sqlite.go index 443f2ea27..6c67da878 100644 --- a/g/database/gdb/gdb_sqlite.go +++ b/g/database/gdb/gdb_sqlite.go @@ -3,7 +3,7 @@ // This Source Code Form is subject to the terms of the MIT License. // If a copy of the MIT was not distributed with this file, // You can obtain one at https://gitee.com/johng/gf. -//@author wxkj +// @author wxkj package gdb @@ -11,6 +11,9 @@ import ( "database/sql" ) +// 使用时需要import: +// _ "github.com/mattn/go-sqlite3" + // 数据库链接对象 type dbsqlite struct { Db @@ -21,11 +24,6 @@ func (db *dbsqlite) Open(c *ConfigNode) (*sql.DB, error) { if c.Linkinfo != "" { source = c.Linkinfo } else { - //path, err := os.Getwd() - //if err != nil { - // return nil, err - //} - //先这样吧 source = c.Name } if db, err := sql.Open("sqlite3", source); err == nil { diff --git a/g/database/gdb/gdb_transaction.go b/g/database/gdb/gdb_transaction.go index 09d0cc94f..33be6cf73 100644 --- a/g/database/gdb/gdb_transaction.go +++ b/g/database/gdb/gdb_transaction.go @@ -10,12 +10,11 @@ import ( "fmt" "errors" "strings" - "database/sql" - _ "github.com/lib/pq" - _ "github.com/go-sql-driver/mysql" - "gitee.com/johng/gf/g/util/gconv" "reflect" + "database/sql" "gitee.com/johng/gf/g/os/gtime" + "gitee.com/johng/gf/g/util/gconv" + _ "github.com/go-sql-driver/mysql" ) // 数据库事务对象 From 44c615ffae28ba3d95def23996ebdc252ca9054b Mon Sep 17 00:00:00 2001 From: john Date: Wed, 8 Aug 2018 20:37:15 +0800 Subject: [PATCH 7/9] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=B0=83=E8=AF=95?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E4=B8=8B=E7=9A=84SQL=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E6=89=93=E5=8D=B0=E6=96=B9=E6=B3=95PrintQueriedSqls;=E6=94=B9?= =?UTF-8?q?=E8=BF=9Bgtime.NewFromTimeStamp=E6=96=B9=E6=B3=95=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=BA=B3=E7=A7=92=E7=BA=A7=E7=9A=84=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E6=88=B3=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/database/gdb/gdb.go | 3 ++- g/database/gdb/gdb_base.go | 23 ++++++++++++++++++++--- g/database/gdb/gdb_transaction.go | 6 ++++-- g/os/gtime/gtime_time.go | 9 ++++++--- geg/database/mysql/gdb_debug.go | 28 ++++++++++------------------ geg/other/test.go | 19 ++++++++++++------- 6 files changed, 54 insertions(+), 34 deletions(-) diff --git a/g/database/gdb/gdb.go b/g/database/gdb/gdb.go index 22b899add..aaeb3ce71 100644 --- a/g/database/gdb/gdb.go +++ b/g/database/gdb/gdb.go @@ -102,7 +102,8 @@ type Sql struct { Sql string // SQL语句(可能带有预处理占位符) Args []interface{} // 预处理参数值列表 Error error // 执行结果(nil为成功) - Cost int64 // 执行时间消耗(毫秒) + Start int64 // 执行开始时间(毫秒) + End int64 // 执行结束时间(毫秒) Func string // 执行方法名称 } diff --git a/g/database/gdb/gdb_base.go b/g/database/gdb/gdb_base.go index f3754a942..01ec77e2a 100644 --- a/g/database/gdb/gdb_base.go +++ b/g/database/gdb/gdb_base.go @@ -32,7 +32,7 @@ func (db *Db) SetDebug(debug bool) { } } -// 获取已经执行的SQL列表 +// 获取已经执行的SQL列表(仅在debug=true时有效) func (db *Db) GetQueriedSqls() []*Sql { if db.sqls == nil { return nil @@ -49,6 +49,21 @@ func (db *Db) GetQueriedSqls() []*Sql { return sqls } +// 打印已经执行的SQL列表(仅在debug=true时有效) +func (db *Db) PrintQueriedSqls() { + sqls := db.GetQueriedSqls() + for k, v := range sqls { + fmt.Println(len(sqls) - k, ":") + fmt.Println(" Sql :", v.Sql) + fmt.Println(" Args :", v.Args) + fmt.Println(" Error:", v.Error) + fmt.Println(" Start:", gtime.NewFromTimeStamp(v.Start).Format("Y-m-d H:i:s.u")) + fmt.Println(" End :", gtime.NewFromTimeStamp(v.End).Format("Y-m-d H:i:s.u")) + fmt.Println(" Cost :", v.End - v.Start, "ms") + fmt.Println(" Func :", v.Func) + } +} + // 关闭链接 func (db *Db) Close() error { if db.master != nil { @@ -81,7 +96,8 @@ func (db *Db) Query(query string, args ...interface{}) (*sql.Rows, error) { Sql : *p, Args : args, Error : err, - Cost : militime2 - militime1, + Start : militime1, + End : militime2, Func : "DB:Query", }) } else { @@ -108,7 +124,8 @@ func (db *Db) Exec(query string, args ...interface{}) (sql.Result, error) { Sql : *p, Args : args, Error : err, - Cost : militime2 - militime1, + Start : militime1, + End : militime2, Func : "DB:Exec", }) } else { diff --git a/g/database/gdb/gdb_transaction.go b/g/database/gdb/gdb_transaction.go index 33be6cf73..86d51d7dd 100644 --- a/g/database/gdb/gdb_transaction.go +++ b/g/database/gdb/gdb_transaction.go @@ -46,7 +46,8 @@ func (tx *Tx) Query(query string, args ...interface{}) (*sql.Rows, error) { Sql : *p, Args : args, Error : err, - Cost : militime2 - militime1, + Start : militime1, + End : militime2, Func : "TX:Query", }) } else { @@ -73,7 +74,8 @@ func (tx *Tx) Exec(query string, args ...interface{}) (sql.Result, error) { Sql : *p, Args : args, Error : err, - Cost : militime2 - militime1, + Start : militime1, + End : militime2, Func : "TX:Exec", }) } else { diff --git a/g/os/gtime/gtime_time.go b/g/os/gtime/gtime_time.go index 1c4a4f8c6..b94043ff8 100644 --- a/g/os/gtime/gtime_time.go +++ b/g/os/gtime/gtime_time.go @@ -66,10 +66,13 @@ func NewFromStrLayout (str string, layout string) *Time { return nil } -// 时间戳转换为时间对象 +// 时间戳转换为时间对象,时间戳支持到纳秒的数值 func NewFromTimeStamp (timestamp int64) *Time { - return &Time{ - time.Unix(timestamp, 0), + for timestamp < 1e18 { + timestamp *= 10 + } + return &Time { + time.Unix(int64(timestamp/1e9), timestamp%1e9), } } diff --git a/geg/database/mysql/gdb_debug.go b/geg/database/mysql/gdb_debug.go index a5bcbfccd..9d17c4bf1 100644 --- a/geg/database/mysql/gdb_debug.go +++ b/geg/database/mysql/gdb_debug.go @@ -1,20 +1,19 @@ package main import ( - "fmt" "gitee.com/johng/gf/g/database/gdb" ) func main() { - gdb.AddDefaultConfigNode(gdb.ConfigNode { - Host : "127.0.0.1", - Port : "3306", - User : "root", - Pass : "123456", - Name : "test", - Type : "mysql", - Role : "master", - Charset : "utf8", + gdb.AddDefaultConfigNode(gdb.ConfigNode{ + Host: "127.0.0.1", + Port: "3306", + User: "root", + Pass: "123456", + Name: "test", + Type: "mysql", + Role: "master", + Charset: "utf8", }) db, err := gdb.New() if err != nil { @@ -29,12 +28,5 @@ func main() { // 构造一条错误查询 db.Table("user").Where("no_such_field=?", "just_test").One() - for k, v := range db.GetQueriedSqls() { - fmt.Println(k, ":") - fmt.Println("Sql :", v.Sql) - fmt.Println("Args :", v.Args) - fmt.Println("Error:", v.Error) - fmt.Println("Cost :", v.Cost) - fmt.Println("Func :", v.Func) - } + db.PrintQueriedSqls() } \ No newline at end of file diff --git a/geg/other/test.go b/geg/other/test.go index b54b9da63..ab813f9ee 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -2,14 +2,19 @@ package main import ( "fmt" - "gitee.com/johng/gf/g/util/gregex" + "gitee.com/johng/gf/g/os/gtime" ) func main() { - name := "page" - path := "/page/template/{page}.html" - rule := fmt.Sprintf(`{%s}`, name, name) - tpl, err := gregex.ReplaceString(rule, `{.page}`, path) - fmt.Println(err) - fmt.Println(tpl) + fmt.Println(gtime.Second()) + fmt.Println(gtime.Nanosecond()) + t := gtime.Millisecond() + for t < 1e18 { + t *= 10 + } + fmt.Println(t) + fmt.Println(int64(t/1e9)) + fmt.Println(t%1e9) + + fmt.Println(gtime.NewFromTimeStamp(t).Format("Y-m-d H:i:s.u")) } From 9bb481ea961d2c540b16e0927c0b1246817f0f62 Mon Sep 17 00:00:00 2001 From: john Date: Thu, 9 Aug 2018 09:49:57 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E8=B0=83=E6=95=B4orm=E7=A4=BA=E4=BE=8B?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E7=9B=AE=E5=BD=95=EF=BC=8Csqlite=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0todo=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/database/gdb/gdb_base.go | 1 - g/database/gdb/gdb_sqlite.go | 3 ++ geg/database/{ => orm}/mysql/gdb.go | 0 geg/database/{ => orm}/mysql/gdb_cache.go | 0 geg/database/{ => orm}/mysql/gdb_debug.go | 0 geg/database/{ => orm}/mysql/gdb_json_xml.go | 0 geg/database/orm/sqlite/sqlite.go | 47 ++++++++++++++++++++ geg/other/test.go | 17 ++----- 8 files changed, 53 insertions(+), 15 deletions(-) rename geg/database/{ => orm}/mysql/gdb.go (100%) rename geg/database/{ => orm}/mysql/gdb_cache.go (100%) rename geg/database/{ => orm}/mysql/gdb_debug.go (100%) rename geg/database/{ => orm}/mysql/gdb_json_xml.go (100%) create mode 100644 geg/database/orm/sqlite/sqlite.go diff --git a/g/database/gdb/gdb_base.go b/g/database/gdb/gdb_base.go index 01ec77e2a..032bdbf23 100644 --- a/g/database/gdb/gdb_base.go +++ b/g/database/gdb/gdb_base.go @@ -308,7 +308,6 @@ func (db *Db) Begin() (*Tx, error) { func (db *Db) getInsertOperationByOption(option uint8) string { oper := "INSERT" switch option { - case OPTION_INSERT: case OPTION_REPLACE: oper = "REPLACE" case OPTION_SAVE: diff --git a/g/database/gdb/gdb_sqlite.go b/g/database/gdb/gdb_sqlite.go index 6c67da878..2dda7fe9c 100644 --- a/g/database/gdb/gdb_sqlite.go +++ b/g/database/gdb/gdb_sqlite.go @@ -44,6 +44,9 @@ func (db *dbsqlite) getQuoteCharRight() string { } // 在执行sql之前对sql进行进一步处理 +// @todo 需要增加对Save方法的支持,可使用正则来实现替换, +// @todo 将ON DUPLICATE KEY UPDATE触发器修改为两条SQL语句(INSERT OR IGNORE & UPDATE) func (db *dbsqlite) handleSqlBeforeExec(q *string) *string { + return q } diff --git a/geg/database/mysql/gdb.go b/geg/database/orm/mysql/gdb.go similarity index 100% rename from geg/database/mysql/gdb.go rename to geg/database/orm/mysql/gdb.go diff --git a/geg/database/mysql/gdb_cache.go b/geg/database/orm/mysql/gdb_cache.go similarity index 100% rename from geg/database/mysql/gdb_cache.go rename to geg/database/orm/mysql/gdb_cache.go diff --git a/geg/database/mysql/gdb_debug.go b/geg/database/orm/mysql/gdb_debug.go similarity index 100% rename from geg/database/mysql/gdb_debug.go rename to geg/database/orm/mysql/gdb_debug.go diff --git a/geg/database/mysql/gdb_json_xml.go b/geg/database/orm/mysql/gdb_json_xml.go similarity index 100% rename from geg/database/mysql/gdb_json_xml.go rename to geg/database/orm/mysql/gdb_json_xml.go diff --git a/geg/database/orm/sqlite/sqlite.go b/geg/database/orm/sqlite/sqlite.go new file mode 100644 index 000000000..8ee930bd1 --- /dev/null +++ b/geg/database/orm/sqlite/sqlite.go @@ -0,0 +1,47 @@ +package main + +//import ( +// _ "github.com/mattn/go-sqlite3" +// "gitee.com/johng/gf/g/database/gdb" +// "gitee.com/johng/gf/g" +// "fmt" +//) +// +//func main() { +// gdb.SetConfig(gdb.Config{ +// "default": gdb.ConfigGroup{ +// gdb.ConfigNode{ +// Name: "/tmp/my.db", +// Type: "sqlite", +// }, +// }, +// }) +// db := g.Database() +// if db == nil { +// panic("db create failed") +// } +// defer db.Close() +// +// // 创建表 +// sql := `CREATE TABLE user ( +// uid INT PRIMARY KEY NOT NULL, +// name VARCHAR(30) NOT NULL +// );` +// if _, err := db.Exec(sql); err != nil { +// fmt.Println(err) +// } +// +// // 写入数据 +// result, err := db.Table("user").Data(g.Map{"uid" : 1, "name" : "john"}).Save() +// if err == nil { +// fmt.Println(result.RowsAffected()) +// } else { +// fmt.Println(err) +// } +// +// // 删除表 +// sql = `DROP TABLE user;` +// if _, err := db.Exec(sql); err != nil { +// fmt.Println(err) +// } +//} \ No newline at end of file diff --git a/geg/other/test.go b/geg/other/test.go index ab813f9ee..744fb4fea 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -1,20 +1,9 @@ package main import ( - "fmt" - "gitee.com/johng/gf/g/os/gtime" + "fmt" ) func main() { - fmt.Println(gtime.Second()) - fmt.Println(gtime.Nanosecond()) - t := gtime.Millisecond() - for t < 1e18 { - t *= 10 - } - fmt.Println(t) - fmt.Println(int64(t/1e9)) - fmt.Println(t%1e9) - - fmt.Println(gtime.NewFromTimeStamp(t).Format("Y-m-d H:i:s.u")) -} + fmt.Println(1) +} \ No newline at end of file From f874d7c78f9556ac6c65f0300a0f5f7bba23b5f0 Mon Sep 17 00:00:00 2001 From: john Date: Thu, 9 Aug 2018 09:50:50 +0800 Subject: [PATCH 9/9] TODO++ --- TODO | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TODO b/TODO index 0e8f12df6..17b77638a 100644 --- a/TODO +++ b/TODO @@ -15,7 +15,7 @@ ghttp获取参数支持直接转struct功能; map转struct增加对tag的支持; gcache检查在i386下的int64->int转换问题; gfsnotify增加对于目录的监控; - +orm增加sqlite对Save方法的支持(去掉触发器语句); DONE: 1. gconv完善针对不同类型的判断,例如:尽量减少sprintf("%v", xxx)来执行string类型的转换;