From 8f054ae9f523e1eb9aa9d6e1d0b3d4aa0c77d19d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sami=20Koskim=C3=A4ki?= Date: Mon, 8 Aug 2022 19:27:38 +0300 Subject: [PATCH] fixes #132 --- package.json | 2 +- .../operation-node-transformer.ts | 2 +- src/parser/group-by-parser.ts | 12 +++++- .../with-schema/with-schema-transformer.ts | 6 +-- src/query-builder/select-query-builder.ts | 17 +++++---- test/node/src/group-by.test.ts | 37 +++++++++++++++++++ 6 files changed, 60 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 5198731df..9d9c6269a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "kysely", - "version": "0.21.0", + "version": "0.21.1", "description": "Type safe SQL query builder", "repository": { "type": "git", diff --git a/src/operation-node/operation-node-transformer.ts b/src/operation-node/operation-node-transformer.ts index 57a5a6efb..0eacb7e19 100644 --- a/src/operation-node/operation-node-transformer.ts +++ b/src/operation-node/operation-node-transformer.ts @@ -93,7 +93,7 @@ import { SchemableIdentifierNode } from './schemable-identifier-node.js' * * return { * ...node, - * identifier: snakeCase(node.identifier), + * name: snakeCase(node.name), * } * } * } diff --git a/src/parser/group-by-parser.ts b/src/parser/group-by-parser.ts index 34af0cdd8..b32e683f9 100644 --- a/src/parser/group-by-parser.ts +++ b/src/parser/group-by-parser.ts @@ -1,11 +1,19 @@ import { GroupByItemNode } from '../operation-node/group-by-item-node.js' import { parseReferenceExpressionOrList, - ReferenceExpressionOrList, + ReferenceExpression, } from './reference-parser.js' +export type GroupByExpression = + | ReferenceExpression + | (keyof O & string) + +export type GroupByExpressionOrList = + | ReadonlyArray> + | GroupByExpression + export function parseGroupBy( - orderBy: ReferenceExpressionOrList + orderBy: GroupByExpressionOrList ): GroupByItemNode[] { return parseReferenceExpressionOrList(orderBy).map(GroupByItemNode.create) } diff --git a/src/plugin/with-schema/with-schema-transformer.ts b/src/plugin/with-schema/with-schema-transformer.ts index b129be486..2b7fcd631 100644 --- a/src/plugin/with-schema/with-schema-transformer.ts +++ b/src/plugin/with-schema/with-schema-transformer.ts @@ -1,4 +1,5 @@ import { AliasNode } from '../../operation-node/alias-node.js' +import { IdentifierNode } from '../../operation-node/identifier-node.js' import { OperationNodeTransformer } from '../../operation-node/operation-node-transformer.js' import { TableExpressionNode } from '../../operation-node/operation-node-utils.js' import { OperationNode } from '../../operation-node/operation-node.js' @@ -72,10 +73,7 @@ export class WithSchemaTransformer extends OperationNodeTransformer { return { ...transformed, - schema: freeze({ - kind: 'IdentifierNode', - name: this.#schema, - }), + schema: IdentifierNode.create(this.#schema), } } diff --git a/src/query-builder/select-query-builder.ts b/src/query-builder/select-query-builder.ts index f16c4f84d..a23be2dcb 100644 --- a/src/query-builder/select-query-builder.ts +++ b/src/query-builder/select-query-builder.ts @@ -28,10 +28,7 @@ import { WhereGrouper, HavingGrouper, } from '../parser/filter-parser.js' -import { - ReferenceExpression, - ReferenceExpressionOrList, -} from '../parser/reference-parser.js' +import { ReferenceExpression } from '../parser/reference-parser.js' import { SelectQueryNode } from '../operation-node/select-query-node.js' import { QueryNode } from '../operation-node/query-node.js' import { @@ -52,7 +49,11 @@ import { Compilable } from '../util/compilable.js' import { QueryExecutor } from '../query-executor/query-executor.js' import { QueryId } from '../util/query-id.js' import { freeze } from '../util/object-utils.js' -import { parseGroupBy } from '../parser/group-by-parser.js' +import { + GroupByExpression, + GroupByExpressionOrList, + parseGroupBy, +} from '../parser/group-by-parser.js' import { parseUnion, UnionExpression } from '../parser/union-parser.js' import { KyselyPlugin } from '../plugin/kysely-plugin.js' import { WhereInterface } from './where-interface.js' @@ -1244,12 +1245,12 @@ export class SelectQueryBuilder * ``` */ groupBy( - groupBy: ReadonlyArray> + groupBy: ReadonlyArray> ): SelectQueryBuilder - groupBy(groupBy: ReferenceExpression): SelectQueryBuilder + groupBy(groupBy: GroupByExpression): SelectQueryBuilder - groupBy(groupBy: ReferenceExpressionOrList): any { + groupBy(groupBy: GroupByExpressionOrList): any { return new SelectQueryBuilder({ ...this.#props, queryNode: SelectQueryNode.cloneWithGroupByItems( diff --git a/test/node/src/group-by.test.ts b/test/node/src/group-by.test.ts index e25eb6ffa..f3f68736b 100644 --- a/test/node/src/group-by.test.ts +++ b/test/node/src/group-by.test.ts @@ -68,6 +68,43 @@ for (const dialect of BUILT_IN_DIALECTS) { ]) }) + it('group by selection', async () => { + const query = ctx.db + .selectFrom('person') + .select(['gender as g', sql`max(first_name)`.as('max_first_name')]) + .groupBy('g') + .orderBy('g') + + testSql(query, dialect, { + postgres: { + sql: 'select "gender" as "g", max(first_name) as "max_first_name" from "person" group by "g" order by "g"', + parameters: [], + }, + mysql: { + sql: 'select `gender` as `g`, max(first_name) as `max_first_name` from `person` group by `g` order by `g`', + parameters: [], + }, + sqlite: { + sql: 'select "gender" as "g", max(first_name) as "max_first_name" from "person" group by "g" order by "g"', + parameters: [], + }, + }) + + const persons = await query.execute() + + expect(persons).to.have.length(2) + expect(persons).to.containSubset([ + { + max_first_name: 'Jennifer', + g: 'female', + }, + { + max_first_name: 'Sylvester', + g: 'male', + }, + ]) + }) + it('group by two columns', async () => { const query = ctx.db .selectFrom('person')