mirror of
https://github.com/geektutu/7days-golang.git
synced 2024-04-21 12:32:11 +00:00
refactor Session, remove Value & lower SQL & SQLVars
This commit is contained in:
@@ -2,18 +2,15 @@ package session
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"strings"
|
||||
|
||||
"geeorm/log"
|
||||
)
|
||||
|
||||
// Session keep a pointer to sql.DB and provides all execution of all
|
||||
// kind of database operations.
|
||||
type Session struct {
|
||||
db *sql.DB
|
||||
|
||||
SQL strings.Builder
|
||||
SQLVars []interface{}
|
||||
db *sql.DB
|
||||
sql string
|
||||
sqlVars []interface{}
|
||||
}
|
||||
|
||||
// New creates a instance of Session
|
||||
@@ -21,10 +18,10 @@ func New(db *sql.DB) *Session {
|
||||
return &Session{db: db}
|
||||
}
|
||||
|
||||
// Exec raw SQL with SQLVars
|
||||
// Exec raw sql with sqlVars
|
||||
func (s *Session) Exec() (result sql.Result, err error) {
|
||||
log.Info(s.SQL.String(), s.SQLVars)
|
||||
if result, err = s.db.Exec(s.SQL.String(), s.SQLVars...); err != nil {
|
||||
log.Info(s.sql, s.sqlVars)
|
||||
if result, err = s.db.Exec(s.sql, s.sqlVars...); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
return
|
||||
@@ -32,22 +29,22 @@ func (s *Session) Exec() (result sql.Result, err error) {
|
||||
|
||||
// QueryRow gets a record from db
|
||||
func (s *Session) QueryRow() *sql.Row {
|
||||
log.Info(s.SQL.String(), s.SQLVars)
|
||||
return s.db.QueryRow(s.SQL.String(), s.SQLVars...)
|
||||
log.Info(s.sql, s.sqlVars)
|
||||
return s.db.QueryRow(s.sql, s.sqlVars...)
|
||||
}
|
||||
|
||||
// QueryRows gets a list of records from db
|
||||
func (s *Session) QueryRows() (rows *sql.Rows, err error) {
|
||||
log.Info(s.SQL.String(), s.SQLVars)
|
||||
if rows, err = s.db.Query(s.SQL.String(), s.SQLVars...); err != nil {
|
||||
log.Info(s.sql, s.sqlVars)
|
||||
if rows, err = s.db.Query(s.sql, s.sqlVars...); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Raw appends SQL and SQLVars
|
||||
// Raw appends sql and sqlVars
|
||||
func (s *Session) Raw(sql string, values ...interface{}) *Session {
|
||||
s.SQL.WriteString(sql)
|
||||
s.SQLVars = append(s.SQLVars, values...)
|
||||
s.sql += sql
|
||||
s.sqlVars = append(s.sqlVars, values...)
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@ package session
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"strings"
|
||||
|
||||
"geeorm/dialect"
|
||||
"geeorm/log"
|
||||
"geeorm/schema"
|
||||
@@ -15,10 +13,8 @@ type Session struct {
|
||||
db *sql.DB
|
||||
dialect dialect.Dialect
|
||||
refTable *schema.Schema
|
||||
|
||||
Value interface{}
|
||||
SQL strings.Builder
|
||||
SQLVars []interface{}
|
||||
sql string
|
||||
sqlVars []interface{}
|
||||
}
|
||||
|
||||
// New creates a instance of Session
|
||||
@@ -29,10 +25,10 @@ func New(db *sql.DB, dialect dialect.Dialect) *Session {
|
||||
}
|
||||
}
|
||||
|
||||
// Exec raw SQL with SQLVars
|
||||
// Exec raw sql with sqlVars
|
||||
func (s *Session) Exec() (result sql.Result, err error) {
|
||||
log.Info(s.SQL.String(), s.SQLVars)
|
||||
if result, err = s.db.Exec(s.SQL.String(), s.SQLVars...); err != nil {
|
||||
log.Info(s.sql, s.sqlVars)
|
||||
if result, err = s.db.Exec(s.sql, s.sqlVars...); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
return
|
||||
@@ -40,22 +36,22 @@ func (s *Session) Exec() (result sql.Result, err error) {
|
||||
|
||||
// QueryRow gets a record from db
|
||||
func (s *Session) QueryRow() *sql.Row {
|
||||
log.Info(s.SQL.String(), s.SQLVars)
|
||||
return s.db.QueryRow(s.SQL.String(), s.SQLVars...)
|
||||
log.Info(s.sql, s.sqlVars)
|
||||
return s.db.QueryRow(s.sql, s.sqlVars...)
|
||||
}
|
||||
|
||||
// QueryRows gets a list of records from db
|
||||
func (s *Session) QueryRows() (rows *sql.Rows, err error) {
|
||||
log.Info(s.SQL.String(), s.SQLVars)
|
||||
if rows, err = s.db.Query(s.SQL.String(), s.SQLVars...); err != nil {
|
||||
log.Info(s.sql, s.sqlVars)
|
||||
if rows, err = s.db.Query(s.sql, s.sqlVars...); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Raw appends SQL and SQLVars
|
||||
// Raw appends sql and sqlVars
|
||||
func (s *Session) Raw(sql string, values ...interface{}) *Session {
|
||||
s.SQL.WriteString(sql)
|
||||
s.SQLVars = append(s.SQLVars, values...)
|
||||
s.sql += sql
|
||||
s.sqlVars = append(s.sqlVars, values...)
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package session
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"geeorm/log"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
@@ -18,7 +17,6 @@ var (
|
||||
func setup() {
|
||||
TestDB, _ = sql.Open("sqlite3", "gee.db")
|
||||
TestDial, _ = dialect.GetDialect("sqlite3")
|
||||
log.SetLevel(log.ErrorLevel)
|
||||
}
|
||||
|
||||
func teardown() {
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package clause
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Clause contains SQL conditions
|
||||
type Clause struct {
|
||||
sql map[Type]string
|
||||
sqlVars map[Type][]interface{}
|
||||
}
|
||||
|
||||
// Type is the type of Clause
|
||||
type Type int
|
||||
|
||||
// Support types for Clause
|
||||
const (
|
||||
INSERT Type = 0
|
||||
VALUES Type = 1
|
||||
SELECT Type = 2
|
||||
LIMIT Type = 3
|
||||
)
|
||||
|
||||
// Set adds a sub clause of specific type
|
||||
func (c *Clause) Set(name Type, vars ...interface{}) {
|
||||
if c.sql == nil {
|
||||
c.sql = make(map[Type]string)
|
||||
c.sqlVars = make(map[Type][]interface{})
|
||||
}
|
||||
sql, vars := generators[name](vars...)
|
||||
c.sql[name] = sql
|
||||
c.sqlVars[name] = vars
|
||||
}
|
||||
|
||||
// Build generate the final SQL and SQLVars
|
||||
func (c *Clause) Build(orders []Type) (string, []interface{}) {
|
||||
var sqls []string
|
||||
var vars []interface{}
|
||||
for _, order := range orders {
|
||||
if sql, ok := c.sql[order]; ok {
|
||||
sqls = append(sqls, sql)
|
||||
vars = append(vars, c.sqlVars[order]...)
|
||||
}
|
||||
}
|
||||
return strings.Join(sqls, " "), vars
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package clause
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestClause_Set(t *testing.T) {
|
||||
var clause Clause
|
||||
clause.Set(INSERT, "User", "Name,Age")
|
||||
sql := clause.sql[INSERT]
|
||||
vars := clause.sqlVars[INSERT]
|
||||
t.Log(sql, vars)
|
||||
if sql != "INSERT INTO User (Name,Age)" || len(vars) != 0 {
|
||||
t.Fatal("failed to get clause")
|
||||
}
|
||||
}
|
||||
|
||||
func TestClause_Build(t *testing.T) {
|
||||
var clause Clause
|
||||
clause.Set(LIMIT, 3)
|
||||
clause.Set(SELECT, "User", "*")
|
||||
orders := []Type{SELECT, LIMIT}
|
||||
sql, vars := clause.Build(orders)
|
||||
t.Log(sql, vars)
|
||||
if sql != "SELECT * FROM User LIMIT ?" {
|
||||
t.Fatal("failed to build SQL")
|
||||
}
|
||||
if !reflect.DeepEqual(vars, []interface{}{3}) {
|
||||
t.Fatal("failed to build SQLVars")
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package clause
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type generator func(values ...interface{}) (string, []interface{})
|
||||
|
||||
var generators map[Type]generator
|
||||
|
||||
func init() {
|
||||
generators = make(map[Type]generator)
|
||||
generators[INSERT] = _insert
|
||||
generators[VALUES] = _values
|
||||
generators[SELECT] = _select
|
||||
generators[LIMIT] = _limit
|
||||
}
|
||||
|
||||
func genBindVars(num int) string {
|
||||
var vars []string
|
||||
for i := 0; i < num; i++ {
|
||||
vars = append(vars, "?")
|
||||
}
|
||||
return strings.Join(vars, ", ")
|
||||
}
|
||||
|
||||
func _insert(values ...interface{}) (string, []interface{}) {
|
||||
// INSERT INTO $tableName ($fields)
|
||||
tableName := values[0]
|
||||
fields := values[1]
|
||||
return fmt.Sprintf("INSERT INTO %s (%v)", tableName, fields), []interface{}{}
|
||||
}
|
||||
|
||||
func _values(values ...interface{}) (string, []interface{}) {
|
||||
// VALUES ($v1), (&v2), ...
|
||||
var bindStr string
|
||||
var sql strings.Builder
|
||||
var vars []interface{}
|
||||
sql.WriteString("VALUES ")
|
||||
for i, value := range values {
|
||||
v := value.([]interface{})
|
||||
if bindStr == "" {
|
||||
bindStr = genBindVars(len(v))
|
||||
}
|
||||
sql.WriteString(fmt.Sprintf("(%v)", bindStr))
|
||||
if i+1 != len(values) {
|
||||
sql.WriteString(", ")
|
||||
}
|
||||
vars = append(vars, v...)
|
||||
}
|
||||
return sql.String(), vars
|
||||
|
||||
}
|
||||
|
||||
func _select(values ...interface{}) (string, []interface{}) {
|
||||
// SELECT $fields FROM $tableName
|
||||
tableName := values[0]
|
||||
fields := values[1]
|
||||
return fmt.Sprintf("SELECT %v FROM %s", fields, tableName), []interface{}{}
|
||||
}
|
||||
|
||||
func _limit(values ...interface{}) (string, []interface{}) {
|
||||
// LIMIT $num
|
||||
log.Println(values...)
|
||||
return "LIMIT ?", values
|
||||
}
|
||||
@@ -19,7 +19,6 @@ type Schema struct {
|
||||
PrimaryField *Field
|
||||
Fields []*Field
|
||||
FieldNames []string
|
||||
BindVars []string
|
||||
}
|
||||
|
||||
// Values return the values of dest's member variables
|
||||
@@ -52,7 +51,6 @@ func Parse(dest interface{}, d dialect.Dialect) *Schema {
|
||||
}
|
||||
schema.Fields = append(schema.Fields, field)
|
||||
schema.FieldNames = append(schema.FieldNames, p.Name)
|
||||
schema.BindVars = append(schema.BindVars, "?")
|
||||
}
|
||||
}
|
||||
return schema
|
||||
@@ -66,4 +64,4 @@ func (field *Field) String() string {
|
||||
// String returns readable string
|
||||
func (schema *Schema) String() string {
|
||||
return fmt.Sprintf("TABLE %s %v", schema.TableName, schema.Fields)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,7 @@ package session
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"strings"
|
||||
|
||||
"geeorm/clause"
|
||||
"geeorm/dialect"
|
||||
"geeorm/log"
|
||||
"geeorm/schema"
|
||||
@@ -15,10 +14,9 @@ type Session struct {
|
||||
db *sql.DB
|
||||
dialect dialect.Dialect
|
||||
refTable *schema.Schema
|
||||
|
||||
Value interface{}
|
||||
SQL strings.Builder
|
||||
SQLVars []interface{}
|
||||
clause clause.Clause
|
||||
sql string
|
||||
sqlVars []interface{}
|
||||
}
|
||||
|
||||
// New creates a instance of Session
|
||||
@@ -29,10 +27,10 @@ func New(db *sql.DB, dialect dialect.Dialect) *Session {
|
||||
}
|
||||
}
|
||||
|
||||
// Exec raw SQL with SQLVars
|
||||
// Exec raw sql with sqlVars
|
||||
func (s *Session) Exec() (result sql.Result, err error) {
|
||||
log.Info(s.SQL.String(), s.SQLVars)
|
||||
if result, err = s.db.Exec(s.SQL.String(), s.SQLVars...); err != nil {
|
||||
log.Info(s.sql, s.sqlVars)
|
||||
if result, err = s.db.Exec(s.sql, s.sqlVars...); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
return
|
||||
@@ -40,22 +38,22 @@ func (s *Session) Exec() (result sql.Result, err error) {
|
||||
|
||||
// QueryRow gets a record from db
|
||||
func (s *Session) QueryRow() *sql.Row {
|
||||
log.Info(s.SQL.String(), s.SQLVars)
|
||||
return s.db.QueryRow(s.SQL.String(), s.SQLVars...)
|
||||
log.Info(s.sql, s.sqlVars)
|
||||
return s.db.QueryRow(s.sql, s.sqlVars...)
|
||||
}
|
||||
|
||||
// QueryRows gets a list of records from db
|
||||
func (s *Session) QueryRows() (rows *sql.Rows, err error) {
|
||||
log.Info(s.SQL.String(), s.SQLVars)
|
||||
if rows, err = s.db.Query(s.SQL.String(), s.SQLVars...); err != nil {
|
||||
log.Info(s.sql, s.sqlVars)
|
||||
if rows, err = s.db.Query(s.sql, s.sqlVars...); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Raw appends SQL and SQLVars
|
||||
// Raw appends sql and sqlVars
|
||||
func (s *Session) Raw(sql string, values ...interface{}) *Session {
|
||||
s.SQL.WriteString(sql)
|
||||
s.SQLVars = append(s.SQLVars, values...)
|
||||
s.sql += sql
|
||||
s.sqlVars = append(s.sqlVars, values...)
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package session
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"geeorm/log"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
@@ -18,7 +17,6 @@ var (
|
||||
func setup() {
|
||||
TestDB, _ = sql.Open("sqlite3", "gee.db")
|
||||
TestDial, _ = dialect.GetDialect("sqlite3")
|
||||
log.SetLevel(log.ErrorLevel)
|
||||
}
|
||||
|
||||
func teardown() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"geeorm/clause"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
@@ -9,23 +9,20 @@ import (
|
||||
// Create one or more records in database
|
||||
func (s *Session) Create(values ...interface{}) (int64, error) {
|
||||
var flag bool
|
||||
for i, value := range values {
|
||||
recordValues := make([]interface{}, 0)
|
||||
for _, value := range values {
|
||||
table := s.RefTable(value)
|
||||
filedSQL := strings.Join(table.FieldNames, ", ")
|
||||
bindVarSQL := strings.Join(table.BindVars, ", ")
|
||||
if !flag {
|
||||
s.Raw(fmt.Sprintf("INSERT INTO %s (%v) VALUES ", table.TableName, filedSQL))
|
||||
flag = true
|
||||
fieldSQL := strings.Join(table.FieldNames, ", ")
|
||||
s.clause.Set(clause.INSERT, table.TableName, fieldSQL)
|
||||
}
|
||||
s.Raw(fmt.Sprintf("(%v)", bindVarSQL), table.Values(value)...)
|
||||
if i == len(values)-1 {
|
||||
s.Raw(";")
|
||||
} else {
|
||||
s.Raw(",")
|
||||
}
|
||||
recordValues = append(recordValues, table.Values(value))
|
||||
}
|
||||
|
||||
result, err := s.Exec()
|
||||
s.clause.Set(clause.VALUES, recordValues...)
|
||||
sql, vars := s.clause.Build([]clause.Type{clause.INSERT, clause.VALUES})
|
||||
result, err := s.Raw(sql, vars...).Exec()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -38,8 +35,12 @@ func (s *Session) First(value interface{}) error {
|
||||
table := s.RefTable(value)
|
||||
|
||||
fieldSQL := strings.Join(table.FieldNames, ", ")
|
||||
selectSQL := fmt.Sprintf("SELECT %v FROM %s LIMIT 1", fieldSQL, table.TableName)
|
||||
row := s.Raw(selectSQL).QueryRow()
|
||||
|
||||
s.clause.Set(clause.SELECT, table.TableName, fieldSQL)
|
||||
s.clause.Set(clause.LIMIT, 1)
|
||||
|
||||
sql, vars := s.clause.Build([]clause.Type{clause.SELECT, clause.LIMIT})
|
||||
row := s.Raw(sql, vars...).QueryRow()
|
||||
|
||||
dest := reflect.ValueOf(value).Elem()
|
||||
var values []interface{}
|
||||
@@ -57,8 +58,9 @@ func (s *Session) Find(values interface{}) error {
|
||||
table := s.RefTable(reflect.New(destType).Elem().Interface())
|
||||
|
||||
fieldSQL := strings.Join(table.FieldNames, ", ")
|
||||
selectSQL := fmt.Sprintf("SELECT %v FROM %s", fieldSQL, table.TableName)
|
||||
rows, err := s.Raw(selectSQL).QueryRows()
|
||||
s.clause.Set(clause.SELECT, table.TableName, fieldSQL)
|
||||
sql, vars := s.clause.Build([]clause.Type{clause.SELECT})
|
||||
rows, err := s.Raw(sql, vars...).QueryRows()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user