Merge branch 'dump-infer-from-type' of gitea.com:zeripath/xorm into dump-infer-from-type

This commit is contained in:
Andrew Thornton 2021-04-11 22:03:02 +01:00
commit 4deb11051f
No known key found for this signature in database
GPG Key ID: 3CDE74631F13A748
30 changed files with 857 additions and 277 deletions

View File

@ -2,58 +2,288 @@
kind: pipeline
name: testing
steps:
- name: restore-cache
image: meltwater/drone-cache
pull: always
settings:
backend: "filesystem"
restore: true
cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}'
archive_format: "gzip"
filesystem_cache_root: "/go"
mount:
- pkg.mod
- pkg.build
volumes:
- name: cache
path: /go
- name: test-vet
image: golang:1.11 # The lowest golang requirement
image: golang:1.15
environment:
GO111MODULE: "on"
GOPROXY: "https://goproxy.cn"
GOPROXY: "https://goproxy.io"
CGO_ENABLED: 1
GOMODCACHE: '/drone/src/pkg.mod'
GOCACHE: '/drone/src/pkg.build'
commands:
- make vet
- make test
- make fmt-check
volumes:
- name: cache
path: /go
when:
event:
- push
- pull_request
- name: test-sqlite
image: golang:1.12
- name: rebuild-cache
image: meltwater/drone-cache
pull: true
settings:
backend: "filesystem"
rebuild: true
cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}'
archive_format: "gzip"
filesystem_cache_root: "/go"
mount:
- pkg.mod
- pkg.build
volumes:
- name: cache
path: /go
volumes:
- name: cache
temp: {}
---
kind: pipeline
name: test-sqlite
depends_on:
- testing
steps:
- name: restore-cache
image: meltwater/drone-cache:dev
pull: always
settings:
backend: "filesystem"
restore: true
cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}'
archive_format: "gzip"
filesystem_cache_root: "/go"
mount:
- pkg.mod
- pkg.build
volumes:
- name: cache
path: /go
- name: test-sqlite3
image: golang:1.15
environment:
GO111MODULE: "on"
GOPROXY: "https://goproxy.cn"
GOPROXY: "https://goproxy.io"
CGO_ENABLED: 1
GOMODCACHE: '/drone/src/pkg.mod'
GOCACHE: '/drone/src/pkg.build'
commands:
- make test-sqlite3
- TEST_CACHE_ENABLE=true make test-sqlite3
- TEST_QUOTE_POLICY=reserved make test-sqlite3
volumes:
- name: cache
path: /go
- name: test-sqlite
image: golang:1.15
environment:
GO111MODULE: "on"
GOPROXY: "https://goproxy.io"
CGO_ENABLED: 1
GOMODCACHE: '/drone/src/pkg.mod'
GOCACHE: '/drone/src/pkg.build'
commands:
- make test-sqlite
- TEST_CACHE_ENABLE=true make test-sqlite
- TEST_QUOTE_POLICY=reserved make test-sqlite
when:
event:
- push
- pull_request
volumes:
- name: cache
path: /go
- name: rebuild-cache
image: meltwater/drone-cache:dev
pull: true
settings:
backend: "filesystem"
rebuild: true
cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}'
archive_format: "gzip"
filesystem_cache_root: "/go"
mount:
- pkg.mod
- pkg.build
volumes:
- name: cache
path: /go
volumes:
- name: cache
temp: {}
---
kind: pipeline
name: test-mysql
depends_on:
- testing
steps:
- name: restore-cache
image: meltwater/drone-cache
pull: always
settings:
backend: "filesystem"
restore: true
cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}'
archive_format: "gzip"
filesystem_cache_root: "/go"
mount:
- pkg.mod
- pkg.build
volumes:
- name: cache
path: /go
- name: test-mysql
image: golang:1.12
image: golang:1.15
environment:
GO111MODULE: "on"
GOPROXY: "https://goproxy.cn"
GOPROXY: "https://goproxy.io"
CGO_ENABLED: 1
GOMODCACHE: '/drone/src/pkg.mod'
GOCACHE: '/drone/src/pkg.build'
TEST_MYSQL_HOST: mysql
TEST_MYSQL_CHARSET: utf8
TEST_MYSQL_DBNAME: xorm_test
TEST_MYSQL_USERNAME: root
TEST_MYSQL_PASSWORD:
commands:
- make test
- make test-mysql
- TEST_CACHE_ENABLE=true make test-mysql
- TEST_QUOTE_POLICY=reserved make test-mysql
volumes:
- name: cache
path: /go
- name: test-mysql-utf8mb4
image: golang:1.15
depends_on:
- test-mysql
environment:
GO111MODULE: "on"
GOPROXY: "https://goproxy.io"
CGO_ENABLED: 1
GOMODCACHE: '/drone/src/pkg.mod'
GOCACHE: '/drone/src/pkg.build'
TEST_MYSQL_HOST: mysql
TEST_MYSQL_CHARSET: utf8mb4
TEST_MYSQL_DBNAME: xorm_test
TEST_MYSQL_USERNAME: root
TEST_MYSQL_PASSWORD:
commands:
- make test-mysql
- TEST_CACHE_ENABLE=true make test-mysql
- TEST_QUOTE_POLICY=reserved make test-mysql
when:
event:
- push
- pull_request
volumes:
- name: cache
path: /go
- name: test-mysql8
image: golang:1.12
- name: test-mymysql
pull: default
image: golang:1.15
depends_on:
- test-mysql-utf8mb4
environment:
GO111MODULE: "on"
GOPROXY: "https://goproxy.cn"
GOPROXY: "https://goproxy.io"
CGO_ENABLED: 1
GOMODCACHE: '/drone/src/pkg.mod'
GOCACHE: '/drone/src/pkg.build'
TEST_MYSQL_HOST: mysql:3306
TEST_MYSQL_DBNAME: xorm_test
TEST_MYSQL_USERNAME: root
TEST_MYSQL_PASSWORD:
commands:
- make test-mymysql
- TEST_CACHE_ENABLE=true make test-mymysql
- TEST_QUOTE_POLICY=reserved make test-mymysql
volumes:
- name: cache
path: /go
- name: rebuild-cache
image: meltwater/drone-cache
depends_on:
- test-mysql
- test-mysql-utf8mb4
- test-mymysql
pull: true
settings:
backend: "filesystem"
rebuild: true
cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}'
archive_format: "gzip"
filesystem_cache_root: "/go"
mount:
- pkg.mod
- pkg.build
volumes:
- name: cache
path: /go
volumes:
- name: cache
temp: {}
services:
- name: mysql
pull: default
image: mysql:5.7
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: xorm_test
---
kind: pipeline
name: test-mysql8
depends_on:
- test-mysql
- test-sqlite
steps:
- name: restore-cache
image: meltwater/drone-cache
pull: always
settings:
backend: "filesystem"
restore: true
cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}'
archive_format: "gzip"
filesystem_cache_root: "/go"
mount:
- pkg.mod
- pkg.build
volumes:
- name: cache
path: /go
- name: test-mysql8
image: golang:1.15
environment:
GO111MODULE: "on"
GOPROXY: "https://goproxy.io"
CGO_ENABLED: 1
GOMODCACHE: '/drone/src/pkg.mod'
GOCACHE: '/drone/src/pkg.build'
TEST_MYSQL_HOST: mysql8
TEST_MYSQL_CHARSET: utf8mb4
TEST_MYSQL_DBNAME: xorm_test
@ -63,58 +293,70 @@ steps:
- make test-mysql
- TEST_CACHE_ENABLE=true make test-mysql
- TEST_QUOTE_POLICY=reserved make test-mysql
when:
event:
- push
- pull_request
volumes:
- name: cache
path: /go
- name: test-mysql-utf8mb4
image: golang:1.12
- name: rebuild-cache
image: meltwater/drone-cache:dev
pull: true
depends_on:
- test-mysql
environment:
GO111MODULE: "on"
GOPROXY: "https://goproxy.cn"
TEST_MYSQL_HOST: mysql
TEST_MYSQL_CHARSET: utf8mb4
TEST_MYSQL_DBNAME: xorm_test
TEST_MYSQL_USERNAME: root
TEST_MYSQL_PASSWORD:
commands:
- make test-mysql
- TEST_CACHE_ENABLE=true make test-mysql
- TEST_QUOTE_POLICY=reserved make test-mysql
when:
event:
- push
- pull_request
- test-mysql8
settings:
backend: "filesystem"
rebuild: true
cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}'
archive_format: "gzip"
filesystem_cache_root: "/go"
mount:
- pkg.mod
- pkg.build
volumes:
- name: cache
path: /go
- name: test-mymysql
volumes:
- name: cache
temp: {}
services:
- name: mysql8
pull: default
image: golang:1.12
depends_on:
- test-mysql-utf8mb4
image: mysql:8.0
environment:
GO111MODULE: "on"
GOPROXY: "https://goproxy.cn"
TEST_MYSQL_HOST: mysql:3306
TEST_MYSQL_DBNAME: xorm_test
TEST_MYSQL_USERNAME: root
TEST_MYSQL_PASSWORD:
commands:
- make test-mymysql
- TEST_CACHE_ENABLE=true make test-mymysql
- TEST_QUOTE_POLICY=reserved make test-mymysql
when:
event:
- push
- pull_request
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: xorm_test
---
kind: pipeline
name: test-mariadb
depends_on:
- test-mysql8
steps:
- name: restore-cache
image: meltwater/drone-cache
pull: always
settings:
backend: "filesystem"
restore: true
cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}'
archive_format: "gzip"
filesystem_cache_root: "/go"
mount:
- pkg.mod
- pkg.build
volumes:
- name: cache
path: /go
- name: test-mariadb
image: golang:1.12
image: golang:1.15
environment:
GO111MODULE: "on"
GOPROXY: "https://goproxy.cn"
GOPROXY: "https://goproxy.io"
CGO_ENABLED: 1
GOMODCACHE: '/drone/src/pkg.mod'
GOCACHE: '/drone/src/pkg.build'
TEST_MYSQL_HOST: mariadb
TEST_MYSQL_CHARSET: utf8mb4
TEST_MYSQL_DBNAME: xorm_test
@ -124,17 +366,71 @@ steps:
- make test-mysql
- TEST_CACHE_ENABLE=true make test-mysql
- TEST_QUOTE_POLICY=reserved make test-mysql
when:
event:
- push
- pull_request
volumes:
- name: cache
path: /go
- name: rebuild-cache
image: meltwater/drone-cache:dev
depends_on:
- test-mariadb
pull: true
settings:
backend: "filesystem"
rebuild: true
cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}'
archive_format: "gzip"
filesystem_cache_root: "/go"
mount:
- pkg.mod
- pkg.build
volumes:
- name: cache
path: /go
volumes:
- name: cache
temp: {}
services:
- name: mariadb
pull: default
image: mariadb:10.4
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: xorm_test
---
kind: pipeline
name: test-postgres
depends_on:
- test-mariadb
steps:
- name: restore-cache
image: meltwater/drone-cache
pull: always
settings:
backend: "filesystem"
restore: true
cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}'
archive_format: "gzip"
filesystem_cache_root: "/go"
mount:
- pkg.mod
- pkg.build
volumes:
- name: cache
path: /go
- name: test-postgres
pull: default
image: golang:1.12
image: golang:1.15
environment:
GO111MODULE: "on"
GOPROXY: "https://goproxy.cn"
GOPROXY: "https://goproxy.io"
CGO_ENABLED: 1
GOMODCACHE: '/drone/src/pkg.mod'
GOCACHE: '/drone/src/pkg.build'
TEST_PGSQL_HOST: pgsql
TEST_PGSQL_DBNAME: xorm_test
TEST_PGSQL_USERNAME: postgres
@ -143,19 +439,21 @@ steps:
- make test-postgres
- TEST_CACHE_ENABLE=true make test-postgres
- TEST_QUOTE_POLICY=reserved make test-postgres
when:
event:
- push
- pull_request
volumes:
- name: cache
path: /go
- name: test-postgres-schema
pull: default
image: golang:1.12
image: golang:1.15
depends_on:
- test-postgres
environment:
GO111MODULE: "on"
GOPROXY: "https://goproxy.cn"
GOPROXY: "https://goproxy.io"
CGO_ENABLED: 1
GOMODCACHE: '/drone/src/pkg.mod'
GOCACHE: '/drone/src/pkg.build'
TEST_PGSQL_HOST: pgsql
TEST_PGSQL_SCHEMA: xorm
TEST_PGSQL_DBNAME: xorm_test
@ -165,17 +463,72 @@ steps:
- make test-postgres
- TEST_CACHE_ENABLE=true make test-postgres
- TEST_QUOTE_POLICY=reserved make test-postgres
when:
event:
- push
- pull_request
volumes:
- name: cache
path: /go
- name: rebuild-cache
image: meltwater/drone-cache:dev
pull: true
depends_on:
- test-postgres-schema
settings:
backend: "filesystem"
rebuild: true
cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}'
archive_format: "gzip"
filesystem_cache_root: "/go"
mount:
- pkg.mod
- pkg.build
volumes:
- name: cache
path: /go
volumes:
- name: cache
temp: {}
services:
- name: pgsql
pull: default
image: postgres:9.5
environment:
POSTGRES_DB: xorm_test
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
---
kind: pipeline
name: test-mssql
depends_on:
- test-postgres
steps:
- name: restore-cache
image: meltwater/drone-cache
pull: always
settings:
backend: "filesystem"
restore: true
cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}'
archive_format: "gzip"
filesystem_cache_root: "/go"
mount:
- pkg.mod
- pkg.build
volumes:
- name: cache
path: /go
- name: test-mssql
pull: default
image: golang:1.12
image: golang:1.15
environment:
GO111MODULE: "on"
GOPROXY: "https://goproxy.cn"
GOPROXY: "https://goproxy.io"
CGO_ENABLED: 1
GOMODCACHE: '/drone/src/pkg.mod'
GOCACHE: '/drone/src/pkg.build'
TEST_MSSQL_HOST: mssql
TEST_MSSQL_DBNAME: xorm_test
TEST_MSSQL_USERNAME: sa
@ -185,17 +538,70 @@ steps:
- TEST_CACHE_ENABLE=true make test-mssql
- TEST_QUOTE_POLICY=reserved make test-mssql
- TEST_MSSQL_DEFAULT_VARCHAR=NVARCHAR TEST_MSSQL_DEFAULT_CHAR=NCHAR make test-mssql
when:
event:
- push
- pull_request
volumes:
- name: cache
path: /go
- name: rebuild-cache
image: meltwater/drone-cache:dev
pull: true
settings:
backend: "filesystem"
rebuild: true
cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}'
archive_format: "gzip"
filesystem_cache_root: "/go"
mount:
- pkg.mod
- pkg.build
volumes:
- name: cache
path: /go
volumes:
- name: cache
temp: {}
services:
- name: mssql
pull: default
image: microsoft/mssql-server-linux:latest
environment:
ACCEPT_EULA: Y
SA_PASSWORD: yourStrong(!)Password
MSSQL_PID: Developer
---
kind: pipeline
name: test-tidb
depends_on:
- test-mssql
steps:
- name: restore-cache
image: meltwater/drone-cache
pull: always
settings:
backend: "filesystem"
restore: true
cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}'
archive_format: "gzip"
filesystem_cache_root: "/go"
mount:
- pkg.mod
- pkg.build
volumes:
- name: cache
path: /go
- name: test-tidb
pull: default
image: golang:1.12
image: golang:1.15
environment:
GO111MODULE: "on"
GOPROXY: "https://goproxy.cn"
GOPROXY: "https://goproxy.io"
CGO_ENABLED: 1
GOMODCACHE: '/drone/src/pkg.mod'
GOCACHE: '/drone/src/pkg.build'
TEST_TIDB_HOST: "tidb:4000"
TEST_TIDB_DBNAME: xorm_test
TEST_TIDB_USERNAME: root
@ -204,17 +610,66 @@ steps:
- make test-tidb
- TEST_CACHE_ENABLE=true make test-tidb
- TEST_QUOTE_POLICY=reserved make test-tidb
when:
event:
- push
- pull_request
volumes:
- name: cache
path: /go
- name: rebuild-cache
image: meltwater/drone-cache:dev
pull: true
settings:
backend: "filesystem"
rebuild: true
cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}'
archive_format: "gzip"
filesystem_cache_root: "/go"
mount:
- pkg.mod
- pkg.build
volumes:
- name: cache
path: /go
volumes:
- name: cache
temp: {}
services:
- name: tidb
pull: default
image: pingcap/tidb:v3.0.3
---
kind: pipeline
name: test-cockroach
depends_on:
- test-tidb
steps:
- name: restore-cache
image: meltwater/drone-cache
pull: always
settings:
backend: "filesystem"
restore: true
cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}'
archive_format: "gzip"
filesystem_cache_root: "/go"
mount:
- pkg.mod
- pkg.build
volumes:
- name: cache
path: /go
- name: test-cockroach
pull: default
image: golang:1.13
image: golang:1.15
environment:
GO111MODULE: "on"
GOPROXY: "https://goproxy.cn"
GOPROXY: "https://goproxy.io"
CGO_ENABLED: 1
GOMODCACHE: '/drone/src/pkg.mod'
GOCACHE: '/drone/src/pkg.build'
TEST_COCKROACH_HOST: "cockroach:26257"
TEST_COCKROACH_DBNAME: xorm_test
TEST_COCKROACH_USERNAME: root
@ -223,115 +678,62 @@ steps:
- sleep 10
- make test-cockroach
- TEST_CACHE_ENABLE=true make test-cockroach
when:
event:
- push
- pull_request
volumes:
- name: cache
path: /go
- name: merge_coverage
pull: default
image: golang:1.12
environment:
GO111MODULE: "on"
GOPROXY: "https://goproxy.cn"
depends_on:
- test-vet
- test-sqlite
- test-mysql
- test-mysql8
- test-mymysql
- test-postgres
- test-postgres-schema
- test-mssql
- test-tidb
- test-cockroach
commands:
- make coverage
when:
event:
- push
- pull_request
- name: rebuild-cache
image: meltwater/drone-cache:dev
pull: true
settings:
backend: "filesystem"
rebuild: true
cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}'
archive_format: "gzip"
filesystem_cache_root: "/go"
mount:
- pkg.mod
- pkg.build
volumes:
- name: cache
path: /go
volumes:
- name: cache
temp: {}
services:
- name: mysql
pull: default
image: mysql:5.7
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: xorm_test
when:
event:
- push
- tag
- pull_request
- name: mysql8
pull: default
image: mysql:8.0
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: xorm_test
when:
event:
- push
- tag
- pull_request
- name: mariadb
pull: default
image: mariadb:10.4
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: xorm_test
when:
event:
- push
- tag
- pull_request
- name: pgsql
pull: default
image: postgres:9.5
environment:
POSTGRES_DB: xorm_test
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
when:
event:
- push
- tag
- pull_request
- name: mssql
pull: default
image: microsoft/mssql-server-linux:latest
environment:
ACCEPT_EULA: Y
SA_PASSWORD: yourStrong(!)Password
MSSQL_PID: Developer
when:
event:
- push
- tag
- pull_request
- name: tidb
pull: default
image: pingcap/tidb:v3.0.3
when:
event:
- push
- tag
- pull_request
- name: cockroach
pull: default
image: cockroachdb/cockroach:v19.2.4
commands:
- /cockroach/cockroach start --insecure
---
kind: pipeline
name: merge_coverage
depends_on:
- testing
- test-sqlite
- test-mysql
- test-mysql8
- test-mariadb
- test-postgres
- test-mssql
- test-tidb
- test-cockroach
steps:
- name: merge_coverage
pull: default
image: golang:1.15
environment:
GO111MODULE: "on"
GOPROXY: "https://goproxy.io"
commands:
- make coverage
when:
branch:
- master
event:
- push
- tag
- pull_request
- push
- pull_request

