harbor/src/common/dao/base.go

177 lines
4.6 KiB
Go
Raw Normal View History

// Copyright Project Harbor Authors
2017-04-13 12:54:58 +02:00
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2016-02-26 11:54:14 +01:00
2016-02-01 12:59:10 +01:00
package dao
import (
"errors"
"fmt"
2016-12-30 11:04:01 +01:00
"strconv"
2016-11-16 13:25:40 +01:00
"strings"
2016-05-24 03:41:34 +02:00
"sync"
2016-02-01 12:59:10 +01:00
"github.com/astaxie/beego/orm"
"github.com/goharbor/harbor/src/common/models"
"github.com/goharbor/harbor/src/lib/log"
2016-02-01 12:59:10 +01:00
)
const (
// NonExistUserID : if a user does not exist, the ID of the user will be 0.
NonExistUserID = 0
)
2016-02-01 12:59:10 +01:00
// ErrDupRows is returned by DAO when inserting failed with error "duplicate key value violates unique constraint"
var ErrDupRows = errors.New("sql: duplicate row in DB")
2016-09-13 11:41:32 +02:00
// Database is an interface of different databases
type Database interface {
// Name returns the name of database
Name() string
// String returns the details of database
String() string
// Register registers the database which will be used
Register(alias ...string) error
// UpgradeSchema upgrades the DB schema to the latest version
UpgradeSchema() error
2016-09-13 11:41:32 +02:00
}
// UpgradeSchema will call the internal migrator to upgrade schema based on the setting of database.
func UpgradeSchema(database *models.Database) error {
2016-12-30 11:04:01 +01:00
db, err := getDatabase(database)
2016-02-01 12:59:10 +01:00
if err != nil {
2016-12-30 11:04:01 +01:00
return err
2016-02-01 12:59:10 +01:00
}
return db.UpgradeSchema()
}
2016-02-01 12:59:10 +01:00
// InitDatabase registers the database
func InitDatabase(database *models.Database) error {
db, err := getDatabase(database)
if err != nil {
2016-12-30 11:04:01 +01:00
return err
2016-09-13 11:41:32 +02:00
}
log.Infof("Registering database: %s", db.String())
if err := db.Register(); err != nil {
return err
}
log.Info("Register database completed")
return nil
}
2016-12-30 11:04:01 +01:00
func getDatabase(database *models.Database) (db Database, err error) {
2016-12-30 11:04:01 +01:00
switch database.Type {
case "", "postgresql":
db = NewPGSQL(
database.PostGreSQL.Host,
strconv.Itoa(database.PostGreSQL.Port),
database.PostGreSQL.Username,
database.PostGreSQL.Password,
database.PostGreSQL.Database,
database.PostGreSQL.SSLMode,
database.PostGreSQL.MaxIdleConns,
database.PostGreSQL.MaxOpenConns,
)
2016-09-13 11:41:32 +02:00
default:
2016-12-30 11:04:01 +01:00
err = fmt.Errorf("invalid database: %s", database.Type)
2016-09-13 11:41:32 +02:00
}
return
}
2016-05-20 10:36:10 +02:00
var globalOrm orm.Ormer
2016-05-24 03:41:34 +02:00
var once sync.Once
2016-05-20 10:36:10 +02:00
2016-05-20 10:54:24 +02:00
// GetOrmer :set ormer singleton
2016-05-20 10:36:10 +02:00
func GetOrmer() orm.Ormer {
2016-05-24 03:41:34 +02:00
once.Do(func() {
// override the default value(1000) to return all records when setting no limit
orm.DefaultRowsLimit = -1
2016-05-20 10:36:10 +02:00
globalOrm = orm.NewOrm()
2016-05-24 03:41:34 +02:00
})
2016-05-20 10:36:10 +02:00
return globalOrm
}
// IsDupRecErr checks if the error is due to a duplication of record, currently this
// works only for pgSQL
func IsDupRecErr(e error) bool {
return strings.Contains(e.Error(), "duplicate key value violates unique constraint")
}
2017-05-23 07:33:20 +02:00
// ClearTable is the shortcut for test cases, it should be called only in test cases.
func ClearTable(table string) error {
o := GetOrmer()
sql := fmt.Sprintf("delete from %s where 1=1", table)
if table == models.ProjectTable {
sql = fmt.Sprintf("delete from %s where project_id > 1", table)
}
if table == models.UserTable {
sql = fmt.Sprintf("delete from %s where user_id > 2", table)
}
if table == "project_member" { // make sure admin in library
sql = fmt.Sprintf("delete from %s where id > 1", table)
}
if table == "project_metadata" { // make sure library is public
sql = fmt.Sprintf("delete from %s where id > 1", table)
}
2017-05-23 07:33:20 +02:00
_, err := o.Raw(sql).Exec()
return err
}
// PaginateForRawSQL ...
func PaginateForRawSQL(sql string, limit, offset int64) string {
return fmt.Sprintf("%s limit %d offset %d", sql, limit, offset)
}
2016-11-16 13:25:40 +01:00
// PaginateForQuerySetter ...
func PaginateForQuerySetter(qs orm.QuerySeter, page, size int64) orm.QuerySeter {
if size > 0 {
qs = qs.Limit(size)
if page > 0 {
qs = qs.Offset((page - 1) * size)
}
}
return qs
}
// Escape ..
2018-02-06 03:59:49 +01:00
func Escape(str string) string {
str = strings.Replace(str, `\`, `\\`, -1)
2016-11-16 13:25:40 +01:00
str = strings.Replace(str, `%`, `\%`, -1)
str = strings.Replace(str, `_`, `\_`, -1)
return str
}
// implements github.com/golang-migrate/migrate/v4.Logger
type mLogger struct {
logger *log.Logger
}
func newMigrateLogger() *mLogger {
return &mLogger{
logger: log.DefaultLogger().WithDepth(5),
}
}
// Verbose ...
func (l *mLogger) Verbose() bool {
return l.logger.GetLevel() <= log.DebugLevel
}
// Printf ...
func (l *mLogger) Printf(format string, v ...interface{}) {
l.logger.Infof(format, v...)
}