join.go 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090
  1. package vrtxsql
  2. // JOIN 查询执行: 多表嵌套循环 + 右表索引点查, 结果物化后立即放锁。
  3. // 仅 SELECT ... FROM t1 JOIN t2 ON ... 走本路径 (单表查询仍走流式路径,
  4. // 见 exec.go queryStatement)。
  5. //
  6. // 执行策略:
  7. // - 左表全扫描 (本表 WHERE 条件下推), 每行存 别名(小写) → 列(小写) → driver.Value;
  8. // - 逐 JOIN: 取组合行里 ON 左列的值, 对右表做索引点查
  9. // (tbl.Query().Where(core.Eq(...)) + 右表本表条件), 命中行做笛卡尔组合;
  10. // INNER 无匹配丢行, LEFT 无匹配时右表列全 NULL 保留行;
  11. // - WHERE 按列归属拆分: 叶子条件 (AND 结构) 下推到所属表, 跨表 OR/NOT/列比较
  12. // 作为残余谓词在组合行上用 Go 值比较过滤 (= != < <= > >=);
  13. // - 投影 (*/t.*/t.col/col 混用, 重名列用 别名_列名 去重) → ORDER BY 内存
  14. // 稳定排序 (NULL 视为最小) → LIMIT/OFFSET, 返回物化 *rows。
  15. import (
  16. "database/sql/driver"
  17. "fmt"
  18. "sort"
  19. "strconv"
  20. "strings"
  21. "time"
  22. "git.ycl.pub/yl32940/TsDB2/DB/core"
  23. "git.ycl.pub/yl32940/TsDB2/DB/core/types"
  24. )
  25. // =============================================================================
  26. // 限定名列引用的解析辅助 (单表路径解限定 + JOIN 路径归属判定共用)
  27. // =============================================================================
  28. // splitQualCol 把列引用拆成 (限定词, 列名); 无 '.' 时 qual 为空。
  29. func splitQualCol(ref string) (qual, col string) {
  30. if i := strings.IndexByte(ref, '.'); i >= 0 {
  31. return ref[:i], ref[i+1:]
  32. }
  33. return "", ref
  34. }
  35. // dequalifyColRef 校验并剥掉列引用的限定词 ("t.col" → "col"); 非限定名原样返回。
  36. func dequalifyColRef(ref string, quals ...string) (string, error) {
  37. qual, col := splitQualCol(ref)
  38. if qual == "" {
  39. return ref, nil
  40. }
  41. for _, q := range quals {
  42. if strings.EqualFold(q, qual) {
  43. return col, nil
  44. }
  45. }
  46. return "", fmt.Errorf("列限定 %q 与 FROM 表 (%s) 不匹配", qual, strings.Join(quals, "/"))
  47. }
  48. // dequalifyExpr 剥掉表达式里所有列引用的限定词 (单表 SELECT 用; 值原样保留)。
  49. func dequalifyExpr(e expr, quals ...string) (expr, error) {
  50. if e == nil {
  51. return nil, nil
  52. }
  53. switch t := e.(type) {
  54. case *andExpr:
  55. l, err := dequalifyExpr(t.l, quals...)
  56. if err != nil {
  57. return nil, err
  58. }
  59. r, err := dequalifyExpr(t.r, quals...)
  60. if err != nil {
  61. return nil, err
  62. }
  63. return &andExpr{l: l, r: r}, nil
  64. case *orExpr:
  65. l, err := dequalifyExpr(t.l, quals...)
  66. if err != nil {
  67. return nil, err
  68. }
  69. r, err := dequalifyExpr(t.r, quals...)
  70. if err != nil {
  71. return nil, err
  72. }
  73. return &orExpr{l: l, r: r}, nil
  74. case *notExpr:
  75. inner, err := dequalifyExpr(t.e, quals...)
  76. if err != nil {
  77. return nil, err
  78. }
  79. return &notExpr{e: inner}, nil
  80. case *cmpExpr:
  81. col, err := dequalifyColRef(t.col, quals...)
  82. if err != nil {
  83. return nil, err
  84. }
  85. return &cmpExpr{col: col, op: t.op, val: t.val}, nil
  86. case *colCmpExpr:
  87. l, err := dequalifyColRef(t.left, quals...)
  88. if err != nil {
  89. return nil, err
  90. }
  91. r, err := dequalifyColRef(t.right, quals...)
  92. if err != nil {
  93. return nil, err
  94. }
  95. return &colCmpExpr{left: l, op: t.op, right: r}, nil
  96. case *inExpr:
  97. col, err := dequalifyColRef(t.col, quals...)
  98. if err != nil {
  99. return nil, err
  100. }
  101. return &inExpr{col: col, vals: t.vals, neg: t.neg}, nil
  102. case *isNullExpr:
  103. col, err := dequalifyColRef(t.col, quals...)
  104. if err != nil {
  105. return nil, err
  106. }
  107. return &isNullExpr{col: col, neg: t.neg}, nil
  108. case *likeExpr:
  109. if t.lhs != nil {
  110. parts := make([]concatPart, len(t.lhs.parts))
  111. copy(parts, t.lhs.parts)
  112. for i := range parts {
  113. if !parts[i].isCol {
  114. continue
  115. }
  116. col, err := dequalifyColRef(parts[i].col, quals...)
  117. if err != nil {
  118. return nil, err
  119. }
  120. parts[i].col = col
  121. }
  122. return &likeExpr{lhs: &concatExpr{parts: parts}, pattern: t.pattern, neg: t.neg}, nil
  123. }
  124. col, err := dequalifyColRef(t.col, quals...)
  125. if err != nil {
  126. return nil, err
  127. }
  128. return &likeExpr{col: col, pattern: t.pattern, neg: t.neg}, nil
  129. }
  130. return nil, fmt.Errorf("无法处理的 WHERE 表达式")
  131. }
  132. // selectColsSingle 单表 SELECT 的列清单展开: 空 / "*" / "t.*" → 全部活跃列;
  133. // "t.col" → 校验限定词后取列; 列存在性校验与旧行为一致 (ErrFieldNotFound)。
  134. func selectColsSingle(tbl *core.Table, sel *selectStmt, quals ...string) ([]string, error) {
  135. if len(sel.columns) == 0 {
  136. return activeColumnNames(tbl), nil
  137. }
  138. out := make([]string, 0, len(sel.columns))
  139. for _, c := range sel.columns {
  140. if c == "*" {
  141. out = append(out, activeColumnNames(tbl)...)
  142. continue
  143. }
  144. if strings.HasSuffix(c, ".*") {
  145. if _, err := dequalifyColRef(c, quals...); err != nil {
  146. return nil, err
  147. }
  148. out = append(out, activeColumnNames(tbl)...)
  149. continue
  150. }
  151. col, err := dequalifyColRef(c, quals...)
  152. if err != nil {
  153. return nil, err
  154. }
  155. // 投影列名统一改用引擎规范名: 结果集表头与引擎列名一致 (MySQL 语义),
  156. // 也避免下游按用户原文 (大小写混写) 做精确匹配时落空。
  157. fi := findField(tbl, col)
  158. if fi == nil {
  159. return nil, fmt.Errorf("%w: %q", core.ErrFieldNotFound, c)
  160. }
  161. out = append(out, string(fi.FieldName))
  162. }
  163. return out, nil
  164. }
  165. // =============================================================================
  166. // JOIN 执行
  167. // =============================================================================
  168. // joinTable 参与 JOIN 的一张表: 引擎表 + 归一化别名 + 活跃列。
  169. type joinTable struct {
  170. idx int
  171. name string
  172. alias string // 限定名归一化结果 (alias 缺省 = 表名), 比较时大小写不敏感
  173. tbl *core.Table
  174. cols []string // 活跃列名 (原始大小写, 投影展示用)
  175. ft map[string]types.FieldType // 小写列名 → 列类型 (typed 值转换用)
  176. }
  177. func buildJoinTable(idx int, ref tableRef, tbl *core.Table) *joinTable {
  178. alias := ref.alias
  179. if alias == "" {
  180. alias = ref.name
  181. }
  182. jt := &joinTable{idx: idx, name: ref.name, alias: alias, tbl: tbl, ft: map[string]types.FieldType{}}
  183. for i := range tbl.Field {
  184. f := &tbl.Field[i]
  185. if f.IsDropped() {
  186. continue
  187. }
  188. cn := string(f.FieldName)
  189. jt.cols = append(jt.cols, cn)
  190. jt.ft[strings.ToLower(cn)] = f.FieldType
  191. }
  192. return jt
  193. }
  194. // joinRow 组合行: 表别名(小写) → 列名(小写) → driver.Value (未匹配侧为 NULL)。
  195. type joinRow map[string]map[string]driver.Value
  196. func (r joinRow) get(jt *joinTable, col string) driver.Value {
  197. return r[strings.ToLower(jt.alias)][strings.ToLower(col)]
  198. }
  199. func cloneJoinRow(r joinRow) joinRow {
  200. nr := make(joinRow, len(r)+1)
  201. for k, v := range r {
  202. nr[k] = v
  203. }
  204. return nr
  205. }
  206. // nullJoinRow 右表无匹配时 (LEFT JOIN) 的全 NULL 行。
  207. func nullJoinRow(jt *joinTable) map[string]driver.Value {
  208. m := make(map[string]driver.Value, len(jt.cols))
  209. for _, cn := range jt.cols {
  210. m[strings.ToLower(cn)] = nil
  211. }
  212. return m
  213. }
  214. // findQual 按限定词找表 (别名或表名, 大小写不敏感)。
  215. func findQual(ts []*joinTable, qual string) *joinTable {
  216. for _, jt := range ts {
  217. if strings.EqualFold(jt.alias, qual) || strings.EqualFold(jt.name, qual) {
  218. return jt
  219. }
  220. }
  221. return nil
  222. }
  223. // ownerOfCol 解析列引用归属的表: 限定名直查; 非限定名要求在恰好一张表上存在
  224. // (存在于多张报"列不明确", 没有报列不存在)。返回归属表与剥掉限定后的列名。
  225. func ownerOfCol(ts []*joinTable, ref string) (*joinTable, string, error) {
  226. qual, col := splitQualCol(ref)
  227. if qual != "" {
  228. jt := findQual(ts, qual)
  229. if jt == nil {
  230. return nil, "", fmt.Errorf("未知的表限定 %q (列 %q)", qual, ref)
  231. }
  232. if findField(jt.tbl, col) == nil {
  233. return nil, "", fmt.Errorf("%w: %q", core.ErrFieldNotFound, ref)
  234. }
  235. return jt, col, nil
  236. }
  237. var hit *joinTable
  238. for _, jt := range ts {
  239. if findField(jt.tbl, col) != nil {
  240. if hit != nil {
  241. return nil, "", fmt.Errorf("列 %q 不明确 (同时存在于 %q 和 %q)", col, hit.alias, jt.alias)
  242. }
  243. hit = jt
  244. }
  245. }
  246. if hit == nil {
  247. return nil, "", fmt.Errorf("%w: %q", core.ErrFieldNotFound, ref)
  248. }
  249. return hit, col, nil
  250. }
  251. // scanJoinTable 扫一张表 (应用下推条件), 每行 → 小写列名 → driver.Value。
  252. func scanJoinTable(jt *joinTable, cond core.Condition) ([]map[string]driver.Value, error) {
  253. q := jt.tbl.Query()
  254. if cond != nil {
  255. q = q.Where(cond)
  256. }
  257. var out []map[string]driver.Value
  258. var convErr error
  259. readBlob := blobReaderOf(jt.tbl) // Blob 列行内 8B 引用 → 内容字节 (持锁期间调)
  260. err := q.Scan(func(full []types.FieldValue) bool {
  261. m := make(map[string]driver.Value, len(full))
  262. for _, fv := range full {
  263. key := strings.ToLower(string(fv.FieldName))
  264. raw := fv.Value
  265. if ref, isRef := raw.(types.BlobRef); isRef {
  266. data, err := readBlob(ref)
  267. if err != nil {
  268. convErr = fmt.Errorf("读取 BLOB 列 %q: %w", fv.FieldName, err)
  269. return false
  270. }
  271. m[key] = data
  272. continue
  273. }
  274. dv, err := fieldValueToDriverTyped(jt.ft[key], raw)
  275. if err != nil {
  276. convErr = err
  277. return false
  278. }
  279. m[key] = joinTypedValue(jt.ft[key], dv)
  280. }
  281. out = append(out, m)
  282. return true
  283. })
  284. if convErr != nil {
  285. return nil, convErr
  286. }
  287. if err != nil {
  288. return nil, err
  289. }
  290. return out, nil
  291. }
  292. // joinTypedValue 把整型/浮点列的文本化值归一回数值: fieldValueToDriver 对
  293. // int32 等小整型走 fmt.Sprint 兜底成 []byte, 残余谓词/排序会因此变成字符串
  294. // 比较 ("100" < "25"), 这里按列类型归一, 与 BIGINT 的输出形态 (int64) 对齐。
  295. func joinTypedValue(ft types.FieldType, v driver.Value) driver.Value {
  296. if v == nil {
  297. return nil
  298. }
  299. var s string
  300. switch t := v.(type) {
  301. case []byte:
  302. s = string(t)
  303. case string:
  304. s = t
  305. default:
  306. return v
  307. }
  308. if isIntType(ft) {
  309. if n, err := strconv.ParseInt(strings.TrimSpace(s), 10, 64); err == nil {
  310. return n
  311. }
  312. }
  313. switch ft {
  314. case types.FieldType_Float64, types.FieldType_Float32:
  315. if f, err := strconv.ParseFloat(strings.TrimSpace(s), 64); err == nil {
  316. return f
  317. }
  318. }
  319. return v
  320. }
  321. // =============================================================================
  322. // WHERE 按归属拆分: 下推条件 + 残余谓词
  323. // =============================================================================
  324. // joinWherePlan WHERE 拆分结果: perTable[i] 下推到第 i 张表扫描的 AND 条件,
  325. // residual 为不可下推的表达式 (跨表 OR/NOT、列与列比较), 组合行上过滤。
  326. type joinWherePlan struct {
  327. perTable []core.Condition
  328. residual expr
  329. }
  330. func planJoinWhere(ts []*joinTable, where expr, args []driver.NamedValue) (*joinWherePlan, error) {
  331. plan := &joinWherePlan{perTable: make([]core.Condition, len(ts))}
  332. if where == nil {
  333. return plan, nil
  334. }
  335. if err := splitJoinWhere(ts, where, args, plan); err != nil {
  336. return nil, err
  337. }
  338. return plan, nil
  339. }
  340. // splitJoinWhere 递归拆分 AND 结构; 叶子条件按列归属下推, 其余整体留作残余。
  341. func splitJoinWhere(ts []*joinTable, e expr, args []driver.NamedValue, plan *joinWherePlan) error {
  342. switch t := e.(type) {
  343. case *andExpr:
  344. if err := splitJoinWhere(ts, t.l, args, plan); err != nil {
  345. return err
  346. }
  347. return splitJoinWhere(ts, t.r, args, plan)
  348. case *orExpr, *notExpr:
  349. // 结构条件: 整棵子树只涉及一张表仍可下推该表, 跨表则留作残余谓词
  350. owners := map[*joinTable]bool{}
  351. if err := exprOwners(ts, e, owners); err != nil {
  352. return err
  353. }
  354. if len(owners) == 1 {
  355. for jt := range owners {
  356. return pushJoinWhere(jt, e, args, plan)
  357. }
  358. }
  359. plan.residual = andResidual(plan.residual, e)
  360. return nil
  361. case *colCmpExpr:
  362. // 列与列比较: 引擎 Condition 只支持列与值, 一律留作残余 (列归属校验在此做)
  363. if _, _, err := ownerOfCol(ts, t.left); err != nil {
  364. return err
  365. }
  366. if _, _, err := ownerOfCol(ts, t.right); err != nil {
  367. return err
  368. }
  369. plan.residual = andResidual(plan.residual, e)
  370. return nil
  371. case *cmpExpr:
  372. return pushJoinLeaf(ts, t.col, e, args, plan)
  373. case *inExpr:
  374. return pushJoinLeaf(ts, t.col, e, args, plan)
  375. case *isNullExpr:
  376. return pushJoinLeaf(ts, t.col, e, args, plan)
  377. case *likeExpr:
  378. if t.lhs == nil {
  379. return pushJoinLeaf(ts, t.col, e, args, plan)
  380. }
  381. // || 拼接左操作数: 所有列分量同属一张表才下推该表 (组合行求值需整行,
  382. // 跨表则留作残余谓词); 列归属校验顺便在此做。
  383. owners := map[*joinTable]bool{}
  384. if err := exprOwners(ts, e, owners); err != nil {
  385. return err
  386. }
  387. if len(owners) == 1 {
  388. for jt := range owners {
  389. return pushJoinWhere(jt, e, args, plan)
  390. }
  391. }
  392. plan.residual = andResidual(plan.residual, e)
  393. return nil
  394. }
  395. return fmt.Errorf("无法拆分的 WHERE 表达式")
  396. }
  397. // pushJoinLeaf 叶子条件按列归属下推到对应表。
  398. func pushJoinLeaf(ts []*joinTable, ref string, e expr, args []driver.NamedValue, plan *joinWherePlan) error {
  399. jt, _, err := ownerOfCol(ts, ref)
  400. if err != nil {
  401. return err
  402. }
  403. return pushJoinWhere(jt, e, args, plan)
  404. }
  405. // pushJoinWhere 把表达式翻译后 AND 进对应表的下推条件 (先剥限定词再走标准翻译)。
  406. func pushJoinWhere(jt *joinTable, e expr, args []driver.NamedValue, plan *joinWherePlan) error {
  407. dq, err := dequalifyExpr(e, jt.alias, jt.name)
  408. if err != nil {
  409. return err
  410. }
  411. cond, err := translateWhere(jt.tbl, dq, args)
  412. if err != nil {
  413. return err
  414. }
  415. if cond == nil {
  416. return nil
  417. }
  418. if plan.perTable[jt.idx] == nil {
  419. plan.perTable[jt.idx] = cond
  420. } else {
  421. plan.perTable[jt.idx] = core.And(plan.perTable[jt.idx], cond)
  422. }
  423. return nil
  424. }
  425. // andResidual 把不可下推的条件用 AND 串起来。
  426. func andResidual(a, b expr) expr {
  427. if a == nil {
  428. return b
  429. }
  430. return &andExpr{l: a, r: b}
  431. }
  432. // exprOwners 收集表达式引用的全部表 (按指针去重); 列归属解析错误直接透出。
  433. func exprOwners(ts []*joinTable, e expr, owners map[*joinTable]bool) error {
  434. mark := func(ref string) error {
  435. jt, _, err := ownerOfCol(ts, ref)
  436. if err != nil {
  437. return err
  438. }
  439. owners[jt] = true
  440. return nil
  441. }
  442. switch t := e.(type) {
  443. case *andExpr:
  444. if err := exprOwners(ts, t.l, owners); err != nil {
  445. return err
  446. }
  447. return exprOwners(ts, t.r, owners)
  448. case *orExpr:
  449. if err := exprOwners(ts, t.l, owners); err != nil {
  450. return err
  451. }
  452. return exprOwners(ts, t.r, owners)
  453. case *notExpr:
  454. return exprOwners(ts, t.e, owners)
  455. case *cmpExpr:
  456. return mark(t.col)
  457. case *colCmpExpr:
  458. if err := mark(t.left); err != nil {
  459. return err
  460. }
  461. return mark(t.right)
  462. case *inExpr:
  463. return mark(t.col)
  464. case *isNullExpr:
  465. return mark(t.col)
  466. case *likeExpr:
  467. if t.lhs != nil {
  468. for _, part := range t.lhs.parts {
  469. if !part.isCol {
  470. continue
  471. }
  472. if err := mark(part.col); err != nil {
  473. return err
  474. }
  475. }
  476. return nil
  477. }
  478. return mark(t.col)
  479. }
  480. return nil
  481. }
  482. // =============================================================================
  483. // 残余谓词求值: 组合行上的 Go 值比较
  484. // =============================================================================
  485. // evalJoinExpr 在组合行上求值残余谓词 (跨表 WHERE 条件)。
  486. func evalJoinExpr(e expr, ts []*joinTable, r joinRow, args []driver.NamedValue) (bool, error) {
  487. switch t := e.(type) {
  488. case *andExpr:
  489. l, err := evalJoinExpr(t.l, ts, r, args)
  490. if err != nil || !l {
  491. return l, err
  492. }
  493. return evalJoinExpr(t.r, ts, r, args)
  494. case *orExpr:
  495. l, err := evalJoinExpr(t.l, ts, r, args)
  496. if err != nil || l {
  497. return l, err
  498. }
  499. return evalJoinExpr(t.r, ts, r, args)
  500. case *notExpr:
  501. v, err := evalJoinExpr(t.e, ts, r, args)
  502. if err != nil {
  503. return false, err
  504. }
  505. return !v, nil
  506. case *cmpExpr:
  507. jt, col, err := ownerOfCol(ts, t.col)
  508. if err != nil {
  509. return false, err
  510. }
  511. fi := findField(jt.tbl, col)
  512. raw, err := resolveValue(fi, t.val, args)
  513. if err != nil {
  514. return false, err
  515. }
  516. rv, err := fieldValueToDriverTyped(fi.FieldType, raw)
  517. if err != nil {
  518. return false, err
  519. }
  520. return compareOp(r.get(jt, col), rv, t.op), nil
  521. case *colCmpExpr:
  522. ljt, lcol, err := ownerOfCol(ts, t.left)
  523. if err != nil {
  524. return false, err
  525. }
  526. rjt, rcol, err := ownerOfCol(ts, t.right)
  527. if err != nil {
  528. return false, err
  529. }
  530. return compareOp(r.get(ljt, lcol), r.get(rjt, rcol), t.op), nil
  531. case *inExpr:
  532. jt, col, err := ownerOfCol(ts, t.col)
  533. if err != nil {
  534. return false, err
  535. }
  536. fi := findField(jt.tbl, col)
  537. lv := r.get(jt, col)
  538. hit := false
  539. for _, tv := range t.vals {
  540. raw, err := resolveValue(fi, tv, args)
  541. if err != nil {
  542. return false, err
  543. }
  544. ev, err := fieldValueToDriverTyped(fi.FieldType, raw)
  545. if err != nil {
  546. return false, err
  547. }
  548. if c, ok := compareDriverValues(lv, ev); ok && c == 0 {
  549. hit = true
  550. break
  551. }
  552. }
  553. return hit != t.neg, nil
  554. case *isNullExpr:
  555. jt, col, err := ownerOfCol(ts, t.col)
  556. if err != nil {
  557. return false, err
  558. }
  559. return (r.get(jt, col) == nil) != t.neg, nil
  560. case *likeExpr:
  561. pat, err := resolveLikePattern(t.pattern, args)
  562. if err != nil {
  563. return false, err
  564. }
  565. if t.lhs != nil {
  566. // || 拼接左操作数: 逐分量取组合行文本拼接; 任一列分量为 NULL/非文本
  567. // 时拼接结果为 NULL (SQL 语义), LIKE 不匹配 (NOT LIKE 相应为真)。
  568. var sb strings.Builder
  569. nullish := false
  570. for _, part := range t.lhs.parts {
  571. if !part.isCol {
  572. sb.WriteString(part.lit)
  573. continue
  574. }
  575. jt, col, err := ownerOfCol(ts, part.col)
  576. if err != nil {
  577. return false, err
  578. }
  579. s, ok := toCmpString(r.get(jt, col))
  580. if !ok {
  581. nullish = true
  582. break
  583. }
  584. sb.WriteString(s)
  585. }
  586. if nullish {
  587. return t.neg, nil
  588. }
  589. return likeMatch(sb.String(), pat) != t.neg, nil
  590. }
  591. jt, col, err := ownerOfCol(ts, t.col)
  592. if err != nil {
  593. return false, err
  594. }
  595. s, ok := toCmpString(r.get(jt, col))
  596. if !ok {
  597. // NULL / 非文本: LIKE 不匹配 (NOT LIKE 相应为真)
  598. return t.neg, nil
  599. }
  600. return likeMatch(s, pat) != t.neg, nil
  601. }
  602. return false, fmt.Errorf("无法求值的 WHERE 表达式")
  603. }
  604. // compareOp 按比较符求值; 类型不可比视为不匹配。
  605. func compareOp(l, r driver.Value, op string) bool {
  606. c, ok := compareDriverValues(l, r)
  607. if !ok {
  608. return false
  609. }
  610. switch op {
  611. case "=":
  612. return c == 0
  613. case "!=":
  614. return c != 0
  615. case "<":
  616. return c < 0
  617. case "<=":
  618. return c <= 0
  619. case ">":
  620. return c > 0
  621. case ">=":
  622. return c >= 0
  623. }
  624. return false
  625. }
  626. // compareDriverValues 归一化比较两个 driver.Value, 返回 -1/0/1; 类型不可比返回
  627. // ok=false。NULL 视为最小 (两 NULL 相等); 数值按数值比, 文本按字典序比。
  628. func compareDriverValues(a, b driver.Value) (int, bool) {
  629. if a == nil || b == nil {
  630. switch {
  631. case a == nil && b == nil:
  632. return 0, true
  633. case a == nil:
  634. return -1, true
  635. default:
  636. return 1, true
  637. }
  638. }
  639. if av, ok := toCmpFloat(a); ok {
  640. bv, ok := toCmpFloat(b)
  641. if !ok {
  642. return 0, false
  643. }
  644. switch {
  645. case av < bv:
  646. return -1, true
  647. case av > bv:
  648. return 1, true
  649. default:
  650. return 0, true
  651. }
  652. }
  653. if av, ok := toCmpString(a); ok {
  654. bv, ok := toCmpString(b)
  655. if !ok {
  656. return 0, false
  657. }
  658. return strings.Compare(av, bv), true
  659. }
  660. if av, ok := a.(time.Time); ok {
  661. bv, ok := b.(time.Time)
  662. if !ok {
  663. return 0, false
  664. }
  665. switch {
  666. case av.Before(bv):
  667. return -1, true
  668. case av.After(bv):
  669. return 1, true
  670. default:
  671. return 0, true
  672. }
  673. }
  674. return 0, false
  675. }
  676. // toCmpFloat 数值型 driver.Value → float64 (bool 按 0/1)。
  677. func toCmpFloat(v driver.Value) (float64, bool) {
  678. switch t := v.(type) {
  679. case int64:
  680. return float64(t), true
  681. case float64:
  682. return t, true
  683. case bool:
  684. if t {
  685. return 1, true
  686. }
  687. return 0, true
  688. }
  689. return 0, false
  690. }
  691. // toCmpString 文本型 driver.Value → string。
  692. func toCmpString(v driver.Value) (string, bool) {
  693. switch t := v.(type) {
  694. case string:
  695. return t, true
  696. case []byte:
  697. return string(t), true
  698. }
  699. return "", false
  700. }
  701. // likeMatch SQL LIKE 匹配: % 任意长度任意字符, _ 单字符, 其余原样。
  702. func likeMatch(s, pat string) bool {
  703. sr, pr := []rune(s), []rune(pat)
  704. si, pi := 0, 0
  705. starP, starS := -1, 0
  706. for si < len(sr) {
  707. switch {
  708. case pi < len(pr) && (pr[pi] == '_' || pr[pi] == sr[si]):
  709. si++
  710. pi++
  711. case pi < len(pr) && pr[pi] == '%':
  712. starP, starS = pi, si
  713. pi++
  714. case starP != -1:
  715. pi = starP + 1
  716. starS++
  717. si = starS
  718. default:
  719. return false
  720. }
  721. }
  722. for pi < len(pr) && pr[pi] == '%' {
  723. pi++
  724. }
  725. return pi == len(pr)
  726. }
  727. // =============================================================================
  728. // ON 解析 / 投影 / 排序
  729. // =============================================================================
  730. // resolvedJoinOn 定好左右的 ON 条件: right 指向本 JOIN 的新表, left 指向其左侧
  731. // 已连接的表 (允许 "b.y = a.x" 写法, 解析期交换回来)。
  732. type resolvedJoinOn struct {
  733. leftIdx int
  734. leftCol string
  735. rightIdx int
  736. rightCol string
  737. }
  738. func resolveJoinOn(ts []*joinTable, newIdx int, jc *joinClause) (resolvedJoinOn, error) {
  739. li, lcol, err := qualIndexCol(ts, jc.onL)
  740. if err != nil {
  741. return resolvedJoinOn{}, err
  742. }
  743. ri, rcol, err := qualIndexCol(ts, jc.onR)
  744. if err != nil {
  745. return resolvedJoinOn{}, err
  746. }
  747. if li == newIdx && ri < newIdx {
  748. li, lcol, ri, rcol = ri, rcol, li, lcol
  749. }
  750. if ri != newIdx || li >= newIdx {
  751. return resolvedJoinOn{}, fmt.Errorf("JOIN ON 条件 %q = %q 必须连接新表 %q 与其左侧的表", jc.onL, jc.onR, ts[newIdx].alias)
  752. }
  753. return resolvedJoinOn{leftIdx: li, leftCol: lcol, rightIdx: ri, rightCol: rcol}, nil
  754. }
  755. // qualIndexCol 解析 ON 里的限定列名为 (表下标, 列名); 必须是限定名且列存在。
  756. func qualIndexCol(ts []*joinTable, ref string) (int, string, error) {
  757. qual, col := splitQualCol(ref)
  758. if qual == "" {
  759. return -1, "", fmt.Errorf("JOIN ON 列 %q 必须是限定名 (别名.列)", ref)
  760. }
  761. for i, jt := range ts {
  762. if strings.EqualFold(jt.alias, qual) || strings.EqualFold(jt.name, qual) {
  763. if findField(jt.tbl, col) == nil {
  764. return -1, "", fmt.Errorf("%w: %q", core.ErrFieldNotFound, ref)
  765. }
  766. return i, col, nil
  767. }
  768. }
  769. return -1, "", fmt.Errorf("未知的表限定 %q (列 %q)", qual, ref)
  770. }
  771. // joinProjCol 投影列: 归属表 + 小写列名 (行内取值) + 列元信息 + 展示名 (已去重)。
  772. type joinProjCol struct {
  773. jt *joinTable
  774. col string
  775. fi *types.FieldInfo
  776. name string
  777. }
  778. // buildJoinProjection 展开 SELECT 清单 (*/t.*/t.col/col 混用); 展示名为列名,
  779. // 重名列用 "别名_列名" 去重。
  780. func buildJoinProjection(ts []*joinTable, columns []string) ([]joinProjCol, error) {
  781. var out []joinProjCol
  782. seen := map[string]bool{}
  783. add := func(jt *joinTable, col string) error {
  784. fi := findField(jt.tbl, col)
  785. if fi == nil {
  786. return fmt.Errorf("%w: %q", core.ErrFieldNotFound, col)
  787. }
  788. name := string(fi.FieldName)
  789. if seen[strings.ToLower(name)] {
  790. name = jt.alias + "_" + name
  791. for seen[strings.ToLower(name)] {
  792. name += "_"
  793. }
  794. }
  795. seen[strings.ToLower(name)] = true
  796. out = append(out, joinProjCol{jt: jt, col: strings.ToLower(col), fi: fi, name: name})
  797. return nil
  798. }
  799. expand := func(jt *joinTable) error {
  800. for _, cn := range jt.cols {
  801. if err := add(jt, cn); err != nil {
  802. return err
  803. }
  804. }
  805. return nil
  806. }
  807. expandAll := func() error {
  808. for _, jt := range ts {
  809. if err := expand(jt); err != nil {
  810. return err
  811. }
  812. }
  813. return nil
  814. }
  815. if len(columns) == 0 {
  816. return out, expandAll()
  817. }
  818. for _, c := range columns {
  819. switch {
  820. case c == "*":
  821. if err := expandAll(); err != nil {
  822. return nil, err
  823. }
  824. case strings.HasSuffix(c, ".*"):
  825. jt := findQual(ts, c[:len(c)-2])
  826. if jt == nil {
  827. return nil, fmt.Errorf("未知的表限定 %q (列 %q)", c[:len(c)-2], c)
  828. }
  829. if err := expand(jt); err != nil {
  830. return nil, err
  831. }
  832. default:
  833. jt, col, err := ownerOfCol(ts, c) // 限定名/非限定名统一走归属解析
  834. if err != nil {
  835. return nil, err
  836. }
  837. if err := add(jt, col); err != nil {
  838. return nil, err
  839. }
  840. }
  841. }
  842. return out, nil
  843. }
  844. // joinOrderKey 排序键: 归属表 + 列 + 方向。
  845. type joinOrderKey struct {
  846. jt *joinTable
  847. col string
  848. desc bool
  849. }
  850. // resolveJoinOrderKeys 解析 ORDER BY 键 (限定名直查, 非限定名按唯一归属)。
  851. func resolveJoinOrderKeys(ts []*joinTable, specs []orderSpec) ([]joinOrderKey, error) {
  852. keys := make([]joinOrderKey, len(specs))
  853. for i, o := range specs {
  854. jt, col, err := ownerOfCol(ts, o.col)
  855. if err != nil {
  856. return nil, err
  857. }
  858. keys[i] = joinOrderKey{jt: jt, col: strings.ToLower(col), desc: o.desc}
  859. }
  860. return keys, nil
  861. }
  862. // =============================================================================
  863. // queryJoin: JOIN 查询主流程
  864. // =============================================================================
  865. func queryJoin(db *core.DB, sel *selectStmt, args []driver.NamedValue, release func()) (driver.Rows, error) {
  866. if release != nil {
  867. defer release() // 物化结果集, 算完即放锁
  868. }
  869. if sel.agg != nil {
  870. return nil, fmt.Errorf("JOIN 与聚合函数暂不支持同时使用")
  871. }
  872. // a. 解析所有表并归一化别名 (别名冲突提前报错)
  873. refs := make([]tableRef, 0, len(sel.joins)+1)
  874. refs = append(refs, sel.from)
  875. for _, j := range sel.joins {
  876. refs = append(refs, j.table)
  877. }
  878. ts := make([]*joinTable, len(refs))
  879. seenAlias := map[string]bool{}
  880. for i, ref := range refs {
  881. tbl, err := findTable(db, ref.name)
  882. if err != nil {
  883. return nil, err
  884. }
  885. ts[i] = buildJoinTable(i, ref, tbl)
  886. key := strings.ToLower(ts[i].alias)
  887. if seenAlias[key] {
  888. return nil, fmt.Errorf("JOIN 表别名 %q 重复", ts[i].alias)
  889. }
  890. seenAlias[key] = true
  891. }
  892. // b. WHERE 按归属拆分: 单表条件下推, 跨表条件留作残余谓词
  893. plan, err := planJoinWhere(ts, sel.where, args)
  894. if err != nil {
  895. return nil, err
  896. }
  897. // c. 左表扫描 (本表条件下推), 每行包一层别名空间
  898. leftRows, err := scanJoinTable(ts[0], plan.perTable[0])
  899. if err != nil {
  900. return nil, err
  901. }
  902. rows := make([]joinRow, 0, len(leftRows))
  903. for _, m := range leftRows {
  904. rows = append(rows, joinRow{strings.ToLower(ts[0].alias): m})
  905. }
  906. // d. 逐 JOIN: 左行 ON 列值 → 右表索引点查 (+右表条件下推), 组合笛卡尔行
  907. for i := range sel.joins {
  908. jc := &sel.joins[i]
  909. jt := ts[i+1]
  910. on, err := resolveJoinOn(ts, i+1, jc)
  911. if err != nil {
  912. return nil, err
  913. }
  914. onFi := findField(jt.tbl, on.rightCol)
  915. next := make([]joinRow, 0, len(rows))
  916. for _, lr := range rows {
  917. onVal := lr.get(ts[on.leftIdx], on.leftCol)
  918. var matched []map[string]driver.Value
  919. if onVal != nil {
  920. // NULL 与任何值都不相等, 右表点查直接跳过 (INNER 丢行 / LEFT 补 NULL)
  921. ev, err := driverToEngineValue(onFi, onVal)
  922. if err != nil {
  923. return nil, fmt.Errorf("JOIN ON 列 %q: %w", on.rightCol, err)
  924. }
  925. // 引擎条件按精确字节匹配列名, 改用引擎规范名
  926. // (ON 右列经 qualIndexCol 存在性校验, 这里取规范名构造点查条件)。
  927. cond := core.Eq(string(onFi.FieldName), ev, onFi.FieldType)
  928. if plan.perTable[i+1] != nil {
  929. cond = core.And(cond, plan.perTable[i+1])
  930. }
  931. matched, err = scanJoinTable(jt, cond)
  932. if err != nil {
  933. return nil, err
  934. }
  935. }
  936. if len(matched) == 0 {
  937. if jc.left {
  938. nr := cloneJoinRow(lr)
  939. nr[strings.ToLower(jt.alias)] = nullJoinRow(jt)
  940. next = append(next, nr)
  941. }
  942. continue // INNER JOIN: 无匹配丢行
  943. }
  944. for _, rm := range matched {
  945. nr := cloneJoinRow(lr)
  946. nr[strings.ToLower(jt.alias)] = rm
  947. next = append(next, nr)
  948. }
  949. }
  950. rows = next
  951. }
  952. // e. 残余谓词: 组合行上过滤 (跨表比较)
  953. if plan.residual != nil {
  954. kept := make([]joinRow, 0, len(rows))
  955. for _, r := range rows {
  956. ok, err := evalJoinExpr(plan.residual, ts, r, args)
  957. if err != nil {
  958. return nil, err
  959. }
  960. if ok {
  961. kept = append(kept, r)
  962. }
  963. }
  964. rows = kept
  965. }
  966. // f. 投影列清单 (*/t.*/t.col/col 混用, 重名列 别名_列名 去重)
  967. proj, err := buildJoinProjection(ts, sel.columns)
  968. if err != nil {
  969. return nil, err
  970. }
  971. // g. ORDER BY: 投影前对组合行内存稳定排序 (NULL 视为最小), 再 LIMIT/OFFSET
  972. if len(sel.orderBy) > 0 {
  973. keys, err := resolveJoinOrderKeys(ts, sel.orderBy)
  974. if err != nil {
  975. return nil, err
  976. }
  977. sort.SliceStable(rows, func(x, y int) bool {
  978. for _, k := range keys {
  979. c, ok := compareDriverValues(rows[x].get(k.jt, k.col), rows[y].get(k.jt, k.col))
  980. if !ok || c == 0 {
  981. continue
  982. }
  983. if k.desc {
  984. return c > 0
  985. }
  986. return c < 0
  987. }
  988. return false
  989. })
  990. }
  991. if sel.offset != nil {
  992. o, err := resolveLimitValue("OFFSET", sel.offset, args)
  993. if err != nil {
  994. return nil, err
  995. }
  996. if int(o) >= len(rows) {
  997. rows = nil
  998. } else {
  999. rows = rows[int(o):]
  1000. }
  1001. }
  1002. if sel.limit != nil {
  1003. l, err := resolveLimitValue("LIMIT", sel.limit, args)
  1004. if err != nil {
  1005. return nil, err
  1006. }
  1007. if int(l) < len(rows) {
  1008. rows = rows[:int(l)]
  1009. }
  1010. }
  1011. // 物化投影行 (DISTINCT 按投影值去重)
  1012. colNames := make([]string, len(proj))
  1013. metas := make([]colMeta, len(proj))
  1014. for i, pc := range proj {
  1015. colNames[i] = pc.name
  1016. metas[i] = colMetaFor(pc.fi)
  1017. }
  1018. data := make([][]driver.Value, 0, len(rows))
  1019. var seen map[string]bool
  1020. if sel.distinct {
  1021. seen = map[string]bool{}
  1022. }
  1023. for _, r := range rows {
  1024. vals := make([]driver.Value, len(proj))
  1025. for i, pc := range proj {
  1026. vals[i] = r.get(pc.jt, pc.col) // LEFT JOIN 未匹配侧 → NULL
  1027. }
  1028. if seen != nil {
  1029. key := distinctKey(vals)
  1030. if seen[key] {
  1031. continue
  1032. }
  1033. seen[key] = true
  1034. }
  1035. data = append(data, vals)
  1036. }
  1037. return materialRows(colNames, metas, data), nil
  1038. }