From 5ba53e56c9718d2b6f44f11d6bb9cccc082d9751 Mon Sep 17 00:00:00 2001 From: John Date: Thu, 26 Nov 2020 22:11:58 +0800 Subject: [PATCH] improve join feature for sub-query for gdb.Model --- database/gdb/gdb_model_join.go | 91 ++++++++++------------------------ 1 file changed, 27 insertions(+), 64 deletions(-) diff --git a/database/gdb/gdb_model_join.go b/database/gdb/gdb_model_join.go index 8deab49d1..a519b3a4b 100644 --- a/database/gdb/gdb_model_join.go +++ b/database/gdb/gdb_model_join.go @@ -13,7 +13,7 @@ import ( // isSubQuery checks and returns whether given string a sub-query sql string. func isSubQuery(s string) bool { - s = gstr.TrimLeft(s) + s = gstr.TrimLeft(s, "()") if p := gstr.Pos(s, " "); p != -1 { if gstr.Equal(s[:p], "select") { return true @@ -27,35 +27,9 @@ func isSubQuery(s string) bool { // and also with its alias name, like: // Table("user").LeftJoin("user_detail", "user_detail.uid=user.uid") // Table("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid") +// Table("user", "u").LeftJoin("SELECT xxx FROM xxx AS a", "a.uid=u.uid") func (m *Model) LeftJoin(table ...string) *Model { - var ( - model = m.getModel() - joinStr = "" - ) - if len(table) > 0 { - if isSubQuery(table[0]) { - joinStr = "(" + table[0] + ")" - } else { - joinStr = m.db.QuotePrefixTableName(table[0]) - } - } - if len(table) > 2 { - model.tables += fmt.Sprintf( - " LEFT JOIN %s AS %s ON (%s)", - joinStr, m.db.QuoteWord(table[1]), table[2], - ) - } else if len(table) == 2 { - model.tables += fmt.Sprintf( - " LEFT JOIN %s ON (%s)", - joinStr, table[1], - ) - } else if len(table) == 1 { - model.tables += fmt.Sprintf( - " LEFT JOIN %s", - joinStr, - ) - } - return model + return m.doJoin("LEFT", table...) } // RightJoin does "RIGHT JOIN ... ON ..." statement on the model. @@ -63,35 +37,9 @@ func (m *Model) LeftJoin(table ...string) *Model { // and also with its alias name, like: // Table("user").RightJoin("user_detail", "user_detail.uid=user.uid") // Table("user", "u").RightJoin("user_detail", "ud", "ud.uid=u.uid") +// Table("user", "u").RightJoin("SELECT xxx FROM xxx AS a", "a.uid=u.uid") func (m *Model) RightJoin(table ...string) *Model { - var ( - model = m.getModel() - joinStr = "" - ) - if len(table) > 0 { - if isSubQuery(table[0]) { - joinStr = "(" + table[0] + ")" - } else { - joinStr = m.db.QuotePrefixTableName(table[0]) - } - } - if len(table) > 2 { - model.tables += fmt.Sprintf( - " RIGHT JOIN %s AS %s ON (%s)", - joinStr, m.db.QuoteWord(table[1]), table[2], - ) - } else if len(table) == 2 { - model.tables += fmt.Sprintf( - " RIGHT JOIN %s ON (%s)", - joinStr, table[1], - ) - } else if len(table) == 1 { - model.tables += fmt.Sprintf( - " RIGHT JOIN %s", - joinStr, - ) - } - return model + return m.doJoin("RIGHT", table...) } // InnerJoin does "INNER JOIN ... ON ..." statement on the model. @@ -99,32 +47,47 @@ func (m *Model) RightJoin(table ...string) *Model { // and also with its alias name, like: // Table("user").InnerJoin("user_detail", "user_detail.uid=user.uid") // Table("user", "u").InnerJoin("user_detail", "ud", "ud.uid=u.uid") +// Table("user", "u").InnerJoin("SELECT xxx FROM xxx AS a", "a.uid=u.uid") func (m *Model) InnerJoin(table ...string) *Model { + return m.doJoin("INNER", table...) +} + +// doJoin does "LEFT/RIGHT/INNER JOIN ... ON ..." statement on the model. +// The parameter can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").InnerJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").InnerJoin("user_detail", "ud", "ud.uid=u.uid") +// Table("user", "u").InnerJoin("SELECT xxx FROM xxx AS a", "a.uid=u.uid") +// Related issues: +// https://github.com/gogf/gf/issues/1024 +func (m *Model) doJoin(operator string, table ...string) *Model { var ( model = m.getModel() joinStr = "" ) if len(table) > 0 { if isSubQuery(table[0]) { - joinStr = "(" + table[0] + ")" + joinStr = gstr.Trim(table[0]) + if joinStr[0] != '(' { + joinStr = "(" + joinStr + ")" + } } else { joinStr = m.db.QuotePrefixTableName(table[0]) } } if len(table) > 2 { model.tables += fmt.Sprintf( - " INNER JOIN %s AS %s ON (%s)", - joinStr, m.db.QuoteWord(table[1]), table[2], + " %s JOIN %s AS %s ON (%s)", + operator, joinStr, m.db.QuoteWord(table[1]), table[2], ) } else if len(table) == 2 { model.tables += fmt.Sprintf( - " INNER JOIN %s ON (%s)", - joinStr, table[1], + " %s JOIN %s ON (%s)", + operator, joinStr, table[1], ) } else if len(table) == 1 { model.tables += fmt.Sprintf( - " INNER JOIN %s", - joinStr, + " %s JOIN %s", operator, joinStr, ) } return model