Skip to content

Commit

Permalink
feat: limit, offset and ordering
Browse files Browse the repository at this point in the history
  • Loading branch information
Looskie committed Dec 7, 2023
1 parent a699c65 commit 1e351e4
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/classes/clickhouse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export class ClickHouse<T extends Record<string, Table>> {
});

const primaryKeyColumn = Object.entries(table.columns).find(
([_, column]) => column.primaryKey,
([_, column]) => column.isPrimaryKey,
)?.[0];

await this.client.query({
Expand Down
26 changes: 21 additions & 5 deletions src/classes/query.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { QueryParams } from "@clickhouse/client";
import type { Client } from ".";
import { AllExpressions } from "../expressions";
import { AllExpressions, OrderByExpression } from "../expressions";
import * as conditions from "../expressions/conditions";
import { ColumnBuilder } from "../schema/builder";
import { ClickhouseJSONResponse, ExtractPropsFromTable } from "../types/clickhouse";
Expand All @@ -11,7 +11,9 @@ import { SQLParser, sql } from "../utils/sql";

type GenericParams<T extends Table> = {
where: (columns: T["columns"], conditions: AllExpressions) => SQLParser;
orderBy?: (columns: T["columns"], conditions: AllExpressions) => string;
orderBy?: (columns: T["columns"], conditions: OrderByExpression) => string;
limit?: number;
offset?: number;
};

export class Query<T extends Table> {
Expand All @@ -25,13 +27,20 @@ export class Query<T extends Table> {
this.table = table;
}

public async findFirst(params: GenericParams<T>) {
public async findFirst(params: Omit<GenericParams<T>, "limit">) {
const { template, queryParams: query_params } = parseQuery(
params.where(this.table.columns, conditions),
);

const queriedData = await this.client.query({
query: `SELECT * FROM ${this.database}.${this.table.name} WHERE ${template} LIMIT 1`,
query: `SELECT * FROM ${this.database}.${this.table.name} WHERE ${template} ${
params.orderBy
? `ORDER BY ${params.orderBy(this.table.columns, {
asc: conditions.asc,
desc: conditions.desc,
})}`
: ""
} LIMIT 1 OFFSET ${params.offset ?? 0}`,
query_params,
});

Expand All @@ -46,7 +55,14 @@ export class Query<T extends Table> {
);

const queriedData = await this.client.query({
query: `SELECT * FROM ${this.database}.${this.table.name} WHERE ${template}`,
query: `SELECT * FROM ${this.database}.${this.table.name} WHERE ${template} ${
params.orderBy
? `ORDER BY ${params.orderBy(this.table.columns, {
asc: conditions.asc,
desc: conditions.desc,
})}`
: ""
} LIMIT ${params.limit ?? 100} OFFSET ${params.offset ?? 0}`,
query_params,
});

Expand Down
4 changes: 2 additions & 2 deletions src/expressions/conditions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ export function arrayOverlaps<T extends ColumnBuilder = ColumnBuilder>(column1:

// Order by
export function asc<T extends ColumnBuilder = ColumnBuilder>(column: T) {
return sql`${column} ASC`;
return `${column.name} ASC`;
}

export function desc<T extends ColumnBuilder = ColumnBuilder>(column: T) {
return sql`${column} DESC`;
return `${column.name} DESC`;
}
3 changes: 2 additions & 1 deletion src/expressions/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as conditions from "./conditions";

export type AllExpressions = typeof conditions;
export type AllExpressions = Omit<typeof conditions, "asc" | "desc">;
export type OrderByExpression = { asc: typeof conditions.asc; desc: typeof conditions.desc };

export function combineExpression(...conditions: string[]) {
return conditions.join(" AND ");
Expand Down
8 changes: 8 additions & 0 deletions tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import getCustomer from "./query/complex/getCustomer";
import createUser from "./query/createUser";
import deleteUser from "./query/deleteUser";
import getUser from "./query/getUser";
import limit from "./query/limit";
import offset from "./query/offset";
import ordering from "./query/ordering";
import updateUser from "./query/updateUser";
import { testSchemas } from "./testSchemas";
import parseQuery from "./utils/parseQuery";
Expand Down Expand Up @@ -51,6 +54,11 @@ describe("Test chorm", () => {
it("should be defined", defined);
it("should have all schemas in .query", checkProperties);

/* Check Ordering */
it("should check ordering", ordering);
it("should check limit", limit);
it("should check offset", offset);

/* Query */
it("should create a user", createUser);
it("should fetch a user", getUser);
Expand Down
11 changes: 11 additions & 0 deletions tests/query/limit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { chorm } from "../index.test";

export default async function () {
const testDesc = await chorm.query.ordering.findMany({
where: (columns, { isNotNull }) => isNotNull(columns.num),
limit: 5,
});

expect(testDesc).toBeDefined();
expect(testDesc).toHaveLength(5);
}
14 changes: 14 additions & 0 deletions tests/query/offset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { chorm } from "../index.test";

export default async function () {
const testDesc = await chorm.query.ordering.findMany({
where: (columns, { isNotNull }) => isNotNull(columns.num),
offset: 2,
orderBy(columns, conditions) {
return conditions.asc(columns.num);
},
});

expect(testDesc).toBeDefined();
expect(testDesc?.[0]?.num).toBe(2);
}
32 changes: 32 additions & 0 deletions tests/query/ordering.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { chorm } from "../index.test";

export default async function () {
const userIds = new Array(100).fill(0).map((_, i) => i);

for await (const id of userIds) {
const query = await chorm.query.ordering.insert({
id: id.toString(),
num: id,
});

expect(query).toBeDefined();
}

const testDesc = await chorm.query.ordering.findMany({
where: (columns, { isNotNull }) => isNotNull(columns.num),
orderBy: (columns, { desc }) => desc(columns.num),
});

expect(testDesc).toBeDefined();
expect(testDesc).toHaveLength(100);
expect(testDesc?.[0]?.num).toBe(99);

const testAsc = await chorm.query.ordering.findMany({
where: (columns, { isNotNull }) => isNotNull(columns.num),
orderBy: (columns, { asc }) => asc(columns.num),
});

expect(testAsc).toBeDefined();
expect(testAsc).toHaveLength(100);
expect(testAsc?.[0]?.num).toBe(0);
}
4 changes: 4 additions & 0 deletions tests/testSchemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,8 @@ export const testSchemas = {
null_column: text("null_column"),
array: array("array", { type: DATA_TYPE.String }).$type<string[]>().notNull(),
}),
ordering: table("ordering", {
id: text("id").primaryKey().notNull(),
num: integer("num").notNull(),
}),
};

0 comments on commit 1e351e4

Please sign in to comment.