exec.go 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151
  1. package vrtxsql
  2. // 语句执行: AST → 引擎查询体系 (core.Query / Condition / Table)。
  3. // 调用约定: 进入本文件任一函数时 shared.mu 已由调用方持有。
  4. import (
  5. "context"
  6. "database/sql/driver"
  7. "fmt"
  8. "math"
  9. "reflect"
  10. "strconv"
  11. "strings"
  12. "time"
  13. "git.ycl.pub/yl32940/TsDB2/DB/core"
  14. "git.ycl.pub/yl32940/TsDB2/DB/core/page"
  15. "git.ycl.pub/yl32940/TsDB2/DB/core/types"
  16. )
  17. // execStatement 执行非查询语句 (INSERT/UPDATE/DELETE/DDL)。
  18. func execStatement(db *core.DB, st *statement, args []driver.NamedValue) (driver.Result, error) {
  19. switch st.kind {
  20. case kInsert:
  21. return execInsert(db, st.ins, args)
  22. case kUpdate:
  23. return execUpdate(db, st.upd, args)
  24. case kDelete:
  25. return execDelete(db, st.del, args)
  26. case kCreate:
  27. return execCreate(db, st.crt)
  28. case kCreateIndex:
  29. return execCreateIndex(db, st.cidx)
  30. case kDrop:
  31. return execDrop(db, st.drop)
  32. case kAlter:
  33. return execAlter(db, st.alt)
  34. case kTruncate:
  35. return execTruncate(db, st.trunc)
  36. case kVacuum:
  37. return execVacuum(db)
  38. default:
  39. return nil, fmt.Errorf("vrtx: 该语句不能用 Exec 执行")
  40. }
  41. }
  42. // execVacuum VACUUM —— 整库重建。引擎层会全程持有操作级串行锁并自行
  43. // Close/Open 句柄 (句柄指针不变, 驱动层的 shared.db 引用不需要跟着换),
  44. // 驱动侧的 shared.mu 正好把并发语句挡在门外, 两者不冲突。
  45. // 活跃事务中拒绝 (引擎层 ErrTxnActive); 只读模式 (force-inspect) 下
  46. // Commit 阶段即报错, 不会真动文件。
  47. func execVacuum(db *core.DB) (driver.Result, error) {
  48. res, err := db.VACUUM()
  49. if err != nil {
  50. return nil, err
  51. }
  52. return &result{affected: res.RowsCopied}, nil
  53. }
  54. func execInsert(db *core.DB, ins *insertStmt, args []driver.NamedValue) (driver.Result, error) {
  55. tbl, err := findTable(db, ins.table)
  56. if err != nil {
  57. return nil, err
  58. }
  59. cols, _, err := resolveInsertColumns(tbl, ins.columns)
  60. if err != nil {
  61. return nil, err
  62. }
  63. // SQL INSERT 语义: 未提供的列 = NULL (可空列置 NULL 位, 非空列报错)。
  64. // 引擎原生约定"未提供的列 = 零值"——驱动层把缺失列显式补成 nil,
  65. // 由 serializeRow 按 FlagNullable 裁决。
  66. provided := make(map[string]int, len(cols))
  67. for i, c := range cols {
  68. provided[strings.ToLower(c)] = i
  69. }
  70. allCols := activeColumnNames(tbl)
  71. // 显式主键: 提供了主键列的整数值就走 InsertRowWithID (SQL 语义: 给定 id 就是行号);
  72. // 未提供则走引擎自增 (InsertRow 分配的号会回填进主键镜像列)
  73. pkCol := pkColumnName(tbl)
  74. var pkFi *types.FieldInfo
  75. if pkCol != "" {
  76. pkFi = findField(tbl, pkCol)
  77. }
  78. var lastID int64
  79. for _, row := range ins.rows {
  80. if len(row) != len(cols) {
  81. return nil, fmt.Errorf("INSERT 列数 (%d) 与值数 (%d) 不一致", len(cols), len(row))
  82. }
  83. fvs := make([]types.FieldValue, 0, len(allCols))
  84. for _, cn := range allCols {
  85. fi := findField(tbl, cn)
  86. if pi, ok := provided[strings.ToLower(cn)]; ok {
  87. fv, err := buildFieldValue(fi, row[pi], args)
  88. if err != nil {
  89. return nil, fmt.Errorf("列 %q: %w", cn, err)
  90. }
  91. if fv != nil {
  92. fvs = append(fvs, *fv)
  93. continue
  94. }
  95. }
  96. // 未提供 / 显式 NULL: 显式写 nil (引擎置 NULL 位或按非空拒绝)
  97. fvs = append(fvs, types.FieldValue{FieldName: fi.FieldName, Value: nil})
  98. }
  99. // 主键判定
  100. var explicitPK *uint64
  101. if pkFi != nil {
  102. if pi, ok := provided[strings.ToLower(pkCol)]; ok {
  103. if _, isNull := row[pi].(nullValue); isNull {
  104. return nil, fmt.Errorf("主键列 %q 不能为 NULL", pkCol)
  105. }
  106. v, err := resolveValue(pkFi, row[pi], args)
  107. if err != nil {
  108. return nil, fmt.Errorf("主键列 %q: %w", pkCol, err)
  109. }
  110. n, ok := v.(int64)
  111. if !ok {
  112. return nil, fmt.Errorf("主键列 %q 需要整数值, 实际 %T", pkCol, v)
  113. }
  114. if n < 0 {
  115. return nil, fmt.Errorf("主键列 %q 不能为负: %d", pkCol, n)
  116. }
  117. u := uint64(n)
  118. explicitPK = &u
  119. }
  120. }
  121. var id uint64
  122. if explicitPK != nil {
  123. id, err = tbl.InsertRowWithID(*explicitPK, fvs)
  124. } else {
  125. id, err = tbl.InsertRow(fvs)
  126. }
  127. if err != nil {
  128. return nil, err
  129. }
  130. if id > math.MaxInt64 {
  131. return nil, fmt.Errorf("pkID %d 超出 int64 表示范围", id)
  132. }
  133. lastID = int64(id)
  134. }
  135. return &result{lastID: lastID, affected: int64(len(ins.rows))}, nil
  136. }
  137. // pkColumnName 返回行存储索引 (主键/时序) 的第一个分量列名; 无行存储返回 ""。
  138. func pkColumnName(tbl *core.Table) string {
  139. meta, ok := tbl.IndexMeta().GetRowStoreIndex()
  140. if !ok {
  141. return ""
  142. }
  143. fields := meta.Fields()
  144. if len(fields) == 0 {
  145. return ""
  146. }
  147. idx := int(fields[0])
  148. if idx < 0 || idx >= len(tbl.Field) {
  149. return ""
  150. }
  151. return string(tbl.Field[idx].FieldName)
  152. }
  153. func execUpdate(db *core.DB, upd *updateStmt, args []driver.NamedValue) (driver.Result, error) {
  154. tbl, err := findTable(db, upd.table)
  155. if err != nil {
  156. return nil, err
  157. }
  158. cond, err := translateWhere(tbl, upd.where, args)
  159. if err != nil {
  160. return nil, err
  161. }
  162. sets := make([]types.FieldValue, 0, len(upd.sets))
  163. for _, set := range upd.sets {
  164. fi := findField(tbl, set.col)
  165. if fi == nil {
  166. return nil, fmt.Errorf("%w: %q", core.ErrFieldNotFound, set.col)
  167. }
  168. fv, err := buildFieldValue(fi, set.val, args)
  169. if err != nil {
  170. return nil, fmt.Errorf("SET 列 %q: %w", set.col, err)
  171. }
  172. if fv != nil {
  173. sets = append(sets, *fv)
  174. }
  175. }
  176. // WHERE → pkID 集合 → 逐行更新 (引擎的 UpdateRowByPK 未提供的列沿用旧值)
  177. q := tbl.Query()
  178. if cond != nil {
  179. q = q.Where(cond)
  180. }
  181. var pkIDs []uint64
  182. err = q.ScanWithPKID(func(pkID uint64, row []types.FieldValue) bool {
  183. pkIDs = append(pkIDs, pkID)
  184. return true
  185. })
  186. if err != nil {
  187. return nil, err
  188. }
  189. for _, pkID := range pkIDs {
  190. if err := tbl.UpdateRowByPK(pkID, sets); err != nil {
  191. return nil, fmt.Errorf("更新 pkID=%d: %w", pkID, err)
  192. }
  193. }
  194. return &result{affected: int64(len(pkIDs))}, nil
  195. }
  196. func execDelete(db *core.DB, del *deleteStmt, args []driver.NamedValue) (driver.Result, error) {
  197. tbl, err := findTable(db, del.table)
  198. if err != nil {
  199. return nil, err
  200. }
  201. cond, err := translateWhere(tbl, del.where, args)
  202. if err != nil {
  203. return nil, err
  204. }
  205. q := tbl.Query()
  206. if cond != nil {
  207. q = q.Where(cond)
  208. }
  209. var pkIDs []uint64
  210. err = q.ScanWithPKID(func(pkID uint64, row []types.FieldValue) bool {
  211. pkIDs = append(pkIDs, pkID)
  212. return true
  213. })
  214. if err != nil {
  215. return nil, err
  216. }
  217. for _, pkID := range pkIDs {
  218. if err := tbl.DeleteRowByPK(pkID); err != nil {
  219. return nil, fmt.Errorf("删除 pkID=%d: %w", pkID, err)
  220. }
  221. }
  222. return &result{affected: int64(len(pkIDs))}, nil
  223. }
  224. // execCreate CREATE TABLE → 引擎建表 + 主键/唯一/普通索引。
  225. func execCreate(db *core.DB, crt *createStmt) (driver.Result, error) {
  226. if _, ok := db.FindTable(crt.table); ok {
  227. if crt.ifNotExists {
  228. return &result{}, nil
  229. }
  230. return nil, fmt.Errorf("表 %q 已存在", crt.table)
  231. }
  232. infos := make([]types.FieldInfo, 0, len(crt.columns))
  233. for _, c := range crt.columns {
  234. fi, err := sqlTypeToFieldInfo(c)
  235. if err != nil {
  236. return nil, fmt.Errorf("列 %q: %w", c.name, err)
  237. }
  238. infos = append(infos, fi)
  239. }
  240. tbl, err := db.CreateTable(crt.table, infos)
  241. if err != nil {
  242. return nil, err
  243. }
  244. // 主键索引 (整型列, 引擎行存储要求)
  245. if crt.pkCol != "" {
  246. fi := findField(tbl, crt.pkCol)
  247. if fi == nil {
  248. return nil, fmt.Errorf("%w (PRIMARY KEY): %q", core.ErrFieldNotFound, crt.pkCol)
  249. }
  250. if !isIntType(fi.FieldType) {
  251. return nil, fmt.Errorf("PRIMARY KEY 列 %q 必须是整数类型 (引擎行存储定位键)", crt.pkCol)
  252. }
  253. if _, err := tbl.CreateIndex("pk_"+crt.table, page.IndexTypePrimary, []byte{byte(fieldIndex(tbl, crt.pkCol))}); err != nil {
  254. return nil, err
  255. }
  256. }
  257. // 列级 UNIQUE → 唯一二级索引
  258. for _, c := range crt.columns {
  259. if !c.unique {
  260. continue
  261. }
  262. idx := inlineIndex{name: "ux_" + crt.table + "_" + c.name, columns: []string{c.name}, unique: true}
  263. crt.indexes = append(crt.indexes, idx)
  264. }
  265. // 内联索引 (KEY/UNIQUE KEY)
  266. for _, idx := range crt.indexes {
  267. fi := findField(tbl, idx.columns[0])
  268. if fi == nil {
  269. return nil, fmt.Errorf("%w (索引 %q): %q", core.ErrFieldNotFound, idx.name, idx.columns[0])
  270. }
  271. if fi.IsDropped() || types.IsDynamic(fi.FieldType) || types.IsBlob(fi.FieldType) {
  272. return nil, fmt.Errorf("索引 %q 的列 %q 不能建索引 (动态/二进制列)", idx.name, idx.columns[0])
  273. }
  274. name := idx.name
  275. if name == "" {
  276. name = "idx_" + crt.table + "_" + idx.columns[0]
  277. }
  278. if _, err := tbl.CreateIndex(name, page.IndexTypeBTree, []byte{byte(fieldIndex(tbl, idx.columns[0]))}, idx.unique); err != nil {
  279. return nil, err
  280. }
  281. }
  282. return &result{}, nil
  283. }
  284. // execCreateIndex CREATE [UNIQUE] INDEX name ON t (col)
  285. func execCreateIndex(db *core.DB, ci *createIndexStmt) (driver.Result, error) {
  286. tbl, err := findTable(db, ci.table)
  287. if err != nil {
  288. return nil, err
  289. }
  290. fi := findField(tbl, ci.col)
  291. if fi == nil {
  292. return nil, fmt.Errorf("%w: %q", core.ErrFieldNotFound, ci.col)
  293. }
  294. if _, err := tbl.CreateIndex(ci.name, page.IndexTypeBTree, []byte{byte(fieldIndex(tbl, ci.col))}, ci.unique); err != nil {
  295. return nil, err
  296. }
  297. return &result{}, nil
  298. }
  299. func execDrop(db *core.DB, d *dropStmt) (driver.Result, error) {
  300. if _, ok := db.FindTable(d.table); !ok {
  301. if d.ifExists {
  302. return &result{}, nil
  303. }
  304. return nil, fmt.Errorf("表 %q 不存在", d.table)
  305. }
  306. if err := db.DropTable(d.table); err != nil {
  307. return nil, err
  308. }
  309. return &result{}, nil
  310. }
  311. // execAlter ALTER TABLE t ADD/DROP COLUMN ... —— 引擎 AddField/DropField 已支持 schema 演进。
  312. func execAlter(db *core.DB, alt *alterStmt) (driver.Result, error) {
  313. tbl, err := findTable(db, alt.table)
  314. if err != nil {
  315. return nil, err
  316. }
  317. for _, op := range alt.ops {
  318. if op.drop {
  319. if err := tbl.DropField(op.col); err != nil {
  320. return nil, err
  321. }
  322. continue
  323. }
  324. fi, err := sqlTypeToFieldInfo(op.def)
  325. if err != nil {
  326. return nil, fmt.Errorf("列 %q: %w", op.def.name, err)
  327. }
  328. if err := tbl.AddField(fi); err != nil {
  329. return nil, err
  330. }
  331. // ADD 的 UNIQUE 列: AddField 只加列与 schema, 这里补建唯一索引。
  332. if op.def.unique {
  333. idx := fieldIndex(tbl, op.def.name)
  334. if idx < 0 {
  335. return nil, fmt.Errorf("ADD COLUMN 后找不到新列 %q", op.def.name)
  336. }
  337. if _, err := tbl.CreateIndex("ux_"+alt.table+"_"+op.def.name,
  338. page.IndexTypeBTree, []byte{byte(idx)}, true); err != nil {
  339. return nil, err
  340. }
  341. }
  342. }
  343. return &result{}, nil
  344. }
  345. // execTruncate TRUNCATE [TABLE] t —— 清空数据、保留表结构与索引定义。
  346. func execTruncate(db *core.DB, tr *truncateStmt) (driver.Result, error) {
  347. if _, err := findTable(db, tr.table); err != nil {
  348. return nil, err
  349. }
  350. if err := db.TruncateTable(tr.table); err != nil {
  351. return nil, err
  352. }
  353. return &result{}, nil
  354. }
  355. // execShow 以查询方式执行 SHOW / DESCRIBE, 返回物化结果集。算完即 release 锁。
  356. func execShow(db *core.DB, sh *showStmt, release func()) (driver.Rows, error) {
  357. if release != nil {
  358. defer release()
  359. }
  360. switch sh.what {
  361. case "TABLES":
  362. list := db.GetAllTables()
  363. data := make([][]driver.Value, 0, len(list))
  364. for _, t := range list {
  365. data = append(data, []driver.Value{[]byte(t.Name)})
  366. }
  367. cols := []string{"Tables_in_vrtx"}
  368. metas := []colMeta{{dbName: "VARCHAR", nullable: false, scanType: reflect.TypeOf("")}}
  369. return materialRows(cols, metas, data), nil
  370. case "COLUMNS", "DESCRIBE":
  371. tbl, err := findTable(db, sh.table)
  372. if err != nil {
  373. return nil, err
  374. }
  375. // MySQL 六列: Field / Type / Null / Key / Default / Extra
  376. cols := []string{"Field", "Type", "Null", "Key", "Default", "Extra"}
  377. vmeta := colMeta{dbName: "VARCHAR", nullable: false, scanType: reflect.TypeOf("")}
  378. metas := []colMeta{vmeta, vmeta, vmeta, vmeta, vmeta, vmeta}
  379. metas[4].nullable = true // Default 列可空
  380. var data [][]driver.Value
  381. for i := range tbl.Field {
  382. f := &tbl.Field[i]
  383. if f.IsDropped() {
  384. continue
  385. }
  386. null := "NO"
  387. if f.IsNullable() {
  388. null = "YES"
  389. }
  390. data = append(data, []driver.Value{
  391. []byte(string(f.FieldName)),
  392. []byte(columnTypeDisplay(f)),
  393. []byte(null),
  394. []byte(columnKeyIndicator(tbl, i)),
  395. nil, // Default: 引擎不持久化列默认值
  396. []byte(""),
  397. })
  398. }
  399. return materialRows(cols, metas, data), nil
  400. }
  401. return nil, fmt.Errorf("不支持的 SHOW 类型 %q", sh.what)
  402. }
  403. // columnTypeDisplay 生成 SHOW COLUMNS 的 Type 列文本, 如 varchar(255) / int / datetime。
  404. func columnTypeDisplay(f *types.FieldInfo) string {
  405. base := strings.ToLower(fieldTypeToSQLName(f.FieldType))
  406. switch f.FieldType {
  407. case types.FieldType_String:
  408. return fmt.Sprintf("%s(%d)", base, f.Width())
  409. case types.FieldType_Decimal:
  410. if f.Scale() > 0 { // FieldInfo 只持久化 scale, 无精度
  411. return fmt.Sprintf("%s(%d)", base, f.Scale())
  412. }
  413. }
  414. return base
  415. }
  416. // columnKeyIndicator 生成 SHOW COLUMNS 的 Key 列: PRI(主键/时序) / UNI(唯一) / MUL(普通) / ""。
  417. func columnKeyIndicator(tbl *core.Table, target int) string {
  418. pri, uni, mul := "", "", ""
  419. for _, m := range tbl.IndexMeta().GetIndexes() {
  420. hit := false
  421. for _, fid := range m.Fields() {
  422. if int(fid) == target {
  423. hit = true
  424. }
  425. }
  426. if !hit {
  427. continue
  428. }
  429. switch {
  430. case m.IndexType == page.IndexTypePrimary || m.IndexType == page.IndexTypeTime:
  431. pri = "PRI"
  432. case m.Unique():
  433. uni = "UNI"
  434. default:
  435. mul = "MUL"
  436. }
  437. }
  438. switch {
  439. case pri != "":
  440. return pri
  441. case uni != "":
  442. return uni
  443. default:
  444. return mul
  445. }
  446. }
  447. // queryStatement 执行 SELECT。普通单表 SELECT 流式返回 (持锁至 rows.Close, 首行
  448. // 不必等全扫完, 内存 O(缓冲)); 聚合一次性跑完、立即放锁并返回物化单行;
  449. // JOIN 查询 (join.go) 物化嵌套循环执行, 算完即放锁。
  450. // release 非 nil 表示锁由本次查询 (非事务) 获取, 任何提前返回错误都必须 release。
  451. func queryStatement(ctx context.Context, db *core.DB, sel *selectStmt, args []driver.NamedValue, release func()) (driver.Rows, error) {
  452. // SELECT 值清单 (无 FROM, 如探活语句 SELECT 1): 不触引擎, 物化单行立即返回。
  453. if sel.noFrom {
  454. return queryLiteralRow(sel, args, release)
  455. }
  456. if len(sel.joins) > 0 {
  457. return queryJoin(db, sel, args, release)
  458. }
  459. fail := func(err error) (driver.Rows, error) {
  460. if release != nil {
  461. release()
  462. }
  463. return nil, err
  464. }
  465. tbl, err := findTable(db, sel.from.name)
  466. if err != nil {
  467. return fail(err)
  468. }
  469. // 列引用统一允许限定名 (别名.列 / 表名.列): 单表路径校验限定词是本表后剥掉,
  470. // 剥好的 where/orderBy/agg.col 放语句副本, 不动 AST (Prepare 的语句要复用)。
  471. quals := []string{sel.from.alias, sel.from.name}
  472. sel2 := *sel
  473. if sel2.where, err = dequalifyExpr(sel.where, quals...); err != nil {
  474. return fail(err)
  475. }
  476. sel2.orderBy = make([]orderSpec, len(sel.orderBy))
  477. for i, o := range sel.orderBy {
  478. if sel2.orderBy[i].col, err = dequalifyColRef(o.col, quals...); err != nil {
  479. return fail(err)
  480. }
  481. sel2.orderBy[i].desc = o.desc
  482. }
  483. // 聚合: SELECT COUNT(*)/SUM/... FROM t [WHERE ...] —— 一次性算完, 立即放锁
  484. if sel.agg != nil {
  485. agg := *sel.agg
  486. if agg.col, err = dequalifyColRef(agg.col, quals...); err != nil {
  487. return fail(err)
  488. }
  489. sel2.agg = &agg
  490. r, err := queryAggregate(tbl, &sel2, args)
  491. if release != nil {
  492. release()
  493. }
  494. return r, err
  495. }
  496. // 列清单: * / t.* = 全部活跃列; 否则按请求列
  497. colNames, err := selectColsSingle(tbl, &sel2, quals...)
  498. if err != nil {
  499. return fail(err)
  500. }
  501. metas := make([]colMeta, len(colNames))
  502. for i, cn := range colNames {
  503. metas[i] = colMetaFor(findField(tbl, cn))
  504. }
  505. // 不在此 Select(): q.Scan 回调给的是未投影完整行, worker 按 colNames 自投影。
  506. q := tbl.Query()
  507. cond, err := translateWhere(tbl, sel2.where, args)
  508. if err != nil {
  509. return fail(err)
  510. }
  511. if cond != nil {
  512. q = q.Where(cond)
  513. }
  514. for _, o := range sel2.orderBy {
  515. // 引擎排序键按精确字节匹配列名: findField 校验存在后改用引擎规范名
  516. // (用户写 "ORDER BY Name" 也要落到 "name" 列)。
  517. fi := findField(tbl, o.col)
  518. if fi == nil {
  519. return fail(fmt.Errorf("%w: %q", core.ErrFieldNotFound, o.col))
  520. }
  521. q = q.OrderBy(string(fi.FieldName), o.desc)
  522. }
  523. if sel.limit != nil {
  524. lim, err := resolveLimitValue("LIMIT", sel.limit, args)
  525. if err != nil {
  526. return fail(err)
  527. }
  528. q = q.Limit(int(lim))
  529. }
  530. if sel.offset != nil {
  531. off, err := resolveLimitValue("OFFSET", sel.offset, args)
  532. if err != nil {
  533. return fail(err)
  534. }
  535. q = q.Offset(int(off))
  536. }
  537. r := newStreamRows(colNames, metas, blobReaderOf(tbl), release)
  538. r.start(ctx, colNames, sel.distinct, q)
  539. return r, nil
  540. }
  541. // queryLiteralRow 执行无 FROM 的 SELECT 值清单 ("SELECT 1" / "SELECT 'a', NULL"):
  542. // 每个值物化成 driver.Value, 拼成单行结果。不触引擎, 立即放锁。
  543. func queryLiteralRow(sel *selectStmt, args []driver.NamedValue, release func()) (driver.Rows, error) {
  544. if release != nil {
  545. defer release()
  546. }
  547. cols := make([]string, len(sel.literalVals))
  548. metas := make([]colMeta, len(sel.literalVals))
  549. row := make([]driver.Value, len(sel.literalVals))
  550. for i, v := range sel.literalVals {
  551. cols[i] = "?column?"
  552. dv, m, err := resolveLiteralValue(v, args)
  553. if err != nil {
  554. return nil, fmt.Errorf("SELECT 值清单第 %d 项: %w", i+1, err)
  555. }
  556. metas[i] = m
  557. row[i] = dv
  558. }
  559. return materialRows(cols, metas, [][]driver.Value{row}), nil
  560. }
  561. // resolveLiteralValue 把无 FROM 值清单里的字面量/占位符物化成 driver.Value,
  562. // 并按值的种类给出列元数据 (供 ColumnType* 反射)。
  563. func resolveLiteralValue(v value, args []driver.NamedValue) (driver.Value, colMeta, error) {
  564. intMeta := colMeta{dbName: "BIGINT", nullable: false, scanType: reflect.TypeOf(int64(0))}
  565. floatMeta := colMeta{dbName: "DOUBLE", nullable: false, scanType: reflect.TypeOf(float64(0))}
  566. strMeta := colMeta{dbName: "VARCHAR", nullable: false, scanType: reflect.TypeOf("")}
  567. nullMeta := colMeta{dbName: "NULL", nullable: true, scanType: reflect.TypeOf("")}
  568. switch t := v.(type) {
  569. case nullValue:
  570. return nil, nullMeta, nil
  571. case strValue:
  572. return []byte(t.s), strMeta, nil
  573. case litValue:
  574. raw := strings.TrimSpace(t.raw)
  575. if strings.Contains(raw, ".") {
  576. f, err := strconv.ParseFloat(raw, 64)
  577. if err != nil {
  578. return nil, colMeta{}, fmt.Errorf("浮点字面量 %q: %w", t.raw, err)
  579. }
  580. return f, floatMeta, nil
  581. }
  582. n, err := strconv.ParseInt(raw, 10, 64)
  583. if err != nil {
  584. return nil, colMeta{}, fmt.Errorf("整数字面量 %q: %w", t.raw, err)
  585. }
  586. return n, intMeta, nil
  587. case argValue:
  588. if t.idx >= len(args) {
  589. return nil, colMeta{}, fmt.Errorf("占位符 ?%d 没有对应参数 (共 %d 个)", t.idx+1, len(args))
  590. }
  591. switch x := args[t.idx].Value.(type) {
  592. case nil:
  593. return nil, nullMeta, nil
  594. case int64:
  595. return x, intMeta, nil
  596. case float64:
  597. return x, floatMeta, nil
  598. case bool:
  599. return x, colMeta{dbName: "BOOLEAN", nullable: false, scanType: reflect.TypeOf(false)}, nil
  600. case string:
  601. return []byte(x), strMeta, nil
  602. case []byte:
  603. return x, strMeta, nil
  604. case time.Time:
  605. return x, colMeta{dbName: "DATETIME", nullable: false, scanType: reflect.TypeOf(time.Time{})}, nil
  606. }
  607. return nil, colMeta{}, fmt.Errorf("参数类型 %T 不能出现在 SELECT 值清单", args[t.idx].Value)
  608. }
  609. return nil, colMeta{}, fmt.Errorf("无法解析的值")
  610. }
  611. // resolveLimitValue 解析 LIMIT/OFFSET 的量: 字面量直解整数; 占位符从 args
  612. // 取整数 (int64/uint64/数字字符串/整值浮点均可, 非整数报错)。
  613. func resolveLimitValue(keyword string, v value, args []driver.NamedValue) (int64, error) {
  614. switch t := v.(type) {
  615. case litValue:
  616. n, err := strconv.ParseInt(strings.TrimSpace(t.raw), 10, 64)
  617. if err != nil {
  618. return 0, fmt.Errorf("%s 期望整数, 实际是 %q", keyword, t.raw)
  619. }
  620. return n, nil
  621. case argValue:
  622. if t.idx >= len(args) {
  623. return 0, fmt.Errorf("占位符 ?%d 没有对应参数 (共 %d 个)", t.idx+1, len(args))
  624. }
  625. n, err := limitArgToInt64(args[t.idx].Value)
  626. if err != nil {
  627. return 0, fmt.Errorf("%s: %w", keyword, err)
  628. }
  629. return n, nil
  630. }
  631. return 0, fmt.Errorf("%s 只支持整数或 ? 占位符", keyword)
  632. }
  633. // limitArgToInt64 把 LIMIT/OFFSET 的参数值规整成 int64。
  634. func limitArgToInt64(v driver.Value) (int64, error) {
  635. switch x := v.(type) {
  636. case int64:
  637. return x, nil
  638. case uint64:
  639. if x > math.MaxInt64 {
  640. return 0, fmt.Errorf("超出 int64 范围: %d", x)
  641. }
  642. return int64(x), nil
  643. case float64:
  644. if x != math.Trunc(x) {
  645. return 0, fmt.Errorf("参数必须是非负整数, 实际 %v", x)
  646. }
  647. return int64(x), nil
  648. case string:
  649. n, err := strconv.ParseInt(strings.TrimSpace(x), 10, 64)
  650. if err != nil {
  651. return 0, fmt.Errorf("参数 %q 不是整数", x)
  652. }
  653. return n, nil
  654. case []byte:
  655. return limitArgToInt64(string(x))
  656. }
  657. return 0, fmt.Errorf("参数必须是整数, 实际 %T", v)
  658. }
  659. func queryAggregate(tbl *core.Table, sel *selectStmt, args []driver.NamedValue) (*rows, error) {
  660. cond, err := translateWhere(tbl, sel.where, args)
  661. if err != nil {
  662. return nil, err
  663. }
  664. q := tbl.Query()
  665. if cond != nil {
  666. q = q.Where(cond)
  667. }
  668. col := sel.agg.col
  669. // 聚合目标列在引擎侧同样按精确字节匹配: findField 校验存在后改用引擎
  670. // 规范名 (COUNT(*) 无目标列, 跳过校验)。
  671. if col != "" {
  672. fi := findField(tbl, col)
  673. if fi == nil {
  674. return nil, fmt.Errorf("%w: %q", core.ErrFieldNotFound, col)
  675. }
  676. col = string(fi.FieldName)
  677. }
  678. var dv driver.Value
  679. var m colMeta
  680. switch sel.agg.fn {
  681. case "COUNT":
  682. n, err := q.Count()
  683. if err != nil {
  684. return nil, err
  685. }
  686. dv = n
  687. m = colMeta{dbName: "BIGINT", nullable: false, scanType: reflect.TypeOf(int64(0))}
  688. case "SUM":
  689. v, err := q.Sum(col)
  690. if err != nil {
  691. return nil, err
  692. }
  693. dv = v
  694. m = colMeta{dbName: "DOUBLE", nullable: true, scanType: reflect.TypeOf(float64(0))}
  695. case "MIN":
  696. fi := findField(tbl, col)
  697. v, err := q.Min(col)
  698. if err != nil {
  699. return nil, err
  700. }
  701. dv, err = fieldValueToDriverTyped(fi.FieldType, v)
  702. if err != nil {
  703. return nil, err
  704. }
  705. m = colMetaFor(fi)
  706. m.nullable = true
  707. case "MAX":
  708. fi := findField(tbl, col)
  709. v, err := q.Max(col)
  710. if err != nil {
  711. return nil, err
  712. }
  713. dv, err = fieldValueToDriverTyped(fi.FieldType, v)
  714. if err != nil {
  715. return nil, err
  716. }
  717. m = colMetaFor(fi)
  718. m.nullable = true
  719. case "AVG":
  720. s, err := q.Sum(col)
  721. if err != nil {
  722. return nil, err
  723. }
  724. // AVG 的分母是"该列非 NULL 的行数", 不是全表行数。
  725. // 注意引擎 Query.Where 是覆盖语义, 分母查询必须把 WHERE 与
  726. // IS NOT NULL 合成一个条件, 否则后写覆盖先写、过滤被丢掉。
  727. var denomCond core.Condition = core.IsNotNull(col)
  728. if cond != nil {
  729. denomCond = core.And(cond, denomCond)
  730. }
  731. n, err := tbl.Query().Where(denomCond).Count()
  732. if err != nil {
  733. return nil, err
  734. }
  735. if n == 0 {
  736. dv = nil // SQL: 无输入行 → NULL
  737. } else {
  738. dv = s / float64(n)
  739. }
  740. m = colMeta{dbName: "DOUBLE", nullable: true, scanType: reflect.TypeOf(float64(0))}
  741. default:
  742. return nil, fmt.Errorf("不支持的聚合函数 %q", sel.agg.fn)
  743. }
  744. name := strings.ToLower(sel.agg.fn)
  745. if col != "" {
  746. name += "_" + col
  747. }
  748. return materialRows([]string{name}, []colMeta{m}, [][]driver.Value{{dv}}), nil
  749. }
  750. // =============================================================================
  751. // 结果集列元数据 (driver.RowsColumnType* 系列)
  752. // =============================================================================
  753. // colMeta 描述一列在结果集中的类型信息。
  754. type colMeta struct {
  755. ft types.FieldType // 引擎列类型 (typed 值转换用)
  756. dbName string // 数据库类型名 (BIGINT/VARCHAR/...)
  757. nullable bool // 是否可空
  758. scanType reflect.Type // Scan 的目标 Go 类型 (sqlx/GORM 反射用)
  759. length int64 // 定长字符串宽度
  760. hasLen bool
  761. }
  762. func colMetaFor(fi *types.FieldInfo) colMeta {
  763. m := colMeta{
  764. ft: fi.FieldType,
  765. dbName: fieldTypeToSQLName(fi.FieldType),
  766. nullable: fi.Flag&types.FlagNullable != 0,
  767. scanType: fieldTypeScanType(fi.FieldType),
  768. }
  769. if fi.FieldType == types.FieldType_String {
  770. if w := fi.Width(); w > 0 {
  771. m.length = int64(w)
  772. m.hasLen = true
  773. }
  774. }
  775. return m
  776. }
  777. func fieldTypeScanType(ft types.FieldType) reflect.Type {
  778. switch ft {
  779. case types.FieldType_DateTime:
  780. return reflect.TypeOf(time.Time{})
  781. case types.FieldType_Float64, types.FieldType_Float32:
  782. return reflect.TypeOf(float64(0))
  783. case types.FieldType_Bool:
  784. return reflect.TypeOf(false)
  785. case types.FieldType_Blob, types.FieldType_Dynamicbyte:
  786. return reflect.TypeOf([]byte(nil))
  787. default:
  788. if isIntType(ft) {
  789. return reflect.TypeOf(int64(0))
  790. }
  791. return reflect.TypeOf("") // String / Decimal / UUID
  792. }
  793. }
  794. func fieldTypeToSQLName(ft types.FieldType) string {
  795. switch ft {
  796. case types.FieldType_DateTime:
  797. return "DATETIME"
  798. case types.FieldType_Int64:
  799. return "BIGINT"
  800. case types.FieldType_Int32:
  801. return "INT"
  802. case types.FieldType_Int16:
  803. return "SMALLINT"
  804. case types.FieldType_Int8:
  805. return "TINYINT"
  806. case types.FieldType_Uint64:
  807. return "BIGINT UNSIGNED"
  808. case types.FieldType_Uint32:
  809. return "INT UNSIGNED"
  810. case types.FieldType_Uint16:
  811. return "SMALLINT UNSIGNED"
  812. case types.FieldType_Uint8:
  813. return "TINYINT UNSIGNED"
  814. case types.FieldType_Float64:
  815. return "DOUBLE"
  816. case types.FieldType_Float32:
  817. return "FLOAT"
  818. case types.FieldType_Bool:
  819. return "BOOLEAN"
  820. case types.FieldType_String:
  821. return "VARCHAR"
  822. case types.FieldType_Dynamicbyte:
  823. return "TEXT"
  824. case types.FieldType_Blob:
  825. return "BLOB"
  826. case types.FieldType_Decimal:
  827. return "DECIMAL"
  828. case types.FieldType_UUID:
  829. return "UUID"
  830. case types.FieldType_Year:
  831. return "YEAR"
  832. }
  833. return ""
  834. }
  835. // =============================================================================
  836. // WHERE 翻译: SQL 表达式 → core.Condition
  837. // =============================================================================
  838. func translateWhere(tbl *core.Table, e expr, args []driver.NamedValue) (core.Condition, error) {
  839. if e == nil {
  840. return nil, nil
  841. }
  842. switch t := e.(type) {
  843. case *andExpr:
  844. l, err := translateWhere(tbl, t.l, args)
  845. if err != nil {
  846. return nil, err
  847. }
  848. r, err := translateWhere(tbl, t.r, args)
  849. if err != nil {
  850. return nil, err
  851. }
  852. return core.And(l, r), nil
  853. case *orExpr:
  854. l, err := translateWhere(tbl, t.l, args)
  855. if err != nil {
  856. return nil, err
  857. }
  858. r, err := translateWhere(tbl, t.r, args)
  859. if err != nil {
  860. return nil, err
  861. }
  862. return core.Or(l, r), nil
  863. case *notExpr:
  864. inner, err := translateWhere(tbl, t.e, args)
  865. if err != nil {
  866. return nil, err
  867. }
  868. return core.Not(inner), nil
  869. case *cmpExpr:
  870. col := resolveColRef(t.col)
  871. fi := findField(tbl, col)
  872. if fi == nil {
  873. return nil, fmt.Errorf("%w (WHERE): %q", core.ErrFieldNotFound, t.col)
  874. }
  875. v, err := resolveValue(fi, t.val, args)
  876. if err != nil {
  877. return nil, err
  878. }
  879. // 引擎条件按精确字节匹配列名, 统一改用引擎规范名 (findField 已做
  880. // 大小写不敏感的存在性校验, 用户写 "Title" 也能落到 "title" 列)。
  881. canon := string(fi.FieldName)
  882. switch t.op {
  883. case "=":
  884. return core.Eq(canon, v, fi.FieldType), nil
  885. case "!=":
  886. return core.Not(core.Eq(canon, v, fi.FieldType)), nil
  887. case ">":
  888. return core.Gt(canon, v, fi.FieldType), nil
  889. case ">=":
  890. return core.Ge(canon, v, fi.FieldType), nil
  891. case "<":
  892. return core.Lt(canon, v, fi.FieldType), nil
  893. case "<=":
  894. return core.Le(canon, v, fi.FieldType), nil
  895. }
  896. return nil, fmt.Errorf("不支持的比较符 %q", t.op)
  897. case *colCmpExpr:
  898. // 列与列比较: 引擎 Condition 只支持列与值, 仅 JOIN 查询把它当残余谓词在
  899. // 组合行上求值; 单表/UPDATE/DELETE 走到这里说明用法越界, 明确报错。
  900. return nil, fmt.Errorf("列与列的比较 (%s %s %s) 仅在多表 JOIN 查询中支持", t.left, t.op, t.right)
  901. case *inExpr:
  902. col := resolveColRef(t.col)
  903. fi := findField(tbl, col)
  904. if fi == nil {
  905. return nil, fmt.Errorf("%w (WHERE): %q", core.ErrFieldNotFound, t.col)
  906. }
  907. vals := make([]interface{}, 0, len(t.vals))
  908. for _, tv := range t.vals {
  909. v, err := resolveValue(fi, tv, args)
  910. if err != nil {
  911. return nil, err
  912. }
  913. vals = append(vals, v)
  914. }
  915. c := core.In(string(fi.FieldName), vals, fi.FieldType)
  916. if t.neg {
  917. return core.Not(c), nil
  918. }
  919. return c, nil
  920. case *isNullExpr:
  921. // IS [NOT] NULL → 引擎的 NullCondition: 直接读行内 NULL 位图
  922. // (与反序列化/索引提取同一口径; Eq 对 NULL 行一律不匹配, 表达不了 IS NULL)
  923. // 列名同样要剥限定前缀 — GORM 生成 `t`.`deleted_at` IS NULL,
  924. // 不剥的话 NullCondition 按全名找不到列、静默恒假 (UPDATE/DELETE 0 行)。
  925. // NullCondition.Field 也是按精确字节匹配, 必须改用引擎规范名。
  926. col := resolveColRef(t.col)
  927. fi := findField(tbl, col)
  928. if fi == nil {
  929. return nil, fmt.Errorf("%w (WHERE): %q", core.ErrFieldNotFound, t.col)
  930. }
  931. if t.neg {
  932. return core.IsNotNull(string(fi.FieldName)), nil
  933. }
  934. return core.IsNull(string(fi.FieldName)), nil
  935. case *likeExpr:
  936. pat, err := resolveLikePattern(t.pattern, args)
  937. if err != nil {
  938. return nil, err
  939. }
  940. if t.lhs != nil {
  941. // || 拼接左操作数: 逐分量翻译 (字面量原样 / 列名剥限定并改引擎规范名),
  942. // 拼好后按 LIKE 语义匹配 (core.ConcatLikeCondition 内部完成)。
  943. parts := make([]core.ConcatPart, 0, len(t.lhs.parts))
  944. for _, cp := range t.lhs.parts {
  945. if !cp.isCol {
  946. parts = append(parts, core.ConcatPart{Lit: cp.lit})
  947. continue
  948. }
  949. col := resolveColRef(cp.col)
  950. fi := findField(tbl, col)
  951. if fi == nil {
  952. return nil, fmt.Errorf("%w (WHERE): %q", core.ErrFieldNotFound, cp.col)
  953. }
  954. parts = append(parts, core.ConcatPart{IsCol: true, Col: string(fi.FieldName)})
  955. }
  956. return core.ConcatLikeCondition{Parts: parts, Pattern: pat, Neg: t.neg}, nil
  957. }
  958. col := resolveColRef(t.col)
  959. fi := findField(tbl, col)
  960. if fi == nil {
  961. return nil, fmt.Errorf("%w (WHERE): %q", core.ErrFieldNotFound, t.col)
  962. }
  963. c := core.Like(string(fi.FieldName), pat)
  964. if t.neg {
  965. return core.Not(c), nil
  966. }
  967. return c, nil
  968. }
  969. return nil, fmt.Errorf("无法翻译的 WHERE 表达式")
  970. }
  971. // resolveColRef 列名归一: 剥掉 "表名." / "别名." 限定前缀。GORM 等 ORM 生成的
  972. // SQL 普遍带反引号限定 (`t`.`col`, 词法层拼成 "t.col"), 而引擎条件按裸列名
  973. // 匹配 — 不剥的话: 等值/IN/LIKE 报"列不存在", IS NULL 按全名找不到列、
  974. // Match 静默恒假 (UPDATE/DELETE 作用 0 行, 无任何报错)。
  975. func resolveColRef(col string) string {
  976. if i := strings.LastIndexByte(col, '.'); i >= 0 {
  977. return col[i+1:]
  978. }
  979. return col
  980. }
  981. // =============================================================================
  982. // 表/列/值解析辅助
  983. // =============================================================================
  984. func findTable(db *core.DB, name string) (*core.Table, error) {
  985. tbl, ok := db.FindTable(name)
  986. if !ok {
  987. return nil, fmt.Errorf("%w: %q", core.ErrTableNotFound, name)
  988. }
  989. return tbl, nil
  990. }
  991. // findField 按列名查活跃字段 (大小写不敏感)。
  992. func findField(tbl *core.Table, name string) *types.FieldInfo {
  993. for i := range tbl.Field {
  994. f := &tbl.Field[i]
  995. if f.IsDropped() {
  996. continue
  997. }
  998. if strings.EqualFold(string(f.FieldName), name) {
  999. return f
  1000. }
  1001. }
  1002. return nil
  1003. }
  1004. func fieldIndex(tbl *core.Table, name string) int {
  1005. for i := range tbl.Field {
  1006. if !tbl.Field[i].IsDropped() && strings.EqualFold(string(tbl.Field[i].FieldName), name) {
  1007. return i
  1008. }
  1009. }
  1010. return -1
  1011. }
  1012. func activeColumnNames(tbl *core.Table) []string {
  1013. out := make([]string, 0, len(tbl.Field))
  1014. for i := range tbl.Field {
  1015. if !tbl.Field[i].IsDropped() {
  1016. out = append(out, string(tbl.Field[i].FieldName))
  1017. }
  1018. }
  1019. return out
  1020. }
  1021. func resolveInsertColumns(tbl *core.Table, columns []string) ([]string, []*types.FieldInfo, error) {
  1022. if len(columns) == 0 {
  1023. names := activeColumnNames(tbl)
  1024. infos := make([]*types.FieldInfo, 0, len(names))
  1025. for _, n := range names {
  1026. infos = append(infos, findField(tbl, n))
  1027. }
  1028. return names, infos, nil
  1029. }
  1030. infos := make([]*types.FieldInfo, 0, len(columns))
  1031. for _, c := range columns {
  1032. fi := findField(tbl, c)
  1033. if fi == nil {
  1034. return nil, nil, fmt.Errorf("%w: %q", core.ErrFieldNotFound, c)
  1035. }
  1036. infos = append(infos, fi)
  1037. }
  1038. return columns, infos, nil
  1039. }
  1040. // resolveValue 把 AST 值 (占位/字面量/字符串/NULL) 解析成引擎值。
  1041. // 字面量按列类型解释 (数字 → int64/float64; 字符串按列类型编码)。
  1042. func resolveValue(fi *types.FieldInfo, v value, args []driver.NamedValue) (interface{}, error) {
  1043. switch t := v.(type) {
  1044. case argValue:
  1045. if t.idx >= len(args) {
  1046. return nil, fmt.Errorf("占位符 ?%d 没有对应参数 (共 %d 个)", t.idx+1, len(args))
  1047. }
  1048. return driverToEngineValue(fi, args[t.idx].Value)
  1049. case strValue:
  1050. return parseLiteralAsType(fi, t.s)
  1051. case litValue:
  1052. return parseLiteralAsType(fi, t.raw)
  1053. case nullValue:
  1054. return nil, nil
  1055. }
  1056. return nil, fmt.Errorf("无法解析的值")
  1057. }
  1058. // buildFieldValue 构造 FieldValue; NULL 返回 nil (调用方跳过, 由引擎按可空/非空裁决)。
  1059. func buildFieldValue(fi *types.FieldInfo, v value, args []driver.NamedValue) (*types.FieldValue, error) {
  1060. if _, isNull := v.(nullValue); isNull {
  1061. return nil, nil
  1062. }
  1063. ev, err := resolveValue(fi, v, args)
  1064. if err != nil {
  1065. return nil, err
  1066. }
  1067. return &types.FieldValue{FieldName: fi.FieldName, Value: ev}, nil
  1068. }
  1069. func resolveLikePattern(v value, args []driver.NamedValue) (string, error) {
  1070. switch t := v.(type) {
  1071. case strValue:
  1072. return t.s, nil
  1073. case argValue:
  1074. if t.idx >= len(args) {
  1075. return "", fmt.Errorf("LIKE 的占位符没有对应参数")
  1076. }
  1077. s, ok := args[t.idx].Value.(string)
  1078. if !ok {
  1079. if b, ok2 := args[t.idx].Value.([]byte); ok2 {
  1080. return string(b), nil
  1081. }
  1082. return "", fmt.Errorf("LIKE 参数必须是字符串")
  1083. }
  1084. return s, nil
  1085. }
  1086. return "", fmt.Errorf("LIKE 模式必须是字符串字面量或占位符")
  1087. }
  1088. func isIntType(ft types.FieldType) bool {
  1089. switch ft {
  1090. case types.FieldType_Int64, types.FieldType_Uint64,
  1091. types.FieldType_Int32, types.FieldType_Uint32,
  1092. types.FieldType_Int16, types.FieldType_Uint16,
  1093. types.FieldType_Int8, types.FieldType_Uint8:
  1094. return true
  1095. }
  1096. return false
  1097. }
  1098. // 时间戳约定: driver 的 time.Time 与引擎 uint64 毫秒互转。
  1099. var unixEpoch = time.Unix(0, 0)
  1100. func timeToMillis(t time.Time) uint64 {
  1101. return uint64(t.Sub(unixEpoch).Milliseconds())
  1102. }
  1103. func millisToTime(ms uint64) time.Time {
  1104. return unixEpoch.Add(time.Duration(ms) * time.Millisecond)
  1105. }