Move database settings from models to setting (#7806)
* move database settings from models to setting * update docs * fix checkout pr * fix tests * fix lint * remove unsupported tidb options * correct wrong variable name * remove tidb totally
This commit is contained in:
parent
26af3401c3
commit
f83db078f0
35 changed files with 423 additions and 376 deletions
|
@ -38,7 +38,7 @@ func initDB() error {
|
||||||
|
|
||||||
func initDBDisableConsole(disableConsole bool) error {
|
func initDBDisableConsole(disableConsole bool) error {
|
||||||
setting.NewContext()
|
setting.NewContext()
|
||||||
models.LoadConfigs()
|
setting.InitDBConfig()
|
||||||
|
|
||||||
setting.NewXORMLogService(disableConsole)
|
setting.NewXORMLogService(disableConsole)
|
||||||
if err := models.SetEngine(); err != nil {
|
if err := models.SetEngine(); err != nil {
|
||||||
|
|
|
@ -31,9 +31,9 @@ func runConvert(ctx *cli.Context) error {
|
||||||
log.Trace("AppWorkPath: %s", setting.AppWorkPath)
|
log.Trace("AppWorkPath: %s", setting.AppWorkPath)
|
||||||
log.Trace("Custom path: %s", setting.CustomPath)
|
log.Trace("Custom path: %s", setting.CustomPath)
|
||||||
log.Trace("Log path: %s", setting.LogRootPath)
|
log.Trace("Log path: %s", setting.LogRootPath)
|
||||||
models.LoadConfigs()
|
setting.InitDBConfig()
|
||||||
|
|
||||||
if models.DbCfg.Type != "mysql" {
|
if !setting.Database.UseMySQL {
|
||||||
fmt.Println("This command can only be used with a MySQL database")
|
fmt.Println("This command can only be used with a MySQL database")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,6 @@ It can be used for backup and capture Gitea server image to send to maintainer`,
|
||||||
func runDump(ctx *cli.Context) error {
|
func runDump(ctx *cli.Context) error {
|
||||||
setting.NewContext()
|
setting.NewContext()
|
||||||
setting.NewServices() // cannot access session settings otherwise
|
setting.NewServices() // cannot access session settings otherwise
|
||||||
models.LoadConfigs()
|
|
||||||
|
|
||||||
err := models.SetEngine()
|
err := models.SetEngine()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -104,8 +103,8 @@ func runDump(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
targetDBType := ctx.String("database")
|
targetDBType := ctx.String("database")
|
||||||
if len(targetDBType) > 0 && targetDBType != models.DbCfg.Type {
|
if len(targetDBType) > 0 && targetDBType != setting.Database.Type {
|
||||||
log.Printf("Dumping database %s => %s...", models.DbCfg.Type, targetDBType)
|
log.Printf("Dumping database %s => %s...", setting.Database.Type, targetDBType)
|
||||||
} else {
|
} else {
|
||||||
log.Printf("Dumping database...")
|
log.Printf("Dumping database...")
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ func runMigrate(ctx *cli.Context) error {
|
||||||
log.Trace("AppWorkPath: %s", setting.AppWorkPath)
|
log.Trace("AppWorkPath: %s", setting.AppWorkPath)
|
||||||
log.Trace("Custom path: %s", setting.CustomPath)
|
log.Trace("Custom path: %s", setting.CustomPath)
|
||||||
log.Trace("Log path: %s", setting.LogRootPath)
|
log.Trace("Log path: %s", setting.LogRootPath)
|
||||||
models.LoadConfigs()
|
setting.InitDBConfig()
|
||||||
|
|
||||||
if err := models.NewEngine(migrations.Migrate); err != nil {
|
if err := models.NewEngine(migrations.Migrate); err != nil {
|
||||||
log.Fatal("Failed to initialize ORM engine: %v", err)
|
log.Fatal("Failed to initialize ORM engine: %v", err)
|
||||||
|
|
|
@ -79,16 +79,16 @@ func runPR() {
|
||||||
setting.CheckLFSVersion()
|
setting.CheckLFSVersion()
|
||||||
//models.LoadConfigs()
|
//models.LoadConfigs()
|
||||||
/*
|
/*
|
||||||
models.DbCfg.Type = "sqlite3"
|
setting.Database.Type = "sqlite3"
|
||||||
models.DbCfg.Path = ":memory:"
|
setting.Database.Path = ":memory:"
|
||||||
models.DbCfg.Timeout = 500
|
setting.Database.Timeout = 500
|
||||||
*/
|
*/
|
||||||
db := setting.Cfg.Section("database")
|
db := setting.Cfg.Section("database")
|
||||||
db.NewKey("DB_TYPE", "sqlite3")
|
db.NewKey("DB_TYPE", "sqlite3")
|
||||||
db.NewKey("PATH", ":memory:")
|
db.NewKey("PATH", ":memory:")
|
||||||
setting.LogSQL = true
|
|
||||||
models.LoadConfigs()
|
|
||||||
routers.NewServices()
|
routers.NewServices()
|
||||||
|
setting.Database.LogSQL = true
|
||||||
//x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared")
|
//x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared")
|
||||||
|
|
||||||
var helper testfixtures.Helper = &testfixtures.SQLite{}
|
var helper testfixtures.Helper = &testfixtures.SQLite{}
|
||||||
|
|
|
@ -275,6 +275,10 @@ LOG_SQL = true
|
||||||
DB_RETRIES = 10
|
DB_RETRIES = 10
|
||||||
; Backoff time per DB retry (time.Duration)
|
; Backoff time per DB retry (time.Duration)
|
||||||
DB_RETRY_BACKOFF = 3s
|
DB_RETRY_BACKOFF = 3s
|
||||||
|
; Max idle database connections on connnection pool, default is 0
|
||||||
|
MAX_IDLE_CONNS = 0
|
||||||
|
; Database connection max life time, default is 3s
|
||||||
|
CONN_MAX_LIFETIME = 3s
|
||||||
|
|
||||||
[indexer]
|
[indexer]
|
||||||
; Issue indexer type, currently support: bleve or db, default is bleve
|
; Issue indexer type, currently support: bleve or db, default is bleve
|
||||||
|
|
|
@ -166,6 +166,8 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
||||||
- `LOG_SQL`: **true**: Log the executed SQL.
|
- `LOG_SQL`: **true**: Log the executed SQL.
|
||||||
- `DB_RETRIES`: **10**: How many ORM init / DB connect attempts allowed.
|
- `DB_RETRIES`: **10**: How many ORM init / DB connect attempts allowed.
|
||||||
- `DB_RETRY_BACKOFF`: **3s**: time.Duration to wait before trying another ORM init / DB connect attempt, if failure occured.
|
- `DB_RETRY_BACKOFF`: **3s**: time.Duration to wait before trying another ORM init / DB connect attempt, if failure occured.
|
||||||
|
- `MAX_IDLE_CONNS` **0**: Max idle database connections on connnection pool, default is 0
|
||||||
|
- `CONN_MAX_LIFETIME` **3s**: Database connection max lifetime
|
||||||
|
|
||||||
## Indexer (`indexer`)
|
## Indexer (`indexer`)
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,8 @@ menu:
|
||||||
- `CHARSET`: **utf8**: 仅当数据库为 MySQL 时有效, 可以为 "utf8" 或 "utf8mb4"。注意:如果使用 "utf8mb4",你的 MySQL InnoDB 版本必须在 5.6 以上。
|
- `CHARSET`: **utf8**: 仅当数据库为 MySQL 时有效, 可以为 "utf8" 或 "utf8mb4"。注意:如果使用 "utf8mb4",你的 MySQL InnoDB 版本必须在 5.6 以上。
|
||||||
- `PATH`: Tidb 或者 SQLite3 数据文件存放路径。
|
- `PATH`: Tidb 或者 SQLite3 数据文件存放路径。
|
||||||
- `LOG_SQL`: **true**: 显示生成的SQL,默认为真。
|
- `LOG_SQL`: **true**: 显示生成的SQL,默认为真。
|
||||||
|
- `MAX_IDLE_CONNS` **0**: 最大空闲数据库连接
|
||||||
|
- `CONN_MAX_LIFETIME` **3s**: 数据库连接最大存活时间
|
||||||
|
|
||||||
## Indexer (`indexer`)
|
## Indexer (`indexer`)
|
||||||
|
|
||||||
|
|
|
@ -59,13 +59,13 @@ func TestMain(m *testing.M) {
|
||||||
routes.RegisterRoutes(mac)
|
routes.RegisterRoutes(mac)
|
||||||
|
|
||||||
var helper testfixtures.Helper
|
var helper testfixtures.Helper
|
||||||
if setting.UseMySQL {
|
if setting.Database.UseMySQL {
|
||||||
helper = &testfixtures.MySQL{}
|
helper = &testfixtures.MySQL{}
|
||||||
} else if setting.UsePostgreSQL {
|
} else if setting.Database.UsePostgreSQL {
|
||||||
helper = &testfixtures.PostgreSQL{}
|
helper = &testfixtures.PostgreSQL{}
|
||||||
} else if setting.UseSQLite3 {
|
} else if setting.Database.UseSQLite3 {
|
||||||
helper = &testfixtures.SQLite{}
|
helper = &testfixtures.SQLite{}
|
||||||
} else if setting.UseMSSQL {
|
} else if setting.Database.UseMSSQL {
|
||||||
helper = &testfixtures.SQLServer{}
|
helper = &testfixtures.SQLServer{}
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("Unsupported RDBMS for integration tests")
|
fmt.Println("Unsupported RDBMS for integration tests")
|
||||||
|
@ -121,12 +121,12 @@ func initIntegrationTest() {
|
||||||
setting.SetCustomPathAndConf("", "", "")
|
setting.SetCustomPathAndConf("", "", "")
|
||||||
setting.NewContext()
|
setting.NewContext()
|
||||||
setting.CheckLFSVersion()
|
setting.CheckLFSVersion()
|
||||||
models.LoadConfigs()
|
setting.InitDBConfig()
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case setting.UseMySQL:
|
case setting.Database.UseMySQL:
|
||||||
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/",
|
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/",
|
||||||
models.DbCfg.User, models.DbCfg.Passwd, models.DbCfg.Host))
|
setting.Database.User, setting.Database.Passwd, setting.Database.Host))
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("sql.Open: %v", err)
|
log.Fatalf("sql.Open: %v", err)
|
||||||
|
@ -134,14 +134,14 @@ func initIntegrationTest() {
|
||||||
if _, err = db.Exec("CREATE DATABASE IF NOT EXISTS testgitea"); err != nil {
|
if _, err = db.Exec("CREATE DATABASE IF NOT EXISTS testgitea"); err != nil {
|
||||||
log.Fatalf("db.Exec: %v", err)
|
log.Fatalf("db.Exec: %v", err)
|
||||||
}
|
}
|
||||||
case setting.UsePostgreSQL:
|
case setting.Database.UsePostgreSQL:
|
||||||
db, err := sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/?sslmode=%s",
|
db, err := sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/?sslmode=%s",
|
||||||
models.DbCfg.User, models.DbCfg.Passwd, models.DbCfg.Host, models.DbCfg.SSLMode))
|
setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.SSLMode))
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("sql.Open: %v", err)
|
log.Fatalf("sql.Open: %v", err)
|
||||||
}
|
}
|
||||||
rows, err := db.Query(fmt.Sprintf("SELECT 1 FROM pg_database WHERE datname = '%s'", models.DbCfg.Name))
|
rows, err := db.Query(fmt.Sprintf("SELECT 1 FROM pg_database WHERE datname = '%s'", setting.Database.Name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("db.Query: %v", err)
|
log.Fatalf("db.Query: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -153,10 +153,10 @@ func initIntegrationTest() {
|
||||||
if _, err = db.Exec("CREATE DATABASE testgitea"); err != nil {
|
if _, err = db.Exec("CREATE DATABASE testgitea"); err != nil {
|
||||||
log.Fatalf("db.Exec: %v", err)
|
log.Fatalf("db.Exec: %v", err)
|
||||||
}
|
}
|
||||||
case setting.UseMSSQL:
|
case setting.Database.UseMSSQL:
|
||||||
host, port := models.ParseMSSQLHostPort(models.DbCfg.Host)
|
host, port := setting.ParseMSSQLHostPort(setting.Database.Host)
|
||||||
db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;",
|
db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;",
|
||||||
host, port, "master", models.DbCfg.User, models.DbCfg.Passwd))
|
host, port, "master", setting.Database.User, setting.Database.Passwd))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("sql.Open: %v", err)
|
log.Fatalf("sql.Open: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ func storeObjectInRepo(t *testing.T, repositoryID int64, content *[]byte) string
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
var lfsMetaObject *models.LFSMetaObject
|
var lfsMetaObject *models.LFSMetaObject
|
||||||
|
|
||||||
if setting.UsePostgreSQL {
|
if setting.Database.UsePostgreSQL {
|
||||||
lfsMetaObject = &models.LFSMetaObject{ID: lfsID, Oid: oid, Size: int64(len(*content)), RepositoryID: repositoryID}
|
lfsMetaObject = &models.LFSMetaObject{ID: lfsID, Oid: oid, Size: int64(len(*content)), RepositoryID: repositoryID}
|
||||||
} else {
|
} else {
|
||||||
lfsMetaObject = &models.LFSMetaObject{Oid: oid, Size: int64(len(*content)), RepositoryID: repositoryID}
|
lfsMetaObject = &models.LFSMetaObject{Oid: oid, Size: int64(len(*content)), RepositoryID: repositoryID}
|
||||||
|
|
|
@ -54,7 +54,7 @@ func initMigrationTest(t *testing.T) {
|
||||||
|
|
||||||
setting.NewContext()
|
setting.NewContext()
|
||||||
setting.CheckLFSVersion()
|
setting.CheckLFSVersion()
|
||||||
models.LoadConfigs()
|
setting.InitDBConfig()
|
||||||
setting.NewLogServices(true)
|
setting.NewLogServices(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ func availableVersions() ([]string, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer migrationsDir.Close()
|
defer migrationsDir.Close()
|
||||||
versionRE, err := regexp.Compile("gitea-v(?P<version>.+)\\." + regexp.QuoteMeta(models.DbCfg.Type) + "\\.sql.gz")
|
versionRE, err := regexp.Compile("gitea-v(?P<version>.+)\\." + regexp.QuoteMeta(setting.Database.Type) + "\\.sql.gz")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ func availableVersions() ([]string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func readSQLFromFile(version string) (string, error) {
|
func readSQLFromFile(version string) (string, error) {
|
||||||
filename := fmt.Sprintf("integrations/migration-test/gitea-v%s.%s.sql.gz", version, models.DbCfg.Type)
|
filename := fmt.Sprintf("integrations/migration-test/gitea-v%s.%s.sql.gz", version, setting.Database.Type)
|
||||||
|
|
||||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||||
return "", nil
|
return "", nil
|
||||||
|
@ -114,17 +114,17 @@ func restoreOldDB(t *testing.T, version string) bool {
|
||||||
data, err := readSQLFromFile(version)
|
data, err := readSQLFromFile(version)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
integrations.Printf("No db found to restore for %s version: %s\n", models.DbCfg.Type, version)
|
integrations.Printf("No db found to restore for %s version: %s\n", setting.Database.Type, version)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case setting.UseSQLite3:
|
case setting.Database.UseSQLite3:
|
||||||
os.Remove(models.DbCfg.Path)
|
os.Remove(setting.Database.Path)
|
||||||
err := os.MkdirAll(path.Dir(models.DbCfg.Path), os.ModePerm)
|
err := os.MkdirAll(path.Dir(setting.Database.Path), os.ModePerm)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
db, err := sql.Open("sqlite3", fmt.Sprintf("file:%s?cache=shared&mode=rwc&_busy_timeout=%d", models.DbCfg.Path, models.DbCfg.Timeout))
|
db, err := sql.Open("sqlite3", fmt.Sprintf("file:%s?cache=shared&mode=rwc&_busy_timeout=%d", setting.Database.Path, setting.Database.Timeout))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
|
@ -132,20 +132,20 @@ func restoreOldDB(t *testing.T, version string) bool {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
db.Close()
|
db.Close()
|
||||||
|
|
||||||
case setting.UseMySQL:
|
case setting.Database.UseMySQL:
|
||||||
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/",
|
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/",
|
||||||
models.DbCfg.User, models.DbCfg.Passwd, models.DbCfg.Host))
|
setting.Database.User, setting.Database.Passwd, setting.Database.Host))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
_, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS %s", models.DbCfg.Name))
|
_, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS %s", setting.Database.Name))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
_, err = db.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", models.DbCfg.Name))
|
_, err = db.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", setting.Database.Name))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
db, err = sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?multiStatements=true",
|
db, err = sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?multiStatements=true",
|
||||||
models.DbCfg.User, models.DbCfg.Passwd, models.DbCfg.Host, models.DbCfg.Name))
|
setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
|
@ -153,21 +153,21 @@ func restoreOldDB(t *testing.T, version string) bool {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
db.Close()
|
db.Close()
|
||||||
|
|
||||||
case setting.UsePostgreSQL:
|
case setting.Database.UsePostgreSQL:
|
||||||
db, err := sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/?sslmode=%s",
|
db, err := sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/?sslmode=%s",
|
||||||
models.DbCfg.User, models.DbCfg.Passwd, models.DbCfg.Host, models.DbCfg.SSLMode))
|
setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.SSLMode))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
_, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS %s", models.DbCfg.Name))
|
_, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS %s", setting.Database.Name))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
_, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s", models.DbCfg.Name))
|
_, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s", setting.Database.Name))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
db.Close()
|
db.Close()
|
||||||
|
|
||||||
db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s",
|
db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s",
|
||||||
models.DbCfg.User, models.DbCfg.Passwd, models.DbCfg.Host, models.DbCfg.Name, models.DbCfg.SSLMode))
|
setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name, setting.Database.SSLMode))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
|
@ -175,10 +175,10 @@ func restoreOldDB(t *testing.T, version string) bool {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
db.Close()
|
db.Close()
|
||||||
|
|
||||||
case setting.UseMSSQL:
|
case setting.Database.UseMSSQL:
|
||||||
host, port := models.ParseMSSQLHostPort(models.DbCfg.Host)
|
host, port := setting.ParseMSSQLHostPort(setting.Database.Host)
|
||||||
db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;",
|
db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;",
|
||||||
host, port, "master", models.DbCfg.User, models.DbCfg.Passwd))
|
host, port, "master", setting.Database.User, setting.Database.Passwd))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ func restoreOldDB(t *testing.T, version string) bool {
|
||||||
dbname := statement[5 : len(statement)-1]
|
dbname := statement[5 : len(statement)-1]
|
||||||
db.Close()
|
db.Close()
|
||||||
db, err = sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;",
|
db, err = sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;",
|
||||||
host, port, dbname, models.DbCfg.User, models.DbCfg.Passwd))
|
host, port, dbname, setting.Database.User, setting.Database.Passwd))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
}
|
}
|
||||||
|
@ -210,7 +210,7 @@ func wrappedMigrate(x *xorm.Engine) error {
|
||||||
|
|
||||||
func doMigrationTest(t *testing.T, version string) {
|
func doMigrationTest(t *testing.T, version string) {
|
||||||
integrations.PrintCurrentTest(t)
|
integrations.PrintCurrentTest(t)
|
||||||
integrations.Printf("Performing migration test for %s version: %s\n", models.DbCfg.Type, version)
|
integrations.Printf("Performing migration test for %s version: %s\n", setting.Database.Type, version)
|
||||||
if !restoreOldDB(t, version) {
|
if !restoreOldDB(t, version) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -227,7 +227,7 @@ func doMigrationTest(t *testing.T, version string) {
|
||||||
func TestMigrations(t *testing.T) {
|
func TestMigrations(t *testing.T) {
|
||||||
initMigrationTest(t)
|
initMigrationTest(t)
|
||||||
|
|
||||||
dialect := models.DbCfg.Type
|
dialect := setting.Database.Type
|
||||||
versions, err := availableVersions()
|
versions, err := availableVersions()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,15 @@
|
||||||
|
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
)
|
||||||
|
|
||||||
// ConvertUtf8ToUtf8mb4 converts database and tables from utf8 to utf8mb4 if it's mysql
|
// ConvertUtf8ToUtf8mb4 converts database and tables from utf8 to utf8mb4 if it's mysql
|
||||||
func ConvertUtf8ToUtf8mb4() error {
|
func ConvertUtf8ToUtf8mb4() error {
|
||||||
_, err := x.Exec(fmt.Sprintf("ALTER DATABASE `%s` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci", DbCfg.Name))
|
_, err := x.Exec(fmt.Sprintf("ALTER DATABASE `%s` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci", setting.Database.Name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -296,7 +296,7 @@ func dropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin
|
||||||
// TODO: This will not work if there are foreign keys
|
// TODO: This will not work if there are foreign keys
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case setting.UseSQLite3:
|
case setting.Database.UseSQLite3:
|
||||||
// First drop the indexes on the columns
|
// First drop the indexes on the columns
|
||||||
res, errIndex := sess.Query(fmt.Sprintf("PRAGMA index_list(`%s`)", tableName))
|
res, errIndex := sess.Query(fmt.Sprintf("PRAGMA index_list(`%s`)", tableName))
|
||||||
if errIndex != nil {
|
if errIndex != nil {
|
||||||
|
@ -372,7 +372,7 @@ func dropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
case setting.UsePostgreSQL:
|
case setting.Database.UsePostgreSQL:
|
||||||
cols := ""
|
cols := ""
|
||||||
for _, col := range columnNames {
|
for _, col := range columnNames {
|
||||||
if cols != "" {
|
if cols != "" {
|
||||||
|
@ -383,7 +383,7 @@ func dropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin
|
||||||
if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` %s", tableName, cols)); err != nil {
|
if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` %s", tableName, cols)); err != nil {
|
||||||
return fmt.Errorf("Drop table `%s` columns %v: %v", tableName, columnNames, err)
|
return fmt.Errorf("Drop table `%s` columns %v: %v", tableName, columnNames, err)
|
||||||
}
|
}
|
||||||
case setting.UseMySQL, setting.UseTiDB:
|
case setting.Database.UseMySQL:
|
||||||
// Drop indexes on columns first
|
// Drop indexes on columns first
|
||||||
sql := fmt.Sprintf("SHOW INDEX FROM %s WHERE column_name IN ('%s')", tableName, strings.Join(columnNames, "','"))
|
sql := fmt.Sprintf("SHOW INDEX FROM %s WHERE column_name IN ('%s')", tableName, strings.Join(columnNames, "','"))
|
||||||
res, err := sess.Query(sql)
|
res, err := sess.Query(sql)
|
||||||
|
@ -409,7 +409,7 @@ func dropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin
|
||||||
if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` %s", tableName, cols)); err != nil {
|
if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` %s", tableName, cols)); err != nil {
|
||||||
return fmt.Errorf("Drop table `%s` columns %v: %v", tableName, columnNames, err)
|
return fmt.Errorf("Drop table `%s` columns %v: %v", tableName, columnNames, err)
|
||||||
}
|
}
|
||||||
case setting.UseMSSQL:
|
case setting.Database.UseMSSQL:
|
||||||
cols := ""
|
cols := ""
|
||||||
for _, col := range columnNames {
|
for _, col := range columnNames {
|
||||||
if cols != "" {
|
if cols != "" {
|
||||||
|
|
|
@ -42,7 +42,7 @@ func generateAndMigrateGitHooks(x *xorm.Engine) (err error) {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
return x.Where("id > 0").BufferSize(setting.IterateBufferSize).Iterate(new(Repository),
|
return x.Where("id > 0").BufferSize(setting.Database.IterateBufferSize).Iterate(new(Repository),
|
||||||
func(idx int, bean interface{}) error {
|
func(idx int, bean interface{}) error {
|
||||||
repo := bean.(*Repository)
|
repo := bean.(*Repository)
|
||||||
user := new(User)
|
user := new(User)
|
||||||
|
|
|
@ -42,7 +42,7 @@ func generateAndMigrateWikiGitHooks(x *xorm.Engine) (err error) {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
return x.Where("id > 0").BufferSize(setting.IterateBufferSize).Iterate(new(Repository),
|
return x.Where("id > 0").BufferSize(setting.Database.IterateBufferSize).Iterate(new(Repository),
|
||||||
func(idx int, bean interface{}) error {
|
func(idx int, bean interface{}) error {
|
||||||
repo := bean.(*Repository)
|
repo := bean.(*Repository)
|
||||||
user := new(User)
|
user := new(User)
|
||||||
|
|
|
@ -36,7 +36,7 @@ func generateAndMigrateGitHookChains(x *xorm.Engine) (err error) {
|
||||||
hookTpl = fmt.Sprintf("#!/usr/bin/env %s\ndata=$(cat)\nexitcodes=\"\"\nhookname=$(basename $0)\nGIT_DIR=${GIT_DIR:-$(dirname $0)}\n\nfor hook in ${GIT_DIR}/hooks/${hookname}.d/*; do\ntest -x \"${hook}\" || continue\necho \"${data}\" | \"${hook}\"\nexitcodes=\"${exitcodes} $?\"\ndone\n\nfor i in ${exitcodes}; do\n[ ${i} -eq 0 ] || exit ${i}\ndone\n", setting.ScriptType)
|
hookTpl = fmt.Sprintf("#!/usr/bin/env %s\ndata=$(cat)\nexitcodes=\"\"\nhookname=$(basename $0)\nGIT_DIR=${GIT_DIR:-$(dirname $0)}\n\nfor hook in ${GIT_DIR}/hooks/${hookname}.d/*; do\ntest -x \"${hook}\" || continue\necho \"${data}\" | \"${hook}\"\nexitcodes=\"${exitcodes} $?\"\ndone\n\nfor i in ${exitcodes}; do\n[ ${i} -eq 0 ] || exit ${i}\ndone\n", setting.ScriptType)
|
||||||
)
|
)
|
||||||
|
|
||||||
return x.Where("id > 0").BufferSize(setting.IterateBufferSize).Iterate(new(Repository),
|
return x.Where("id > 0").BufferSize(setting.Database.IterateBufferSize).Iterate(new(Repository),
|
||||||
func(idx int, bean interface{}) error {
|
func(idx int, bean interface{}) error {
|
||||||
repo := bean.(*Repository)
|
repo := bean.(*Repository)
|
||||||
user := new(User)
|
user := new(User)
|
||||||
|
|
|
@ -41,8 +41,6 @@ func convertIntervalToDuration(x *xorm.Engine) (err error) {
|
||||||
_, err = sess.Exec("ALTER TABLE mirror MODIFY `interval` BIGINT")
|
_, err = sess.Exec("ALTER TABLE mirror MODIFY `interval` BIGINT")
|
||||||
case "postgres":
|
case "postgres":
|
||||||
_, err = sess.Exec("ALTER TABLE mirror ALTER COLUMN \"interval\" SET DATA TYPE bigint")
|
_, err = sess.Exec("ALTER TABLE mirror ALTER COLUMN \"interval\" SET DATA TYPE bigint")
|
||||||
case "tidb":
|
|
||||||
_, err = sess.Exec("ALTER TABLE mirror MODIFY `interval` BIGINT")
|
|
||||||
case "mssql":
|
case "mssql":
|
||||||
_, err = sess.Exec("ALTER TABLE mirror ALTER COLUMN \"interval\" BIGINT")
|
_, err = sess.Exec("ALTER TABLE mirror ALTER COLUMN \"interval\" BIGINT")
|
||||||
case "sqlite3":
|
case "sqlite3":
|
||||||
|
|
|
@ -15,9 +15,9 @@ import (
|
||||||
|
|
||||||
func removeActionColumns(x *xorm.Engine) error {
|
func removeActionColumns(x *xorm.Engine) error {
|
||||||
switch {
|
switch {
|
||||||
case setting.UseSQLite3:
|
case setting.Database.UseSQLite3:
|
||||||
log.Warn("Unable to drop columns in SQLite")
|
log.Warn("Unable to drop columns in SQLite")
|
||||||
case setting.UseMySQL, setting.UsePostgreSQL, setting.UseMSSQL, setting.UseTiDB:
|
case setting.Database.UseMySQL, setting.Database.UsePostgreSQL, setting.Database.UseMSSQL:
|
||||||
if _, err := x.Exec("ALTER TABLE action DROP COLUMN act_user_name"); err != nil {
|
if _, err := x.Exec("ALTER TABLE action DROP COLUMN act_user_name"); err != nil {
|
||||||
return fmt.Errorf("DROP COLUMN act_user_name: %v", err)
|
return fmt.Errorf("DROP COLUMN act_user_name: %v", err)
|
||||||
} else if _, err = x.Exec("ALTER TABLE action DROP COLUMN repo_user_name"); err != nil {
|
} else if _, err = x.Exec("ALTER TABLE action DROP COLUMN repo_user_name"); err != nil {
|
||||||
|
|
|
@ -13,9 +13,9 @@ import (
|
||||||
|
|
||||||
func removeIndexColumnFromRepoUnitTable(x *xorm.Engine) (err error) {
|
func removeIndexColumnFromRepoUnitTable(x *xorm.Engine) (err error) {
|
||||||
switch {
|
switch {
|
||||||
case setting.UseSQLite3:
|
case setting.Database.UseSQLite3:
|
||||||
log.Warn("Unable to drop columns in SQLite")
|
log.Warn("Unable to drop columns in SQLite")
|
||||||
case setting.UseMySQL, setting.UsePostgreSQL, setting.UseMSSQL, setting.UseTiDB:
|
case setting.Database.UseMySQL, setting.Database.UsePostgreSQL, setting.Database.UseMSSQL:
|
||||||
if _, err := x.Exec("ALTER TABLE repo_unit DROP COLUMN `index`"); err != nil {
|
if _, err := x.Exec("ALTER TABLE repo_unit DROP COLUMN `index`"); err != nil {
|
||||||
// Ignoring this error in case we run this migration second time (after migration reordering)
|
// Ignoring this error in case we run this migration second time (after migration reordering)
|
||||||
log.Warn("DROP COLUMN index: %v", err)
|
log.Warn("DROP COLUMN index: %v", err)
|
||||||
|
|
|
@ -40,9 +40,9 @@ func migrateProtectedBranchStruct(x *xorm.Engine) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case setting.UseSQLite3:
|
case setting.Database.UseSQLite3:
|
||||||
log.Warn("Unable to drop columns in SQLite")
|
log.Warn("Unable to drop columns in SQLite")
|
||||||
case setting.UseMySQL, setting.UsePostgreSQL, setting.UseMSSQL, setting.UseTiDB:
|
case setting.Database.UseMySQL, setting.Database.UsePostgreSQL, setting.Database.UseMSSQL:
|
||||||
if _, err := x.Exec("ALTER TABLE protected_branch DROP COLUMN can_push"); err != nil {
|
if _, err := x.Exec("ALTER TABLE protected_branch DROP COLUMN can_push"); err != nil {
|
||||||
// Ignoring this error in case we run this migration second time (after migration reordering)
|
// Ignoring this error in case we run this migration second time (after migration reordering)
|
||||||
log.Warn("DROP COLUMN can_push (skipping): %v", err)
|
log.Warn("DROP COLUMN can_push (skipping): %v", err)
|
||||||
|
|
|
@ -80,7 +80,7 @@ func removeStaleWatches(x *xorm.Engine) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
repoCache := make(map[int64]*Repository)
|
repoCache := make(map[int64]*Repository)
|
||||||
err := sess.BufferSize(setting.IterateBufferSize).Iterate(new(Watch),
|
err := sess.BufferSize(setting.Database.IterateBufferSize).Iterate(new(Watch),
|
||||||
func(idx int, bean interface{}) error {
|
func(idx int, bean interface{}) error {
|
||||||
watch := bean.(*Watch)
|
watch := bean.(*Watch)
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ func removeStaleWatches(x *xorm.Engine) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
repoCache = make(map[int64]*Repository)
|
repoCache = make(map[int64]*Repository)
|
||||||
err = sess.BufferSize(setting.IterateBufferSize).
|
err = sess.BufferSize(setting.Database.IterateBufferSize).
|
||||||
Distinct("issue_watch.user_id", "issue.repo_id").
|
Distinct("issue_watch.user_id", "issue.repo_id").
|
||||||
Join("INNER", "issue", "issue_watch.issue_id = issue.id").
|
Join("INNER", "issue", "issue_watch.issue_id = issue.id").
|
||||||
Where("issue_watch.is_watching = ?", true).
|
Where("issue_watch.is_watching = ?", true).
|
||||||
|
|
|
@ -14,8 +14,6 @@ func changeU2FCounterType(x *xorm.Engine) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
switch x.Dialect().DriverName() {
|
switch x.Dialect().DriverName() {
|
||||||
case "tidb":
|
|
||||||
fallthrough
|
|
||||||
case "mysql":
|
case "mysql":
|
||||||
_, err = x.Exec("ALTER TABLE `u2f_registration` MODIFY `counter` BIGINT")
|
_, err = x.Exec("ALTER TABLE `u2f_registration` MODIFY `counter` BIGINT")
|
||||||
case "postgres":
|
case "postgres":
|
||||||
|
|
144
models/models.go
144
models/models.go
|
@ -9,12 +9,6 @@ import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
|
@ -53,23 +47,10 @@ type Engine interface {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
x *xorm.Engine
|
x *xorm.Engine
|
||||||
supportedDatabases = []string{"mysql", "postgres", "mssql"}
|
|
||||||
tables []interface{}
|
tables []interface{}
|
||||||
|
|
||||||
// HasEngine specifies if we have a xorm.Engine
|
// HasEngine specifies if we have a xorm.Engine
|
||||||
HasEngine bool
|
HasEngine bool
|
||||||
|
|
||||||
// DbCfg holds the database settings
|
|
||||||
DbCfg struct {
|
|
||||||
Type, Host, Name, User, Passwd, Path, SSLMode, Charset string
|
|
||||||
Timeout int
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnableSQLite3 use SQLite3
|
|
||||||
EnableSQLite3 bool
|
|
||||||
|
|
||||||
// EnableTiDB enable TiDB
|
|
||||||
EnableTiDB bool
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -139,120 +120,13 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadConfigs loads the database settings
|
|
||||||
func LoadConfigs() {
|
|
||||||
sec := setting.Cfg.Section("database")
|
|
||||||
DbCfg.Type = sec.Key("DB_TYPE").String()
|
|
||||||
switch DbCfg.Type {
|
|
||||||
case "sqlite3":
|
|
||||||
setting.UseSQLite3 = true
|
|
||||||
case "mysql":
|
|
||||||
setting.UseMySQL = true
|
|
||||||
case "postgres":
|
|
||||||
setting.UsePostgreSQL = true
|
|
||||||
case "tidb":
|
|
||||||
setting.UseTiDB = true
|
|
||||||
case "mssql":
|
|
||||||
setting.UseMSSQL = true
|
|
||||||
}
|
|
||||||
DbCfg.Host = sec.Key("HOST").String()
|
|
||||||
DbCfg.Name = sec.Key("NAME").String()
|
|
||||||
DbCfg.User = sec.Key("USER").String()
|
|
||||||
if len(DbCfg.Passwd) == 0 {
|
|
||||||
DbCfg.Passwd = sec.Key("PASSWD").String()
|
|
||||||
}
|
|
||||||
DbCfg.SSLMode = sec.Key("SSL_MODE").MustString("disable")
|
|
||||||
DbCfg.Charset = sec.Key("CHARSET").In("utf8", []string{"utf8", "utf8mb4"})
|
|
||||||
DbCfg.Path = sec.Key("PATH").MustString(filepath.Join(setting.AppDataPath, "gitea.db"))
|
|
||||||
DbCfg.Timeout = sec.Key("SQLITE_TIMEOUT").MustInt(500)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parsePostgreSQLHostPort parses given input in various forms defined in
|
|
||||||
// https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING
|
|
||||||
// and returns proper host and port number.
|
|
||||||
func parsePostgreSQLHostPort(info string) (string, string) {
|
|
||||||
host, port := "127.0.0.1", "5432"
|
|
||||||
if strings.Contains(info, ":") && !strings.HasSuffix(info, "]") {
|
|
||||||
idx := strings.LastIndex(info, ":")
|
|
||||||
host = info[:idx]
|
|
||||||
port = info[idx+1:]
|
|
||||||
} else if len(info) > 0 {
|
|
||||||
host = info
|
|
||||||
}
|
|
||||||
return host, port
|
|
||||||
}
|
|
||||||
|
|
||||||
func getPostgreSQLConnectionString(dbHost, dbUser, dbPasswd, dbName, dbParam, dbsslMode string) (connStr string) {
|
|
||||||
host, port := parsePostgreSQLHostPort(dbHost)
|
|
||||||
if host[0] == '/' { // looks like a unix socket
|
|
||||||
connStr = fmt.Sprintf("postgres://%s:%s@:%s/%s%ssslmode=%s&host=%s",
|
|
||||||
url.PathEscape(dbUser), url.PathEscape(dbPasswd), port, dbName, dbParam, dbsslMode, host)
|
|
||||||
} else {
|
|
||||||
connStr = fmt.Sprintf("postgres://%s:%s@%s:%s/%s%ssslmode=%s",
|
|
||||||
url.PathEscape(dbUser), url.PathEscape(dbPasswd), host, port, dbName, dbParam, dbsslMode)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseMSSQLHostPort splits the host into host and port
|
|
||||||
func ParseMSSQLHostPort(info string) (string, string) {
|
|
||||||
host, port := "127.0.0.1", "1433"
|
|
||||||
if strings.Contains(info, ":") {
|
|
||||||
host = strings.Split(info, ":")[0]
|
|
||||||
port = strings.Split(info, ":")[1]
|
|
||||||
} else if strings.Contains(info, ",") {
|
|
||||||
host = strings.Split(info, ",")[0]
|
|
||||||
port = strings.TrimSpace(strings.Split(info, ",")[1])
|
|
||||||
} else if len(info) > 0 {
|
|
||||||
host = info
|
|
||||||
}
|
|
||||||
return host, port
|
|
||||||
}
|
|
||||||
|
|
||||||
func getEngine() (*xorm.Engine, error) {
|
func getEngine() (*xorm.Engine, error) {
|
||||||
connStr := ""
|
connStr, err := setting.DBConnStr()
|
||||||
var Param = "?"
|
if err != nil {
|
||||||
if strings.Contains(DbCfg.Name, Param) {
|
return nil, err
|
||||||
Param = "&"
|
|
||||||
}
|
|
||||||
switch DbCfg.Type {
|
|
||||||
case "mysql":
|
|
||||||
connType := "tcp"
|
|
||||||
if DbCfg.Host[0] == '/' { // looks like a unix socket
|
|
||||||
connType = "unix"
|
|
||||||
}
|
|
||||||
tls := DbCfg.SSLMode
|
|
||||||
if tls == "disable" { // allow (Postgres-inspired) default value to work in MySQL
|
|
||||||
tls = "false"
|
|
||||||
}
|
|
||||||
connStr = fmt.Sprintf("%s:%s@%s(%s)/%s%scharset=%s&parseTime=true&tls=%s",
|
|
||||||
DbCfg.User, DbCfg.Passwd, connType, DbCfg.Host, DbCfg.Name, Param, DbCfg.Charset, tls)
|
|
||||||
case "postgres":
|
|
||||||
connStr = getPostgreSQLConnectionString(DbCfg.Host, DbCfg.User, DbCfg.Passwd, DbCfg.Name, Param, DbCfg.SSLMode)
|
|
||||||
case "mssql":
|
|
||||||
host, port := ParseMSSQLHostPort(DbCfg.Host)
|
|
||||||
connStr = fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", host, port, DbCfg.Name, DbCfg.User, DbCfg.Passwd)
|
|
||||||
case "sqlite3":
|
|
||||||
if !EnableSQLite3 {
|
|
||||||
return nil, errors.New("this binary version does not build support for SQLite3")
|
|
||||||
}
|
|
||||||
if err := os.MkdirAll(path.Dir(DbCfg.Path), os.ModePerm); err != nil {
|
|
||||||
return nil, fmt.Errorf("Failed to create directories: %v", err)
|
|
||||||
}
|
|
||||||
connStr = fmt.Sprintf("file:%s?cache=shared&mode=rwc&_busy_timeout=%d", DbCfg.Path, DbCfg.Timeout)
|
|
||||||
case "tidb":
|
|
||||||
if !EnableTiDB {
|
|
||||||
return nil, errors.New("this binary version does not build support for TiDB")
|
|
||||||
}
|
|
||||||
if err := os.MkdirAll(path.Dir(DbCfg.Path), os.ModePerm); err != nil {
|
|
||||||
return nil, fmt.Errorf("Failed to create directories: %v", err)
|
|
||||||
}
|
|
||||||
connStr = "goleveldb://" + DbCfg.Path
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("Unknown database type: %s", DbCfg.Type)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return xorm.NewEngine(DbCfg.Type, connStr)
|
return xorm.NewEngine(setting.Database.Type, connStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTestEngine sets a new test xorm.Engine
|
// NewTestEngine sets a new test xorm.Engine
|
||||||
|
@ -280,11 +154,11 @@ func SetEngine() (err error) {
|
||||||
x.SetMapper(core.GonicMapper{})
|
x.SetMapper(core.GonicMapper{})
|
||||||
// WARNING: for serv command, MUST remove the output to os.stdout,
|
// WARNING: for serv command, MUST remove the output to os.stdout,
|
||||||
// so use log file to instead print to stdout.
|
// so use log file to instead print to stdout.
|
||||||
x.SetLogger(NewXORMLogger(setting.LogSQL))
|
x.SetLogger(NewXORMLogger(setting.Database.LogSQL))
|
||||||
x.ShowSQL(setting.LogSQL)
|
x.ShowSQL(setting.Database.LogSQL)
|
||||||
if DbCfg.Type == "mysql" {
|
if setting.Database.UseMySQL {
|
||||||
x.SetMaxIdleConns(0)
|
x.SetMaxIdleConns(setting.Database.MaxIdleConns)
|
||||||
x.SetConnMaxLifetime(3 * time.Second)
|
x.SetConnMaxLifetime(setting.Database.ConnMaxLifetime)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// Copyright 2016 The Gogs Authors. All rights reserved.
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
@ -11,99 +10,19 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_parsePostgreSQLHostPort(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
HostPort string
|
|
||||||
Host string
|
|
||||||
Port string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
HostPort: "127.0.0.1:1234",
|
|
||||||
Host: "127.0.0.1",
|
|
||||||
Port: "1234",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
HostPort: "127.0.0.1",
|
|
||||||
Host: "127.0.0.1",
|
|
||||||
Port: "5432",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
HostPort: "[::1]:1234",
|
|
||||||
Host: "[::1]",
|
|
||||||
Port: "1234",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
HostPort: "[::1]",
|
|
||||||
Host: "[::1]",
|
|
||||||
Port: "5432",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
HostPort: "/tmp/pg.sock:1234",
|
|
||||||
Host: "/tmp/pg.sock",
|
|
||||||
Port: "1234",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
HostPort: "/tmp/pg.sock",
|
|
||||||
Host: "/tmp/pg.sock",
|
|
||||||
Port: "5432",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
host, port := parsePostgreSQLHostPort(test.HostPort)
|
|
||||||
assert.Equal(t, test.Host, host)
|
|
||||||
assert.Equal(t, test.Port, port)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_getPostgreSQLConnectionString(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
Host string
|
|
||||||
Port string
|
|
||||||
User string
|
|
||||||
Passwd string
|
|
||||||
Name string
|
|
||||||
Param string
|
|
||||||
SSLMode string
|
|
||||||
Output string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
Host: "/tmp/pg.sock",
|
|
||||||
Port: "4321",
|
|
||||||
User: "testuser",
|
|
||||||
Passwd: "space space !#$%^^%^```-=?=",
|
|
||||||
Name: "gitea",
|
|
||||||
Param: "",
|
|
||||||
SSLMode: "false",
|
|
||||||
Output: "postgres://testuser:space%20space%20%21%23$%25%5E%5E%25%5E%60%60%60-=%3F=@:5432/giteasslmode=false&host=/tmp/pg.sock",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Host: "localhost",
|
|
||||||
Port: "1234",
|
|
||||||
User: "pgsqlusername",
|
|
||||||
Passwd: "I love Gitea!",
|
|
||||||
Name: "gitea",
|
|
||||||
Param: "",
|
|
||||||
SSLMode: "true",
|
|
||||||
Output: "postgres://pgsqlusername:I%20love%20Gitea%21@localhost:5432/giteasslmode=true",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
connStr := getPostgreSQLConnectionString(test.Host, test.User, test.Passwd, test.Name, test.Param, test.SSLMode)
|
|
||||||
assert.Equal(t, test.Output, connStr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDumpDatabase(t *testing.T) {
|
func TestDumpDatabase(t *testing.T) {
|
||||||
assert.NoError(t, PrepareTestDatabase())
|
assert.NoError(t, PrepareTestDatabase())
|
||||||
|
|
||||||
dir, err := ioutil.TempDir(os.TempDir(), "dump")
|
dir, err := ioutil.TempDir(os.TempDir(), "dump")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
for _, dbType := range supportedDatabases {
|
for _, dbName := range setting.SupportedDatabases {
|
||||||
|
dbType := setting.GetDBTypeByName(dbName)
|
||||||
assert.NoError(t, DumpDatabase(filepath.Join(dir, dbType+".sql"), dbType))
|
assert.NoError(t, DumpDatabase(filepath.Join(dir, dbType+".sql"), dbType))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2201,7 +2201,7 @@ func GitFsck() {
|
||||||
log.Trace("Doing: GitFsck")
|
log.Trace("Doing: GitFsck")
|
||||||
|
|
||||||
if err := x.
|
if err := x.
|
||||||
Where("id>0 AND is_fsck_enabled=?", true).BufferSize(setting.IterateBufferSize).
|
Where("id>0 AND is_fsck_enabled=?", true).BufferSize(setting.Database.IterateBufferSize).
|
||||||
Iterate(new(Repository),
|
Iterate(new(Repository),
|
||||||
func(idx int, bean interface{}) error {
|
func(idx int, bean interface{}) error {
|
||||||
repo := bean.(*Repository)
|
repo := bean.(*Repository)
|
||||||
|
@ -2225,7 +2225,7 @@ func GitFsck() {
|
||||||
func GitGcRepos() error {
|
func GitGcRepos() error {
|
||||||
args := append([]string{"gc"}, setting.Git.GCArgs...)
|
args := append([]string{"gc"}, setting.Git.GCArgs...)
|
||||||
return x.
|
return x.
|
||||||
Where("id > 0").BufferSize(setting.IterateBufferSize).
|
Where("id > 0").BufferSize(setting.Database.IterateBufferSize).
|
||||||
Iterate(new(Repository),
|
Iterate(new(Repository),
|
||||||
func(idx int, bean interface{}) error {
|
func(idx int, bean interface{}) error {
|
||||||
repo := bean.(*Repository)
|
repo := bean.(*Repository)
|
||||||
|
@ -2568,7 +2568,7 @@ func (repo *Repository) generateRandomAvatar(e Engine) error {
|
||||||
// RemoveRandomAvatars removes the randomly generated avatars that were created for repositories
|
// RemoveRandomAvatars removes the randomly generated avatars that were created for repositories
|
||||||
func RemoveRandomAvatars() error {
|
func RemoveRandomAvatars() error {
|
||||||
return x.
|
return x.
|
||||||
Where("id > 0").BufferSize(setting.IterateBufferSize).
|
Where("id > 0").BufferSize(setting.Database.IterateBufferSize).
|
||||||
Iterate(new(Repository),
|
Iterate(new(Repository),
|
||||||
func(idx int, bean interface{}) error {
|
func(idx int, bean interface{}) error {
|
||||||
repository := bean.(*Repository)
|
repository := bean.(*Repository)
|
||||||
|
|
|
@ -49,7 +49,7 @@ func MainTest(m *testing.M, pathToGiteaRoot string) {
|
||||||
setting.RunUser = "runuser"
|
setting.RunUser = "runuser"
|
||||||
setting.SSH.Port = 3000
|
setting.SSH.Port = 3000
|
||||||
setting.SSH.Domain = "try.gitea.io"
|
setting.SSH.Domain = "try.gitea.io"
|
||||||
setting.UseSQLite3 = true
|
setting.Database.UseSQLite3 = true
|
||||||
setting.RepoRootPath, err = ioutil.TempDir(os.TempDir(), "repos")
|
setting.RepoRootPath, err = ioutil.TempDir(os.TempDir(), "repos")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalTestError("TempDir: %v\n", err)
|
fatalTestError("TempDir: %v\n", err)
|
||||||
|
|
|
@ -40,7 +40,6 @@ import (
|
||||||
"golang.org/x/crypto/scrypt"
|
"golang.org/x/crypto/scrypt"
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
"xorm.io/core"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// UserType defines the user type
|
// UserType defines the user type
|
||||||
|
@ -1432,9 +1431,9 @@ func (opts *SearchUserOptions) toConds() builder.Cond {
|
||||||
|
|
||||||
if opts.OwnerID > 0 {
|
if opts.OwnerID > 0 {
|
||||||
var exprCond builder.Cond
|
var exprCond builder.Cond
|
||||||
if DbCfg.Type == core.MYSQL {
|
if setting.Database.UseMySQL {
|
||||||
exprCond = builder.Expr("org_user.org_id = user.id")
|
exprCond = builder.Expr("org_user.org_id = user.id")
|
||||||
} else if DbCfg.Type == core.MSSQL {
|
} else if setting.Database.UseMSSQL {
|
||||||
exprCond = builder.Expr("org_user.org_id = [user].id")
|
exprCond = builder.Expr("org_user.org_id = [user].id")
|
||||||
} else {
|
} else {
|
||||||
exprCond = builder.Expr("org_user.org_id = \"user\".id")
|
exprCond = builder.Expr("org_user.org_id = \"user\".id")
|
||||||
|
|
|
@ -21,13 +21,13 @@ func GetUserHeatmapDataByUser(user *User) ([]*UserHeatmapData, error) {
|
||||||
var groupBy string
|
var groupBy string
|
||||||
var groupByName = "timestamp" // We need this extra case because mssql doesn't allow grouping by alias
|
var groupByName = "timestamp" // We need this extra case because mssql doesn't allow grouping by alias
|
||||||
switch {
|
switch {
|
||||||
case setting.UseSQLite3:
|
case setting.Database.UseSQLite3:
|
||||||
groupBy = "strftime('%s', strftime('%Y-%m-%d', created_unix, 'unixepoch'))"
|
groupBy = "strftime('%s', strftime('%Y-%m-%d', created_unix, 'unixepoch'))"
|
||||||
case setting.UseMySQL:
|
case setting.Database.UseMySQL:
|
||||||
groupBy = "UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(created_unix)))"
|
groupBy = "UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(created_unix)))"
|
||||||
case setting.UsePostgreSQL:
|
case setting.Database.UsePostgreSQL:
|
||||||
groupBy = "extract(epoch from date_trunc('day', to_timestamp(created_unix)))"
|
groupBy = "extract(epoch from date_trunc('day', to_timestamp(created_unix)))"
|
||||||
case setting.UseMSSQL:
|
case setting.Database.UseMSSQL:
|
||||||
groupBy = "datediff(SECOND, '19700101', dateadd(DAY, 0, datediff(day, 0, dateadd(s, created_unix, '19700101'))))"
|
groupBy = "datediff(SECOND, '19700101', dateadd(DAY, 0, datediff(day, 0, dateadd(s, created_unix, '19700101'))))"
|
||||||
groupByName = groupBy
|
groupByName = groupBy
|
||||||
}
|
}
|
||||||
|
|
171
modules/setting/database.go
Normal file
171
modules/setting/database.go
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package setting
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// SupportedDatabases includes all supported databases type
|
||||||
|
SupportedDatabases = []string{"MySQL", "PostgreSQL", "MSSQL"}
|
||||||
|
dbTypes = map[string]string{"MySQL": "mysql", "PostgreSQL": "postgres", "MSSQL": "mssql", "SQLite3": "sqlite3"}
|
||||||
|
|
||||||
|
// EnableSQLite3 use SQLite3, set by build flag
|
||||||
|
EnableSQLite3 bool
|
||||||
|
|
||||||
|
// Database holds the database settings
|
||||||
|
Database = struct {
|
||||||
|
Type string
|
||||||
|
Host string
|
||||||
|
Name string
|
||||||
|
User string
|
||||||
|
Passwd string
|
||||||
|
SSLMode string
|
||||||
|
Path string
|
||||||
|
LogSQL bool
|
||||||
|
Charset string
|
||||||
|
Timeout int // seconds
|
||||||
|
UseSQLite3 bool
|
||||||
|
UseMySQL bool
|
||||||
|
UseMSSQL bool
|
||||||
|
UsePostgreSQL bool
|
||||||
|
DBConnectRetries int
|
||||||
|
DBConnectBackoff time.Duration
|
||||||
|
MaxIdleConns int
|
||||||
|
ConnMaxLifetime time.Duration
|
||||||
|
IterateBufferSize int
|
||||||
|
}{
|
||||||
|
Timeout: 500,
|
||||||
|
MaxIdleConns: 0,
|
||||||
|
ConnMaxLifetime: 3 * time.Second,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetDBTypeByName returns the dataase type as it defined on XORM according the given name
|
||||||
|
func GetDBTypeByName(name string) string {
|
||||||
|
return dbTypes[name]
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitDBConfig loads the database settings
|
||||||
|
func InitDBConfig() {
|
||||||
|
sec := Cfg.Section("database")
|
||||||
|
Database.Type = sec.Key("DB_TYPE").String()
|
||||||
|
switch Database.Type {
|
||||||
|
case "sqlite3":
|
||||||
|
Database.UseSQLite3 = true
|
||||||
|
case "mysql":
|
||||||
|
Database.UseMySQL = true
|
||||||
|
case "postgres":
|
||||||
|
Database.UsePostgreSQL = true
|
||||||
|
case "mssql":
|
||||||
|
Database.UseMSSQL = true
|
||||||
|
}
|
||||||
|
Database.Host = sec.Key("HOST").String()
|
||||||
|
Database.Name = sec.Key("NAME").String()
|
||||||
|
Database.User = sec.Key("USER").String()
|
||||||
|
if len(Database.Passwd) == 0 {
|
||||||
|
Database.Passwd = sec.Key("PASSWD").String()
|
||||||
|
}
|
||||||
|
Database.SSLMode = sec.Key("SSL_MODE").MustString("disable")
|
||||||
|
Database.Charset = sec.Key("CHARSET").In("utf8", []string{"utf8", "utf8mb4"})
|
||||||
|
Database.Path = sec.Key("PATH").MustString(filepath.Join(AppDataPath, "gitea.db"))
|
||||||
|
Database.Timeout = sec.Key("SQLITE_TIMEOUT").MustInt(500)
|
||||||
|
Database.MaxIdleConns = sec.Key("MAX_IDLE_CONNS").MustInt(0)
|
||||||
|
Database.ConnMaxLifetime = sec.Key("CONN_MAX_LIFE_TIME").MustDuration(3 * time.Second)
|
||||||
|
|
||||||
|
Database.IterateBufferSize = sec.Key("ITERATE_BUFFER_SIZE").MustInt(50)
|
||||||
|
Database.LogSQL = sec.Key("LOG_SQL").MustBool(true)
|
||||||
|
Database.DBConnectRetries = sec.Key("DB_RETRIES").MustInt(10)
|
||||||
|
Database.DBConnectBackoff = sec.Key("DB_RETRY_BACKOFF").MustDuration(3 * time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DBConnStr returns database connection string
|
||||||
|
func DBConnStr() (string, error) {
|
||||||
|
connStr := ""
|
||||||
|
var Param = "?"
|
||||||
|
if strings.Contains(Database.Name, Param) {
|
||||||
|
Param = "&"
|
||||||
|
}
|
||||||
|
switch Database.Type {
|
||||||
|
case "mysql":
|
||||||
|
connType := "tcp"
|
||||||
|
if Database.Host[0] == '/' { // looks like a unix socket
|
||||||
|
connType = "unix"
|
||||||
|
}
|
||||||
|
tls := Database.SSLMode
|
||||||
|
if tls == "disable" { // allow (Postgres-inspired) default value to work in MySQL
|
||||||
|
tls = "false"
|
||||||
|
}
|
||||||
|
connStr = fmt.Sprintf("%s:%s@%s(%s)/%s%scharset=%s&parseTime=true&tls=%s",
|
||||||
|
Database.User, Database.Passwd, connType, Database.Host, Database.Name, Param, Database.Charset, tls)
|
||||||
|
case "postgres":
|
||||||
|
connStr = getPostgreSQLConnectionString(Database.Host, Database.User, Database.Passwd, Database.Name, Param, Database.SSLMode)
|
||||||
|
case "mssql":
|
||||||
|
host, port := ParseMSSQLHostPort(Database.Host)
|
||||||
|
connStr = fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", host, port, Database.Name, Database.User, Database.Passwd)
|
||||||
|
case "sqlite3":
|
||||||
|
if !EnableSQLite3 {
|
||||||
|
return "", errors.New("this binary version does not build support for SQLite3")
|
||||||
|
}
|
||||||
|
if err := os.MkdirAll(path.Dir(Database.Path), os.ModePerm); err != nil {
|
||||||
|
return "", fmt.Errorf("Failed to create directories: %v", err)
|
||||||
|
}
|
||||||
|
connStr = fmt.Sprintf("file:%s?cache=shared&mode=rwc&_busy_timeout=%d", Database.Path, Database.Timeout)
|
||||||
|
default:
|
||||||
|
return "", fmt.Errorf("Unknown database type: %s", Database.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
return connStr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parsePostgreSQLHostPort parses given input in various forms defined in
|
||||||
|
// https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING
|
||||||
|
// and returns proper host and port number.
|
||||||
|
func parsePostgreSQLHostPort(info string) (string, string) {
|
||||||
|
host, port := "127.0.0.1", "5432"
|
||||||
|
if strings.Contains(info, ":") && !strings.HasSuffix(info, "]") {
|
||||||
|
idx := strings.LastIndex(info, ":")
|
||||||
|
host = info[:idx]
|
||||||
|
port = info[idx+1:]
|
||||||
|
} else if len(info) > 0 {
|
||||||
|
host = info
|
||||||
|
}
|
||||||
|
return host, port
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPostgreSQLConnectionString(dbHost, dbUser, dbPasswd, dbName, dbParam, dbsslMode string) (connStr string) {
|
||||||
|
host, port := parsePostgreSQLHostPort(dbHost)
|
||||||
|
if host[0] == '/' { // looks like a unix socket
|
||||||
|
connStr = fmt.Sprintf("postgres://%s:%s@:%s/%s%ssslmode=%s&host=%s",
|
||||||
|
url.PathEscape(dbUser), url.PathEscape(dbPasswd), port, dbName, dbParam, dbsslMode, host)
|
||||||
|
} else {
|
||||||
|
connStr = fmt.Sprintf("postgres://%s:%s@%s:%s/%s%ssslmode=%s",
|
||||||
|
url.PathEscape(dbUser), url.PathEscape(dbPasswd), host, port, dbName, dbParam, dbsslMode)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseMSSQLHostPort splits the host into host and port
|
||||||
|
func ParseMSSQLHostPort(info string) (string, string) {
|
||||||
|
host, port := "127.0.0.1", "1433"
|
||||||
|
if strings.Contains(info, ":") {
|
||||||
|
host = strings.Split(info, ":")[0]
|
||||||
|
port = strings.Split(info, ":")[1]
|
||||||
|
} else if strings.Contains(info, ",") {
|
||||||
|
host = strings.Split(info, ",")[0]
|
||||||
|
port = strings.TrimSpace(strings.Split(info, ",")[1])
|
||||||
|
} else if len(info) > 0 {
|
||||||
|
host = info
|
||||||
|
}
|
||||||
|
return host, port
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package models
|
package setting
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
@ -12,5 +12,5 @@ import (
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
EnableSQLite3 = true
|
EnableSQLite3 = true
|
||||||
supportedDatabases = append(supportedDatabases, "sqlite3")
|
SupportedDatabases = append(SupportedDatabases, "SQLite3")
|
||||||
}
|
}
|
94
modules/setting/database_test.go
Normal file
94
modules/setting/database_test.go
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package setting
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_parsePostgreSQLHostPort(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
HostPort string
|
||||||
|
Host string
|
||||||
|
Port string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
HostPort: "127.0.0.1:1234",
|
||||||
|
Host: "127.0.0.1",
|
||||||
|
Port: "1234",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
HostPort: "127.0.0.1",
|
||||||
|
Host: "127.0.0.1",
|
||||||
|
Port: "5432",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
HostPort: "[::1]:1234",
|
||||||
|
Host: "[::1]",
|
||||||
|
Port: "1234",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
HostPort: "[::1]",
|
||||||
|
Host: "[::1]",
|
||||||
|
Port: "5432",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
HostPort: "/tmp/pg.sock:1234",
|
||||||
|
Host: "/tmp/pg.sock",
|
||||||
|
Port: "1234",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
HostPort: "/tmp/pg.sock",
|
||||||
|
Host: "/tmp/pg.sock",
|
||||||
|
Port: "5432",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
host, port := parsePostgreSQLHostPort(test.HostPort)
|
||||||
|
assert.Equal(t, test.Host, host)
|
||||||
|
assert.Equal(t, test.Port, port)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_getPostgreSQLConnectionString(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
Host string
|
||||||
|
Port string
|
||||||
|
User string
|
||||||
|
Passwd string
|
||||||
|
Name string
|
||||||
|
Param string
|
||||||
|
SSLMode string
|
||||||
|
Output string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Host: "/tmp/pg.sock",
|
||||||
|
Port: "4321",
|
||||||
|
User: "testuser",
|
||||||
|
Passwd: "space space !#$%^^%^```-=?=",
|
||||||
|
Name: "gitea",
|
||||||
|
Param: "",
|
||||||
|
SSLMode: "false",
|
||||||
|
Output: "postgres://testuser:space%20space%20%21%23$%25%5E%5E%25%5E%60%60%60-=%3F=@:5432/giteasslmode=false&host=/tmp/pg.sock",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Host: "localhost",
|
||||||
|
Port: "1234",
|
||||||
|
User: "pgsqlusername",
|
||||||
|
Passwd: "I love Gitea!",
|
||||||
|
Name: "gitea",
|
||||||
|
Param: "",
|
||||||
|
SSLMode: "true",
|
||||||
|
Output: "postgres://pgsqlusername:I%20love%20Gitea%21@localhost:5432/giteasslmode=true",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
connStr := getPostgreSQLConnectionString(test.Host, test.User, test.Passwd, test.Name, test.Param, test.SSLMode)
|
||||||
|
assert.Equal(t, test.Output, connStr)
|
||||||
|
}
|
||||||
|
}
|
|
@ -148,16 +148,6 @@ var (
|
||||||
DisableGitHooks bool
|
DisableGitHooks bool
|
||||||
PasswordHashAlgo string
|
PasswordHashAlgo string
|
||||||
|
|
||||||
// Database settings
|
|
||||||
UseSQLite3 bool
|
|
||||||
UseMySQL bool
|
|
||||||
UseMSSQL bool
|
|
||||||
UsePostgreSQL bool
|
|
||||||
UseTiDB bool
|
|
||||||
LogSQL bool
|
|
||||||
DBConnectRetries int
|
|
||||||
DBConnectBackoff time.Duration
|
|
||||||
|
|
||||||
// UI settings
|
// UI settings
|
||||||
UI = struct {
|
UI = struct {
|
||||||
ExplorePagingNum int
|
ExplorePagingNum int
|
||||||
|
@ -357,7 +347,10 @@ var (
|
||||||
IsWindows bool
|
IsWindows bool
|
||||||
HasRobotsTxt bool
|
HasRobotsTxt bool
|
||||||
InternalToken string // internal access token
|
InternalToken string // internal access token
|
||||||
IterateBufferSize int
|
|
||||||
|
// UILocation is the location on the UI, so that we can display the time on UI.
|
||||||
|
// Currently only show the default time.Local, it could be added to app.ini after UI is ready
|
||||||
|
UILocation = time.Local
|
||||||
)
|
)
|
||||||
|
|
||||||
// DateLang transforms standard language locale name to corresponding value in datetime plugin.
|
// DateLang transforms standard language locale name to corresponding value in datetime plugin.
|
||||||
|
@ -775,10 +768,6 @@ func NewContext() {
|
||||||
CSRFCookieHTTPOnly = sec.Key("CSRF_COOKIE_HTTP_ONLY").MustBool(true)
|
CSRFCookieHTTPOnly = sec.Key("CSRF_COOKIE_HTTP_ONLY").MustBool(true)
|
||||||
|
|
||||||
InternalToken = loadInternalToken(sec)
|
InternalToken = loadInternalToken(sec)
|
||||||
IterateBufferSize = Cfg.Section("database").Key("ITERATE_BUFFER_SIZE").MustInt(50)
|
|
||||||
LogSQL = Cfg.Section("database").Key("LOG_SQL").MustBool(true)
|
|
||||||
DBConnectRetries = Cfg.Section("database").Key("DB_RETRIES").MustInt(10)
|
|
||||||
DBConnectBackoff = Cfg.Section("database").Key("DB_RETRY_BACKOFF").MustDuration(3 * time.Second)
|
|
||||||
|
|
||||||
sec = Cfg.Section("attachment")
|
sec = Cfg.Section("attachment")
|
||||||
AttachmentPath = sec.Key("PATH").MustString(path.Join(AppDataPath, "attachments"))
|
AttachmentPath = sec.Key("PATH").MustString(path.Join(AppDataPath, "attachments"))
|
||||||
|
@ -1037,6 +1026,7 @@ func loadOrGenerateInternalToken(sec *ini.Section) string {
|
||||||
|
|
||||||
// NewServices initializes the services
|
// NewServices initializes the services
|
||||||
func NewServices() {
|
func NewServices() {
|
||||||
|
InitDBConfig()
|
||||||
newService()
|
newService()
|
||||||
NewLogServices(false)
|
NewLogServices(false)
|
||||||
newCacheService()
|
newCacheService()
|
||||||
|
|
|
@ -289,7 +289,7 @@ func Config(ctx *context.Context) {
|
||||||
ctx.Data["LFS"] = setting.LFS
|
ctx.Data["LFS"] = setting.LFS
|
||||||
|
|
||||||
ctx.Data["Service"] = setting.Service
|
ctx.Data["Service"] = setting.Service
|
||||||
ctx.Data["DbCfg"] = models.DbCfg
|
ctx.Data["DbCfg"] = setting.Database
|
||||||
ctx.Data["Webhook"] = setting.Webhook
|
ctx.Data["Webhook"] = setting.Webhook
|
||||||
|
|
||||||
ctx.Data["MailerEnabled"] = false
|
ctx.Data["MailerEnabled"] = false
|
||||||
|
@ -333,7 +333,7 @@ func Config(ctx *context.Context) {
|
||||||
ctx.Data["AccessLogTemplate"] = setting.AccessLogTemplate
|
ctx.Data["AccessLogTemplate"] = setting.AccessLogTemplate
|
||||||
ctx.Data["DisableRouterLog"] = setting.DisableRouterLog
|
ctx.Data["DisableRouterLog"] = setting.DisableRouterLog
|
||||||
ctx.Data["EnableXORMLog"] = setting.EnableXORMLog
|
ctx.Data["EnableXORMLog"] = setting.EnableXORMLog
|
||||||
ctx.Data["LogSQL"] = setting.LogSQL
|
ctx.Data["LogSQL"] = setting.Database.LogSQL
|
||||||
|
|
||||||
ctx.HTML(200, tplConfig)
|
ctx.HTML(200, tplConfig)
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,16 +47,16 @@ func NewServices() {
|
||||||
// In case of problems connecting to DB, retry connection. Eg, PGSQL in Docker Container on Synology
|
// In case of problems connecting to DB, retry connection. Eg, PGSQL in Docker Container on Synology
|
||||||
func initDBEngine() (err error) {
|
func initDBEngine() (err error) {
|
||||||
log.Info("Beginning ORM engine initialization.")
|
log.Info("Beginning ORM engine initialization.")
|
||||||
for i := 0; i < setting.DBConnectRetries; i++ {
|
for i := 0; i < setting.Database.DBConnectRetries; i++ {
|
||||||
log.Info("ORM engine initialization attempt #%d/%d...", i+1, setting.DBConnectRetries)
|
log.Info("ORM engine initialization attempt #%d/%d...", i+1, setting.Database.DBConnectRetries)
|
||||||
if err = models.NewEngine(migrations.Migrate); err == nil {
|
if err = models.NewEngine(migrations.Migrate); err == nil {
|
||||||
break
|
break
|
||||||
} else if i == setting.DBConnectRetries-1 {
|
} else if i == setting.Database.DBConnectRetries-1 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.Error("ORM engine initialization attempt #%d/%d failed. Error: %v", i+1, setting.DBConnectRetries, err)
|
log.Error("ORM engine initialization attempt #%d/%d failed. Error: %v", i+1, setting.Database.DBConnectRetries, err)
|
||||||
log.Info("Backing off for %d seconds", int64(setting.DBConnectBackoff/time.Second))
|
log.Info("Backing off for %d seconds", int64(setting.Database.DBConnectBackoff/time.Second))
|
||||||
time.Sleep(setting.DBConnectBackoff)
|
time.Sleep(setting.Database.DBConnectBackoff)
|
||||||
}
|
}
|
||||||
models.HasEngine = true
|
models.HasEngine = true
|
||||||
return nil
|
return nil
|
||||||
|
@ -73,7 +73,7 @@ func GlobalInit() {
|
||||||
log.Trace("AppWorkPath: %s", setting.AppWorkPath)
|
log.Trace("AppWorkPath: %s", setting.AppWorkPath)
|
||||||
log.Trace("Custom path: %s", setting.CustomPath)
|
log.Trace("Custom path: %s", setting.CustomPath)
|
||||||
log.Trace("Log path: %s", setting.LogRootPath)
|
log.Trace("Log path: %s", setting.LogRootPath)
|
||||||
models.LoadConfigs()
|
|
||||||
NewServices()
|
NewServices()
|
||||||
|
|
||||||
if setting.InstallLock {
|
if setting.InstallLock {
|
||||||
|
@ -102,12 +102,9 @@ func GlobalInit() {
|
||||||
models.InitDeliverHooks()
|
models.InitDeliverHooks()
|
||||||
models.InitTestPullRequests()
|
models.InitTestPullRequests()
|
||||||
}
|
}
|
||||||
if models.EnableSQLite3 {
|
if setting.EnableSQLite3 {
|
||||||
log.Info("SQLite3 Supported")
|
log.Info("SQLite3 Supported")
|
||||||
}
|
}
|
||||||
if models.EnableTiDB {
|
|
||||||
log.Info("TiDB Supported")
|
|
||||||
}
|
|
||||||
checkRunMode()
|
checkRunMode()
|
||||||
|
|
||||||
if setting.InstallLock && setting.SSH.StartBuiltinServer {
|
if setting.InstallLock && setting.SSH.StartBuiltinServer {
|
||||||
|
|
|
@ -40,11 +40,7 @@ func InstallInit(ctx *context.Context) {
|
||||||
ctx.Data["Title"] = ctx.Tr("install.install")
|
ctx.Data["Title"] = ctx.Tr("install.install")
|
||||||
ctx.Data["PageIsInstall"] = true
|
ctx.Data["PageIsInstall"] = true
|
||||||
|
|
||||||
dbOpts := []string{"MySQL", "PostgreSQL", "MSSQL"}
|
ctx.Data["DbOptions"] = setting.SupportedDatabases
|
||||||
if models.EnableSQLite3 {
|
|
||||||
dbOpts = append(dbOpts, "SQLite3")
|
|
||||||
}
|
|
||||||
ctx.Data["DbOptions"] = dbOpts
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Install render installation page
|
// Install render installation page
|
||||||
|
@ -52,21 +48,21 @@ func Install(ctx *context.Context) {
|
||||||
form := auth.InstallForm{}
|
form := auth.InstallForm{}
|
||||||
|
|
||||||
// Database settings
|
// Database settings
|
||||||
form.DbHost = models.DbCfg.Host
|
form.DbHost = setting.Database.Host
|
||||||
form.DbUser = models.DbCfg.User
|
form.DbUser = setting.Database.User
|
||||||
form.DbPasswd = models.DbCfg.Passwd
|
form.DbPasswd = setting.Database.Passwd
|
||||||
form.DbName = models.DbCfg.Name
|
form.DbName = setting.Database.Name
|
||||||
form.DbPath = models.DbCfg.Path
|
form.DbPath = setting.Database.Path
|
||||||
form.Charset = models.DbCfg.Charset
|
form.Charset = setting.Database.Charset
|
||||||
|
|
||||||
ctx.Data["CurDbOption"] = "MySQL"
|
ctx.Data["CurDbOption"] = "MySQL"
|
||||||
switch models.DbCfg.Type {
|
switch setting.Database.Type {
|
||||||
case "postgres":
|
case "postgres":
|
||||||
ctx.Data["CurDbOption"] = "PostgreSQL"
|
ctx.Data["CurDbOption"] = "PostgreSQL"
|
||||||
case "mssql":
|
case "mssql":
|
||||||
ctx.Data["CurDbOption"] = "MSSQL"
|
ctx.Data["CurDbOption"] = "MSSQL"
|
||||||
case "sqlite3":
|
case "sqlite3":
|
||||||
if models.EnableSQLite3 {
|
if setting.EnableSQLite3 {
|
||||||
ctx.Data["CurDbOption"] = "SQLite3"
|
ctx.Data["CurDbOption"] = "SQLite3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,18 +140,18 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) {
|
||||||
|
|
||||||
// Pass basic check, now test configuration.
|
// Pass basic check, now test configuration.
|
||||||
// Test database setting.
|
// Test database setting.
|
||||||
dbTypes := map[string]string{"MySQL": "mysql", "PostgreSQL": "postgres", "MSSQL": "mssql", "SQLite3": "sqlite3"}
|
|
||||||
models.DbCfg.Type = dbTypes[form.DbType]
|
|
||||||
models.DbCfg.Host = form.DbHost
|
|
||||||
models.DbCfg.User = form.DbUser
|
|
||||||
models.DbCfg.Passwd = form.DbPasswd
|
|
||||||
models.DbCfg.Name = form.DbName
|
|
||||||
models.DbCfg.SSLMode = form.SSLMode
|
|
||||||
models.DbCfg.Charset = form.Charset
|
|
||||||
models.DbCfg.Path = form.DbPath
|
|
||||||
|
|
||||||
if (models.DbCfg.Type == "sqlite3") &&
|
setting.Database.Type = setting.GetDBTypeByName(form.DbType)
|
||||||
len(models.DbCfg.Path) == 0 {
|
setting.Database.Host = form.DbHost
|
||||||
|
setting.Database.User = form.DbUser
|
||||||
|
setting.Database.Passwd = form.DbPasswd
|
||||||
|
setting.Database.Name = form.DbName
|
||||||
|
setting.Database.SSLMode = form.SSLMode
|
||||||
|
setting.Database.Charset = form.Charset
|
||||||
|
setting.Database.Path = form.DbPath
|
||||||
|
|
||||||
|
if (setting.Database.Type == "sqlite3") &&
|
||||||
|
len(setting.Database.Path) == 0 {
|
||||||
ctx.Data["Err_DbPath"] = true
|
ctx.Data["Err_DbPath"] = true
|
||||||
ctx.RenderWithErr(ctx.Tr("install.err_empty_db_path"), tplInstall, &form)
|
ctx.RenderWithErr(ctx.Tr("install.err_empty_db_path"), tplInstall, &form)
|
||||||
return
|
return
|
||||||
|
@ -265,14 +261,14 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) {
|
||||||
log.Error("Failed to load custom conf '%s': %v", setting.CustomConf, err)
|
log.Error("Failed to load custom conf '%s': %v", setting.CustomConf, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cfg.Section("database").Key("DB_TYPE").SetValue(models.DbCfg.Type)
|
cfg.Section("database").Key("DB_TYPE").SetValue(setting.Database.Type)
|
||||||
cfg.Section("database").Key("HOST").SetValue(models.DbCfg.Host)
|
cfg.Section("database").Key("HOST").SetValue(setting.Database.Host)
|
||||||
cfg.Section("database").Key("NAME").SetValue(models.DbCfg.Name)
|
cfg.Section("database").Key("NAME").SetValue(setting.Database.Name)
|
||||||
cfg.Section("database").Key("USER").SetValue(models.DbCfg.User)
|
cfg.Section("database").Key("USER").SetValue(setting.Database.User)
|
||||||
cfg.Section("database").Key("PASSWD").SetValue(models.DbCfg.Passwd)
|
cfg.Section("database").Key("PASSWD").SetValue(setting.Database.Passwd)
|
||||||
cfg.Section("database").Key("SSL_MODE").SetValue(models.DbCfg.SSLMode)
|
cfg.Section("database").Key("SSL_MODE").SetValue(setting.Database.SSLMode)
|
||||||
cfg.Section("database").Key("CHARSET").SetValue(models.DbCfg.Charset)
|
cfg.Section("database").Key("CHARSET").SetValue(setting.Database.Charset)
|
||||||
cfg.Section("database").Key("PATH").SetValue(models.DbCfg.Path)
|
cfg.Section("database").Key("PATH").SetValue(setting.Database.Path)
|
||||||
|
|
||||||
cfg.Section("").Key("APP_NAME").SetValue(form.AppName)
|
cfg.Section("").Key("APP_NAME").SetValue(form.AppName)
|
||||||
cfg.Section("repository").Key("ROOT").SetValue(form.RepoRootPath)
|
cfg.Section("repository").Key("ROOT").SetValue(form.RepoRootPath)
|
||||||
|
|
Reference in a new issue