functions.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  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. "fmt"
  17. "strings"
  18. )
  19. // IFunctionQueryField is a special type of field that is an aggregate function
  20. type IFunctionQueryField interface {
  21. IQueryField
  22. // is this an aggregate function?
  23. IsAggregate() bool
  24. }
  25. // IFunction is the interface for a SQL embedded function, such as MIN, MAX, NOW, etc.
  26. type IFunction interface {
  27. expression() string
  28. variables() []interface{}
  29. database() *SDatabase
  30. queryFields() []IQueryField
  31. }
  32. // NewFunction creates a field with SQL function
  33. // for example: SUM(count) as total
  34. func NewFunction(ifunc IFunction, name string, isAggre bool) IQueryField {
  35. return &SFunctionFieldBase{
  36. IFunction: ifunc,
  37. alias: name,
  38. aggregate: isAggre,
  39. }
  40. }
  41. // SFunctionFieldBase is a query field that is the result of a SQL embedded function, e.g. COUNT(*) as count
  42. type SFunctionFieldBase struct {
  43. IFunction
  44. alias string
  45. aggregate bool
  46. convertFunc func(interface{}) interface{}
  47. }
  48. func (ff *SFunctionFieldBase) getQuoteChar() string {
  49. qChar := ""
  50. if ff.database() != nil {
  51. qChar = ff.database().backend.QuoteChar()
  52. }
  53. return qChar
  54. }
  55. // Reference implementation of SFunctionFieldBase for IQueryField
  56. func (ff *SFunctionFieldBase) Reference() string {
  57. if len(ff.alias) == 0 {
  58. // log.Warningf("reference a function field without alias! %s", ff.expression())
  59. return ff.expression()
  60. }
  61. qChar := ff.getQuoteChar()
  62. return fmt.Sprintf("%s%s%s", qChar, ff.alias, qChar)
  63. }
  64. // Expression implementation of SFunctionFieldBase for IQueryField
  65. func (ff *SFunctionFieldBase) Expression() string {
  66. return ff.expression()
  67. }
  68. // Name implementation of SFunctionFieldBase for IQueryField
  69. func (ff *SFunctionFieldBase) Name() string {
  70. if len(ff.alias) > 0 {
  71. return ff.alias
  72. }
  73. return ff.expression()
  74. }
  75. // Label implementation of SFunctionFieldBase for IQueryField
  76. func (ff *SFunctionFieldBase) Label(label string) IQueryField {
  77. if len(label) > 0 {
  78. ff.alias = label
  79. }
  80. return ff
  81. }
  82. // Variables implementation of SFunctionFieldBase for IQueryField
  83. func (ff *SFunctionFieldBase) Variables() []interface{} {
  84. return ff.variables()
  85. }
  86. // ConvertFromValue implementation of SFunctionFieldBase for IQueryField
  87. func (ff *SFunctionFieldBase) ConvertFromValue(val interface{}) interface{} {
  88. if ff.convertFunc != nil {
  89. return ff.convertFunc(val)
  90. }
  91. return val
  92. }
  93. func (ff *SFunctionFieldBase) IsAggregate() bool {
  94. return ff.aggregate
  95. }
  96. type sExprFunction struct {
  97. fields []IQueryField
  98. function string
  99. }
  100. func (ff *sExprFunction) expression() string {
  101. fieldRefs := make([]interface{}, 0)
  102. for _, f := range ff.fields {
  103. fieldRefs = append(fieldRefs, f.Expression())
  104. }
  105. return fmt.Sprintf(ff.function, fieldRefs...)
  106. }
  107. func (ff *sExprFunction) variables() []interface{} {
  108. vars := make([]interface{}, 0)
  109. for _, f := range ff.fields {
  110. fromVars := f.Variables()
  111. vars = append(vars, fromVars...)
  112. }
  113. return vars
  114. }
  115. func (ff *sExprFunction) database() *SDatabase {
  116. for i := range ff.fields {
  117. db := ff.fields[i].database()
  118. if db != nil {
  119. return db
  120. }
  121. }
  122. // if ff.function != "COUNT(*)" {
  123. // log.Debugf("no fields function? %s", ff.expression())
  124. // }
  125. return nil
  126. }
  127. func (ff *sExprFunction) queryFields() []IQueryField {
  128. return ff.fields
  129. }
  130. func NewFunctionField(name string, isAggr bool, funcexp string, fields ...IQueryField) IQueryField {
  131. return NewFunctionFieldWithConvert(name, isAggr, funcexp, nil, fields...)
  132. }
  133. // NewFunctionField returns an instance of query field by calling a SQL embedded function
  134. func NewFunctionFieldWithConvert(name string, isAggr bool, funcexp string, convertFunc func(interface{}) interface{}, fields ...IQueryField) IQueryField {
  135. funcBase := &sExprFunction{
  136. fields: fields,
  137. function: funcexp,
  138. }
  139. return &SFunctionFieldBase{
  140. IFunction: funcBase,
  141. alias: name,
  142. aggregate: isAggr,
  143. convertFunc: convertFunc,
  144. }
  145. }
  146. // COUNT represents the SQL function COUNT
  147. func COUNT(name string, field ...IQueryField) IQueryField {
  148. return getFieldBackend(field...).COUNT(name, field...)
  149. }
  150. // MAX represents the SQL function MAX
  151. func MAX(name string, field IQueryField) IQueryField {
  152. return getFieldBackend(field).MAX(name, field)
  153. }
  154. // MIN represents the SQL function MIN
  155. func MIN(name string, field IQueryField) IQueryField {
  156. return getFieldBackend(field).MIN(name, field)
  157. }
  158. // SUM represents the SQL function SUM
  159. func SUM(name string, field IQueryField) IQueryField {
  160. return getFieldBackend(field).SUM(name, field)
  161. }
  162. // AVG represents the SQL function SUM
  163. func AVG(name string, field IQueryField) IQueryField {
  164. return getFieldBackend(field).AVG(name, field)
  165. }
  166. // LOWER represents the SQL function SUM
  167. func LOWER(name string, field IQueryField) IQueryField {
  168. return getFieldBackend(field).LOWER(name, field)
  169. }
  170. // UPPER represents the SQL function SUM
  171. func UPPER(name string, field IQueryField) IQueryField {
  172. return getFieldBackend(field).UPPER(name, field)
  173. }
  174. // DISTINCT represents the SQL function DISTINCT
  175. func DISTINCT(name string, field IQueryField) IQueryField {
  176. return getFieldBackend(field).DISTINCT(name, field)
  177. }
  178. // GROUP_CONCAT represents the SQL function GROUP_CONCAT
  179. func GROUP_CONCAT(name string, field IQueryField) IQueryField {
  180. return GROUP_CONCAT2(name, ",", field)
  181. }
  182. // GROUP_CONCAT2 represents the SQL function GROUP_CONCAT
  183. func GROUP_CONCAT2(name string, sep string, field IQueryField) IQueryField {
  184. // return NewFunctionField(name, "GROUP_CONCAT(%s)", field)
  185. return getFieldBackend(field).GROUP_CONCAT2(name, sep, field)
  186. }
  187. // REPLACE represents the SQL function REPLACE
  188. func REPLACE(name string, field IQueryField, old string, new string) IQueryField {
  189. return getFieldBackend(field).REPLACE(name, field, old, new)
  190. }
  191. // SConstField is a query field of a constant
  192. type SConstField struct {
  193. constVar interface{}
  194. alias string
  195. db *SDatabase
  196. }
  197. // Expression implementation of SConstField for IQueryField
  198. func (s *SConstField) Expression() string {
  199. return s.Reference()
  200. }
  201. // Name implementation of SConstField for IQueryField
  202. func (s *SConstField) Name() string {
  203. return s.alias
  204. }
  205. // Reference implementation of SConstField for IQueryField
  206. func (s *SConstField) Reference() string {
  207. return getQuoteStringValue(s.constVar)
  208. }
  209. // Label implementation of SConstField for IQueryField
  210. func (s *SConstField) Label(label string) IQueryField {
  211. if len(label) > 0 {
  212. s.alias = label
  213. }
  214. return s
  215. }
  216. // ConvertFromValue implementation of SConstField for IQueryField
  217. func (s *SConstField) ConvertFromValue(val interface{}) interface{} {
  218. return val
  219. }
  220. // database implementation of SConstField for IQueryField
  221. func (s *SConstField) database() *SDatabase {
  222. return s.db
  223. }
  224. // Variables implementation of SConstField for IQueryField
  225. func (s *SConstField) Variables() []interface{} {
  226. return nil
  227. }
  228. // IsAggregate implementation of SConstField for IFunctionQueryField
  229. func (s *SConstField) IsAggregate() bool {
  230. return true
  231. }
  232. // NewConstField returns an instance of SConstField
  233. func NewConstField(variable interface{}) *SConstField {
  234. return &SConstField{constVar: variable}
  235. }
  236. // database implementation of SStringField for IQueryField
  237. func (s *SConstField) WithField(f IQueryField) *SConstField {
  238. s.db = f.database()
  239. return s
  240. }
  241. func (q *SQuery) ConstField(variable interface{}) *SConstField {
  242. f := NewConstField(variable)
  243. f.db = q.db
  244. return f
  245. }
  246. // SStringField is a query field of a string constant
  247. type SStringField struct {
  248. strConst string
  249. alias string
  250. db *SDatabase
  251. }
  252. // Expression implementation of SStringField for IQueryField
  253. func (s *SStringField) Expression() string {
  254. return s.Reference()
  255. }
  256. // Name implementation of SStringField for IQueryField
  257. func (s *SStringField) Name() string {
  258. return s.alias
  259. }
  260. // Reference implementation of SStringField for IQueryField
  261. func (s *SStringField) Reference() string {
  262. return getQuoteStringValue(s.strConst)
  263. }
  264. // Label implementation of SStringField for IQueryField
  265. func (s *SStringField) Label(label string) IQueryField {
  266. if len(label) > 0 {
  267. s.alias = label
  268. }
  269. return s
  270. }
  271. // ConvertFromValue implementation of SStringField for IQueryField
  272. func (s *SStringField) ConvertFromValue(val interface{}) interface{} {
  273. return val
  274. }
  275. // database implementation of SStringField for IQueryField
  276. func (s *SStringField) database() *SDatabase {
  277. return s.db
  278. }
  279. // Variables implementation of SStringField for IQueryField
  280. func (s *SStringField) Variables() []interface{} {
  281. return nil
  282. }
  283. // IsAggregate implementation of SStringField for IFunctionQueryField
  284. func (s *SStringField) IsAggregate() bool {
  285. return true
  286. }
  287. // database implementation of SStringField for IQueryField
  288. func (s *SStringField) WithField(f IQueryField) *SStringField {
  289. s.db = f.database()
  290. return s
  291. }
  292. // NewStringField returns an instance of SStringField
  293. func NewStringField(strConst string) *SStringField {
  294. return &SStringField{strConst: strConst}
  295. }
  296. func (q *SQuery) StringField(strConst string) *SStringField {
  297. f := NewStringField(strConst)
  298. f.db = q.db
  299. return f
  300. }
  301. // CONCAT represents a SQL function CONCAT
  302. func CONCAT(name string, fields ...IQueryField) IQueryField {
  303. return getFieldBackend(fields...).CONCAT(name, fields...)
  304. }
  305. // SubStr represents a SQL function SUBSTR
  306. // Deprecated
  307. func SubStr(name string, field IQueryField, pos, length int) IQueryField {
  308. return SUBSTR(name, field, pos, length)
  309. }
  310. // SUBSTR represents a SQL function SUBSTR
  311. func SUBSTR(name string, field IQueryField, pos, length int) IQueryField {
  312. return getFieldBackend(field).SUBSTR(name, field, pos, length)
  313. }
  314. // OR_Val represents a SQL function that does binary | operation on a field
  315. func OR_Val(name string, field IQueryField, v interface{}) IQueryField {
  316. return getFieldBackend(field).OR_Val(name, field, v)
  317. }
  318. // AND_Val represents a SQL function that does binary & operation on a field
  319. func AND_Val(name string, field IQueryField, v interface{}) IQueryField {
  320. return getFieldBackend(field).AND_Val(name, field, v)
  321. }
  322. // INET_ATON represents a SQL function INET_ATON
  323. func INET_ATON(field IQueryField) IQueryField {
  324. return getFieldBackend(field).INET_ATON(field)
  325. }
  326. // INET6_ATON represents a SQL function INET_ATON
  327. func INET6_ATON(field IQueryField) IQueryField {
  328. return getFieldBackend(field).INET6_ATON(field)
  329. }
  330. // TimestampAdd represents a SQL function TimestampAdd
  331. func TimestampAdd(name string, field IQueryField, offsetSeconds int) IQueryField {
  332. return TIMESTAMPADD(name, field, offsetSeconds)
  333. }
  334. // TIMESTAMPADD represents a SQL function TimestampAdd
  335. func TIMESTAMPADD(name string, field IQueryField, offsetSeconds int) IQueryField {
  336. return getFieldBackend(field).TIMESTAMPADD(name, field, offsetSeconds)
  337. }
  338. // DATE_FORMAT represents a SQL function DATE_FORMAT
  339. func DATE_FORMAT(name string, field IQueryField, format string) IQueryField {
  340. return getFieldBackend(field).DATE_FORMAT(name, field, format)
  341. }
  342. // CAST represents a SQL function cast types
  343. func CAST(field IQueryField, typeStr string, fieldname string) IQueryField {
  344. return getFieldBackend(field).CAST(field, typeStr, fieldname)
  345. }
  346. // CASTString represents a SQL function cast any type to String
  347. func CASTString(field IQueryField, fieldname string) IQueryField {
  348. return getFieldBackend(field).CASTString(field, fieldname)
  349. }
  350. // CASTInt represents a SQL function cast any type to Integer
  351. func CASTInt(field IQueryField, fieldname string) IQueryField {
  352. return getFieldBackend(field).CASTInt(field, fieldname)
  353. }
  354. // CASTFloat represents a SQL function cast any type to Float
  355. func CASTFloat(field IQueryField, fieldname string) IQueryField {
  356. return getFieldBackend(field).CASTFloat(field, fieldname)
  357. }
  358. // LENGTH represents a SQL function of LENGTH
  359. func LENGTH(name string, field IQueryField) IQueryField {
  360. return getFieldBackend(field).LENGTH(name, field)
  361. }
  362. func bc(name, op string, fields ...IQueryField) IQueryField {
  363. exps := []string{}
  364. for i := 0; i < len(fields); i++ {
  365. exps = append(exps, "%s")
  366. }
  367. return NewFunctionField(name, false, strings.Join(exps, fmt.Sprintf(" %s ", op)), fields...)
  368. }
  369. func ADD(name string, fields ...IQueryField) IQueryField {
  370. return bc(name, "+", fields...)
  371. }
  372. func SUB(name string, fields ...IQueryField) IQueryField {
  373. return bc(name, "-", fields...)
  374. }
  375. func MUL(name string, fields ...IQueryField) IQueryField {
  376. return bc(name, "*", fields...)
  377. }
  378. func DIV(name string, fields ...IQueryField) IQueryField {
  379. return bc(name, "/", fields...)
  380. }
  381. func DATEDIFF(unit string, field1, field2 IQueryField) IQueryField {
  382. return getFieldBackend(field1).DATEDIFF(unit, field1, field2)
  383. }
  384. func ABS(name string, field IQueryField) IQueryField {
  385. return NewFunctionField(name, false, "ABS(%s)", field)
  386. }