add dialect for different database

This commit is contained in:
kk
2024-10-09 21:54:06 +08:00
parent 81c9b744df
commit cff0ff03d7
4 changed files with 51 additions and 49 deletions

View File

@@ -111,11 +111,15 @@ var rose = gorose.Open(
```
## 驱动支持
- MySQL
- MsSQL
- Postgresql
- Oracle
- Sqlite3
- mysql : https://github.com/go-sql-driver/mysql
- sqlite3 : https://github.com/mattn/go-sqlite3
- postgres : https://github.com/lib/pq
- oracle : https://github.com/mattn/go-oci8
- mssql : https://github.com/denisenkom/go-mssqldb
目前实现了以上5中数据库的支持, 通用数据库,只需要添加更多的 `gorose/driver/dialect.IDialect` 接口即可
非通用数据库,只要实现了 gorose/driver.IDriver 接口,理论上可以支持任意数据库,包括 redis,mongo 等都可以通过这个接口来实现
所有的 orm 链式操作都在 `gorose/builder.Context` 中, 直接可以拿到最原始的数据
## 事务
```go
@@ -125,7 +129,7 @@ db().Transaction(func(tx gorose.TxHandler) error {
tx().Insert(&user)
tx().Update(&user)
tx().To(&user)
}
})
// 手动事务
tx = db().Begin()
@@ -269,6 +273,7 @@ db().Table(User{}).Where("id",">", 1).Where(func(wh builder.IWhere) {
wh.Where("sex", 1).OrWhere("sex", 2)
})
```
这里的 Where 等同于 WhereNested
```go
// where id>1 and (sex=1 or sex=2)
db().Table(User{}).Where("id",">", 1).WhereNested(func(wh builder.IWhere) {
@@ -386,9 +391,6 @@ db().Table("users").MinTo("age", &min)
## 日志
默认采用 官方库的 slog debug level, 如果不想显示sql日志, 只需要设置slog的level到debug以上即可, 如: Info, Warn, Error
## 驱动
只要实现了 gorose/driver.IDriver 接口即可,理论上可以支持任意数据库, 目前实现了mysql的支持, 可以开发更多接口的支持
## 数据库字段为null的处理
```go
type User struct {
@@ -475,7 +477,8 @@ if age.Valid {
- [x] Pluck
- [x] List
- [x] Value
- [x] Value
- [x] Paginate
- [x] Increment
- [x] Decrement
@@ -508,3 +511,4 @@ if age.Valid {
- [x] MaxTo
- [x] UnionTo
- [x] UnionAllTo

View File

@@ -53,7 +53,6 @@ func (db *Database) Paginate(obj ...any) (result Pagination, err error) {
return
}
func (db *Database) WhereSub(column string, operation string, sub builder.WhereSubHandler) *Database {
db.Context.WhereClause.WhereSub(column, operation, sub)
return db
@@ -113,6 +112,7 @@ func (db *Database) OrWhereLike(column, value string) *Database {
db.Context.WhereClause.OrWhereLike(column, value)
return db
}
//func (db *Database) WhereNotIn(column string, value any) *Database {
// db.Context.WhereClause.WhereNotIn(column, value)
// return db
@@ -148,6 +148,7 @@ func (db *Database) OrWhereLike(column, value string) *Database {
// db.Context.WhereClause.whereLike("OR", column, value, true)
// return db
//}
func (db *Database) WhereNot(column any, args ...any) *Database {
db.Context.WhereClause.WhereNot(column, args...)
return db

View File

@@ -11,10 +11,10 @@ type User struct {
}
// var dbg = Open("mysql") // just test toSql
// var dbg = Open("postgresql") // just test toSql
var dbg = Open("postgresql") // just test toSql
// var dbg = Open("mssql") // just test toSql
// var dbg = Open("oracle") // just test toSql
var dbg = Open("sqlite3") // just test toSql
//var dbg = Open("sqlite3") // just test toSql
func db() *Database {
return dbg.NewDatabase()
@@ -63,12 +63,15 @@ func TestDatabase_ToSqlInsert(t *testing.T) {
driver.AssertsEqual(t, expectValues, values)
}
func TestDatabase_ToSqlInserts(t *testing.T) {
var user = []User{{Name: "John"}, {Name: "Alice"}}
var user = []User{{Id: 1, Name: "John"}, {Id: 2, Name: "Alice"}}
prepare, values, err := db().ToSqlInsert(&user)
driver.AssertsError(t, err)
var expect = "INSERT INTO `User` (`name`) VALUES (?),(?)"
driver.AssertsEqual(t, expect, prepare)
var expectValues = []string{"John", "Alice"}
var expect = map[string]string{
"mysql": "INSERT INTO `User` (`id`,`name`) VALUES (?,?),(?,?)",
"postgresql": `INSERT INTO "User" ("id","name") VALUES ($1,$2),($3,$4)`,
}
driver.AssertsEqual(t, expect[dbg.driver], prepare)
var expectValues = []interface{}{1, "John", 2, "Alice"}
driver.AssertsEqual(t, expectValues, values)
}
func TestDatabase_ToSqlUpdate(t *testing.T) {

58
util.go
View File

@@ -2,11 +2,8 @@ package gorose
import (
"database/sql"
"fmt"
"github.com/gohouse/gorose/v3/builder"
"math/rand"
"regexp"
"strings"
"time"
)
@@ -23,32 +20,33 @@ func As(table any, alias string) builder.TableClause {
func GetRandomInt(num int) int {
return rand.Intn(num)
}
func GetRandomWeightedIndex(weights []int) int {
if len(weights) == 0 {
return 0
}
if len(weights) == 1 {
return 0
}
totalWeight := 0
for _, w := range weights {
totalWeight += w
}
if totalWeight == 0 {
return rand.Intn(len(weights))
}
rnd := rand.Intn(totalWeight)
currentWeight := 0
for i, w := range weights {
currentWeight += w
if rnd < currentWeight {
return i
}
}
return -1 // 如果权重都为 0或者总权重为 0则返回 -1
}
//func GetRandomWeightedIndex(weights []int) int {
// if len(weights) == 0 {
// return 0
// }
// if len(weights) == 1 {
// return 0
// }
// totalWeight := 0
// for _, w := range weights {
// totalWeight += w
// }
// if totalWeight == 0 {
// return rand.Intn(len(weights))
// }
//
// rnd := rand.Intn(totalWeight)
//
// currentWeight := 0
// for i, w := range weights {
// currentWeight += w
// if rnd < currentWeight {
// return i
// }
// }
// return -1 // 如果权重都为 0或者总权重为 0则返回 -1
//}
//////////// struct field ptr 4 orm helpers ////////////
@@ -61,7 +59,3 @@ func Ptr[T any](arg T) *T {
func Null[T any](arg T) sql.Null[T] {
return sql.Null[T]{V: arg, Valid: true}
}
func NamedSprintf(format string, a ...any) string {
return strings.TrimSpace(regexp.MustCompile(`\s{2,}`).ReplaceAllString(fmt.Sprintf(regexp.MustCompile(`:\w+`).ReplaceAllString(format, "%s"), a...), " "))
}