View File

@ -6,7 +6,9 @@ GOFMT ?= gofmt -s
TAGS ?=
SED_INPLACE := sed -i
GOFILES := $(shell find . -name "*.go" -type f)
GO_DIRS := caches contexts integrations convert core dialects internal log migrate names schemas tags
GOFILES := $(wildcard *.go)
GOFILES += $(shell find $(GO_DIRS) -name "*.go" -type f)
INTEGRATION_PACKAGES := xorm.io/xorm/integrations
PACKAGES ?= $(filter-out $(INTEGRATION_PACKAGES),$(shell $(GO) list ./...))

View File

@ -19,6 +19,7 @@ type LevelDBStore struct {
var _ CacheStore = &LevelDBStore{}
// NewLevelDBStore creates a leveldb store
func NewLevelDBStore(dbfile string) (*LevelDBStore, error) {
db := &LevelDBStore{}
h, err := leveldb.OpenFile(dbfile, nil)
@ -29,6 +30,7 @@ func NewLevelDBStore(dbfile string) (*LevelDBStore, error) {
return db, nil
}
// Put implements CacheStore
func (s *LevelDBStore) Put(key string, value interface{}) error {
val, err := Encode(value)
if err != nil {
@ -50,6 +52,7 @@ func (s *LevelDBStore) Put(key string, value interface{}) error {
return err
}
// Get implements CacheStore
func (s *LevelDBStore) Get(key string) (interface{}, error) {
data, err := s.store.Get([]byte(key), nil)
if err != nil {
@ -75,6 +78,7 @@ func (s *LevelDBStore) Get(key string) (interface{}, error) {
return s.v, err
}
// Del implements CacheStore
func (s *LevelDBStore) Del(key string) error {
err := s.store.Delete([]byte(key), nil)
if err != nil {
@ -89,6 +93,7 @@ func (s *LevelDBStore) Del(key string) error {
return err
}
// Close implements CacheStore
func (s *LevelDBStore) Close() {
s.store.Close()
}

View File

@ -6,6 +6,7 @@ package caches
import "sync"
// Manager represents a cache manager
type Manager struct {
cacher Cacher
disableGlobalCache bool
@ -14,6 +15,7 @@ type Manager struct {
cacherLock sync.RWMutex
}
// NewManager creates a cache manager
func NewManager() *Manager {
return &Manager{
cachers: make(map[string]Cacher),
@ -27,12 +29,14 @@ func (mgr *Manager) SetDisableGlobalCache(disable bool) {
}
}
// SetCacher set cacher of table
func (mgr *Manager) SetCacher(tableName string, cacher Cacher) {
mgr.cacherLock.Lock()
mgr.cachers[tableName] = cacher
mgr.cacherLock.Unlock()
}
// GetCacher returns a cache of a table
func (mgr *Manager) GetCacher(tableName string) Cacher {
var cacher Cacher
var ok bool

View File

@ -31,6 +31,7 @@ func NewContextHook(ctx context.Context, sql string, args []interface{}) *Contex
}
}
// End finish the hook invokation
func (c *ContextHook) End(ctx context.Context, result sql.Result, err error) {
c.Ctx = ctx
c.Result = result
@ -38,19 +39,23 @@ func (c *ContextHook) End(ctx context.Context, result sql.Result, err error) {
c.ExecuteTime = time.Now().Sub(c.start)
}
// Hook represents a hook behaviour
type Hook interface {
BeforeProcess(c *ContextHook) (context.Context, error)
AfterProcess(c *ContextHook) error
}
// Hooks implements Hook interface but contains multiple Hook
type Hooks struct {
hooks []Hook
}
// AddHook adds a Hook
func (h *Hooks) AddHook(hooks ...Hook) {
h.hooks = append(h.hooks, hooks...)
}
// BeforeProcess invoked before execute the process
func (h *Hooks) BeforeProcess(c *ContextHook) (context.Context, error) {
ctx := c.Ctx
for _, h := range h.hooks {
@ -63,6 +68,7 @@ func (h *Hooks) BeforeProcess(c *ContextHook) (context.Context, error) {
return ctx, nil
}
// AfterProcess invoked after exetue the process
func (h *Hooks) AfterProcess(c *ContextHook) error {
firstErr := c.Err
for _, h := range h.hooks {

View File

@ -79,32 +79,34 @@ type Base struct {
quoter schemas.Quoter
}
func (b *Base) Quoter() schemas.Quoter {
return b.quoter
// Quoter returns the current database Quoter
func (db *Base) Quoter() schemas.Quoter {
return db.quoter
}
func (b *Base) Init(dialect Dialect, uri *URI) error {
b.dialect, b.uri = dialect, uri
// Init initialize the dialect
func (db *Base) Init(dialect Dialect, uri *URI) error {
db.dialect, db.uri = dialect, uri
return nil
}
func (b *Base) URI() *URI {
return b.uri
// URI returns the uri of database
func (db *Base) URI() *URI {
return db.uri
}
func (b *Base) DBType() schemas.DBType {
return b.uri.DBType
}
func (b *Base) FormatBytes(bs []byte) string {
// FormatBytes formats bytes
func (db *Base) FormatBytes(bs []byte) string {
return fmt.Sprintf("0x%x", bs)
}
// DropTableSQL returns drop table SQL
func (db *Base) DropTableSQL(tableName string) (string, bool) {
quote := db.dialect.Quoter().Quote
return fmt.Sprintf("DROP TABLE IF EXISTS %s", quote(tableName)), true
}
// HasRecords returns true if the SQL has records returned
func (db *Base) HasRecords(queryer core.Queryer, ctx context.Context, query string, args ...interface{}) (bool, error) {
rows, err := queryer.QueryContext(ctx, query, args...)
if err != nil {
@ -118,6 +120,7 @@ func (db *Base) HasRecords(queryer core.Queryer, ctx context.Context, query stri
return false, nil
}
// IsColumnExist returns true if the column of the table exist
func (db *Base) IsColumnExist(queryer core.Queryer, ctx context.Context, tableName, colName string) (bool, error) {
quote := db.dialect.Quoter().Quote
query := fmt.Sprintf(
@ -132,11 +135,13 @@ func (db *Base) IsColumnExist(queryer core.Queryer, ctx context.Context, tableNa
return db.HasRecords(queryer, ctx, query, db.uri.DBName, tableName, colName)
}
// AddColumnSQL returns a SQL to add a column
func (db *Base) AddColumnSQL(tableName string, col *schemas.Column) string {
s, _ := ColumnString(db.dialect, col, true)
return fmt.Sprintf("ALTER TABLE %v ADD %v", db.dialect.Quoter().Quote(tableName), s)
}
// CreateIndexSQL returns a SQL to create index
func (db *Base) CreateIndexSQL(tableName string, index *schemas.Index) string {
quoter := db.dialect.Quoter()
var unique string
@ -150,6 +155,7 @@ func (db *Base) CreateIndexSQL(tableName string, index *schemas.Index) string {
quoter.Join(index.Cols, ","))
}
// DropIndexSQL returns a SQL to drop index
func (db *Base) DropIndexSQL(tableName string, index *schemas.Index) string {
quote := db.dialect.Quoter().Quote
var name string
@ -161,16 +167,19 @@ func (db *Base) DropIndexSQL(tableName string, index *schemas.Index) string {
return fmt.Sprintf("DROP INDEX %v ON %s", quote(name), quote(tableName))
}
// ModifyColumnSQL returns a SQL to modify SQL
func (db *Base) ModifyColumnSQL(tableName string, col *schemas.Column) string {
s, _ := ColumnString(db.dialect, col, false)
return fmt.Sprintf("ALTER TABLE %s MODIFY COLUMN %s", tableName, s)
}
func (b *Base) ForUpdateSQL(query string) string {
// ForUpdateSQL returns for updateSQL
func (db *Base) ForUpdateSQL(query string) string {
return query + " FOR UPDATE"
}
func (b *Base) SetParams(params map[string]string) {
// SetParams set params
func (db *Base) SetParams(params map[string]string) {
}
var (

View File

@ -284,7 +284,7 @@ func (db *mssql) SQLType(c *schemas.Column) string {
case schemas.TimeStampz:
res = "DATETIMEOFFSET"
c.Length = 7
case schemas.MediumInt:
case schemas.MediumInt, schemas.UnsignedInt:
res = schemas.Int
case schemas.Text, schemas.MediumText, schemas.TinyText, schemas.LongText, schemas.Json:
res = db.defaultVarchar + "(MAX)"
@ -296,7 +296,7 @@ func (db *mssql) SQLType(c *schemas.Column) string {
case schemas.TinyInt:
res = schemas.TinyInt
c.Length = 0
case schemas.BigInt:
case schemas.BigInt, schemas.UnsignedBigInt:
res = schemas.BigInt
c.Length = 0
case schemas.NVarchar:

View File

@ -254,6 +254,10 @@ func (db *mysql) SQLType(c *schemas.Column) string {
c.Length = 40
case schemas.Json:
res = schemas.Text
case schemas.UnsignedInt:
res = schemas.Int
case schemas.UnsignedBigInt:
res = schemas.BigInt
default:
res = t
}
@ -271,6 +275,11 @@ func (db *mysql) SQLType(c *schemas.Column) string {
} else if hasLen1 {
res += "(" + strconv.Itoa(c.Length) + ")"
}
if c.SQLType.Name == schemas.UnsignedBigInt || c.SQLType.Name == schemas.UnsignedInt {
res += " UNSIGNED"
}
return res
}
@ -331,16 +340,16 @@ func (db *mysql) GetColumns(queryer core.Queryer, ctx context.Context, tableName
col := new(schemas.Column)
col.Indexes = make(map[string]int)
var columnName, isNullable, colType, colKey, extra, comment string
var alreadyQuoted bool
var columnName, nullableStr, colType, colKey, extra, comment string
var alreadyQuoted, isUnsigned bool
var colDefault *string
err = rows.Scan(&columnName, &isNullable, &colDefault, &colType, &colKey, &extra, &comment, &alreadyQuoted)
err = rows.Scan(&columnName, &nullableStr, &colDefault, &colType, &colKey, &extra, &comment, &alreadyQuoted)
if err != nil {
return nil, nil, err
}
col.Name = strings.Trim(columnName, "` ")
col.Comment = comment
if "YES" == isNullable {
if nullableStr == "YES" {
col.Nullable = true
}
@ -351,8 +360,15 @@ func (db *mysql) GetColumns(queryer core.Queryer, ctx context.Context, tableName
col.DefaultIsEmpty = true
}
fields := strings.Fields(colType)
if len(fields) == 2 && fields[1] == "unsigned" {
isUnsigned = true
}
colType = fields[0]
cts := strings.Split(colType, "(")
colName := cts[0]
// Remove the /* mariadb-5.3 */ suffix from coltypes
colName = strings.TrimSuffix(colName, "/* mariadb-5.3 */")
colType = strings.ToUpper(colName)
var len1, len2 int
if len(cts) == 2 {
@ -387,11 +403,8 @@ func (db *mysql) GetColumns(queryer core.Queryer, ctx context.Context, tableName
}
}
}
if colType == "FLOAT UNSIGNED" {
colType = "FLOAT"
}
if colType == "DOUBLE UNSIGNED" {
colType = "DOUBLE"
if isUnsigned {
colType = "UNSIGNED " + colType
}
col.Length = len1
col.Length2 = len2

View File

@ -833,12 +833,12 @@ func (db *postgres) SQLType(c *schemas.Column) string {
case schemas.Bit:
res = schemas.Boolean
return res
case schemas.MediumInt, schemas.Int, schemas.Integer:
case schemas.MediumInt, schemas.Int, schemas.Integer, schemas.UnsignedInt:
if c.IsAutoIncrement {
return schemas.Serial
}
return schemas.Integer
case schemas.BigInt:
case schemas.BigInt, schemas.UnsignedBigInt:
if c.IsAutoIncrement {
return schemas.BigSerial
}
@ -1052,6 +1052,10 @@ WHERE n.nspname= s.table_schema AND c.relkind = 'r'::char AND c.relname = $1%s A
}
}
if colDefault != nil && *colDefault == "unique_rowid()" { // ignore the system column added by cockroach
continue
}
col.Name = strings.Trim(colName, `" `)
if colDefault != nil {

View File

@ -193,7 +193,8 @@ func (db *sqlite3) SQLType(c *schemas.Column) string {
case schemas.Char, schemas.Varchar, schemas.NVarchar, schemas.TinyText,
schemas.Text, schemas.MediumText, schemas.LongText, schemas.Json:
return schemas.Text
case schemas.Bit, schemas.TinyInt, schemas.SmallInt, schemas.MediumInt, schemas.Int, schemas.Integer, schemas.BigInt:
case schemas.Bit, schemas.TinyInt, schemas.SmallInt, schemas.MediumInt, schemas.Int, schemas.Integer, schemas.BigInt,
schemas.UnsignedBigInt, schemas.UnsignedInt:
return schemas.Integer
case schemas.Float, schemas.Double, schemas.Real:
return schemas.Real

View File

@ -1321,6 +1321,7 @@ func (engine *Engine) SetSchema(schema string) {
engine.dialect.URI().SetSchema(schema)
}
// AddHook adds a context Hook
func (engine *Engine) AddHook(hook contexts.Hook) {
engine.db.AddHook(hook)
}
@ -1336,7 +1337,7 @@ func (engine *Engine) tbNameWithSchema(v string) string {
return dialects.TableNameWithSchema(engine.dialect, v)
}
// ContextHook creates a session with the context
// Context creates a session with the context
func (engine *Engine) Context(ctx context.Context) *Session {
session := engine.NewSession()
session.isAutoClose = true

View File

@ -79,7 +79,7 @@ func (eg *EngineGroup) Close() error {
return nil
}
// ContextHook returned a group session
// Context returned a group session
func (eg *EngineGroup) Context(ctx context.Context) *Session {
sess := eg.NewSession()
sess.isAutoClose = true
@ -144,6 +144,7 @@ func (eg *EngineGroup) SetLogger(logger interface{}) {
}
}
// AddHook adds Hook
func (eg *EngineGroup) AddHook(hook contexts.Hook) {
eg.Engine.AddHook(hook)
for i := 0; i < len(eg.slaves); i++ {

4
go.mod
View File

@ -1,9 +1,9 @@
module xorm.io/xorm
go 1.11
go 1.13
require (
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc
github.com/denisenkom/go-mssqldb v0.9.0
github.com/go-sql-driver/mysql v1.5.0
github.com/lib/pq v1.7.0
github.com/mattn/go-sqlite3 v1.14.6

4
go.sum
View File

@ -2,8 +2,8 @@ gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGq
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc h1:VRRKCwnzqk8QCaRC4os14xoKDdbHqqlJtJA0oc1ZAjg=
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/denisenkom/go-mssqldb v0.9.0 h1:RSohk2RsiZqLZ0zCjtfn3S4Gp4exhpBWHyQ7D0yGjAk=
github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=

View File

@ -189,6 +189,10 @@ func TestSetSchema(t *testing.T) {
}
func TestImport(t *testing.T) {
if testEngine.Dialect().URI().DBType != schemas.MYSQL {
t.Skip()
return
}
sess := testEngine.NewSession()
defer sess.Close()
assert.NoError(t, sess.Begin())

View File

@ -757,6 +757,8 @@ func TestAutoIncrTag(t *testing.T) {
assert.True(t, cols[0].IsAutoIncrement)
assert.True(t, cols[0].IsPrimaryKey)
assert.Equal(t, "id", cols[0].Name)
assert.True(t, cols[0].DefaultIsEmpty)
assert.EqualValues(t, "", cols[0].Default)
type TestAutoIncr2 struct {
Id int64 `xorm:"id"`
@ -770,6 +772,8 @@ func TestAutoIncrTag(t *testing.T) {
assert.False(t, cols[0].IsAutoIncrement)
assert.False(t, cols[0].IsPrimaryKey)
assert.Equal(t, "id", cols[0].Name)
assert.True(t, cols[0].DefaultIsEmpty)
assert.EqualValues(t, "", cols[0].Default)
type TestAutoIncr3 struct {
Id int64 `xorm:"'ID'"`
@ -783,6 +787,8 @@ func TestAutoIncrTag(t *testing.T) {
assert.False(t, cols[0].IsAutoIncrement)
assert.False(t, cols[0].IsPrimaryKey)
assert.Equal(t, "ID", cols[0].Name)
assert.True(t, cols[0].DefaultIsEmpty)
assert.EqualValues(t, "", cols[0].Default)
type TestAutoIncr4 struct {
Id int64 `xorm:"pk"`
@ -796,6 +802,8 @@ func TestAutoIncrTag(t *testing.T) {
assert.False(t, cols[0].IsAutoIncrement)
assert.True(t, cols[0].IsPrimaryKey)
assert.Equal(t, "id", cols[0].Name)
assert.True(t, cols[0].DefaultIsEmpty)
assert.EqualValues(t, "", cols[0].Default)
}
func TestTagComment(t *testing.T) {
@ -809,6 +817,16 @@ func TestTagComment(t *testing.T) {
Id int64 `xorm:"comment(主键)"`
}
tb, err := testEngine.TableInfo(new(TestComment1))
assert.NoError(t, err)
cols := tb.Columns()
assert.EqualValues(t, 1, len(cols))
assert.False(t, cols[0].IsAutoIncrement)
assert.False(t, cols[0].IsPrimaryKey)
assert.Equal(t, "id", cols[0].Name)
assert.True(t, cols[0].DefaultIsEmpty)
assert.EqualValues(t, "", cols[0].Default)
assert.NoError(t, testEngine.Sync2(new(TestComment1)))
tables, err := testEngine.DBMetas()
@ -823,6 +841,16 @@ func TestTagComment(t *testing.T) {
Id int64 `xorm:"comment('主键')"`
}
tb, err = testEngine.TableInfo(new(TestComment2))
assert.NoError(t, err)
cols = tb.Columns()
assert.EqualValues(t, 1, len(cols))
assert.False(t, cols[0].IsAutoIncrement)
assert.False(t, cols[0].IsPrimaryKey)
assert.Equal(t, "id", cols[0].Name)
assert.True(t, cols[0].DefaultIsEmpty)
assert.EqualValues(t, "", cols[0].Default)
assert.NoError(t, testEngine.Sync2(new(TestComment2)))
tables, err = testEngine.DBMetas()
@ -841,6 +869,28 @@ func TestTagDefault(t *testing.T) {
Age int `xorm:"default(10)"`
}
tb, err := testEngine.TableInfo(new(DefaultStruct))
assert.NoError(t, err)
cols := tb.Columns()
assert.EqualValues(t, 3, len(cols))
assert.True(t, cols[0].IsAutoIncrement)
assert.True(t, cols[0].IsPrimaryKey)
assert.Equal(t, "id", cols[0].Name)
assert.True(t, cols[0].DefaultIsEmpty)
assert.EqualValues(t, "", cols[0].Default)
assert.False(t, cols[1].IsAutoIncrement)
assert.False(t, cols[1].IsPrimaryKey)
assert.Equal(t, "name", cols[1].Name)
assert.True(t, cols[1].DefaultIsEmpty)
assert.EqualValues(t, "", cols[1].Default)
assert.False(t, cols[2].IsAutoIncrement)
assert.False(t, cols[2].IsPrimaryKey)
assert.Equal(t, "age", cols[2].Name)
assert.False(t, cols[2].DefaultIsEmpty)
assert.EqualValues(t, "10", cols[2].Default)
assertSync(t, new(DefaultStruct))
tables, err := testEngine.DBMetas()
@ -880,10 +930,33 @@ func TestTagDefault2(t *testing.T) {
assert.NoError(t, PrepareEngine())
type DefaultStruct2 struct {
Id int64
Name string
Id int64
Name string
NullDefault string `xorm:"default('NULL')"`
}
tb, err := testEngine.TableInfo(new(DefaultStruct2))
assert.NoError(t, err)
cols := tb.Columns()
assert.EqualValues(t, 3, len(cols))
assert.True(t, cols[0].IsAutoIncrement)
assert.True(t, cols[0].IsPrimaryKey)
assert.Equal(t, "id", cols[0].Name)
assert.True(t, cols[0].DefaultIsEmpty)
assert.EqualValues(t, "", cols[0].Default)
assert.False(t, cols[1].IsAutoIncrement)
assert.False(t, cols[1].IsPrimaryKey)
assert.Equal(t, "name", cols[1].Name)
assert.True(t, cols[1].DefaultIsEmpty)
assert.EqualValues(t, "", cols[1].Default)
assert.False(t, cols[2].IsAutoIncrement)
assert.False(t, cols[2].IsPrimaryKey)
assert.Equal(t, "null_default", cols[2].Name)
assert.False(t, cols[2].DefaultIsEmpty)
assert.EqualValues(t, "'NULL'", cols[2].Default)
assertSync(t, new(DefaultStruct2))
tables, err := testEngine.DBMetas()

View File

@ -8,6 +8,7 @@ import (
"database/sql"
"flag"
"fmt"
"net/url"
"os"
"strings"
"testing"
@ -97,6 +98,13 @@ func createEngine(dbType, connStr string) error {
return fmt.Errorf("db.Exec: %v", err)
}
db.Close()
case schemas.SQLITE, "sqlite":
u, err := url.Parse(connStr)
if err != nil {
return err
}
connStr = u.Path
*ignoreSelectUpdate = true
default:
*ignoreSelectUpdate = true
}
@ -164,10 +172,12 @@ func createEngine(dbType, connStr string) error {
return nil
}
// PrepareEngine prepare tests ORM engine
func PrepareEngine() error {
return createEngine(dbType, connString)
}
// MainTest the tests entrance
func MainTest(m *testing.M) {
flag.Parse()

View File

@ -375,3 +375,30 @@ func TestCustomType2(t *testing.T) {
fmt.Println(users)
}
func TestUnsigned(t *testing.T) {
type MyUnsignedStruct struct {
Id uint64
}
assert.NoError(t, PrepareEngine())
assertSync(t, new(MyUnsignedStruct))
tables, err := testEngine.DBMetas()
assert.NoError(t, err)
assert.EqualValues(t, 1, len(tables))
assert.EqualValues(t, 1, len(tables[0].Columns()))
switch testEngine.Dialect().URI().DBType {
case schemas.SQLITE:
assert.EqualValues(t, "INTEGER", tables[0].Columns()[0].SQLType.Name)
case schemas.MYSQL:
assert.EqualValues(t, "UNSIGNED BIGINT", tables[0].Columns()[0].SQLType.Name)
case schemas.POSTGRES:
assert.EqualValues(t, "BIGINT", tables[0].Columns()[0].SQLType.Name)
case schemas.MSSQL:
assert.EqualValues(t, "BIGINT", tables[0].Columns()[0].SQLType.Name)
default:
assert.False(t, true, "Unsigned is not implemented")
}
}

View File

@ -6,15 +6,15 @@ package json
import "encoding/json"
// JSONInterface represents an interface to handle json data
type JSONInterface interface {
// Interface represents an interface to handle json data
type Interface interface {
Marshal(v interface{}) ([]byte, error)
Unmarshal(data []byte, v interface{}) error
}
var (
// DefaultJSONHandler default json handler
DefaultJSONHandler JSONInterface = StdJSON{}
DefaultJSONHandler Interface = StdJSON{}
)
// StdJSON implements JSONInterface via encoding/json

View File

@ -8,6 +8,7 @@ import (
"fmt"
)
// IndexName returns index name
func IndexName(tableName, idxName string) string {
return fmt.Sprintf("IDX_%v_%v", tableName, idxName)
}

View File

@ -8,6 +8,7 @@ import (
"reflect"
)
// ReflectValue returns value of a bean
func ReflectValue(bean interface{}) reflect.Value {
return reflect.Indirect(reflect.ValueOf(bean))
}

View File

@ -8,6 +8,7 @@ import (
"strings"
)
// IsSubQuery returns true if it contains a sub query
func IsSubQuery(tbName string) bool {
const selStr = "select"
if len(tbName) <= len(selStr)+1 {

View File

@ -8,10 +8,12 @@ import (
"strings"
)
// IndexNoCase index a string in a string with no care of capitalize
func IndexNoCase(s, sep string) int {
return strings.Index(strings.ToLower(s), strings.ToLower(sep))
}
// SplitNoCase split a string by a seperator with no care of capitalize
func SplitNoCase(s, sep string) []string {
idx := IndexNoCase(s, sep)
if idx < 0 {
@ -20,6 +22,7 @@ func SplitNoCase(s, sep string) []string {
return strings.Split(s, s[idx:idx+len(sep)])
}
// SplitNNoCase split n by a seperator with no care of capitalize
func SplitNNoCase(s, sep string, n int) []string {
idx := IndexNoCase(s, sep)
if idx < 0 {

View File

@ -9,6 +9,7 @@ import (
"time"
)
// Zeroable represents an interface which could know if it's a zero value
type Zeroable interface {
IsZero() bool
}
@ -21,39 +22,39 @@ func IsZero(k interface{}) bool {
return true
}
switch k.(type) {
switch t := k.(type) {
case int:
return k.(int) == 0
return t == 0
case int8:
return k.(int8) == 0
return t == 0
case int16:
return k.(int16) == 0
return t == 0
case int32:
return k.(int32) == 0
return t == 0
case int64:
return k.(int64) == 0
return t == 0
case uint:
return k.(uint) == 0
return t == 0
case uint8:
return k.(uint8) == 0
return t == 0
case uint16:
return k.(uint16) == 0
return t == 0
case uint32:
return k.(uint32) == 0
return t == 0
case uint64:
return k.(uint64) == 0
return t == 0
case float32:
return k.(float32) == 0
return t == 0
case float64:
return k.(float64) == 0
return t == 0
case bool:
return k.(bool) == false
return !t
case string:
return k.(string) == ""
return t == ""
case *time.Time:
return k.(*time.Time) == nilTime || IsTimeZero(*k.(*time.Time))
return t == nilTime || IsTimeZero(*t)
case time.Time:
return IsTimeZero(k.(time.Time))
return IsTimeZero(t)
case Zeroable:
return k.(Zeroable) == nil || k.(Zeroable).IsZero()
case reflect.Value: // for go version less than 1.13 because reflect.Value has no method IsZero
@ -65,6 +66,7 @@ func IsZero(k interface{}) bool {
var zeroType = reflect.TypeOf((*Zeroable)(nil)).Elem()
// IsValueZero returns true if the reflect Value is a zero
func IsValueZero(v reflect.Value) bool {
switch v.Kind() {
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Slice:
@ -88,6 +90,7 @@ func IsValueZero(v reflect.Value) bool {
return false
}
// IsStructZero returns true if the Value is a struct and all fields is zero
func IsStructZero(v reflect.Value) bool {
if !v.IsValid() || v.NumField() == 0 {
return true
@ -120,6 +123,7 @@ func IsStructZero(v reflect.Value) bool {
return true
}
// IsArrayZero returns true is a slice of array is zero
func IsArrayZero(v reflect.Value) bool {
if !v.IsValid() || v.Len() == 0 {
return true
@ -134,11 +138,13 @@ func IsArrayZero(v reflect.Value) bool {
return true
}
// represents all zero times
const (
ZeroTime0 = "0000-00-00 00:00:00"
ZeroTime1 = "0001-01-01 00:00:00"
)
// IsTimeZero return true if a time is zero
func IsTimeZero(t time.Time) bool {
return t.IsZero() || t.Format("2006-01-02 15:04:05") == ZeroTime0 ||
t.Format("2006-01-02 15:04:05") == ZeroTime1

View File

@ -110,10 +110,7 @@ func (m *Migrate) RollbackLast() error {
return err
}
if err := m.RollbackMigration(lastRunnedMigration); err != nil {
return err
}
return nil
return m.RollbackMigration(lastRunnedMigration)
}
func (m *Migrate) getLastRunnedMigration() (*Migration, error) {

View File

@ -106,10 +106,7 @@ func TestInitSchema(t *testing.T) {
if err := tx.Sync2(&Person{}); err != nil {
return err
}
if err := tx.Sync2(&Pet{}); err != nil {
return err
}
return nil
return tx.Sync2(&Pet{})
})
err = m.Migrate()

View File

@ -73,13 +73,16 @@ func (s *SQLType) IsXML() bool {
}
var (
Bit = "BIT"
TinyInt = "TINYINT"
SmallInt = "SMALLINT"
MediumInt = "MEDIUMINT"
Int = "INT"
Integer = "INTEGER"
BigInt = "BIGINT"
Bit = "BIT"
UnsignedBit = "UNSIGNED BIT"
TinyInt = "TINYINT"
SmallInt = "SMALLINT"
MediumInt = "MEDIUMINT"
Int = "INT"
UnsignedInt = "UNSIGNED INT"
Integer = "INTEGER"
BigInt = "BIGINT"
UnsignedBigInt = "UNSIGNED BIGINT"
Enum = "ENUM"
Set = "SET"
@ -136,13 +139,16 @@ var (
Array = "ARRAY"
SqlTypes = map[string]int{
Bit: NUMERIC_TYPE,
TinyInt: NUMERIC_TYPE,
SmallInt: NUMERIC_TYPE,
MediumInt: NUMERIC_TYPE,
Int: NUMERIC_TYPE,
Integer: NUMERIC_TYPE,
BigInt: NUMERIC_TYPE,
Bit: NUMERIC_TYPE,
UnsignedBit: NUMERIC_TYPE,
TinyInt: NUMERIC_TYPE,
SmallInt: NUMERIC_TYPE,
MediumInt: NUMERIC_TYPE,
Int: NUMERIC_TYPE,
UnsignedInt: NUMERIC_TYPE,
Integer: NUMERIC_TYPE,
BigInt: NUMERIC_TYPE,
UnsignedBigInt: NUMERIC_TYPE,
Enum: TEXT_TYPE,
Set: TEXT_TYPE,
@ -280,10 +286,14 @@ var (
// Type2SQLType generate SQLType acorrding Go's type
func Type2SQLType(t reflect.Type) (st SQLType) {
switch k := t.Kind(); k {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32:
st = SQLType{Int, 0, 0}
case reflect.Int64, reflect.Uint64:
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
st = SQLType{UnsignedInt, 0, 0}
case reflect.Int64:
st = SQLType{BigInt, 0, 0}
case reflect.Uint64:
st = SQLType{UnsignedBigInt, 0, 0}
case reflect.Float32:
st = SQLType{Float, 0, 0}
case reflect.Float64:

View File

@ -169,6 +169,7 @@ func (session *Session) db() *core.DB {
return session.engine.db
}
// Engine returns session Engine
func (session *Session) Engine() *Engine {
return session.engine
}
@ -895,7 +896,7 @@ func (session *Session) incrVersionFieldValue(fieldValue *reflect.Value) {
}
}
// ContextHook sets the context on this session
// Context sets the context on this session
func (session *Session) Context(ctx context.Context) *Session {
session.ctx = ctx
return session

View File

@ -17,6 +17,7 @@ import (
)
var (
// ErrObjectIsNil return error of object is nil
ErrObjectIsNil = errors.New("object should not be nil")
)

View File

@ -85,7 +85,7 @@ func (session *Session) Commit() error {
return nil
}
// if current session is in a transaction
// IsInTx if current session is in a transaction
func (session *Session) IsInTx() bool {
return !session.isAutoCommit
}