Merge branch 'lunny/test_oracle2'

This commit is contained in:
chendy 2020-08-18 17:34:22 +08:00
commit 912adc5435
20 changed files with 493 additions and 197 deletions

View File

@ -109,6 +109,46 @@ steps:
- push
- pull_request
- name: test-oracle
pull: default
image: golang:1.12
environment:
GO111MODULE: "on"
GOPROXY: "https://goproxy.cn"
TEST_ORACLE_HOST: oracle:1521
TEST_ORACLE_DBNAME: xe
TEST_ORACLE_USERNAME: system
TEST_ORACLE_PASSWORD: oracle
TEST_CACHE_ENABLE: false
commands:
- make test-oracle
- TEST_CACHE_ENABLE=true make test-oracle
when:
event:
- push
- pull_request
- name: test-oracle-schema
pull: default
image: golang:1.12
environment:
GO111MODULE: "on"
GOPROXY: "https://goproxy.cn"
TEST_ORACLE_SCHEMA: xorm
TEST_ORACLE_HOST: oracle:1521
TEST_ORACLE_DBNAME: xe
TEST_ORACLE_USERNAME: system
TEST_ORACLE_PASSWORD: oracle
TEST_CACHE_ENABLE: false
SCHEMA: xorm
commands:
- make test-oracle
- TEST_CACHE_ENABLE=true make test-oracle
when:
event:
- push
- pull_request
- name: test-postgres
pull: default
image: golang:1.12
@ -292,6 +332,18 @@ services:
- tag
- pull_request
- name: oracle
pull: default
image: oracleinanutshell/oracle-xe-11g:latest
environment:
ORACLE_ALLOW_REMOTE: true
ORACLE_ENABLE_XDB: true
when:
event:
- push
- tag
- pull_request
- name: cockroach
pull: default
image: cockroachdb/cockroach:v19.2.4

View File

