2013-07-30 12:32:38 +00:00
|
|
|
package orm
|
|
|
|
|
|
|
|
import (
|
|
|
|
"database/sql"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"reflect"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
format_Date = "2006-01-02"
|
|
|
|
format_DateTime = "2006-01-02 15:04:05"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
ErrMissPK = errors.New("missed pk value")
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
operators = map[string]bool{
|
|
|
|
"exact": true,
|
|
|
|
"iexact": true,
|
|
|
|
"contains": true,
|
|
|
|
"icontains": true,
|
|
|
|
// "regex": true,
|
|
|
|
// "iregex": true,
|
|
|
|
"gt": true,
|
|
|
|
"gte": true,
|
|
|
|
"lt": true,
|
|
|
|
"lte": true,
|
|
|
|
"startswith": true,
|
|
|
|
"endswith": true,
|
|
|
|
"istartswith": true,
|
|
|
|
"iendswith": true,
|
|
|
|
"in": true,
|
|
|
|
// "range": true,
|
|
|
|
// "year": true,
|
|
|
|
// "month": true,
|
|
|
|
// "day": true,
|
|
|
|
// "week_day": true,
|
|
|
|
"isnull": true,
|
|
|
|
// "search": true,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
type dbBase struct {
|
|
|
|
ins dbBaser
|
|
|
|
}
|
|
|
|
|
2013-08-07 11:11:44 +00:00
|
|
|
func (d *dbBase) existPk(mi *modelInfo, ind reflect.Value) (column string, value interface{}, exist bool) {
|
|
|
|
|
|
|
|
fi := mi.fields.pk
|
|
|
|
|
|
|
|
v := ind.Field(fi.fieldIndex)
|
|
|
|
if fi.fieldType&IsIntegerField > 0 {
|
|
|
|
vu := v.Int()
|
|
|
|
exist = vu > 0
|
|
|
|
value = vu
|
|
|
|
} else {
|
|
|
|
vu := v.String()
|
|
|
|
exist = vu != ""
|
|
|
|
value = vu
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
2013-08-07 11:11:44 +00:00
|
|
|
|
|
|
|
column = fi.column
|
|
|
|
|
|
|
|
return
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (d *dbBase) collectValues(mi *modelInfo, ind reflect.Value, skipAuto bool, insert bool) (columns []string, values []interface{}, err error) {
|
2013-08-07 11:11:44 +00:00
|
|
|
_, pkValue, _ := d.existPk(mi, ind)
|
2013-07-30 12:32:38 +00:00
|
|
|
for _, column := range mi.fields.orders {
|
|
|
|
fi := mi.fields.columns[column]
|
|
|
|
if fi.dbcol == false || fi.auto && skipAuto {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
var value interface{}
|
2013-08-07 11:11:44 +00:00
|
|
|
if fi.pk {
|
|
|
|
value = pkValue
|
2013-07-30 12:32:38 +00:00
|
|
|
} else {
|
|
|
|
field := ind.Field(fi.fieldIndex)
|
|
|
|
if fi.isFielder {
|
|
|
|
f := field.Addr().Interface().(Fielder)
|
|
|
|
value = f.RawValue()
|
|
|
|
} else {
|
|
|
|
switch fi.fieldType {
|
|
|
|
case TypeBooleanField:
|
|
|
|
value = field.Bool()
|
|
|
|
case TypeCharField, TypeTextField:
|
|
|
|
value = field.String()
|
|
|
|
case TypeFloatField, TypeDecimalField:
|
|
|
|
value = field.Float()
|
|
|
|
case TypeDateField, TypeDateTimeField:
|
|
|
|
value = field.Interface()
|
|
|
|
default:
|
|
|
|
switch {
|
|
|
|
case fi.fieldType&IsPostiveIntegerField > 0:
|
|
|
|
value = field.Uint()
|
|
|
|
case fi.fieldType&IsIntegerField > 0:
|
|
|
|
value = field.Int()
|
|
|
|
case fi.fieldType&IsRelField > 0:
|
|
|
|
if field.IsNil() {
|
|
|
|
value = nil
|
|
|
|
} else {
|
2013-08-07 11:11:44 +00:00
|
|
|
if _, vu, ok := d.existPk(fi.relModelInfo, reflect.Indirect(field)); ok {
|
|
|
|
value = vu
|
2013-07-30 12:32:38 +00:00
|
|
|
} else {
|
|
|
|
value = nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if fi.null == false && value == nil {
|
|
|
|
return nil, nil, errors.New(fmt.Sprintf("field `%s` cannot be NULL", fi.fullName))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch fi.fieldType {
|
|
|
|
case TypeDateField, TypeDateTimeField:
|
|
|
|
if fi.auto_now || fi.auto_now_add && insert {
|
|
|
|
tnow := time.Now()
|
|
|
|
if fi.fieldType == TypeDateField {
|
|
|
|
value = timeFormat(tnow, format_Date)
|
|
|
|
} else {
|
|
|
|
value = timeFormat(tnow, format_DateTime)
|
|
|
|
}
|
|
|
|
if fi.isFielder {
|
|
|
|
f := field.Addr().Interface().(Fielder)
|
|
|
|
f.SetRaw(tnow)
|
|
|
|
} else {
|
|
|
|
field.Set(reflect.ValueOf(tnow))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
columns = append(columns, column)
|
|
|
|
values = append(values, value)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2013-08-09 05:20:19 +00:00
|
|
|
func (d *dbBase) PrepareInsert(q dbQuerier, mi *modelInfo) (stmtQuerier, string, error) {
|
2013-08-10 16:15:26 +00:00
|
|
|
Q := d.ins.TableQuote()
|
|
|
|
|
2013-07-30 12:32:38 +00:00
|
|
|
dbcols := make([]string, 0, len(mi.fields.dbcols))
|
|
|
|
marks := make([]string, 0, len(mi.fields.dbcols))
|
|
|
|
for _, fi := range mi.fields.fieldsDB {
|
|
|
|
if fi.auto == false {
|
|
|
|
dbcols = append(dbcols, fi.column)
|
|
|
|
marks = append(marks, "?")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
qmarks := strings.Join(marks, ", ")
|
2013-08-10 16:15:26 +00:00
|
|
|
sep := fmt.Sprintf("%s, %s", Q, Q)
|
|
|
|
columns := strings.Join(dbcols, sep)
|
|
|
|
|
|
|
|
query := fmt.Sprintf("INSERT INTO %s%s%s (%s%s%s) VALUES (%s)", Q, mi.table, Q, Q, columns, Q, qmarks)
|
|
|
|
|
|
|
|
d.ins.ReplaceMarks(&query)
|
2013-07-30 12:32:38 +00:00
|
|
|
|
2013-08-09 05:20:19 +00:00
|
|
|
stmt, err := q.Prepare(query)
|
|
|
|
return stmt, query, err
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
|
|
|
|
2013-08-09 05:20:19 +00:00
|
|
|
func (d *dbBase) InsertStmt(stmt stmtQuerier, mi *modelInfo, ind reflect.Value) (int64, error) {
|
2013-07-30 12:32:38 +00:00
|
|
|
_, values, err := d.collectValues(mi, ind, true, true)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if res, err := stmt.Exec(values...); err == nil {
|
|
|
|
return res.LastInsertId()
|
|
|
|
} else {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-01 07:51:53 +00:00
|
|
|
func (d *dbBase) Read(q dbQuerier, mi *modelInfo, ind reflect.Value) error {
|
2013-08-07 11:11:44 +00:00
|
|
|
pkColumn, pkValue, ok := d.existPk(mi, ind)
|
2013-08-01 07:51:53 +00:00
|
|
|
if ok == false {
|
|
|
|
return ErrMissPK
|
|
|
|
}
|
|
|
|
|
2013-08-10 16:15:26 +00:00
|
|
|
Q := d.ins.TableQuote()
|
|
|
|
|
|
|
|
sep := fmt.Sprintf("%s, %s", Q, Q)
|
|
|
|
sels := strings.Join(mi.fields.dbcols, sep)
|
2013-08-01 07:51:53 +00:00
|
|
|
colsNum := len(mi.fields.dbcols)
|
|
|
|
|
2013-08-10 16:15:26 +00:00
|
|
|
query := fmt.Sprintf("SELECT %s%s%s FROM %s%s%s WHERE %s%s%s = ?", Q, sels, Q, Q, mi.table, Q, Q, pkColumn, Q)
|
2013-08-01 07:51:53 +00:00
|
|
|
|
|
|
|
refs := make([]interface{}, colsNum)
|
|
|
|
for i, _ := range refs {
|
|
|
|
var ref interface{}
|
|
|
|
refs[i] = &ref
|
|
|
|
}
|
|
|
|
|
2013-08-10 16:15:26 +00:00
|
|
|
d.ins.ReplaceMarks(&query)
|
|
|
|
|
2013-08-07 11:11:44 +00:00
|
|
|
row := q.QueryRow(query, pkValue)
|
2013-08-01 07:51:53 +00:00
|
|
|
if err := row.Scan(refs...); err != nil {
|
2013-08-07 11:11:44 +00:00
|
|
|
if err == sql.ErrNoRows {
|
|
|
|
return ErrNoRows
|
|
|
|
}
|
2013-08-01 07:51:53 +00:00
|
|
|
return err
|
|
|
|
} else {
|
|
|
|
elm := reflect.New(mi.addrField.Elem().Type())
|
|
|
|
mind := reflect.Indirect(elm)
|
|
|
|
|
|
|
|
d.setColsValues(mi, &mind, mi.fields.dbcols, refs)
|
|
|
|
|
|
|
|
ind.Set(mind)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2013-07-30 12:32:38 +00:00
|
|
|
func (d *dbBase) Insert(q dbQuerier, mi *modelInfo, ind reflect.Value) (int64, error) {
|
|
|
|
names, values, err := d.collectValues(mi, ind, true, true)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
|
2013-08-10 16:15:26 +00:00
|
|
|
Q := d.ins.TableQuote()
|
|
|
|
|
2013-07-30 12:32:38 +00:00
|
|
|
marks := make([]string, len(names))
|
|
|
|
for i, _ := range marks {
|
|
|
|
marks[i] = "?"
|
|
|
|
}
|
2013-08-10 16:15:26 +00:00
|
|
|
|
|
|
|
sep := fmt.Sprintf("%s, %s", Q, Q)
|
2013-07-30 12:32:38 +00:00
|
|
|
qmarks := strings.Join(marks, ", ")
|
2013-08-10 16:15:26 +00:00
|
|
|
columns := strings.Join(names, sep)
|
|
|
|
|
|
|
|
query := fmt.Sprintf("INSERT INTO %s%s%s (%s%s%s) VALUES (%s)", Q, mi.table, Q, Q, columns, Q, qmarks)
|
2013-07-30 12:32:38 +00:00
|
|
|
|
2013-08-10 16:15:26 +00:00
|
|
|
d.ins.ReplaceMarks(&query)
|
2013-07-30 12:32:38 +00:00
|
|
|
|
|
|
|
if res, err := q.Exec(query, values...); err == nil {
|
|
|
|
return res.LastInsertId()
|
|
|
|
} else {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *dbBase) Update(q dbQuerier, mi *modelInfo, ind reflect.Value) (int64, error) {
|
2013-08-07 11:11:44 +00:00
|
|
|
pkName, pkValue, ok := d.existPk(mi, ind)
|
2013-07-30 12:32:38 +00:00
|
|
|
if ok == false {
|
|
|
|
return 0, ErrMissPK
|
|
|
|
}
|
|
|
|
setNames, setValues, err := d.collectValues(mi, ind, true, false)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
|
2013-08-10 16:15:26 +00:00
|
|
|
setValues = append(setValues, pkValue)
|
|
|
|
|
|
|
|
Q := d.ins.TableQuote()
|
2013-07-30 12:32:38 +00:00
|
|
|
|
2013-08-10 16:15:26 +00:00
|
|
|
sep := fmt.Sprintf("%s = ?, %s", Q, Q)
|
|
|
|
setColumns := strings.Join(setNames, sep)
|
2013-07-30 12:32:38 +00:00
|
|
|
|
2013-08-10 16:15:26 +00:00
|
|
|
query := fmt.Sprintf("UPDATE %s%s%s SET %s%s%s = ? WHERE %s%s%s = ?", Q, mi.table, Q, Q, setColumns, Q, Q, pkName, Q)
|
|
|
|
|
|
|
|
d.ins.ReplaceMarks(&query)
|
2013-07-30 12:32:38 +00:00
|
|
|
|
|
|
|
if res, err := q.Exec(query, setValues...); err == nil {
|
|
|
|
return res.RowsAffected()
|
|
|
|
} else {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *dbBase) Delete(q dbQuerier, mi *modelInfo, ind reflect.Value) (int64, error) {
|
2013-08-07 11:11:44 +00:00
|
|
|
pkName, pkValue, ok := d.existPk(mi, ind)
|
2013-07-30 12:32:38 +00:00
|
|
|
if ok == false {
|
|
|
|
return 0, ErrMissPK
|
|
|
|
}
|
|
|
|
|
2013-08-10 16:15:26 +00:00
|
|
|
Q := d.ins.TableQuote()
|
|
|
|
|
|
|
|
query := fmt.Sprintf("DELETE FROM %s%s%s WHERE %s%s%s = ?", Q, mi.table, Q, Q, pkName, Q)
|
|
|
|
|
|
|
|
d.ins.ReplaceMarks(&query)
|
2013-07-30 12:32:38 +00:00
|
|
|
|
2013-08-07 11:11:44 +00:00
|
|
|
if res, err := q.Exec(query, pkValue); err == nil {
|
2013-07-30 12:32:38 +00:00
|
|
|
|
|
|
|
num, err := res.RowsAffected()
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if num > 0 {
|
2013-08-07 11:11:44 +00:00
|
|
|
if mi.fields.pk.auto {
|
|
|
|
ind.Field(mi.fields.pk.fieldIndex).SetInt(0)
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
|
|
|
|
2013-08-07 11:11:44 +00:00
|
|
|
err := d.deleteRels(q, mi, []interface{}{pkValue})
|
|
|
|
if err != nil {
|
|
|
|
return num, err
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return num, err
|
|
|
|
} else {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *dbBase) UpdateBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, params Params) (int64, error) {
|
|
|
|
columns := make([]string, 0, len(params))
|
|
|
|
values := make([]interface{}, 0, len(params))
|
|
|
|
for col, val := range params {
|
2013-08-07 11:11:44 +00:00
|
|
|
if fi, ok := mi.fields.GetByAny(col); ok == false || fi.dbcol == false {
|
|
|
|
panic(fmt.Sprintf("wrong field/column name `%s`", col))
|
|
|
|
} else {
|
|
|
|
columns = append(columns, fi.column)
|
|
|
|
values = append(values, val)
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(columns) == 0 {
|
|
|
|
panic("update params cannot empty")
|
|
|
|
}
|
|
|
|
|
|
|
|
tables := newDbTables(mi, d.ins)
|
|
|
|
if qs != nil {
|
|
|
|
tables.parseRelated(qs.related, qs.relDepth)
|
|
|
|
}
|
|
|
|
|
|
|
|
where, args := tables.getCondSql(cond, false)
|
|
|
|
|
2013-08-10 16:15:26 +00:00
|
|
|
values = append(values, args...)
|
|
|
|
|
2013-07-30 12:32:38 +00:00
|
|
|
join := tables.getJoinSql()
|
|
|
|
|
2013-08-10 16:15:26 +00:00
|
|
|
var query string
|
2013-07-30 12:32:38 +00:00
|
|
|
|
2013-08-10 16:15:26 +00:00
|
|
|
Q := d.ins.TableQuote()
|
|
|
|
|
|
|
|
if d.ins.SupportUpdateJoin() {
|
|
|
|
cols := strings.Join(columns, fmt.Sprintf("%s = ?, T0.%s", Q, Q))
|
|
|
|
query = fmt.Sprintf("UPDATE %s%s%s T0 %sSET T0.%s%s%s = ? %s", Q, mi.table, Q, join, Q, cols, Q, where)
|
|
|
|
} else {
|
|
|
|
cols := strings.Join(columns, fmt.Sprintf("%s = ?, %s", Q, Q))
|
|
|
|
supQuery := fmt.Sprintf("SELECT T0.%s%s%s FROM %s%s%s T0 %s%s", Q, mi.fields.pk.column, Q, Q, mi.table, Q, join, where)
|
|
|
|
query = fmt.Sprintf("UPDATE %s%s%s SET %s%s%s = ? WHERE %s%s%s IN ( %s )", Q, mi.table, Q, Q, cols, Q, Q, mi.fields.pk.column, Q, supQuery)
|
|
|
|
}
|
|
|
|
|
|
|
|
d.ins.ReplaceMarks(&query)
|
2013-07-30 12:32:38 +00:00
|
|
|
|
|
|
|
if res, err := q.Exec(query, values...); err == nil {
|
|
|
|
return res.RowsAffected()
|
|
|
|
} else {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *dbBase) deleteRels(q dbQuerier, mi *modelInfo, args []interface{}) error {
|
|
|
|
for _, fi := range mi.fields.fieldsReverse {
|
|
|
|
fi = fi.reverseFieldInfo
|
|
|
|
switch fi.onDelete {
|
|
|
|
case od_CASCADE:
|
2013-08-07 11:11:44 +00:00
|
|
|
cond := NewCondition().And(fmt.Sprintf("%s__in", fi.name), args...)
|
2013-07-30 12:32:38 +00:00
|
|
|
_, err := d.DeleteBatch(q, nil, fi.mi, cond)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
case od_SET_DEFAULT, od_SET_NULL:
|
2013-08-07 11:11:44 +00:00
|
|
|
cond := NewCondition().And(fmt.Sprintf("%s__in", fi.name), args...)
|
2013-07-30 12:32:38 +00:00
|
|
|
params := Params{fi.column: nil}
|
|
|
|
if fi.onDelete == od_SET_DEFAULT {
|
|
|
|
params[fi.column] = fi.initial.String()
|
|
|
|
}
|
|
|
|
_, err := d.UpdateBatch(q, nil, fi.mi, cond, params)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
case od_DO_NOTHING:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *dbBase) DeleteBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition) (int64, error) {
|
|
|
|
tables := newDbTables(mi, d.ins)
|
|
|
|
if qs != nil {
|
|
|
|
tables.parseRelated(qs.related, qs.relDepth)
|
|
|
|
}
|
|
|
|
|
|
|
|
if cond == nil || cond.IsEmpty() {
|
|
|
|
panic("delete operation cannot execute without condition")
|
|
|
|
}
|
|
|
|
|
2013-08-10 16:15:26 +00:00
|
|
|
Q := d.ins.TableQuote()
|
|
|
|
|
2013-07-30 12:32:38 +00:00
|
|
|
where, args := tables.getCondSql(cond, false)
|
|
|
|
join := tables.getJoinSql()
|
|
|
|
|
2013-08-10 16:15:26 +00:00
|
|
|
cols := fmt.Sprintf("T0.%s%s%s", Q, mi.fields.pk.column, Q)
|
|
|
|
query := fmt.Sprintf("SELECT %s FROM %s%s%s T0 %s%s", cols, Q, mi.table, Q, join, where)
|
|
|
|
|
|
|
|
d.ins.ReplaceMarks(&query)
|
2013-07-30 12:32:38 +00:00
|
|
|
|
|
|
|
var rs *sql.Rows
|
|
|
|
if r, err := q.Query(query, args...); err != nil {
|
|
|
|
return 0, err
|
|
|
|
} else {
|
|
|
|
rs = r
|
|
|
|
}
|
|
|
|
|
2013-08-07 11:11:44 +00:00
|
|
|
var ref interface{}
|
2013-07-30 12:32:38 +00:00
|
|
|
|
|
|
|
args = make([]interface{}, 0)
|
|
|
|
cnt := 0
|
|
|
|
for rs.Next() {
|
2013-08-07 11:11:44 +00:00
|
|
|
if err := rs.Scan(&ref); err != nil {
|
2013-07-30 12:32:38 +00:00
|
|
|
return 0, err
|
|
|
|
}
|
2013-08-07 11:11:44 +00:00
|
|
|
args = append(args, reflect.ValueOf(ref).Interface())
|
2013-07-30 12:32:38 +00:00
|
|
|
cnt++
|
|
|
|
}
|
|
|
|
|
|
|
|
if cnt == 0 {
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
|
2013-08-10 16:15:26 +00:00
|
|
|
sql, args := d.ins.GenerateOperatorSql(mi, "in", args)
|
|
|
|
query = fmt.Sprintf("DELETE FROM %s%s%s WHERE %s%s%s %s", Q, mi.table, Q, Q, mi.fields.pk.column, Q, sql)
|
|
|
|
|
|
|
|
d.ins.ReplaceMarks(&query)
|
2013-07-30 12:32:38 +00:00
|
|
|
|
|
|
|
if res, err := q.Exec(query, args...); err == nil {
|
|
|
|
num, err := res.RowsAffected()
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
|
2013-08-07 11:11:44 +00:00
|
|
|
if num > 0 {
|
2013-07-30 12:32:38 +00:00
|
|
|
err := d.deleteRels(q, mi, args)
|
|
|
|
if err != nil {
|
|
|
|
return num, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return num, nil
|
|
|
|
} else {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, container interface{}) (int64, error) {
|
|
|
|
|
|
|
|
val := reflect.ValueOf(container)
|
|
|
|
ind := reflect.Indirect(val)
|
|
|
|
|
|
|
|
errTyp := true
|
|
|
|
|
|
|
|
one := true
|
|
|
|
|
|
|
|
if val.Kind() == reflect.Ptr {
|
2013-08-09 12:14:18 +00:00
|
|
|
fn := ""
|
2013-07-30 12:32:38 +00:00
|
|
|
if ind.Kind() == reflect.Slice {
|
|
|
|
one = false
|
|
|
|
if ind.Type().Elem().Kind() == reflect.Ptr {
|
2013-08-09 12:14:18 +00:00
|
|
|
typ := ind.Type().Elem().Elem()
|
|
|
|
fn = getFullName(typ)
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
2013-08-09 12:14:18 +00:00
|
|
|
} else {
|
|
|
|
fn = getFullName(ind.Type())
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
2013-08-09 12:14:18 +00:00
|
|
|
errTyp = fn != mi.fullName
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if errTyp {
|
2013-08-09 12:14:18 +00:00
|
|
|
panic(fmt.Sprintf("wrong object type `%s` for rows scan, need *[]*%s or *%s", ind.Type(), mi.fullName, mi.fullName))
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rlimit := qs.limit
|
|
|
|
offset := qs.offset
|
|
|
|
if one {
|
|
|
|
rlimit = 0
|
|
|
|
offset = 0
|
|
|
|
}
|
|
|
|
|
2013-08-10 16:15:26 +00:00
|
|
|
Q := d.ins.TableQuote()
|
|
|
|
|
2013-07-30 12:32:38 +00:00
|
|
|
tables := newDbTables(mi, d.ins)
|
|
|
|
tables.parseRelated(qs.related, qs.relDepth)
|
|
|
|
|
|
|
|
where, args := tables.getCondSql(cond, false)
|
|
|
|
orderBy := tables.getOrderSql(qs.orders)
|
2013-08-10 16:15:26 +00:00
|
|
|
limit := tables.getLimitSql(mi, offset, rlimit)
|
2013-07-30 12:32:38 +00:00
|
|
|
join := tables.getJoinSql()
|
|
|
|
|
|
|
|
colsNum := len(mi.fields.dbcols)
|
2013-08-10 16:15:26 +00:00
|
|
|
sep := fmt.Sprintf("%s, T0.%s", Q, Q)
|
|
|
|
cols := fmt.Sprintf("T0.%s%s%s", Q, strings.Join(mi.fields.dbcols, sep), Q)
|
2013-07-30 12:32:38 +00:00
|
|
|
for _, tbl := range tables.tables {
|
|
|
|
if tbl.sel {
|
|
|
|
colsNum += len(tbl.mi.fields.dbcols)
|
2013-08-10 16:15:26 +00:00
|
|
|
sep := fmt.Sprintf("%s, %s.%s", Q, tbl.index, Q)
|
|
|
|
cols += fmt.Sprintf(", %s.%s%s%s", tbl.index, Q, strings.Join(tbl.mi.fields.dbcols, sep), Q)
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-10 16:15:26 +00:00
|
|
|
query := fmt.Sprintf("SELECT %s FROM %s%s%s T0 %s%s%s%s", cols, Q, mi.table, Q, join, where, orderBy, limit)
|
|
|
|
|
|
|
|
d.ins.ReplaceMarks(&query)
|
2013-07-30 12:32:38 +00:00
|
|
|
|
|
|
|
var rs *sql.Rows
|
|
|
|
if r, err := q.Query(query, args...); err != nil {
|
|
|
|
return 0, err
|
|
|
|
} else {
|
|
|
|
rs = r
|
|
|
|
}
|
|
|
|
|
|
|
|
refs := make([]interface{}, colsNum)
|
|
|
|
for i, _ := range refs {
|
2013-07-31 14:11:22 +00:00
|
|
|
var ref interface{}
|
2013-07-30 12:32:38 +00:00
|
|
|
refs[i] = &ref
|
|
|
|
}
|
|
|
|
|
|
|
|
slice := ind
|
|
|
|
|
|
|
|
var cnt int64
|
|
|
|
for rs.Next() {
|
|
|
|
if one && cnt == 0 || one == false {
|
|
|
|
if err := rs.Scan(refs...); err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
elm := reflect.New(mi.addrField.Elem().Type())
|
|
|
|
mind := reflect.Indirect(elm)
|
|
|
|
|
|
|
|
cacheV := make(map[string]*reflect.Value)
|
|
|
|
cacheM := make(map[string]*modelInfo)
|
|
|
|
trefs := refs
|
|
|
|
|
|
|
|
d.setColsValues(mi, &mind, mi.fields.dbcols, refs[:len(mi.fields.dbcols)])
|
|
|
|
trefs = refs[len(mi.fields.dbcols):]
|
|
|
|
|
|
|
|
for _, tbl := range tables.tables {
|
|
|
|
if tbl.sel {
|
|
|
|
last := mind
|
|
|
|
names := ""
|
|
|
|
mmi := mi
|
|
|
|
for _, name := range tbl.names {
|
|
|
|
names += name
|
|
|
|
if val, ok := cacheV[names]; ok {
|
|
|
|
last = *val
|
|
|
|
mmi = cacheM[names]
|
|
|
|
} else {
|
|
|
|
fi := mmi.fields.GetByName(name)
|
|
|
|
lastm := mmi
|
|
|
|
mmi := fi.relModelInfo
|
|
|
|
field := reflect.Indirect(last.Field(fi.fieldIndex))
|
2013-07-31 14:11:22 +00:00
|
|
|
if field.IsValid() {
|
|
|
|
d.setColsValues(mmi, &field, mmi.fields.dbcols, trefs[:len(mmi.fields.dbcols)])
|
|
|
|
for _, fi := range mmi.fields.fieldsReverse {
|
|
|
|
if fi.reverseFieldInfo.mi == lastm {
|
|
|
|
if fi.reverseFieldInfo != nil {
|
|
|
|
field.Field(fi.fieldIndex).Set(last.Addr())
|
|
|
|
}
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
|
|
|
}
|
2013-07-31 14:11:22 +00:00
|
|
|
cacheV[names] = &field
|
|
|
|
cacheM[names] = mmi
|
|
|
|
last = field
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
|
|
|
trefs = trefs[len(mmi.fields.dbcols):]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if one {
|
|
|
|
ind.Set(mind)
|
|
|
|
} else {
|
|
|
|
slice = reflect.Append(slice, mind.Addr())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cnt++
|
|
|
|
}
|
|
|
|
|
|
|
|
if one == false {
|
|
|
|
ind.Set(slice)
|
|
|
|
}
|
|
|
|
|
|
|
|
return cnt, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *dbBase) Count(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition) (cnt int64, err error) {
|
|
|
|
tables := newDbTables(mi, d.ins)
|
|
|
|
tables.parseRelated(qs.related, qs.relDepth)
|
|
|
|
|
|
|
|
where, args := tables.getCondSql(cond, false)
|
|
|
|
tables.getOrderSql(qs.orders)
|
|
|
|
join := tables.getJoinSql()
|
|
|
|
|
2013-08-10 16:15:26 +00:00
|
|
|
Q := d.ins.TableQuote()
|
|
|
|
|
|
|
|
query := fmt.Sprintf("SELECT COUNT(*) FROM %s%s%s T0 %s%s", Q, mi.table, Q, join, where)
|
|
|
|
|
|
|
|
d.ins.ReplaceMarks(&query)
|
2013-07-30 12:32:38 +00:00
|
|
|
|
|
|
|
row := q.QueryRow(query, args...)
|
|
|
|
|
|
|
|
err = row.Scan(&cnt)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2013-08-08 14:34:18 +00:00
|
|
|
func (d *dbBase) getOperatorParams(operator string, args []interface{}) (params []interface{}) {
|
|
|
|
for _, arg := range args {
|
|
|
|
val := reflect.ValueOf(arg)
|
|
|
|
|
|
|
|
if arg == nil {
|
|
|
|
params = append(params, arg)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
kind := val.Kind()
|
|
|
|
|
|
|
|
switch kind {
|
|
|
|
case reflect.Slice, reflect.Array:
|
|
|
|
var args []interface{}
|
|
|
|
for i := 0; i < val.Len(); i++ {
|
|
|
|
v := val.Index(i)
|
|
|
|
|
|
|
|
var vu interface{}
|
|
|
|
if v.CanInterface() {
|
|
|
|
vu = v.Interface()
|
|
|
|
}
|
|
|
|
|
|
|
|
if vu == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
args = append(args, vu)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(args) > 0 {
|
|
|
|
p := d.getOperatorParams(operator, args)
|
|
|
|
params = append(params, p...)
|
|
|
|
}
|
|
|
|
|
|
|
|
case reflect.Ptr, reflect.Struct:
|
|
|
|
ind := reflect.Indirect(val)
|
|
|
|
|
|
|
|
if ind.Kind() == reflect.Struct {
|
|
|
|
typ := ind.Type()
|
2013-08-09 12:14:18 +00:00
|
|
|
name := getFullName(typ)
|
2013-08-08 14:34:18 +00:00
|
|
|
var value interface{}
|
2013-08-09 12:14:18 +00:00
|
|
|
if mmi, ok := modelCache.getByFN(name); ok {
|
2013-08-08 14:34:18 +00:00
|
|
|
if _, vu, exist := d.existPk(mmi, ind); exist {
|
|
|
|
value = vu
|
|
|
|
}
|
|
|
|
}
|
|
|
|
arg = value
|
|
|
|
|
|
|
|
if arg == nil {
|
2013-08-09 12:14:18 +00:00
|
|
|
panic(fmt.Sprintf("`%s` operator need a valid args value, unknown table or value `%s`", operator, name))
|
2013-08-08 14:34:18 +00:00
|
|
|
}
|
2013-08-07 11:11:44 +00:00
|
|
|
} else {
|
2013-08-08 14:34:18 +00:00
|
|
|
arg = ind.Interface()
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
2013-08-08 14:34:18 +00:00
|
|
|
|
|
|
|
params = append(params, arg)
|
|
|
|
|
|
|
|
default:
|
|
|
|
params = append(params, arg)
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
2013-08-08 14:34:18 +00:00
|
|
|
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
2013-08-08 14:34:18 +00:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2013-08-10 16:15:26 +00:00
|
|
|
func (d *dbBase) GenerateOperatorSql(mi *modelInfo, operator string, args []interface{}) (string, []interface{}) {
|
2013-08-08 14:34:18 +00:00
|
|
|
sql := ""
|
|
|
|
params := d.getOperatorParams(operator, args)
|
|
|
|
|
2013-07-30 12:32:38 +00:00
|
|
|
if operator == "in" {
|
|
|
|
marks := make([]string, len(params))
|
|
|
|
for i, _ := range marks {
|
|
|
|
marks[i] = "?"
|
|
|
|
}
|
|
|
|
sql = fmt.Sprintf("IN (%s)", strings.Join(marks, ", "))
|
|
|
|
} else {
|
|
|
|
if len(params) > 1 {
|
|
|
|
panic(fmt.Sprintf("operator `%s` need 1 args not %d", operator, len(params)))
|
|
|
|
}
|
2013-08-10 16:15:26 +00:00
|
|
|
sql = d.ins.OperatorSql(operator)
|
2013-07-30 12:32:38 +00:00
|
|
|
arg := params[0]
|
|
|
|
switch operator {
|
2013-07-31 14:11:22 +00:00
|
|
|
case "exact":
|
|
|
|
if arg == nil {
|
|
|
|
params[0] = "IS NULL"
|
|
|
|
}
|
2013-07-30 12:32:38 +00:00
|
|
|
case "iexact", "contains", "icontains", "startswith", "endswith", "istartswith", "iendswith":
|
|
|
|
param := strings.Replace(ToStr(arg), `%`, `\%`, -1)
|
|
|
|
switch operator {
|
2013-07-31 14:11:22 +00:00
|
|
|
case "iexact":
|
|
|
|
case "contains", "icontains":
|
2013-07-30 12:32:38 +00:00
|
|
|
param = fmt.Sprintf("%%%s%%", param)
|
|
|
|
case "startswith", "istartswith":
|
|
|
|
param = fmt.Sprintf("%s%%", param)
|
|
|
|
case "endswith", "iendswith":
|
|
|
|
param = fmt.Sprintf("%%%s", param)
|
|
|
|
}
|
|
|
|
params[0] = param
|
|
|
|
case "isnull":
|
|
|
|
if b, ok := arg.(bool); ok {
|
|
|
|
if b {
|
|
|
|
sql = "IS NULL"
|
|
|
|
} else {
|
|
|
|
sql = "IS NOT NULL"
|
|
|
|
}
|
|
|
|
params = nil
|
|
|
|
} else {
|
|
|
|
panic(fmt.Sprintf("operator `%s` need a bool value not `%T`", operator, arg))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return sql, params
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *dbBase) setColsValues(mi *modelInfo, ind *reflect.Value, cols []string, values []interface{}) {
|
|
|
|
for i, column := range cols {
|
|
|
|
val := reflect.Indirect(reflect.ValueOf(values[i])).Interface()
|
|
|
|
|
|
|
|
fi := mi.fields.GetByColumn(column)
|
|
|
|
|
|
|
|
field := ind.Field(fi.fieldIndex)
|
|
|
|
|
|
|
|
value, err := d.getValue(fi, val)
|
|
|
|
if err != nil {
|
2013-08-10 16:15:26 +00:00
|
|
|
panic(fmt.Sprintf("Raw value: `%v` %s", val, err.Error()))
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_, err = d.setValue(fi, value, &field)
|
|
|
|
|
|
|
|
if err != nil {
|
2013-08-10 16:15:26 +00:00
|
|
|
panic(fmt.Sprintf("Raw value: `%v` %s", val, err.Error()))
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *dbBase) getValue(fi *fieldInfo, val interface{}) (interface{}, error) {
|
|
|
|
if val == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var value interface{}
|
2013-08-10 16:15:26 +00:00
|
|
|
var tErr error
|
2013-07-30 12:32:38 +00:00
|
|
|
|
|
|
|
var str *StrTo
|
|
|
|
switch v := val.(type) {
|
|
|
|
case []byte:
|
|
|
|
s := StrTo(string(v))
|
|
|
|
str = &s
|
|
|
|
case string:
|
|
|
|
s := StrTo(v)
|
|
|
|
str = &s
|
|
|
|
}
|
|
|
|
|
|
|
|
fieldType := fi.fieldType
|
|
|
|
|
|
|
|
setValue:
|
|
|
|
switch {
|
|
|
|
case fieldType == TypeBooleanField:
|
|
|
|
if str == nil {
|
|
|
|
switch v := val.(type) {
|
|
|
|
case int64:
|
|
|
|
b := v == 1
|
|
|
|
value = b
|
|
|
|
default:
|
|
|
|
s := StrTo(ToStr(v))
|
|
|
|
str = &s
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if str != nil {
|
|
|
|
b, err := str.Bool()
|
|
|
|
if err != nil {
|
2013-08-10 16:15:26 +00:00
|
|
|
tErr = err
|
|
|
|
goto end
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
|
|
|
value = b
|
|
|
|
}
|
|
|
|
case fieldType == TypeCharField || fieldType == TypeTextField:
|
|
|
|
if str == nil {
|
2013-08-08 14:15:27 +00:00
|
|
|
value = ToStr(val)
|
|
|
|
} else {
|
|
|
|
value = str.String()
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
|
|
|
case fieldType == TypeDateField || fieldType == TypeDateTimeField:
|
|
|
|
if str == nil {
|
|
|
|
switch v := val.(type) {
|
|
|
|
case time.Time:
|
|
|
|
value = v
|
|
|
|
default:
|
|
|
|
s := StrTo(ToStr(v))
|
|
|
|
str = &s
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if str != nil {
|
2013-08-10 16:15:26 +00:00
|
|
|
s := str.String()
|
|
|
|
var format string
|
2013-07-30 12:32:38 +00:00
|
|
|
if fi.fieldType == TypeDateField {
|
|
|
|
format = format_Date
|
2013-08-10 16:15:26 +00:00
|
|
|
if len(s) > 10 {
|
|
|
|
s = s[:10]
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
format = format_DateTime
|
|
|
|
if len(s) > 19 {
|
|
|
|
s = s[:19]
|
|
|
|
}
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
|
|
|
t, err := timeParse(s, format)
|
|
|
|
if err != nil && s != "0000-00-00" && s != "0000-00-00 00:00:00" {
|
2013-08-10 16:15:26 +00:00
|
|
|
tErr = err
|
|
|
|
goto end
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
|
|
|
value = t
|
|
|
|
}
|
|
|
|
case fieldType&IsIntegerField > 0:
|
|
|
|
if str == nil {
|
|
|
|
s := StrTo(ToStr(val))
|
|
|
|
str = &s
|
|
|
|
}
|
|
|
|
if str != nil {
|
|
|
|
var err error
|
|
|
|
switch fieldType {
|
|
|
|
case TypeSmallIntegerField:
|
|
|
|
_, err = str.Int16()
|
|
|
|
case TypeIntegerField:
|
|
|
|
_, err = str.Int32()
|
|
|
|
case TypeBigIntegerField:
|
|
|
|
_, err = str.Int64()
|
|
|
|
case TypePositiveSmallIntegerField:
|
|
|
|
_, err = str.Uint16()
|
|
|
|
case TypePositiveIntegerField:
|
|
|
|
_, err = str.Uint32()
|
|
|
|
case TypePositiveBigIntegerField:
|
|
|
|
_, err = str.Uint64()
|
|
|
|
}
|
|
|
|
if err != nil {
|
2013-08-10 16:15:26 +00:00
|
|
|
tErr = err
|
|
|
|
goto end
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
|
|
|
if fieldType&IsPostiveIntegerField > 0 {
|
|
|
|
v, _ := str.Uint64()
|
|
|
|
value = v
|
|
|
|
} else {
|
|
|
|
v, _ := str.Int64()
|
|
|
|
value = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case fieldType == TypeFloatField || fieldType == TypeDecimalField:
|
|
|
|
if str == nil {
|
|
|
|
switch v := val.(type) {
|
|
|
|
case float64:
|
|
|
|
value = v
|
|
|
|
default:
|
|
|
|
s := StrTo(ToStr(v))
|
|
|
|
str = &s
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if str != nil {
|
|
|
|
v, err := str.Float64()
|
|
|
|
if err != nil {
|
2013-08-10 16:15:26 +00:00
|
|
|
tErr = err
|
|
|
|
goto end
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
|
|
|
value = v
|
|
|
|
}
|
|
|
|
case fieldType&IsRelField > 0:
|
2013-08-10 16:15:26 +00:00
|
|
|
fi = fi.relModelInfo.fields.pk
|
|
|
|
fieldType = fi.fieldType
|
2013-07-30 12:32:38 +00:00
|
|
|
goto setValue
|
|
|
|
}
|
|
|
|
|
2013-08-10 16:15:26 +00:00
|
|
|
end:
|
|
|
|
if tErr != nil {
|
|
|
|
err := fmt.Errorf("convert to `%s` failed, field: %s err: %s", fi.addrValue.Type(), fi.fullName, tErr)
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2013-07-30 12:32:38 +00:00
|
|
|
return value, nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *dbBase) setValue(fi *fieldInfo, value interface{}, field *reflect.Value) (interface{}, error) {
|
|
|
|
|
|
|
|
fieldType := fi.fieldType
|
|
|
|
isNative := fi.isFielder == false
|
|
|
|
|
|
|
|
setValue:
|
|
|
|
switch {
|
|
|
|
case fieldType == TypeBooleanField:
|
|
|
|
if isNative {
|
2013-07-31 14:11:22 +00:00
|
|
|
if value == nil {
|
|
|
|
value = false
|
|
|
|
}
|
2013-07-30 12:32:38 +00:00
|
|
|
field.SetBool(value.(bool))
|
|
|
|
}
|
|
|
|
case fieldType == TypeCharField || fieldType == TypeTextField:
|
|
|
|
if isNative {
|
2013-07-31 14:11:22 +00:00
|
|
|
if value == nil {
|
|
|
|
value = ""
|
|
|
|
}
|
2013-07-30 12:32:38 +00:00
|
|
|
field.SetString(value.(string))
|
|
|
|
}
|
|
|
|
case fieldType == TypeDateField || fieldType == TypeDateTimeField:
|
|
|
|
if isNative {
|
2013-07-31 14:11:22 +00:00
|
|
|
if value == nil {
|
|
|
|
value = time.Time{}
|
|
|
|
}
|
2013-07-30 12:32:38 +00:00
|
|
|
field.Set(reflect.ValueOf(value))
|
|
|
|
}
|
|
|
|
case fieldType&IsIntegerField > 0:
|
|
|
|
if fieldType&IsPostiveIntegerField > 0 {
|
|
|
|
if isNative {
|
2013-07-31 14:11:22 +00:00
|
|
|
if value == nil {
|
|
|
|
value = uint64(0)
|
|
|
|
}
|
2013-07-30 12:32:38 +00:00
|
|
|
field.SetUint(value.(uint64))
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if isNative {
|
2013-07-31 14:11:22 +00:00
|
|
|
if value == nil {
|
|
|
|
value = int64(0)
|
|
|
|
}
|
2013-07-30 12:32:38 +00:00
|
|
|
field.SetInt(value.(int64))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case fieldType == TypeFloatField || fieldType == TypeDecimalField:
|
|
|
|
if isNative {
|
2013-07-31 14:11:22 +00:00
|
|
|
if value == nil {
|
|
|
|
value = float64(0)
|
|
|
|
}
|
2013-07-30 12:32:38 +00:00
|
|
|
field.SetFloat(value.(float64))
|
|
|
|
}
|
|
|
|
case fieldType&IsRelField > 0:
|
2013-07-31 14:11:22 +00:00
|
|
|
if value != nil {
|
2013-08-07 11:11:44 +00:00
|
|
|
fieldType = fi.relModelInfo.fields.pk.fieldType
|
2013-07-31 14:11:22 +00:00
|
|
|
mf := reflect.New(fi.relModelInfo.addrField.Elem().Type())
|
|
|
|
field.Set(mf)
|
2013-08-07 11:11:44 +00:00
|
|
|
f := mf.Elem().Field(fi.relModelInfo.fields.pk.fieldIndex)
|
2013-07-31 14:11:22 +00:00
|
|
|
field = &f
|
|
|
|
goto setValue
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if isNative == false {
|
|
|
|
fd := field.Addr().Interface().(Fielder)
|
|
|
|
err := fd.SetRaw(value)
|
|
|
|
if err != nil {
|
2013-08-10 16:15:26 +00:00
|
|
|
err = fmt.Errorf("converted value `%v` set to Fielder `%s` failed, err: %s", value, fi.fullName, err)
|
2013-07-30 12:32:38 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return value, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, exprs []string, container interface{}) (int64, error) {
|
|
|
|
|
|
|
|
var (
|
|
|
|
maps []Params
|
|
|
|
lists []ParamsList
|
|
|
|
list ParamsList
|
|
|
|
)
|
|
|
|
|
|
|
|
typ := 0
|
|
|
|
switch container.(type) {
|
|
|
|
case *[]Params:
|
|
|
|
typ = 1
|
|
|
|
case *[]ParamsList:
|
|
|
|
typ = 2
|
|
|
|
case *ParamsList:
|
|
|
|
typ = 3
|
|
|
|
default:
|
|
|
|
panic(fmt.Sprintf("unsupport read values type `%T`", container))
|
|
|
|
}
|
|
|
|
|
|
|
|
tables := newDbTables(mi, d.ins)
|
|
|
|
|
|
|
|
var (
|
|
|
|
cols []string
|
|
|
|
infos []*fieldInfo
|
|
|
|
)
|
|
|
|
|
|
|
|
hasExprs := len(exprs) > 0
|
|
|
|
|
2013-08-10 16:15:26 +00:00
|
|
|
Q := d.ins.TableQuote()
|
|
|
|
|
2013-07-30 12:32:38 +00:00
|
|
|
if hasExprs {
|
|
|
|
cols = make([]string, 0, len(exprs))
|
|
|
|
infos = make([]*fieldInfo, 0, len(exprs))
|
|
|
|
for _, ex := range exprs {
|
2013-08-01 04:09:17 +00:00
|
|
|
index, col, name, fi, suc := tables.parseExprs(mi, strings.Split(ex, ExprSep))
|
2013-07-30 12:32:38 +00:00
|
|
|
if suc == false {
|
|
|
|
panic(fmt.Errorf("unknown field/column name `%s`", ex))
|
|
|
|
}
|
2013-08-10 16:15:26 +00:00
|
|
|
cols = append(cols, fmt.Sprintf("%s.%s%s%s %s%s%s", index, Q, col, Q, Q, name, Q))
|
2013-07-30 12:32:38 +00:00
|
|
|
infos = append(infos, fi)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cols = make([]string, 0, len(mi.fields.dbcols))
|
|
|
|
infos = make([]*fieldInfo, 0, len(exprs))
|
|
|
|
for _, fi := range mi.fields.fieldsDB {
|
2013-08-10 16:15:26 +00:00
|
|
|
cols = append(cols, fmt.Sprintf("T0.%s%s%s %s%s%s", Q, fi.column, Q, Q, fi.name, Q))
|
2013-07-30 12:32:38 +00:00
|
|
|
infos = append(infos, fi)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
where, args := tables.getCondSql(cond, false)
|
|
|
|
orderBy := tables.getOrderSql(qs.orders)
|
2013-08-10 16:15:26 +00:00
|
|
|
limit := tables.getLimitSql(mi, qs.offset, qs.limit)
|
2013-07-30 12:32:38 +00:00
|
|
|
join := tables.getJoinSql()
|
|
|
|
|
|
|
|
sels := strings.Join(cols, ", ")
|
|
|
|
|
2013-08-10 16:15:26 +00:00
|
|
|
query := fmt.Sprintf("SELECT %s FROM %s%s%s T0 %s%s%s%s", sels, Q, mi.table, Q, join, where, orderBy, limit)
|
2013-07-30 12:32:38 +00:00
|
|
|
|
|
|
|
var rs *sql.Rows
|
|
|
|
if r, err := q.Query(query, args...); err != nil {
|
|
|
|
return 0, err
|
|
|
|
} else {
|
|
|
|
rs = r
|
|
|
|
}
|
|
|
|
|
|
|
|
refs := make([]interface{}, len(cols))
|
|
|
|
for i, _ := range refs {
|
2013-07-31 14:11:22 +00:00
|
|
|
var ref interface{}
|
2013-07-30 12:32:38 +00:00
|
|
|
refs[i] = &ref
|
|
|
|
}
|
|
|
|
|
2013-08-01 04:09:17 +00:00
|
|
|
var (
|
|
|
|
cnt int64
|
|
|
|
columns []string
|
|
|
|
)
|
2013-07-30 12:32:38 +00:00
|
|
|
for rs.Next() {
|
2013-08-01 04:09:17 +00:00
|
|
|
if cnt == 0 {
|
|
|
|
if cols, err := rs.Columns(); err != nil {
|
|
|
|
return 0, err
|
|
|
|
} else {
|
|
|
|
columns = cols
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-30 12:32:38 +00:00
|
|
|
if err := rs.Scan(refs...); err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
switch typ {
|
|
|
|
case 1:
|
|
|
|
params := make(Params, len(cols))
|
|
|
|
for i, ref := range refs {
|
|
|
|
fi := infos[i]
|
|
|
|
|
|
|
|
val := reflect.Indirect(reflect.ValueOf(ref)).Interface()
|
|
|
|
|
|
|
|
value, err := d.getValue(fi, val)
|
|
|
|
if err != nil {
|
|
|
|
panic(fmt.Sprintf("db value convert failed `%v` %s", val, err.Error()))
|
|
|
|
}
|
|
|
|
|
2013-08-01 04:09:17 +00:00
|
|
|
params[columns[i]] = value
|
2013-07-30 12:32:38 +00:00
|
|
|
}
|
|
|
|
maps = append(maps, params)
|
|
|
|
case 2:
|
|
|
|
params := make(ParamsList, 0, len(cols))
|
|
|
|
for i, ref := range refs {
|
|
|
|
fi := infos[i]
|
|
|
|
|
|
|
|
val := reflect.Indirect(reflect.ValueOf(ref)).Interface()
|
|
|
|
|
|
|
|
value, err := d.getValue(fi, val)
|
|
|
|
if err != nil {
|
|
|
|
panic(fmt.Sprintf("db value convert failed `%v` %s", val, err.Error()))
|
|
|
|
}
|
|
|
|
|
|
|
|
params = append(params, value)
|
|
|
|
}
|
|
|
|
lists = append(lists, params)
|
|
|
|
case 3:
|
|
|
|
for i, ref := range refs {
|
|
|
|
fi := infos[i]
|
|
|
|
|
|
|
|
val := reflect.Indirect(reflect.ValueOf(ref)).Interface()
|
|
|
|
|
|
|
|
value, err := d.getValue(fi, val)
|
|
|
|
if err != nil {
|
|
|
|
panic(fmt.Sprintf("db value convert failed `%v` %s", val, err.Error()))
|
|
|
|
}
|
|
|
|
|
|
|
|
list = append(list, value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cnt++
|
|
|
|
}
|
|
|
|
|
|
|
|
switch v := container.(type) {
|
|
|
|
case *[]Params:
|
|
|
|
*v = maps
|
|
|
|
case *[]ParamsList:
|
|
|
|
*v = lists
|
|
|
|
case *ParamsList:
|
|
|
|
*v = list
|
|
|
|
}
|
|
|
|
|
|
|
|
return cnt, nil
|
|
|
|
}
|
2013-08-10 16:15:26 +00:00
|
|
|
|
|
|
|
func (d *dbBase) SupportUpdateJoin() bool {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *dbBase) MaxLimit() uint64 {
|
|
|
|
return 18446744073709551615
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *dbBase) TableQuote() string {
|
|
|
|
return "`"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *dbBase) ReplaceMarks(query *string) {
|
|
|
|
// default use `?` as mark, do nothing
|
|
|
|
}
|