query.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. package DB
  2. import (
  3. "git.ycl.pub/yl32940/TsDB2/DB/core"
  4. "git.ycl.pub/yl32940/TsDB2/DB/core/types"
  5. "fmt"
  6. "reflect"
  7. )
  8. // Query 泛型查询构建器
  9. type Query[T any] struct {
  10. table *Table[T]
  11. wheres []whereClause
  12. orders []orderClause
  13. limit int
  14. offset int
  15. }
  16. type whereClause struct {
  17. field string
  18. op string
  19. value interface{}
  20. }
  21. type orderClause struct {
  22. field string
  23. desc bool
  24. }
  25. func (q *Query[T]) addWhere(field, op string, value interface{}) *Query[T] {
  26. q.wheres = append(q.wheres, whereClause{field: field, op: op, value: value})
  27. return q
  28. }
  29. // Where 添加条件
  30. func (q *Query[T]) Where(field string, op string, value interface{}) *Query[T] {
  31. q.wheres = append(q.wheres, whereClause{field: field, op: op, value: value})
  32. return q
  33. }
  34. // OrderBy 排序
  35. func (q *Query[T]) OrderBy(field string, desc ...bool) *Query[T] {
  36. d := false
  37. if len(desc) > 0 && desc[0] {
  38. d = true
  39. }
  40. q.orders = append(q.orders, orderClause{field: field, desc: d})
  41. return q
  42. }
  43. // Limit 限制行数
  44. func (q *Query[T]) Limit(n int) *Query[T] {
  45. q.limit = n
  46. return q
  47. }
  48. // Offset 跳过行数
  49. func (q *Query[T]) Offset(n int) *Query[T] {
  50. q.offset = n
  51. return q
  52. }
  53. // Find 执行查询返回所有结果
  54. //
  55. // 用 ScanWithPKID 而不是 Find: 行号不在字段值里, 但它决定了返回的对象能不能被精确
  56. // 地改 / 删 —— 同一个时间戳下有多行时, 只有行号指得清"返回的是哪一行"。
  57. func (q *Query[T]) Find() ([]*T, error) {
  58. cq := q.buildCoreQuery()
  59. result := make([]*T, 0)
  60. err := cq.ScanWithPKID(func(pkID uint64, row []types.FieldValue) bool {
  61. obj := new(T)
  62. if err := fieldValuesToStruct(row, q.table.model, obj, q.table.coreTable); err != nil {
  63. return true
  64. }
  65. setRowIDOf(obj, pkID)
  66. q.table.bindModel(obj)
  67. result = append(result, obj)
  68. return true
  69. })
  70. if err != nil {
  71. return nil, err
  72. }
  73. return result, nil
  74. }
  75. // First 返回第一条结果
  76. func (q *Query[T]) First() (*T, error) {
  77. q.limit = 1
  78. results, err := q.Find()
  79. if err != nil {
  80. return nil, err
  81. }
  82. if len(results) == 0 {
  83. return nil, fmt.Errorf("tsdb: record not found")
  84. }
  85. return results[0], nil
  86. }
  87. // Count 返回匹配行数
  88. func (q *Query[T]) Count() (int64, error) {
  89. cq := q.buildCoreQuery()
  90. return cq.Count()
  91. }
  92. // Scan 流式遍历
  93. func (q *Query[T]) Scan(callback func(*T) bool) error {
  94. cq := q.buildCoreQuery()
  95. return cq.ScanWithPKID(func(pkID uint64, row []types.FieldValue) bool {
  96. obj := new(T)
  97. if err := fieldValuesToStruct(row, q.table.model, obj, q.table.coreTable); err != nil {
  98. return true
  99. }
  100. setRowIDOf(obj, pkID)
  101. q.table.bindModel(obj)
  102. return callback(obj)
  103. })
  104. }
  105. // buildCoreQuery 构建 core 层的 Query
  106. func (q *Query[T]) buildCoreQuery() *core.Query {
  107. cq := q.table.coreTable.Query()
  108. // 构建 WHERE 条件
  109. if len(q.wheres) > 0 {
  110. cond := q.buildCondition(q.wheres[0])
  111. for i := 1; i < len(q.wheres); i++ {
  112. cond = core.And(cond, q.buildCondition(q.wheres[i]))
  113. }
  114. cq = cq.Where(cond)
  115. }
  116. // ORDER BY
  117. for _, o := range q.orders {
  118. cq = cq.OrderBy(o.field, o.desc)
  119. }
  120. // LIMIT / OFFSET
  121. if q.limit > 0 {
  122. cq = cq.Limit(q.limit)
  123. }
  124. if q.offset > 0 {
  125. cq = cq.Offset(q.offset)
  126. }
  127. return cq
  128. }
  129. // buildCondition 将 whereClause 转换为 core.Condition
  130. func (q *Query[T]) buildCondition(w whereClause) core.Condition {
  131. // ft 只用来把条件值归一化成列期望的 Go 类型 (normalizeCondValue);
  132. // 条件构造函数的第三个参数已废弃 —— 比较一律按列的实际存储类型进行
  133. // (见 core.Table.compareTypeFor), 故统一传 types.FieldType(0)。
  134. ft := q.findFieldType(w.field)
  135. val := normalizeCondValue(w.value, ft)
  136. switch w.op {
  137. case "=", "==", "eq":
  138. return core.Eq(w.field, val, types.FieldType(0))
  139. case "!=", "<>":
  140. return core.Not(core.Eq(w.field, val, types.FieldType(0)))
  141. case ">", "gt":
  142. return core.Gt(w.field, val, types.FieldType(0))
  143. case ">=", "ge", "gte":
  144. return core.Ge(w.field, val, types.FieldType(0))
  145. case "<", "lt":
  146. return core.Lt(w.field, val, types.FieldType(0))
  147. case "<=", "le", "lte":
  148. return core.Le(w.field, val, types.FieldType(0))
  149. case "like":
  150. if s, ok := w.value.(string); ok {
  151. return core.Like(w.field, s)
  152. }
  153. return core.Eq(w.field, val, types.FieldType(0))
  154. case "in", "In", "IN":
  155. // 值须是切片/数组; 每个分量先经 normalizeCondValue 归一成列期望的
  156. // Go 类型再交给 core.In (分量类型不一会按列类型逐个编码比较)。
  157. var vals []interface{}
  158. rv := reflect.ValueOf(w.value)
  159. switch rv.Kind() {
  160. case reflect.Slice, reflect.Array:
  161. vals = make([]interface{}, rv.Len())
  162. for i := 0; i < rv.Len(); i++ {
  163. vals[i] = normalizeCondValue(rv.Index(i).Interface(), ft)
  164. }
  165. default:
  166. // 单值容忍: Where("Age","in",25) ≡ Where("Age","=",25)
  167. return core.Eq(w.field, val, types.FieldType(0))
  168. }
  169. if len(vals) == 0 {
  170. // 空集合恒假: InCondition.Match 对每行返回 false (无索引特化路径,
  171. // 不会被 nil 条件的"跳过过滤"语义坑成查全表)。
  172. return core.In(w.field, nil, types.FieldType(0))
  173. }
  174. return core.In(w.field, vals, types.FieldType(0))
  175. default:
  176. return core.Eq(w.field, val, types.FieldType(0))
  177. }
  178. }
  179. // normalizeCondValue 将条件值转换为 core 期望的类型
  180. func normalizeCondValue(v interface{}, ft types.FieldType) interface{} {
  181. switch ft {
  182. case types.FieldType_Uint64:
  183. return toUint64(v)
  184. case types.FieldType_Uint32:
  185. return toInt32(v)
  186. case types.FieldType_Uint16:
  187. return int16(toUint64(v))
  188. case types.FieldType_Uint8:
  189. return uint8(toUint64(v))
  190. case types.FieldType_Int8:
  191. return toInt8(v)
  192. case types.FieldType_Int16:
  193. return toInt16(v)
  194. case types.FieldType_Int32:
  195. return toInt32(v)
  196. case types.FieldType_Int64:
  197. return toInt64(v)
  198. case types.FieldType_Float64:
  199. // 不能走 toUint64: 那会把条件值的小数先砍掉, 变成在浮点列上按整数匹配
  200. return toFloatVal(v)
  201. // ===== 扩展类型 =====
  202. //
  203. // 全部原样下传, 交给 core 的 types.EncodeValue / DecimalFromValue 解析与校验。
  204. // 尤其是 Decimal / UUID: 条件值常常是字符串 ("1.50" / "550e8400-..."), 一旦落进
  205. // 下面的 default 分支会被当定长串补零成定长字节, 比较和索引键就全错了。
  206. case types.FieldType_Bool,
  207. types.FieldType_Float32,
  208. types.FieldType_Decimal,
  209. types.FieldType_UUID,
  210. types.FieldType_Year,
  211. types.FieldType_Int128,
  212. types.FieldType_Blob:
  213. return v
  214. default:
  215. // 定长字符串类型: 原样下传, 由 core 按【列的实际宽度】编码
  216. // (types.EncodeValue 接受 string, 并顺带成为宽度闸门: 超宽报错而不是截断)。
  217. //
  218. // 不能在这里按 types.GetSize(ft) 自己补零: 那只是类型默认宽度, 对用宽度码声明的
  219. // 列 (maxlen:1000 → 1024 字节档) 会编出 256 字节——与行内字节不同源, 比较与索引键
  220. // 全错。而且这里只有 ft 没有列级参数, 本就拼不出正确的宽度。
  221. return v
  222. }
  223. }
  224. // findFieldType 查找字段的 FieldType
  225. // 优先从 DB schema 查找,回退到 struct model
  226. func (q *Query[T]) findFieldType(name string) types.FieldType {
  227. // 优先从 DB schema 查找
  228. if ft, ok := q.table.coreTable.GetActiveFieldType(name); ok {
  229. return ft
  230. }
  231. // 回退到 struct model
  232. for _, fd := range q.table.model.AllFields {
  233. if fd.ColName == name || fd.Name == name {
  234. return fd.FieldType
  235. }
  236. }
  237. return types.FieldType_Uint64 // 默认
  238. }