2020-02-28 12:29:08 +00:00
|
|
|
// Copyright 2017 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 statements
|
|
|
|
|
|
|
|
import (
|
2021-12-14 01:00:35 +00:00
|
|
|
"os"
|
2020-02-28 12:29:08 +00:00
|
|
|
"reflect"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
2020-03-06 06:43:49 +00:00
|
|
|
"time"
|
2020-02-28 12:29:08 +00:00
|
|
|
|
2020-03-06 06:43:49 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
2023-10-27 15:26:59 +00:00
|
|
|
|
2023-10-27 14:27:46 +00:00
|
|
|
"xorm.io/xorm/v2/dialects"
|
|
|
|
"xorm.io/xorm/v2/names"
|
|
|
|
"xorm.io/xorm/v2/schemas"
|
|
|
|
"xorm.io/xorm/v2/tags"
|
2020-03-06 06:43:49 +00:00
|
|
|
|
|
|
|
_ "github.com/mattn/go-sqlite3"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
dialect dialects.Dialect
|
|
|
|
tagParser *tags.Parser
|
2020-02-28 12:29:08 +00:00
|
|
|
)
|
|
|
|
|
2020-03-06 06:43:49 +00:00
|
|
|
func TestMain(m *testing.M) {
|
|
|
|
var err error
|
|
|
|
dialect, err = dialects.OpenDialect("sqlite3", "./test.db")
|
|
|
|
if err != nil {
|
|
|
|
panic("unknow dialect")
|
|
|
|
}
|
|
|
|
|
2023-10-27 15:26:59 +00:00
|
|
|
tagParser = tags.NewParser("xorm", dialect, names.SnakeMapper{}, names.SnakeMapper{})
|
2020-03-06 06:43:49 +00:00
|
|
|
if tagParser == nil {
|
|
|
|
panic("tags parser is nil")
|
|
|
|
}
|
|
|
|
m.Run()
|
2021-12-14 01:00:35 +00:00
|
|
|
os.Exit(0)
|
2020-03-06 06:43:49 +00:00
|
|
|
}
|
|
|
|
|
2020-02-28 12:29:08 +00:00
|
|
|
var colStrTests = []struct {
|
|
|
|
omitColumn string
|
|
|
|
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`"},
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestColumnsStringGeneration(t *testing.T) {
|
|
|
|
for ndx, testCase := range colStrTests {
|
2020-03-06 06:43:49 +00:00
|
|
|
statement, err := createTestStatement()
|
|
|
|
assert.NoError(t, err)
|
2020-02-28 12:29:08 +00:00
|
|
|
|
|
|
|
if testCase.omitColumn != "" {
|
|
|
|
statement.Omit(testCase.omitColumn)
|
|
|
|
}
|
|
|
|
|
|
|
|
columns := statement.RefTable.Columns()
|
|
|
|
if testCase.onlyToDBColumnNdx >= 0 {
|
|
|
|
columns[testCase.onlyToDBColumnNdx].MapType = schemas.ONLYTODB
|
|
|
|
}
|
|
|
|
|
|
|
|
actual := statement.genColumnStr()
|
|
|
|
|
|
|
|
if actual != testCase.expected {
|
|
|
|
t.Errorf("[test #%d] Unexpected columns string:\nwant:\t%s\nhave:\t%s", ndx, testCase.expected, actual)
|
|
|
|
}
|
|
|
|
if testCase.onlyToDBColumnNdx >= 0 {
|
|
|
|
columns[testCase.onlyToDBColumnNdx].MapType = schemas.TWOSIDES
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-25 16:03:18 +00:00
|
|
|
func TestConvertSQLOrArgs(t *testing.T) {
|
|
|
|
statement, err := createTestStatement()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
// example orm struct
|
|
|
|
// type Table struct {
|
|
|
|
// ID int
|
|
|
|
// del *time.Time `xorm:"deleted"`
|
|
|
|
// }
|
|
|
|
args := []interface{}{
|
|
|
|
"INSERT `table` (`id`, `del`) VALUES (?, ?)", 1, (*time.Time)(nil),
|
|
|
|
}
|
|
|
|
// before fix, here will panic
|
|
|
|
_, _, err = statement.convertSQLOrArgs(args...)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
2020-02-28 12:29:08 +00:00
|
|
|
func BenchmarkGetFlagForColumnWithICKey_ContainsKey(b *testing.B) {
|
|
|
|
b.StopTimer()
|
|
|
|
|
|
|
|
mapCols := make(map[string]bool)
|
|
|
|
cols := []*schemas.Column{
|
|
|
|
{Name: `ID`},
|
|
|
|
{Name: `IsDeleted`},
|
|
|
|
{Name: `Caption`},
|
|
|
|
{Name: `Code1`},
|
|
|
|
{Name: `Code2`},
|
|
|
|
{Name: `Code3`},
|
|
|
|
{Name: `ParentID`},
|
|
|
|
{Name: `Latitude`},
|
|
|
|
{Name: `Longitude`},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, col := range cols {
|
|
|
|
mapCols[strings.ToLower(col.Name)] = true
|
|
|
|
}
|
|
|
|
|
|
|
|
b.StartTimer()
|
|
|
|
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
for _, col := range cols {
|
|
|
|
if _, ok := getFlagForColumn(mapCols, col); !ok {
|
|
|
|
b.Fatal("Unexpected result")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkGetFlagForColumnWithICKey_EmptyMap(b *testing.B) {
|
|
|
|
b.StopTimer()
|
|
|
|
|
|
|
|
mapCols := make(map[string]bool)
|
|
|
|
cols := []*schemas.Column{
|
|
|
|
{Name: `ID`},
|
|
|
|
{Name: `IsDeleted`},
|
|
|
|
{Name: `Caption`},
|
|
|
|
{Name: `Code1`},
|
|
|
|
{Name: `Code2`},
|
|
|
|
{Name: `Code3`},
|
|
|
|
{Name: `ParentID`},
|
|
|
|
{Name: `Latitude`},
|
|
|
|
{Name: `Longitude`},
|
|
|
|
}
|
|
|
|
|
|
|
|
b.StartTimer()
|
|
|
|
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
for _, col := range cols {
|
|
|
|
if _, ok := getFlagForColumn(mapCols, col); ok {
|
|
|
|
b.Fatal("Unexpected result")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type TestType struct {
|
|
|
|
ID int64 `xorm:"ID PK"`
|
|
|
|
IsDeleted bool `xorm:"IsDeleted"`
|
|
|
|
Caption string `xorm:"Caption"`
|
|
|
|
Code1 string `xorm:"Code1"`
|
|
|
|
Code2 string `xorm:"Code2"`
|
|
|
|
Code3 string `xorm:"Code3"`
|
|
|
|
ParentID int64 `xorm:"ParentID"`
|
|
|
|
Latitude float64 `xorm:"Latitude"`
|
|
|
|
Longitude float64 `xorm:"Longitude"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (TestType) TableName() string {
|
|
|
|
return "TestTable"
|
|
|
|
}
|
|
|
|
|
2020-03-06 06:43:49 +00:00
|
|
|
func createTestStatement() (*Statement, error) {
|
|
|
|
statement := NewStatement(dialect, tagParser, time.Local)
|
|
|
|
if err := statement.SetRefValue(reflect.ValueOf(TestType{})); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return statement, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkColumnsStringGeneration(b *testing.B) {
|
|
|
|
b.StopTimer()
|
|
|
|
|
|
|
|
statement, err := createTestStatement()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
testCase := colStrTests[0]
|
|
|
|
|
|
|
|
if testCase.omitColumn != "" {
|
|
|
|
statement.Omit(testCase.omitColumn) // !nemec784! Column must be skipped
|
|
|
|
}
|
|
|
|
|
|
|
|
if testCase.onlyToDBColumnNdx >= 0 {
|
|
|
|
columns := statement.RefTable.Columns()
|
|
|
|
columns[testCase.onlyToDBColumnNdx].MapType = schemas.ONLYTODB // !nemec784! Column must be skipped
|
|
|
|
}
|
|
|
|
|
|
|
|
b.StartTimer()
|
|
|
|
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
actual := statement.genColumnStr()
|
|
|
|
|
|
|
|
if actual != testCase.expected {
|
|
|
|
b.Errorf("Unexpected columns string:\nwant:\t%s\nhave:\t%s", testCase.expected, actual)
|
|
|
|
}
|
2020-02-28 12:29:08 +00:00
|
|
|
}
|
|
|
|
}
|