/* * Copyright (c) 2025 SimcuTeam. All rights reserved. * 查询构建器:条件/排序/分页 → SQL,委托执行回调物化结果。 * * 解耦设计:QueryBuilder 不直接依赖 DbContext/驱动。 * 构造时传入 执行回调 (sql, params) -> ArrayList,由 DbContext 提供。 */ package simcu::orm.query import std.collection.* import simcu::orm.model.* import simcu::orm.sql.* /** * 分页结果。 */ public class PagedResult { /// 当前页数据 public var items: ArrayList = ArrayList() /// 满足条件的总条数 public var total: Int64 = 0 /// 页码(从 1 开始) public var page: Int64 = 1 /// 每页条数 public var pageSize: Int64 = 20 public init() {} public init(items: ArrayList, total: Int64, page: Int64, pageSize: Int64) { this.items = items this.total = total this.page = page this.pageSize = pageSize } /// 总页数 public func totalPages(): Int64 { if (pageSize <= 0) { return 0 } (total + pageSize - 1) / pageSize } } /** * 查询构建器(对齐 EF Core IQueryable 的常用子集)。 */ public class QueryBuilder { private let _model: EntityModel private let _dialect: ISqlDialect private let _executor: (String, ArrayList) -> ArrayList private let _counter: (String, ArrayList) -> Int64 private let _whereParts = ArrayList() private let _params = ArrayList() private let _orderByParts = ArrayList() private var _skip: Int64 = 0 private var _take: Int64 = 0 public init(model: EntityModel, dialect: ISqlDialect, executor: (String, ArrayList) -> ArrayList, counter: (String, ArrayList) -> Int64) { this._model = model this._dialect = dialect this._executor = executor this._counter = counter } /// filter("age > ?", [18]):原始片段,参数按 ? 顺序;片段中请直接写数据库列名 public func filter(condition: String, params: ArrayList): QueryBuilder { _whereParts.add("(${condition})") for (p in params) { _params.add(p) } this } /// filter("age", ">", 18):属性名/列名自动映射为列名 public func filter(property: String, op: String, value: Any): QueryBuilder { let col = _model.mapColumn(property) _whereParts.add("(${_dialect.quoteName(col)} ${op} ?)") _params.add(value) this } public func orderBy(property: String): QueryBuilder { _orderByParts.add("${_dialect.quoteName(_model.mapColumn(property))} ASC") this } public func orderByDesc(property: String): QueryBuilder { _orderByParts.add("${_dialect.quoteName(_model.mapColumn(property))} DESC") this } public func skip(n: Int64): QueryBuilder { _skip = n this } public func take(n: Int64): QueryBuilder { _take = n this } /// 执行查询,返回实体列表 public func toList(): ArrayList { _executor(buildSelectSql(), copyParams()) } /// 返回第一条(无结果返回 None) public func first(): ?T { let saved = _take _take = 1 let list = toList() _take = saved if (list.size > 0) { return Some(list[0]) } None } /// 满足条件的总数 public func count(): Int64 { let sql = _dialect.buildCount(_model.tableName, whereSql()) _counter(sql, copyParams()) } /// 分页(page 从 1 开始) public func page(page: Int64, pageSize: Int64): PagedResult { let total = count() let savedSkip = _skip let savedTake = _take _skip = (page - 1) * pageSize _take = pageSize let items = toList() _skip = savedSkip _take = savedTake PagedResult(items, total, page, pageSize) } private func buildSelectSql(): String { _dialect.buildSelect(_model.tableName, selectColumns(), whereSql(), orderBySql(), _skip, _take) } /// 物化列(与属性顺序一致,结果集按此索引读取) private func selectColumns(): ArrayList { let cols = ArrayList() for (p in _model.properties) { cols.add(p.columnName) } cols } private func whereSql(): String { var sb = StringBuilder() var first = true for (w in _whereParts) { if (!first) { sb.append(" AND ") } sb.append(w) first = false } sb.toString() } private func orderBySql(): String { var sb = StringBuilder() var first = true for (o in _orderByParts) { if (!first) { sb.append(", ") } sb.append(o) first = false } sb.toString() } private func copyParams(): ArrayList { let copy = ArrayList() for (p in _params) { copy.add(p) } copy } }