1. 修复FloatColumn对numeric的问题
2. 数据库抛出错误时,增加sql属性 3. 查询器排序问题的修复
This commit is contained in:
@ -4,6 +4,10 @@ import { DeleteBuilder, IDeleteBuilder, IInsertBuilder, InsertBuilder, ISelectBu
|
||||
import { Class } from "./types";
|
||||
import { formatSQL } from "./util";
|
||||
|
||||
interface IQueryResult<R extends QueryResultRow = any> extends QueryResult<R> {
|
||||
sql: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据库基本操作
|
||||
*/
|
||||
@ -13,7 +17,7 @@ export interface IDatabase {
|
||||
* @param sql sql语句
|
||||
* @param args sql参数
|
||||
*/
|
||||
query<R extends QueryResultRow = any>(sql: string, args?: any[] | Record<string, any>): Promise<QueryResult<R>>
|
||||
query<R extends QueryResultRow = any>(sql: string, args?: any[] | Record<string, any>): Promise<IQueryResult<R>>
|
||||
|
||||
/**
|
||||
* 查询实体
|
||||
@ -83,7 +87,16 @@ class PostgresClient implements IPostgresClient {
|
||||
this.#client = client;
|
||||
}
|
||||
|
||||
public query<R extends QueryResultRow = any>(sql: string, args?: any[] | Record<string, any>): Promise<QueryResult<R>> { return this.#client.query(args ? formatSQL(sql, args) : sql); }
|
||||
public async query<R extends QueryResultRow = any>(sql: string, args?: any[] | Record<string, any>): Promise<IQueryResult<R>> {
|
||||
sql = args ? formatSQL(sql, args) : sql;
|
||||
try {
|
||||
const res = await this.#client.query(sql);
|
||||
return { ...res, sql };
|
||||
} catch (err: any) {
|
||||
err.sql = sql;
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async trans() {
|
||||
@ -155,7 +168,16 @@ export const database: IPostgresDatabase = {
|
||||
if (pool) pool.end().catch((err) => console.error(err));
|
||||
},
|
||||
|
||||
query(sql, args) { return getPool().query(args ? formatSQL(sql, args) : sql); },
|
||||
async query(sql, args) {
|
||||
sql = args ? formatSQL(sql, args) : sql;
|
||||
try {
|
||||
const res = await getPool().query(sql);
|
||||
return { ...res, sql };
|
||||
} catch (err: any) {
|
||||
err.sql = sql;
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
select(Entity, alias) { return new SelectBuilder(this.query.bind(this), Entity, alias); },
|
||||
insert(Entity) { return new InsertBuilder(this.query.bind(this), Entity); },
|
||||
update(Entity) { return new UpdateBuilder(this.query.bind(this), Entity); },
|
||||
|
@ -179,7 +179,7 @@ export function FloatColumn(name?: any, option?: any) {
|
||||
name = undefined;
|
||||
}
|
||||
|
||||
return Field(name, v => escapeValue(v), v => v, false, option?.virtual ?? false);
|
||||
return Field(name, v => escapeValue(v), v => parseFloat(v), false, option?.virtual ?? false);
|
||||
}
|
||||
|
||||
|
||||
|
35
src/query.ts
35
src/query.ts
@ -40,7 +40,7 @@ interface ISearchOptionMap {
|
||||
tsquery: string | string[] | {
|
||||
/** 关键字 */
|
||||
keywords: string | string[]
|
||||
/** 是否进行绝对匹配,如果为true,则只匹配关键字,否则匹配关键字前缀,默认true */
|
||||
/** 是否进行绝对匹配,如果为true,则只匹配关键字,否则匹配关键字前缀,默认false */
|
||||
absolute?: boolean
|
||||
/** 匹配方式,默认or */
|
||||
method?: "or" | "and"
|
||||
@ -140,7 +140,14 @@ interface IGroupFn<E extends BasicEntity> {
|
||||
group(...name: Array<(keyof E) | (() => string)>): this
|
||||
}
|
||||
|
||||
export interface ISelectBuilder<E extends BasicEntity> extends IWhereFn<E>, IFilterFn<E>, IJoinFn<E> {
|
||||
interface IOrderByOption {
|
||||
/** 对nul字段的处理方式 */
|
||||
nulls?: "first" | "last"
|
||||
/** 是否将排序字段添加到内部的分组中 */
|
||||
group?: boolean
|
||||
}
|
||||
|
||||
export interface ISelectBuilder<E extends BasicEntity> extends IWhereFn<E>, IFilterFn<E>, IJoinFn<E>, IGroupFn<E> {
|
||||
/**
|
||||
* 设置查询偏移
|
||||
* @param offset 查询偏移
|
||||
@ -158,13 +165,13 @@ export interface ISelectBuilder<E extends BasicEntity> extends IWhereFn<E>, IFil
|
||||
* @param name 排序名称
|
||||
* @param sort 排序方式
|
||||
*/
|
||||
order(name: string, sort: "asc" | "desc"): this
|
||||
order(name: string, sort: "asc" | "desc", option?: IOrderByOption): this
|
||||
/**
|
||||
* 排序
|
||||
* @param name 排序名称
|
||||
* @param sort 排序方式
|
||||
*/
|
||||
order(name: keyof E, sort: "asc" | "desc"): this
|
||||
order(name: keyof E, sort: "asc" | "desc", option?: IOrderByOption): this
|
||||
|
||||
// __sql__(count: boolean): string
|
||||
|
||||
@ -472,7 +479,7 @@ function WithWhere<E extends BasicEntity, B extends Constructor<E>>(Base: B) {
|
||||
const opt = option as ISearchOptionMap["tsquery"];
|
||||
let keywords: string[];
|
||||
let method: "or" | "and" = "or";
|
||||
let absolute = true;
|
||||
let absolute = false;
|
||||
//处理选项
|
||||
if (typeof opt === "string") keywords = opt.split(/\s+/).map(s => s.trim()).filter(s => s.length);
|
||||
else if (opt instanceof Array) keywords = opt;
|
||||
@ -617,6 +624,7 @@ class Joinner<E extends BasicEntity> extends WithGroup(WithJoin(WithWhere(WithFi
|
||||
}
|
||||
|
||||
public build<BE extends BasicEntity, D>(base: BE, data: D[]) {
|
||||
if (!this.columns.length) return;
|
||||
const parsed = this.__build__(data, this.joinners);
|
||||
if (this.#joinConfig.many) base[this.#baseName as keyof BE] = parsed as any;
|
||||
else base[this.#baseName as keyof BE] = (parsed[0] ?? null) as any;
|
||||
@ -626,7 +634,7 @@ class Joinner<E extends BasicEntity> extends WithGroup(WithJoin(WithWhere(WithFi
|
||||
export class SelectBuilder<E extends BasicEntity> extends WithGroup(WithJoin(WithWhere(WithFilter(SQLBuilder))))<E> implements ISelectBuilder<E> {
|
||||
#offset?: number
|
||||
#limit?: number
|
||||
#orders?: Array<[name: string, order: "asc" | "desc"]>
|
||||
#orders?: Array<[name: string, order: "asc" | "desc", nulls: "first" | "last" | null, group: boolean]>
|
||||
#query: IQueryFunc<any>
|
||||
#fullJoinners?: Joinner<any>[]
|
||||
|
||||
@ -645,11 +653,11 @@ export class SelectBuilder<E extends BasicEntity> extends WithGroup(WithJoin(Wit
|
||||
return this;
|
||||
}
|
||||
|
||||
public order(name: any, sort: "asc" | "desc") {
|
||||
public order(name: any, sort: "asc" | "desc", option?: IOrderByOption) {
|
||||
this.#orders ??= [];
|
||||
const col = this.config.fields.find(f => f.prop === name);
|
||||
if (col) this.#orders.push([escapeID(this.alias, col.name), sort]);
|
||||
else this.#orders.push([name, sort]);
|
||||
if (col) this.#orders.push([escapeID(this.alias, col.name), sort, option?.nulls ?? null, option?.group ?? false]);
|
||||
else this.#orders.push([name, sort, option?.nulls ?? null, option?.group ?? false]);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -670,6 +678,7 @@ export class SelectBuilder<E extends BasicEntity> extends WithGroup(WithJoin(Wit
|
||||
}
|
||||
|
||||
async findAndCount() {
|
||||
// console.log(this.__sql__(true))
|
||||
const res = await this.#query(this.__sql__(true));
|
||||
const count = res.rows[0]?.__data_count__ ?? 0;
|
||||
return [this.build(res.rows) as E[], parseInt(count)] as [E[], number];
|
||||
@ -710,14 +719,16 @@ export class SelectBuilder<E extends BasicEntity> extends WithGroup(WithJoin(Wit
|
||||
}
|
||||
|
||||
public __inner_sql__(count: boolean, join = "\n") {
|
||||
const groups = [...this.primaryNames.map(p => escapeID(this.alias, p))];
|
||||
this.#orders?.filter(([name, ord, nulls, group]) => group).forEach(([name, ord, nulls, group]) => groups.push(name));
|
||||
//内部的join
|
||||
const innerSQLItems = [
|
||||
`select ${escapeID(this.alias)}.*${count ? `, count(*) over () as __data_count__` : ''}`, //字段列表
|
||||
`from ${this.tableSQL} ${escapeID(this.alias)}`, //表名
|
||||
...this.__joins__, //join
|
||||
...this.__wheres__.length ? [`where ${this.__wheres__}`] : [], //where条件
|
||||
`group by ${this.primaryNames.map(p => escapeID(this.alias, p)).join(",")}`, //内部查询分组
|
||||
...(!count && this.#orders?.length) ? [`order by ${this.#orders.map(([name, order]) => `${name} ${order}`).join(",")}`] : [], //排序
|
||||
`group by ${groups.join(",")}`, //内部查询分组
|
||||
...(count && this.#orders?.length) ? [`order by ${this.#orders.map(([name, ord, nulls]) => `${name} ${ord}${nulls ? ` nulls ${nulls}` : ""}`).join(",")}`] : [], //排序
|
||||
...(typeof this.#offset == "number") ? [`offset ${this.#offset}`] : [], //offset
|
||||
...(typeof this.#limit == "number") ? [`limit ${this.#limit}`] : [], //limit
|
||||
];
|
||||
@ -732,7 +743,7 @@ export class SelectBuilder<E extends BasicEntity> extends WithGroup(WithJoin(Wit
|
||||
...this.__joins__, //join
|
||||
...this.__wheres__.length ? [`where ${this.__wheres__}`] : [], //where条件
|
||||
...this.ctx.groups.length ? [`group by ${this.ctx.groups.join(",")}`] : [], //分组
|
||||
...this.#orders ? [`order by ${this.#orders.map(([name, ord]) => `${name} ${ord}`).join(", ")}`] : [], //排序
|
||||
...this.#orders ? [`order by ${this.#orders.map(([name, ord, nulls]) => `${name} ${ord}${nulls ? ` nulls ${nulls}` : ""}`).join(", ")}`] : [], //排序
|
||||
];
|
||||
|
||||
return outterSQLItems.join("\n");
|
||||
|
Reference in New Issue
Block a user