join.go 26 KB

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