refactor: openpitrix module
Signed-off-by: hongming <talonwan@yunify.com>
This commit is contained in:
12
vendor/openpitrix.io/openpitrix/pkg/db/Dockerfile
generated
vendored
Normal file
12
vendor/openpitrix.io/openpitrix/pkg/db/Dockerfile
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
# Copyright 2017 The OpenPitrix Authors. All rights reserved.
|
||||
# Use of this source code is governed by a Apache license
|
||||
# that can be found in the LICENSE file.
|
||||
|
||||
FROM dhoer/flyway:5.1.4-mysql-8.0.11-alpine
|
||||
|
||||
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
||||
RUN apk add --no-cache mysql-client
|
||||
|
||||
COPY ./schema /flyway/sql
|
||||
COPY ./ddl /flyway/sql/ddl
|
||||
COPY ./scripts /flyway/sql/ddl
|
||||
107
vendor/openpitrix.io/openpitrix/pkg/db/condition.go
generated
vendored
Normal file
107
vendor/openpitrix.io/openpitrix/pkg/db/condition.go
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
// Copyright 2017 The OpenPitrix Authors. All rights reserved.
|
||||
// Use of this source code is governed by a Apache license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/gocraft/dbr"
|
||||
)
|
||||
|
||||
const (
|
||||
placeholder = "?"
|
||||
)
|
||||
|
||||
type EqCondition struct {
|
||||
dbr.Builder
|
||||
Column string
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
// Copy From vendor/github.com/gocraft/dbr/condition.go:36
|
||||
func buildCmp(d dbr.Dialect, buf dbr.Buffer, pred string, column string, value interface{}) error {
|
||||
buf.WriteString(d.QuoteIdent(column))
|
||||
buf.WriteString(" ")
|
||||
buf.WriteString(pred)
|
||||
buf.WriteString(" ")
|
||||
buf.WriteString(placeholder)
|
||||
|
||||
buf.WriteValue(value)
|
||||
return nil
|
||||
}
|
||||
|
||||
// And creates AND from a list of conditions
|
||||
func And(cond ...dbr.Builder) dbr.Builder {
|
||||
return dbr.And(cond...)
|
||||
}
|
||||
|
||||
// Or creates OR from a list of conditions
|
||||
func Or(cond ...dbr.Builder) dbr.Builder {
|
||||
return dbr.Or(cond...)
|
||||
}
|
||||
|
||||
func escape(str string) string {
|
||||
return strings.Map(func(r rune) rune {
|
||||
switch r {
|
||||
case '%', '\'', '^', '[', ']', '!', '_':
|
||||
return ' '
|
||||
}
|
||||
return r
|
||||
}, str)
|
||||
}
|
||||
|
||||
func Like(column string, value string) dbr.Builder {
|
||||
value = "%" + strings.TrimSpace(escape(value)) + "%"
|
||||
return dbr.BuildFunc(func(d dbr.Dialect, buf dbr.Buffer) error {
|
||||
return buildCmp(d, buf, "LIKE", column, value)
|
||||
})
|
||||
}
|
||||
|
||||
func Prefix(column string, value string) dbr.Builder {
|
||||
value = strings.TrimSpace(escape(value)) + "%"
|
||||
return dbr.BuildFunc(func(d dbr.Dialect, buf dbr.Buffer) error {
|
||||
return buildCmp(d, buf, "LIKE", column, value)
|
||||
})
|
||||
}
|
||||
|
||||
// Eq is `=`.
|
||||
// When value is nil, it will be translated to `IS NULL`.
|
||||
// When value is a slice, it will be translated to `IN`.
|
||||
// Otherwise it will be translated to `=`.
|
||||
func Eq(column string, value interface{}) dbr.Builder {
|
||||
return &EqCondition{
|
||||
Builder: dbr.Eq(column, value),
|
||||
Column: column,
|
||||
Value: value,
|
||||
}
|
||||
}
|
||||
|
||||
// Neq is `!=`.
|
||||
// When value is nil, it will be translated to `IS NOT NULL`.
|
||||
// When value is a slice, it will be translated to `NOT IN`.
|
||||
// Otherwise it will be translated to `!=`.
|
||||
func Neq(column string, value interface{}) dbr.Builder {
|
||||
return dbr.Neq(column, value)
|
||||
}
|
||||
|
||||
// Gt is `>`.
|
||||
func Gt(column string, value interface{}) dbr.Builder {
|
||||
return dbr.Gt(column, value)
|
||||
}
|
||||
|
||||
// Gte is '>='.
|
||||
func Gte(column string, value interface{}) dbr.Builder {
|
||||
return dbr.Gte(column, value)
|
||||
}
|
||||
|
||||
// Lt is '<'.
|
||||
func Lt(column string, value interface{}) dbr.Builder {
|
||||
return dbr.Lt(column, value)
|
||||
}
|
||||
|
||||
// Lte is `<=`.
|
||||
func Lte(column string, value interface{}) dbr.Builder {
|
||||
return dbr.Lte(column, value)
|
||||
}
|
||||
72
vendor/openpitrix.io/openpitrix/pkg/db/connection.go
generated
vendored
Normal file
72
vendor/openpitrix.io/openpitrix/pkg/db/connection.go
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
// Copyright 2017 The OpenPitrix Authors. All rights reserved.
|
||||
// Use of this source code is governed by a Apache license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gocraft/dbr"
|
||||
|
||||
"openpitrix.io/openpitrix/pkg/config"
|
||||
"openpitrix.io/openpitrix/pkg/logger"
|
||||
)
|
||||
|
||||
type key int
|
||||
|
||||
var dbMap = sync.Map{}
|
||||
var dbKey key
|
||||
|
||||
type Database struct {
|
||||
Conn *dbr.Connection
|
||||
}
|
||||
|
||||
func OpenDatabase(cfg config.MysqlConfig) (*Database, error) {
|
||||
// https://github.com/go-sql-driver/mysql/issues/9
|
||||
conn, err := dbr.Open("mysql", cfg.GetUrl()+"?parseTime=1&multiStatements=1&charset=utf8mb4&collation=utf8mb4_unicode_ci", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn.SetMaxIdleConns(100)
|
||||
conn.SetMaxOpenConns(100)
|
||||
conn.SetConnMaxLifetime(10 * time.Second)
|
||||
|
||||
db := &Database{
|
||||
Conn: conn,
|
||||
}
|
||||
dbMap.Store(cfg, db)
|
||||
return db, nil
|
||||
}
|
||||
|
||||
func NewContext(ctx context.Context, cfg config.MysqlConfig) context.Context {
|
||||
return context.WithValue(ctx, dbKey, cfg)
|
||||
}
|
||||
|
||||
func FromContext(ctx context.Context) (*Database, bool) {
|
||||
cfg := ctx.Value(dbKey).(config.MysqlConfig)
|
||||
var err error
|
||||
db, ok := dbMap.Load(cfg)
|
||||
if !ok {
|
||||
db, err = OpenDatabase(cfg)
|
||||
if err != nil {
|
||||
logger.Critical(ctx, "Failed to open database: %+v", err)
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
return db.(*Database), true
|
||||
}
|
||||
|
||||
func (db *Database) New(ctx context.Context) *Conn {
|
||||
actualDb, ok := FromContext(ctx)
|
||||
conn := db.Conn
|
||||
if ok {
|
||||
conn = actualDb.Conn
|
||||
}
|
||||
return &Conn{
|
||||
Session: conn.NewSession(&EventReceiver{ctx}),
|
||||
ctx: ctx,
|
||||
}
|
||||
}
|
||||
272
vendor/openpitrix.io/openpitrix/pkg/db/db.go
generated
vendored
Normal file
272
vendor/openpitrix.io/openpitrix/pkg/db/db.go
generated
vendored
Normal file
@@ -0,0 +1,272 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/gocraft/dbr"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultSelectLimit = 200
|
||||
)
|
||||
|
||||
func GetLimit(n uint64) uint64 {
|
||||
if n < 0 {
|
||||
n = 0
|
||||
}
|
||||
if n > DefaultSelectLimit {
|
||||
n = DefaultSelectLimit
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func GetOffset(n uint64) uint64 {
|
||||
if n < 0 {
|
||||
n = 0
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
type InsertHook func(query *InsertQuery)
|
||||
type UpdateHook func(query *UpdateQuery)
|
||||
type DeleteHook func(query *DeleteQuery)
|
||||
|
||||
type SelectQuery struct {
|
||||
*dbr.SelectBuilder
|
||||
ctx context.Context
|
||||
JoinCount int // for join filter
|
||||
}
|
||||
|
||||
type InsertQuery struct {
|
||||
*dbr.InsertBuilder
|
||||
ctx context.Context
|
||||
Hook InsertHook
|
||||
}
|
||||
|
||||
type DeleteQuery struct {
|
||||
*dbr.DeleteBuilder
|
||||
ctx context.Context
|
||||
Hook DeleteHook
|
||||
}
|
||||
|
||||
type UpdateQuery struct {
|
||||
*dbr.UpdateBuilder
|
||||
ctx context.Context
|
||||
Hook UpdateHook
|
||||
}
|
||||
|
||||
type Conn struct {
|
||||
*dbr.Session
|
||||
ctx context.Context
|
||||
InsertHook InsertHook
|
||||
UpdateHook UpdateHook
|
||||
DeleteHook DeleteHook
|
||||
}
|
||||
|
||||
// SelectQuery
|
||||
// Example: Select().From().Where().Limit().Offset().OrderDir().Load()
|
||||
// Select().From().Where().Limit().Offset().OrderDir().LoadOne()
|
||||
// Select().From().Where().Count()
|
||||
// SelectAll().From().Where().Limit().Offset().OrderDir().Load()
|
||||
// SelectAll().From().Where().Limit().Offset().OrderDir().LoadOne()
|
||||
// SelectAll().From().Where().Count()
|
||||
|
||||
func (conn *Conn) Select(columns ...string) *SelectQuery {
|
||||
return &SelectQuery{conn.Session.Select(columns...), conn.ctx, 0}
|
||||
}
|
||||
|
||||
func (conn *Conn) SelectBySql(query string, value ...interface{}) *SelectQuery {
|
||||
return &SelectQuery{conn.Session.SelectBySql(query, value...), conn.ctx, 0}
|
||||
}
|
||||
|
||||
func (conn *Conn) SelectAll(columns ...string) *SelectQuery {
|
||||
return &SelectQuery{conn.Session.Select("*"), conn.ctx, 0}
|
||||
}
|
||||
|
||||
func (b *SelectQuery) Join(table, on interface{}) *SelectQuery {
|
||||
b.SelectBuilder.Join(table, on)
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *SelectQuery) JoinAs(table string, alias string, on interface{}) *SelectQuery {
|
||||
b.SelectBuilder.Join(dbr.I(table).As(alias), on)
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *SelectQuery) From(table string) *SelectQuery {
|
||||
b.SelectBuilder.From(table)
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *SelectQuery) Where(query interface{}, value ...interface{}) *SelectQuery {
|
||||
b.SelectBuilder.Where(query, value...)
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *SelectQuery) GroupBy(col ...string) *SelectQuery {
|
||||
b.SelectBuilder.GroupBy(col...)
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *SelectQuery) Distinct() *SelectQuery {
|
||||
b.SelectBuilder.Distinct()
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *SelectQuery) Limit(n uint64) *SelectQuery {
|
||||
n = GetLimit(n)
|
||||
b.SelectBuilder.Limit(n)
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *SelectQuery) Offset(n uint64) *SelectQuery {
|
||||
n = GetOffset(n)
|
||||
b.SelectBuilder.Offset(n)
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *SelectQuery) OrderDir(col string, isAsc bool) *SelectQuery {
|
||||
b.SelectBuilder.OrderDir(col, isAsc)
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *SelectQuery) Load(value interface{}) (int, error) {
|
||||
return b.SelectBuilder.LoadContext(b.ctx, value)
|
||||
}
|
||||
|
||||
func (b *SelectQuery) LoadOne(value interface{}) error {
|
||||
return b.SelectBuilder.LoadOneContext(b.ctx, value)
|
||||
}
|
||||
|
||||
func getColumns(dbrColumns []interface{}) string {
|
||||
var columns []string
|
||||
for _, column := range dbrColumns {
|
||||
if c, ok := column.(string); ok {
|
||||
columns = append(columns, c)
|
||||
}
|
||||
}
|
||||
return strings.Join(columns, ", ")
|
||||
}
|
||||
|
||||
func (b *SelectQuery) Count() (count uint32, err error) {
|
||||
// cache SelectStmt
|
||||
selectStmt := b.SelectBuilder
|
||||
|
||||
limit := selectStmt.LimitCount
|
||||
offset := selectStmt.OffsetCount
|
||||
column := selectStmt.Column
|
||||
isDistinct := selectStmt.IsDistinct
|
||||
order := selectStmt.Order
|
||||
|
||||
b.LimitCount = -1
|
||||
b.OffsetCount = -1
|
||||
b.Column = []interface{}{"COUNT(*)"}
|
||||
b.Order = []dbr.Builder{}
|
||||
|
||||
if isDistinct {
|
||||
b.Column = []interface{}{fmt.Sprintf("COUNT(DISTINCT %s)", getColumns(column))}
|
||||
b.IsDistinct = false
|
||||
}
|
||||
|
||||
err = b.LoadOne(&count)
|
||||
// fallback SelectStmt
|
||||
selectStmt.LimitCount = limit
|
||||
selectStmt.OffsetCount = offset
|
||||
selectStmt.Column = column
|
||||
selectStmt.IsDistinct = isDistinct
|
||||
selectStmt.Order = order
|
||||
b.SelectBuilder = selectStmt
|
||||
return
|
||||
}
|
||||
|
||||
// InsertQuery
|
||||
// Example: InsertInto().Columns().Record().Exec()
|
||||
|
||||
func (conn *Conn) InsertInto(table string) *InsertQuery {
|
||||
return &InsertQuery{conn.Session.InsertInto(table), conn.ctx, conn.InsertHook}
|
||||
}
|
||||
|
||||
func (b *InsertQuery) Exec() (sql.Result, error) {
|
||||
result, err := b.InsertBuilder.ExecContext(b.ctx)
|
||||
if b.Hook != nil && err == nil {
|
||||
defer b.Hook(b)
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (b *InsertQuery) Columns(columns ...string) *InsertQuery {
|
||||
b.InsertBuilder.Columns(columns...)
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *InsertQuery) Record(structValue interface{}) *InsertQuery {
|
||||
if len(b.Column) == 0 {
|
||||
b.Columns(GetColumnsFromStruct(structValue)...)
|
||||
}
|
||||
b.InsertBuilder.Record(structValue)
|
||||
return b
|
||||
}
|
||||
|
||||
// DeleteQuery
|
||||
// Example: DeleteFrom().Where().Limit().Exec()
|
||||
|
||||
func (conn *Conn) DeleteFrom(table string) *DeleteQuery {
|
||||
return &DeleteQuery{conn.Session.DeleteFrom(table), conn.ctx, conn.DeleteHook}
|
||||
}
|
||||
|
||||
func (b *DeleteQuery) Where(query interface{}, value ...interface{}) *DeleteQuery {
|
||||
b.DeleteBuilder.Where(query, value...)
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *DeleteQuery) Limit(n uint64) *DeleteQuery {
|
||||
b.DeleteBuilder.Limit(n)
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *DeleteQuery) Exec() (sql.Result, error) {
|
||||
result, err := b.DeleteBuilder.ExecContext(b.ctx)
|
||||
if b.Hook != nil && err == nil {
|
||||
defer b.Hook(b)
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
// UpdateQuery
|
||||
// Example: Update().Set().Where().Exec()
|
||||
|
||||
func (conn *Conn) Update(table string) *UpdateQuery {
|
||||
return &UpdateQuery{conn.Session.Update(table), conn.ctx, conn.UpdateHook}
|
||||
}
|
||||
|
||||
func (b *UpdateQuery) Exec() (sql.Result, error) {
|
||||
result, err := b.UpdateBuilder.ExecContext(b.ctx)
|
||||
if b.Hook != nil && err == nil {
|
||||
defer b.Hook(b)
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (b *UpdateQuery) Set(column string, value interface{}) *UpdateQuery {
|
||||
b.UpdateBuilder.Set(column, value)
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *UpdateQuery) SetMap(m map[string]interface{}) *UpdateQuery {
|
||||
b.UpdateBuilder.SetMap(m)
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *UpdateQuery) Where(query interface{}, value ...interface{}) *UpdateQuery {
|
||||
b.UpdateBuilder.Where(query, value...)
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *UpdateQuery) Limit(n uint64) *UpdateQuery {
|
||||
b.UpdateBuilder.Limit(n)
|
||||
return b
|
||||
}
|
||||
22
vendor/openpitrix.io/openpitrix/pkg/db/errors.go
generated
vendored
Normal file
22
vendor/openpitrix.io/openpitrix/pkg/db/errors.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2018 The OpenPitrix Authors. All rights reserved.
|
||||
// Use of this source code is governed by a Apache license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"github.com/gocraft/dbr"
|
||||
)
|
||||
|
||||
// package errors
|
||||
var (
|
||||
ErrNotFound = dbr.ErrNotFound
|
||||
ErrNotSupported = dbr.ErrNotSupported
|
||||
ErrTableNotSpecified = dbr.ErrTableNotSpecified
|
||||
ErrColumnNotSpecified = dbr.ErrColumnNotSpecified
|
||||
ErrInvalidPointer = dbr.ErrInvalidPointer
|
||||
ErrPlaceholderCount = dbr.ErrPlaceholderCount
|
||||
ErrInvalidSliceLength = dbr.ErrInvalidSliceLength
|
||||
ErrCantConvertToTime = dbr.ErrCantConvertToTime
|
||||
ErrInvalidTimestring = dbr.ErrInvalidTimestring
|
||||
)
|
||||
49
vendor/openpitrix.io/openpitrix/pkg/db/event.go
generated
vendored
Normal file
49
vendor/openpitrix.io/openpitrix/pkg/db/event.go
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright 2017 The OpenPitrix Authors. All rights reserved.
|
||||
// Use of this source code is governed by a Apache license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"openpitrix.io/openpitrix/pkg/logger"
|
||||
)
|
||||
|
||||
// EventReceiver is a sentinel EventReceiver; use it if the caller doesn't supply one
|
||||
type EventReceiver struct {
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
// Event receives a simple notification when various events occur
|
||||
func (n *EventReceiver) Event(eventName string) {
|
||||
|
||||
}
|
||||
|
||||
// EventKv receives a notification when various events occur along with
|
||||
// optional key/value data
|
||||
func (n *EventReceiver) EventKv(eventName string, kvs map[string]string) {
|
||||
}
|
||||
|
||||
// EventErr receives a notification of an error if one occurs
|
||||
func (n *EventReceiver) EventErr(eventName string, err error) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// EventErrKv receives a notification of an error if one occurs along with
|
||||
// optional key/value data
|
||||
func (n *EventReceiver) EventErrKv(eventName string, err error, kvs map[string]string) error {
|
||||
logger.Error(n.ctx, "%+v", err)
|
||||
logger.Error(n.ctx, "%s: %+v", eventName, kvs)
|
||||
return err
|
||||
}
|
||||
|
||||
// Timing receives the time an event took to happen
|
||||
func (n *EventReceiver) Timing(eventName string, nanoseconds int64) {
|
||||
|
||||
}
|
||||
|
||||
// TimingKv receives the time an event took to happen along with optional key/value data
|
||||
func (n *EventReceiver) TimingKv(eventName string, nanoseconds int64, kvs map[string]string) {
|
||||
logger.Debug(n.ctx, "%s spend %.2fms: %+v", eventName, float32(nanoseconds)/1000000, kvs)
|
||||
}
|
||||
31
vendor/openpitrix.io/openpitrix/pkg/db/util.go
generated
vendored
Normal file
31
vendor/openpitrix.io/openpitrix/pkg/db/util.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright 2018 The OpenPitrix Authors. All rights reserved.
|
||||
// Use of this source code is governed by a Apache license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"github.com/fatih/structs"
|
||||
|
||||
"openpitrix.io/openpitrix/pkg/util/stringutil"
|
||||
)
|
||||
|
||||
func GetColumnsFromStruct(s interface{}) []string {
|
||||
names := structs.Names(s)
|
||||
for i, name := range names {
|
||||
names[i] = stringutil.CamelCaseToUnderscore(name)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
func GetColumnsFromStructWithPrefix(prefix string, s interface{}) []string {
|
||||
names := structs.Names(s)
|
||||
for i, name := range names {
|
||||
names[i] = WithPrefix(prefix, stringutil.CamelCaseToUnderscore(name))
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
func WithPrefix(prefix, str string) string {
|
||||
return prefix + "." + str
|
||||
}
|
||||
Reference in New Issue
Block a user