123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- package sqlbuilder
- import (
- "bytes"
- "fmt"
- "strconv"
- "strings"
- )
- type JoinOption string
- const (
- LeftJoin JoinOption = "LEFT"
- LeftOuterJoin JoinOption = "LEFT OUTER"
- RightJoin JoinOption = "RIGHT"
- RightOuterJoin JoinOption = "RIGHT OUTER"
- FullJoin JoinOption = "FULL"
- FullOuterJoin JoinOption = "FULL OUTER"
- )
- func NewSelectBuilder() *SelectBuilder {
- return DefaultFlavor.NewSelectBuilder()
- }
- func newSelectBuilder() *SelectBuilder {
- args := &Args{}
- return &SelectBuilder{
- Cond: Cond{
- Args: args,
- },
- limit: -1,
- offset: -1,
- args: args,
- }
- }
- type SelectBuilder struct {
- Cond
- distinct bool
- tables []string
- selectCols []string
- joinOptions []JoinOption
- joinTables []string
- joinExprs [][]string
- whereExprs []string
- havingExprs []string
- groupByCols []string
- orderByCols []string
- order string
- limit int
- offset int
- args *Args
- }
- func (sb *SelectBuilder) Distinct() *SelectBuilder {
- sb.distinct = true
- return sb
- }
- func (sb *SelectBuilder) Select(col ...string) *SelectBuilder {
- sb.selectCols = col
- return sb
- }
- func (sb *SelectBuilder) From(table ...string) *SelectBuilder {
- sb.tables = table
- return sb
- }
- func (sb *SelectBuilder) Join(table string, onExpr ...string) *SelectBuilder {
- return sb.JoinWithOption("", table, onExpr...)
- }
- func (sb *SelectBuilder) JoinWithOption(option JoinOption, table string, onExpr ...string) *SelectBuilder {
- sb.joinOptions = append(sb.joinOptions, option)
- sb.joinTables = append(sb.joinTables, table)
- sb.joinExprs = append(sb.joinExprs, onExpr)
- return sb
- }
- func (sb *SelectBuilder) Where(andExpr ...string) *SelectBuilder {
- sb.whereExprs = append(sb.whereExprs, andExpr...)
- return sb
- }
- func (sb *SelectBuilder) Having(andExpr ...string) *SelectBuilder {
- sb.havingExprs = append(sb.havingExprs, andExpr...)
- return sb
- }
- func (sb *SelectBuilder) GroupBy(col ...string) *SelectBuilder {
- sb.groupByCols = col
- return sb
- }
- func (sb *SelectBuilder) OrderBy(col ...string) *SelectBuilder {
- sb.orderByCols = col
- return sb
- }
- func (sb *SelectBuilder) Asc() *SelectBuilder {
- sb.order = "ASC"
- return sb
- }
- func (sb *SelectBuilder) Desc() *SelectBuilder {
- sb.order = "DESC"
- return sb
- }
- func (sb *SelectBuilder) Limit(limit int) *SelectBuilder {
- sb.limit = limit
- return sb
- }
- func (sb *SelectBuilder) Offset(offset int) *SelectBuilder {
- sb.offset = offset
- return sb
- }
- func (sb *SelectBuilder) As(name, alias string) string {
- return fmt.Sprintf("%s AS %s", name, alias)
- }
- func (sb *SelectBuilder) BuilderAs(builder Builder, alias string) string {
- return fmt.Sprintf("(%s) AS %s", sb.Var(builder), alias)
- }
- func (sb *SelectBuilder) String() string {
- s, _ := sb.Build()
- return s
- }
- func (sb *SelectBuilder) Build() (sql string, args []interface{}) {
- return sb.BuildWithFlavor(sb.args.Flavor)
- }
- func (sb *SelectBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{}) (sql string, args []interface{}) {
- buf := &bytes.Buffer{}
- buf.WriteString("SELECT ")
- if sb.distinct {
- buf.WriteString("DISTINCT ")
- }
- buf.WriteString(strings.Join(sb.selectCols, ", "))
- buf.WriteString(" FROM ")
- buf.WriteString(strings.Join(sb.tables, ", "))
- for i := range sb.joinTables {
- if option := sb.joinOptions[i]; option != "" {
- buf.WriteRune(' ')
- buf.WriteString(string(option))
- }
- buf.WriteString(" JOIN ")
- buf.WriteString(sb.joinTables[i])
- if exprs := sb.joinExprs[i]; len(exprs) > 0 {
- buf.WriteString(" ON ")
- buf.WriteString(strings.Join(sb.joinExprs[i], " AND "))
- }
- }
- if len(sb.whereExprs) > 0 {
- buf.WriteString(" WHERE ")
- buf.WriteString(strings.Join(sb.whereExprs, " AND "))
- }
- if len(sb.groupByCols) > 0 {
- buf.WriteString(" GROUP BY ")
- buf.WriteString(strings.Join(sb.groupByCols, ", "))
- if len(sb.havingExprs) > 0 {
- buf.WriteString(" HAVING ")
- buf.WriteString(strings.Join(sb.havingExprs, " AND "))
- }
- }
- if len(sb.orderByCols) > 0 {
- buf.WriteString(" ORDER BY ")
- buf.WriteString(strings.Join(sb.orderByCols, ", "))
- if sb.order != "" {
- buf.WriteRune(' ')
- buf.WriteString(sb.order)
- }
- }
- if sb.limit >= 0 {
- buf.WriteString(" LIMIT ")
- buf.WriteString(strconv.Itoa(sb.limit))
- }
- if MySQL == flavor && sb.limit >= 0 || PostgreSQL == flavor {
- if sb.offset >= 0 {
- buf.WriteString(" OFFSET ")
- buf.WriteString(strconv.Itoa(sb.offset))
- }
- }
- return sb.Args.CompileWithFlavor(buf.String(), flavor, initialArg...)
- }
- func (sb *SelectBuilder) SetFlavor(flavor Flavor) (old Flavor) {
- old = sb.args.Flavor
- sb.args.Flavor = flavor
- return
- }
|