@ -27,6 +27,12 @@ TEST_MYSQL_DBNAME ?= xorm_test
TEST_MYSQL_USERNAME ?= root
TEST_MYSQL_PASSWORD ?=
TEST_ORACLE_HOST ?= oracle:1521
TEST_ORACLE_SCHEMA ?=
TEST_ORACLE_DBNAME ?= xe
TEST_ORACLE_USERNAME ?= system
TEST_ORACLE_PASSWORD ?= oracle
TEST_PGSQL_HOST ?= pgsql:5432
TEST_PGSQL_SCHEMA ?=
TEST_PGSQL_DBNAME ?= xorm_test
@ -124,6 +130,23 @@ misspell-check:
fi
misspell -error -i unknwon,destory $(GOFILES)
.PHONY: install-instant-client
install-instant-client:
ifeq ("$(PKG_CONFIG_PATH)", )
wget https://download.oracle.com/otn_software/linux/instantclient/19600/instantclient-basic-linux.x64-19.6.0.0.0dbru.zip
unzip instantclient-basic-linux.x64-19.6.0.0.0dbru.zip -d /usr/local/instantclient
echo "prefixdir=/usr/local/instantclient
libdir=${prefixdir}
includedir=${prefixdir}/sdk/include
Name: OCI
Description: Oracle database driver
Version: 11.2
Libs: -L${libdir} -lclntsh
Cflags: -I${includedir}" > /usr/local/instantclient/oci8.pc
export PKG_CONFIG_PATH=/usr/local/instantclient/oci8.pc
endif
.PHONY: test
test: go-check
$(GO) test $(PACKAGES)
@ -176,6 +199,33 @@ test-mysql\#%: go-check
-conn_str="$(TEST_MYSQL_USERNAME):$(TEST_MYSQL_PASSWORD)@tcp($(TEST_MYSQL_HOST))/$(TEST_MYSQL_DBNAME)?charset=$(TEST_MYSQL_CHARSET)" \
-coverprofile=mysql.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic
.PHONY: test-oracle
test-oracle: test-godror
.PNONY: test-oci8
test-oci8: go-check install-instant-client
$(GO) test $(INTEGRATION_PACKAGES) -v -race -tags=oracle -db=oci8 -schema='$(TEST_ORACLE_SCHEMA)' -cache=$(TEST_CACHE_ENABLE) \
-conn_str="$(TEST_ORACLE_USERNAME):$(TEST_ORACLE_PASSWORD)@$(TEST_ORACLE_HOST)/$(TEST_ORACLE_DBNAME)" \
-coverprofile=oracle.$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic
.PHONY: test-oci8\#%
test-oci8\#%: go-check install-instant-client
$(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -tags=oracle -db=oci8 -schema='$(TEST_PGSQL_SCHEMA)' -cache=$(TEST_CACHE_ENABLE) \
-conn_str="postgres://$(TEST_PGSQL_USERNAME):$(TEST_PGSQL_PASSWORD)@$(TEST_PGSQL_HOST)/$(TEST_PGSQL_DBNAME)" \
-coverprofile=oracle.$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic
.PHONY: test-godror
test-godror: go-check install-instant-client
$(GO) test $(INTEGRATION_PACKAGES) -v -race -tags=oracle -db=godror -schema='$(TEST_ORACLE_SCHEMA)' -cache=$(TEST_CACHE_ENABLE) \
-conn_str="oracle://$(TEST_ORACLE_USERNAME):$(TEST_ORACLE_PASSWORD)@$(TEST_ORACLE_HOST)/$(TEST_ORACLE_DBNAME)" \
-coverprofile=oracle.$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic
.PHONY: test-godror\#%
test-godror\#%: go-check install-instant-client
$(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -tags=oracle -db=godror -schema='$(TEST_ORACLE_SCHEMA)' -cache=$(TEST_CACHE_ENABLE) \
-conn_str="oracle://$(TEST_ORACLE_USERNAME):$(TEST_ORACLE_PASSWORD)@$(TEST_ORACLE_HOST)/$(TEST_ORACLE_DBNAME)" \
-coverprofile=oracle.$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic
.PNONY: test-postgres
test-postgres: go-check
$(GO) test $(INTEGRATION_PACKAGES) -v -race -db=postgres -schema='$(TEST_PGSQL_SCHEMA)' -cache=$(TEST_CACHE_ENABLE) \

View File

@ -48,8 +48,9 @@ Drivers for Go's sql package which currently support database/sql includes:
* MsSql
- [github.com/denisenkom/go-mssqldb](https://github.com/denisenkom/go-mssqldb)
* Oracle
- [github.com/mattn/go-oci8](https://github.com/mattn/go-oci8) (experiment)
* Oracle (experiment)
- [github.com/mattn/go-oci8](https://github.com/mattn/go-oci8)
- [github.com/godror/godror](https://github.com/godror/godror)
## Installation

View File

@ -92,7 +92,6 @@ func BenchmarkOriQuery(b *testing.B) {
if err != nil {
b.Error(err)
}
//fmt.Println(Id, Name, Title, Age, Alias, NickName)
}
rows.Close()
}

View File

@ -7,6 +7,7 @@ import (
// Queryer represents an interface to query a SQL to get data from database
type Queryer interface {
QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row
QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error)
}

View File

@ -59,7 +59,7 @@ type Dialect interface {
GetTables(queryer core.Queryer, ctx context.Context) ([]*schemas.Table, error)
IsTableExist(queryer core.Queryer, ctx context.Context, tableName string) (bool, error)
CreateTableSQL(table *schemas.Table, tableName string) ([]string, bool)
DropTableSQL(tableName string) (string, bool)
DropTableSQL(tableName, autoincrCol string) ([]string, bool)
GetColumns(queryer core.Queryer, ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error)
IsColumnExist(queryer core.Queryer, ctx context.Context, tableName string, colName string) (bool, error)
@ -100,9 +100,9 @@ func (b *Base) FormatBytes(bs []byte) string {
return fmt.Sprintf("0x%x", bs)
}
func (db *Base) DropTableSQL(tableName string) (string, bool) {
func (db *Base) DropTableSQL(tableName, autoincrCol string) ([]string, bool) {
quote := db.dialect.Quoter().Quote
return fmt.Sprintf("DROP TABLE IF EXISTS %s", quote(tableName)), true
return []string{fmt.Sprintf("DROP TABLE IF EXISTS %s", quote(tableName))}, true
}
func (db *Base) HasRecords(queryer core.Queryer, ctx context.Context, query string, args ...interface{}) (bool, error) {
@ -207,7 +207,7 @@ func regDrvsNDialects() bool {
"pgx": {"postgres", func() Driver { return &pqDriverPgx{} }, func() Dialect { return &postgres{} }},
"sqlite3": {"sqlite3", func() Driver { return &sqlite3Driver{} }, func() Dialect { return &sqlite3{} }},
"oci8": {"oracle", func() Driver { return &oci8Driver{} }, func() Dialect { return &oracle{} }},
"goracle": {"oracle", func() Driver { return &goracleDriver{} }, func() Dialect { return &oracle{} }},
"godror": {"oracle", func() Driver { return &godrorDriver{} }, func() Dialect { return &oracle{} }},
}
for driverName, v := range providedDrvsNDialects {

View File

@ -311,10 +311,10 @@ func (db *mssql) AutoIncrStr() string {
return "IDENTITY"
}
func (db *mssql) DropTableSQL(tableName string) (string, bool) {
return fmt.Sprintf("IF EXISTS (SELECT * FROM sysobjects WHERE id = "+
func (db *mssql) DropTableSQL(tableName, autoincrCol string) ([]string, bool) {
return []string{fmt.Sprintf("IF EXISTS (SELECT * FROM sysobjects WHERE id = "+
"object_id(N'%s') and OBJECTPROPERTY(id, N'IsUserTable') = 1) "+
"DROP TABLE \"%s\"", tableName, tableName), true
"DROP TABLE \"%s\"", tableName, tableName)}, true
}
func (db *mssql) IndexCheckSQL(tableName, idxName string) (string, []interface{}) {

View File

@ -6,8 +6,10 @@ package dialects
import (
"context"
"database/sql"
"errors"
"fmt"
"net/url"
"regexp"
"strconv"
"strings"
@ -523,9 +525,9 @@ func (db *oracle) SQLType(c *schemas.Column) string {
case schemas.Binary, schemas.VarBinary, schemas.Blob, schemas.TinyBlob, schemas.MediumBlob, schemas.LongBlob, schemas.Bytea:
return schemas.Blob
case schemas.Time, schemas.DateTime, schemas.TimeStamp:
res = schemas.TimeStamp
res = schemas.Date
case schemas.TimeStampz:
res = "TIMESTAMP WITH TIME ZONE"
res = "TIMESTAMP"
case schemas.Float, schemas.Double, schemas.Numeric, schemas.Decimal:
res = "NUMBER"
case schemas.Text, schemas.MediumText, schemas.LongText, schemas.Json:
@ -556,8 +558,14 @@ func (db *oracle) IsReserved(name string) bool {
return ok
}
func (db *oracle) DropTableSQL(tableName string) (string, bool) {
return fmt.Sprintf("DROP TABLE `%s`", tableName), false
func (db *oracle) DropTableSQL(tableName, autoincrCol string) ([]string, bool) {
var sqls = []string{
fmt.Sprintf("DROP TABLE %s", db.quoter.Quote(tableName)),
}
if autoincrCol != "" {
sqls = append(sqls, fmt.Sprintf("DROP SEQUENCE %s", seqName(tableName)))
}
return sqls, false
}
func (db *oracle) CreateTableSQL(table *schemas.Table, tableName string) ([]string, bool) {
@ -589,8 +597,19 @@ func (db *oracle) CreateTableSQL(table *schemas.Table, tableName string) ([]stri
sql += " ), "
}
sql = sql[:len(sql)-2] + ")"
return []string{sql}, false
var sqls = []string{sql[:len(sql)-2] + ")"}
if table.AutoIncrColumn() != nil {
var sql2 = fmt.Sprintf(`CREATE sequence %s
minvalue 1
nomaxvalue
start with 1
increment by 1
nocycle
nocache`, seqName(tableName))
sqls = append(sqls, sql2)
}
return sqls, false
}
func (db *oracle) SetQuotePolicy(quotePolicy QuotePolicy) {
@ -627,12 +646,35 @@ func (db *oracle) IsColumnExist(queryer core.Queryer, ctx context.Context, table
return db.HasRecords(queryer, ctx, query, args...)
}
func (db *oracle) GetColumns(queryer core.Queryer, ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) {
args := []interface{}{tableName}
s := "SELECT column_name,data_default,data_type,data_length,data_precision,data_scale," +
"nullable FROM USER_TAB_COLUMNS WHERE table_name = :1"
func seqName(tableName string) string {
return "SEQ_" + strings.ToUpper(tableName)
}
rows, err := queryer.QueryContext(ctx, s, args...)
func (db *oracle) GetColumns(queryer core.Queryer, ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) {
//s := "SELECT column_name,data_default,data_type,data_length,data_precision,data_scale," +
// "nullable FROM USER_TAB_COLUMNS WHERE table_name = :1"
s := `select column_name from user_cons_columns
where constraint_name = (select constraint_name from user_constraints
where table_name = :1 and constraint_type ='P')`
var pkName string
err := queryer.QueryRowContext(ctx, s, tableName).Scan(&pkName)
if err != nil {
if err == sql.ErrNoRows {
err = nil
}
return nil, nil, err
}
s = `SELECT USER_TAB_COLS.COLUMN_NAME, USER_TAB_COLS.DATA_DEFAULT, USER_TAB_COLS.DATA_TYPE, USER_TAB_COLS.DATA_LENGTH,
USER_TAB_COLS.data_precision, USER_TAB_COLS.data_scale, USER_TAB_COLS.NULLABLE,
user_col_comments.comments
FROM USER_TAB_COLS
LEFT JOIN user_col_comments on user_col_comments.TABLE_NAME=USER_TAB_COLS.TABLE_NAME
AND user_col_comments.COLUMN_NAME=USER_TAB_COLS.COLUMN_NAME
WHERE USER_TAB_COLS.table_name = :1`
rows, err := queryer.QueryContext(ctx, s, tableName)
if err != nil {
return nil, nil, err
}
@ -644,11 +686,11 @@ func (db *oracle) GetColumns(queryer core.Queryer, ctx context.Context, tableNam
col := new(schemas.Column)
col.Indexes = make(map[string]int)
var colName, colDefault, nullable, dataType, dataPrecision, dataScale *string
var colName, colDefault, nullable, dataType, dataPrecision, dataScale, comment *string
var dataLen int
err = rows.Scan(&colName, &colDefault, &dataType, &dataLen, &dataPrecision,
&dataScale, &nullable)
&dataScale, &nullable, &comment)
if err != nil {
return nil, nil, err
}
@ -665,10 +707,26 @@ func (db *oracle) GetColumns(queryer core.Queryer, ctx context.Context, tableNam
col.Nullable = false
}
var ignore bool
if comment != nil {
col.Comment = *comment
}
if pkName != "" && pkName == col.Name {
col.IsPrimaryKey = true
var dt string
var len1, len2 int
has, err := db.HasRecords(queryer, ctx, "SELECT * FROM USER_SEQUENCES WHERE SEQUENCE_NAME = :1", seqName(tableName))
if err != nil {
return nil, nil, err
}
if has {
col.IsAutoIncrement = true
}
}
var (
ignore bool
dt string
len1, len2 int
)
dts := strings.Split(*dataType, "(")
dt = dts[0]
if len(dts) > 1 {
@ -690,7 +748,7 @@ func (db *oracle) GetColumns(queryer core.Queryer, ctx context.Context, tableNam
col.SQLType = schemas.SQLType{Name: schemas.TimeStampz, DefaultLength: 0, DefaultLength2: 0}
case "NUMBER":
col.SQLType = schemas.SQLType{Name: schemas.Double, DefaultLength: len1, DefaultLength2: len2}
case "LONG", "LONG RAW":
case "LONG", "LONG RAW", "NCLOB", "CLOB":
col.SQLType = schemas.SQLType{Name: schemas.Text, DefaultLength: 0, DefaultLength2: 0}
case "RAW":
col.SQLType = schemas.SQLType{Name: schemas.Binary, DefaultLength: 0, DefaultLength2: 0}
@ -721,12 +779,16 @@ func (db *oracle) GetColumns(queryer core.Queryer, ctx context.Context, tableNam
colSeq = append(colSeq, col.Name)
}
/*select *
from user_tab_comments
where Table_Name='用户表' */
return colSeq, cols, nil
}
func (db *oracle) GetTables(queryer core.Queryer, ctx context.Context) ([]*schemas.Table, error) {
args := []interface{}{}
s := "SELECT table_name FROM user_tables"
s := "SELECT table_name FROM user_tables WHERE TABLESPACE_NAME = :1 AND table_name NOT LIKE :2"
args := []interface{}{strings.ToUpper(db.uri.User), "%$%"}
rows, err := queryer.QueryContext(ctx, s, args...)
if err != nil {
@ -802,38 +864,11 @@ func (db *oracle) Filters() []Filter {
}
}
type goracleDriver struct {
// https://github.com/godror/godror
type godrorDriver struct {
}
func (cfg *goracleDriver) Parse(driverName, dataSourceName string) (*URI, error) {
db := &URI{DBType: schemas.ORACLE}
dsnPattern := regexp.MustCompile(
`^(?:(?P<user>.*?)(?::(?P<passwd>.*))?@)?` + // [user[:password]@]
`(?:(?P<net>[^\(]*)(?:\((?P<addr>[^\)]*)\))?)?` + // [net[(addr)]]
`\/(?P<dbname>.*?)` + // /dbname
`(?:\?(?P<params>[^\?]*))?$`) // [?param1=value1&paramN=valueN]
matches := dsnPattern.FindStringSubmatch(dataSourceName)
// tlsConfigRegister := make(map[string]*tls.Config)
names := dsnPattern.SubexpNames()
for i, match := range matches {
switch names[i] {
case "dbname":
db.DBName = match
}
}
if db.DBName == "" {
return nil, errors.New("dbname is empty")
}
return db, nil
}
type oci8Driver struct {
}
// dataSourceName=user/password@ipv4:port/dbname
// dataSourceName=user/password@[ipv6]:port/dbname
func (p *oci8Driver) Parse(driverName, dataSourceName string) (*URI, error) {
func parseNoProtocol(driverName, dataSourceName string) (*URI, error) {
db := &URI{DBType: schemas.ORACLE}
dsnPattern := regexp.MustCompile(
`^(?P<user>.*)\/(?P<password>.*)@` + // user:password@
@ -852,3 +887,45 @@ func (p *oci8Driver) Parse(driverName, dataSourceName string) (*URI, error) {
}
return db, nil
}
func parseOracle(driverName, dataSourceName string) (*URI, error) {
var connStr = dataSourceName
if !strings.HasPrefix(connStr, "oracle://") {
return parseNoProtocol(driverName, dataSourceName)
}
u, err := url.Parse(connStr)
if err != nil {
return nil, err
}
db := &URI{
DBType: schemas.ORACLE,
Host: u.Hostname(),
Port: u.Port(),
DBName: strings.TrimLeft(u.RequestURI(), "/"),
}
if u.User != nil {
db.User = u.User.Username()
db.Passwd, _ = u.User.Password()
}
if db.DBName == "" {
return nil, errors.New("dbname is empty")
}
return db, nil
}
func (cfg *godrorDriver) Parse(driverName, dataSourceName string) (*URI, error) {
return parseOracle(driverName, dataSourceName)
}
type oci8Driver struct {
}
// dataSourceName=user/password@ipv4:port/dbname
// dataSourceName=user/password@[ipv6]:port/dbname
func (p *oci8Driver) Parse(driverName, dataSourceName string) (*URI, error) {
return parseOracle(driverName, dataSourceName)
}

View File

@ -17,7 +17,11 @@ func FormatTime(dialect Dialect, sqlTypeName string, t time.Time) (v interface{}
s := t.Format("2006-01-02 15:04:05") // time.RFC3339
v = s[11:19]
case schemas.Date:
v = t.Format("2006-01-02")
if dialect.URI().DBType == schemas.ORACLE {
v = t
} else {
v = t.Format("2006-01-02")
}
case schemas.DateTime, schemas.TimeStamp, schemas.Varchar: // !DarthPestilane! format time when sqlTypeName is schemas.Varchar.
v = t.Format("2006-01-02 15:04:05")
case schemas.TimeStampz:

11
go.mod
View File

@ -3,10 +3,13 @@ module xorm.io/xorm
go 1.11
require (
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc
github.com/go-sql-driver/mysql v1.5.0
github.com/lib/pq v1.7.0
github.com/mattn/go-sqlite3 v2.0.3+incompatible
github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4
github.com/go-sql-driver/mysql v1.4.1
github.com/godror/godror v0.12.1
github.com/kr/pretty v0.1.0 // indirect
github.com/lib/pq v1.0.0
github.com/mattn/go-oci8 v0.0.4
github.com/mattn/go-sqlite3 v1.10.0
github.com/stretchr/testify v1.4.0
github.com/syndtr/goleveldb v1.0.0
github.com/ziutek/mymysql v1.5.4

97
go.sum
View File

@ -6,29 +6,60 @@ github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc h1:VRRKCwnzq
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/godror/godror v0.12.1 h1:NXKbt10PLKKsqP0GBbqXgUzE9O5SvppTeAx6jznuBE8=
github.com/godror/godror v0.12.1/go.mod h1:9MVLtu25FBJBMHkPs0m3Ngf/VmwGcLpM2HS8PlNGw9U=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/lib/pq v1.7.0 h1:h93mCPfUSkaul3Ka/VG8uZdmW1uMHDGxzu0NWHuJmHY=
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mattn/go-oci8 v0.0.4 h1:3h8d3VE8buPHoEcApdEoww7Gy3G0SWhwJ0UpniYxBJU=
github.com/mattn/go-oci8 v0.0.4/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI=
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@ -40,19 +71,47 @@ golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0F
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=

View File

@ -62,7 +62,7 @@ func TestCacheFind(t *testing.T) {
}
boxes = make([]MailBox, 0, 2)
assert.NoError(t, testEngine.Alias("a").Where("a.id > -1").Asc("a.id").Find(&boxes))
assert.NoError(t, testEngine.Alias("a").Where("`a`.`id` > -1").Asc("`a`.`id`").Find(&boxes))
assert.EqualValues(t, 2, len(boxes))
for i, box := range boxes {
assert.Equal(t, inserts[i].Id, box.Id)
@ -77,7 +77,7 @@ func TestCacheFind(t *testing.T) {
}
boxes2 := make([]MailBox4, 0, 2)
assert.NoError(t, testEngine.Table("mail_box").Where("mail_box.id > -1").Asc("mail_box.id").Find(&boxes2))
assert.NoError(t, testEngine.Table("mail_box").Where("`mail_box`.`id` > -1").Asc("mail_box.id").Find(&boxes2))
assert.EqualValues(t, 2, len(boxes2))
for i, box := range boxes2 {
assert.Equal(t, inserts[i].Id, box.Id)
@ -164,14 +164,14 @@ func TestCacheGet(t *testing.T) {
assert.NoError(t, err)
var box1 MailBox3
has, err := testEngine.Where("id = ?", inserts[0].Id).Get(&box1)
has, err := testEngine.Where("`id` = ?", inserts[0].Id).Get(&box1)
assert.NoError(t, err)
assert.True(t, has)
assert.EqualValues(t, "user1", box1.Username)
assert.EqualValues(t, "pass1", box1.Password)
var box2 MailBox3
has, err = testEngine.Where("id = ?", inserts[0].Id).Get(&box2)
has, err = testEngine.Where("`id` = ?", inserts[0].Id).Get(&box2)
assert.NoError(t, err)
assert.True(t, has)
assert.EqualValues(t, "user1", box2.Username)

View File

@ -16,10 +16,12 @@ import (
_ "github.com/denisenkom/go-mssqldb"
_ "github.com/go-sql-driver/mysql"
_ "github.com/godror/godror"
_ "github.com/lib/pq"
_ "github.com/mattn/go-sqlite3"
"github.com/stretchr/testify/assert"
_ "github.com/ziutek/mymysql/godrv"
"github.com/stretchr/testify/assert"
)
func TestPing(t *testing.T) {
@ -58,8 +60,7 @@ func TestAutoTransaction(t *testing.T) {
engine.Transaction(func(session *xorm.Session) (interface{}, error) {
_, err := session.Insert(TestTx{Msg: "hi"})
assert.NoError(t, err)
return nil, nil
return nil, err
})
has, err := engine.Exist(&TestTx{Msg: "hi"})

View File

@ -0,0 +1,11 @@
// Copyright 20190 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.
// +build oracle
package integrations
import (
_ "github.com/mattn/go-oci8"
)

View File

@ -37,62 +37,62 @@ func TestBuilder(t *testing.T) {
assert.NoError(t, err)
var cond Condition
has, err := testEngine.Where(builder.Eq{"col_name": "col1"}).Get(&cond)
has, err := testEngine.Where(builder.Eq{"`col_name`": "col1"}).Get(&cond)
assert.NoError(t, err)
assert.Equal(t, true, has, "records should exist")
has, err = testEngine.Where(builder.Eq{"col_name": "col1"}.
And(builder.Eq{"op": OpEqual})).
has, err = testEngine.Where(builder.Eq{"`col_name`": "col1"}.
And(builder.Eq{"`op`": OpEqual})).
NoAutoCondition().
Get(&cond)
assert.NoError(t, err)
assert.Equal(t, true, has, "records should exist")
has, err = testEngine.Where(builder.Eq{"col_name": "col1", "op": OpEqual, "value": "1"}).
has, err = testEngine.Where(builder.Eq{"`col_name`": "col1", "`op`": OpEqual, "`value`": "1"}).
NoAutoCondition().
Get(&cond)
assert.NoError(t, err)
assert.Equal(t, true, has, "records should exist")
has, err = testEngine.Where(builder.Eq{"col_name": "col1"}.
And(builder.Neq{"op": OpEqual})).
has, err = testEngine.Where(builder.Eq{"`col_name`": "col1"}.
And(builder.Neq{"`op`": OpEqual})).
NoAutoCondition().
Get(&cond)
assert.NoError(t, err)
assert.Equal(t, false, has, "records should not exist")
var conds []Condition
err = testEngine.Where(builder.Eq{"col_name": "col1"}.
And(builder.Eq{"op": OpEqual})).
err = testEngine.Where(builder.Eq{"`col_name`": "col1"}.
And(builder.Eq{"`op`": OpEqual})).
Find(&conds)
assert.NoError(t, err)
assert.EqualValues(t, 1, len(conds), "records should exist")
conds = make([]Condition, 0)
err = testEngine.Where(builder.Like{"col_name", "col"}).Find(&conds)
err = testEngine.Where(builder.Like{"`col_name`", "col"}).Find(&conds)
assert.NoError(t, err)
assert.EqualValues(t, 1, len(conds), "records should exist")
conds = make([]Condition, 0)
err = testEngine.Where(builder.Expr("col_name = ?", "col1")).Find(&conds)
err = testEngine.Where(builder.Expr("`col_name` = ?", "col1")).Find(&conds)
assert.NoError(t, err)
assert.EqualValues(t, 1, len(conds), "records should exist")
conds = make([]Condition, 0)
err = testEngine.Where(builder.In("col_name", "col1", "col2")).Find(&conds)
err = testEngine.Where(builder.In("`col_name`", "col1", "col2")).Find(&conds)
assert.NoError(t, err)
assert.EqualValues(t, 1, len(conds), "records should exist")
conds = make([]Condition, 0)
err = testEngine.NotIn("col_name", "col1", "col2").Find(&conds)
err = testEngine.NotIn("`col_name`", "col1", "col2").Find(&conds)
assert.NoError(t, err)
assert.EqualValues(t, 0, len(conds), "records should not exist")
// complex condtions
var where = builder.NewCond()
if true {
where = where.And(builder.Eq{"col_name": "col1"})
where = where.Or(builder.And(builder.In("col_name", "col1", "col2"), builder.Expr("col_name = ?", "col1")))
where = where.And(builder.Eq{"`col_name`": "col1"})
where = where.Or(builder.And(builder.In("`col_name`", "col1", "col2"), builder.Expr("`col_name` = ?", "col1")))
}
conds = make([]Condition, 0)

View File

@ -146,13 +146,12 @@ func createEngine(dbType, connStr string) error {
if err != nil {
return err
}
var tableNames = make([]interface{}, 0, len(tables))
for _, table := range tables {
tableNames = append(tableNames, table.Name)
}
if err = testEngine.DropTables(tableNames...); err != nil {
return err
if err = testEngine.DropTables(table); err != nil {
return err
}
}
return nil
}

View File

@ -25,7 +25,7 @@ func (statement *Statement) writeInsertOutput(buf *strings.Builder, table *schem
}
// GenInsertSQL generates insert beans SQL
func (statement *Statement) GenInsertSQL(colNames []string, args []interface{}) (string, []interface{}, error) {
func (statement *Statement) GenInsertSQL(colNames []string, args []interface{}) (*builder.BytesWriter, error) {
var (
buf = builder.NewWriter()
exprs = statement.ExprColumns
@ -34,110 +34,129 @@ func (statement *Statement) GenInsertSQL(colNames []string, args []interface{})
)
if _, err := buf.WriteString("INSERT INTO "); err != nil {
return "", nil, err
return nil, err
}
if err := statement.dialect.Quoter().QuoteTo(buf.Builder, tableName); err != nil {
return "", nil, err
return nil, err
}
if len(colNames) <= 0 {
var hasInsertColumns = len(colNames) > 0
if !hasInsertColumns && statement.dialect.URI().DBType != schemas.ORACLE {
if statement.dialect.URI().DBType == schemas.MYSQL {
if _, err := buf.WriteString(" VALUES ()"); err != nil {
return "", nil, err
return nil, err
}
} else {
if err := statement.writeInsertOutput(buf.Builder, table); err != nil {
return "", nil, err
return nil, err
}
if _, err := buf.WriteString(" DEFAULT VALUES"); err != nil {
return "", nil, err
return nil, err
}
}
} else {
if _, err := buf.WriteString(" ("); err != nil {
return "", nil, err
return nil, err
}
if len(table.AutoIncrement) > 0 && statement.dialect.URI().DBType == schemas.ORACLE {
colNames = append(colNames, table.AutoIncrement)
}
if err := statement.dialect.Quoter().JoinWrite(buf.Builder, append(colNames, exprs.ColNames...), ","); err != nil {
return "", nil, err
return nil, err
}
if _, err := buf.WriteString(")"); err != nil {
return "", nil, err
return nil, err
}
if err := statement.writeInsertOutput(buf.Builder, table); err != nil {
return "", nil, err
return nil, err
}
if statement.Conds().IsValid() {
if _, err := buf.WriteString(" SELECT "); err != nil {
return "", nil, err
return nil, err
}
if err := statement.WriteArgs(buf, args); err != nil {
return "", nil, err
return nil, err
}
if len(exprs.Args) > 0 {
if _, err := buf.WriteString(","); err != nil {
return "", nil, err
return nil, err
}
}
if err := exprs.WriteArgs(buf); err != nil {
return "", nil, err
return nil, err
}
if _, err := buf.WriteString(" FROM "); err != nil {
return "", nil, err
return nil, err
}
if err := statement.dialect.Quoter().QuoteTo(buf.Builder, tableName); err != nil {
return "", nil, err
return nil, err
}
if _, err := buf.WriteString(" WHERE "); err != nil {
return "", nil, err
return nil, err
}
if err := statement.Conds().WriteTo(buf); err != nil {
return "", nil, err
return nil, err
}
} else {
if _, err := buf.WriteString(" VALUES ("); err != nil {
return "", nil, err
return nil, err
}
if err := statement.WriteArgs(buf, args); err != nil {
return "", nil, err
return nil, err
}
// Insert tablename (id) Values(seq_tablename.nextval)
if len(table.AutoIncrement) > 0 && statement.dialect.URI().DBType == schemas.ORACLE {
if hasInsertColumns {
if _, err := buf.WriteString(","); err != nil {
return nil, err
}
}
if _, err := buf.WriteString("seq_" + tableName + ".nextval"); err != nil {
return nil, err
}
}
if len(exprs.Args) > 0 {
if _, err := buf.WriteString(","); err != nil {
return "", nil, err
return nil, err
}
}
if err := exprs.WriteArgs(buf); err != nil {
return "", nil, err
return nil, err
}
if _, err := buf.WriteString(")"); err != nil {
return "", nil, err
return nil, err
}
}
}
if len(table.AutoIncrement) > 0 && statement.dialect.URI().DBType == schemas.POSTGRES {
if len(table.AutoIncrement) > 0 && (statement.dialect.URI().DBType == schemas.POSTGRES ||
statement.dialect.URI().DBType == schemas.ORACLE) {
if _, err := buf.WriteString(" RETURNING "); err != nil {
return "", nil, err
return nil, err
}
if err := statement.dialect.Quoter().QuoteTo(buf.Builder, table.AutoIncrement); err != nil {
return "", nil, err
return nil, err
}
}
return buf.String(), buf.Args(), nil
return buf, nil
}
// GenInsertMapSQL generates insert map SQL

View File

@ -90,6 +90,10 @@ func NewStatement(dialect dialects.Dialect, tagParser *tags.Parser, defaultTimeZ
return statement
}
func (statement *Statement) Dialect() dialects.Dialect {
return statement.dialect
}
func (statement *Statement) SetTableName(tableName string) {
statement.tableName = tableName
}

View File

@ -119,6 +119,7 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error
colMultiPlaces []string
args []interface{}
cols []*schemas.Column
insertCnt int
)
for i := 0; i < size; i++ {
@ -151,6 +152,14 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error
}
fieldValue := *ptrFieldValue
if col.IsAutoIncrement && utils.IsZero(fieldValue.Interface()) {
if session.engine.dialect.URI().DBType == schemas.ORACLE {
if i == 0 {
colNames = append(colNames, col.Name)
cols = append(cols, col)
}
colPlaces = append(colPlaces, fmt.Sprintf("seq_"+tableName+".nextval + %d", insertCnt))
insertCnt++
}
continue
}
if col.MapType == schemas.ONLYFROMDB {
@ -280,7 +289,9 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
if err := session.statement.SetRefBean(bean); err != nil {
return 0, err
}
if len(session.statement.TableName()) <= 0 {
var tableName = session.statement.TableName()
if tableName == "" {
return 0, ErrTableNotFound
}
@ -294,7 +305,6 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
processor.BeforeInsert()
}
var tableName = session.statement.TableName()
table := session.statement.RefTable
colNames, args, err := session.genInsertColumns(bean)
@ -302,7 +312,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
return 0, err
}
sqlStr, args, err := session.statement.GenInsertSQL(colNames, args)
buf, err := session.statement.GenInsertSQL(colNames, args)
if err != nil {
return 0, err
}
@ -335,14 +345,28 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
cleanupProcessorsClosures(&session.afterClosures) // cleanup after used
}
var dialect = session.statement.Dialect()
// for postgres, many of them didn't implement lastInsertId, so we should
// implemented it ourself.
if session.engine.dialect.URI().DBType == schemas.ORACLE && len(table.AutoIncrement) > 0 {
res, err := session.queryBytes("select seq_atable.currval from dual", args...)
if len(table.AutoIncrement) > 0 && (dialect.URI().DBType == schemas.POSTGRES ||
dialect.URI().DBType == schemas.MSSQL ||
dialect.URI().DBType == schemas.ORACLE) {
var id int64
if dialect.URI().DBType == schemas.ORACLE {
if _, err := buf.WriteString(" INTO :var_name"); err != nil {
return 0, err
}
buf.Append(&id)
}
res, err := session.queryBytes(buf.String(), buf.Args()...)
if err != nil {
return 0, err
}
fmt.Println("=====", id)
defer handleAfterInsertProcessorFunc(bean)
session.cacheInsert(tableName)
@ -356,56 +380,16 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
}
}
if len(res) < 1 {
return 0, errors.New("insert no error but not returned id")
}
idByte := res[0][table.AutoIncrement]
id, err := strconv.ParseInt(string(idByte), 10, 64)
if err != nil || id <= 0 {
return 1, err
}
aiValue, err := table.AutoIncrColumn().ValueOf(bean)
if err != nil {
session.engine.logger.Errorf("%v", err)
}
if aiValue == nil || !aiValue.IsValid() || !aiValue.CanSet() {
return 1, nil
}
aiValue.Set(int64ToIntValue(id, aiValue.Type()))
return 1, nil
} else if len(table.AutoIncrement) > 0 && (session.engine.dialect.URI().DBType == schemas.POSTGRES ||
session.engine.dialect.URI().DBType == schemas.MSSQL) {
res, err := session.queryBytes(sqlStr, args...)
if err != nil {
return 0, err
}
defer handleAfterInsertProcessorFunc(bean)
session.cacheInsert(tableName)
if table.Version != "" && session.statement.CheckVersion {
verValue, err := table.VersionColumn().ValueOf(bean)
if err != nil {
session.engine.logger.Errorf("%v", err)
} else if verValue.IsValid() && verValue.CanSet() {
session.incrVersionFieldValue(verValue)
if dialect.URI().DBType != schemas.ORACLE {
if len(res) < 1 {
return 0, errors.New("insert successfully but not returned id")
}
}
if len(res) < 1 {
return 0, errors.New("insert successfully but not returned id")
}
idByte := res[0][table.AutoIncrement]
id, err := strconv.ParseInt(string(idByte), 10, 64)
if err != nil || id <= 0 {
return 1, err
idByte := res[0][table.AutoIncrement]
id, err = strconv.ParseInt(string(idByte), 10, 64)
if err != nil || id <= 0 {
return 1, err
}
}
aiValue, err := table.AutoIncrColumn().ValueOf(bean)
@ -422,7 +406,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
return 1, nil
}
res, err := session.exec(sqlStr, args...)
res, err := session.exec(buf.String(), buf.Args()...)
if err != nil {
return 0, err
}
@ -537,10 +521,14 @@ func (session *Session) genInsertColumns(bean interface{}) ([]string, []interfac
}
}
if (col.IsCreated || col.IsUpdated) && session.statement.UseAutoTime /*&& isZero(fieldValue.Interface())*/ {
if (col.IsCreated || col.IsUpdated) && session.statement.UseAutoTime {
// if time is non-empty, then set to auto time
val, t := session.engine.nowTime(col)
args = append(args, val)
if session.engine.dialect.URI().DBType == schemas.ORACLE {
args = append(args, t)
} else {
args = append(args, val)
}
var colName = col.Name
session.afterClosures = append(session.afterClosures, func(bean interface{}) {

View File

@ -131,8 +131,33 @@ func (session *Session) DropTable(beanOrTableName interface{}) error {
}
func (session *Session) dropTable(beanOrTableName interface{}) error {
tableName := session.engine.TableName(beanOrTableName)
sqlStr, checkIfExist := session.engine.dialect.DropTableSQL(session.engine.TableName(tableName, true))
var tableName, autoIncrementCol string
switch beanOrTableName.(type) {
case *schemas.Table:
table := beanOrTableName.(*schemas.Table)
tableName = table.Name
if table.AutoIncrColumn() != nil {
autoIncrementCol = table.AutoIncrColumn().Name
}
case string:
tableName = beanOrTableName.(string)
default:
v := utils.ReflectValue(beanOrTableName)
table, err := session.engine.tagParser.ParseWithCache(v)
if err != nil {
return err
}
if session.statement.AltTableName != "" {
tableName = session.statement.AltTableName
} else {
tableName = table.Name
}
if table.AutoIncrColumn() != nil {
autoIncrementCol = table.AutoIncrColumn().Name
}
}
sqlStrs, checkIfExist := session.engine.dialect.DropTableSQL(tableName, autoIncrementCol)
if !checkIfExist {
exist, err := session.engine.dialect.IsTableExist(session.getQueryer(), session.ctx, tableName)
if err != nil {
@ -142,8 +167,11 @@ func (session *Session) dropTable(beanOrTableName interface{}) error {
}
if checkIfExist {
_, err := session.exec(sqlStr)
return err
for _, sqlStr := range sqlStrs {
if _, err := session.exec(sqlStr); err != nil {
return err
}
}
}
return nil
}