querydefs.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package sqlchemy
  15. import (
  16. "bytes"
  17. "fmt"
  18. "sort"
  19. )
  20. // IQuery is an interface that reprsents a SQL query, e.g.
  21. // SELECT ... FROM ... WHERE ...
  22. type IQuery interface {
  23. // String returns the queryString
  24. String(fields ...IQueryField) string
  25. // QueryFields returns fields in the select clause
  26. QueryFields() []IQueryField
  27. // Variables returns variables in statement
  28. Variables() []interface{}
  29. // SubQuery convert this SQL to a subquery
  30. SubQuery() *SSubQuery
  31. // Field reference to a field by name
  32. Field(name string) IQueryField
  33. // Database returns the database for this query
  34. database() *SDatabase
  35. }
  36. // IQuerySource is an interface that represents a data source of a SQL query. the source can be a table or a subquery
  37. // e.g. SELECT ... FROM (SELECT * FROM tbl) AS A
  38. type IQuerySource interface {
  39. // Expression string in select ... from (expresson here)
  40. Expression() string
  41. // Alias is the alias in select ... from (express) as alias
  42. Alias() string
  43. // variables in statement
  44. Variables() []interface{}
  45. // Field reference to a field by name, optionally giving an alias name
  46. Field(id string, alias ...string) IQueryField
  47. // Fields return all the fields that this source provides
  48. Fields() []IQueryField
  49. // Database returns the database of this IQuerySource
  50. database() *SDatabase
  51. }
  52. // IQueryField is an interface that represents a select field in a SQL query
  53. type IQueryField interface {
  54. // the string after select
  55. Expression() string
  56. // the name of thie field
  57. Name() string
  58. // the reference string in where clause
  59. Reference() string
  60. // give this field an alias name
  61. Label(label string) IQueryField
  62. // return variables
  63. Variables() []interface{}
  64. // ConvertFromValue returns the SQL representation of a value for this
  65. ConvertFromValue(val interface{}) interface{}
  66. // Database returns the database of this IQuerySource
  67. database() *SDatabase
  68. }
  69. // DoQuery returns a SQuery instance that query specified fields from a query source
  70. func DoQuery(from IQuerySource, f ...IQueryField) *SQuery {
  71. if from.database() == nil {
  72. panic("DoQuery IQuerySource with empty database")
  73. }
  74. // if len(f) == 0 {
  75. // f = from.Fields()
  76. // }
  77. tq := SQuery{fields: f, from: from, db: from.database()}
  78. return &tq
  79. }
  80. func queryString(tq *SQuery, tmpFields ...IQueryField) string {
  81. if len(tq.rawSql) > 0 {
  82. return tq.rawSql
  83. }
  84. qChar := tq.database().backend.QuoteChar()
  85. var buf bytes.Buffer
  86. buf.WriteString("SELECT ")
  87. if tq.distinct {
  88. buf.WriteString("DISTINCT ")
  89. }
  90. fields := tmpFields
  91. if len(fields) == 0 {
  92. if len(tq.fields) > 0 {
  93. fields = append(fields, tq.fields...)
  94. } else {
  95. fields = append(fields, tq.from.Fields()...)
  96. for i := range fields {
  97. tq.from.Field(fields[i].Name())
  98. }
  99. }
  100. }
  101. {
  102. // add reference query fields
  103. queryFields := make(map[string]IQueryField)
  104. for i, f := range fields {
  105. queryFields[f.Name()] = fields[i]
  106. }
  107. refFields := make([]IQueryField, 0)
  108. for _, f := range tq.refFieldMap {
  109. if _, ok := queryFields[f.Name()]; !ok {
  110. queryFields[f.Name()] = f
  111. refFields = append(refFields, f)
  112. }
  113. }
  114. sort.Sort(queryFieldList(refFields))
  115. fields = append(fields, refFields...)
  116. }
  117. groupFields := make(map[string]IQueryField)
  118. if len(tq.groupBy) > 0 {
  119. for i := range tq.groupBy {
  120. f := tq.groupBy[i]
  121. groupFields[f.Name()] = f
  122. }
  123. }
  124. for i := range fields {
  125. if i > 0 {
  126. buf.WriteString(", ")
  127. }
  128. f := fields[i]
  129. if len(tq.groupBy) > 0 {
  130. if gf, ok := groupFields[f.Name()]; ok && f.Reference() == gf.Reference() {
  131. // in group by, normal
  132. buf.WriteString(f.Expression())
  133. } else {
  134. // not in group by, check if the field is a group aggregate function
  135. if gf, ok := f.(IFunctionQueryField); ok && gf.IsAggregate() {
  136. // is a aggregate function field
  137. buf.WriteString(f.Expression())
  138. } else {
  139. f = MAX(f.Name(), f)
  140. buf.WriteString(f.Expression())
  141. }
  142. }
  143. } else {
  144. // normal
  145. buf.WriteString(f.Expression())
  146. }
  147. if f.Name() != "" {
  148. buf.WriteString(fmt.Sprintf(" AS %s%s%s", qChar, f.Name(), qChar))
  149. }
  150. }
  151. buf.WriteString(" FROM ")
  152. buf.WriteString(fmt.Sprintf("%s AS %s%s%s", tq.from.Expression(), qChar, tq.from.Alias(), qChar))
  153. for _, join := range tq.joins {
  154. buf.WriteByte(' ')
  155. buf.WriteString(string(join.jointype))
  156. buf.WriteByte(' ')
  157. buf.WriteString(fmt.Sprintf("%s AS %s%s%s", join.from.Expression(), qChar, join.from.Alias(), qChar))
  158. whereCls := join.condition.WhereClause()
  159. if len(whereCls) > 0 {
  160. buf.WriteString(" ON ")
  161. buf.WriteString(whereCls)
  162. }
  163. }
  164. if tq.where != nil {
  165. whereCls := tq.where.WhereClause()
  166. if len(whereCls) > 0 {
  167. buf.WriteString(" WHERE ")
  168. buf.WriteString(whereCls)
  169. }
  170. }
  171. if tq.groupBy != nil && len(tq.groupBy) > 0 {
  172. buf.WriteString(" GROUP BY ")
  173. groupByFields := make(map[string]IQueryField)
  174. for i := range tq.groupBy {
  175. f := tq.groupBy[i]
  176. if _, ok := groupByFields[f.Reference()]; ok {
  177. continue
  178. }
  179. if i > 0 {
  180. buf.WriteString(", ")
  181. }
  182. buf.WriteString(f.Reference())
  183. groupByFields[f.Reference()] = f
  184. }
  185. // DAMENG SQL Compatibility, all order by fields should be in group by
  186. for i := range tq.orderBy {
  187. f := tq.orderBy[i]
  188. if _, ok := groupByFields[f.field.Reference()]; ok {
  189. continue
  190. }
  191. if ff, ok := f.field.(IFunctionQueryField); ok && ff.IsAggregate() {
  192. continue
  193. }
  194. buf.WriteString(", ")
  195. buf.WriteString(f.field.Reference())
  196. groupByFields[f.field.Reference()] = f.field
  197. }
  198. }
  199. /*if tq.having != nil {
  200. buf.WriteString(" HAVING ")
  201. buf.WriteString(tq.having.WhereClause())
  202. }*/
  203. if tq.orderBy != nil && len(tq.orderBy) > 0 {
  204. buf.WriteString(" ORDER BY ")
  205. for i := range tq.orderBy {
  206. f := tq.orderBy[i]
  207. if i > 0 {
  208. buf.WriteString(", ")
  209. }
  210. buf.WriteString(fmt.Sprintf("%s %s", f.field.Reference(), f.order))
  211. }
  212. }
  213. if tq.limit > 0 {
  214. buf.WriteString(fmt.Sprintf(" LIMIT %d", tq.limit))
  215. }
  216. if tq.offset > 0 {
  217. buf.WriteString(fmt.Sprintf(" OFFSET %d", tq.offset))
  218. }
  219. return buf.String()
  220. }
  221. func getFieldBackend(fields ...IQueryField) IBackend {
  222. for _, f := range fields {
  223. db := f.database()
  224. if db != nil {
  225. return db.backend
  226. }
  227. }
  228. return defaultBackend
  229. }