diff --git a/.drone.yml b/.drone.yml index b162d7c8a..61da41694 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,6 +1,6 @@ --- kind: pipeline -name: matrix-1 +name: go1.10 platform: os: linux @@ -21,13 +21,6 @@ steps: 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 @@ -48,6 +41,8 @@ steps: - 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" + - "go test -v -race -db=\"sqlite3\" -conn_str=\"./test.db\" -col_quote=reserved -coverprofile=coverage1-3.txt -covermode=atomic" + - "go test -v -race -db=\"sqlite3\" -conn_str=\"./test.db\" -col_quote=reserved -cache=true -coverprofile=coverage1-4.txt -covermode=atomic" when: event: - push @@ -59,6 +54,8 @@ steps: 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" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test\" -col_quote=reserved -coverprofile=coverage2-3.txt -covermode=atomic" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test\" -col_quote=reserved -cache=true -coverprofile=coverage2-4.txt -covermode=atomic" when: event: - push @@ -70,6 +67,8 @@ steps: 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" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test?charset=utf8mb4\" -col_quote=reserved -coverprofile=coverage2.1-3.txt -covermode=atomic" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test?charset=utf8mb4\" -col_quote=reserved -cache=true -coverprofile=coverage2.1-4.txt -covermode=atomic" when: event: - push @@ -81,6 +80,8 @@ steps: 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" + - "go test -v -race -db=\"mymysql\" -conn_str=\"tcp:mysql:3306*xorm_test/root/\" -col_quote=reserved -coverprofile=coverage3-3.txt -covermode=atomic" + - "go test -v -race -db=\"mymysql\" -conn_str=\"tcp:mysql:3306*xorm_test/root/\" -col_quote=reserved -cache=true -coverprofile=coverage3-4.txt -covermode=atomic" when: event: - push @@ -92,6 +93,8 @@ steps: 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" + - "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -col_quote=reserved -coverprofile=coverage4-3.txt -covermode=atomic" + - "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -col_quote=reserved -cache=true -coverprofile=coverage4-4.txt -covermode=atomic" when: event: - push @@ -103,6 +106,8 @@ steps: 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" + - "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -col_quote=reserved -schema=xorm -coverprofile=coverage5-3.txt -covermode=atomic" + - "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -col_quote=reserved -schema=xorm -cache=true -coverprofile=coverage5-4.txt -covermode=atomic" when: event: - push @@ -114,6 +119,8 @@ steps: commands: - "go test -v -race -db=\"mssql\" -conn_str=\"server=mssql;user id=sa;password=yourStrong(!)Password;database=xorm_test\" -coverprofile=coverage6-1.txt -covermode=atomic" - "go test -v -race -db=\"mssql\" -conn_str=\"server=mssql;user id=sa;password=yourStrong(!)Password;database=xorm_test\" -cache=true -coverprofile=coverage6-2.txt -covermode=atomic" + - "go test -v -race -db=\"mssql\" -conn_str=\"server=mssql;user id=sa;password=yourStrong(!)Password;database=xorm_test\" -col_quote=reserved -coverprofile=coverage6-3.txt -covermode=atomic" + - "go test -v -race -db=\"mssql\" -conn_str=\"server=mssql;user id=sa;password=yourStrong(!)Password;database=xorm_test\" -col_quote=reserved -cache=true -coverprofile=coverage6-4.txt -covermode=atomic" when: event: - push @@ -125,7 +132,17 @@ steps: commands: - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(tidb:4000)/xorm_test\" -ignore_select_update=true -coverprofile=coverage7-1.txt -covermode=atomic" - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(tidb:4000)/xorm_test\" -ignore_select_update=true -cache=true -coverprofile=coverage7-2.txt -covermode=atomic" - - 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 coverage6-1.txt coverage6-2.txt coverage7-1.txt coverage7-2.txt > coverage.txt + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(tidb:4000)/xorm_test\" -col_quote=reserved -ignore_select_update=true -coverprofile=coverage7-3.txt -covermode=atomic" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(tidb:4000)/xorm_test\" -col_quote=reserved -ignore_select_update=true -cache=true -coverprofile=coverage7-4.txt -covermode=atomic" + - > + gocovmerge coverage1-1.txt coverage1-2.txt coverage1-3.txt coverage1-4.txt + coverage2-1.txt coverage2-2.txt coverage2-3.txt coverage2-4.txt + coverage2.1-1.txt coverage2.1-2.txt coverage2.1-3.txt coverage2.1-4.txt + coverage3-1.txt coverage3-2.txt coverage3-3.txt coverage3-4.txt + coverage4-1.txt coverage4-2.txt coverage4-3.txt coverage4-4.txt + coverage5-1.txt coverage5-2.txt coverage5-3.txt coverage5-4.txt + coverage6-1.txt coverage6-2.txt coverage6-3.txt coverage6-4.txt + coverage7-1.txt coverage7-2.txt coverage7-3.txt coverage7-4.txt > coverage.txt when: event: - push @@ -180,7 +197,7 @@ services: --- kind: pipeline -name: matrix-2 +name: go1.11 platform: os: linux @@ -201,13 +218,6 @@ steps: 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 @@ -245,6 +255,8 @@ steps: commands: - "go test -v -race -db=\"sqlite3\" -conn_str=\"./test.db\" -coverprofile=coverage1-1.txt -covermode=atomic" - "go test -v -race -db=\"sqlite3\" -conn_str=\"./test.db\" -cache=true -coverprofile=coverage1-2.txt -covermode=atomic" + - "go test -v -race -db=\"sqlite3\" -conn_str=\"./test.db\" -col_quote=reserved -coverprofile=coverage1-3.txt -covermode=atomic" + - "go test -v -race -db=\"sqlite3\" -conn_str=\"./test.db\" -col_quote=reserved -cache=true -coverprofile=coverage1-4.txt -covermode=atomic" when: event: - push @@ -259,6 +271,8 @@ steps: 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" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test\" -col_quote=reserved -coverprofile=coverage2-3.txt -covermode=atomic" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test\" -col_quote=reserved -cache=true -coverprofile=coverage2-4.txt -covermode=atomic" when: event: - push @@ -273,6 +287,8 @@ steps: 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" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test?charset=utf8mb4\" -col_quote=reserved -coverprofile=coverage2.1-3.txt -covermode=atomic" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test?charset=utf8mb4\" -col_quote=reserved -cache=true -coverprofile=coverage2.1-4.txt -covermode=atomic" when: event: - push @@ -287,6 +303,8 @@ steps: 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" + - "go test -v -race -db=\"mymysql\" -conn_str=\"tcp:mysql:3306*xorm_test/root/\" -col_quote=reserved -coverprofile=coverage3-3.txt -covermode=atomic" + - "go test -v -race -db=\"mymysql\" -conn_str=\"tcp:mysql:3306*xorm_test/root/\" -col_quote=reserved -cache=true -coverprofile=coverage3-4.txt -covermode=atomic" when: event: - push @@ -301,6 +319,8 @@ steps: 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" + #- "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -col_quote=reserved -coverprofile=coverage4-3.txt -covermode=atomic" + #- "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -col_quote=reserved -cache=true -coverprofile=coverage4-4.txt -covermode=atomic" when: event: - push @@ -315,6 +335,8 @@ steps: 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" + #- "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -col_quote=reserved -schema=xorm -coverprofile=coverage5-3.txt -covermode=atomic" + #- "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -col_quote=reserved -schema=xorm -cache=true -coverprofile=coverage5-4.txt -covermode=atomic" when: event: - push @@ -329,6 +351,8 @@ steps: commands: - "go test -v -race -db=\"mssql\" -conn_str=\"server=mssql;user id=sa;password=yourStrong(!)Password;database=xorm_test\" -coverprofile=coverage6-1.txt -covermode=atomic" - "go test -v -race -db=\"mssql\" -conn_str=\"server=mssql;user id=sa;password=yourStrong(!)Password;database=xorm_test\" -cache=true -coverprofile=coverage6-2.txt -covermode=atomic" + - "go test -v -race -db=\"mssql\" -conn_str=\"server=mssql;user id=sa;password=yourStrong(!)Password;database=xorm_test\" -col_quote=reserved -coverprofile=coverage6-3.txt -covermode=atomic" + - "go test -v -race -db=\"mssql\" -conn_str=\"server=mssql;user id=sa;password=yourStrong(!)Password;database=xorm_test\" -col_quote=reserved -cache=true -coverprofile=coverage6-4.txt -covermode=atomic" when: event: @@ -344,8 +368,18 @@ steps: commands: - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(tidb:4000)/xorm_test\" -ignore_select_update=true -coverprofile=coverage7-1.txt -covermode=atomic" - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(tidb:4000)/xorm_test\" -ignore_select_update=true -cache=true -coverprofile=coverage7-2.txt -covermode=atomic" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(tidb:4000)/xorm_test\" -ignore_select_update=true -col_quote=reserved -coverprofile=coverage7-3.txt -covermode=atomic" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(tidb:4000)/xorm_test\" -ignore_select_update=true -col_quote=reserved -cache=true -coverprofile=coverage7-4.txt -covermode=atomic" - go get github.com/wadey/gocovmerge - - 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 coverage6-1.txt coverage6-2.txt coverage7-1.txt coverage7-2.txt > coverage.txt + - > + gocovmerge coverage1-1.txt coverage1-2.txt coverage1-3.txt coverage1-4.txt + coverage2-1.txt coverage2-2.txt coverage2-3.txt coverage2-4.txt + coverage2.1-1.txt coverage2.1-2.txt coverage2.1-3.txt coverage2.1-4.txt + coverage3-1.txt coverage3-2.txt coverage3-3.txt coverage3-4.txt + coverage4-1.txt coverage4-2.txt coverage4-3.txt coverage4-4.txt + coverage5-1.txt coverage5-2.txt coverage5-3.txt coverage5-4.txt + coverage6-1.txt coverage6-2.txt coverage6-3.txt coverage6-4.txt + coverage7-1.txt coverage7-2.txt coverage7-3.txt coverage7-4.txt > coverage.txt when: event: - push @@ -400,7 +434,7 @@ services: --- kind: pipeline -name: matrix-3 +name: go1.12 platform: os: linux @@ -458,6 +492,8 @@ steps: commands: - "go test -v -race -db=\"sqlite3\" -conn_str=\"./test.db\" -coverprofile=coverage1-1.txt -covermode=atomic" - "go test -v -race -db=\"sqlite3\" -conn_str=\"./test.db\" -cache=true -coverprofile=coverage1-2.txt -covermode=atomic" + - "go test -v -race -db=\"sqlite3\" -conn_str=\"./test.db\" -col_quote=reserved -coverprofile=coverage1-3.txt -covermode=atomic" + - "go test -v -race -db=\"sqlite3\" -conn_str=\"./test.db\" -col_quote=reserved -cache=true -coverprofile=coverage1-4.txt -covermode=atomic" when: event: - push @@ -472,6 +508,8 @@ steps: 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" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test\" -col_quote=reserved -coverprofile=coverage2-3.txt -covermode=atomic" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test\" -col_quote=reserved -cache=true -coverprofile=coverage2-4.txt -covermode=atomic" when: event: - push @@ -486,6 +524,8 @@ steps: 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" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test?charset=utf8mb4\" -col_quote=reserved -coverprofile=coverage2.1-3.txt -covermode=atomic" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test?charset=utf8mb4\" -col_quote=reserved -cache=true -coverprofile=coverage2.1-4.txt -covermode=atomic" when: event: - push @@ -500,6 +540,8 @@ steps: 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" + - "go test -v -race -db=\"mymysql\" -conn_str=\"tcp:mysql:3306*xorm_test/root/\" -col_quote=reserved -coverprofile=coverage3-3.txt -covermode=atomic" + - "go test -v -race -db=\"mymysql\" -conn_str=\"tcp:mysql:3306*xorm_test/root/\" -col_quote=reserved -cache=true -coverprofile=coverage3-4.txt -covermode=atomic" when: event: - push @@ -514,6 +556,8 @@ steps: 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" + #- "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -col_quote=reserved -coverprofile=coverage4-3.txt -covermode=atomic" + #- "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -col_quote=reserved -cache=true -coverprofile=coverage4-4.txt -covermode=atomic" when: event: - push @@ -528,6 +572,8 @@ steps: 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" + #- "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -col_quote=reserved -schema=xorm -coverprofile=coverage5-3.txt -covermode=atomic" + #- "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -col_quote=reserved -schema=xorm -cache=true -coverprofile=coverage5-4.txt -covermode=atomic" when: event: - push @@ -542,6 +588,8 @@ steps: commands: - "go test -v -race -db=\"mssql\" -conn_str=\"server=mssql;user id=sa;password=yourStrong(!)Password;database=xorm_test\" -coverprofile=coverage6-1.txt -covermode=atomic" - "go test -v -race -db=\"mssql\" -conn_str=\"server=mssql;user id=sa;password=yourStrong(!)Password;database=xorm_test\" -cache=true -coverprofile=coverage6-2.txt -covermode=atomic" + - "go test -v -race -db=\"mssql\" -conn_str=\"server=mssql;user id=sa;password=yourStrong(!)Password;database=xorm_test\" -col_quote=reserved -coverprofile=coverage6-3.txt -covermode=atomic" + - "go test -v -race -db=\"mssql\" -conn_str=\"server=mssql;user id=sa;password=yourStrong(!)Password;database=xorm_test\" -col_quote=reserved -cache=true -coverprofile=coverage6-4.txt -covermode=atomic" when: event: - push @@ -556,8 +604,18 @@ steps: commands: - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(tidb:4000)/xorm_test\" -ignore_select_update=true -coverprofile=coverage7-1.txt -covermode=atomic" - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(tidb:4000)/xorm_test\" -ignore_select_update=true -cache=true -coverprofile=coverage7-2.txt -covermode=atomic" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(tidb:4000)/xorm_test\" -ignore_select_update=true -col_quote=reserved -coverprofile=coverage7-3.txt -covermode=atomic" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(tidb:4000)/xorm_test\" -ignore_select_update=true -col_quote=reserved -cache=true -coverprofile=coverage7-4.txt -covermode=atomic" - go get github.com/wadey/gocovmerge - - 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 coverage6-1.txt coverage6-2.txt coverage7-1.txt coverage7-2.txt > coverage.txt + - > + gocovmerge coverage1-1.txt coverage1-2.txt coverage1-3.txt coverage1-4.txt + coverage2-1.txt coverage2-2.txt coverage2-3.txt coverage2-4.txt + coverage2.1-1.txt coverage2.1-2.txt coverage2.1-3.txt coverage2.1-4.txt + coverage3-1.txt coverage3-2.txt coverage3-3.txt coverage3-4.txt + coverage4-1.txt coverage4-2.txt coverage4-3.txt coverage4-4.txt + coverage5-1.txt coverage5-2.txt coverage5-3.txt coverage5-4.txt + coverage6-1.txt coverage6-2.txt coverage6-3.txt coverage6-4.txt + coverage7-1.txt coverage7-2.txt coverage7-3.txt coverage7-4.txt > coverage.txt when: event: - push @@ -670,6 +728,8 @@ steps: commands: - "go test -v -race -db=\"sqlite3\" -conn_str=\"./test.db\" -coverprofile=coverage1-1.txt -covermode=atomic" - "go test -v -race -db=\"sqlite3\" -conn_str=\"./test.db\" -cache=true -coverprofile=coverage1-2.txt -covermode=atomic" + - "go test -v -race -db=\"sqlite3\" -conn_str=\"./test.db\" -col_quote=reserved -coverprofile=coverage1-3.txt -covermode=atomic" + - "go test -v -race -db=\"sqlite3\" -conn_str=\"./test.db\" -col_quote=reserved -cache=true -coverprofile=coverage1-4.txt -covermode=atomic" when: event: - push @@ -684,6 +744,8 @@ steps: 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" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test\" -col_quote=reserved -coverprofile=coverage2-3.txt -covermode=atomic" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test\" -col_quote=reserved -cache=true -coverprofile=coverage2-4.txt -covermode=atomic" when: event: - push @@ -698,6 +760,8 @@ steps: 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" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test?charset=utf8mb4\" -col_quote=reserved -coverprofile=coverage2.1-3.txt -covermode=atomic" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test?charset=utf8mb4\" -col_quote=reserved -cache=true -coverprofile=coverage2.1-4.txt -covermode=atomic" when: event: - push @@ -712,6 +776,8 @@ steps: 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" + - "go test -v -race -db=\"mymysql\" -conn_str=\"tcp:mysql:3306*xorm_test/root/\" -col_quote=reserved -coverprofile=coverage3-3.txt -covermode=atomic" + - "go test -v -race -db=\"mymysql\" -conn_str=\"tcp:mysql:3306*xorm_test/root/\" -col_quote=reserved -cache=true -coverprofile=coverage3-4.txt -covermode=atomic" when: event: - push @@ -726,6 +792,8 @@ steps: 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" + #- "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -col_quote=reserved -coverprofile=coverage4-3.txt -covermode=atomic" + #- "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -col_quote=reserved -cache=true -coverprofile=coverage4-4.txt -covermode=atomic" when: event: - push @@ -740,6 +808,8 @@ steps: 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" + #- "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -col_quote=reserved -schema=xorm -coverprofile=coverage5-3.txt -covermode=atomic" + #- "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -col_quote=reserved -schema=xorm -cache=true -coverprofile=coverage5-4.txt -covermode=atomic" when: event: - push @@ -754,6 +824,8 @@ steps: commands: - "go test -v -race -db=\"mssql\" -conn_str=\"server=mssql;user id=sa;password=yourStrong(!)Password;database=xorm_test\" -coverprofile=coverage6-1.txt -covermode=atomic" - "go test -v -race -db=\"mssql\" -conn_str=\"server=mssql;user id=sa;password=yourStrong(!)Password;database=xorm_test\" -cache=true -coverprofile=coverage6-2.txt -covermode=atomic" + - "go test -v -race -db=\"mssql\" -conn_str=\"server=mssql;user id=sa;password=yourStrong(!)Password;database=xorm_test\" -col_quote=reserved -coverprofile=coverage6-3.txt -covermode=atomic" + - "go test -v -race -db=\"mssql\" -conn_str=\"server=mssql;user id=sa;password=yourStrong(!)Password;database=xorm_test\" -col_quote=reserved -cache=true -coverprofile=coverage6-4.txt -covermode=atomic" when: event: - push @@ -768,8 +840,18 @@ steps: commands: - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(tidb:4000)/xorm_test\" -ignore_select_update=true -coverprofile=coverage7-1.txt -covermode=atomic" - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(tidb:4000)/xorm_test\" -ignore_select_update=true -cache=true -coverprofile=coverage7-2.txt -covermode=atomic" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(tidb:4000)/xorm_test\" -ignore_select_update=true -col_quote=reserved -coverprofile=coverage7-3.txt -covermode=atomic" + - "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(tidb:4000)/xorm_test\" -ignore_select_update=true -col_quote=reserved -cache=true -coverprofile=coverage7-4.txt -covermode=atomic" - go get github.com/wadey/gocovmerge - - 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 coverage6-1.txt coverage6-2.txt coverage7-1.txt coverage7-2.txt > coverage.txt + - > + gocovmerge coverage1-1.txt coverage1-2.txt coverage1-3.txt coverage1-4.txt + coverage2-1.txt coverage2-2.txt coverage2-3.txt coverage2-4.txt + coverage2.1-1.txt coverage2.1-2.txt coverage2.1-3.txt coverage2.1-4.txt + coverage3-1.txt coverage3-2.txt coverage3-3.txt coverage3-4.txt + coverage4-1.txt coverage4-2.txt coverage4-3.txt coverage4-4.txt + coverage5-1.txt coverage5-2.txt coverage5-3.txt coverage5-4.txt + coverage6-1.txt coverage6-2.txt coverage6-3.txt coverage6-4.txt + coverage7-1.txt coverage7-2.txt coverage7-3.txt coverage7-4.txt > coverage.txt when: event: - push diff --git a/dialect_mssql.go b/dialect_mssql.go index 29070da2f..60bdbbbc3 100644 --- a/dialect_mssql.go +++ b/dialect_mssql.go @@ -281,7 +281,7 @@ func (db *mssql) SupportInsertMany() bool { } func (db *mssql) IsReserved(name string) bool { - _, ok := mssqlReservedWords[name] + _, ok := mssqlReservedWords[strings.ToUpper(name)] return ok } @@ -533,7 +533,7 @@ func (db *mssql) ForUpdateSql(query string) string { } func (db *mssql) Filters() []core.Filter { - return []core.Filter{&core.IdFilter{}, &core.QuoteFilter{}} + return []core.Filter{&core.QuoteFilter{}} } type odbcDriver struct { diff --git a/dialect_mysql.go b/dialect_mysql.go index cf1dbb6f2..56f008976 100644 --- a/dialect_mysql.go +++ b/dialect_mysql.go @@ -270,7 +270,7 @@ func (db *mysql) SupportInsertMany() bool { } func (db *mysql) IsReserved(name string) bool { - _, ok := mysqlReservedWords[name] + _, ok := mysqlReservedWords[strings.ToUpper(name)] return ok } @@ -560,7 +560,7 @@ func (db *mysql) CreateTableSql(table *core.Table, tableName, storeEngine, chars } func (db *mysql) Filters() []core.Filter { - return []core.Filter{&core.IdFilter{}} + return []core.Filter{} } type mymysqlDriver struct { diff --git a/dialect_oracle.go b/dialect_oracle.go index 15010ca5a..848f81bfd 100644 --- a/dialect_oracle.go +++ b/dialect_oracle.go @@ -547,7 +547,7 @@ func (db *oracle) SupportInsertMany() bool { } func (db *oracle) IsReserved(name string) bool { - _, ok := oracleReservedWords[name] + _, ok := oracleReservedWords[strings.ToUpper(name)] return ok } @@ -847,7 +847,7 @@ func (db *oracle) GetIndexes(tableName string) (map[string]*core.Index, error) { } func (db *oracle) Filters() []core.Filter { - return []core.Filter{&core.QuoteFilter{}, &core.SeqFilter{Prefix: ":", Start: 1}, &core.IdFilter{}} + return []core.Filter{&core.QuoteFilter{}, &core.SeqFilter{Prefix: ":", Start: 1}} } type goracleDriver struct { diff --git a/dialect_postgres.go b/dialect_postgres.go index ccef3086b..1c07c4deb 100644 --- a/dialect_postgres.go +++ b/dialect_postgres.go @@ -854,7 +854,7 @@ func (db *postgres) SupportInsertMany() bool { } func (db *postgres) IsReserved(name string) bool { - _, ok := postgresReservedWords[name] + _, ok := postgresReservedWords[strings.ToUpper(name)] return ok } @@ -1160,7 +1160,7 @@ func (db *postgres) GetIndexes(tableName string) (map[string]*core.Index, error) } func (db *postgres) Filters() []core.Filter { - return []core.Filter{&core.IdFilter{}, &core.QuoteFilter{}, &core.SeqFilter{Prefix: "$", Start: 1}} + return []core.Filter{&core.QuoteFilter{}, &core.SeqFilter{Prefix: "$", Start: 1}} } type pqDriver struct { diff --git a/dialect_sqlite3.go b/dialect_sqlite3.go index 0a290f3c4..265f14fdc 100644 --- a/dialect_sqlite3.go +++ b/dialect_sqlite3.go @@ -194,7 +194,7 @@ func (db *sqlite3) SupportInsertMany() bool { } func (db *sqlite3) IsReserved(name string) bool { - _, ok := sqlite3ReservedWords[name] + _, ok := sqlite3ReservedWords[strings.ToUpper(name)] return ok } @@ -477,7 +477,7 @@ func (db *sqlite3) GetIndexes(tableName string) (map[string]*core.Index, error) } func (db *sqlite3) Filters() []core.Filter { - return []core.Filter{&core.IdFilter{}} + return []core.Filter{} } type sqlite3Driver struct { diff --git a/engine.go b/engine.go index 4ed0f77a9..7c94a00fc 100644 --- a/engine.go +++ b/engine.go @@ -55,6 +55,9 @@ type Engine struct { cacherLock sync.RWMutex defaultContext context.Context + + colQuoter Quoter + tableQuoter Quoter } func (engine *Engine) setCacher(tableName string, cacher core.Cacher) { @@ -175,64 +178,6 @@ func (engine *Engine) SupportInsertMany() bool { return engine.dialect.SupportInsertMany() } -func (engine *Engine) quoteColumns(columnStr string) string { - columns := strings.Split(columnStr, ",") - for i := 0; i < len(columns); i++ { - columns[i] = engine.Quote(strings.TrimSpace(columns[i])) - } - return strings.Join(columns, ",") -} - -// Quote Use QuoteStr quote the string sql -func (engine *Engine) Quote(value string) string { - value = strings.TrimSpace(value) - if len(value) == 0 { - return value - } - - buf := strings.Builder{} - engine.QuoteTo(&buf, value) - - return buf.String() -} - -// QuoteTo quotes string and writes into the buffer -func (engine *Engine) QuoteTo(buf *strings.Builder, value string) { - if buf == nil { - return - } - - value = strings.TrimSpace(value) - if value == "" { - return - } - - 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) - } -} - -func (engine *Engine) quote(sql string) string { - return engine.dialect.Quote(sql) -} - // SqlType will be deprecated, please use SQLType instead // // Deprecated: use SQLType instead @@ -474,6 +419,8 @@ func (engine *Engine) dumpTables(tables []*core.Table, w io.Writer, tp ...core.D return err } + colQuoter := newQuoter(dialect, engine.colQuoter.QuotePolicy()) + for i, table := range tables { if i > 0 { _, err = io.WriteString(w, "\n") @@ -493,10 +440,10 @@ func (engine *Engine) dumpTables(tables []*core.Table, w io.Writer, tp ...core.D } cols := table.ColumnsSeq() - colNames := engine.dialect.Quote(strings.Join(cols, engine.dialect.Quote(", "))) - destColNames := dialect.Quote(strings.Join(cols, dialect.Quote(", "))) + colNames := quoteJoin(engine.colQuoter, cols) + destColNames := quoteJoin(colQuoter, cols) - rows, err := engine.DB().Query("SELECT " + colNames + " FROM " + engine.Quote(table.Name)) + rows, err := engine.DB().Query("SELECT " + colNames + " FROM " + engine.quote(table.Name, false)) if err != nil { return err } diff --git a/engine_cond.go b/engine_cond.go index 702ac8043..a323f3ee9 100644 --- a/engine_cond.go +++ b/engine_cond.go @@ -44,9 +44,9 @@ func (engine *Engine) buildConds(table *core.Table, bean interface{}, if len(aliasName) > 0 { nm = aliasName } - colName = engine.Quote(nm) + "." + engine.Quote(col.Name) + colName = engine.quote(nm, false) + "." + engine.quote(col.Name, true) } else { - colName = engine.Quote(col.Name) + colName = engine.quote(col.Name, true) } fieldValuePtr, err := col.ValueOf(bean) diff --git a/engine_quote.go b/engine_quote.go new file mode 100644 index 000000000..fd12afbc1 --- /dev/null +++ b/engine_quote.go @@ -0,0 +1,186 @@ +// Copyright 2019 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package xorm + +import ( + "fmt" + "strings" + + "xorm.io/builder" + "xorm.io/core" +) + +// QuotePolicy describes quote handle policy +type QuotePolicy int + +// All QuotePolicies +const ( + QuotePolicyAlways QuotePolicy = iota + QuotePolicyNone + QuotePolicyReserved +) + +// Quoter represents an object has Quote method +type Quoter interface { + Quotes() (byte, byte) + QuotePolicy() QuotePolicy + IsReserved(string) bool + WriteTo(w *builder.BytesWriter, value string) error +} + +type quoter struct { + dialect core.Dialect + quotePolicy QuotePolicy +} + +func newQuoter(dialect core.Dialect, quotePolicy QuotePolicy) Quoter { + return "er{ + dialect: dialect, + quotePolicy: quotePolicy, + } +} + +func (q *quoter) Quotes() (byte, byte) { + quotes := q.dialect.Quote("") + return quotes[0], quotes[1] +} + +func (q *quoter) QuotePolicy() QuotePolicy { + return q.quotePolicy +} + +func (q *quoter) IsReserved(value string) bool { + return q.dialect.IsReserved(value) +} + +func (q *quoter) needQuote(value string) bool { + return q.quotePolicy == QuotePolicyAlways || (q.quotePolicy == QuotePolicyReserved && q.IsReserved(value)) +} + +func (q *quoter) WriteTo(w *builder.BytesWriter, name string) error { + leftQuote, rightQuote := q.Quotes() + needQuote := q.needQuote(name) + if needQuote && name[0] != '`' { + if err := w.WriteByte(leftQuote); err != nil { + return err + } + } + if _, err := w.WriteString(name); err != nil { + return err + } + if needQuote && name[len(name)-1] != '`' { + if err := w.WriteByte(rightQuote); err != nil { + return err + } + } + return nil +} + +func quoteColumns(quoter Quoter, columnStr string) string { + columns := strings.Split(columnStr, ",") + return quoteJoin(quoter, columns) +} + +func quoteJoin(quoter Quoter, columns []string) string { + for i := 0; i < len(columns); i++ { + columns[i] = quote(quoter, columns[i]) + } + return strings.Join(columns, ",") +} + +// quote Use QuoteStr quote the string sql +func quote(quoter Quoter, value string) string { + buf := strings.Builder{} + quoteTo(quoter, &buf, value) + return buf.String() +} + +// Quote add quotes to the value +func (engine *Engine) quote(value string, isColumn bool) string { + if isColumn { + return quote(engine.colQuoter, value) + } + return quote(engine.tableQuoter, value) +} + +// Quote add quotes to the value +func (engine *Engine) Quote(value string, isColumn bool) string { + return engine.quote(value, isColumn) +} + +// Quotes return the left quote and right quote +func (engine *Engine) Quotes() (byte, byte) { + quotes := engine.dialect.Quote("") + return quotes[0], quotes[1] +} + +// IsReserved return true if the value is a reserved word of the database +func (engine *Engine) IsReserved(value string) bool { + return engine.dialect.IsReserved(value) +} + +// SetTableQuotePolicy set table quote policy +func (engine *Engine) SetTableQuotePolicy(policy QuotePolicy) { + engine.tableQuoter = newQuoter(engine.dialect, policy) +} + +// SetColumnQuotePolicy set column quote policy +func (engine *Engine) SetColumnQuotePolicy(policy QuotePolicy) { + engine.colQuoter = newQuoter(engine.dialect, policy) +} + +// quoteTo quotes string and writes into the buffer +func quoteTo(quoter Quoter, buf *strings.Builder, value string) { + left, right := quoter.Quotes() + if (quoter.QuotePolicy() == QuotePolicyAlways) || + (quoter.QuotePolicy() == QuotePolicyReserved && quoter.IsReserved(value)) { + realQuoteTo(left, right, buf, value) + return + } + buf.WriteString(value) +} + +func realQuoteTo(quoteLeft, quoteRight byte, buf *strings.Builder, value string) { + if buf == nil { + return + } + + value = strings.TrimSpace(value) + if value == "" { + return + } else if value == "*" { + buf.WriteString("*") + return + } + + if value[0] == '`' || value[0] == quoteLeft { // no quote + _, _ = buf.WriteString(value) + return + } else { + _ = buf.WriteByte(quoteLeft) + for i := 0; i < len(value); i++ { + if value[i] == '.' { + _ = buf.WriteByte(quoteRight) + _ = buf.WriteByte('.') + _ = buf.WriteByte(quoteLeft) + } else { + _ = buf.WriteByte(value[i]) + } + } + _ = buf.WriteByte(quoteRight) + } +} + +func unQuote(quoter Quoter, value string) string { + left, right := quoter.Quotes() + return strings.Trim(value, fmt.Sprintf("%v%v`", left, right)) +} + +func quoteJoinFunc(cols []string, quoteFunc func(string) string, sep string) string { + for i := range cols { + cols[i] = quoteFunc(cols[i]) + } + return strings.Join(cols, sep+" ") +} diff --git a/engine_quote_test.go b/engine_quote_test.go new file mode 100644 index 000000000..3318acd4b --- /dev/null +++ b/engine_quote_test.go @@ -0,0 +1,98 @@ +// Copyright 2019 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package xorm + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestQuoteColumns(t *testing.T) { + cols := []string{"f1", "f2", "f3"} + quoteFunc := func(value string) string { + return "[" + value + "]" + } + + assert.EqualValues(t, "[f1], [f2], [f3]", quoteJoinFunc(cols, quoteFunc, ",")) +} + +func TestChangeQuotePolicy(t *testing.T) { + assert.NoError(t, prepareEngine()) + + type ChangeQuotePolicy struct { + Id int64 + Name string + } + + testEngine.SetColumnQuotePolicy(QuotePolicyNone) + defer func() { + testEngine.SetColumnQuotePolicy(colQuotePolicy) + }() + + assertSync(t, new(ChangeQuotePolicy)) + + var obj1 = ChangeQuotePolicy{ + Name: "obj1", + } + _, err := testEngine.Insert(&obj1) + assert.NoError(t, err) + + var obj2 ChangeQuotePolicy + _, err = testEngine.ID(obj1.Id).Get(&obj2) + assert.NoError(t, err) + + var objs []ChangeQuotePolicy + err = testEngine.Find(&objs) + assert.NoError(t, err) + + _, err = testEngine.ID(obj1.Id).Update(&ChangeQuotePolicy{ + Name: "obj2", + }) + assert.NoError(t, err) + + _, err = testEngine.ID(obj1.Id).Delete(new(ChangeQuotePolicy)) + assert.NoError(t, err) +} + +func TestChangeQuotePolicy2(t *testing.T) { + assert.NoError(t, prepareEngine()) + + type ChangeQuotePolicy2 struct { + Id int64 + Name string + User string + Index int + } + + testEngine.SetColumnQuotePolicy(QuotePolicyReserved) + defer func() { + testEngine.SetColumnQuotePolicy(colQuotePolicy) + }() + + assertSync(t, new(ChangeQuotePolicy2)) + + var obj1 = ChangeQuotePolicy2{ + Name: "obj1", + } + _, err := testEngine.Insert(&obj1) + assert.NoError(t, err) + + var obj2 ChangeQuotePolicy2 + _, err = testEngine.ID(obj1.Id).Get(&obj2) + assert.NoError(t, err) + + var objs []ChangeQuotePolicy2 + err = testEngine.Find(&objs) + assert.NoError(t, err) + + _, err = testEngine.ID(obj1.Id).Update(&ChangeQuotePolicy2{ + Name: "obj2", + }) + assert.NoError(t, err) + + _, err = testEngine.ID(obj1.Id).Delete(new(ChangeQuotePolicy2)) + assert.NoError(t, err) +} diff --git a/engine_table.go b/engine_table.go index eb5aa850a..c7018d75e 100644 --- a/engine_table.go +++ b/engine_table.go @@ -63,9 +63,9 @@ func (engine *Engine) tbNameNoSchema(tablename interface{}) string { case []string: t := tablename.([]string) if len(t) > 1 { - return fmt.Sprintf("%v AS %v", engine.Quote(t[0]), engine.Quote(t[1])) + return fmt.Sprintf("%v AS %v", engine.quote(t[0], false), engine.quote(t[1], false)) } else if len(t) == 1 { - return engine.Quote(t[0]) + return engine.quote(t[0], false) } case []interface{}: t := tablename.([]interface{}) @@ -84,15 +84,15 @@ func (engine *Engine) tbNameNoSchema(tablename interface{}) string { if t.Kind() == reflect.Struct { table = engine.tbNameForMap(v) } else { - table = engine.Quote(fmt.Sprintf("%v", f)) + table = engine.quote(fmt.Sprintf("%v", f), false) } } } if l > 1 { - return fmt.Sprintf("%v AS %v", engine.Quote(table), - engine.Quote(fmt.Sprintf("%v", t[1]))) + return fmt.Sprintf("%v AS %v", engine.quote(table, false), + engine.quote(fmt.Sprintf("%v", t[1]), false)) } else if l == 1 { - return engine.Quote(table) + return engine.quote(table, false) } case TableName: return tablename.(TableName).TableName() @@ -107,7 +107,7 @@ func (engine *Engine) tbNameNoSchema(tablename interface{}) string { if t.Kind() == reflect.Struct { return engine.tbNameForMap(v) } - return engine.Quote(fmt.Sprintf("%v", tablename)) + return engine.quote(fmt.Sprintf("%v", tablename), false) } return "" } diff --git a/helpers.go b/helpers.go index a31e922c0..8ad99277f 100644 --- a/helpers.go +++ b/helpers.go @@ -323,10 +323,3 @@ func eraseAny(value string, strToErase ...string) string { 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+" ") -} diff --git a/helpers_test.go b/helpers_test.go index caf7b9f0b..fc9ece27f 100644 --- a/helpers_test.go +++ b/helpers_test.go @@ -16,12 +16,3 @@ func TestEraseAny(t *testing.T) { assert.EqualValues(t, "SELECT * FROM table.[table_name]", eraseAny(raw, "`")) assert.EqualValues(t, "SELECT * FROM table.table_name", eraseAny(raw, "`", "[", "]")) } - -func TestQuoteColumns(t *testing.T) { - cols := []string{"f1", "f2", "f3"} - quoteFunc := func(value string) string { - return "[" + value + "]" - } - - assert.EqualValues(t, "[f1], [f2], [f3]", quoteColumns(cols, quoteFunc, ",")) -} diff --git a/interface.go b/interface.go index a564db126..3da9bd69b 100644 --- a/interface.go +++ b/interface.go @@ -89,8 +89,9 @@ type EngineInterface interface { MapCacher(interface{}, core.Cacher) error NewSession() *Session NoAutoTime() *Session - Quote(string) string + Quote(string, bool) string SetCacher(string, core.Cacher) + SetColumnQuotePolicy(policy QuotePolicy) SetConnMaxLifetime(time.Duration) SetDefaultCacher(core.Cacher) SetLogger(logger core.ILogger) @@ -99,6 +100,7 @@ type EngineInterface interface { SetMaxOpenConns(int) SetMaxIdleConns(int) SetSchema(string) + SetTableQuotePolicy(policy QuotePolicy) SetTZDatabase(tz *time.Location) SetTZLocation(tz *time.Location) ShowExecTime(...bool) diff --git a/rows_test.go b/rows_test.go index af3338619..f022a8887 100644 --- a/rows_test.go +++ b/rows_test.go @@ -70,7 +70,7 @@ func TestRows(t *testing.T) { } assert.EqualValues(t, 1, cnt) - var tbName = testEngine.Quote(testEngine.TableName(user, true)) + var tbName = testEngine.Quote(testEngine.TableName(user, true), false) rows2, err := testEngine.SQL("SELECT * FROM " + tbName).Rows(new(UserRows)) assert.NoError(t, err) defer rows2.Close() diff --git a/session.go b/session.go index b33955fdc..f08ef92e2 100644 --- a/session.go +++ b/session.go @@ -649,7 +649,7 @@ func (session *Session) slice2Bean(scanResults []interface{}, fields []string, b // !! 增加支持sql.Scanner接口的结构,如sql.NullString hasAssigned = true if err := nulVal.Scan(vv.Interface()); err != nil { - session.engine.logger.Error("sql.Sanner error:", err.Error()) + session.engine.logger.Error("sql.Scanner error:", err.Error()) hasAssigned = false } } else if col.SQLType.IsJson() { diff --git a/session_cond_test.go b/session_cond_test.go index 106504845..d6c3417f0 100644 --- a/session_cond_test.go +++ b/session_cond_test.go @@ -9,8 +9,8 @@ import ( "fmt" "testing" - "xorm.io/builder" "github.com/stretchr/testify/assert" + "xorm.io/builder" ) func TestBuilder(t *testing.T) { @@ -122,7 +122,8 @@ func TestIn(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, 3, cnt) - department := "`" + testEngine.GetColumnMapper().Obj2Table("Departname") + "`" + department := testEngine.Quote(colMapper.Obj2Table("Departname"), true) + idStr := testEngine.Quote(colMapper.Obj2Table("Id"), true) var usrs []Userinfo err = testEngine.Where(department+" = ?", "dev").Limit(3).Find(&usrs) assert.NoError(t, err) @@ -137,13 +138,13 @@ func TestIn(t *testing.T) { idsStr = idsStr[:len(idsStr)-1] users := make([]Userinfo, 0) - err = testEngine.In("(id)", ids[0], ids[1], ids[2]).Find(&users) + err = testEngine.In(idStr, ids[0], ids[1], ids[2]).Find(&users) assert.NoError(t, err) fmt.Println(users) assert.EqualValues(t, 3, len(users)) users = make([]Userinfo, 0) - err = testEngine.In("(id)", ids).Find(&users) + err = testEngine.In(idStr, ids).Find(&users) assert.NoError(t, err) fmt.Println(users) assert.EqualValues(t, 3, len(users)) @@ -161,7 +162,7 @@ func TestIn(t *testing.T) { idsInterface = append(idsInterface, id) } - err = testEngine.Where(department+" = ?", "dev").In("(id)", idsInterface...).Find(&users) + err = testEngine.Where(department+" = ?", "dev").In(idStr, idsInterface...).Find(&users) assert.NoError(t, err) fmt.Println(users) assert.EqualValues(t, 3, len(users)) @@ -175,11 +176,11 @@ func TestIn(t *testing.T) { dev := testEngine.GetColumnMapper().Obj2Table("Dev") - err = testEngine.In("(id)", 1).In("(id)", 2).In(department, dev).Find(&users) + err = testEngine.In(idStr, 1).In(idStr, 2).In(department, dev).Find(&users) assert.NoError(t, err) fmt.Println(users) - cnt, err = testEngine.In("(id)", ids[0]).Update(&Userinfo{Departname: "dev-"}) + cnt, err = testEngine.In(idStr, ids[0]).Update(&Userinfo{Departname: "dev-"}) assert.NoError(t, err) assert.EqualValues(t, 1, cnt) @@ -189,11 +190,11 @@ func TestIn(t *testing.T) { assert.True(t, has) assert.EqualValues(t, "dev-", user.Departname) - cnt, err = testEngine.In("(id)", ids[0]).Update(&Userinfo{Departname: "dev"}) + cnt, err = testEngine.In(idStr, ids[0]).Update(&Userinfo{Departname: "dev"}) assert.NoError(t, err) assert.EqualValues(t, 1, cnt) - cnt, err = testEngine.In("(id)", ids[1]).Delete(&Userinfo{}) + cnt, err = testEngine.In(idStr, ids[1]).Delete(&Userinfo{}) assert.NoError(t, err) assert.EqualValues(t, 1, cnt) } diff --git a/session_delete.go b/session_delete.go index 675d4d8c7..8b7c9a079 100644 --- a/session_delete.go +++ b/session_delete.go @@ -106,7 +106,7 @@ func (session *Session) Delete(bean interface{}) (int64, error) { } var tableNameNoQuote = session.statement.TableName() - var tableName = session.engine.Quote(tableNameNoQuote) + var tableName = session.engine.quote(tableNameNoQuote, false) var table = session.statement.RefTable var deleteSQL string if len(condSQL) > 0 { @@ -160,8 +160,8 @@ func (session *Session) Delete(bean interface{}) (int64, error) { deletedColumn := table.DeletedColumn() realSQL = fmt.Sprintf("UPDATE %v SET %v = ? WHERE %v", - session.engine.Quote(session.statement.TableName()), - session.engine.Quote(deletedColumn.Name), + session.engine.quote(session.statement.TableName(), false), + session.engine.quote(deletedColumn.Name, true), condSQL) if len(orderSQL) > 0 { diff --git a/session_exist.go b/session_exist.go index 660cc47e4..c76aa7f50 100644 --- a/session_exist.go +++ b/session_exist.go @@ -34,7 +34,7 @@ func (session *Session) Exist(bean ...interface{}) (bool, error) { return false, ErrTableNotFound } - tableName = session.statement.Engine.Quote(tableName) + tableName = session.statement.Engine.quote(tableName, false) if session.statement.cond.IsValid() { condSQL, condArgs, err := builder.ToSQL(session.statement.cond) diff --git a/session_find.go b/session_find.go index 6b8aa469d..8a58bd833 100644 --- a/session_find.go +++ b/session_find.go @@ -112,13 +112,13 @@ func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{}) // !oinume! Add " IS NULL" to WHERE whatever condiBean is given. // See https://github.com/go-xorm/xorm/issues/179 if col := table.DeletedColumn(); col != nil && !session.statement.unscoped { // tag "deleted" is enabled - var colName = session.engine.Quote(col.Name) + var colName = session.engine.quote(col.Name, true) if addedTableName { var nm = session.statement.TableName() if len(session.statement.TableAlias) > 0 { nm = session.statement.TableAlias } - colName = session.engine.Quote(nm) + "." + colName + colName = session.engine.quote(nm, false) + "." + colName } autoCond = session.engine.CondDeleted(colName) @@ -141,7 +141,7 @@ func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{}) if session.statement.JoinStr == "" { if columnStr == "" { if session.statement.GroupByStr != "" { - columnStr = session.engine.quoteColumns(session.statement.GroupByStr) + columnStr = quoteColumns(session.engine.colQuoter, session.statement.GroupByStr) } else { columnStr = session.statement.genColumnStr() } @@ -149,7 +149,7 @@ func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{}) } else { if columnStr == "" { if session.statement.GroupByStr != "" { - columnStr = session.engine.quoteColumns(session.statement.GroupByStr) + columnStr = quoteColumns(session.engine.colQuoter, session.statement.GroupByStr) } else { columnStr = "*" } diff --git a/session_find_test.go b/session_find_test.go index f805f06e0..4396a7635 100644 --- a/session_find_test.go +++ b/session_find_test.go @@ -10,8 +10,8 @@ import ( "testing" "time" - "xorm.io/core" "github.com/stretchr/testify/assert" + "xorm.io/core" ) func TestJoinLimit(t *testing.T) { @@ -103,7 +103,7 @@ func TestFind(t *testing.T) { } users2 := make([]Userinfo, 0) - var tbName = testEngine.Quote(testEngine.TableName(new(Userinfo), true)) + var tbName = testEngine.Quote(testEngine.TableName(new(Userinfo), true), false) err = testEngine.SQL("select * from " + tbName).Find(&users2) assert.NoError(t, err) } @@ -309,13 +309,14 @@ func TestOrderSameMapper(t *testing.T) { assertSync(t, new(Userinfo)) + idStr := testEngine.Quote("id", true) users := make([]Userinfo, 0) - err := testEngine.OrderBy("(id) desc").Find(&users) + err := testEngine.OrderBy(idStr + " desc").Find(&users) assert.NoError(t, err) fmt.Println(users) users2 := make([]Userinfo, 0) - err = testEngine.Asc("(id)", "Username").Desc("Height").Find(&users2) + err = testEngine.Asc(idStr, "Username").Desc("Height").Find(&users2) assert.NoError(t, err) fmt.Println(users2) } diff --git a/session_insert.go b/session_insert.go index 1e19ce7a4..02c9a2d98 100644 --- a/session_insert.go +++ b/session_insert.go @@ -248,18 +248,20 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error var sql string if session.engine.dialect.DBType() == core.ORACLE { temp := fmt.Sprintf(") INTO %s (%v) VALUES (", - session.engine.Quote(tableName), - quoteColumns(colNames, session.engine.Quote, ",")) + session.engine.quote(tableName, false), + quoteJoin(session.engine.colQuoter, colNames)) sql = fmt.Sprintf("INSERT ALL INTO %s (%v) VALUES (%v) SELECT 1 FROM DUAL", - session.engine.Quote(tableName), - quoteColumns(colNames, session.engine.Quote, ","), + session.engine.quote(tableName, false), + quoteJoin(session.engine.colQuoter, colNames), strings.Join(colMultiPlaces, temp)) } else { sql = fmt.Sprintf("INSERT INTO %s (%v) VALUES (%v)", - session.engine.Quote(tableName), - quoteColumns(colNames, session.engine.Quote, ","), + session.engine.quote(tableName, false), + quoteJoin(session.engine.colQuoter, colNames), strings.Join(colMultiPlaces, "),(")) } + + fmt.Println("====", sql) res, err := session.exec(sql, args...) if err != nil { return 0, err @@ -358,7 +360,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) { } var buf = builder.NewWriter() - if _, err := buf.WriteString(fmt.Sprintf("INSERT INTO %s", session.engine.Quote(tableName))); err != nil { + if _, err := buf.WriteString(fmt.Sprintf("INSERT INTO %s", session.engine.quote(tableName, false))); err != nil { return 0, err } @@ -377,7 +379,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) { return 0, err } - if err := writeStrings(buf, append(colNames, exprs.colNames...), "`", "`"); err != nil { + if err := writeStrings(buf, append(colNames, exprs.colNames...), session.engine.colQuoter); err != nil { return 0, err } @@ -399,7 +401,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) { return 0, err } - if _, err := buf.WriteString(fmt.Sprintf(" FROM %v WHERE ", session.engine.Quote(tableName))); err != nil { + if _, err := buf.WriteString(fmt.Sprintf(" FROM %v WHERE ", session.engine.quote(tableName, false))); err != nil { return 0, err } @@ -426,7 +428,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) { } if len(table.AutoIncrement) > 0 && session.engine.dialect.DBType() == core.POSTGRES { - if _, err := buf.WriteString(" RETURNING " + session.engine.Quote(table.AutoIncrement)); err != nil { + if _, err := buf.WriteString(" RETURNING " + session.engine.quote(table.AutoIncrement, true)); err != nil { return 0, err } } @@ -731,11 +733,11 @@ func (session *Session) insertMapInterface(m map[string]interface{}) (int64, err w := builder.NewWriter() if session.statement.cond.IsValid() { - if _, err := w.WriteString(fmt.Sprintf("INSERT INTO %s (", session.engine.Quote(tableName))); err != nil { + if _, err := w.WriteString(fmt.Sprintf("INSERT INTO %s (", session.engine.quote(tableName, false))); err != nil { return 0, err } - if err := writeStrings(w, append(columns, exprs.colNames...), "`", "`"); err != nil { + if err := writeStrings(w, append(columns, exprs.colNames...), session.engine.colQuoter); err != nil { return 0, err } @@ -756,7 +758,7 @@ func (session *Session) insertMapInterface(m map[string]interface{}) (int64, err } } - if _, err := w.WriteString(fmt.Sprintf(" FROM %s WHERE ", session.engine.Quote(tableName))); err != nil { + if _, err := w.WriteString(fmt.Sprintf(" FROM %s WHERE ", session.engine.quote(tableName, false))); err != nil { return 0, err } @@ -767,7 +769,7 @@ func (session *Session) insertMapInterface(m map[string]interface{}) (int64, err qm := strings.Repeat("?,", len(columns)) qm = qm[:len(qm)-1] - if _, err := w.WriteString(fmt.Sprintf("INSERT INTO %s (`%s`) VALUES (%s)", session.engine.Quote(tableName), strings.Join(columns, "`,`"), qm)); err != nil { + if _, err := w.WriteString(fmt.Sprintf("INSERT INTO %s (`%s`) VALUES (%s)", session.engine.quote(tableName, false), strings.Join(columns, "`,`"), qm)); err != nil { return 0, err } w.Append(args...) @@ -817,11 +819,11 @@ func (session *Session) insertMapString(m map[string]string) (int64, error) { w := builder.NewWriter() if session.statement.cond.IsValid() { - if _, err := w.WriteString(fmt.Sprintf("INSERT INTO %s (", session.engine.Quote(tableName))); err != nil { + if _, err := w.WriteString(fmt.Sprintf("INSERT INTO %s (", session.engine.quote(tableName, false))); err != nil { return 0, err } - if err := writeStrings(w, append(columns, exprs.colNames...), "`", "`"); err != nil { + if err := writeStrings(w, append(columns, exprs.colNames...), session.engine.colQuoter); err != nil { return 0, err } @@ -842,7 +844,7 @@ func (session *Session) insertMapString(m map[string]string) (int64, error) { } } - if _, err := w.WriteString(fmt.Sprintf(" FROM %s WHERE ", session.engine.Quote(tableName))); err != nil { + if _, err := w.WriteString(fmt.Sprintf(" FROM %s WHERE ", session.engine.quote(tableName, false))); err != nil { return 0, err } @@ -853,7 +855,9 @@ func (session *Session) insertMapString(m map[string]string) (int64, error) { qm := strings.Repeat("?,", len(columns)) qm = qm[:len(qm)-1] - if _, err := w.WriteString(fmt.Sprintf("INSERT INTO %s (`%s`) VALUES (%s)", session.engine.Quote(tableName), strings.Join(columns, "`,`"), qm)); err != nil { + if _, err := w.WriteString(fmt.Sprintf("INSERT INTO %s (%s) VALUES (%s)", + session.engine.quote(tableName, false), + quoteJoin(session.engine.colQuoter, columns), qm)); err != nil { return 0, err } w.Append(args...) diff --git a/session_insert_test.go b/session_insert_test.go index 2785401d8..b28ba2ca4 100644 --- a/session_insert_test.go +++ b/session_insert_test.go @@ -201,28 +201,13 @@ func TestInsertDefault(t *testing.T) { _, err = testEngine.Omit(testEngine.GetColumnMapper().Obj2Table("Status")).Insert(&di2) assert.NoError(t, err) - has, err := testEngine.Desc("(id)").Get(di) + idStr := colMapper.Obj2Table("Id") + has, err := testEngine.Desc(idStr).Get(di) assert.NoError(t, err) - if !has { - err = errors.New("error with no data") - t.Error(err) - panic(err) - } - if di.Status != -1 { - err = errors.New("inserted error data") - t.Error(err) - panic(err) - } - if di2.Updated.Unix() != di.Updated.Unix() { - err = errors.New("updated should equal") - t.Error(err, di.Updated, di2.Updated) - panic(err) - } - if di2.Created.Unix() != di.Created.Unix() { - err = errors.New("created should equal") - t.Error(err, di.Created, di2.Created) - panic(err) - } + assert.True(t, has, "error with no data") + assert.EqualValues(t, -1, di.Status, "inserted error data") + assert.EqualValues(t, di.Updated.Unix(), di2.Updated.Unix(), "updated should equal") + assert.EqualValues(t, di.Created.Unix(), di2.Created.Unix()) } type DefaultInsert2 struct { @@ -237,53 +222,21 @@ func TestInsertDefault2(t *testing.T) { di := new(DefaultInsert2) err := testEngine.Sync2(di) - if err != nil { - t.Error(err) - } + assert.NoError(t, err) var di2 = DefaultInsert2{Name: "test"} _, err = testEngine.Omit(testEngine.GetColumnMapper().Obj2Table("CheckTime")).Insert(&di2) - if err != nil { - t.Error(err) - } - - has, err := testEngine.Desc("(id)").Get(di) - if err != nil { - t.Error(err) - } - if !has { - err = errors.New("error with no data") - t.Error(err) - panic(err) - } - - has, err = testEngine.NoAutoCondition().Desc("(id)").Get(&di2) - if err != nil { - t.Error(err) - } - - if !has { - err = errors.New("error with no data") - t.Error(err) - panic(err) - } + assert.NoError(t, err) - if *di != di2 { - err = fmt.Errorf("%v is not equal to %v", di, di2) - t.Error(err) - panic(err) - } + idStr := testEngine.Quote(testEngine.GetColumnMapper().Obj2Table("Id"), true) + has, err := testEngine.Desc(idStr).Get(di) + assert.NoError(t, err) + assert.True(t, has, "error with no data") - /*if di2.Updated.Unix() != di.Updated.Unix() { - err = errors.New("updated should equal") - t.Error(err, di.Updated, di2.Updated) - panic(err) - } - if di2.Created.Unix() != di.Created.Unix() { - err = errors.New("created should equal") - t.Error(err, di.Created, di2.Created) - panic(err) - }*/ + has, err = testEngine.NoAutoCondition().Desc(idStr).Get(&di2) + assert.NoError(t, err) + assert.True(t, has, "error with no data") + assert.EqualValues(t, *di, di2, fmt.Errorf("%v is not equal to %v", di, di2)) } type CreatedInsert struct { @@ -321,19 +274,15 @@ func TestInsertCreated(t *testing.T) { di := new(CreatedInsert) err := testEngine.Sync2(di) - if err != nil { - t.Fatal(err) - } + assert.NoError(t, err) + ci := &CreatedInsert{} _, err = testEngine.Insert(ci) - if err != nil { - t.Fatal(err) - } + assert.NoError(t, err) - has, err := testEngine.Desc("(id)").Get(di) - if err != nil { - t.Fatal(err) - } + idStr := testEngine.Quote(colMapper.Obj2Table("Id"), true) + has, err := testEngine.Desc(idStr).Get(di) + assert.NoError(t, err) if !has { t.Fatal(ErrNotExist) } @@ -344,18 +293,14 @@ func TestInsertCreated(t *testing.T) { di2 := new(CreatedInsert2) err = testEngine.Sync2(di2) - if err != nil { - t.Fatal(err) - } + assert.NoError(t, err) + ci2 := &CreatedInsert2{} _, err = testEngine.Insert(ci2) - if err != nil { - t.Fatal(err) - } - has, err = testEngine.Desc("(id)").Get(di2) - if err != nil { - t.Fatal(err) - } + assert.NoError(t, err) + + has, err = testEngine.Desc(idStr).Get(di2) + assert.NoError(t, err) if !has { t.Fatal(ErrNotExist) } @@ -366,18 +311,14 @@ func TestInsertCreated(t *testing.T) { di3 := new(CreatedInsert3) err = testEngine.Sync2(di3) - if err != nil { - t.Fatal(err) - } + assert.NoError(t, err) + ci3 := &CreatedInsert3{} _, err = testEngine.Insert(ci3) - if err != nil { - t.Fatal(err) - } - has, err = testEngine.Desc("(id)").Get(di3) - if err != nil { - t.Fatal(err) - } + assert.NoError(t, err) + + has, err = testEngine.Desc(idStr).Get(di3) + assert.NoError(t, err) if !has { t.Fatal(ErrNotExist) } @@ -388,18 +329,14 @@ func TestInsertCreated(t *testing.T) { di4 := new(CreatedInsert4) err = testEngine.Sync2(di4) - if err != nil { - t.Fatal(err) - } + assert.NoError(t, err) + ci4 := &CreatedInsert4{} _, err = testEngine.Insert(ci4) - if err != nil { - t.Fatal(err) - } - has, err = testEngine.Desc("(id)").Get(di4) - if err != nil { - t.Fatal(err) - } + assert.NoError(t, err) + + has, err = testEngine.Desc(idStr).Get(di4) + assert.NoError(t, err) if !has { t.Fatal(ErrNotExist) } @@ -410,18 +347,14 @@ func TestInsertCreated(t *testing.T) { di5 := new(CreatedInsert5) err = testEngine.Sync2(di5) - if err != nil { - t.Fatal(err) - } + assert.NoError(t, err) + ci5 := &CreatedInsert5{} _, err = testEngine.Insert(ci5) - if err != nil { - t.Fatal(err) - } - has, err = testEngine.Desc("(id)").Get(di5) - if err != nil { - t.Fatal(err) - } + assert.NoError(t, err) + + has, err = testEngine.Desc(idStr).Get(di5) + assert.NoError(t, err) if !has { t.Fatal(ErrNotExist) } @@ -432,20 +365,15 @@ func TestInsertCreated(t *testing.T) { di6 := new(CreatedInsert6) err = testEngine.Sync2(di6) - if err != nil { - t.Fatal(err) - } + assert.NoError(t, err) + oldTime := time.Now().Add(-time.Hour) ci6 := &CreatedInsert6{Created: oldTime} _, err = testEngine.Insert(ci6) - if err != nil { - t.Fatal(err) - } + assert.NoError(t, err) - has, err = testEngine.Desc("(id)").Get(di6) - if err != nil { - t.Fatal(err) - } + has, err = testEngine.Desc(idStr).Get(di6) + assert.NoError(t, err) if !has { t.Fatal(ErrNotExist) } @@ -476,8 +404,7 @@ func (j JsonTime) MarshalJSON() ([]byte, error) { func TestDefaultTime3(t *testing.T) { type PrepareTask struct { - Id int `xorm:"not null pk autoincr INT(11)" json:"id"` - // ... + Id int `xorm:"not null pk autoincr INT(11)" json:"id"` StartTime JsonTime `xorm:"not null default '2006-01-02 15:04:05' TIMESTAMP index" json:"start_time"` EndTime JsonTime `xorm:"not null default '2006-01-02 15:04:05' TIMESTAMP" json:"end_time"` Cuser string `xorm:"not null default '' VARCHAR(64) index" json:"cuser"` @@ -509,31 +436,22 @@ func TestCreatedJsonTime(t *testing.T) { di5 := new(MyJsonTime) err := testEngine.Sync2(di5) - if err != nil { - t.Fatal(err) - } + assert.NoError(t, err) + ci5 := &MyJsonTime{} _, err = testEngine.Insert(ci5) - if err != nil { - t.Fatal(err) - } - has, err := testEngine.Desc("(id)").Get(di5) - if err != nil { - t.Fatal(err) - } - if !has { - t.Fatal(ErrNotExist) - } - if time.Time(ci5.Created).Unix() != time.Time(di5.Created).Unix() { - t.Fatal("should equal:", time.Time(ci5.Created).Unix(), time.Time(di5.Created).Unix()) - } - fmt.Println("ci5:", ci5, "di5:", di5) + assert.NoError(t, err) + + idStr := testEngine.Quote(colMapper.Obj2Table("Id"), true) + has, err := testEngine.Desc(idStr).Get(di5) + assert.NoError(t, err) + assert.True(t, has, ErrNotExist.Error()) + assert.EqualValues(t, time.Time(ci5.Created).Unix(), time.Time(di5.Created).Unix(), + fmt.Sprintf("should equal: %v %v", time.Time(ci5.Created).Unix(), time.Time(di5.Created).Unix())) var dis = make([]MyJsonTime, 0) err = testEngine.Find(&dis) - if err != nil { - t.Fatal(err) - } + assert.NoError(t, err) } func TestInsertMulti2(t *testing.T) { @@ -548,10 +466,7 @@ func TestInsertMulti2(t *testing.T) { {Username: "xlw22", Departname: "dev", Alias: "lunny3", Created: time.Now()}, } cnt, err := testEngine.Insert(&users) - if err != nil { - t.Error(err) - panic(err) - } + assert.NoError(t, err) if cnt != int64(len(users)) { err = errors.New("insert not returned 1") t.Error(err) @@ -567,10 +482,7 @@ func TestInsertMulti2(t *testing.T) { } cnt, err = testEngine.Insert(&users2) - if err != nil { - t.Error(err) - panic(err) - } + assert.NoError(t, err) if cnt != int64(len(users2)) { err = errors.New(fmt.Sprintf("insert not returned %v", len(users2))) @@ -588,10 +500,7 @@ func TestInsertTwoTable(t *testing.T) { userinfo := Userinfo{Username: "xlw3", Departname: "dev", Alias: "lunny4", Created: time.Now(), Detail: userdetail} cnt, err := testEngine.Insert(&userinfo, &userdetail) - if err != nil { - t.Error(err) - panic(err) - } + assert.NoError(t, err) if userinfo.Uid <= 0 { err = errors.New("not return id error") diff --git a/session_query.go b/session_query.go index 21c00b8d7..8ea86df30 100644 --- a/session_query.go +++ b/session_query.go @@ -35,7 +35,7 @@ func (session *Session) genQuerySQL(sqlOrArgs ...interface{}) (string, []interfa if session.statement.JoinStr == "" { if columnStr == "" { if session.statement.GroupByStr != "" { - columnStr = session.engine.quoteColumns(session.statement.GroupByStr) + columnStr = quoteColumns(session.engine.colQuoter, session.statement.GroupByStr) } else { columnStr = session.statement.genColumnStr() } @@ -43,7 +43,7 @@ func (session *Session) genQuerySQL(sqlOrArgs ...interface{}) (string, []interfa } else { if columnStr == "" { if session.statement.GroupByStr != "" { - columnStr = session.engine.quoteColumns(session.statement.GroupByStr) + columnStr = quoteColumns(session.engine.colQuoter, session.statement.GroupByStr) } else { columnStr = "*" } diff --git a/session_query_test.go b/session_query_test.go index 772206a8a..b831754c0 100644 --- a/session_query_test.go +++ b/session_query_test.go @@ -372,7 +372,7 @@ func TestJoinWithSubQuery(t *testing.T) { assert.EqualValues(t, 1, cnt) var querys []JoinWithSubQuery1 - err = testEngine.Join("INNER", builder.Select("id").From(testEngine.Quote(testEngine.TableName("join_with_sub_query_depart", true))), + err = testEngine.Join("INNER", builder.Select("id").From(testEngine.Quote(testEngine.TableName("join_with_sub_query_depart", true), false)), "join_with_sub_query_depart.id = join_with_sub_query1.depart_id").Find(&querys) assert.NoError(t, err) assert.EqualValues(t, 1, len(querys)) diff --git a/session_schema.go b/session_schema.go index 738c831a3..fb183bc18 100644 --- a/session_schema.go +++ b/session_schema.go @@ -168,7 +168,7 @@ func (session *Session) IsTableEmpty(bean interface{}) (bool, error) { func (session *Session) isTableEmpty(tableName string) (bool, error) { var total int64 - sqlStr := fmt.Sprintf("select count(*) from %s", session.engine.Quote(session.engine.TableName(tableName, true))) + sqlStr := fmt.Sprintf("select count(*) from %s", session.engine.quote(session.engine.TableName(tableName, true), false)) err := session.queryRow(sqlStr).Scan(&total) if err != nil { if err == sql.ErrNoRows { diff --git a/session_update.go b/session_update.go index c5c65a452..6f1ef957f 100644 --- a/session_update.go +++ b/session_update.go @@ -100,15 +100,7 @@ func (session *Session) cacheUpdate(table *core.Table, tableName, sqlStr string, for idx, kv := range kvs { sps := strings.SplitN(kv, "=", 2) sps2 := strings.Split(sps[0], ".") - colName := sps2[len(sps2)-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 - } + colName := unQuote(session.engine.colQuoter, sps2[len(sps2)-1]) if col := table.GetColumn(colName); col != nil { fieldValue, err := col.ValueOf(bean) @@ -195,7 +187,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 bValue := reflect.Indirect(reflect.ValueOf(bean)) for _, v := range bValue.MapKeys() { - colNames = append(colNames, session.engine.Quote(v.String())+" = ?") + colNames = append(colNames, session.engine.quote(v.String(), true)+" = ?") args = append(args, bValue.MapIndex(v).Interface()) } } else { @@ -207,7 +199,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 if session.statement.UseAutoTime && table != nil && table.Updated != "" { if !session.statement.columnMap.contain(table.Updated) && !session.statement.omitColumnMap.contain(table.Updated) { - colNames = append(colNames, session.engine.Quote(table.Updated)+" = ?") + colNames = append(colNames, session.engine.quote(table.Updated, true)+" = ?") col := table.UpdatedColumn() val, t := session.engine.nowTime(col) args = append(args, val) @@ -225,13 +217,13 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 // for update action to like "column = column + ?" incColumns := session.statement.incrColumns for i, colName := range incColumns.colNames { - colNames = append(colNames, session.engine.Quote(colName)+" = "+session.engine.Quote(colName)+" + ?") + colNames = append(colNames, session.engine.quote(colName, true)+" = "+session.engine.quote(colName, true)+" + ?") args = append(args, incColumns.args[i]) } // for update action to like "column = column - ?" decColumns := session.statement.decrColumns for i, colName := range decColumns.colNames { - colNames = append(colNames, session.engine.Quote(colName)+" = "+session.engine.Quote(colName)+" - ?") + colNames = append(colNames, session.engine.quote(colName, true)+" = "+session.engine.quote(colName, true)+" - ?") args = append(args, decColumns.args[i]) } // for update action to like "column = expression" @@ -239,13 +231,13 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 for i, colName := range exprColumns.colNames { switch tp := exprColumns.args[i].(type) { case string: - colNames = append(colNames, session.engine.Quote(colName)+" = "+tp) + colNames = append(colNames, session.engine.quote(colName, true)+" = "+tp) case *builder.Builder: subQuery, subArgs, err := builder.ToSQL(tp) if err != nil { return 0, err } - colNames = append(colNames, session.engine.Quote(colName)+" = ("+subQuery+")") + colNames = append(colNames, session.engine.quote(colName, true)+" = ("+subQuery+")") args = append(args, subArgs...) } } @@ -281,7 +273,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 if !condBeanIsStruct && table != nil { if col := table.DeletedColumn(); col != nil && !session.statement.unscoped { // tag "deleted" is enabled - autoCond1 := session.engine.CondDeleted(session.engine.Quote(col.Name)) + autoCond1 := session.engine.CondDeleted(session.engine.quote(col.Name, true)) if autoCond == nil { autoCond = autoCond1 @@ -307,8 +299,8 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 return 0, err } - cond = cond.And(builder.Eq{session.engine.Quote(table.Version): verValue.Interface()}) - colNames = append(colNames, session.engine.Quote(table.Version)+" = "+session.engine.Quote(table.Version)+" + 1") + cond = cond.And(builder.Eq{session.engine.quote(table.Version, true): verValue.Interface()}) + colNames = append(colNames, session.engine.quote(table.Version, true)+" = "+session.engine.quote(table.Version, true)+" + 1") } condSQL, condArgs, err = builder.ToSQL(cond) @@ -333,7 +325,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 } else if st.Engine.dialect.DBType() == core.SQLITE { tempCondSQL := condSQL + fmt.Sprintf(" LIMIT %d", st.LimitN) cond = cond.And(builder.Expr(fmt.Sprintf("rowid IN (SELECT rowid FROM %v %v)", - session.engine.Quote(tableName), tempCondSQL), condArgs...)) + session.engine.quote(tableName, false), tempCondSQL), condArgs...)) condSQL, condArgs, err = builder.ToSQL(cond) if err != nil { return 0, err @@ -344,7 +336,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 } else if st.Engine.dialect.DBType() == core.POSTGRES { tempCondSQL := condSQL + fmt.Sprintf(" LIMIT %d", st.LimitN) cond = cond.And(builder.Expr(fmt.Sprintf("CTID IN (SELECT CTID FROM %v %v)", - session.engine.Quote(tableName), tempCondSQL), condArgs...)) + session.engine.quote(tableName, false), tempCondSQL), condArgs...)) condSQL, condArgs, err = builder.ToSQL(cond) if err != nil { return 0, err @@ -358,7 +350,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 table != nil && len(table.PrimaryKeys) == 1 { cond = builder.Expr(fmt.Sprintf("%s IN (SELECT TOP (%d) %s FROM %v%v)", table.PrimaryKeys[0], st.LimitN, table.PrimaryKeys[0], - session.engine.Quote(tableName), condSQL), condArgs...) + session.engine.quote(tableName, false), condSQL), condArgs...) condSQL, condArgs, err = builder.ToSQL(cond) if err != nil { @@ -379,7 +371,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 sqlStr = fmt.Sprintf("UPDATE %v%v SET %v %v", top, - session.engine.Quote(tableName), + session.engine.quote(tableName, false), strings.Join(colNames, ", "), condSQL) @@ -519,7 +511,7 @@ func (session *Session) genUpdateColumns(bean interface{}) ([]string, []interfac args = append(args, arg) } - colNames = append(colNames, session.engine.Quote(col.Name)+" = ?") + colNames = append(colNames, session.engine.quote(col.Name, true)+" = ?") } return colNames, args, nil } diff --git a/statement.go b/statement.go index 3cc0831ee..9130152f5 100644 --- a/statement.go +++ b/statement.go @@ -191,14 +191,14 @@ func (statement *Statement) Or(query interface{}, args ...interface{}) *Statemen // In generate "Where column IN (?) " statement func (statement *Statement) In(column string, args ...interface{}) *Statement { - in := builder.In(statement.Engine.Quote(column), args...) + in := builder.In(statement.Engine.quote(column, true), args...) statement.cond = statement.cond.And(in) return statement } // NotIn generate "Where column NOT IN (?) " statement func (statement *Statement) NotIn(column string, args ...interface{}) *Statement { - notIn := builder.NotIn(statement.Engine.Quote(column), args...) + notIn := builder.NotIn(statement.Engine.quote(column, true), args...) statement.cond = statement.cond.And(notIn) return statement } @@ -327,7 +327,7 @@ func (statement *Statement) buildUpdates(bean interface{}, if fieldValue.IsNil() { if includeNil { args = append(args, nil) - colNames = append(colNames, fmt.Sprintf("%v=?", engine.Quote(col.Name))) + colNames = append(colNames, fmt.Sprintf("%v=?", engine.quote(col.Name, true))) } continue } else if !fieldValue.IsValid() { @@ -474,7 +474,7 @@ func (statement *Statement) buildUpdates(bean interface{}, if col.IsPrimaryKey && engine.dialect.DBType() == "ql" { continue } - colNames = append(colNames, fmt.Sprintf("%v = ?", engine.Quote(col.Name))) + colNames = append(colNames, fmt.Sprintf("%v = ?", engine.quote(col.Name, true))) } return colNames, args @@ -490,9 +490,9 @@ func (statement *Statement) colName(col *core.Column, tableName string) string { if len(statement.TableAlias) > 0 { nm = statement.TableAlias } - return statement.Engine.Quote(nm) + "." + statement.Engine.Quote(col.Name) + return statement.Engine.quote(nm, false) + "." + statement.Engine.quote(col.Name, true) } - return statement.Engine.Quote(col.Name) + return statement.Engine.quote(col.Name, true) } // TableName return current tableName @@ -560,9 +560,8 @@ func (statement *Statement) SetExpr(column string, expression interface{}) *Stat func (statement *Statement) col2NewColsWithQuote(columns ...string) []string { newColumns := make([]string, 0) - quotes := append(strings.Split(statement.Engine.Quote(""), ""), "`") for _, col := range columns { - newColumns = append(newColumns, statement.Engine.Quote(eraseAny(col, quotes...))) + newColumns = append(newColumns, statement.Engine.quote(col, true)) } return newColumns } @@ -571,7 +570,7 @@ func (statement *Statement) colmap2NewColsWithQuote() []string { newColumns := make([]string, len(statement.columnMap), len(statement.columnMap)) copy(newColumns, statement.columnMap) for i := 0; i < len(statement.columnMap); i++ { - newColumns[i] = statement.Engine.Quote(newColumns[i]) + newColumns[i] = statement.Engine.quote(newColumns[i], true) } return newColumns } @@ -604,8 +603,7 @@ func (statement *Statement) Cols(columns ...string) *Statement { newColumns := statement.colmap2NewColsWithQuote() - statement.ColumnStr = strings.Join(newColumns, ", ") - statement.ColumnStr = strings.Replace(statement.ColumnStr, statement.Engine.quote("*"), "*", -1) + statement.ColumnStr = quoteJoin(statement.Engine.colQuoter, newColumns) return statement } @@ -640,7 +638,7 @@ func (statement *Statement) Omit(columns ...string) { for _, nc := range newColumns { statement.omitColumnMap = append(statement.omitColumnMap, nc) } - statement.OmitStr = statement.Engine.Quote(strings.Join(newColumns, statement.Engine.Quote(", "))) + statement.OmitStr = quoteJoin(statement.Engine.colQuoter, newColumns) } // Nullable Update use only: update columns to null when value is nullable and zero-value @@ -733,9 +731,8 @@ func (statement *Statement) Join(joinOP string, tablename interface{}, condition return statement } tbs := strings.Split(tp.TableName(), ".") - quotes := append(strings.Split(statement.Engine.Quote(""), ""), "`") - var aliasName = strings.Trim(tbs[len(tbs)-1], strings.Join(quotes, "")) + var aliasName = unQuote(statement.Engine.tableQuoter, tbs[len(tbs)-1]) fmt.Fprintf(&buf, "(%s) %s ON %v", subSQL, aliasName, condition) statement.joinArgs = append(statement.joinArgs, subQueryArgs...) case *builder.Builder: @@ -745,9 +742,8 @@ func (statement *Statement) Join(joinOP string, tablename interface{}, condition return statement } tbs := strings.Split(tp.TableName(), ".") - quotes := append(strings.Split(statement.Engine.Quote(""), ""), "`") - var aliasName = strings.Trim(tbs[len(tbs)-1], strings.Join(quotes, "")) + var aliasName = unQuote(statement.Engine.tableQuoter, tbs[len(tbs)-1]) fmt.Fprintf(&buf, "(%s) %s ON %v", subSQL, aliasName, condition) statement.joinArgs = append(statement.joinArgs, subQueryArgs...) default: @@ -813,7 +809,7 @@ func (statement *Statement) genColumnStr() string { buf.WriteString(".") } - statement.Engine.QuoteTo(&buf, col.Name) + quoteTo(statement.Engine.colQuoter, &buf, col.Name) } return buf.String() @@ -868,9 +864,9 @@ func (statement *Statement) genDelIndexSQL() []string { } else if index.Type == core.IndexType { rIdxName = indexName(idxPrefixName, idxName) } - sql := fmt.Sprintf("DROP INDEX %v", statement.Engine.Quote(statement.Engine.TableName(rIdxName, true))) + sql := fmt.Sprintf("DROP INDEX %v", statement.Engine.quote(statement.Engine.TableName(rIdxName, true), false)) if statement.Engine.dialect.IndexOnTable() { - sql += fmt.Sprintf(" ON %v", statement.Engine.Quote(tbName)) + sql += fmt.Sprintf(" ON %v", statement.Engine.quote(tbName, false)) } sqls = append(sqls, sql) } @@ -878,8 +874,8 @@ func (statement *Statement) genDelIndexSQL() []string { } func (statement *Statement) genAddColumnStr(col *core.Column) (string, []interface{}) { - quote := statement.Engine.Quote - sql := fmt.Sprintf("ALTER TABLE %v ADD %v", quote(statement.TableName()), + quote := statement.Engine.quote + sql := fmt.Sprintf("ALTER TABLE %v ADD %v", quote(statement.TableName(), false), col.String(statement.Engine.dialect)) if statement.Engine.dialect.DBType() == core.MYSQL && len(col.Comment) > 0 { sql += " COMMENT '" + col.Comment + "'" @@ -932,7 +928,7 @@ func (statement *Statement) genGetSQL(bean interface{}) (string, []interface{}, if len(statement.JoinStr) == 0 { if len(columnStr) == 0 { if len(statement.GroupByStr) > 0 { - columnStr = statement.Engine.quoteColumns(statement.GroupByStr) + columnStr = quoteColumns(statement.Engine.colQuoter, statement.GroupByStr) } else { columnStr = statement.genColumnStr() } @@ -940,7 +936,7 @@ func (statement *Statement) genGetSQL(bean interface{}) (string, []interface{}, } else { if len(columnStr) == 0 { if len(statement.GroupByStr) > 0 { - columnStr = statement.Engine.quoteColumns(statement.GroupByStr) + columnStr = quoteColumns(statement.Engine.colQuoter, statement.GroupByStr) } } } @@ -1008,7 +1004,7 @@ func (statement *Statement) genSumSQL(bean interface{}, columns ...string) (stri var sumStrs = make([]string, 0, len(columns)) for _, colName := range columns { if !strings.Contains(colName, " ") && !strings.Contains(colName, "(") { - colName = statement.Engine.Quote(colName) + colName = statement.Engine.quote(colName, true) } sumStrs = append(sumStrs, fmt.Sprintf("COALESCE(sum(%s),0)", colName)) } @@ -1031,7 +1027,7 @@ func (statement *Statement) genSelectSQL(columnStr, condSQL string, needLimit, n var ( distinct string dialect = statement.Engine.Dialect() - quote = statement.Engine.Quote + quote = statement.Engine.quote fromStr = " FROM " top, mssqlCondi, whereStr string ) @@ -1045,14 +1041,14 @@ func (statement *Statement) genSelectSQL(columnStr, condSQL string, needLimit, n if dialect.DBType() == core.MSSQL && strings.Contains(statement.TableName(), "..") { fromStr += statement.TableName() } else { - fromStr += quote(statement.TableName()) + fromStr += quote(statement.TableName(), false) } if statement.TableAlias != "" { if dialect.DBType() == core.ORACLE { - fromStr += " " + quote(statement.TableAlias) + fromStr += " " + quote(statement.TableAlias, false) } else { - fromStr += " AS " + quote(statement.TableAlias) + fromStr += " AS " + quote(statement.TableAlias, false) } } if statement.JoinStr != "" { @@ -1169,10 +1165,10 @@ func (statement *Statement) joinColumns(cols []*core.Column, includeTableName bo var colnames = make([]string, len(cols)) for i, col := range cols { if includeTableName { - colnames[i] = statement.Engine.Quote(statement.TableName()) + - "." + statement.Engine.Quote(col.Name) + colnames[i] = statement.Engine.quote(statement.TableName(), false) + + "." + statement.Engine.quote(col.Name, true) } else { - colnames[i] = statement.Engine.Quote(col.Name) + colnames[i] = statement.Engine.quote(col.Name, true) } } return strings.Join(colnames, ", ") @@ -1212,7 +1208,7 @@ func (statement *Statement) convertUpdateSQL(sqlStr string) (string, string) { if len(sqls) != 2 { if len(sqls) == 1 { return sqls[0], fmt.Sprintf("SELECT %v FROM %v", - colstrs, statement.Engine.Quote(statement.TableName())) + colstrs, statement.Engine.quote(statement.TableName(), false)) } return "", "" } @@ -1239,6 +1235,6 @@ func (statement *Statement) convertUpdateSQL(sqlStr string) (string, string) { } return sqls[0], fmt.Sprintf("SELECT %v FROM %v WHERE %v", - colstrs, statement.Engine.Quote(statement.TableName()), + colstrs, statement.Engine.quote(statement.TableName(), false), whereStr) } diff --git a/statement_args.go b/statement_args.go index 310f24d6b..e5c85c150 100644 --- a/statement_args.go +++ b/statement_args.go @@ -145,21 +145,11 @@ func (statement *Statement) writeArgs(w *builder.BytesWriter, args []interface{} return nil } -func writeStrings(w *builder.BytesWriter, cols []string, leftQuote, rightQuote string) error { +func writeStrings(w *builder.BytesWriter, cols []string, quoter Quoter) error { for i, colName := range cols { - if len(leftQuote) > 0 && colName[0] != '`' { - if _, err := w.WriteString(leftQuote); err != nil { - return err - } - } - if _, err := w.WriteString(colName); err != nil { + if err := quoter.WriteTo(w, colName); err != nil { return err } - if len(rightQuote) > 0 && colName[len(colName)-1] != '`' { - if _, err := w.WriteString(rightQuote); err != nil { - return err - } - } if i+1 != len(cols) { if _, err := w.WriteString(","); err != nil { return err diff --git a/statement_test.go b/statement_test.go index acc542abe..b287d96df 100644 --- a/statement_test.go +++ b/statement_test.go @@ -18,12 +18,12 @@ var colStrTests = []struct { onlyToDBColumnNdx int expected string }{ - {"", -1, "`ID`, `IsDeleted`, `Caption`, `Code1`, `Code2`, `Code3`, `ParentID`, `Latitude`, `Longitude`"}, - {"Code2", -1, "`ID`, `IsDeleted`, `Caption`, `Code1`, `Code3`, `ParentID`, `Latitude`, `Longitude`"}, - {"", 1, "`ID`, `Caption`, `Code1`, `Code2`, `Code3`, `ParentID`, `Latitude`, `Longitude`"}, - {"Code3", 1, "`ID`, `Caption`, `Code1`, `Code2`, `ParentID`, `Latitude`, `Longitude`"}, - {"Longitude", 1, "`ID`, `Caption`, `Code1`, `Code2`, `Code3`, `ParentID`, `Latitude`"}, - {"", 8, "`ID`, `IsDeleted`, `Caption`, `Code1`, `Code2`, `Code3`, `ParentID`, `Latitude`"}, + {"", -1, "ID, IsDeleted, Caption, Code1, Code2, Code3, ParentID, Latitude, Longitude"}, + {"Code2", -1, "ID, IsDeleted, Caption, Code1, Code3, ParentID, Latitude, Longitude"}, + {"", 1, "ID, Caption, Code1, Code2, Code3, ParentID, Latitude, Longitude"}, + {"Code3", 1, "ID, Caption, Code1, Code2, ParentID, Latitude, Longitude"}, + {"Longitude", 1, "ID, Caption, Code1, Code2, Code3, ParentID, Latitude"}, + {"", 8, "ID, IsDeleted, Caption, Code1, Code2, Code3, ParentID, Latitude"}, } func TestColumnsStringGeneration(t *testing.T) { @@ -31,6 +31,11 @@ func TestColumnsStringGeneration(t *testing.T) { return } + testEngine.SetColumnQuotePolicy(QuotePolicyNone) + defer func() { + testEngine.SetColumnQuotePolicy(colQuotePolicy) + }() + var statement *Statement for ndx, testCase := range colStrTests { @@ -243,6 +248,9 @@ func TestCol2NewColsWithQuote(t *testing.T) { statement := createTestStatement() - quotedCols := statement.col2NewColsWithQuote(cols...) - assert.EqualValues(t, []string{statement.Engine.Quote("f1"), statement.Engine.Quote("f2"), statement.Engine.Quote("t3.f3")}, quotedCols) + quotedCols := quoteJoin(statement.Engine.colQuoter, cols) + assert.EqualValues(t, statement.Engine.Quote("f1", true)+","+ + statement.Engine.Quote("f2", true)+","+ + statement.Engine.Quote("t3.f3", true), + quotedCols) } diff --git a/tag_extends_test.go b/tag_extends_test.go index 5a8031f01..78f3fbe4d 100644 --- a/tag_extends_test.go +++ b/tag_extends_test.go @@ -10,8 +10,8 @@ import ( "testing" "time" - "xorm.io/core" "github.com/stretchr/testify/assert" + "xorm.io/core" ) type tempUser struct { @@ -157,7 +157,7 @@ func TestExtends(t *testing.T) { uiid := testEngine.GetColumnMapper().Obj2Table("Id") udid := "detail_id" sql := fmt.Sprintf("select * from %s, %s where %s.%s = %s.%s", - qt(ui), qt(ud), qt(ui), qt(udid), qt(ud), qt(uiid)) + qt(ui, false), qt(ud, false), qt(ui, false), qt(udid, true), qt(ud, false), qt(uiid, true)) b, err := testEngine.SQL(sql).NoCascade().Get(&info) assert.NoError(t, err) if !b { @@ -175,7 +175,7 @@ func TestExtends(t *testing.T) { fmt.Println("----join--info2") var info2 UserAndDetail b, err = testEngine.Table(&Userinfo{}). - Join("LEFT", qt(ud), qt(ui)+"."+qt("detail_id")+" = "+qt(ud)+"."+qt(uiid)). + Join("LEFT", qt(ud, false), qt(ui, false)+"."+qt("detail_id", true)+" = "+qt(ud, false)+"."+qt(uiid, true)). NoCascade().Get(&info2) if err != nil { t.Error(err) @@ -196,7 +196,7 @@ func TestExtends(t *testing.T) { fmt.Println("----join--infos2") var infos2 = make([]UserAndDetail, 0) err = testEngine.Table(&Userinfo{}). - Join("LEFT", qt(ud), qt(ui)+"."+qt("detail_id")+" = "+qt(ud)+"."+qt(uiid)). + Join("LEFT", qt(ud, false), qt(ui, false)+"."+qt("detail_id", true)+" = "+qt(ud, false)+"."+qt(uiid, true)). NoCascade(). Find(&infos2) assert.NoError(t, err) @@ -286,9 +286,9 @@ func TestExtends2(t *testing.T) { var mapper = testEngine.GetTableMapper().Obj2Table var quote = testEngine.Quote - userTableName := quote(testEngine.TableName(mapper("MessageUser"), true)) - typeTableName := quote(testEngine.TableName(mapper("MessageType"), true)) - msgTableName := quote(testEngine.TableName(mapper("Message"), true)) + userTableName := quote(testEngine.TableName(mapper("MessageUser"), true), false) + typeTableName := quote(testEngine.TableName(mapper("MessageType"), true), false) + msgTableName := quote(testEngine.TableName(mapper("Message"), true), false) list := make([]Message, 0) err = session.Table(msgTableName).Join("LEFT", []string{userTableName, "sender"}, "`sender`.`"+mapper("Id")+"`="+msgTableName+".`"+mapper("Uid")+"`"). @@ -355,9 +355,9 @@ func TestExtends3(t *testing.T) { var mapper = testEngine.GetTableMapper().Obj2Table var quote = testEngine.Quote - userTableName := quote(testEngine.TableName(mapper("MessageUser"), true)) - typeTableName := quote(testEngine.TableName(mapper("MessageType"), true)) - msgTableName := quote(testEngine.TableName(mapper("Message"), true)) + userTableName := quote(testEngine.TableName(mapper("MessageUser"), true), false) + typeTableName := quote(testEngine.TableName(mapper("MessageType"), true), false) + msgTableName := quote(testEngine.TableName(mapper("Message"), true), false) list := make([]MessageExtend3, 0) err = session.Table(msgTableName).Join("LEFT", []string{userTableName, "sender"}, "`sender`.`"+mapper("Id")+"`="+msgTableName+".`"+mapper("Uid")+"`"). @@ -449,9 +449,9 @@ func TestExtends4(t *testing.T) { var mapper = testEngine.GetTableMapper().Obj2Table var quote = testEngine.Quote - userTableName := quote(testEngine.TableName(mapper("MessageUser"), true)) - typeTableName := quote(testEngine.TableName(mapper("MessageType"), true)) - msgTableName := quote(testEngine.TableName(mapper("Message"), true)) + userTableName := quote(testEngine.TableName(mapper("MessageUser"), true), false) + typeTableName := quote(testEngine.TableName(mapper("MessageType"), true), false) + msgTableName := quote(testEngine.TableName(mapper("Message"), true), false) list := make([]MessageExtend4, 0) err = session.Table(msgTableName).Join("LEFT", userTableName, userTableName+".`"+mapper("Id")+"`="+msgTableName+".`"+mapper("Uid")+"`"). @@ -549,21 +549,21 @@ func TestExtends5(t *testing.T) { var mapper = testEngine.GetTableMapper().Obj2Table var quote = testEngine.Quote - bookTableName := quote(testEngine.TableName(mapper("Book"), true)) - sizeTableName := quote(testEngine.TableName(mapper("Size"), true)) + bookTableName := quote(testEngine.TableName(mapper("Book"), true), false) + sizeTableName := quote(testEngine.TableName(mapper("Size"), true), false) list := make([]Book, 0) err = session. Select(fmt.Sprintf( "%s.%s, sc.%s AS %s, sc.%s AS %s, s.%s, s.%s", - quote(bookTableName), - quote("id"), - quote("Width"), - quote("ClosedWidth"), - quote("Height"), - quote("ClosedHeight"), - quote("Width"), - quote("Height"), + quote(bookTableName, false), + quote("id", true), + quote("Width", true), + quote("ClosedWidth", true), + quote("Height", true), + quote("ClosedHeight", true), + quote("Width", true), + quote("Height", true), )). Table(bookTableName). Join( diff --git a/tag_test.go b/tag_test.go index 979ba9297..bff7742b0 100644 --- a/tag_test.go +++ b/tag_test.go @@ -250,7 +250,7 @@ func TestTagDefault(t *testing.T) { var defaultVal string var isDefaultExist bool - tableName := testEngine.GetColumnMapper().Obj2Table("DefaultStruct") + tableName := tableMapper.Obj2Table("DefaultStruct") for _, table := range tables { if table.Name == tableName { col := table.GetColumn("age") @@ -293,7 +293,7 @@ func TestTagDefault2(t *testing.T) { var defaultVal string var isDefaultExist bool - tableName := testEngine.GetColumnMapper().Obj2Table("DefaultStruct2") + tableName := tableMapper.Obj2Table("DefaultStruct2") for _, table := range tables { if table.Name == tableName { col := table.GetColumn("name") @@ -322,7 +322,7 @@ func TestTagDefault3(t *testing.T) { var defaultVal string var isDefaultExist bool - tableName := testEngine.GetColumnMapper().Obj2Table("DefaultStruct3") + tableName := tableMapper.Obj2Table("DefaultStruct3") for _, table := range tables { if table.Name == tableName { col := table.GetColumn("name") @@ -351,7 +351,7 @@ func TestTagDefault4(t *testing.T) { var defaultVal string var isDefaultExist bool - tableName := testEngine.GetColumnMapper().Obj2Table("DefaultStruct4") + tableName := tableMapper.Obj2Table("DefaultStruct4") for _, table := range tables { if table.Name == tableName { col := table.GetColumn("created") @@ -387,7 +387,7 @@ func TestTagDefault5(t *testing.T) { var defaultVal string var isDefaultExist bool - tableName := testEngine.GetColumnMapper().Obj2Table("DefaultStruct5") + tableName := colMapper.Obj2Table("DefaultStruct5") for _, table := range tables { if table.Name == tableName { col := table.GetColumn("created") diff --git a/types_null_test.go b/types_null_test.go index 22fc1024f..4bffaa0eb 100644 --- a/types_null_test.go +++ b/types_null_test.go @@ -22,7 +22,7 @@ type NullType struct { Age sql.NullInt64 Height sql.NullFloat64 IsMan sql.NullBool `xorm:"null"` - CustomStruct CustomStruct `xorm:"valchar(64) null"` + CustomStruct CustomStruct `xorm:"varchar(64) null"` } type CustomStruct struct { diff --git a/types_test.go b/types_test.go index 274609b20..780035e88 100644 --- a/types_test.go +++ b/types_test.go @@ -9,8 +9,8 @@ import ( "fmt" "testing" - "xorm.io/core" "github.com/stretchr/testify/assert" + "xorm.io/core" ) func TestArrayField(t *testing.T) { @@ -305,7 +305,7 @@ func TestCustomType2(t *testing.T) { assert.NoError(t, err) tableName := testEngine.TableName(&uc, true) - _, err = testEngine.Exec("delete from " + testEngine.Quote(tableName)) + _, err = testEngine.Exec("delete from " + testEngine.Quote(tableName, false)) assert.NoError(t, err) session := testEngine.NewSession() diff --git a/xorm.go b/xorm.go index 26d00d264..6435d77e2 100644 --- a/xorm.go +++ b/xorm.go @@ -95,6 +95,8 @@ func NewEngine(driverName string, dataSourceName string) (*Engine, error) { tagHandlers: defaultTagHandlers, cachers: make(map[string]core.Cacher), defaultContext: context.Background(), + colQuoter: newQuoter(dialect, QuotePolicyAlways), + tableQuoter: newQuoter(dialect, QuotePolicyAlways), } if uri.DbType == core.SQLITE { diff --git a/xorm_test.go b/xorm_test.go index 21715256d..e82cfbe9c 100644 --- a/xorm_test.go +++ b/xorm_test.go @@ -35,9 +35,11 @@ var ( splitter = flag.String("splitter", ";", "the splitter on connstr for cluster") schema = flag.String("schema", "", "specify the schema") ignoreSelectUpdate = flag.Bool("ignore_select_update", false, "ignore select update if implementation difference, only for tidb") + colQuotePolicyStr = flag.String("col_quote", "always", "quote could be always, none, reversed") - tableMapper core.IMapper - colMapper core.IMapper + tableMapper core.IMapper + colMapper core.IMapper + colQuotePolicy QuotePolicy ) func createEngine(dbType, connStr string) error { @@ -123,6 +125,15 @@ func createEngine(dbType, connStr string) error { testEngine.SetMapper(core.LintGonicMapper) } } + + if *colQuotePolicyStr == "none" { + colQuotePolicy = QuotePolicyNone + } else if *colQuotePolicyStr == "reserved" { + colQuotePolicy = QuotePolicyReserved + } else { + colQuotePolicy = QuotePolicyAlways + } + testEngine.SetColumnQuotePolicy(colQuotePolicy) } tableMapper = testEngine.GetTableMapper()