builder.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  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. package builder
  5. import (
  6. sql2 "database/sql"
  7. "fmt"
  8. )
  9. type optype byte
  10. const (
  11. condType optype = iota // only conditions
  12. selectType // select
  13. insertType // insert
  14. updateType // update
  15. deleteType // delete
  16. unionType // union
  17. )
  18. const (
  19. POSTGRES = "postgres"
  20. SQLITE = "sqlite3"
  21. MYSQL = "mysql"
  22. MSSQL = "mssql"
  23. ORACLE = "oracle"
  24. )
  25. type join struct {
  26. joinType string
  27. joinTable string
  28. joinCond Cond
  29. }
  30. type union struct {
  31. unionType string
  32. builder *Builder
  33. }
  34. type limit struct {
  35. limitN int
  36. offset int
  37. }
  38. // Builder describes a SQL statement
  39. type Builder struct {
  40. optype
  41. dialect string
  42. isNested bool
  43. tableName string
  44. subQuery *Builder
  45. cond Cond
  46. selects []string
  47. joins []join
  48. unions []union
  49. limitation *limit
  50. inserts Eq
  51. updates []Eq
  52. orderBy string
  53. groupBy string
  54. having string
  55. }
  56. // Dialect sets the db dialect of Builder.
  57. func Dialect(dialect string) *Builder {
  58. builder := &Builder{cond: NewCond(), dialect: dialect}
  59. return builder
  60. }
  61. // MySQL is shortcut of Dialect(MySQL)
  62. func MySQL() *Builder {
  63. return Dialect(MYSQL)
  64. }
  65. // MsSQL is shortcut of Dialect(MsSQL)
  66. func MsSQL() *Builder {
  67. return Dialect(MSSQL)
  68. }
  69. // Oracle is shortcut of Dialect(Oracle)
  70. func Oracle() *Builder {
  71. return Dialect(ORACLE)
  72. }
  73. // Postgres is shortcut of Dialect(Postgres)
  74. func Postgres() *Builder {
  75. return Dialect(POSTGRES)
  76. }
  77. // SQLite is shortcut of Dialect(SQLITE)
  78. func SQLite() *Builder {
  79. return Dialect(SQLITE)
  80. }
  81. // Where sets where SQL
  82. func (b *Builder) Where(cond Cond) *Builder {
  83. if b.cond.IsValid() {
  84. b.cond = b.cond.And(cond)
  85. } else {
  86. b.cond = cond
  87. }
  88. return b
  89. }
  90. // From sets from subject(can be a table name in string or a builder pointer) and its alias
  91. func (b *Builder) From(subject interface{}, alias ...string) *Builder {
  92. switch subject.(type) {
  93. case *Builder:
  94. b.subQuery = subject.(*Builder)
  95. if len(alias) > 0 {
  96. b.tableName = alias[0]
  97. } else {
  98. b.isNested = true
  99. }
  100. case string:
  101. b.tableName = subject.(string)
  102. if len(alias) > 0 {
  103. b.tableName = b.tableName + " " + alias[0]
  104. }
  105. }
  106. return b
  107. }
  108. // TableName returns the table name
  109. func (b *Builder) TableName() string {
  110. return b.tableName
  111. }
  112. // Into sets insert table name
  113. func (b *Builder) Into(tableName string) *Builder {
  114. b.tableName = tableName
  115. return b
  116. }
  117. // Join sets join table and conditions
  118. func (b *Builder) Join(joinType, joinTable string, joinCond interface{}) *Builder {
  119. switch joinCond.(type) {
  120. case Cond:
  121. b.joins = append(b.joins, join{joinType, joinTable, joinCond.(Cond)})
  122. case string:
  123. b.joins = append(b.joins, join{joinType, joinTable, Expr(joinCond.(string))})
  124. }
  125. return b
  126. }
  127. // Union sets union conditions
  128. func (b *Builder) Union(unionTp string, unionCond *Builder) *Builder {
  129. var builder *Builder
  130. if b.optype != unionType {
  131. builder = &Builder{cond: NewCond()}
  132. builder.optype = unionType
  133. builder.dialect = b.dialect
  134. builder.selects = b.selects
  135. currentUnions := b.unions
  136. // erase sub unions (actually append to new Builder.unions)
  137. b.unions = nil
  138. for e := range currentUnions {
  139. currentUnions[e].builder.dialect = b.dialect
  140. }
  141. builder.unions = append(append(builder.unions, union{"", b}), currentUnions...)
  142. } else {
  143. builder = b
  144. }
  145. if unionCond != nil {
  146. if unionCond.dialect == "" && builder.dialect != "" {
  147. unionCond.dialect = builder.dialect
  148. }
  149. builder.unions = append(builder.unions, union{unionTp, unionCond})
  150. }
  151. return builder
  152. }
  153. // Limit sets limitN condition
  154. func (b *Builder) Limit(limitN int, offset ...int) *Builder {
  155. b.limitation = &limit{limitN: limitN}
  156. if len(offset) > 0 {
  157. b.limitation.offset = offset[0]
  158. }
  159. return b
  160. }
  161. // InnerJoin sets inner join
  162. func (b *Builder) InnerJoin(joinTable string, joinCond interface{}) *Builder {
  163. return b.Join("INNER", joinTable, joinCond)
  164. }
  165. // LeftJoin sets left join SQL
  166. func (b *Builder) LeftJoin(joinTable string, joinCond interface{}) *Builder {
  167. return b.Join("LEFT", joinTable, joinCond)
  168. }
  169. // RightJoin sets right join SQL
  170. func (b *Builder) RightJoin(joinTable string, joinCond interface{}) *Builder {
  171. return b.Join("RIGHT", joinTable, joinCond)
  172. }
  173. // CrossJoin sets cross join SQL
  174. func (b *Builder) CrossJoin(joinTable string, joinCond interface{}) *Builder {
  175. return b.Join("CROSS", joinTable, joinCond)
  176. }
  177. // FullJoin sets full join SQL
  178. func (b *Builder) FullJoin(joinTable string, joinCond interface{}) *Builder {
  179. return b.Join("FULL", joinTable, joinCond)
  180. }
  181. // Select sets select SQL
  182. func (b *Builder) Select(cols ...string) *Builder {
  183. b.selects = cols
  184. b.optype = selectType
  185. return b
  186. }
  187. // And sets AND condition
  188. func (b *Builder) And(cond Cond) *Builder {
  189. b.cond = And(b.cond, cond)
  190. return b
  191. }
  192. // Or sets OR condition
  193. func (b *Builder) Or(cond Cond) *Builder {
  194. b.cond = Or(b.cond, cond)
  195. return b
  196. }
  197. // Insert sets insert SQL
  198. func (b *Builder) Insert(eq Eq) *Builder {
  199. b.inserts = eq
  200. b.optype = insertType
  201. return b
  202. }
  203. // Update sets update SQL
  204. func (b *Builder) Update(updates ...Eq) *Builder {
  205. b.updates = make([]Eq, 0, len(updates))
  206. for _, update := range updates {
  207. if update.IsValid() {
  208. b.updates = append(b.updates, update)
  209. }
  210. }
  211. b.optype = updateType
  212. return b
  213. }
  214. // Delete sets delete SQL
  215. func (b *Builder) Delete(conds ...Cond) *Builder {
  216. b.cond = b.cond.And(conds...)
  217. b.optype = deleteType
  218. return b
  219. }
  220. // WriteTo implements Writer interface
  221. func (b *Builder) WriteTo(w Writer) error {
  222. switch b.optype {
  223. /*case condType:
  224. return b.cond.WriteTo(w)*/
  225. case selectType:
  226. return b.selectWriteTo(w)
  227. case insertType:
  228. return b.insertWriteTo(w)
  229. case updateType:
  230. return b.updateWriteTo(w)
  231. case deleteType:
  232. return b.deleteWriteTo(w)
  233. case unionType:
  234. return b.unionWriteTo(w)
  235. }
  236. return ErrNotSupportType
  237. }
  238. // ToSQL convert a builder to SQL and args
  239. func (b *Builder) ToSQL() (string, []interface{}, error) {
  240. w := NewWriter()
  241. if err := b.WriteTo(w); err != nil {
  242. return "", nil, err
  243. }
  244. // in case of sql.NamedArg in args
  245. for e := range w.args {
  246. if namedArg, ok := w.args[e].(sql2.NamedArg); ok {
  247. w.args[e] = namedArg.Value
  248. }
  249. }
  250. var sql = w.writer.String()
  251. var err error
  252. switch b.dialect {
  253. case ORACLE, MSSQL:
  254. // This is for compatibility with different sql drivers
  255. for e := range w.args {
  256. w.args[e] = sql2.Named(fmt.Sprintf("p%d", e+1), w.args[e])
  257. }
  258. var prefix string
  259. if b.dialect == ORACLE {
  260. prefix = ":p"
  261. } else {
  262. prefix = "@p"
  263. }
  264. if sql, err = ConvertPlaceholder(sql, prefix); err != nil {
  265. return "", nil, err
  266. }
  267. case POSTGRES:
  268. if sql, err = ConvertPlaceholder(sql, "$"); err != nil {
  269. return "", nil, err
  270. }
  271. }
  272. return sql, w.args, nil
  273. }
  274. // ToBoundSQL
  275. func (b *Builder) ToBoundSQL() (string, error) {
  276. w := NewWriter()
  277. if err := b.WriteTo(w); err != nil {
  278. return "", err
  279. }
  280. return ConvertToBoundSQL(w.writer.String(), w.args)
  281. }