1
0
mirror of https://github.com/astaxie/beego.git synced 2024-11-22 20:00:54 +00:00

Merge pull request #3378 from nukc/develop

orm: support filter raw sql
This commit is contained in:
astaxie 2018-11-08 23:28:30 +08:00 committed by GitHub
commit 6b5a70d246
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 49 additions and 1 deletions

View File

@ -372,7 +372,13 @@ func (t *dbTables) getCondSQL(cond *Condition, sub bool, tz *time.Location) (whe
operator = "exact" operator = "exact"
} }
operSQL, args := t.base.GenerateOperatorSQL(mi, fi, operator, p.args, tz) var operSQL string
var args []interface{}
if p.isRaw {
operSQL = p.sql
} else {
operSQL, args = t.base.GenerateOperatorSQL(mi, fi, operator, p.args, tz)
}
leftCol := fmt.Sprintf("%s.%s%s%s", index, Q, fi.column, Q) leftCol := fmt.Sprintf("%s.%s%s%s", index, Q, fi.column, Q)
t.base.GenerateOperatorLeftCol(fi, operator, &leftCol) t.base.GenerateOperatorLeftCol(fi, operator, &leftCol)

View File

@ -31,6 +31,8 @@ type condValue struct {
isOr bool isOr bool
isNot bool isNot bool
isCond bool isCond bool
isRaw bool
sql string
} }
// Condition struct. // Condition struct.
@ -45,6 +47,15 @@ func NewCondition() *Condition {
return c return c
} }
// Raw add raw sql to condition
func (c Condition) Raw(expr string, sql string) *Condition {
if len(sql) == 0 {
panic(fmt.Errorf("<Condition.Raw> sql cannot empty"))
}
c.params = append(c.params, condValue{exprs: strings.Split(expr, ExprSep), sql: sql, isRaw: true})
return &c
}
// And add expression to condition // And add expression to condition
func (c Condition) And(expr string, args ...interface{}) *Condition { func (c Condition) And(expr string, args ...interface{}) *Condition {
if expr == "" || len(args) == 0 { if expr == "" || len(args) == 0 {

View File

@ -79,6 +79,15 @@ func (o querySet) Filter(expr string, args ...interface{}) QuerySeter {
return &o return &o
} }
// add raw sql to querySeter.
func (o querySet) FilterRaw(expr string, sql string) QuerySeter {
if o.cond == nil {
o.cond = NewCondition()
}
o.cond = o.cond.Raw(expr, sql)
return &o
}
// add NOT condition to querySeter. // add NOT condition to querySeter.
func (o querySet) Exclude(expr string, args ...interface{}) QuerySeter { func (o querySet) Exclude(expr string, args ...interface{}) QuerySeter {
if o.cond == nil { if o.cond == nil {

View File

@ -899,6 +899,18 @@ func TestOperators(t *testing.T) {
num, err = qs.Filter("id__between", []int{2, 3}).Count() num, err = qs.Filter("id__between", []int{2, 3}).Count()
throwFail(t, err) throwFail(t, err)
throwFail(t, AssertIs(num, 2)) throwFail(t, AssertIs(num, 2))
num, err = qs.FilterRaw("user_name", "= 'slene'").Count()
throwFail(t, err)
throwFail(t, AssertIs(num, 1))
num, err = qs.FilterRaw("status", "IN (1, 2)").Count()
throwFail(t, err)
throwFail(t, AssertIs(num, 2))
num, err = qs.FilterRaw("profile_id", "IN (SELECT id FROM user_profile WHERE age=30)").Count()
throwFail(t, err)
throwFail(t, AssertIs(num, 1))
} }
func TestSetCond(t *testing.T) { func TestSetCond(t *testing.T) {
@ -924,6 +936,11 @@ func TestSetCond(t *testing.T) {
num, err = qs.SetCond(cond4).Count() num, err = qs.SetCond(cond4).Count()
throwFail(t, err) throwFail(t, err)
throwFail(t, AssertIs(num, 3)) throwFail(t, AssertIs(num, 3))
cond5 := cond.Raw("user_name", "= 'slene'").OrNotCond(cond.And("user_name", "slene"))
num, err = qs.SetCond(cond5).Count()
throwFail(t, err)
throwFail(t, AssertIs(num, 3))
} }
func TestLimit(t *testing.T) { func TestLimit(t *testing.T) {

View File

@ -147,6 +147,11 @@ type QuerySeter interface {
// // time compare // // time compare
// qs.Filter("created", time.Now()) // qs.Filter("created", time.Now())
Filter(string, ...interface{}) QuerySeter Filter(string, ...interface{}) QuerySeter
// add raw sql to querySeter.
// for example:
// qs.FilterRaw("user_id IN (SELECT id FROM profile WHERE age>=18)")
// //sql-> WHERE user_id IN (SELECT id FROM profile WHERE age>=18)
FilterRaw(string, string) QuerySeter
// add NOT condition to querySeter. // add NOT condition to querySeter.
// have the same usage as Filter // have the same usage as Filter
Exclude(string, ...interface{}) QuerySeter Exclude(string, ...interface{}) QuerySeter