Improve insert (#1583)
Improve insert Reviewed-on: https://gitea.com/xorm/xorm/pulls/1583
This commit is contained in:
parent
8b100bb7d4
commit
f238bb9d07
11
error.go
11
error.go
|
@ -6,7 +6,6 @@ package xorm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -23,13 +22,3 @@ var (
|
||||||
// ErrConditionType condition type unsupported
|
// ErrConditionType condition type unsupported
|
||||||
ErrConditionType = errors.New("Unsupported condition type")
|
ErrConditionType = errors.New("Unsupported condition type")
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrFieldIsNotExist columns does not exist
|
|
||||||
type ErrFieldIsNotExist struct {
|
|
||||||
FieldName string
|
|
||||||
TableName string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e ErrFieldIsNotExist) Error() string {
|
|
||||||
return fmt.Sprintf("field %s is not valid on table %s", e.FieldName, e.TableName)
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
// Copyright 2020 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 (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"xorm.io/builder"
|
||||||
|
"xorm.io/xorm/schemas"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (statement *Statement) writeInsertOutput(buf *strings.Builder, table *schemas.Table) error {
|
||||||
|
if statement.dialect.URI().DBType == schemas.MSSQL && len(table.AutoIncrement) > 0 {
|
||||||
|
if _, err := buf.WriteString(" OUTPUT Inserted."); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := buf.WriteString(table.AutoIncrement); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (statement *Statement) GenInsertSQL(colNames []string, args []interface{}) (string, []interface{}, error) {
|
||||||
|
var (
|
||||||
|
table = statement.RefTable
|
||||||
|
tableName = statement.TableName()
|
||||||
|
exprs = statement.ExprColumns
|
||||||
|
colPlaces = strings.Repeat("?, ", len(colNames))
|
||||||
|
)
|
||||||
|
if exprs.Len() <= 0 && len(colPlaces) > 0 {
|
||||||
|
colPlaces = colPlaces[0 : len(colPlaces)-2]
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf = builder.NewWriter()
|
||||||
|
if _, err := buf.WriteString("INSERT INTO "); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := statement.dialect.Quoter().QuoteTo(buf.Builder, tableName); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(colPlaces) <= 0 {
|
||||||
|
if statement.dialect.URI().DBType == schemas.MYSQL {
|
||||||
|
if _, err := buf.WriteString(" VALUES ()"); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := statement.writeInsertOutput(buf.Builder, table); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
if _, err := buf.WriteString(" DEFAULT VALUES"); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if _, err := buf.WriteString(" ("); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := statement.dialect.Quoter().JoinWrite(buf.Builder, append(colNames, exprs.ColNames...), ","); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if statement.Conds().IsValid() {
|
||||||
|
if _, err := buf.WriteString(")"); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
if err := statement.writeInsertOutput(buf.Builder, table); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
if _, err := buf.WriteString(" SELECT "); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := statement.WriteArgs(buf, args); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(exprs.Args) > 0 {
|
||||||
|
if _, err := buf.WriteString(","); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := exprs.WriteArgs(buf); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := buf.WriteString(" FROM "); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := statement.dialect.Quoter().QuoteTo(buf.Builder, tableName); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := buf.WriteString(" WHERE "); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := statement.Conds().WriteTo(buf); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buf.Append(args...)
|
||||||
|
|
||||||
|
if _, err := buf.WriteString(")"); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
if err := statement.writeInsertOutput(buf.Builder, table); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
if _, err := buf.WriteString(" VALUES ("); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
if _, err := buf.WriteString(colPlaces); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := exprs.WriteArgs(buf); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := buf.WriteString(")"); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(table.AutoIncrement) > 0 && statement.dialect.URI().DBType == schemas.POSTGRES {
|
||||||
|
if _, err := buf.WriteString(" RETURNING "); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
if err := statement.dialect.Quoter().QuoteTo(buf.Builder, table.AutoIncrement); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.String(), buf.Args(), nil
|
||||||
|
}
|
10
session.go
10
session.go
|
@ -22,6 +22,16 @@ import (
|
||||||
"xorm.io/xorm/schemas"
|
"xorm.io/xorm/schemas"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ErrFieldIsNotExist columns does not exist
|
||||||
|
type ErrFieldIsNotExist struct {
|
||||||
|
FieldName string
|
||||||
|
TableName string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ErrFieldIsNotExist) Error() string {
|
||||||
|
return fmt.Sprintf("field %s is not valid on table %s", e.FieldName, e.TableName)
|
||||||
|
}
|
||||||
|
|
||||||
// ErrFieldIsNotValid is not valid
|
// ErrFieldIsNotValid is not valid
|
||||||
type ErrFieldIsNotValid struct {
|
type ErrFieldIsNotValid struct {
|
||||||
FieldName string
|
FieldName string
|
||||||
|
|
|
@ -326,8 +326,6 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
|
||||||
return 0, ErrTableNotFound
|
return 0, ErrTableNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
table := session.statement.RefTable
|
|
||||||
|
|
||||||
// handle BeforeInsertProcessor
|
// handle BeforeInsertProcessor
|
||||||
for _, closure := range session.beforeClosures {
|
for _, closure := range session.beforeClosures {
|
||||||
closure(bean)
|
closure(bean)
|
||||||
|
@ -338,100 +336,19 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
|
||||||
processor.BeforeInsert()
|
processor.BeforeInsert()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tableName = session.statement.TableName()
|
||||||
|
table := session.statement.RefTable
|
||||||
|
|
||||||
colNames, args, err := session.genInsertColumns(bean)
|
colNames, args, err := session.genInsertColumns(bean)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
exprs := session.statement.ExprColumns
|
sqlStr, args, err := session.statement.GenInsertSQL(colNames, args)
|
||||||
colPlaces := strings.Repeat("?, ", len(colNames))
|
if err != nil {
|
||||||
if exprs.Len() <= 0 && len(colPlaces) > 0 {
|
|
||||||
colPlaces = colPlaces[0 : len(colPlaces)-2]
|
|
||||||
}
|
|
||||||
|
|
||||||
var tableName = session.statement.TableName()
|
|
||||||
var output string
|
|
||||||
if session.engine.dialect.URI().DBType == schemas.MSSQL && len(table.AutoIncrement) > 0 {
|
|
||||||
output = fmt.Sprintf(" OUTPUT Inserted.%s", table.AutoIncrement)
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf = builder.NewWriter()
|
|
||||||
if _, err := buf.WriteString(fmt.Sprintf("INSERT INTO %s", session.engine.Quote(tableName))); err != nil {
|
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(colPlaces) <= 0 {
|
|
||||||
if session.engine.dialect.URI().DBType == schemas.MYSQL {
|
|
||||||
if _, err := buf.WriteString(" VALUES ()"); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if _, err := buf.WriteString(fmt.Sprintf("%s DEFAULT VALUES", output)); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if _, err := buf.WriteString(" ("); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := session.engine.dialect.Quoter().JoinWrite(buf.Builder, append(colNames, exprs.ColNames...), ","); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if session.statement.Conds().IsValid() {
|
|
||||||
if _, err := buf.WriteString(fmt.Sprintf(")%s SELECT ", output)); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := session.statement.WriteArgs(buf, args); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(exprs.Args) > 0 {
|
|
||||||
if _, err := buf.WriteString(","); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := exprs.WriteArgs(buf); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := buf.WriteString(fmt.Sprintf(" FROM %v WHERE ", session.engine.Quote(tableName))); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := session.statement.Conds().WriteTo(buf); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
buf.Append(args...)
|
|
||||||
|
|
||||||
if _, err := buf.WriteString(fmt.Sprintf(")%s VALUES (%v",
|
|
||||||
output,
|
|
||||||
colPlaces)); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := exprs.WriteArgs(buf); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := buf.WriteString(")"); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(table.AutoIncrement) > 0 && session.engine.dialect.URI().DBType == schemas.POSTGRES {
|
|
||||||
if _, err := buf.WriteString(" RETURNING " + session.engine.Quote(table.AutoIncrement)); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sqlStr := buf.String()
|
|
||||||
args = buf.Args()
|
|
||||||
|
|
||||||
handleAfterInsertProcessorFunc := func(bean interface{}) {
|
handleAfterInsertProcessorFunc := func(bean interface{}) {
|
||||||
if session.isAutoCommit {
|
if session.isAutoCommit {
|
||||||
for _, closure := range session.afterClosures {
|
for _, closure := range session.afterClosures {
|
||||||
|
@ -545,7 +462,8 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
|
||||||
aiValue.Set(int64ToIntValue(id, aiValue.Type()))
|
aiValue.Set(int64ToIntValue(id, aiValue.Type()))
|
||||||
|
|
||||||
return 1, nil
|
return 1, nil
|
||||||
} else {
|
}
|
||||||
|
|
||||||
res, err := session.exec(sqlStr, args...)
|
res, err := session.exec(sqlStr, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
@ -587,7 +505,6 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
|
||||||
|
|
||||||
return res.RowsAffected()
|
return res.RowsAffected()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// InsertOne insert only one struct into database as a record.
|
// InsertOne insert only one struct into database as a record.
|
||||||
// The in parameter bean must a struct or a point to struct. The return
|
// The in parameter bean must a struct or a point to struct. The return
|
||||||
|
|
Loading…
Reference in New Issue