exec.go 33 KB

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