http urls monitor.

template.go 7.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. package sqlbuilder
  2. import (
  3. "database/sql/driver"
  4. "fmt"
  5. "strings"
  6. "upper.io/db.v3"
  7. "upper.io/db.v3/internal/sqladapter/exql"
  8. )
  9. type templateWithUtils struct {
  10. *exql.Template
  11. }
  12. func newTemplateWithUtils(template *exql.Template) *templateWithUtils {
  13. return &templateWithUtils{template}
  14. }
  15. func (tu *templateWithUtils) PlaceholderValue(in interface{}) (exql.Fragment, []interface{}) {
  16. switch t := in.(type) {
  17. case db.RawValue:
  18. return exql.RawValue(t.String()), t.Arguments()
  19. case db.Function:
  20. fnName := t.Name()
  21. fnArgs := []interface{}{}
  22. args, _ := toInterfaceArguments(t.Arguments())
  23. fragments := []string{}
  24. for i := range args {
  25. frag, args := tu.PlaceholderValue(args[i])
  26. fragment, err := frag.Compile(tu.Template)
  27. if err == nil {
  28. fragments = append(fragments, fragment)
  29. fnArgs = append(fnArgs, args...)
  30. }
  31. }
  32. return exql.RawValue(fnName + `(` + strings.Join(fragments, `, `) + `)`), fnArgs
  33. default:
  34. // Value must be escaped.
  35. return sqlPlaceholder, []interface{}{in}
  36. }
  37. }
  38. // toWhereWithArguments converts the given parameters into a exql.Where
  39. // value.
  40. func (tu *templateWithUtils) toWhereWithArguments(term interface{}) (where exql.Where, args []interface{}) {
  41. args = []interface{}{}
  42. switch t := term.(type) {
  43. case []interface{}:
  44. if len(t) > 0 {
  45. if s, ok := t[0].(string); ok {
  46. if strings.ContainsAny(s, "?") || len(t) == 1 {
  47. s, args = Preprocess(s, t[1:])
  48. where.Conditions = []exql.Fragment{exql.RawValue(s)}
  49. } else {
  50. var val interface{}
  51. key := s
  52. if len(t) > 2 {
  53. val = t[1:]
  54. } else {
  55. val = t[1]
  56. }
  57. cv, v := tu.toColumnValues(db.NewConstraint(key, val))
  58. args = append(args, v...)
  59. for i := range cv.ColumnValues {
  60. where.Conditions = append(where.Conditions, cv.ColumnValues[i])
  61. }
  62. }
  63. return
  64. }
  65. }
  66. for i := range t {
  67. w, v := tu.toWhereWithArguments(t[i])
  68. if len(w.Conditions) == 0 {
  69. continue
  70. }
  71. args = append(args, v...)
  72. where.Conditions = append(where.Conditions, w.Conditions...)
  73. }
  74. return
  75. case db.RawValue:
  76. r, v := Preprocess(t.Raw(), t.Arguments())
  77. where.Conditions = []exql.Fragment{exql.RawValue(r)}
  78. args = append(args, v...)
  79. return
  80. case db.Constraints:
  81. for _, c := range t.Constraints() {
  82. w, v := tu.toWhereWithArguments(c)
  83. if len(w.Conditions) == 0 {
  84. continue
  85. }
  86. args = append(args, v...)
  87. where.Conditions = append(where.Conditions, w.Conditions...)
  88. }
  89. return
  90. case db.Compound:
  91. var cond exql.Where
  92. for _, c := range t.Sentences() {
  93. w, v := tu.toWhereWithArguments(c)
  94. if len(w.Conditions) == 0 {
  95. continue
  96. }
  97. args = append(args, v...)
  98. cond.Conditions = append(cond.Conditions, w.Conditions...)
  99. }
  100. if len(cond.Conditions) > 0 {
  101. var frag exql.Fragment
  102. switch t.Operator() {
  103. case db.OperatorNone, db.OperatorAnd:
  104. q := exql.And(cond)
  105. frag = &q
  106. case db.OperatorOr:
  107. q := exql.Or(cond)
  108. frag = &q
  109. default:
  110. panic(fmt.Sprintf("Unknown type %T", t))
  111. }
  112. where.Conditions = append(where.Conditions, frag)
  113. }
  114. return
  115. case db.Constraint:
  116. cv, v := tu.toColumnValues(t)
  117. args = append(args, v...)
  118. where.Conditions = append(where.Conditions, cv.ColumnValues...)
  119. return where, args
  120. }
  121. panic(fmt.Sprintf("Unknown condition type %T", term))
  122. }
  123. func (tu *templateWithUtils) comparisonOperatorMapper(t db.ComparisonOperator) string {
  124. if t == db.ComparisonOperatorNone {
  125. return ""
  126. }
  127. if tu.ComparisonOperator != nil {
  128. if op, ok := tu.ComparisonOperator[t]; ok {
  129. return op
  130. }
  131. }
  132. if op, ok := comparisonOperators[t]; ok {
  133. return op
  134. }
  135. panic(fmt.Sprintf("unsupported comparison operator %v", t))
  136. }
  137. func (tu *templateWithUtils) toColumnValues(term interface{}) (cv exql.ColumnValues, args []interface{}) {
  138. args = []interface{}{}
  139. switch t := term.(type) {
  140. case db.Constraint:
  141. columnValue := exql.ColumnValue{}
  142. // Getting column and operator.
  143. if column, ok := t.Key().(string); ok {
  144. chunks := strings.SplitN(strings.TrimSpace(column), " ", 2)
  145. columnValue.Column = exql.ColumnWithName(chunks[0])
  146. if len(chunks) > 1 {
  147. columnValue.Operator = chunks[1]
  148. }
  149. } else {
  150. if rawValue, ok := t.Key().(db.RawValue); ok {
  151. columnValue.Column = exql.RawValue(rawValue.Raw())
  152. args = append(args, rawValue.Arguments()...)
  153. } else {
  154. columnValue.Column = exql.RawValue(fmt.Sprintf("%v", t.Key()))
  155. }
  156. }
  157. switch value := t.Value().(type) {
  158. case db.Function:
  159. fnName, fnArgs := value.Name(), value.Arguments()
  160. if len(fnArgs) == 0 {
  161. // A function with no arguments.
  162. fnName = fnName + "()"
  163. } else {
  164. // A function with one or more arguments.
  165. fnName = fnName + "(?" + strings.Repeat("?, ", len(fnArgs)-1) + ")"
  166. }
  167. fnName, fnArgs = Preprocess(fnName, fnArgs)
  168. columnValue.Value = exql.RawValue(fnName)
  169. args = append(args, fnArgs...)
  170. case db.RawValue:
  171. q, a := Preprocess(value.Raw(), value.Arguments())
  172. columnValue.Value = exql.RawValue(q)
  173. args = append(args, a...)
  174. case driver.Valuer:
  175. columnValue.Value = exql.RawValue("?")
  176. args = append(args, value)
  177. case db.Comparison:
  178. wrapper := &operatorWrapper{
  179. tu: tu,
  180. cv: &columnValue,
  181. op: value,
  182. }
  183. q, a := wrapper.preprocess()
  184. q, a = Preprocess(q, a)
  185. columnValue = exql.ColumnValue{
  186. Column: exql.RawValue(q),
  187. }
  188. if a != nil {
  189. args = append(args, a...)
  190. }
  191. cv.ColumnValues = append(cv.ColumnValues, &columnValue)
  192. return cv, args
  193. default:
  194. wrapper := &operatorWrapper{
  195. tu: tu,
  196. cv: &columnValue,
  197. v: value,
  198. }
  199. q, a := wrapper.preprocess()
  200. q, a = Preprocess(q, a)
  201. columnValue = exql.ColumnValue{
  202. Column: exql.RawValue(q),
  203. }
  204. if a != nil {
  205. args = append(args, a...)
  206. }
  207. cv.ColumnValues = append(cv.ColumnValues, &columnValue)
  208. return cv, args
  209. }
  210. if columnValue.Operator == "" {
  211. columnValue.Operator = tu.comparisonOperatorMapper(db.ComparisonOperatorEqual)
  212. }
  213. cv.ColumnValues = append(cv.ColumnValues, &columnValue)
  214. return cv, args
  215. case db.RawValue:
  216. columnValue := exql.ColumnValue{}
  217. p, q := Preprocess(t.Raw(), t.Arguments())
  218. columnValue.Column = exql.RawValue(p)
  219. cv.ColumnValues = append(cv.ColumnValues, &columnValue)
  220. args = append(args, q...)
  221. return cv, args
  222. case db.Constraints:
  223. for _, constraint := range t.Constraints() {
  224. p, q := tu.toColumnValues(constraint)
  225. cv.ColumnValues = append(cv.ColumnValues, p.ColumnValues...)
  226. args = append(args, q...)
  227. }
  228. return cv, args
  229. }
  230. panic(fmt.Sprintf("Unknown term type %T.", term))
  231. }
  232. func (tu *templateWithUtils) setColumnValues(term interface{}) (cv exql.ColumnValues, args []interface{}) {
  233. args = []interface{}{}
  234. switch t := term.(type) {
  235. case []interface{}:
  236. l := len(t)
  237. for i := 0; i < l; i++ {
  238. column, isString := t[i].(string)
  239. if !isString {
  240. p, q := tu.setColumnValues(t[i])
  241. cv.ColumnValues = append(cv.ColumnValues, p.ColumnValues...)
  242. args = append(args, q...)
  243. continue
  244. }
  245. if !strings.ContainsAny(column, tu.AssignmentOperator) {
  246. column = column + " " + tu.AssignmentOperator + " ?"
  247. }
  248. chunks := strings.SplitN(column, tu.AssignmentOperator, 2)
  249. column = chunks[0]
  250. format := strings.TrimSpace(chunks[1])
  251. columnValue := exql.ColumnValue{
  252. Column: exql.ColumnWithName(column),
  253. Operator: tu.AssignmentOperator,
  254. Value: exql.RawValue(format),
  255. }
  256. ps := strings.Count(format, "?")
  257. if i+ps < l {
  258. for j := 0; j < ps; j++ {
  259. args = append(args, t[i+j+1])
  260. }
  261. i = i + ps
  262. } else {
  263. panic(fmt.Sprintf("Format string %q has more placeholders than given arguments.", format))
  264. }
  265. cv.ColumnValues = append(cv.ColumnValues, &columnValue)
  266. }
  267. return cv, args
  268. case db.RawValue:
  269. columnValue := exql.ColumnValue{}
  270. p, q := Preprocess(t.Raw(), t.Arguments())
  271. columnValue.Column = exql.RawValue(p)
  272. cv.ColumnValues = append(cv.ColumnValues, &columnValue)
  273. args = append(args, q...)
  274. return cv, args
  275. }
  276. panic(fmt.Sprintf("Unknown term type %T.", term))
  277. }