You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

175 lines
3.5 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. package vql
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "strings"
  6. "sync"
  7. )
  8. type VirtualQlConvert func(val map[string]interface{}) (string, error)
  9. func NoParameConvertFunc(vTable string, convertSql string) *VirtualTable {
  10. return &VirtualTable{
  11. MappingTableName: vTable,
  12. SqlConvert: func(val map[string]interface{}) (string, error) {
  13. return convertSql, nil
  14. },
  15. }
  16. }
  17. type VirtualTable struct {
  18. MappingTableName string //example: user(db:db1,id:1)
  19. ArgNames []string //example: [db,id]
  20. SqlConvert VirtualQlConvert
  21. }
  22. func parseTableName(tableNameExpression string) (tableName string, args map[string]string, err error) {
  23. args = make(map[string]string)
  24. source := []rune(tableNameExpression)
  25. flag := "table"
  26. argStr := ""
  27. for i := range source {
  28. switch flag {
  29. case "table":
  30. if source[i] == '(' {
  31. flag = "arg"
  32. continue
  33. }
  34. tableName += string(source[i])
  35. case "arg":
  36. if source[i] == ')' {
  37. flag = "end"
  38. continue
  39. }
  40. argStr += string(source[i])
  41. case "end":
  42. break
  43. }
  44. }
  45. argsArr := []string{}
  46. if argStr != "" {
  47. argsArr = strings.Split(strings.TrimSpace(argStr), ",")
  48. }
  49. for i := range argsArr {
  50. arg := strings.Split(argsArr[i], ":")
  51. if len(arg) != 2 {
  52. err = fmt.Errorf("table name expression error")
  53. return
  54. }
  55. args[arg[0]] = arg[1]
  56. }
  57. return
  58. }
  59. var DefaultVirtualQL = &VirtualQL{}
  60. type VirtualQL struct {
  61. tables map[string]VirtualTable
  62. locker sync.RWMutex
  63. }
  64. func (vql *VirtualQL) getTable(tableName string) (vt VirtualTable, args map[string]string, err error) {
  65. vql.locker.RLock()
  66. defer vql.locker.RUnlock()
  67. tableName, args, err = parseTableName(tableName)
  68. vqlTable := vql.tables[tableName]
  69. return vqlTable, args, err
  70. }
  71. func (vql *VirtualQL) Register(v *VirtualTable) {
  72. if vql.tables == nil {
  73. vql.tables = make(map[string]VirtualTable)
  74. }
  75. vql.locker.Lock()
  76. defer vql.locker.Unlock()
  77. vql.tables[v.MappingTableName] = *v
  78. }
  79. func (vql *VirtualQL) Compile(sql string, param map[string]interface{}) (*Query, error) {
  80. query, err := Analyze(sql)
  81. if err != nil {
  82. return nil, err
  83. }
  84. err = vql.convert(query, param)
  85. if err != nil {
  86. return nil, err
  87. }
  88. return query, nil
  89. }
  90. func (vql *VirtualQL) convert(query *Query, val map[string]interface{}) error {
  91. if query.From.Table == "" && query.From.SubQuery == nil {
  92. return fmt.Errorf("from table is empty")
  93. }
  94. if query.From.Table != "" {
  95. vtable, args, err := vql.getTable(query.From.Table)
  96. if err != nil {
  97. return err
  98. }
  99. if vtable.SqlConvert == nil {
  100. return fmt.Errorf("table %s is not register", query.From.Table)
  101. }
  102. if val == nil {
  103. val = make(map[string]interface{})
  104. }
  105. for k := range vtable.ArgNames {
  106. if args[vtable.ArgNames[k]] != "" {
  107. val[vtable.ArgNames[k]] = args[vtable.ArgNames[k]]
  108. }
  109. }
  110. convertSql, err := vtable.SqlConvert(val)
  111. if err != nil {
  112. return err
  113. }
  114. if convertSql == "" {
  115. return fmt.Errorf("table %s is not register!", query.From.Table)
  116. }
  117. newAs := query.From.As
  118. if newAs == "" {
  119. newAs = query.From.Table
  120. }
  121. query.From = From{
  122. raw: convertSql,
  123. As: newAs,
  124. }
  125. } else {
  126. err := vql.convert(query.From.SubQuery, val)
  127. if err != nil {
  128. return err
  129. }
  130. }
  131. for i := range query.Join {
  132. err := vql.convert(query.Join[i].Query, val)
  133. if err != nil {
  134. return err
  135. }
  136. }
  137. return nil
  138. }
  139. func jsonEncode(val interface{}) string {
  140. raw, _ := json.Marshal(val)
  141. return string(raw)
  142. }
  143. func Analyze(sql string) (*Query, error) {
  144. q := Query{}
  145. err := q.FromSql(sql)
  146. return &q, err
  147. }
  148. // func (vql *VirtualQL) CompileWithApijson(sql apijson.QueryNode, param map[string]interface{}) (*Query, error) {
  149. // }