1// Copyright 2016 The Xorm Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package builder 6 7import ( 8 "fmt" 9) 10 11// Select creates a select Builder 12func Select(cols ...string) *Builder { 13 builder := &Builder{cond: NewCond()} 14 return builder.Select(cols...) 15} 16 17func (b *Builder) selectWriteTo(w Writer) error { 18 if len(b.from) <= 0 && !b.isNested { 19 return ErrNoTableName 20 } 21 22 // perform limit before writing to writer when b.dialect between ORACLE and MSSQL 23 // this avoid a duplicate writing problem in simple limit query 24 if b.limitation != nil && (b.dialect == ORACLE || b.dialect == MSSQL) { 25 return b.limitWriteTo(w) 26 } 27 28 if _, err := fmt.Fprint(w, "SELECT "); err != nil { 29 return err 30 } 31 if len(b.selects) > 0 { 32 for i, s := range b.selects { 33 if _, err := fmt.Fprint(w, s); err != nil { 34 return err 35 } 36 if i != len(b.selects)-1 { 37 if _, err := fmt.Fprint(w, ","); err != nil { 38 return err 39 } 40 } 41 } 42 } else { 43 if _, err := fmt.Fprint(w, "*"); err != nil { 44 return err 45 } 46 } 47 48 if b.subQuery == nil { 49 if _, err := fmt.Fprint(w, " FROM ", b.from); err != nil { 50 return err 51 } 52 } else { 53 if b.cond.IsValid() && len(b.from) <= 0 { 54 return ErrUnnamedDerivedTable 55 } 56 if b.subQuery.dialect != "" && b.dialect != b.subQuery.dialect { 57 return ErrInconsistentDialect 58 } 59 60 // dialect of sub-query will inherit from the main one (if not set up) 61 if b.dialect != "" && b.subQuery.dialect == "" { 62 b.subQuery.dialect = b.dialect 63 } 64 65 switch b.subQuery.optype { 66 case selectType, setOpType: 67 fmt.Fprint(w, " FROM (") 68 if err := b.subQuery.WriteTo(w); err != nil { 69 return err 70 } 71 72 if len(b.from) == 0 { 73 fmt.Fprintf(w, ")") 74 } else { 75 fmt.Fprintf(w, ") %v", b.from) 76 } 77 default: 78 return ErrUnexpectedSubQuery 79 } 80 } 81 82 for _, v := range b.joins { 83 b, ok := v.joinTable.(*Builder) 84 if ok { 85 if _, err := fmt.Fprintf(w, " %s JOIN (", v.joinType); err != nil { 86 return err 87 } 88 if err := b.WriteTo(w); err != nil { 89 return err 90 } 91 if _, err := fmt.Fprintf(w, ") ON "); err != nil { 92 return err 93 } 94 } else { 95 if _, err := fmt.Fprintf(w, " %s JOIN %s ON ", v.joinType, v.joinTable); err != nil { 96 return err 97 } 98 } 99 100 if err := v.joinCond.WriteTo(w); err != nil { 101 return err 102 } 103 } 104 105 if b.cond.IsValid() { 106 if _, err := fmt.Fprint(w, " WHERE "); err != nil { 107 return err 108 } 109 110 if err := b.cond.WriteTo(w); err != nil { 111 return err 112 } 113 } 114 115 if len(b.groupBy) > 0 { 116 if _, err := fmt.Fprint(w, " GROUP BY ", b.groupBy); err != nil { 117 return err 118 } 119 } 120 121 if len(b.having) > 0 { 122 if _, err := fmt.Fprint(w, " HAVING ", b.having); err != nil { 123 return err 124 } 125 } 126 127 if len(b.orderBy) > 0 { 128 if _, err := fmt.Fprint(w, " ORDER BY ", b.orderBy); err != nil { 129 return err 130 } 131 } 132 133 if b.limitation != nil { 134 if err := b.limitWriteTo(w); err != nil { 135 return err 136 } 137 } 138 139 return nil 140} 141 142// OrderBy orderBy SQL 143func (b *Builder) OrderBy(orderBy string) *Builder { 144 b.orderBy = orderBy 145 return b 146} 147 148// GroupBy groupby SQL 149func (b *Builder) GroupBy(groupby string) *Builder { 150 b.groupBy = groupby 151 return b 152} 153 154// Having having SQL 155func (b *Builder) Having(having string) *Builder { 156 b.having = having 157 return b 158} 159