diff --git a/src/query-builder/function-module.ts b/src/query-builder/function-module.ts index cfb7cda3c..174109119 100644 --- a/src/query-builder/function-module.ts +++ b/src/query-builder/function-module.ts @@ -24,6 +24,7 @@ import { SelectQueryBuilderExpression } from '../query-builder/select-query-buil import { isString } from '../util/object-utils.js' import { parseTable } from '../parser/table-parser.js' import { Selectable } from '../util/column-type.js' +import { RawBuilder } from '../raw-builder/raw-builder.js' /** * Helpers for type safe SQL function calls. @@ -657,6 +658,8 @@ export interface FunctionModule { * * This function is only available on PostgreSQL. * + * You can use it either on a table: + * * ```ts * await db.selectFrom('person') * .innerJoin('pet', 'pet.owner_id', 'person.id') @@ -673,6 +676,44 @@ export interface FunctionModule { * inner join "pet" on "pet"."owner_id" = "person"."id" * group by "person"."first_name" * ``` + * + * ... or on a column: + * + * ```ts + * await db.selectFrom('person') + * .innerJoin('pet', 'pet.owner_id', 'person.id') + * .select((eb) => ['first_name', eb.fn.jsonAgg('pet.names').as('pet_names')]) + * .groupBy('person.first_name') + * .execute() + * + * await db.selectFrom('person') + * .select((eb) => [ + * 'first_name', + * eb + * .selectFrom('pet') + * .select((eb) => [eb.fn.jsonAgg("pet.owner_id")]) + * .whereRef('pet.owner_id', '=', 'person.id') + * .as('petnames'), + * ]) + * .execute() + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```sql + * select "first_name", json_agg("pet"."names") AS "pet_names" + * from "person" + * inner join "pet" ON "pet"."owner_id" = "person"."id" + * group by "person"."first_name" + * + * select "first_name", + * ( + * select json_agg("pet"."owner_id") + * from "pet" + * where "pet"."owner_id" = "person"."id" + * ) as "petnames" + * from "person" + * ``` */ jsonAgg>( table: T, @@ -685,6 +726,9 @@ export interface FunctionModule { ? O[] : never > + jsonAgg>( + column: RE, + ): RawBuilder[] | null> /** * Creates a to_json function call. diff --git a/test/typings/test-d/postgres-json.test-d.ts b/test/typings/test-d/postgres-json.test-d.ts index 898ffe5c9..79e2908b1 100644 --- a/test/typings/test-d/postgres-json.test-d.ts +++ b/test/typings/test-d/postgres-json.test-d.ts @@ -169,6 +169,39 @@ async function testPostgresJsonAgg(db: Kysely) { status: string | null }[] }>(r4) + + const r5 = await db + .selectFrom('person') + .innerJoin('pet', 'pet.owner_id', 'person.id') + .select((eb) => ['first_name', eb.fn.jsonAgg('owner_id').as('pet_names')]) + .groupBy('person.first_name') + .execute() + + expectType< + { + first_name: string + pet_names: number[] | null + }[] + >(r5) + + const r6 = await db + .selectFrom('person') + .select((eb) => [ + 'first_name', + eb + .selectFrom('pet') + .select((eb) => [eb.fn.jsonAgg('pet.owner_id').as('pet_names')]) + .whereRef('pet.owner_id', '=', 'person.id') + .as('pet_names'), + ]) + .execute() + + expectType< + { + first_name: string + pet_names: number[] | null + }[] + >(r6) } async function testPostgresToJson(db: Kysely) {