github.com/gogf/gf@v1.16.9/database/gdb/gdb_model_join.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/gogf/gf.
     6  
     7  package gdb
     8  
     9  import (
    10  	"fmt"
    11  
    12  	"github.com/gogf/gf/text/gstr"
    13  )
    14  
    15  // isSubQuery checks and returns whether given string a sub-query sql string.
    16  func isSubQuery(s string) bool {
    17  	s = gstr.TrimLeft(s, "()")
    18  	if p := gstr.Pos(s, " "); p != -1 {
    19  		if gstr.Equal(s[:p], "select") {
    20  			return true
    21  		}
    22  	}
    23  	return false
    24  }
    25  
    26  // LeftJoin does "LEFT JOIN ... ON ..." statement on the model.
    27  // The parameter `table` can be joined table and its joined condition,
    28  // and also with its alias name, like:
    29  // Table("user").LeftJoin("user_detail", "user_detail.uid=user.uid")
    30  // Table("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid")
    31  // Table("user", "u").LeftJoin("SELECT xxx FROM xxx AS a", "a.uid=u.uid")
    32  func (m *Model) LeftJoin(table ...string) *Model {
    33  	return m.doJoin("LEFT", table...)
    34  }
    35  
    36  // RightJoin does "RIGHT JOIN ... ON ..." statement on the model.
    37  // The parameter `table` can be joined table and its joined condition,
    38  // and also with its alias name, like:
    39  // Table("user").RightJoin("user_detail", "user_detail.uid=user.uid")
    40  // Table("user", "u").RightJoin("user_detail", "ud", "ud.uid=u.uid")
    41  // Table("user", "u").RightJoin("SELECT xxx FROM xxx AS a", "a.uid=u.uid")
    42  func (m *Model) RightJoin(table ...string) *Model {
    43  	return m.doJoin("RIGHT", table...)
    44  }
    45  
    46  // InnerJoin does "INNER JOIN ... ON ..." statement on the model.
    47  // The parameter `table` can be joined table and its joined condition,
    48  // and also with its alias name, like:
    49  // Table("user").InnerJoin("user_detail", "user_detail.uid=user.uid")
    50  // Table("user", "u").InnerJoin("user_detail", "ud", "ud.uid=u.uid")
    51  // Table("user", "u").InnerJoin("SELECT xxx FROM xxx AS a", "a.uid=u.uid")
    52  func (m *Model) InnerJoin(table ...string) *Model {
    53  	return m.doJoin("INNER", table...)
    54  }
    55  
    56  // doJoin does "LEFT/RIGHT/INNER JOIN ... ON ..." statement on the model.
    57  // The parameter `table` can be joined table and its joined condition,
    58  // and also with its alias name, like:
    59  //     Model("user").InnerJoin("user_detail", "user_detail.uid=user.uid")
    60  //     Model("user", "u").InnerJoin("user_detail", "ud", "ud.uid=u.uid")
    61  //     Model("user", "u").InnerJoin("SELECT xxx FROM xxx AS a", "a.uid=u.uid")
    62  // Related issues:
    63  // https://github.com/gogf/gf/issues/1024
    64  func (m *Model) doJoin(operator string, table ...string) *Model {
    65  	var (
    66  		model   = m.getModel()
    67  		joinStr = ""
    68  	)
    69  	if len(table) > 0 {
    70  		if isSubQuery(table[0]) {
    71  			joinStr = gstr.Trim(table[0])
    72  			if joinStr[0] != '(' {
    73  				joinStr = "(" + joinStr + ")"
    74  			}
    75  		} else {
    76  			joinStr = m.db.GetCore().QuotePrefixTableName(table[0])
    77  		}
    78  	}
    79  	if len(table) > 2 {
    80  		model.tables += fmt.Sprintf(
    81  			" %s JOIN %s AS %s ON (%s)",
    82  			operator, joinStr, m.db.GetCore().QuoteWord(table[1]), table[2],
    83  		)
    84  	} else if len(table) == 2 {
    85  		model.tables += fmt.Sprintf(
    86  			" %s JOIN %s ON (%s)",
    87  			operator, joinStr, table[1],
    88  		)
    89  	} else if len(table) == 1 {
    90  		model.tables += fmt.Sprintf(
    91  			" %s JOIN %s", operator, joinStr,
    92  		)
    93  	}
    94  	return model
    95  }