* Retry create issue to cope with duplicate keys * Use .SetExpr().Where().Insert()tags/v1.10.0-rc1
@@ -45,7 +45,7 @@ require ( | |||
github.com/glycerine/goconvey v0.0.0-20190315024820-982ee783a72e // indirect | |||
github.com/go-redis/redis v6.15.2+incompatible | |||
github.com/go-sql-driver/mysql v1.4.1 | |||
github.com/go-xorm/xorm v0.7.4 | |||
github.com/go-xorm/xorm v0.7.7-0.20190822154023-17592d96b35b | |||
github.com/gogits/chardet v0.0.0-20150115103509-2404f7772561 | |||
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14 | |||
github.com/google/go-github/v24 v24.0.1 | |||
@@ -117,5 +117,5 @@ require ( | |||
mvdan.cc/xurls/v2 v2.0.0 | |||
strk.kbt.io/projects/go/libravatar v0.0.0-20160628055650-5eed7bff870a | |||
xorm.io/builder v0.3.5 | |||
xorm.io/core v0.6.3 | |||
xorm.io/core v0.7.0 | |||
) |
@@ -143,6 +143,8 @@ github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:9wScpmSP5A3Bk | |||
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:56xuuqnHyryaerycW3BfssRdxQstACi0Epw/yC5E2xM= | |||
github.com/go-xorm/xorm v0.7.4 h1:g/NgC590SzqV5VKmdRDNe/K3Holw3YJUCXX28r+rFGw= | |||
github.com/go-xorm/xorm v0.7.4/go.mod h1:vpza5fydeRgt+stvo9qgMhSNohYqmNt0I1/D6hkCekA= | |||
github.com/go-xorm/xorm v0.7.7-0.20190822154023-17592d96b35b h1:Y0hWUheXDHpIs7BWtJcykO4d1VOsVDKg1PsP5YJwxxM= | |||
github.com/go-xorm/xorm v0.7.7-0.20190822154023-17592d96b35b/go.mod h1:nqz2TAsuOHWH2yk4FYWtacCGgdbrcdZ5mF1XadqEHls= | |||
github.com/gogits/chardet v0.0.0-20150115103509-2404f7772561 h1:deE7ritpK04PgtpyVOS2TYcQEld9qLCD5b5EbVNOuLA= | |||
github.com/gogits/chardet v0.0.0-20150115103509-2404f7772561/go.mod h1:YgYOrVn3Nj9Tq0EvjmFbphRytDj7JNRoWSStJZWDJTQ= | |||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= | |||
@@ -430,6 +432,7 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h | |||
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20190730183949-1393eb018365/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
@@ -446,6 +449,7 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm | |||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= | |||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | |||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | |||
golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= | |||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= | |||
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= | |||
golang.org/x/tools v0.0.0-20190731214159-1e85ed8060aa h1:kwa/4M1dbmhZqOIqYiTtbA6JrvPwo1+jqlub2qDXX90= | |||
@@ -454,6 +458,7 @@ google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMt | |||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= | |||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= | |||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= | |||
google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= | |||
google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I= | |||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= | |||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= | |||
@@ -509,3 +514,5 @@ xorm.io/builder v0.3.5 h1:EilU39fvWDxjb1cDaELpYhsF+zziRBhew8xk4pngO+A= | |||
xorm.io/builder v0.3.5/go.mod h1:ZFbByS/KxZI1FKRjL05PyJ4YrK2bcxlUaAxdum5aTR8= | |||
xorm.io/core v0.6.3 h1:n1NhVZt1s2oLw1BZfX2ocIJsHyso259uPgg63BGr37M= | |||
xorm.io/core v0.6.3/go.mod h1:8kz/C6arVW/O9vk3PgCiMJO2hIAm1UcuOL3dSPyZ2qo= | |||
xorm.io/core v0.7.0 h1:hKxuOKWZNeiFQsSuGet/KV8HZ788hclvAl+7azx3tkM= | |||
xorm.io/core v0.7.0/go.mod h1:TuOJjIVa7e3w/rN8tDcAvuLBMtwzdHPbyOzE6Gk1EUI= |
@@ -5,7 +5,6 @@ | |||
package models | |||
import ( | |||
"errors" | |||
"fmt" | |||
"path" | |||
"regexp" | |||
@@ -74,6 +73,7 @@ var ( | |||
const issueTasksRegexpStr = `(^\s*[-*]\s\[[\sx]\]\s.)|(\n\s*[-*]\s\[[\sx]\]\s.)` | |||
const issueTasksDoneRegexpStr = `(^\s*[-*]\s\[[x]\]\s.)|(\n\s*[-*]\s\[[x]\]\s.)` | |||
const issueMaxDupIndexAttempts = 3 | |||
func init() { | |||
issueTasksPat = regexp.MustCompile(issueTasksRegexpStr) | |||
@@ -1031,36 +1031,9 @@ type NewIssueOptions struct { | |||
IsPull bool | |||
} | |||
// GetMaxIndexOfIssue returns the max index on issue | |||
func GetMaxIndexOfIssue(repoID int64) (int64, error) { | |||
return getMaxIndexOfIssue(x, repoID) | |||
} | |||
func getMaxIndexOfIssue(e Engine, repoID int64) (int64, error) { | |||
var ( | |||
maxIndex int64 | |||
has bool | |||
err error | |||
) | |||
has, err = e.SQL("SELECT COALESCE((SELECT MAX(`index`) FROM issue WHERE repo_id = ?),0)", repoID).Get(&maxIndex) | |||
if err != nil { | |||
return 0, err | |||
} else if !has { | |||
return 0, errors.New("Retrieve Max index from issue failed") | |||
} | |||
return maxIndex, nil | |||
} | |||
func newIssue(e *xorm.Session, doer *User, opts NewIssueOptions) (err error) { | |||
opts.Issue.Title = strings.TrimSpace(opts.Issue.Title) | |||
maxIndex, err := getMaxIndexOfIssue(e, opts.Issue.RepoID) | |||
if err != nil { | |||
return err | |||
} | |||
opts.Issue.Index = maxIndex + 1 | |||
if opts.Issue.MilestoneID > 0 { | |||
milestone, err := getMilestoneByRepoID(e, opts.Issue.RepoID, opts.Issue.MilestoneID) | |||
if err != nil && !IsErrMilestoneNotExist(err) { | |||
@@ -1109,10 +1082,31 @@ func newIssue(e *xorm.Session, doer *User, opts NewIssueOptions) (err error) { | |||
} | |||
// Milestone and assignee validation should happen before insert actual object. | |||
if _, err = e.Insert(opts.Issue); err != nil { | |||
// There's no good way to identify a duplicate key error in database/sql; brute force some retries | |||
dupIndexAttempts := issueMaxDupIndexAttempts | |||
for { | |||
_, err := e.SetExpr("`index`", "coalesce(MAX(`index`),0)+1"). | |||
Where("repo_id=?", opts.Issue.RepoID). | |||
Insert(opts.Issue) | |||
if err == nil { | |||
break | |||
} | |||
dupIndexAttempts-- | |||
if dupIndexAttempts <= 0 { | |||
return err | |||
} | |||
} | |||
inserted, err := getIssueByID(e, opts.Issue.ID) | |||
if err != nil { | |||
return err | |||
} | |||
// Patch Index with the value calculated by the database | |||
opts.Issue.Index = inserted.Index | |||
if opts.Issue.MilestoneID > 0 { | |||
if err = changeMilestoneAssign(e, doer, opts.Issue, -1); err != nil { | |||
return err |
@@ -252,15 +252,8 @@ func CreatePullRequest(ctx *context.APIContext, form api.CreatePullRequestOption | |||
deadlineUnix = timeutil.TimeStamp(form.Deadline.Unix()) | |||
} | |||
maxIndex, err := models.GetMaxIndexOfIssue(repo.ID) | |||
if err != nil { | |||
ctx.ServerError("GetPatch", err) | |||
return | |||
} | |||
prIssue := &models.Issue{ | |||
RepoID: repo.ID, | |||
Index: maxIndex + 1, | |||
Title: form.Title, | |||
PosterID: ctx.User.ID, | |||
Poster: ctx.User, |
@@ -710,15 +710,8 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm) | |||
return | |||
} | |||
maxIndex, err := models.GetMaxIndexOfIssue(repo.ID) | |||
if err != nil { | |||
ctx.ServerError("GetPatch", err) | |||
return | |||
} | |||
pullIssue := &models.Issue{ | |||
RepoID: repo.ID, | |||
Index: maxIndex + 1, | |||
Title: form.Title, | |||
PosterID: ctx.User.ID, | |||
Poster: ctx.User, |
@@ -1,125 +1,431 @@ | |||
--- | |||
kind: pipeline | |||
name: matrix-1 | |||
platform: | |||
os: linux | |||
arch: amd64 | |||
clone: | |||
disable: true | |||
workspace: | |||
base: /go | |||
path: src/github.com/go-xorm/xorm | |||
steps: | |||
- name: git | |||
pull: default | |||
image: plugins/git:next | |||
settings: | |||
depth: 50 | |||
tags: true | |||
- name: init_postgres | |||
pull: default | |||
image: postgres:9.5 | |||
commands: | |||
- "until psql -U postgres -d xorm_test -h pgsql \\\n -c \"SELECT 1;\" >/dev/null 2>&1; do sleep 1; done\n" | |||
- "psql -U postgres -d xorm_test -h pgsql \\\n -c \"create schema xorm;\"\n" | |||
- name: build | |||
pull: default | |||
image: golang:1.10 | |||
commands: | |||
- go get -t -d -v ./... | |||
- go get -u xorm.io/core | |||
- go get -u xorm.io/builder | |||
- go build -v | |||
when: | |||
event: | |||
- push | |||
- pull_request | |||
- name: test-sqlite | |||
pull: default | |||
image: golang:1.10 | |||
commands: | |||
- go get -u github.com/wadey/gocovmerge | |||
- "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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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" | |||
- gocovmerge coverage1-1.txt coverage1-2.txt coverage2-1.txt coverage2-2.txt coverage2.1-1.txt coverage2.1-2.txt coverage3-1.txt coverage3-2.txt coverage4-1.txt coverage4-2.txt coverage5-1.txt coverage5-2.txt > coverage.txt | |||
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 | |||
--- | |||
kind: pipeline | |||
name: matrix-2 | |||
platform: | |||
os: linux | |||
arch: amd64 | |||
clone: | |||
disable: true | |||
workspace: | |||
base: /go | |||
path: src/github.com/go-xorm/xorm | |||
steps: | |||
- name: git | |||
pull: default | |||
image: plugins/git:next | |||
settings: | |||
depth: 50 | |||
tags: true | |||
- name: init_postgres | |||
pull: default | |||
image: postgres:9.5 | |||
commands: | |||
- "until psql -U postgres -d xorm_test -h pgsql \\\n -c \"SELECT 1;\" >/dev/null 2>&1; do sleep 1; done\n" | |||
- "psql -U postgres -d xorm_test -h pgsql \\\n -c \"create schema xorm;\"\n" | |||
- name: build | |||
pull: default | |||
image: golang:1.11 | |||
commands: | |||
- go get -t -d -v ./... | |||
- go get -u xorm.io/core | |||
- go get -u xorm.io/builder | |||
- GO111MODULE=off go build -v | |||
when: | |||
event: | |||
- push | |||
- pull_request | |||
- name: build-gomod | |||
pull: default | |||
image: golang:1.11 | |||
environment: | |||
GOPROXY: "https://goproxy.cn" | |||
commands: | |||
- GO111MODULE=on go build -v | |||
when: | |||
event: | |||
- push | |||
- pull_request | |||
- name: test-sqlite | |||
pull: default | |||
image: golang:1.11 | |||
commands: | |||
- go get -u github.com/wadey/gocovmerge | |||
- "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.11 | |||
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.11 | |||
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.11 | |||
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.11 | |||
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.11 | |||
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" | |||
- gocovmerge coverage1-1.txt coverage1-2.txt coverage2-1.txt coverage2-2.txt coverage2.1-1.txt coverage2.1-2.txt coverage3-1.txt coverage3-2.txt coverage4-1.txt coverage4-2.txt coverage5-1.txt coverage5-2.txt > coverage.txt | |||
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 | |||
--- | |||
kind: pipeline | |||
name: matrix-3 | |||
platform: | |||
os: linux | |||
arch: amd64 | |||
clone: | |||
git: | |||
image: plugins/git:next | |||
disable: true | |||
workspace: | |||
base: /go | |||
path: src/github.com/go-xorm/xorm | |||
steps: | |||
- name: git | |||
pull: default | |||
image: plugins/git:next | |||
settings: | |||
depth: 50 | |||
tags: true | |||
- name: init_postgres | |||
pull: default | |||
image: postgres:9.5 | |||
commands: | |||
- "until psql -U postgres -d xorm_test -h pgsql \\\n -c \"SELECT 1;\" >/dev/null 2>&1; do sleep 1; done\n" | |||
- "psql -U postgres -d xorm_test -h pgsql \\\n -c \"create schema xorm;\"\n" | |||
- name: build | |||
pull: default | |||
image: golang:1.12 | |||
commands: | |||
- go get -t -d -v ./... | |||
- go get -u xorm.io/core | |||
- go get -u xorm.io/builder | |||
- GO111MODULE=off go build -v | |||
when: | |||
event: | |||
- push | |||
- pull_request | |||
- name: build-gomod | |||
pull: default | |||
image: golang:1.12 | |||
environment: | |||
GOPROXY: "https://goproxy.cn" | |||
commands: | |||
- GO111MODULE=on go build -v | |||
when: | |||
event: | |||
- push | |||
- pull_request | |||
- name: test-sqlite | |||
pull: default | |||
image: golang:1.12 | |||
commands: | |||
- go get -u github.com/wadey/gocovmerge | |||
- "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.12 | |||
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.12 | |||
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.12 | |||
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.12 | |||
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.12 | |||
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" | |||
- gocovmerge coverage1-1.txt coverage1-2.txt coverage2-1.txt coverage2-2.txt coverage2.1-1.txt coverage2.1-2.txt coverage3-1.txt coverage3-2.txt coverage4-1.txt coverage4-2.txt coverage5-1.txt coverage5-2.txt > coverage.txt | |||
when: | |||
event: | |||
- push | |||
- pull_request | |||
services: | |||
mysql: | |||
image: mysql:5.7 | |||
environment: | |||
- MYSQL_DATABASE=xorm_test | |||
- MYSQL_ALLOW_EMPTY_PASSWORD=yes | |||
when: | |||
event: [ push, tag, pull_request ] | |||
pgsql: | |||
image: postgres:9.5 | |||
environment: | |||
- POSTGRES_USER=postgres | |||
- POSTGRES_DB=xorm_test | |||
when: | |||
event: [ push, tag, pull_request ] | |||
#mssql: | |||
# image: microsoft/mssql-server-linux:2017-CU11 | |||
# environment: | |||
# - ACCEPT_EULA=Y | |||
# - SA_PASSWORD=yourStrong(!)Password | |||
# - MSSQL_PID=Developer | |||
# commands: | |||
# - echo 'CREATE DATABASE xorm_test' > create.sql | |||
# - /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P yourStrong(!)Password -i "create.sql" | |||
matrix: | |||
GO_VERSION: | |||
- 1.8 | |||
- 1.9 | |||
- 1.10 | |||
- 1.11 | |||
pipeline: | |||
init_postgres: | |||
image: postgres:9.5 | |||
commands: | |||
# wait for postgres service to become available | |||
- | | |||
until psql -U postgres -d xorm_test -h pgsql \ | |||
-c "SELECT 1;" >/dev/null 2>&1; do sleep 1; done | |||
# query the database | |||
- | | |||
psql -U postgres -d xorm_test -h pgsql \ | |||
-c "create schema xorm;" | |||
build: | |||
image: golang:${GO_VERSION} | |||
commands: | |||
- go get -t -d -v ./... | |||
- go get -u xorm.io/core | |||
- go get -u xorm.io/builder | |||
- go build -v | |||
when: | |||
event: [ push, pull_request ] | |||
test-sqlite: | |||
image: golang:${GO_VERSION} | |||
commands: | |||
- go get -u github.com/wadey/gocovmerge | |||
- 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 ] | |||
test-mysql: | |||
image: golang:${GO_VERSION} | |||
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 ] | |||
test-mysql-utf8mb4: | |||
image: golang:${GO_VERSION} | |||
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 ] | |||
test-mymysql: | |||
image: golang:${GO_VERSION} | |||
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 ] | |||
test-postgres: | |||
image: golang:${GO_VERSION} | |||
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 ] | |||
test-postgres-schema: | |||
image: golang:${GO_VERSION} | |||
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 | |||
- gocovmerge coverage1-1.txt coverage1-2.txt coverage2-1.txt coverage2-2.txt coverage2.1-1.txt coverage2.1-2.txt coverage3-1.txt coverage3-2.txt coverage4-1.txt coverage4-2.txt coverage5-1.txt coverage5-2.txt > coverage.txt | |||
when: | |||
event: [ push, pull_request ] | |||
#coverage: | |||
# image: robertstettner/drone-codecov | |||
# secrets: [ codecov_token ] | |||
# files: | |||
# - coverage.txt | |||
# when: | |||
# event: [ push, pull_request ] | |||
# branch: [ master ] | |||
- 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 |
@@ -284,6 +284,13 @@ counts, err := engine.Count(&user) | |||
// SELECT count(*) AS total FROM user | |||
``` | |||
* `FindAndCount` combines function `Find` with `Count` which is usually used in query by page | |||
```Go | |||
var users []User | |||
counts, err := engine.FindAndCount(&users) | |||
``` | |||
* `Sum` sum functions | |||
```Go |
@@ -16,191 +16,191 @@ import ( | |||
var ( | |||
mssqlReservedWords = map[string]bool{ | |||
"ADD": true, | |||
"EXTERNAL": true, | |||
"PROCEDURE": true, | |||
"ALL": true, | |||
"FETCH": true, | |||
"PUBLIC": true, | |||
"ALTER": true, | |||
"FILE": true, | |||
"RAISERROR": true, | |||
"AND": true, | |||
"FILLFACTOR": true, | |||
"READ": true, | |||
"ANY": true, | |||
"FOR": true, | |||
"READTEXT": true, | |||
"AS": true, | |||
"FOREIGN": true, | |||
"RECONFIGURE": true, | |||
"ASC": true, | |||
"FREETEXT": true, | |||
"REFERENCES": true, | |||
"AUTHORIZATION": true, | |||
"FREETEXTTABLE": true, | |||
"REPLICATION": true, | |||
"BACKUP": true, | |||
"FROM": true, | |||
"RESTORE": true, | |||
"BEGIN": true, | |||
"FULL": true, | |||
"RESTRICT": true, | |||
"BETWEEN": true, | |||
"FUNCTION": true, | |||
"RETURN": true, | |||
"BREAK": true, | |||
"GOTO": true, | |||
"REVERT": true, | |||
"BROWSE": true, | |||
"GRANT": true, | |||
"REVOKE": true, | |||
"BULK": true, | |||
"GROUP": true, | |||
"RIGHT": true, | |||
"BY": true, | |||
"HAVING": true, | |||
"ROLLBACK": true, | |||
"CASCADE": true, | |||
"HOLDLOCK": true, | |||
"ROWCOUNT": true, | |||
"CASE": true, | |||
"IDENTITY": true, | |||
"ROWGUIDCOL": true, | |||
"CHECK": true, | |||
"IDENTITY_INSERT": true, | |||
"RULE": true, | |||
"CHECKPOINT": true, | |||
"IDENTITYCOL": true, | |||
"SAVE": true, | |||
"CLOSE": true, | |||
"IF": true, | |||
"SCHEMA": true, | |||
"CLUSTERED": true, | |||
"IN": true, | |||
"SECURITYAUDIT": true, | |||
"COALESCE": true, | |||
"INDEX": true, | |||
"SELECT": true, | |||
"COLLATE": true, | |||
"INNER": true, | |||
"SEMANTICKEYPHRASETABLE": true, | |||
"COLUMN": true, | |||
"INSERT": true, | |||
"ADD": true, | |||
"EXTERNAL": true, | |||
"PROCEDURE": true, | |||
"ALL": true, | |||
"FETCH": true, | |||
"PUBLIC": true, | |||
"ALTER": true, | |||
"FILE": true, | |||
"RAISERROR": true, | |||
"AND": true, | |||
"FILLFACTOR": true, | |||
"READ": true, | |||
"ANY": true, | |||
"FOR": true, | |||
"READTEXT": true, | |||
"AS": true, | |||
"FOREIGN": true, | |||
"RECONFIGURE": true, | |||
"ASC": true, | |||
"FREETEXT": true, | |||
"REFERENCES": true, | |||
"AUTHORIZATION": true, | |||
"FREETEXTTABLE": true, | |||
"REPLICATION": true, | |||
"BACKUP": true, | |||
"FROM": true, | |||
"RESTORE": true, | |||
"BEGIN": true, | |||
"FULL": true, | |||
"RESTRICT": true, | |||
"BETWEEN": true, | |||
"FUNCTION": true, | |||
"RETURN": true, | |||
"BREAK": true, | |||
"GOTO": true, | |||
"REVERT": true, | |||
"BROWSE": true, | |||
"GRANT": true, | |||
"REVOKE": true, | |||
"BULK": true, | |||
"GROUP": true, | |||
"RIGHT": true, | |||
"BY": true, | |||
"HAVING": true, | |||
"ROLLBACK": true, | |||
"CASCADE": true, | |||
"HOLDLOCK": true, | |||
"ROWCOUNT": true, | |||
"CASE": true, | |||
"IDENTITY": true, | |||
"ROWGUIDCOL": true, | |||
"CHECK": true, | |||
"IDENTITY_INSERT": true, | |||
"RULE": true, | |||
"CHECKPOINT": true, | |||
"IDENTITYCOL": true, | |||
"SAVE": true, | |||
"CLOSE": true, | |||
"IF": true, | |||
"SCHEMA": true, | |||
"CLUSTERED": true, | |||
"IN": true, | |||
"SECURITYAUDIT": true, | |||
"COALESCE": true, | |||
"INDEX": true, | |||
"SELECT": true, | |||
"COLLATE": true, | |||
"INNER": true, | |||
"SEMANTICKEYPHRASETABLE": true, | |||
"COLUMN": true, | |||
"INSERT": true, | |||
"SEMANTICSIMILARITYDETAILSTABLE": true, | |||
"COMMIT": true, | |||
"INTERSECT": true, | |||
"SEMANTICSIMILARITYTABLE": true, | |||
"COMPUTE": true, | |||
"INTO": true, | |||
"SESSION_USER": true, | |||
"CONSTRAINT": true, | |||
"IS": true, | |||
"SET": true, | |||
"CONTAINS": true, | |||
"JOIN": true, | |||
"SETUSER": true, | |||
"CONTAINSTABLE": true, | |||
"KEY": true, | |||
"SHUTDOWN": true, | |||
"CONTINUE": true, | |||
"KILL": true, | |||
"SOME": true, | |||
"CONVERT": true, | |||
"LEFT": true, | |||
"STATISTICS": true, | |||
"CREATE": true, | |||
"LIKE": true, | |||
"SYSTEM_USER": true, | |||
"CROSS": true, | |||
"LINENO": true, | |||
"TABLE": true, | |||
"CURRENT": true, | |||
"LOAD": true, | |||
"TABLESAMPLE": true, | |||
"CURRENT_DATE": true, | |||
"MERGE": true, | |||
"TEXTSIZE": true, | |||
"CURRENT_TIME": true, | |||
"NATIONAL": true, | |||
"THEN": true, | |||
"CURRENT_TIMESTAMP": true, | |||
"NOCHECK": true, | |||
"TO": true, | |||
"CURRENT_USER": true, | |||
"NONCLUSTERED": true, | |||
"TOP": true, | |||
"CURSOR": true, | |||
"NOT": true, | |||
"TRAN": true, | |||
"DATABASE": true, | |||
"NULL": true, | |||
"TRANSACTION": true, | |||
"DBCC": true, | |||
"NULLIF": true, | |||
"TRIGGER": true, | |||
"DEALLOCATE": true, | |||
"OF": true, | |||
"TRUNCATE": true, | |||
"DECLARE": true, | |||
"OFF": true, | |||
"TRY_CONVERT": true, | |||
"DEFAULT": true, | |||
"OFFSETS": true, | |||
"TSEQUAL": true, | |||
"DELETE": true, | |||
"ON": true, | |||
"UNION": true, | |||
"DENY": true, | |||
"OPEN": true, | |||
"UNIQUE": true, | |||
"DESC": true, | |||
"OPENDATASOURCE": true, | |||
"UNPIVOT": true, | |||
"DISK": true, | |||
"OPENQUERY": true, | |||
"UPDATE": true, | |||
"DISTINCT": true, | |||
"OPENROWSET": true, | |||
"UPDATETEXT": true, | |||
"DISTRIBUTED": true, | |||
"OPENXML": true, | |||
"USE": true, | |||
"DOUBLE": true, | |||
"OPTION": true, | |||
"USER": true, | |||
"DROP": true, | |||
"OR": true, | |||
"VALUES": true, | |||
"DUMP": true, | |||
"ORDER": true, | |||
"VARYING": true, | |||
"ELSE": true, | |||
"OUTER": true, | |||
"VIEW": true, | |||
"END": true, | |||
"OVER": true, | |||
"WAITFOR": true, | |||
"ERRLVL": true, | |||
"PERCENT": true, | |||
"WHEN": true, | |||
"ESCAPE": true, | |||
"PIVOT": true, | |||
"WHERE": true, | |||
"EXCEPT": true, | |||
"PLAN": true, | |||
"WHILE": true, | |||
"EXEC": true, | |||
"PRECISION": true, | |||
"WITH": true, | |||
"EXECUTE": true, | |||
"PRIMARY": true, | |||
"WITHIN": true, | |||
"EXISTS": true, | |||
"PRINT": true, | |||
"WRITETEXT": true, | |||
"EXIT": true, | |||
"PROC": true, | |||
"COMMIT": true, | |||
"INTERSECT": true, | |||
"SEMANTICSIMILARITYTABLE": true, | |||
"COMPUTE": true, | |||
"INTO": true, | |||
"SESSION_USER": true, | |||
"CONSTRAINT": true, | |||
"IS": true, | |||
"SET": true, | |||
"CONTAINS": true, | |||
"JOIN": true, | |||
"SETUSER": true, | |||
"CONTAINSTABLE": true, | |||
"KEY": true, | |||
"SHUTDOWN": true, | |||
"CONTINUE": true, | |||
"KILL": true, | |||
"SOME": true, | |||
"CONVERT": true, | |||
"LEFT": true, | |||
"STATISTICS": true, | |||
"CREATE": true, | |||
"LIKE": true, | |||
"SYSTEM_USER": true, | |||
"CROSS": true, | |||
"LINENO": true, | |||
"TABLE": true, | |||
"CURRENT": true, | |||
"LOAD": true, | |||
"TABLESAMPLE": true, | |||
"CURRENT_DATE": true, | |||
"MERGE": true, | |||
"TEXTSIZE": true, | |||
"CURRENT_TIME": true, | |||
"NATIONAL": true, | |||
"THEN": true, | |||
"CURRENT_TIMESTAMP": true, | |||
"NOCHECK": true, | |||
"TO": true, | |||
"CURRENT_USER": true, | |||
"NONCLUSTERED": true, | |||
"TOP": true, | |||
"CURSOR": true, | |||
"NOT": true, | |||
"TRAN": true, | |||
"DATABASE": true, | |||
"NULL": true, | |||
"TRANSACTION": true, | |||
"DBCC": true, | |||
"NULLIF": true, | |||
"TRIGGER": true, | |||
"DEALLOCATE": true, | |||
"OF": true, | |||
"TRUNCATE": true, | |||
"DECLARE": true, | |||
"OFF": true, | |||
"TRY_CONVERT": true, | |||
"DEFAULT": true, | |||
"OFFSETS": true, | |||
"TSEQUAL": true, | |||
"DELETE": true, | |||
"ON": true, | |||
"UNION": true, | |||
"DENY": true, | |||
"OPEN": true, | |||
"UNIQUE": true, | |||
"DESC": true, | |||
"OPENDATASOURCE": true, | |||
"UNPIVOT": true, | |||
"DISK": true, | |||
"OPENQUERY": true, | |||
"UPDATE": true, | |||
"DISTINCT": true, | |||
"OPENROWSET": true, | |||
"UPDATETEXT": true, | |||
"DISTRIBUTED": true, | |||
"OPENXML": true, | |||
"USE": true, | |||
"DOUBLE": true, | |||
"OPTION": true, | |||
"USER": true, | |||
"DROP": true, | |||
"OR": true, | |||
"VALUES": true, | |||
"DUMP": true, | |||
"ORDER": true, | |||
"VARYING": true, | |||
"ELSE": true, | |||
"OUTER": true, | |||
"VIEW": true, | |||
"END": true, | |||
"OVER": true, | |||
"WAITFOR": true, | |||
"ERRLVL": true, | |||
"PERCENT": true, | |||
"WHEN": true, | |||
"ESCAPE": true, | |||
"PIVOT": true, | |||
"WHERE": true, | |||
"EXCEPT": true, | |||
"PLAN": true, | |||
"WHILE": true, | |||
"EXEC": true, | |||
"PRECISION": true, | |||
"WITH": true, | |||
"EXECUTE": true, | |||
"PRIMARY": true, | |||
"WITHIN": true, | |||
"EXISTS": true, | |||
"PRINT": true, | |||
"WRITETEXT": true, | |||
"EXIT": true, | |||
"PROC": true, | |||
} | |||
) | |||
@@ -286,10 +286,6 @@ func (db *mssql) Quote(name string) string { | |||
return "\"" + name + "\"" | |||
} | |||
func (db *mssql) QuoteStr() string { | |||
return "\"" | |||
} | |||
func (db *mssql) SupportEngine() bool { | |||
return false | |||
} | |||
@@ -507,7 +503,7 @@ func (db *mssql) CreateTableSql(table *core.Table, tableName, storeEngine, chars | |||
sql = "IF NOT EXISTS (SELECT [name] FROM sys.tables WHERE [name] = '" + tableName + "' ) CREATE TABLE " | |||
sql += db.QuoteStr() + tableName + db.QuoteStr() + " (" | |||
sql += db.Quote(tableName) + " (" | |||
pkList := table.PrimaryKeys | |||
@@ -220,7 +220,7 @@ func (db *mysql) SqlType(c *core.Column) string { | |||
case core.TimeStampz: | |||
res = core.Char | |||
c.Length = 64 | |||
case core.Enum: //mysql enum | |||
case core.Enum: // mysql enum | |||
res = core.Enum | |||
res += "(" | |||
opts := "" | |||
@@ -229,7 +229,7 @@ func (db *mysql) SqlType(c *core.Column) string { | |||
} | |||
res += strings.TrimLeft(opts, ",") | |||
res += ")" | |||
case core.Set: //mysql set | |||
case core.Set: // mysql set | |||
res = core.Set | |||
res += "(" | |||
opts := "" | |||
@@ -278,10 +278,6 @@ func (db *mysql) Quote(name string) string { | |||
return "`" + name + "`" | |||
} | |||
func (db *mysql) QuoteStr() string { | |||
return "`" | |||
} | |||
func (db *mysql) SupportEngine() bool { | |||
return true | |||
} | |||
@@ -360,7 +356,7 @@ func (db *mysql) GetColumns(tableName string) ([]string, map[string]*core.Column | |||
var len1, len2 int | |||
if len(cts) == 2 { | |||
idx := strings.Index(cts[1], ")") | |||
if colType == core.Enum && cts[1][0] == '\'' { //enum | |||
if colType == core.Enum && cts[1][0] == '\'' { // enum | |||
options := strings.Split(cts[1][0:idx], ",") | |||
col.EnumOptions = make(map[string]int) | |||
for k, v := range options { | |||
@@ -408,7 +404,7 @@ func (db *mysql) GetColumns(tableName string) ([]string, map[string]*core.Column | |||
col.IsPrimaryKey = true | |||
} | |||
if colKey == "UNI" { | |||
//col.is | |||
// col.is | |||
} | |||
if extra == "auto_increment" { | |||
@@ -554,12 +550,10 @@ func (db *mysql) CreateTableSql(table *core.Table, tableName, storeEngine, chars | |||
if len(charset) == 0 { | |||
charset = db.URI().Charset | |||
} | |||
} | |||
if len(charset) != 0 { | |||
sql += " DEFAULT CHARSET " + charset | |||
} | |||
if db.rowFormat != "" { | |||
sql += " ROW_FORMAT=" + db.rowFormat | |||
@@ -633,7 +627,7 @@ func (p *mysqlDriver) Parse(driverName, dataSourceName string) (*core.Uri, error | |||
`\/(?P<dbname>.*?)` + // /dbname | |||
`(?:\?(?P<params>[^\?]*))?$`) // [?param1=value1¶mN=valueN] | |||
matches := dsnPattern.FindStringSubmatch(dataSourceName) | |||
//tlsConfigRegister := make(map[string]*tls.Config) | |||
// tlsConfigRegister := make(map[string]*tls.Config) | |||
names := dsnPattern.SubexpNames() | |||
uri := &core.Uri{DbType: core.MYSQL} |
@@ -230,271 +230,271 @@ var ( | |||
"LOGGING": true, | |||
"LOGICAL_READS_PER_CALL": true, | |||
"LOGICAL_READS_PER_SESSION": true, | |||
"LONG": true, | |||
"MANAGE": true, | |||
"MASTER": true, | |||
"MAX": true, | |||
"MAXARCHLOGS": true, | |||
"MAXDATAFILES": true, | |||
"MAXEXTENTS": true, | |||
"MAXINSTANCES": true, | |||
"MAXLOGFILES": true, | |||
"MAXLOGHISTORY": true, | |||
"MAXLOGMEMBERS": true, | |||
"MAXSIZE": true, | |||
"MAXTRANS": true, | |||
"MAXVALUE": true, | |||
"MIN": true, | |||
"MEMBER": true, | |||
"MINIMUM": true, | |||
"MINEXTENTS": true, | |||
"MINUS": true, | |||
"MINVALUE": true, | |||
"MLSLABEL": true, | |||
"MLS_LABEL_FORMAT": true, | |||
"MODE": true, | |||
"MODIFY": true, | |||
"MOUNT": true, | |||
"MOVE": true, | |||
"MTS_DISPATCHERS": true, | |||
"MULTISET": true, | |||
"NATIONAL": true, | |||
"NCHAR": true, | |||
"NCHAR_CS": true, | |||
"NCLOB": true, | |||
"NEEDED": true, | |||
"NESTED": true, | |||
"NETWORK": true, | |||
"NEW": true, | |||
"NEXT": true, | |||
"NOARCHIVELOG": true, | |||
"NOAUDIT": true, | |||
"NOCACHE": true, | |||
"NOCOMPRESS": true, | |||
"NOCYCLE": true, | |||
"NOFORCE": true, | |||
"NOLOGGING": true, | |||
"NOMAXVALUE": true, | |||
"NOMINVALUE": true, | |||
"NONE": true, | |||
"NOORDER": true, | |||
"NOOVERRIDE": true, | |||
"NOPARALLEL": true, | |||
"NOREVERSE": true, | |||
"NORMAL": true, | |||
"NOSORT": true, | |||
"NOT": true, | |||
"NOTHING": true, | |||
"NOWAIT": true, | |||
"NULL": true, | |||
"NUMBER": true, | |||
"NUMERIC": true, | |||
"NVARCHAR2": true, | |||
"OBJECT": true, | |||
"OBJNO": true, | |||
"OBJNO_REUSE": true, | |||
"OF": true, | |||
"OFF": true, | |||
"OFFLINE": true, | |||
"OID": true, | |||
"OIDINDEX": true, | |||
"OLD": true, | |||
"ON": true, | |||
"ONLINE": true, | |||
"ONLY": true, | |||
"OPCODE": true, | |||
"OPEN": true, | |||
"OPTIMAL": true, | |||
"OPTIMIZER_GOAL": true, | |||
"OPTION": true, | |||
"OR": true, | |||
"ORDER": true, | |||
"ORGANIZATION": true, | |||
"OSLABEL": true, | |||
"OVERFLOW": true, | |||
"OWN": true, | |||
"PACKAGE": true, | |||
"PARALLEL": true, | |||
"PARTITION": true, | |||
"PASSWORD": true, | |||
"PASSWORD_GRACE_TIME": true, | |||
"PASSWORD_LIFE_TIME": true, | |||
"PASSWORD_LOCK_TIME": true, | |||
"PASSWORD_REUSE_MAX": true, | |||
"PASSWORD_REUSE_TIME": true, | |||
"PASSWORD_VERIFY_FUNCTION": true, | |||
"PCTFREE": true, | |||
"PCTINCREASE": true, | |||
"PCTTHRESHOLD": true, | |||
"PCTUSED": true, | |||
"PCTVERSION": true, | |||
"PERCENT": true, | |||
"PERMANENT": true, | |||
"PLAN": true, | |||
"PLSQL_DEBUG": true, | |||
"POST_TRANSACTION": true, | |||
"PRECISION": true, | |||
"PRESERVE": true, | |||
"PRIMARY": true, | |||
"PRIOR": true, | |||
"PRIVATE": true, | |||
"PRIVATE_SGA": true, | |||
"PRIVILEGE": true, | |||
"PRIVILEGES": true, | |||
"PROCEDURE": true, | |||
"PROFILE": true, | |||
"PUBLIC": true, | |||
"PURGE": true, | |||
"QUEUE": true, | |||
"QUOTA": true, | |||
"RANGE": true, | |||
"RAW": true, | |||
"RBA": true, | |||
"READ": true, | |||
"READUP": true, | |||
"REAL": true, | |||
"REBUILD": true, | |||
"RECOVER": true, | |||
"RECOVERABLE": true, | |||
"RECOVERY": true, | |||
"REF": true, | |||
"REFERENCES": true, | |||
"REFERENCING": true, | |||
"REFRESH": true, | |||
"RENAME": true, | |||
"REPLACE": true, | |||
"RESET": true, | |||
"RESETLOGS": true, | |||
"RESIZE": true, | |||
"RESOURCE": true, | |||
"RESTRICTED": true, | |||
"RETURN": true, | |||
"RETURNING": true, | |||
"REUSE": true, | |||
"REVERSE": true, | |||
"REVOKE": true, | |||
"ROLE": true, | |||
"ROLES": true, | |||
"ROLLBACK": true, | |||
"ROW": true, | |||
"ROWID": true, | |||
"ROWNUM": true, | |||
"ROWS": true, | |||
"RULE": true, | |||
"SAMPLE": true, | |||
"SAVEPOINT": true, | |||
"SB4": true, | |||
"SCAN_INSTANCES": true, | |||
"SCHEMA": true, | |||
"SCN": true, | |||
"SCOPE": true, | |||
"SD_ALL": true, | |||
"SD_INHIBIT": true, | |||
"SD_SHOW": true, | |||
"SEGMENT": true, | |||
"SEG_BLOCK": true, | |||
"SEG_FILE": true, | |||
"SELECT": true, | |||
"SEQUENCE": true, | |||
"SERIALIZABLE": true, | |||
"SESSION": true, | |||
"SESSION_CACHED_CURSORS": true, | |||
"SESSIONS_PER_USER": true, | |||
"SET": true, | |||
"SHARE": true, | |||
"SHARED": true, | |||
"SHARED_POOL": true, | |||
"SHRINK": true, | |||
"SIZE": true, | |||
"SKIP": true, | |||
"SKIP_UNUSABLE_INDEXES": true, | |||
"SMALLINT": true, | |||
"SNAPSHOT": true, | |||
"SOME": true, | |||
"SORT": true, | |||
"SPECIFICATION": true, | |||
"SPLIT": true, | |||
"SQL_TRACE": true, | |||
"STANDBY": true, | |||
"START": true, | |||
"STATEMENT_ID": true, | |||
"STATISTICS": true, | |||
"STOP": true, | |||
"STORAGE": true, | |||
"STORE": true, | |||
"STRUCTURE": true, | |||
"SUCCESSFUL": true, | |||
"SWITCH": true, | |||
"SYS_OP_ENFORCE_NOT_NULL$": true, | |||
"SYS_OP_NTCIMG$": true, | |||
"SYNONYM": true, | |||
"SYSDATE": true, | |||
"SYSDBA": true, | |||
"SYSOPER": true, | |||
"SYSTEM": true, | |||
"TABLE": true, | |||
"TABLES": true, | |||
"TABLESPACE": true, | |||
"TABLESPACE_NO": true, | |||
"TABNO": true, | |||
"TEMPORARY": true, | |||
"THAN": true, | |||
"THE": true, | |||
"THEN": true, | |||
"THREAD": true, | |||
"TIMESTAMP": true, | |||
"TIME": true, | |||
"TO": true, | |||
"TOPLEVEL": true, | |||
"TRACE": true, | |||
"TRACING": true, | |||
"TRANSACTION": true, | |||
"TRANSITIONAL": true, | |||
"TRIGGER": true, | |||
"TRIGGERS": true, | |||
"TRUE": true, | |||
"TRUNCATE": true, | |||
"TX": true, | |||
"TYPE": true, | |||
"UB2": true, | |||
"UBA": true, | |||
"UID": true, | |||
"UNARCHIVED": true, | |||
"UNDO": true, | |||
"UNION": true, | |||
"UNIQUE": true, | |||
"UNLIMITED": true, | |||
"UNLOCK": true, | |||
"UNRECOVERABLE": true, | |||
"UNTIL": true, | |||
"UNUSABLE": true, | |||
"UNUSED": true, | |||
"UPDATABLE": true, | |||
"UPDATE": true, | |||
"USAGE": true, | |||
"USE": true, | |||
"USER": true, | |||
"USING": true, | |||
"VALIDATE": true, | |||
"VALIDATION": true, | |||
"VALUE": true, | |||
"VALUES": true, | |||
"VARCHAR": true, | |||
"VARCHAR2": true, | |||
"VARYING": true, | |||
"VIEW": true, | |||
"WHEN": true, | |||
"WHENEVER": true, | |||
"WHERE": true, | |||
"WITH": true, | |||
"WITHOUT": true, | |||
"WORK": true, | |||
"WRITE": true, | |||
"WRITEDOWN": true, | |||
"WRITEUP": true, | |||
"XID": true, | |||
"YEAR": true, | |||
"ZONE": true, | |||
"LONG": true, | |||
"MANAGE": true, | |||
"MASTER": true, | |||
"MAX": true, | |||
"MAXARCHLOGS": true, | |||
"MAXDATAFILES": true, | |||
"MAXEXTENTS": true, | |||
"MAXINSTANCES": true, | |||
"MAXLOGFILES": true, | |||
"MAXLOGHISTORY": true, | |||
"MAXLOGMEMBERS": true, | |||
"MAXSIZE": true, | |||
"MAXTRANS": true, | |||
"MAXVALUE": true, | |||
"MIN": true, | |||
"MEMBER": true, | |||
"MINIMUM": true, | |||
"MINEXTENTS": true, | |||
"MINUS": true, | |||
"MINVALUE": true, | |||
"MLSLABEL": true, | |||
"MLS_LABEL_FORMAT": true, | |||
"MODE": true, | |||
"MODIFY": true, | |||
"MOUNT": true, | |||
"MOVE": true, | |||
"MTS_DISPATCHERS": true, | |||
"MULTISET": true, | |||
"NATIONAL": true, | |||
"NCHAR": true, | |||
"NCHAR_CS": true, | |||
"NCLOB": true, | |||
"NEEDED": true, | |||
"NESTED": true, | |||
"NETWORK": true, | |||
"NEW": true, | |||
"NEXT": true, | |||
"NOARCHIVELOG": true, | |||
"NOAUDIT": true, | |||
"NOCACHE": true, | |||
"NOCOMPRESS": true, | |||
"NOCYCLE": true, | |||
"NOFORCE": true, | |||
"NOLOGGING": true, | |||
"NOMAXVALUE": true, | |||
"NOMINVALUE": true, | |||
"NONE": true, | |||
"NOORDER": true, | |||
"NOOVERRIDE": true, | |||
"NOPARALLEL": true, | |||
"NOREVERSE": true, | |||
"NORMAL": true, | |||
"NOSORT": true, | |||
"NOT": true, | |||
"NOTHING": true, | |||
"NOWAIT": true, | |||
"NULL": true, | |||
"NUMBER": true, | |||
"NUMERIC": true, | |||
"NVARCHAR2": true, | |||
"OBJECT": true, | |||
"OBJNO": true, | |||
"OBJNO_REUSE": true, | |||
"OF": true, | |||
"OFF": true, | |||
"OFFLINE": true, | |||
"OID": true, | |||
"OIDINDEX": true, | |||
"OLD": true, | |||
"ON": true, | |||
"ONLINE": true, | |||
"ONLY": true, | |||
"OPCODE": true, | |||
"OPEN": true, | |||
"OPTIMAL": true, | |||
"OPTIMIZER_GOAL": true, | |||
"OPTION": true, | |||
"OR": true, | |||
"ORDER": true, | |||
"ORGANIZATION": true, | |||
"OSLABEL": true, | |||
"OVERFLOW": true, | |||
"OWN": true, | |||
"PACKAGE": true, | |||
"PARALLEL": true, | |||
"PARTITION": true, | |||
"PASSWORD": true, | |||
"PASSWORD_GRACE_TIME": true, | |||
"PASSWORD_LIFE_TIME": true, | |||
"PASSWORD_LOCK_TIME": true, | |||
"PASSWORD_REUSE_MAX": true, | |||
"PASSWORD_REUSE_TIME": true, | |||
"PASSWORD_VERIFY_FUNCTION": true, | |||
"PCTFREE": true, | |||
"PCTINCREASE": true, | |||
"PCTTHRESHOLD": true, | |||
"PCTUSED": true, | |||
"PCTVERSION": true, | |||
"PERCENT": true, | |||
"PERMANENT": true, | |||
"PLAN": true, | |||
"PLSQL_DEBUG": true, | |||
"POST_TRANSACTION": true, | |||
"PRECISION": true, | |||
"PRESERVE": true, | |||
"PRIMARY": true, | |||
"PRIOR": true, | |||
"PRIVATE": true, | |||
"PRIVATE_SGA": true, | |||
"PRIVILEGE": true, | |||
"PRIVILEGES": true, | |||
"PROCEDURE": true, | |||
"PROFILE": true, | |||
"PUBLIC": true, | |||
"PURGE": true, | |||
"QUEUE": true, | |||
"QUOTA": true, | |||
"RANGE": true, | |||
"RAW": true, | |||
"RBA": true, | |||
"READ": true, | |||
"READUP": true, | |||
"REAL": true, | |||
"REBUILD": true, | |||
"RECOVER": true, | |||
"RECOVERABLE": true, | |||
"RECOVERY": true, | |||
"REF": true, | |||
"REFERENCES": true, | |||
"REFERENCING": true, | |||
"REFRESH": true, | |||
"RENAME": true, | |||
"REPLACE": true, | |||
"RESET": true, | |||
"RESETLOGS": true, | |||
"RESIZE": true, | |||
"RESOURCE": true, | |||
"RESTRICTED": true, | |||
"RETURN": true, | |||
"RETURNING": true, | |||
"REUSE": true, | |||
"REVERSE": true, | |||
"REVOKE": true, | |||
"ROLE": true, | |||
"ROLES": true, | |||
"ROLLBACK": true, | |||
"ROW": true, | |||
"ROWID": true, | |||
"ROWNUM": true, | |||
"ROWS": true, | |||
"RULE": true, | |||
"SAMPLE": true, | |||
"SAVEPOINT": true, | |||
"SB4": true, | |||
"SCAN_INSTANCES": true, | |||
"SCHEMA": true, | |||
"SCN": true, | |||
"SCOPE": true, | |||
"SD_ALL": true, | |||
"SD_INHIBIT": true, | |||
"SD_SHOW": true, | |||
"SEGMENT": true, | |||
"SEG_BLOCK": true, | |||
"SEG_FILE": true, | |||
"SELECT": true, | |||
"SEQUENCE": true, | |||
"SERIALIZABLE": true, | |||
"SESSION": true, | |||
"SESSION_CACHED_CURSORS": true, | |||
"SESSIONS_PER_USER": true, | |||
"SET": true, | |||
"SHARE": true, | |||
"SHARED": true, | |||
"SHARED_POOL": true, | |||
"SHRINK": true, | |||
"SIZE": true, | |||
"SKIP": true, | |||
"SKIP_UNUSABLE_INDEXES": true, | |||
"SMALLINT": true, | |||
"SNAPSHOT": true, | |||
"SOME": true, | |||
"SORT": true, | |||
"SPECIFICATION": true, | |||
"SPLIT": true, | |||
"SQL_TRACE": true, | |||
"STANDBY": true, | |||
"START": true, | |||
"STATEMENT_ID": true, | |||
"STATISTICS": true, | |||
"STOP": true, | |||
"STORAGE": true, | |||
"STORE": true, | |||
"STRUCTURE": true, | |||
"SUCCESSFUL": true, | |||
"SWITCH": true, | |||
"SYS_OP_ENFORCE_NOT_NULL$": true, | |||
"SYS_OP_NTCIMG$": true, | |||
"SYNONYM": true, | |||
"SYSDATE": true, | |||
"SYSDBA": true, | |||
"SYSOPER": true, | |||
"SYSTEM": true, | |||
"TABLE": true, | |||
"TABLES": true, | |||
"TABLESPACE": true, | |||
"TABLESPACE_NO": true, | |||
"TABNO": true, | |||
"TEMPORARY": true, | |||
"THAN": true, | |||
"THE": true, | |||
"THEN": true, | |||
"THREAD": true, | |||
"TIMESTAMP": true, | |||
"TIME": true, | |||
"TO": true, | |||
"TOPLEVEL": true, | |||
"TRACE": true, | |||
"TRACING": true, | |||
"TRANSACTION": true, | |||
"TRANSITIONAL": true, | |||
"TRIGGER": true, | |||
"TRIGGERS": true, | |||
"TRUE": true, | |||
"TRUNCATE": true, | |||
"TX": true, | |||
"TYPE": true, | |||
"UB2": true, | |||
"UBA": true, | |||
"UID": true, | |||
"UNARCHIVED": true, | |||
"UNDO": true, | |||
"UNION": true, | |||
"UNIQUE": true, | |||
"UNLIMITED": true, | |||
"UNLOCK": true, | |||
"UNRECOVERABLE": true, | |||
"UNTIL": true, | |||
"UNUSABLE": true, | |||
"UNUSED": true, | |||
"UPDATABLE": true, | |||
"UPDATE": true, | |||
"USAGE": true, | |||
"USE": true, | |||
"USER": true, | |||
"USING": true, | |||
"VALIDATE": true, | |||
"VALIDATION": true, | |||
"VALUE": true, | |||
"VALUES": true, | |||
"VARCHAR": true, | |||
"VARCHAR2": true, | |||
"VARYING": true, | |||
"VIEW": true, | |||
"WHEN": true, | |||
"WHENEVER": true, | |||
"WHERE": true, | |||
"WITH": true, | |||
"WITHOUT": true, | |||
"WORK": true, | |||
"WRITE": true, | |||
"WRITEDOWN": true, | |||
"WRITEUP": true, | |||
"XID": true, | |||
"YEAR": true, | |||
"ZONE": true, | |||
} | |||
) | |||
@@ -552,11 +552,7 @@ func (db *oracle) IsReserved(name string) bool { | |||
} | |||
func (db *oracle) Quote(name string) string { | |||
return "\"" + name + "\"" | |||
} | |||
func (db *oracle) QuoteStr() string { | |||
return "\"" | |||
return "[" + name + "]" | |||
} | |||
func (db *oracle) SupportEngine() bool { | |||
@@ -596,7 +592,7 @@ func (db *oracle) CreateTableSql(table *core.Table, tableName, storeEngine, char | |||
sql += col.String(b.dialect) | |||
} else {*/ | |||
sql += col.StringNoPk(db) | |||
//} | |||
// } | |||
sql = strings.TrimSpace(sql) | |||
sql += ", " | |||
} | |||
@@ -865,7 +861,7 @@ func (cfg *goracleDriver) Parse(driverName, dataSourceName string) (*core.Uri, e | |||
`\/(?P<dbname>.*?)` + // /dbname | |||
`(?:\?(?P<params>[^\?]*))?$`) // [?param1=value1¶mN=valueN] | |||
matches := dsnPattern.FindStringSubmatch(dataSourceName) | |||
//tlsConfigRegister := make(map[string]*tls.Config) | |||
// tlsConfigRegister := make(map[string]*tls.Config) | |||
names := dsnPattern.SubexpNames() | |||
for i, match := range matches { | |||
@@ -883,8 +879,8 @@ func (cfg *goracleDriver) Parse(driverName, dataSourceName string) (*core.Uri, e | |||
type oci8Driver struct { | |||
} | |||
//dataSourceName=user/password@ipv4:port/dbname | |||
//dataSourceName=user/password@[ipv6]:port/dbname | |||
// dataSourceName=user/password@ipv4:port/dbname | |||
// dataSourceName=user/password@[ipv6]:port/dbname | |||
func (p *oci8Driver) Parse(driverName, dataSourceName string) (*core.Uri, error) { | |||
db := &core.Uri{DbType: core.ORACLE} | |||
dsnPattern := regexp.MustCompile( |
@@ -202,10 +202,6 @@ func (db *sqlite3) Quote(name string) string { | |||
return "`" + name + "`" | |||
} | |||
func (db *sqlite3) QuoteStr() string { | |||
return "`" | |||
} | |||
func (db *sqlite3) AutoIncrStr() string { | |||
return "AUTOINCREMENT" | |||
} |
@@ -175,12 +175,6 @@ func (engine *Engine) SupportInsertMany() bool { | |||
return engine.dialect.SupportInsertMany() | |||
} | |||
// QuoteStr Engine's database use which character as quote. | |||
// mysql, sqlite use ` and postgres use " | |||
func (engine *Engine) QuoteStr() string { | |||
return engine.dialect.QuoteStr() | |||
} | |||
func (engine *Engine) quoteColumns(columnStr string) string { | |||
columns := strings.Split(columnStr, ",") | |||
for i := 0; i < len(columns); i++ { | |||
@@ -196,13 +190,10 @@ func (engine *Engine) Quote(value string) string { | |||
return value | |||
} | |||
if string(value[0]) == engine.dialect.QuoteStr() || value[0] == '`' { | |||
return value | |||
} | |||
value = strings.Replace(value, ".", engine.dialect.QuoteStr()+"."+engine.dialect.QuoteStr(), -1) | |||
buf := builder.StringBuilder{} | |||
engine.QuoteTo(&buf, value) | |||
return engine.dialect.QuoteStr() + value + engine.dialect.QuoteStr() | |||
return buf.String() | |||
} | |||
// QuoteTo quotes string and writes into the buffer | |||
@@ -216,20 +207,30 @@ func (engine *Engine) QuoteTo(buf *builder.StringBuilder, value string) { | |||
return | |||
} | |||
if string(value[0]) == engine.dialect.QuoteStr() || value[0] == '`' { | |||
buf.WriteString(value) | |||
quotePair := engine.dialect.Quote("") | |||
if value[0] == '`' || len(quotePair) < 2 || value[0] == quotePair[0] { // no quote | |||
_, _ = buf.WriteString(value) | |||
return | |||
} else { | |||
prefix, suffix := quotePair[0], quotePair[1] | |||
_ = buf.WriteByte(prefix) | |||
for i := 0; i < len(value); i++ { | |||
if value[i] == '.' { | |||
_ = buf.WriteByte(suffix) | |||
_ = buf.WriteByte('.') | |||
_ = buf.WriteByte(prefix) | |||
} else { | |||
_ = buf.WriteByte(value[i]) | |||
} | |||
} | |||
_ = buf.WriteByte(suffix) | |||
} | |||
value = strings.Replace(value, ".", engine.dialect.QuoteStr()+"."+engine.dialect.QuoteStr(), -1) | |||
buf.WriteString(engine.dialect.QuoteStr()) | |||
buf.WriteString(value) | |||
buf.WriteString(engine.dialect.QuoteStr()) | |||
} | |||
func (engine *Engine) quote(sql string) string { | |||
return engine.dialect.QuoteStr() + sql + engine.dialect.QuoteStr() | |||
return engine.dialect.Quote(sql) | |||
} | |||
// SqlType will be deprecated, please use SQLType instead | |||
@@ -1581,7 +1582,7 @@ func (engine *Engine) formatColTime(col *core.Column, t time.Time) (v interface{ | |||
func (engine *Engine) formatTime(sqlTypeName string, t time.Time) (v interface{}) { | |||
switch sqlTypeName { | |||
case core.Time: | |||
s := t.Format("2006-01-02 15:04:05") //time.RFC3339 | |||
s := t.Format("2006-01-02 15:04:05") // time.RFC3339 | |||
v = s[11:19] | |||
case core.Date: | |||
v = t.Format("2006-01-02") |
@@ -15,5 +15,5 @@ require ( | |||
github.com/stretchr/testify v1.3.0 | |||
github.com/ziutek/mymysql v1.5.4 | |||
xorm.io/builder v0.3.5 | |||
xorm.io/core v0.6.3 | |||
xorm.io/core v0.7.0 | |||
) |
@@ -1,5 +1,4 @@ | |||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= | |||
cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg= | |||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= | |||
cloud.google.com/go v0.37.4 h1:glPeL3BQJsbF6aIIYfZizMwc5LTYz250bDMjttbBGAU= | |||
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= | |||
@@ -13,7 +12,6 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 | |||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= | |||
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= | |||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= | |||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= | |||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | |||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | |||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | |||
@@ -36,6 +34,7 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU | |||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= | |||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= | |||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | |||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | |||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= | |||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= | |||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= | |||
@@ -100,8 +99,9 @@ github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wK | |||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= | |||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= | |||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | |||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI= | |||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | |||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU= | |||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | |||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | |||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= | |||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= | |||
@@ -114,29 +114,38 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r | |||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | |||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | |||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= | |||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= | |||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | |||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | |||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | |||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= | |||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | |||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | |||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | |||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | |||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= | |||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | |||
golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= | |||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= | |||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= | |||
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= | |||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= | |||
google.golang.org/appengine v1.6.0 h1:Tfd7cKwKbFRsI8RMAD3oqqw7JPFRrvFlOsfbgVkjOOw= | |||
google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= | |||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= | |||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= | |||
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= | |||
@@ -155,5 +164,5 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh | |||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= | |||
xorm.io/builder v0.3.5 h1:EilU39fvWDxjb1cDaELpYhsF+zziRBhew8xk4pngO+A= | |||
xorm.io/builder v0.3.5/go.mod h1:ZFbByS/KxZI1FKRjL05PyJ4YrK2bcxlUaAxdum5aTR8= | |||
xorm.io/core v0.6.3 h1:n1NhVZt1s2oLw1BZfX2ocIJsHyso259uPgg63BGr37M= | |||
xorm.io/core v0.6.3/go.mod h1:8kz/C6arVW/O9vk3PgCiMJO2hIAm1UcuOL3dSPyZ2qo= | |||
xorm.io/core v0.7.0 h1:hKxuOKWZNeiFQsSuGet/KV8HZ788hclvAl+7azx3tkM= | |||
xorm.io/core v0.7.0/go.mod h1:TuOJjIVa7e3w/rN8tDcAvuLBMtwzdHPbyOzE6Gk1EUI= |
@@ -281,7 +281,7 @@ func rValue(bean interface{}) reflect.Value { | |||
func rType(bean interface{}) reflect.Type { | |||
sliceValue := reflect.Indirect(reflect.ValueOf(bean)) | |||
//return reflect.TypeOf(sliceValue.Interface()) | |||
// return reflect.TypeOf(sliceValue.Interface()) | |||
return sliceValue.Type() | |||
} | |||
@@ -309,3 +309,24 @@ func sliceEq(left, right []string) bool { | |||
func indexName(tableName, idxName string) string { | |||
return fmt.Sprintf("IDX_%v_%v", tableName, idxName) | |||
} | |||
func eraseAny(value string, strToErase ...string) string { | |||
if len(strToErase) == 0 { | |||
return value | |||
} | |||
var replaceSeq []string | |||
for _, s := range strToErase { | |||
replaceSeq = append(replaceSeq, s, "") | |||
} | |||
replacer := strings.NewReplacer(replaceSeq...) | |||
return replacer.Replace(value) | |||
} | |||
func quoteColumns(cols []string, quoteFunc func(string) string, sep string) string { | |||
for i := range cols { | |||
cols[i] = quoteFunc(cols[i]) | |||
} | |||
return strings.Join(cols, sep+" ") | |||
} |
@@ -63,6 +63,8 @@ func (session *Session) FindAndCount(rowsSlicePtr interface{}, condiBean ...inte | |||
} | |||
func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{}) error { | |||
defer session.resetStatement() | |||
if session.statement.lastError != nil { | |||
return session.statement.lastError | |||
} |
@@ -24,6 +24,8 @@ func (session *Session) Get(bean interface{}) (bool, error) { | |||
} | |||
func (session *Session) get(bean interface{}) (bool, error) { | |||
defer session.resetStatement() | |||
if session.statement.lastError != nil { | |||
return false, session.statement.lastError | |||
} | |||
@@ -75,6 +77,8 @@ func (session *Session) get(bean interface{}) (bool, error) { | |||
if context != nil { | |||
res := context.Get(fmt.Sprintf("%v-%v", sqlStr, args)) | |||
if res != nil { | |||
session.engine.logger.Debug("hit context cache", sqlStr) | |||
structValue := reflect.Indirect(reflect.ValueOf(bean)) | |||
structValue.Set(reflect.Indirect(reflect.ValueOf(res))) | |||
session.lastSQL = "" | |||
@@ -114,6 +118,114 @@ func (session *Session) nocacheGet(beanKind reflect.Kind, table *core.Table, bea | |||
return true, rows.Scan(&bean) | |||
case *sql.NullInt64, *sql.NullBool, *sql.NullFloat64, *sql.NullString: | |||
return true, rows.Scan(bean) | |||
case *string: | |||
var res sql.NullString | |||
if err := rows.Scan(&res); err != nil { | |||
return true, err | |||
} | |||
if res.Valid { | |||
*(bean.(*string)) = res.String | |||
} | |||
return true, nil | |||
case *int: | |||
var res sql.NullInt64 | |||
if err := rows.Scan(&res); err != nil { | |||
return true, err | |||
} | |||
if res.Valid { | |||
*(bean.(*int)) = int(res.Int64) | |||
} | |||
return true, nil | |||
case *int8: | |||
var res sql.NullInt64 | |||
if err := rows.Scan(&res); err != nil { | |||
return true, err | |||
} | |||
if res.Valid { | |||
*(bean.(*int8)) = int8(res.Int64) | |||
} | |||
return true, nil | |||
case *int16: | |||
var res sql.NullInt64 | |||
if err := rows.Scan(&res); err != nil { | |||
return true, err | |||
} | |||
if res.Valid { | |||
*(bean.(*int16)) = int16(res.Int64) | |||
} | |||
return true, nil | |||
case *int32: | |||
var res sql.NullInt64 | |||
if err := rows.Scan(&res); err != nil { | |||
return true, err | |||
} | |||
if res.Valid { | |||
*(bean.(*int32)) = int32(res.Int64) | |||
} | |||
return true, nil | |||
case *int64: | |||
var res sql.NullInt64 | |||
if err := rows.Scan(&res); err != nil { | |||
return true, err | |||
} | |||
if res.Valid { | |||
*(bean.(*int64)) = int64(res.Int64) | |||
} | |||
return true, nil | |||
case *uint: | |||
var res sql.NullInt64 | |||
if err := rows.Scan(&res); err != nil { | |||
return true, err | |||
} | |||
if res.Valid { | |||
*(bean.(*uint)) = uint(res.Int64) | |||
} | |||
return true, nil | |||
case *uint8: | |||
var res sql.NullInt64 | |||
if err := rows.Scan(&res); err != nil { | |||
return true, err | |||
} | |||
if res.Valid { | |||
*(bean.(*uint8)) = uint8(res.Int64) | |||
} | |||
return true, nil | |||
case *uint16: | |||
var res sql.NullInt64 | |||
if err := rows.Scan(&res); err != nil { | |||
return true, err | |||
} | |||
if res.Valid { | |||
*(bean.(*uint16)) = uint16(res.Int64) | |||
} | |||
return true, nil | |||
case *uint32: | |||
var res sql.NullInt64 | |||
if err := rows.Scan(&res); err != nil { | |||
return true, err | |||
} | |||
if res.Valid { | |||
*(bean.(*uint32)) = uint32(res.Int64) | |||
} | |||
return true, nil | |||
case *uint64: | |||
var res sql.NullInt64 | |||
if err := rows.Scan(&res); err != nil { | |||
return true, err | |||
} | |||
if res.Valid { | |||
*(bean.(*uint64)) = uint64(res.Int64) | |||
} | |||
return true, nil | |||
case *bool: | |||
var res sql.NullBool | |||
if err := rows.Scan(&res); err != nil { | |||
return true, err | |||
} | |||
if res.Valid { | |||
*(bean.(*bool)) = res.Bool | |||
} | |||
return true, nil | |||
} | |||
switch beanKind { | |||
@@ -142,6 +254,9 @@ func (session *Session) nocacheGet(beanKind reflect.Kind, table *core.Table, bea | |||
err = rows.ScanSlice(bean) | |||
case reflect.Map: | |||
err = rows.ScanMap(bean) | |||
case reflect.String, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, | |||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | |||
err = rows.Scan(bean) | |||
default: | |||
err = rows.Scan(bean) | |||
} |
@@ -12,6 +12,7 @@ import ( | |||
"strconv" | |||
"strings" | |||
"xorm.io/builder" | |||
"xorm.io/core" | |||
) | |||
@@ -242,23 +243,17 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error | |||
var sql string | |||
if session.engine.dialect.DBType() == core.ORACLE { | |||
temp := fmt.Sprintf(") INTO %s (%v%v%v) VALUES (", | |||
temp := fmt.Sprintf(") INTO %s (%v) VALUES (", | |||
session.engine.Quote(tableName), | |||
session.engine.QuoteStr(), | |||
strings.Join(colNames, session.engine.QuoteStr()+", "+session.engine.QuoteStr()), | |||
session.engine.QuoteStr()) | |||
sql = fmt.Sprintf("INSERT ALL INTO %s (%v%v%v) VALUES (%v) SELECT 1 FROM DUAL", | |||
quoteColumns(colNames, session.engine.Quote, ",")) | |||
sql = fmt.Sprintf("INSERT ALL INTO %s (%v) VALUES (%v) SELECT 1 FROM DUAL", | |||
session.engine.Quote(tableName), | |||
session.engine.QuoteStr(), | |||
strings.Join(colNames, session.engine.QuoteStr()+", "+session.engine.QuoteStr()), | |||
session.engine.QuoteStr(), | |||
quoteColumns(colNames, session.engine.Quote, ","), | |||
strings.Join(colMultiPlaces, temp)) | |||
} else { | |||
sql = fmt.Sprintf("INSERT INTO %s (%v%v%v) VALUES (%v)", | |||
sql = fmt.Sprintf("INSERT INTO %s (%v) VALUES (%v)", | |||
session.engine.Quote(tableName), | |||
session.engine.QuoteStr(), | |||
strings.Join(colNames, session.engine.QuoteStr()+", "+session.engine.QuoteStr()), | |||
session.engine.QuoteStr(), | |||
quoteColumns(colNames, session.engine.Quote, ","), | |||
strings.Join(colMultiPlaces, "),(")) | |||
} | |||
res, err := session.exec(sql, args...) | |||
@@ -351,7 +346,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) { | |||
for _, v := range exprColumns { | |||
// remove the expr columns | |||
for i, colName := range colNames { | |||
if colName == v.colName { | |||
if colName == strings.Trim(v.colName, "`") { | |||
colNames = append(colNames[:i], colNames[i+1:]...) | |||
args = append(args[:i], args[i+1:]...) | |||
} | |||
@@ -377,14 +372,30 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) { | |||
if session.engine.dialect.DBType() == core.MSSQL && len(table.AutoIncrement) > 0 { | |||
output = fmt.Sprintf(" OUTPUT Inserted.%s", table.AutoIncrement) | |||
} | |||
if len(colPlaces) > 0 { | |||
sqlStr = fmt.Sprintf("INSERT INTO %s (%v%v%v)%s VALUES (%v)", | |||
session.engine.Quote(tableName), | |||
session.engine.QuoteStr(), | |||
strings.Join(colNames, session.engine.Quote(", ")), | |||
session.engine.QuoteStr(), | |||
output, | |||
colPlaces) | |||
if session.statement.cond.IsValid() { | |||
condSQL, condArgs, err := builder.ToSQL(session.statement.cond) | |||
if err != nil { | |||
return 0, err | |||
} | |||
sqlStr = fmt.Sprintf("INSERT INTO %s (%v)%s SELECT %v FROM %v WHERE %v", | |||
session.engine.Quote(tableName), | |||
quoteColumns(colNames, session.engine.Quote, ","), | |||
output, | |||
colPlaces, | |||
session.engine.Quote(tableName), | |||
condSQL, | |||
) | |||
args = append(args, condArgs...) | |||
} else { | |||
sqlStr = fmt.Sprintf("INSERT INTO %s (%v)%s VALUES (%v)", | |||
session.engine.Quote(tableName), | |||
quoteColumns(colNames, session.engine.Quote, ","), | |||
output, | |||
colPlaces) | |||
} | |||
} else { | |||
if session.engine.dialect.DBType() == core.MYSQL { | |||
sqlStr = fmt.Sprintf("INSERT INTO %s VALUES ()", session.engine.Quote(tableName)) | |||
@@ -671,6 +682,11 @@ func (session *Session) insertMapInterface(m map[string]interface{}) (int64, err | |||
return 0, ErrParamsType | |||
} | |||
tableName := session.statement.TableName() | |||
if len(tableName) <= 0 { | |||
return 0, ErrTableNotFound | |||
} | |||
var columns = make([]string, 0, len(m)) | |||
for k := range m { | |||
columns = append(columns, k) | |||
@@ -678,19 +694,40 @@ func (session *Session) insertMapInterface(m map[string]interface{}) (int64, err | |||
sort.Strings(columns) | |||
qm := strings.Repeat("?,", len(columns)) | |||
qm = "(" + qm[:len(qm)-1] + ")" | |||
tableName := session.statement.TableName() | |||
if len(tableName) <= 0 { | |||
return 0, ErrTableNotFound | |||
} | |||
var sql = fmt.Sprintf("INSERT INTO %s (`%s`) VALUES %s", session.engine.Quote(tableName), strings.Join(columns, "`,`"), qm) | |||
var args = make([]interface{}, 0, len(m)) | |||
for _, colName := range columns { | |||
args = append(args, m[colName]) | |||
} | |||
// insert expr columns, override if exists | |||
exprColumns := session.statement.getExpr() | |||
for _, col := range exprColumns { | |||
columns = append(columns, strings.Trim(col.colName, "`")) | |||
qm = qm + col.expr + "," | |||
} | |||
qm = qm[:len(qm)-1] | |||
var sql string | |||
if session.statement.cond.IsValid() { | |||
condSQL, condArgs, err := builder.ToSQL(session.statement.cond) | |||
if err != nil { | |||
return 0, err | |||
} | |||
sql = fmt.Sprintf("INSERT INTO %s (`%s`) SELECT %s FROM %s WHERE %s", | |||
session.engine.Quote(tableName), | |||
strings.Join(columns, "`,`"), | |||
qm, | |||
session.engine.Quote(tableName), | |||
condSQL, | |||
) | |||
args = append(args, condArgs...) | |||
} else { | |||
sql = fmt.Sprintf("INSERT INTO %s (`%s`) VALUES (%s)", session.engine.Quote(tableName), strings.Join(columns, "`,`"), qm) | |||
} | |||
if err := session.cacheInsert(tableName); err != nil { | |||
return 0, err | |||
} | |||
@@ -711,24 +748,51 @@ func (session *Session) insertMapString(m map[string]string) (int64, error) { | |||
return 0, ErrParamsType | |||
} | |||
tableName := session.statement.TableName() | |||
if len(tableName) <= 0 { | |||
return 0, ErrTableNotFound | |||
} | |||
var columns = make([]string, 0, len(m)) | |||
for k := range m { | |||
columns = append(columns, k) | |||
} | |||
sort.Strings(columns) | |||
var args = make([]interface{}, 0, len(m)) | |||
for _, colName := range columns { | |||
args = append(args, m[colName]) | |||
} | |||
qm := strings.Repeat("?,", len(columns)) | |||
qm = "(" + qm[:len(qm)-1] + ")" | |||
tableName := session.statement.TableName() | |||
if len(tableName) <= 0 { | |||
return 0, ErrTableNotFound | |||
// insert expr columns, override if exists | |||
exprColumns := session.statement.getExpr() | |||
for _, col := range exprColumns { | |||
columns = append(columns, strings.Trim(col.colName, "`")) | |||
qm = qm + col.expr + "," | |||
} | |||
var sql = fmt.Sprintf("INSERT INTO %s (`%s`) VALUES %s", session.engine.Quote(tableName), strings.Join(columns, "`,`"), qm) | |||
var args = make([]interface{}, 0, len(m)) | |||
for _, colName := range columns { | |||
args = append(args, m[colName]) | |||
qm = qm[:len(qm)-1] | |||
var sql string | |||
if session.statement.cond.IsValid() { | |||
qm = "(" + qm[:len(qm)-1] + ")" | |||
condSQL, condArgs, err := builder.ToSQL(session.statement.cond) | |||
if err != nil { | |||
return 0, err | |||
} | |||
sql = fmt.Sprintf("INSERT INTO %s (`%s`) SELECT %s FROM %s WHERE %s", | |||
session.engine.Quote(tableName), | |||
strings.Join(columns, "`,`"), | |||
qm, | |||
session.engine.Quote(tableName), | |||
condSQL, | |||
) | |||
args = append(args, condArgs...) | |||
} else { | |||
sql = fmt.Sprintf("INSERT INTO %s (`%s`) VALUES (%s)", session.engine.Quote(tableName), strings.Join(columns, "`,`"), qm) | |||
} | |||
if err := session.cacheInsert(tableName); err != nil { |
@@ -96,14 +96,15 @@ func (session *Session) cacheUpdate(table *core.Table, tableName, sqlStr string, | |||
return ErrCacheFailed | |||
} | |||
kvs := strings.Split(strings.TrimSpace(sqls[1]), ",") | |||
for idx, kv := range kvs { | |||
sps := strings.SplitN(kv, "=", 2) | |||
sps2 := strings.Split(sps[0], ".") | |||
colName := sps2[len(sps2)-1] | |||
if strings.Contains(colName, "`") { | |||
colName = strings.TrimSpace(strings.Replace(colName, "`", "", -1)) | |||
} else if strings.Contains(colName, session.engine.QuoteStr()) { | |||
colName = strings.TrimSpace(strings.Replace(colName, session.engine.QuoteStr(), "", -1)) | |||
// treat quote prefix, suffix and '`' as quotes | |||
quotes := append(strings.Split(session.engine.Quote(""), ""), "`") | |||
if strings.ContainsAny(colName, strings.Join(quotes, "")) { | |||
colName = strings.TrimSpace(eraseAny(colName, quotes...)) | |||
} else { | |||
session.engine.logger.Debug("[cacheUpdate] cannot find column", tableName, colName) | |||
return ErrCacheFailed | |||
@@ -221,19 +222,19 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 | |||
} | |||
} | |||
//for update action to like "column = column + ?" | |||
// for update action to like "column = column + ?" | |||
incColumns := session.statement.getInc() | |||
for _, v := range incColumns { | |||
colNames = append(colNames, session.engine.Quote(v.colName)+" = "+session.engine.Quote(v.colName)+" + ?") | |||
args = append(args, v.arg) | |||
} | |||
//for update action to like "column = column - ?" | |||
// for update action to like "column = column - ?" | |||
decColumns := session.statement.getDec() | |||
for _, v := range decColumns { | |||
colNames = append(colNames, session.engine.Quote(v.colName)+" = "+session.engine.Quote(v.colName)+" - ?") | |||
args = append(args, v.arg) | |||
} | |||
//for update action to like "column = expression" | |||
// for update action to like "column = expression" | |||
exprColumns := session.statement.getExpr() | |||
for _, v := range exprColumns { | |||
colNames = append(colNames, session.engine.Quote(v.colName)+" = "+v.expr) | |||
@@ -382,7 +383,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 | |||
} | |||
if cacher := session.engine.getCacher(tableName); cacher != nil && session.statement.UseCache { | |||
//session.cacheUpdate(table, tableName, sqlStr, args...) | |||
// session.cacheUpdate(table, tableName, sqlStr, args...) | |||
session.engine.logger.Debug("[cacheUpdate] clear table ", tableName) | |||
cacher.ClearIds(tableName) | |||
cacher.ClearBeans(tableName) |
@@ -6,7 +6,6 @@ package xorm | |||
import ( | |||
"database/sql/driver" | |||
"errors" | |||
"fmt" | |||
"reflect" | |||
"strings" | |||
@@ -398,7 +397,7 @@ func (statement *Statement) buildUpdates(bean interface{}, | |||
continue | |||
} | |||
} else { | |||
//TODO: how to handler? | |||
// TODO: how to handler? | |||
panic("not supported") | |||
} | |||
} else { | |||
@@ -579,21 +578,9 @@ func (statement *Statement) getExpr() map[string]exprParam { | |||
func (statement *Statement) col2NewColsWithQuote(columns ...string) []string { | |||
newColumns := make([]string, 0) | |||
quotes := append(strings.Split(statement.Engine.Quote(""), ""), "`") | |||
for _, col := range columns { | |||
col = strings.Replace(col, "`", "", -1) | |||
col = strings.Replace(col, statement.Engine.QuoteStr(), "", -1) | |||
ccols := strings.Split(col, ",") | |||
for _, c := range ccols { | |||
fields := strings.Split(strings.TrimSpace(c), ".") | |||
if len(fields) == 1 { | |||
newColumns = append(newColumns, statement.Engine.quote(fields[0])) | |||
} else if len(fields) == 2 { | |||
newColumns = append(newColumns, statement.Engine.quote(fields[0])+"."+ | |||
statement.Engine.quote(fields[1])) | |||
} else { | |||
panic(errors.New("unwanted colnames")) | |||
} | |||
} | |||
newColumns = append(newColumns, statement.Engine.Quote(eraseAny(col, quotes...))) | |||
} | |||
return newColumns | |||
} | |||
@@ -764,7 +751,9 @@ func (statement *Statement) Join(joinOP string, tablename interface{}, condition | |||
return statement | |||
} | |||
tbs := strings.Split(tp.TableName(), ".") | |||
var aliasName = strings.Trim(tbs[len(tbs)-1], statement.Engine.QuoteStr()) | |||
quotes := append(strings.Split(statement.Engine.Quote(""), ""), "`") | |||
var aliasName = strings.Trim(tbs[len(tbs)-1], strings.Join(quotes, "")) | |||
fmt.Fprintf(&buf, "(%s) %s ON %v", subSQL, aliasName, condition) | |||
statement.joinArgs = append(statement.joinArgs, subQueryArgs...) | |||
case *builder.Builder: | |||
@@ -774,7 +763,9 @@ func (statement *Statement) Join(joinOP string, tablename interface{}, condition | |||
return statement | |||
} | |||
tbs := strings.Split(tp.TableName(), ".") | |||
var aliasName = strings.Trim(tbs[len(tbs)-1], statement.Engine.QuoteStr()) | |||
quotes := append(strings.Split(statement.Engine.Quote(""), ""), "`") | |||
var aliasName = strings.Trim(tbs[len(tbs)-1], strings.Join(quotes, "")) | |||
fmt.Fprintf(&buf, "(%s) %s ON %v", subSQL, aliasName, condition) | |||
statement.joinArgs = append(statement.joinArgs, subQueryArgs...) | |||
default: | |||
@@ -1157,8 +1148,12 @@ func (statement *Statement) genSelectSQL(columnStr, condSQL string, needLimit, n | |||
if statement.Start != 0 || statement.LimitN != 0 { | |||
oldString := buf.String() | |||
buf.Reset() | |||
rawColStr := columnStr | |||
if rawColStr == "*" { | |||
rawColStr = "at.*" | |||
} | |||
fmt.Fprintf(&buf, "SELECT %v FROM (SELECT %v,ROWNUM RN FROM (%v) at WHERE ROWNUM <= %d) aat WHERE RN > %d", | |||
columnStr, columnStr, oldString, statement.Start+statement.LimitN, statement.Start) | |||
columnStr, rawColStr, oldString, statement.Start+statement.LimitN, statement.Start) | |||
} | |||
} | |||
} | |||
@@ -1242,7 +1237,7 @@ func (statement *Statement) convertUpdateSQL(sqlStr string) (string, string) { | |||
var whereStr = sqls[1] | |||
//TODO: for postgres only, if any other database? | |||
// TODO: for postgres only, if any other database? | |||
var paraStr string | |||
if statement.Engine.dialect.DBType() == core.POSTGRES { | |||
paraStr = "$" |
@@ -148,7 +148,7 @@ github.com/go-redis/redis/internal/proto | |||
github.com/go-redis/redis/internal/util | |||
# github.com/go-sql-driver/mysql v1.4.1 | |||
github.com/go-sql-driver/mysql | |||
# github.com/go-xorm/xorm v0.7.4 | |||
# github.com/go-xorm/xorm v0.7.7-0.20190822154023-17592d96b35b | |||
github.com/go-xorm/xorm | |||
# github.com/gogits/chardet v0.0.0-20150115103509-2404f7772561 | |||
github.com/gogits/chardet | |||
@@ -482,5 +482,5 @@ mvdan.cc/xurls/v2 | |||
strk.kbt.io/projects/go/libravatar | |||
# xorm.io/builder v0.3.5 | |||
xorm.io/builder | |||
# xorm.io/core v0.6.3 | |||
# xorm.io/core v0.7.0 | |||
xorm.io/core |
@@ -0,0 +1,42 @@ | |||
workspace: | |||
base: /go | |||
path: src/xorm.io/core | |||
clone: | |||
git: | |||
image: plugins/git:next | |||
depth: 50 | |||
tags: true | |||
matrix: | |||
GO_VERSION: | |||
- 1.9 | |||
- 1.10 | |||
- 1.11 | |||
- 1.12 | |||
pipeline: | |||
test: | |||
image: golang:${GO_VERSION} | |||
environment: | |||
GOPROXY: https://goproxy.cn | |||
commands: | |||
- go get -u golang.org/x/lint/golint | |||
- go get -u github.com/stretchr/testify/assert | |||
- go get -u github.com/go-xorm/sqlfiddle | |||
- go get -u github.com/go-sql-driver/mysql | |||
- go get -u 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: | |||
mysql: | |||
image: mysql:5.7 | |||
environment: | |||
- MYSQL_DATABASE=core_test | |||
- MYSQL_ALLOW_EMPTY_PASSWORD=yes | |||
when: | |||
event: [ push, tag, pull_request ] |
@@ -1,6 +1,8 @@ | |||
Core is a lightweight wrapper of sql.DB. | |||
[![CircleCI](https://circleci.com/gh/go-xorm/core/tree/master.svg?style=svg)](https://circleci.com/gh/go-xorm/core/tree/master) | |||
[![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) | |||
[![Go Report Card](https://goreportcard.com/badge/code.gitea.io/gitea)](https://goreportcard.com/report/xorm.io/core) | |||
# Open | |||
```Go |
@@ -14,19 +14,20 @@ import ( | |||
) | |||
const ( | |||
// default cache expired time | |||
// CacheExpired is default cache expired time | |||
CacheExpired = 60 * time.Minute | |||
// not use now | |||
// CacheMaxMemory is not use now | |||
CacheMaxMemory = 256 | |||
// evey ten minutes to clear all expired nodes | |||
// CacheGcInterval represents interval time to clear all expired nodes | |||
CacheGcInterval = 10 * time.Minute | |||
// each time when gc to removed max nodes | |||
// CacheGcMaxRemoved represents max nodes removed when gc | |||
CacheGcMaxRemoved = 20 | |||
) | |||
// list all the errors | |||
var ( | |||
ErrCacheMiss = errors.New("xorm/cache: key not found.") | |||
ErrNotStored = errors.New("xorm/cache: not stored.") | |||
ErrCacheMiss = errors.New("xorm/cache: key not found") | |||
ErrNotStored = errors.New("xorm/cache: not stored") | |||
) | |||
// CacheStore is a interface to store cache | |||
@@ -69,6 +70,7 @@ func decodeIds(s string) ([]PK, error) { | |||
return pks, err | |||
} | |||
// GetCacheSql returns cacher PKs via SQL | |||
func GetCacheSql(m Cacher, tableName, sql string, args interface{}) ([]PK, error) { | |||
bytes := m.GetIds(tableName, GenSqlKey(sql, args)) | |||
if bytes == nil { | |||
@@ -77,6 +79,7 @@ func GetCacheSql(m Cacher, tableName, sql string, args interface{}) ([]PK, error | |||
return decodeIds(bytes.(string)) | |||
} | |||
// PutCacheSql puts cacher SQL and PKs | |||
func PutCacheSql(m Cacher, ids []PK, tableName, sql string, args interface{}) error { | |||
bytes, err := encodeIds(ids) | |||
if err != nil { | |||
@@ -86,6 +89,7 @@ func PutCacheSql(m Cacher, ids []PK, tableName, sql string, args interface{}) er | |||
return nil | |||
} | |||
// GenSqlKey generates cache key | |||
func GenSqlKey(sql string, args interface{}) string { | |||
return fmt.Sprintf("%v-%v", sql, args) | |||
} |
@@ -73,7 +73,7 @@ func NewColumn(name, fieldName string, sqlType SQLType, len1, len2 int, nullable | |||
// String generate column description string according dialect | |||
func (col *Column) String(d Dialect) string { | |||
sql := d.QuoteStr() + col.Name + d.QuoteStr() + " " | |||
sql := d.Quote(col.Name) + " " | |||
sql += d.SqlType(col) + " " | |||
@@ -101,7 +101,7 @@ func (col *Column) String(d Dialect) string { | |||
// StringNoPk generate column description string according dialect without primary keys | |||
func (col *Column) StringNoPk(d Dialect) string { | |||
sql := d.QuoteStr() + col.Name + d.QuoteStr() + " " | |||
sql := d.Quote(col.Name) + " " | |||
sql += d.SqlType(col) + " " | |||
@@ -15,6 +15,7 @@ import ( | |||
) | |||
var ( | |||
// DefaultCacheSize sets the default cache size | |||
DefaultCacheSize = 200 | |||
) | |||
@@ -132,6 +133,7 @@ func (db *DB) Query(query string, args ...interface{}) (*Rows, error) { | |||
return db.QueryContext(context.Background(), query, args...) | |||
} | |||
// QueryMapContext executes query with parameters via map and context | |||
func (db *DB) QueryMapContext(ctx context.Context, query string, mp interface{}) (*Rows, error) { | |||
query, args, err := MapToSlice(query, mp) | |||
if err != nil { | |||
@@ -140,6 +142,7 @@ func (db *DB) QueryMapContext(ctx context.Context, query string, mp interface{}) | |||
return db.QueryContext(ctx, query, args...) | |||
} | |||
// QueryMap executes query with parameters via map | |||
func (db *DB) QueryMap(query string, mp interface{}) (*Rows, error) { | |||
return db.QueryMapContext(context.Background(), query, mp) | |||
} | |||
@@ -196,6 +199,7 @@ var ( | |||
re = regexp.MustCompile(`[?](\w+)`) | |||
) | |||
// ExecMapContext exec map with context.Context | |||
// insert into (name) values (?) | |||
// insert into (name) values (?name) | |||
func (db *DB) ExecMapContext(ctx context.Context, query string, mp interface{}) (sql.Result, error) { |
@@ -40,9 +40,9 @@ type Dialect interface { | |||
DriverName() string | |||
DataSourceName() string | |||
QuoteStr() string | |||
IsReserved(string) bool | |||
Quote(string) string | |||
AndStr() string | |||
OrStr() string | |||
EqStr() string | |||
@@ -70,8 +70,8 @@ type Dialect interface { | |||
ForUpdateSql(query string) string | |||
//CreateTableIfNotExists(table *Table, tableName, storeEngine, charset string) error | |||
//MustDropTable(tableName string) error | |||
// CreateTableIfNotExists(table *Table, tableName, storeEngine, charset string) error | |||
// MustDropTable(tableName string) error | |||
GetColumns(tableName string) ([]string, map[string]*Column, error) | |||
GetTables() ([]*Table, error) | |||
@@ -85,6 +85,7 @@ func OpenDialect(dialect Dialect) (*DB, error) { | |||
return Open(dialect.DriverName(), dialect.DataSourceName()) | |||
} | |||
// Base represents a basic dialect and all real dialects could embed this struct | |||
type Base struct { | |||
db *DB | |||
dialect Dialect | |||
@@ -172,8 +173,15 @@ func (db *Base) HasRecords(query string, args ...interface{}) (bool, error) { | |||
} | |||
func (db *Base) IsColumnExist(tableName, colName string) (bool, error) { | |||
query := "SELECT `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? AND `COLUMN_NAME` = ?" | |||
query = strings.Replace(query, "`", db.dialect.QuoteStr(), -1) | |||
query := fmt.Sprintf( | |||
"SELECT %v FROM %v.%v WHERE %v = ? AND %v = ? AND %v = ?", | |||
db.dialect.Quote("COLUMN_NAME"), | |||
db.dialect.Quote("INFORMATION_SCHEMA"), | |||
db.dialect.Quote("COLUMNS"), | |||
db.dialect.Quote("TABLE_SCHEMA"), | |||
db.dialect.Quote("TABLE_NAME"), | |||
db.dialect.Quote("COLUMN_NAME"), | |||
) | |||
return db.HasRecords(query, db.DbName, tableName, colName) | |||
} | |||
@@ -310,7 +318,7 @@ func RegisterDialect(dbName DbType, dialectFunc func() Dialect) { | |||
dialects[strings.ToLower(string(dbName))] = dialectFunc // !nashtsai! allow override dialect | |||
} | |||
// QueryDialect query if registed database dialect | |||
// QueryDialect query if registered database dialect | |||
func QueryDialect(dbName DbType) Dialect { | |||
if d, ok := dialects[strings.ToLower(string(dbName))]; ok { | |||
return d() |
@@ -7,6 +7,8 @@ package core | |||
import "errors" | |||
var ( | |||
ErrNoMapPointer = errors.New("mp should be a map's pointer") | |||
// ErrNoMapPointer represents error when no map pointer | |||
ErrNoMapPointer = errors.New("mp should be a map's pointer") | |||
// ErrNoStructPointer represents error when no struct pointer | |||
ErrNoStructPointer = errors.New("mp should be a struct's pointer") | |||
) |
@@ -19,7 +19,23 @@ type QuoteFilter struct { | |||
} | |||
func (s *QuoteFilter) Do(sql string, dialect Dialect, table *Table) string { | |||
return strings.Replace(sql, "`", dialect.QuoteStr(), -1) | |||
dummy := dialect.Quote("") | |||
if len(dummy) != 2 { | |||
return sql | |||
} | |||
prefix, suffix := dummy[0], dummy[1] | |||
raw := []byte(sql) | |||
for i, cnt := 0, 0; i < len(raw); i = i + 1 { | |||
if raw[i] == '`' { | |||
if cnt%2 == 0 { | |||
raw[i] = prefix | |||
} else { | |||
raw[i] = suffix | |||
} | |||
cnt++ | |||
} | |||
} | |||
return string(raw) | |||
} | |||
// IdFilter filter SQL replace (id) to primary key column name | |||
@@ -35,7 +51,7 @@ func NewQuoter(dialect Dialect) *Quoter { | |||
} | |||
func (q *Quoter) Quote(content string) string { | |||
return q.dialect.QuoteStr() + content + q.dialect.QuoteStr() | |||
return q.dialect.Quote(content) | |||
} | |||
func (i *IdFilter) Do(sql string, dialect Dialect, table *Table) string { |
@@ -2,6 +2,12 @@ module xorm.io/core | |||
require ( | |||
github.com/go-sql-driver/mysql v1.4.1 | |||
github.com/golang/protobuf v1.3.1 // indirect | |||
github.com/mattn/go-sqlite3 v1.10.0 | |||
google.golang.org/appengine v1.4.0 // indirect | |||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 // indirect | |||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65 // indirect | |||
golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed // indirect | |||
golang.org/x/text v0.3.2 // indirect | |||
golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468 // indirect | |||
google.golang.org/appengine v1.6.0 // indirect | |||
) |
@@ -1,9 +1,23 @@ | |||
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= | |||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= | |||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | |||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | |||
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o= | |||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= | |||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | |||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | |||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | |||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | |||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= | |||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | |||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= | |||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | |||
golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= | |||
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= | |||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= | |||
google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= |
@@ -4,8 +4,10 @@ | |||
package core | |||
// LogLevel defines a log level | |||
type LogLevel int | |||
// enumerate all LogLevels | |||
const ( | |||
// !nashtsai! following level also match syslog.Priority value | |||
LOG_DEBUG LogLevel = iota | |||
@@ -16,7 +18,7 @@ const ( | |||
LOG_UNKNOWN | |||
) | |||
// logger interface | |||
// ILogger is a logger interface | |||
type ILogger interface { | |||
Debug(v ...interface{}) | |||
Debugf(format string, v ...interface{}) |
@@ -9,12 +9,13 @@ import ( | |||
"strings" | |||
) | |||
// enumerate all index types | |||
const ( | |||
IndexType = iota + 1 | |||
UniqueType | |||
) | |||
// database index | |||
// Index represents a database index | |||
type Index struct { | |||
IsRegular bool | |||
Name string | |||
@@ -35,7 +36,7 @@ func (index *Index) XName(tableName string) string { | |||
return index.Name | |||
} | |||
// add columns which will be composite index | |||
// AddColumn add columns which will be composite index | |||
func (index *Index) AddColumn(cols ...string) { | |||
for _, col := range cols { | |||
index.Cols = append(index.Cols, col) | |||
@@ -65,7 +66,7 @@ func (index *Index) Equal(dst *Index) bool { | |||
return true | |||
} | |||
// new an index | |||
// NewIndex new an index object | |||
func NewIndex(name string, indexType int) *Index { | |||
return &Index{true, name, indexType, make([]string, 0)} | |||
} |
@@ -9,7 +9,7 @@ import ( | |||
"sync" | |||
) | |||
// name translation between struct, fields names and table, column names | |||
// IMapper represents a name convertation between struct's fields name and table's column name | |||
type IMapper interface { | |||
Obj2Table(string) string | |||
Table2Obj(string) string | |||
@@ -184,7 +184,7 @@ func (mapper GonicMapper) Table2Obj(name string) string { | |||
return string(newstr) | |||
} | |||
// A GonicMapper that contains a list of common initialisms taken from golang/lint | |||
// LintGonicMapper is A GonicMapper that contains a list of common initialisms taken from golang/lint | |||
var LintGonicMapper = GonicMapper{ | |||
"API": true, | |||
"ASCII": true, | |||
@@ -221,7 +221,7 @@ var LintGonicMapper = GonicMapper{ | |||
"XSS": true, | |||
} | |||
// provide prefix table name support | |||
// PrefixMapper provides prefix table name support | |||
type PrefixMapper struct { | |||
Mapper IMapper | |||
Prefix string | |||
@@ -239,7 +239,7 @@ func NewPrefixMapper(mapper IMapper, prefix string) PrefixMapper { | |||
return PrefixMapper{mapper, prefix} | |||
} | |||
// provide suffix table name support | |||
// SuffixMapper provides suffix table name support | |||
type SuffixMapper struct { | |||
Mapper IMapper | |||
Suffix string |
@@ -170,7 +170,7 @@ func (rs *Rows) ScanMap(dest interface{}) error { | |||
newDest := make([]interface{}, len(cols)) | |||
vvv := vv.Elem() | |||
for i, _ := range cols { | |||
for i := range cols { | |||
newDest[i] = rs.db.reflectNew(vvv.Type().Elem()).Interface() | |||
} | |||
@@ -11,6 +11,7 @@ import ( | |||
"reflect" | |||
) | |||
// Stmt reprents a stmt objects | |||
type Stmt struct { | |||
*sql.Stmt | |||
db *DB |
@@ -9,7 +9,7 @@ import ( | |||
"strings" | |||
) | |||
// database table | |||
// Table represents a database table | |||
type Table struct { | |||
Name string | |||
Type reflect.Type | |||
@@ -41,6 +41,7 @@ func NewEmptyTable() *Table { | |||
return NewTable("", nil) | |||
} | |||
// NewTable creates a new Table object | |||
func NewTable(name string, t reflect.Type) *Table { | |||
return &Table{Name: name, Type: t, | |||
columnsSeq: make([]string, 0), | |||
@@ -87,7 +88,7 @@ func (table *Table) GetColumnIdx(name string, idx int) *Column { | |||
return nil | |||
} | |||
// if has primary key, return column | |||
// PKColumns reprents all primary key columns | |||
func (table *Table) PKColumns() []*Column { | |||
columns := make([]*Column, len(table.PrimaryKeys)) | |||
for i, name := range table.PrimaryKeys { | |||
@@ -117,7 +118,7 @@ func (table *Table) DeletedColumn() *Column { | |||
return table.GetColumn(table.Deleted) | |||
} | |||
// add a column to table | |||
// AddColumn adds a column to table | |||
func (table *Table) AddColumn(col *Column) { | |||
table.columnsSeq = append(table.columnsSeq, col.Name) | |||
table.columns = append(table.columns, col) | |||
@@ -148,7 +149,7 @@ func (table *Table) AddColumn(col *Column) { | |||
} | |||
} | |||
// add an index or an unique to table | |||
// AddIndex adds an index or an unique to table | |||
func (table *Table) AddIndex(index *Index) { | |||
table.Indexes[index.Name] = index | |||
} |
@@ -87,16 +87,16 @@ var ( | |||
UniqueIdentifier = "UNIQUEIDENTIFIER" | |||
SysName = "SYSNAME" | |||
Date = "DATE" | |||
DateTime = "DATETIME" | |||
SmallDateTime = "SMALLDATETIME" | |||
Time = "TIME" | |||
TimeStamp = "TIMESTAMP" | |||
TimeStampz = "TIMESTAMPZ" | |||
Decimal = "DECIMAL" | |||
Numeric = "NUMERIC" | |||
Money = "MONEY" | |||
Date = "DATE" | |||
DateTime = "DATETIME" | |||
SmallDateTime = "SMALLDATETIME" | |||
Time = "TIME" | |||
TimeStamp = "TIMESTAMP" | |||
TimeStampz = "TIMESTAMPZ" | |||
Decimal = "DECIMAL" | |||
Numeric = "NUMERIC" | |||
Money = "MONEY" | |||
SmallMoney = "SMALLMONEY" | |||
Real = "REAL" | |||
@@ -147,19 +147,19 @@ var ( | |||
Clob: TEXT_TYPE, | |||
SysName: TEXT_TYPE, | |||
Date: TIME_TYPE, | |||
DateTime: TIME_TYPE, | |||
Time: TIME_TYPE, | |||
TimeStamp: TIME_TYPE, | |||
TimeStampz: TIME_TYPE, | |||
SmallDateTime: TIME_TYPE, | |||
Decimal: NUMERIC_TYPE, | |||
Numeric: NUMERIC_TYPE, | |||
Real: NUMERIC_TYPE, | |||
Float: NUMERIC_TYPE, | |||
Double: NUMERIC_TYPE, | |||
Money: NUMERIC_TYPE, | |||
Date: TIME_TYPE, | |||
DateTime: TIME_TYPE, | |||
Time: TIME_TYPE, | |||
TimeStamp: TIME_TYPE, | |||
TimeStampz: TIME_TYPE, | |||
SmallDateTime: TIME_TYPE, | |||
Decimal: NUMERIC_TYPE, | |||
Numeric: NUMERIC_TYPE, | |||
Real: NUMERIC_TYPE, | |||
Float: NUMERIC_TYPE, | |||
Double: NUMERIC_TYPE, | |||
Money: NUMERIC_TYPE, | |||
SmallMoney: NUMERIC_TYPE, | |||
Binary: BLOB_TYPE, |