diff --git a/Makefile b/Makefile index fe526bb9e45b..5df67948fa64 100644 --- a/Makefile +++ b/Makefile @@ -79,6 +79,7 @@ TEST_PGSQL_HOST ?= pgsql:5432 TEST_PGSQL_DBNAME ?= testgitea TEST_PGSQL_USERNAME ?= postgres TEST_PGSQL_PASSWORD ?= postgres +TEST_PGSQL_SCHEMA ?= gtestschema TEST_MSSQL_HOST ?= mssql:1433 TEST_MSSQL_DBNAME ?= gitea TEST_MSSQL_USERNAME ?= sa @@ -306,6 +307,7 @@ generate-ini-pgsql: -e 's|{{TEST_PGSQL_DBNAME}}|${TEST_PGSQL_DBNAME}|g' \ -e 's|{{TEST_PGSQL_USERNAME}}|${TEST_PGSQL_USERNAME}|g' \ -e 's|{{TEST_PGSQL_PASSWORD}}|${TEST_PGSQL_PASSWORD}|g' \ + -e 's|{{TEST_PGSQL_SCHEMA}}|${TEST_PGSQL_SCHEMA}|g' \ integrations/pgsql.ini.tmpl > integrations/pgsql.ini .PHONY: test-pgsql diff --git a/custom/conf/app.ini.sample b/custom/conf/app.ini.sample index 971a99e264f4..f0829f37b3d2 100644 --- a/custom/conf/app.ini.sample +++ b/custom/conf/app.ini.sample @@ -336,6 +336,10 @@ NAME = gitea USER = root ; Use PASSWD = `your password` for quoting if you use special characters in the password. PASSWD = +; For Postgres, schema to use if different from "public". The schema must exist beforehand, +; the user must have creation privileges on it, and the user search path must be set +; to the look into the schema first. e.g.:ALTER USER user SET SEARCH_PATH = schema_name,"$user",public; +SCHEMA = ; For Postgres, either "disable" (default), "require", or "verify-full" ; For MySQL, either "false" (default), "true", or "skip-verify" SSL_MODE = disable diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md index d63eaf8e46fb..1c03fce3d03f 100644 --- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md +++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md @@ -209,6 +209,9 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`. - `NAME`: **gitea**: Database name. - `USER`: **root**: Database username. - `PASSWD`: **\**: Database user password. Use \`your password\` for quoting if you use special characters in the password. +- `SCHEMA`: **\**: For PostgreSQL only, schema to use if different from "public". The schema must exist beforehand, + the user must have creation privileges on it, and the user search path must be set to the look into the schema first + (e.g. `ALTER USER user SET SEARCH_PATH = schema_name,"$user",public;`). - `SSL_MODE`: **disable**: For PostgreSQL and MySQL only. - `CHARSET`: **utf8**: For MySQL only, either "utf8" or "utf8mb4", default is "utf8". NOTICE: for "utf8mb4" you must use MySQL InnoDB > 5.6. Gitea is unable to check this. - `PATH`: **data/gitea.db**: For SQLite3 only, the database file path. diff --git a/go.mod b/go.mod index 171a47036ba8..943eb2a7924c 100644 --- a/go.mod +++ b/go.mod @@ -112,6 +112,6 @@ require ( mvdan.cc/xurls/v2 v2.1.0 strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251 xorm.io/builder v0.3.6 - xorm.io/core v0.7.2 - xorm.io/xorm v0.8.1 + xorm.io/core v0.7.3 + xorm.io/xorm v0.8.2-0.20200120024500-c37aff9b3a4a ) diff --git a/go.sum b/go.sum index 6363ce75b70c..6f9548acf459 100644 --- a/go.sum +++ b/go.sum @@ -760,7 +760,9 @@ xorm.io/builder v0.3.6 h1:ha28mQ2M+TFx96Hxo+iq6tQgnkC9IZkM6D8w9sKHHF8= xorm.io/builder v0.3.6/go.mod h1:LEFAPISnRzG+zxaxj2vPicRwz67BdhFreKg8yv8/TgU= xorm.io/core v0.7.2 h1:mEO22A2Z7a3fPaZMk6gKL/jMD80iiyNwRrX5HOv3XLw= xorm.io/core v0.7.2/go.mod h1:jJfd0UAEzZ4t87nbQYtVjmqpIODugN6PD2D9E+dJvdM= +xorm.io/core v0.7.3 h1:W8ws1PlrnkS1CZU1YWaYLMQcQilwAmQXU0BJDJon+H0= +xorm.io/core v0.7.3/go.mod h1:jJfd0UAEzZ4t87nbQYtVjmqpIODugN6PD2D9E+dJvdM= xorm.io/xorm v0.8.0 h1:iALxgJrX8O00f8Jk22GbZwPmxJNgssV5Mv4uc2HL9PM= xorm.io/xorm v0.8.0/go.mod h1:ZkJLEYLoVyg7amJK/5r779bHyzs2AU8f8VMiP6BM7uY= -xorm.io/xorm v0.8.1 h1:4f2KXuQxVdaX3RdI3Fw81NzMiSpZeyCZt8m3sEVeIkQ= -xorm.io/xorm v0.8.1/go.mod h1:ZkJLEYLoVyg7amJK/5r779bHyzs2AU8f8VMiP6BM7uY= +xorm.io/xorm v0.8.2-0.20200120024500-c37aff9b3a4a h1:hzGd080rlkZ5a7v6Tr3x8PJJnWPfKxGMMl92c8DNcww= +xorm.io/xorm v0.8.2-0.20200120024500-c37aff9b3a4a/go.mod h1:ZkJLEYLoVyg7amJK/5r779bHyzs2AU8f8VMiP6BM7uY= diff --git a/integrations/integration_test.go b/integrations/integration_test.go index bf363f3b4ddc..138d751859d5 100644 --- a/integrations/integration_test.go +++ b/integrations/integration_test.go @@ -153,18 +153,53 @@ func initIntegrationTest() { if err != nil { log.Fatalf("sql.Open: %v", err) } - rows, err := db.Query(fmt.Sprintf("SELECT 1 FROM pg_database WHERE datname = '%s'", setting.Database.Name)) + dbrows, err := db.Query(fmt.Sprintf("SELECT 1 FROM pg_database WHERE datname = '%s'", setting.Database.Name)) if err != nil { log.Fatalf("db.Query: %v", err) } - defer rows.Close() + defer dbrows.Close() - if rows.Next() { + if !dbrows.Next() { + if _, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s", setting.Database.Name)); err != nil { + log.Fatalf("db.Exec: CREATE DATABASE: %v", err) + } + } + // Check if we need to setup a specific schema + if len(setting.Database.Schema) == 0 { break } - if _, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s", setting.Database.Name)); err != nil { - log.Fatalf("db.Exec: %v", err) + db.Close() + + db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s", + setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name, setting.Database.SSLMode)) + // This is a different db object; requires a different Close() + defer db.Close() + if err != nil { + log.Fatalf("sql.Open: %v", err) } + schrows, err := db.Query(fmt.Sprintf("SELECT 1 FROM information_schema.schemata WHERE schema_name = '%s'", setting.Database.Schema)) + if err != nil { + log.Fatalf("db.Query: %v", err) + } + defer schrows.Close() + + if !schrows.Next() { + // Create and setup a DB schema + if _, err = db.Exec(fmt.Sprintf("CREATE SCHEMA %s", setting.Database.Schema)); err != nil { + log.Fatalf("db.Exec: CREATE SCHEMA: %v", err) + } + } + + // Make the user's default search path the created schema; this will affect new connections + if _, err = db.Exec(fmt.Sprintf(`ALTER USER "%s" SET search_path = %s`, setting.Database.User, setting.Database.Schema)); err != nil { + log.Fatalf("db.Exec: ALTER USER SET search_path: %v", err) + } + + // Make the current connection's search the created schema + if _, err = db.Exec(fmt.Sprintf(`SET search_path = %s`, setting.Database.Schema)); err != nil { + log.Fatalf("db.Exec: ALTER USER SET search_path: %v", err) + } + case setting.Database.UseMSSQL: 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;", diff --git a/integrations/migration-test/gitea-v1.5.3.postgres.sql.gz b/integrations/migration-test/gitea-v1.5.3.postgres.sql.gz index 2fcad82111cf..2380f8dd7fc8 100644 Binary files a/integrations/migration-test/gitea-v1.5.3.postgres.sql.gz and b/integrations/migration-test/gitea-v1.5.3.postgres.sql.gz differ diff --git a/integrations/migration-test/gitea-v1.6.4.postgres.sql.gz b/integrations/migration-test/gitea-v1.6.4.postgres.sql.gz index 8db9022d1c0f..bd66f6ba4f7b 100644 Binary files a/integrations/migration-test/gitea-v1.6.4.postgres.sql.gz and b/integrations/migration-test/gitea-v1.6.4.postgres.sql.gz differ diff --git a/integrations/migration-test/gitea-v1.7.0.postgres.sql.gz b/integrations/migration-test/gitea-v1.7.0.postgres.sql.gz index ed66d41b89d1..e4716c6b4394 100644 Binary files a/integrations/migration-test/gitea-v1.7.0.postgres.sql.gz and b/integrations/migration-test/gitea-v1.7.0.postgres.sql.gz differ diff --git a/integrations/migration-test/migration_test.go b/integrations/migration-test/migration_test.go index c274d482da14..6cdfbf7d7df9 100644 --- a/integrations/migration-test/migration_test.go +++ b/integrations/migration-test/migration_test.go @@ -168,6 +168,32 @@ func restoreOldDB(t *testing.T, version string) bool { assert.NoError(t, err) db.Close() + // Check if we need to setup a specific schema + if len(setting.Database.Schema) != 0 { + db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s", + setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name, setting.Database.SSLMode)) + if !assert.NoError(t, err) { + return false + } + schrows, err := db.Query(fmt.Sprintf("SELECT 1 FROM information_schema.schemata WHERE schema_name = '%s'", setting.Database.Schema)) + if !assert.NoError(t, err) || !assert.NotEmpty(t, schrows) { + return false + } + + if !schrows.Next() { + // Create and setup a DB schema + _, err = db.Exec(fmt.Sprintf("CREATE SCHEMA %s", setting.Database.Schema)) + assert.NoError(t, err) + } + schrows.Close() + + // Make the user's default search path the created schema; this will affect new connections + _, err = db.Exec(fmt.Sprintf(`ALTER USER "%s" SET search_path = %s`, setting.Database.User, setting.Database.Schema)) + assert.NoError(t, err) + + db.Close() + } + db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s", setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name, setting.Database.SSLMode)) assert.NoError(t, err) diff --git a/integrations/pgsql.ini.tmpl b/integrations/pgsql.ini.tmpl index 6265e0d98ec8..f337d98fb4b3 100644 --- a/integrations/pgsql.ini.tmpl +++ b/integrations/pgsql.ini.tmpl @@ -7,6 +7,7 @@ HOST = {{TEST_PGSQL_HOST}} NAME = {{TEST_PGSQL_DBNAME}} USER = {{TEST_PGSQL_USERNAME}} PASSWD = {{TEST_PGSQL_PASSWORD}} +SCHEMA = {{TEST_PGSQL_SCHEMA}} SSL_MODE = disable [indexer] diff --git a/models/models.go b/models/models.go index 9eb174e200d4..74680d847a49 100644 --- a/models/models.go +++ b/models/models.go @@ -128,7 +128,12 @@ func getEngine() (*xorm.Engine, error) { return nil, err } - return xorm.NewEngine(setting.Database.Type, connStr) + engine, err := xorm.NewEngine(setting.Database.Type, connStr) + if err != nil { + return nil, err + } + engine.SetSchema(setting.Database.Schema) + return engine, nil } // NewTestEngine sets a new test xorm.Engine diff --git a/modules/auth/user_form.go b/modules/auth/user_form.go index 8ceb961d241f..228e17dce592 100644 --- a/modules/auth/user_form.go +++ b/modules/auth/user_form.go @@ -25,6 +25,7 @@ type InstallForm struct { SSLMode string Charset string `binding:"Required;In(utf8,utf8mb4)"` DbPath string + DbSchema string AppName string `binding:"Required" locale:"install.app_name"` RepoRootPath string `binding:"Required"` diff --git a/modules/setting/database.go b/modules/setting/database.go index 8c49ba3c5a17..911ac90a05b3 100644 --- a/modules/setting/database.go +++ b/modules/setting/database.go @@ -30,6 +30,7 @@ var ( Name string User string Passwd string + Schema string SSLMode string Path string LogSQL bool @@ -75,6 +76,7 @@ func InitDBConfig() { if len(Database.Passwd) == 0 { Database.Passwd = sec.Key("PASSWD").String() } + Database.Schema = sec.Key("SCHEMA").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")) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 589506f7aa89..a7d8b97d3de5 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -102,6 +102,8 @@ user = Username password = Password db_name = Database Name db_helper = Note to MySQL users: please use the InnoDB storage engine and if you use "utf8mb4", your InnoDB version must be greater than 5.6 . +db_schema = Schema +db_schema_helper = Leave blank for database default ("public"). ssl_mode = SSL charset = Charset path = Path @@ -1953,6 +1955,7 @@ config.db_type = Type config.db_host = Host config.db_name = Name config.db_user = Username +config.db_schema = Schema config.db_ssl_mode = SSL config.db_path = Path diff --git a/routers/install.go b/routers/install.go index 7395aeee84b6..e18adfea150c 100644 --- a/routers/install.go +++ b/routers/install.go @@ -54,6 +54,7 @@ func Install(ctx *context.Context) { form.DbPasswd = setting.Database.Passwd form.DbName = setting.Database.Name form.DbPath = setting.Database.Path + form.DbSchema = setting.Database.Schema form.Charset = setting.Database.Charset ctx.Data["CurDbOption"] = "MySQL" @@ -147,6 +148,7 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) { setting.Database.User = form.DbUser setting.Database.Passwd = form.DbPasswd setting.Database.Name = form.DbName + setting.Database.Schema = form.DbSchema setting.Database.SSLMode = form.SSLMode setting.Database.Charset = form.Charset setting.Database.Path = form.DbPath @@ -267,6 +269,7 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) { cfg.Section("database").Key("NAME").SetValue(setting.Database.Name) cfg.Section("database").Key("USER").SetValue(setting.Database.User) cfg.Section("database").Key("PASSWD").SetValue(setting.Database.Passwd) + cfg.Section("database").Key("SCHEMA").SetValue(setting.Database.Schema) cfg.Section("database").Key("SSL_MODE").SetValue(setting.Database.SSLMode) cfg.Section("database").Key("CHARSET").SetValue(setting.Database.Charset) cfg.Section("database").Key("PATH").SetValue(setting.Database.Path) diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl index c2793ece9dc1..c6a23cd367e4 100644 --- a/templates/admin/config.tmpl +++ b/templates/admin/config.tmpl @@ -128,6 +128,8 @@
{{if .DbCfg.User}}{{.DbCfg.User}}{{else}}-{{end}}
{{end}} {{if eq .DbCfg.Type "postgres"}} +
{{.i18n.Tr "admin.config.db_schema"}}
+
{{if .DbCfg.Schema}}{{.DbCfg.Schema}}{{else}}-{{end}}
{{.i18n.Tr "admin.config.db_ssl_mode"}}
{{if .DbCfg.SSLMode}}{{.DbCfg.SSLMode}}{{else}}-{{end}}
{{end}} diff --git a/templates/install.tmpl b/templates/install.tmpl index f8d1ef04e4e2..7f7c754bbfde 100644 --- a/templates/install.tmpl +++ b/templates/install.tmpl @@ -62,6 +62,11 @@ +
+ + + {{.i18n.Tr "install.db_schema_helper"}} +
diff --git a/vendor/modules.txt b/vendor/modules.txt index 2f36278d7561..6b2546886fd9 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -613,7 +613,7 @@ mvdan.cc/xurls/v2 strk.kbt.io/projects/go/libravatar # xorm.io/builder v0.3.6 xorm.io/builder -# xorm.io/core v0.7.2 +# xorm.io/core v0.7.3 xorm.io/core -# xorm.io/xorm v0.8.1 +# xorm.io/xorm v0.8.2-0.20200120024500-c37aff9b3a4a xorm.io/xorm diff --git a/vendor/xorm.io/core/.drone.yml b/vendor/xorm.io/core/.drone.yml index 4cb2fb4ae60e..3c118d4c06cc 100644 --- a/vendor/xorm.io/core/.drone.yml +++ b/vendor/xorm.io/core/.drone.yml @@ -1,128 +1,8 @@ ---- -kind: pipeline -name: go1.10 - -platform: - os: linux - arch: amd64 - -clone: - disable: true - -workspace: - base: /go - path: src/xorm.io/core - -steps: -- name: git - pull: default - image: plugins/git:next - settings: - depth: 50 - tags: true - -- name: test - pull: default - image: golang:1.10 - commands: - - go get github.com/stretchr/testify/assert - - go get github.com/go-xorm/sqlfiddle - - go get github.com/go-sql-driver/mysql - - go get github.com/mattn/go-sqlite3 - - go vet - - "go test -v -race -coverprofile=coverage.txt -covermode=atomic -dbConn=\"root:@tcp(mysql:3306)/core_test?charset=utf8mb4\"" - when: - event: - - push - - tag - - pull_request - -services: -- name: mysql - pull: default - image: mysql:5.7 - environment: - MYSQL_ALLOW_EMPTY_PASSWORD: yes - MYSQL_DATABASE: core_test - when: - event: - - push - - tag - - pull_request - ---- -kind: pipeline -name: go1.11 - -platform: - os: linux - arch: amd64 - -clone: - disable: true - -workspace: - base: /go - path: src/xorm.io/core - -steps: -- name: git - pull: default - image: plugins/git:next - settings: - depth: 50 - tags: true - -- name: test - pull: default - image: golang:1.11 - commands: - - go vet - - "go test -v -race -coverprofile=coverage.txt -covermode=atomic -dbConn=\"root:@tcp(mysql:3306)/core_test?charset=utf8mb4\"" - environment: - GO111MODULE: "on" - GOPROXY: https://goproxy.cn - when: - event: - - push - - tag - - pull_request - -services: -- name: mysql - pull: default - image: mysql:5.7 - environment: - MYSQL_ALLOW_EMPTY_PASSWORD: yes - MYSQL_DATABASE: core_test - when: - event: - - push - - tag - - pull_request - --- kind: pipeline name: go1.12 -platform: - os: linux - arch: amd64 - -clone: - disable: true - -workspace: - base: /go - path: src/xorm.io/core - steps: -- name: git - pull: default - image: plugins/git:next - settings: - depth: 50 - tags: true - name: test pull: default diff --git a/vendor/xorm.io/core/README.md b/vendor/xorm.io/core/README.md index c2cedcae8cf7..54436b68937d 100644 --- a/vendor/xorm.io/core/README.md +++ b/vendor/xorm.io/core/README.md @@ -1,7 +1,7 @@ Core is a lightweight wrapper of sql.DB. [![Build Status](https://drone.gitea.com/api/badges/xorm/core/status.svg)](https://drone.gitea.com/xorm/core) -[![](http://gocover.io/_badge/xorm.io/core)](http://gocover.io/xorm.io/core) +[![Test Coverage](https://gocover.io/_badge/xorm.io/core)](https://gocover.io/xorm.io/core) [![Go Report Card](https://goreportcard.com/badge/code.gitea.io/gitea)](https://goreportcard.com/report/xorm.io/core) # Open diff --git a/vendor/xorm.io/core/column.go b/vendor/xorm.io/core/column.go index b5906a98748a..8f375db59477 100644 --- a/vendor/xorm.io/core/column.go +++ b/vendor/xorm.io/core/column.go @@ -37,7 +37,7 @@ type Column struct { IsDeleted bool IsCascade bool IsVersion bool - DefaultIsEmpty bool + DefaultIsEmpty bool // false means column has no default set, but not default value is empty EnumOptions map[string]int SetOptions map[string]int DisableTimeZone bool @@ -65,7 +65,7 @@ func NewColumn(name, fieldName string, sqlType SQLType, len1, len2 int, nullable IsDeleted: false, IsCascade: false, IsVersion: false, - DefaultIsEmpty: false, + DefaultIsEmpty: true, // default should be no default EnumOptions: make(map[string]int), Comment: "", } diff --git a/vendor/xorm.io/core/index.go b/vendor/xorm.io/core/index.go index 2915428f26e7..129b5439219b 100644 --- a/vendor/xorm.io/core/index.go +++ b/vendor/xorm.io/core/index.go @@ -26,8 +26,8 @@ type Index struct { func (index *Index) XName(tableName string) string { if !strings.HasPrefix(index.Name, "UQE_") && !strings.HasPrefix(index.Name, "IDX_") { - tableName = strings.Replace(tableName, `"`, "", -1) - tableName = strings.Replace(tableName, `.`, "_", -1) + tableParts := strings.Split(strings.Replace(tableName, `"`, "", -1), ".") + tableName = tableParts[len(tableParts)-1] if index.Type == UniqueType { return fmt.Sprintf("UQE_%v_%v", tableName, index.Name) } diff --git a/vendor/xorm.io/xorm/.drone.yml b/vendor/xorm.io/xorm/.drone.yml index b2198e380a00..e9dae78896d8 100644 --- a/vendor/xorm.io/xorm/.drone.yml +++ b/vendor/xorm.io/xorm/.drone.yml @@ -1,204 +1,14 @@ --- kind: pipeline -name: go1.10-test -workspace: - base: /go - path: src/gitea.com/xorm/xorm - +name: testing steps: -- name: build +- name: test-vet pull: default - image: golang:1.10 - commands: - - go get -t -d -v - - go build -v - when: - event: - - push - - pull_request - -- name: test-sqlite - pull: default - image: golang:1.10 - depends_on: - - build - commands: - - "go test -v -race -db=\"sqlite3\" -conn_str=\"./test.db\" -coverprofile=coverage1-1.txt -covermode=atomic" - - "go test -v -race -db=\"sqlite3\" -conn_str=\"./test.db\" -cache=true -coverprofile=coverage1-2.txt -covermode=atomic" - when: - event: - - push - - pull_request - -- name: test-mysql - pull: default - image: golang:1.10 - depends_on: - - build - commands: - - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test\" -coverprofile=coverage2-1.txt -covermode=atomic" - - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test\" -cache=true -coverprofile=coverage2-2.txt -covermode=atomic" - when: - event: - - push - - pull_request - -- name: test-mysql-utf8mb4 - pull: default - image: golang:1.10 - depends_on: - - test-mysql - commands: - - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test?charset=utf8mb4\" -coverprofile=coverage2.1-1.txt -covermode=atomic" - - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test?charset=utf8mb4\" -cache=true -coverprofile=coverage2.1-2.txt -covermode=atomic" - when: - event: - - push - - pull_request - -- name: test-mymysql - pull: default - image: golang:1.10 - depends_on: - - test-mysql-utf8mb4 - commands: - - "go test -v -race -db=\"mymysql\" -conn_str=\"tcp:mysql:3306*xorm_test/root/\" -coverprofile=coverage3-1.txt -covermode=atomic" - - "go test -v -race -db=\"mymysql\" -conn_str=\"tcp:mysql:3306*xorm_test/root/\" -cache=true -coverprofile=coverage3-2.txt -covermode=atomic" - when: - event: - - push - - pull_request - -- name: test-postgres - pull: default - image: golang:1.10 - depends_on: - - build - commands: - - "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -coverprofile=coverage4-1.txt -covermode=atomic" - - "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -cache=true -coverprofile=coverage4-2.txt -covermode=atomic" - when: - event: - - push - - pull_request - -- name: test-postgres-schema - pull: default - image: golang:1.10 - depends_on: - - build - commands: - - "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -schema=xorm -coverprofile=coverage5-1.txt -covermode=atomic" - - "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -schema=xorm -cache=true -coverprofile=coverage5-2.txt -covermode=atomic" - when: - event: - - push - - pull_request - -- name: test-mssql - pull: default - image: golang:1.10 - depends_on: - - build - commands: - - "go test -v -race -db=\"mssql\" -conn_str=\"server=mssql;user id=sa;password=yourStrong(!)Password;database=xorm_test\" -coverprofile=coverage6-1.txt -covermode=atomic" - - "go test -v -race -db=\"mssql\" -conn_str=\"server=mssql;user id=sa;password=yourStrong(!)Password;database=xorm_test\" -cache=true -coverprofile=coverage6-2.txt -covermode=atomic" - when: - event: - - push - - pull_request - -- name: test-tidb - pull: default - image: golang:1.10 - depends_on: - - build - commands: - - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(tidb:4000)/xorm_test\" -ignore_select_update=true -coverprofile=coverage7-1.txt -covermode=atomic" - - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(tidb:4000)/xorm_test\" -ignore_select_update=true -cache=true -coverprofile=coverage7-2.txt -covermode=atomic" - when: - event: - - push - - pull_request - -- name: test-end - pull: default - image: golang:1.10 - depends_on: - - test-sqlite - - test-mysql - - test-mysql-utf8mb4 - - test-mymysql - - test-postgres - - test-postgres-schema - - test-mssql - - test-tidb - commands: - - echo "go1.10 build end" - when: - event: - - push - - pull_request - -services: -- name: mysql - pull: default - image: mysql:5.7 - environment: - MYSQL_ALLOW_EMPTY_PASSWORD: yes - MYSQL_DATABASE: xorm_test - when: - event: - - push - - tag - - pull_request - -- name: pgsql - pull: default - image: postgres:9.5 - environment: - POSTGRES_DB: xorm_test - POSTGRES_USER: postgres - when: - event: - - push - - tag - - pull_request - -- name: mssql - pull: default - image: microsoft/mssql-server-linux:latest - environment: - ACCEPT_EULA: Y - SA_PASSWORD: yourStrong(!)Password - MSSQL_PID: Developer - when: - event: - - push - - tag - - pull_request - -- name: tidb - pull: default - image: pingcap/tidb:v3.0.3 - when: - event: - - push - - tag - - pull_request - ---- -kind: pipeline -name: go1.13-test -steps: -- name: build - pull: default - image: golang:1.13 + image: golang:1.12 environment: GO111MODULE: "on" GOPROXY: "https://goproxy.cn" commands: - - go build -v - go vet when: event: @@ -207,7 +17,7 @@ steps: - name: test-sqlite pull: default - image: golang:1.13 + image: golang:1.12 environment: GO111MODULE: "on" GOPROXY: "https://goproxy.cn" @@ -221,7 +31,7 @@ steps: - name: test-mysql pull: default - image: golang:1.13 + image: golang:1.12 environment: GO111MODULE: "on" GOPROXY: "https://goproxy.cn" @@ -235,7 +45,7 @@ steps: - name: test-mysql-utf8mb4 pull: default - image: golang:1.13 + image: golang:1.12 depends_on: - test-mysql environment: @@ -251,7 +61,7 @@ steps: - name: test-mymysql pull: default - image: golang:1.13 + image: golang:1.12 depends_on: - test-mysql-utf8mb4 environment: @@ -267,7 +77,7 @@ steps: - name: test-postgres pull: default - image: golang:1.13 + image: golang:1.12 environment: GO111MODULE: "on" GOPROXY: "https://goproxy.cn" @@ -281,7 +91,7 @@ steps: - name: test-postgres-schema pull: default - image: golang:1.13 + image: golang:1.12 environment: GO111MODULE: "on" GOPROXY: "https://goproxy.cn" @@ -295,7 +105,7 @@ steps: - name: test-mssql pull: default - image: golang:1.13 + image: golang:1.12 environment: GO111MODULE: "on" GOPROXY: "https://goproxy.cn" @@ -309,7 +119,7 @@ steps: - name: test-tidb pull: default - image: golang:1.13 + image: golang:1.12 environment: GO111MODULE: "on" GOPROXY: "https://goproxy.cn" @@ -323,12 +133,12 @@ steps: - name: merge_coverage pull: default - image: golang:1.13 + image: golang:1.12 environment: GO111MODULE: "on" GOPROXY: "https://goproxy.cn" depends_on: - - build + - test-vet - test-sqlite - test-mysql - test-mysql-utf8mb4 diff --git a/vendor/xorm.io/xorm/dialect_postgres.go b/vendor/xorm.io/xorm/dialect_postgres.go index ccef3086b264..ac6d4fe8960e 100644 --- a/vendor/xorm.io/xorm/dialect_postgres.go +++ b/vendor/xorm.io/xorm/dialect_postgres.go @@ -901,7 +901,7 @@ func (db *postgres) TableCheckSql(tableName string) (string, []interface{}) { } func (db *postgres) ModifyColumnSql(tableName string, col *core.Column) string { - if len(db.Schema) == 0 { + if len(db.Schema) == 0 || strings.Contains(tableName, ".") { return fmt.Sprintf("alter table %s ALTER COLUMN %s TYPE %s", tableName, col.Name, db.SqlType(col)) } @@ -913,8 +913,8 @@ func (db *postgres) DropIndexSql(tableName string, index *core.Index) string { quote := db.Quote idxName := index.Name - tableName = strings.Replace(tableName, `"`, "", -1) - tableName = strings.Replace(tableName, `.`, "_", -1) + tableParts := strings.Split(strings.Replace(tableName, `"`, "", -1), ".") + tableName = tableParts[len(tableParts)-1] if !strings.HasPrefix(idxName, "UQE_") && !strings.HasPrefix(idxName, "IDX_") { diff --git a/vendor/xorm.io/xorm/session_insert.go b/vendor/xorm.io/xorm/session_insert.go index 1e19ce7a4eda..5f8f7e1ee887 100644 --- a/vendor/xorm.io/xorm/session_insert.go +++ b/vendor/xorm.io/xorm/session_insert.go @@ -729,66 +729,7 @@ func (session *Session) insertMapInterface(m map[string]interface{}) (int64, err args = append(args, m[colName]) } - w := builder.NewWriter() - if session.statement.cond.IsValid() { - if _, err := w.WriteString(fmt.Sprintf("INSERT INTO %s (", session.engine.Quote(tableName))); err != nil { - return 0, err - } - - if err := writeStrings(w, append(columns, exprs.colNames...), "`", "`"); err != nil { - return 0, err - } - - if _, err := w.WriteString(") SELECT "); err != nil { - return 0, err - } - - if err := session.statement.writeArgs(w, args); err != nil { - return 0, err - } - - if len(exprs.args) > 0 { - if _, err := w.WriteString(","); err != nil { - return 0, err - } - if err := exprs.writeArgs(w); err != nil { - return 0, err - } - } - - if _, err := w.WriteString(fmt.Sprintf(" FROM %s WHERE ", session.engine.Quote(tableName))); err != nil { - return 0, err - } - - if err := session.statement.cond.WriteTo(w); err != nil { - return 0, err - } - } else { - qm := strings.Repeat("?,", len(columns)) - qm = qm[:len(qm)-1] - - if _, err := w.WriteString(fmt.Sprintf("INSERT INTO %s (`%s`) VALUES (%s)", session.engine.Quote(tableName), strings.Join(columns, "`,`"), qm)); err != nil { - return 0, err - } - w.Append(args...) - } - - sql := w.String() - args = w.Args() - - if err := session.cacheInsert(tableName); err != nil { - return 0, err - } - - res, err := session.exec(sql, args...) - if err != nil { - return 0, err - } - affected, err := res.RowsAffected() - if err != nil { - return 0, err - } - return affected, nil + return session.insertMap(columns, args) } func (session *Session) insertMapString(m map[string]string) (int64, error) { @@ -808,6 +749,7 @@ func (session *Session) insertMapString(m map[string]string) (int64, error) { columns = append(columns, k) } } + sort.Strings(columns) var args = make([]interface{}, 0, len(m)) @@ -815,7 +757,18 @@ func (session *Session) insertMapString(m map[string]string) (int64, error) { args = append(args, m[colName]) } + return session.insertMap(columns, args) +} + +func (session *Session) insertMap(columns []string, args []interface{}) (int64, error) { + tableName := session.statement.TableName() + if len(tableName) <= 0 { + return 0, ErrTableNotFound + } + + exprs := session.statement.exprColumns w := builder.NewWriter() + // if insert where if session.statement.cond.IsValid() { if _, err := w.WriteString(fmt.Sprintf("INSERT INTO %s (", session.engine.Quote(tableName))); err != nil { return 0, err @@ -853,10 +806,29 @@ func (session *Session) insertMapString(m map[string]string) (int64, error) { qm := strings.Repeat("?,", len(columns)) qm = qm[:len(qm)-1] - if _, err := w.WriteString(fmt.Sprintf("INSERT INTO %s (`%s`) VALUES (%s)", session.engine.Quote(tableName), strings.Join(columns, "`,`"), qm)); err != nil { + if _, err := w.WriteString(fmt.Sprintf("INSERT INTO %s (", session.engine.Quote(tableName))); err != nil { return 0, err } + + if err := writeStrings(w, append(columns, exprs.colNames...), "`", "`"); err != nil { + return 0, err + } + if _, err := w.WriteString(fmt.Sprintf(") VALUES (%s", qm)); err != nil { + return 0, err + } + w.Append(args...) + if len(exprs.args) > 0 { + if _, err := w.WriteString(","); err != nil { + return 0, err + } + if err := exprs.writeArgs(w); err != nil { + return 0, err + } + } + if _, err := w.WriteString(")"); err != nil { + return 0, err + } } sql := w.String() diff --git a/vendor/xorm.io/xorm/session_update.go b/vendor/xorm.io/xorm/session_update.go index 231163e0638c..47ced66d1957 100644 --- a/vendor/xorm.io/xorm/session_update.go +++ b/vendor/xorm.io/xorm/session_update.go @@ -239,14 +239,20 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 for i, colName := range exprColumns.colNames { switch tp := exprColumns.args[i].(type) { case string: - colNames = append(colNames, session.engine.Quote(colName)+" = "+tp) + if len(tp) == 0 { + tp = "''" + } + colNames = append(colNames, session.engine.Quote(colName)+"="+tp) case *builder.Builder: subQuery, subArgs, err := builder.ToSQL(tp) if err != nil { return 0, err } - colNames = append(colNames, session.engine.Quote(colName)+" = ("+subQuery+")") + colNames = append(colNames, session.engine.Quote(colName)+"=("+subQuery+")") args = append(args, subArgs...) + default: + colNames = append(colNames, session.engine.Quote(colName)+"=?") + args = append(args, exprColumns.args[i]) } } diff --git a/vendor/xorm.io/xorm/statement_exprparam.go b/vendor/xorm.io/xorm/statement_exprparam.go index 4da4f1ea122f..fc62e36f1fb9 100644 --- a/vendor/xorm.io/xorm/statement_exprparam.go +++ b/vendor/xorm.io/xorm/statement_exprparam.go @@ -69,10 +69,18 @@ func (exprs *exprParams) writeArgs(w *builder.BytesWriter) error { if _, err := w.WriteString(")"); err != nil { return err } - default: + case string: + if arg == "" { + arg = "''" + } if _, err := w.WriteString(fmt.Sprintf("%v", arg)); err != nil { return err } + default: + if _, err := w.WriteString("?"); err != nil { + return err + } + w.Append(arg) } if i != len(exprs.args)-1 { if _, err := w.WriteString(","); err != nil {