Merge branch 'master' into jcsalem/fix/nil_ptr_is_nullable
This commit is contained in:
commit
e2b2461cd6
|
@ -901,7 +901,7 @@ func (db *postgres) TableCheckSql(tableName string) (string, []interface{}) {
|
|||
}
|
||||
|
||||
func (db *postgres) ModifyColumnSql(tableName string, col *core.Column) string {
|
||||
if len(db.Schema) == 0 {
|
||||
if len(db.Schema) == 0 || strings.Contains(tableName, ".") {
|
||||
return fmt.Sprintf("alter table %s ALTER COLUMN %s TYPE %s",
|
||||
tableName, col.Name, db.SqlType(col))
|
||||
}
|
||||
|
@ -913,8 +913,8 @@ func (db *postgres) DropIndexSql(tableName string, index *core.Index) string {
|
|||
quote := db.Quote
|
||||
idxName := index.Name
|
||||
|
||||
tableName = strings.Replace(tableName, `"`, "", -1)
|
||||
tableName = strings.Replace(tableName, `.`, "_", -1)
|
||||
tableParts := strings.Split(strings.Replace(tableName, `"`, "", -1), ".")
|
||||
tableName = tableParts[len(tableParts)-1]
|
||||
|
||||
if !strings.HasPrefix(idxName, "UQE_") &&
|
||||
!strings.HasPrefix(idxName, "IDX_") {
|
||||
|
|
|
@ -92,6 +92,7 @@ type EngineInterface interface {
|
|||
Quote(string) string
|
||||
SetCacher(string, core.Cacher)
|
||||
SetConnMaxLifetime(time.Duration)
|
||||
SetColumnMapper(core.IMapper)
|
||||
SetDefaultCacher(core.Cacher)
|
||||
SetLogger(logger core.ILogger)
|
||||
SetLogLevel(core.LogLevel)
|
||||
|
@ -99,6 +100,7 @@ type EngineInterface interface {
|
|||
SetMaxOpenConns(int)
|
||||
SetMaxIdleConns(int)
|
||||
SetSchema(string)
|
||||
SetTableMapper(core.IMapper)
|
||||
SetTZDatabase(tz *time.Location)
|
||||
SetTZLocation(tz *time.Location)
|
||||
ShowExecTime(...bool)
|
||||
|
|
|
@ -729,66 +729,7 @@ func (session *Session) insertMapInterface(m map[string]interface{}) (int64, err
|
|||
args = append(args, m[colName])
|
||||
}
|
||||
|
||||
w := builder.NewWriter()
|
||||
if session.statement.cond.IsValid() {
|
||||
if _, err := w.WriteString(fmt.Sprintf("INSERT INTO %s (", session.engine.Quote(tableName))); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if err := writeStrings(w, append(columns, exprs.colNames...), "`", "`"); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if _, err := w.WriteString(") SELECT "); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if err := session.statement.writeArgs(w, args); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if len(exprs.args) > 0 {
|
||||
if _, err := w.WriteString(","); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if err := exprs.writeArgs(w); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := w.WriteString(fmt.Sprintf(" FROM %s WHERE ", session.engine.Quote(tableName))); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if err := session.statement.cond.WriteTo(w); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
} else {
|
||||
qm := strings.Repeat("?,", len(columns))
|
||||
qm = qm[:len(qm)-1]
|
||||
|
||||
if _, err := w.WriteString(fmt.Sprintf("INSERT INTO %s (`%s`) VALUES (%s)", session.engine.Quote(tableName), strings.Join(columns, "`,`"), qm)); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
w.Append(args...)
|
||||
}
|
||||
|
||||
sql := w.String()
|
||||
args = w.Args()
|
||||
|
||||
if err := session.cacheInsert(tableName); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
res, err := session.exec(sql, args...)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
affected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return affected, nil
|
||||
return session.insertMap(columns, args)
|
||||
}
|
||||
|
||||
func (session *Session) insertMapString(m map[string]string) (int64, error) {
|
||||
|
@ -808,6 +749,7 @@ func (session *Session) insertMapString(m map[string]string) (int64, error) {
|
|||
columns = append(columns, k)
|
||||
}
|
||||
}
|
||||
|
||||
sort.Strings(columns)
|
||||
|
||||
var args = make([]interface{}, 0, len(m))
|
||||
|
@ -815,7 +757,18 @@ func (session *Session) insertMapString(m map[string]string) (int64, error) {
|
|||
args = append(args, m[colName])
|
||||
}
|
||||
|
||||
return session.insertMap(columns, args)
|
||||
}
|
||||
|
||||
func (session *Session) insertMap(columns []string, args []interface{}) (int64, error) {
|
||||
tableName := session.statement.TableName()
|
||||
if len(tableName) <= 0 {
|
||||
return 0, ErrTableNotFound
|
||||
}
|
||||
|
||||
exprs := session.statement.exprColumns
|
||||
w := builder.NewWriter()
|
||||
// if insert where
|
||||
if session.statement.cond.IsValid() {
|
||||
if _, err := w.WriteString(fmt.Sprintf("INSERT INTO %s (", session.engine.Quote(tableName))); err != nil {
|
||||
return 0, err
|
||||
|
@ -853,10 +806,29 @@ func (session *Session) insertMapString(m map[string]string) (int64, error) {
|
|||
qm := strings.Repeat("?,", len(columns))
|
||||
qm = qm[:len(qm)-1]
|
||||
|
||||
if _, err := w.WriteString(fmt.Sprintf("INSERT INTO %s (`%s`) VALUES (%s)", session.engine.Quote(tableName), strings.Join(columns, "`,`"), qm)); err != nil {
|
||||
if _, err := w.WriteString(fmt.Sprintf("INSERT INTO %s (", session.engine.Quote(tableName))); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if err := writeStrings(w, append(columns, exprs.colNames...), "`", "`"); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if _, err := w.WriteString(fmt.Sprintf(") VALUES (%s", qm)); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
w.Append(args...)
|
||||
if len(exprs.args) > 0 {
|
||||
if _, err := w.WriteString(","); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if err := exprs.writeArgs(w); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
if _, err := w.WriteString(")"); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
sql := w.String()
|
||||
|
|
|
@ -928,6 +928,64 @@ func TestInsertWhere(t *testing.T) {
|
|||
assert.EqualValues(t, 5, j5.Index)
|
||||
}
|
||||
|
||||
func TestInsertExpr2(t *testing.T) {
|
||||
assert.NoError(t, prepareEngine())
|
||||
|
||||
type InsertExprsRelease struct {
|
||||
Id int64
|
||||
RepoId int
|
||||
IsTag bool
|
||||
IsDraft bool
|
||||
NumCommits int
|
||||
Sha1 string
|
||||
}
|
||||
|
||||
assertSync(t, new(InsertExprsRelease))
|
||||
|
||||
var ie = InsertExprsRelease{
|
||||
RepoId: 1,
|
||||
IsTag: true,
|
||||
}
|
||||
inserted, err := testEngine.
|
||||
SetExpr("is_draft", true).
|
||||
SetExpr("num_commits", 0).
|
||||
SetExpr("sha1", "").
|
||||
Insert(&ie)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 1, inserted)
|
||||
|
||||
var ie2 InsertExprsRelease
|
||||
has, err := testEngine.ID(ie.Id).Get(&ie2)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, has)
|
||||
assert.EqualValues(t, true, ie2.IsDraft)
|
||||
assert.EqualValues(t, "", ie2.Sha1)
|
||||
assert.EqualValues(t, 0, ie2.NumCommits)
|
||||
assert.EqualValues(t, 1, ie2.RepoId)
|
||||
assert.EqualValues(t, true, ie2.IsTag)
|
||||
|
||||
inserted, err = testEngine.Table(new(InsertExprsRelease)).
|
||||
SetExpr("is_draft", true).
|
||||
SetExpr("num_commits", 0).
|
||||
SetExpr("sha1", "").
|
||||
Insert(map[string]interface{}{
|
||||
"repo_id": 1,
|
||||
"is_tag": true,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 1, inserted)
|
||||
|
||||
var ie3 InsertExprsRelease
|
||||
has, err = testEngine.ID(ie.Id + 1).Get(&ie3)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, has)
|
||||
assert.EqualValues(t, true, ie3.IsDraft)
|
||||
assert.EqualValues(t, "", ie3.Sha1)
|
||||
assert.EqualValues(t, 0, ie3.NumCommits)
|
||||
assert.EqualValues(t, 1, ie3.RepoId)
|
||||
assert.EqualValues(t, true, ie3.IsTag)
|
||||
}
|
||||
|
||||
type NightlyRate struct {
|
||||
ID int64 `xorm:"'id' not null pk BIGINT(20)" json:"id"`
|
||||
}
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
|
||||
package xorm
|
||||
|
||||
import "reflect"
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// IterFunc only use by Iterate
|
||||
type IterFunc func(idx int, bean interface{}) error
|
||||
|
@ -60,10 +62,6 @@ func (session *Session) BufferSize(size int) *Session {
|
|||
}
|
||||
|
||||
func (session *Session) bufferIterate(bean interface{}, fun IterFunc) error {
|
||||
if session.isAutoClose {
|
||||
defer session.Close()
|
||||
}
|
||||
|
||||
var bufferSize = session.statement.bufferSize
|
||||
var limit = session.statement.LimitN
|
||||
if limit > 0 && bufferSize > limit {
|
||||
|
@ -73,9 +71,14 @@ func (session *Session) bufferIterate(bean interface{}, fun IterFunc) error {
|
|||
v := rValue(bean)
|
||||
sliceType := reflect.SliceOf(v.Type())
|
||||
var idx = 0
|
||||
for {
|
||||
session.autoResetStatement = false
|
||||
defer func() {
|
||||
session.autoResetStatement = true
|
||||
}()
|
||||
|
||||
for bufferSize > 0 {
|
||||
slice := reflect.New(sliceType)
|
||||
if err := session.Limit(bufferSize, start).find(slice.Interface(), bean); err != nil {
|
||||
if err := session.NoCache().Limit(bufferSize, start).find(slice.Interface(), bean); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -86,13 +89,13 @@ func (session *Session) bufferIterate(bean interface{}, fun IterFunc) error {
|
|||
idx++
|
||||
}
|
||||
|
||||
start = start + slice.Elem().Len()
|
||||
if limit > 0 && idx+bufferSize > limit {
|
||||
bufferSize = limit - idx
|
||||
if bufferSize > slice.Elem().Len() {
|
||||
break
|
||||
}
|
||||
|
||||
if bufferSize <= 0 || slice.Elem().Len() < bufferSize || idx == limit {
|
||||
break
|
||||
start = start + slice.Elem().Len()
|
||||
if limit > 0 && start+bufferSize > limit {
|
||||
bufferSize = limit - start
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -89,4 +89,15 @@ func TestBufferIterate(t *testing.T) {
|
|||
})
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 7, cnt)
|
||||
|
||||
cnt = 0
|
||||
err = testEngine.Where("id <= 10").BufferSize(2).Iterate(new(UserBufferIterate), func(i int, bean interface{}) error {
|
||||
user := bean.(*UserBufferIterate)
|
||||
assert.EqualValues(t, cnt+1, user.Id)
|
||||
assert.EqualValues(t, true, user.IsMan)
|
||||
cnt++
|
||||
return nil
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 10, cnt)
|
||||
}
|
||||
|
|
|
@ -239,14 +239,20 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
|
|||
for i, colName := range exprColumns.colNames {
|
||||
switch tp := exprColumns.args[i].(type) {
|
||||
case string:
|
||||
colNames = append(colNames, session.engine.Quote(colName)+" = "+tp)
|
||||
if len(tp) == 0 {
|
||||
tp = "''"
|
||||
}
|
||||
colNames = append(colNames, session.engine.Quote(colName)+"="+tp)
|
||||
case *builder.Builder:
|
||||
subQuery, subArgs, err := builder.ToSQL(tp)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
colNames = append(colNames, session.engine.Quote(colName)+" = ("+subQuery+")")
|
||||
colNames = append(colNames, session.engine.Quote(colName)+"=("+subQuery+")")
|
||||
args = append(args, subArgs...)
|
||||
default:
|
||||
colNames = append(colNames, session.engine.Quote(colName)+"=?")
|
||||
args = append(args, exprColumns.args[i])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -294,21 +300,25 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
|
|||
|
||||
st := &session.statement
|
||||
|
||||
var sqlStr string
|
||||
var condArgs []interface{}
|
||||
var condSQL string
|
||||
cond := session.statement.cond.And(autoCond)
|
||||
var (
|
||||
sqlStr string
|
||||
condArgs []interface{}
|
||||
condSQL string
|
||||
cond = session.statement.cond.And(autoCond)
|
||||
|
||||
var doIncVer = (table != nil && table.Version != "" && session.statement.checkVersion)
|
||||
var verValue *reflect.Value
|
||||
doIncVer = isStruct && (table != nil && table.Version != "" && session.statement.checkVersion)
|
||||
verValue *reflect.Value
|
||||
)
|
||||
if doIncVer {
|
||||
verValue, err = table.VersionColumn().ValueOf(bean)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
cond = cond.And(builder.Eq{session.engine.Quote(table.Version): verValue.Interface()})
|
||||
colNames = append(colNames, session.engine.Quote(table.Version)+" = "+session.engine.Quote(table.Version)+" + 1")
|
||||
if verValue != nil {
|
||||
cond = cond.And(builder.Eq{session.engine.Quote(table.Version): verValue.Interface()})
|
||||
colNames = append(colNames, session.engine.Quote(table.Version)+" = "+session.engine.Quote(table.Version)+" + 1")
|
||||
}
|
||||
}
|
||||
|
||||
condSQL, condArgs, err = builder.ToSQL(cond)
|
||||
|
|
|
@ -1359,3 +1359,90 @@ func TestUpdateAlias(t *testing.T) {
|
|||
assert.EqualValues(t, 2, ue.NumIssues)
|
||||
assert.EqualValues(t, "lunny xiao", ue.Name)
|
||||
}
|
||||
|
||||
func TestUpdateExprs2(t *testing.T) {
|
||||
assert.NoError(t, prepareEngine())
|
||||
|
||||
type UpdateExprsRelease struct {
|
||||
Id int64
|
||||
RepoId int
|
||||
IsTag bool
|
||||
IsDraft bool
|
||||
NumCommits int
|
||||
Sha1 string
|
||||
}
|
||||
|
||||
assertSync(t, new(UpdateExprsRelease))
|
||||
|
||||
var uer = UpdateExprsRelease{
|
||||
RepoId: 1,
|
||||
IsTag: false,
|
||||
IsDraft: false,
|
||||
NumCommits: 1,
|
||||
Sha1: "sha1",
|
||||
}
|
||||
inserted, err := testEngine.Insert(&uer)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 1, inserted)
|
||||
|
||||
updated, err := testEngine.
|
||||
Where("repo_id = ? AND is_tag = ?", 1, false).
|
||||
SetExpr("is_draft", true).
|
||||
SetExpr("num_commits", 0).
|
||||
SetExpr("sha1", "").
|
||||
Update(new(UpdateExprsRelease))
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 1, updated)
|
||||
|
||||
var uer2 UpdateExprsRelease
|
||||
has, err := testEngine.ID(uer.Id).Get(&uer2)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, has)
|
||||
assert.EqualValues(t, 1, uer2.RepoId)
|
||||
assert.EqualValues(t, false, uer2.IsTag)
|
||||
assert.EqualValues(t, true, uer2.IsDraft)
|
||||
assert.EqualValues(t, 0, uer2.NumCommits)
|
||||
assert.EqualValues(t, "", uer2.Sha1)
|
||||
}
|
||||
|
||||
func TestUpdateMap3(t *testing.T) {
|
||||
assert.NoError(t, prepareEngine())
|
||||
|
||||
type UpdateMapUser struct {
|
||||
Id uint64 `xorm:"PK autoincr"`
|
||||
Name string `xorm:""`
|
||||
Ver uint64 `xorm:"version"`
|
||||
}
|
||||
|
||||
oldMapper := testEngine.GetColumnMapper()
|
||||
defer func() {
|
||||
testEngine.SetColumnMapper(oldMapper)
|
||||
}()
|
||||
|
||||
mapper := core.NewPrefixMapper(core.SnakeMapper{}, "F")
|
||||
testEngine.SetColumnMapper(mapper)
|
||||
|
||||
assertSync(t, new(UpdateMapUser))
|
||||
|
||||
_, err := testEngine.Table(new(UpdateMapUser)).Insert(map[string]interface{}{
|
||||
"Fname": "first user name",
|
||||
"Fver": 1,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
update := map[string]interface{}{
|
||||
"Fname": "user name",
|
||||
"Fver": 1,
|
||||
}
|
||||
rows, err := testEngine.Table(new(UpdateMapUser)).ID(1).Update(update)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 1, rows)
|
||||
|
||||
update = map[string]interface{}{
|
||||
"Name": "user name",
|
||||
"Ver": 1,
|
||||
}
|
||||
rows, err = testEngine.Table(new(UpdateMapUser)).ID(1).Update(update)
|
||||
assert.Error(t, err)
|
||||
assert.EqualValues(t, 0, rows)
|
||||
}
|
||||
|
|
|
@ -69,10 +69,18 @@ func (exprs *exprParams) writeArgs(w *builder.BytesWriter) error {
|
|||
if _, err := w.WriteString(")"); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
case string:
|
||||
if arg == "" {
|
||||
arg = "''"
|
||||
}
|
||||
if _, err := w.WriteString(fmt.Sprintf("%v", arg)); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
if _, err := w.WriteString("?"); err != nil {
|
||||
return err
|
||||
}
|
||||
w.Append(arg)
|
||||
}
|
||||
if i != len(exprs.args)-1 {
|
||||
if _, err := w.WriteString(","); err != nil {
|
||||
|
|
Loading…
Reference in New Issue