From 45919defc68575c006bc138fde99c10116451b0b Mon Sep 17 00:00:00 2001 From: yizhi <946185759@qq.com> Date: Fri, 29 Nov 2024 16:49:52 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=9F=A5=E8=AF=A2=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- src/query.ts | 64 ++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 51 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index f9edd5b..1db7dba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@yizhi/postgres", - "version": "1.0.11", + "version": "1.0.12", "main": "dist/index.js", "types": "typing/index.d.ts", "scripts": {}, diff --git a/src/query.ts b/src/query.ts index 8d8afb0..1db901c 100644 --- a/src/query.ts +++ b/src/query.ts @@ -240,6 +240,7 @@ class SQLBuilderContext { #nameDict: Record = {}; #groups: string[] = []; #searchs: string[] = []; + #hasManyJoin = false; public genName(name: string) { this.#nameDict[name] ??= 0; @@ -254,6 +255,10 @@ class SQLBuilderContext { public addSearch(search: string) { this.#searchs.push(search); } public get searchs() { return this.#searchs; } + + public set hasManyJoin(val: boolean) { this.#hasManyJoin = val; } + + public get hasManyJoin() { return this.#hasManyJoin; } } class SQLBuilder { @@ -537,6 +542,7 @@ function WithJoin>(Base: B) { callback = alias; alias = undefined; } + if (joinConfig.many) this.ctx.hasManyJoin = true; const joinner = new Joinner(this, name, this.alias, JoinEntity, joinConfig, alias ?? name); this.#joinners.push(joinner); if (callback) callback(joinner); @@ -672,13 +678,25 @@ export class SelectBuilder extends WithGroup(WithJoin(Wit async findOne() { return this.find().then(res => res[0] ?? null); } async count() { - const sql = `select count(*) as __data_count__ from (\n\t${this.__inner_sql__(false, "\n\t")}\n)`; + let sql: string; + if (this.ctx.hasManyJoin) { + sql = `select count(*) as __data_count__ from (\n\t${this.__inner_sql__(false, "\n\t")}\n)`; + } + else { + sql = [ + `select count(*) as __data_count__`, + `from ${this.tableSQL} ${escapeID(this.alias)}`, + ...this.__joins__, //join + ...this.__wheres__.length ? [`where ${this.__wheres__}`] : [], //where条件 + ...this.ctx.groups.length ? [`group by ${this.ctx.groups.join(",")}`] : [], //分组 + ].join("\n"); + } + // console.log(sql); const res = await this.#query(sql); return parseInt(res.rows[0].__data_count__) as number } 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]; @@ -736,23 +754,41 @@ export class SelectBuilder extends WithGroup(WithJoin(Wit } public __sql__(count: boolean) { - //外部的SQL - const outterSQLItems = [ - `select ${this.__select_columns__}${count ? `, ${escapeID(this.alias)}.__data_count__` : ''}`, //字段列表 - `from (\n\t${this.__inner_sql__(count, "\n\t")}\n) ${escapeID(this.alias)}`, //子查询 - ...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, nulls]) => `${name} ${ord}${nulls ? ` nulls ${nulls}` : ""}`).join(", ")}`] : [], //排序 - ]; - - return outterSQLItems.join("\n"); + if (this.ctx.hasManyJoin) { + 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)); + const buffer = [ + `select ${this.__select_columns__}${count ? `, ${escapeID(this.alias)}.__data_count__` : ''}`, //字段列表 + `from (`, + `\t${this.__inner_sql__(count, "\n\t")}`, + `) ${escapeID(this.alias)}`, + ...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, nulls]) => `${name} ${ord}${nulls ? ` nulls ${nulls}` : ""}`).join(", ")}`] : [], //排序 + ]; + // console.log(buffer.join("\n")); + return buffer.join("\n"); + } + else { + const buffer = [ + `select ${this.__select_columns__}${count ? `,count(*) over () as __data_count__` : ''}`, //字段列表 + `from ${this.tableSQL} ${escapeID(this.alias)}`, //表名 + ...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, nulls]) => `${name} ${ord}${nulls ? ` nulls ${nulls}` : ""}`).join(", ")}`] : [], //排序 + ...(typeof this.#offset == "number") ? [`offset ${this.#offset}`] : [], //offset + ...(typeof this.#limit == "number") ? [`limit ${this.#limit}`] : [], //limit + ]; + // console.log(buffer.join("\n")); + return buffer.join("\n"); + } } public build(data: D[]) { return this.__build__(data, this.joinners); } - } export class InsertBuilder extends WithReturning(SQLBuilder) implements IInsertBuilder {