Support order, limit and skip on findAll query

This commit is contained in:
Endeavorance 2025-04-18 11:23:28 -04:00
parent f87b3fcf76
commit 4cee7658b8
2 changed files with 64 additions and 11 deletions

View file

@ -362,8 +362,28 @@ export class Table<RowShape> {
* *
* @returns {RowShape[]} An array of all rows in the table. * @returns {RowShape[]} An array of all rows in the table.
*/ */
public findAll(): RowShape[] { public findAll(options?: {
return this._db.prepare<RowShape, []>(`SELECT * FROM ${this}`).all(); order?: string;
limit?: number;
skip?: number;
}): RowShape[] {
const optionParts: string[] = [];
if (options?.order) {
optionParts.push(`ORDER BY ${options.order}`);
}
if (options?.limit) {
optionParts.push(`LIMIT ${options.limit}`);
if (options?.skip) {
optionParts.push(`OFFSET ${options.skip}`);
}
}
return this._db
.prepare<RowShape, []>(`SELECT * FROM ${this} ${optionParts.join(" ")}`)
.all();
} }
/** /**
@ -377,7 +397,7 @@ export class Table<RowShape> {
const whereParts = keys.map((key) => `"${key}" = $${key}`); const whereParts = keys.map((key) => `"${key}" = $${key}`);
const whereClause = whereParts.join(" AND "); const whereClause = whereParts.join(" AND ");
const query = this._db.prepare<RowShape, SQLQueryBindings>( const query = this._db.prepare<RowShape, SQLQueryBindings>(
`SELECT * FROM ${this} WHERE ${whereClause};`, `SELECT * FROM ${this} WHERE ${whereClause}; `,
); );
return query.get(shapeForQuery(conditions)); return query.get(shapeForQuery(conditions));
@ -417,25 +437,25 @@ export class Table<RowShape> {
}, },
): RowShape[] { ): RowShape[] {
const keys = Object.keys(conditions); const keys = Object.keys(conditions);
const whereParts = keys.map((key) => `"${key}" = $${key}`); const whereParts = keys.map((key) => `"${key}" = $${key} `);
const whereClause = whereParts.join(" AND "); const whereClause = whereParts.join(" AND ");
const optionParts: string[] = []; const optionParts: string[] = [];
if (options?.order) { if (options?.order) {
optionParts.push(`ORDER BY ${options.order}`); optionParts.push(`ORDER BY ${options.order} `);
} }
if (options?.limit) { if (options?.limit) {
optionParts.push(`LIMIT ${options.limit}`); optionParts.push(`LIMIT ${options.limit} `);
if (options?.skip) { if (options?.skip) {
optionParts.push(`OFFSET ${options.skip}`); optionParts.push(`OFFSET ${options.skip} `);
} }
} }
const query = this._db.prepare<RowShape, SQLQueryBindings>( const query = this._db.prepare<RowShape, SQLQueryBindings>(
`SELECT * FROM ${this} WHERE ${whereClause} ${optionParts.join(" ")};`, `SELECT * FROM ${this} WHERE ${whereClause} ${optionParts.join(" ")}; `,
); );
return query.all(shapeForQuery(conditions)); return query.all(shapeForQuery(conditions));
@ -472,7 +492,7 @@ export class Table<RowShape> {
); );
} }
this._deleteQuery.run(`${id}`); this._deleteQuery.run(`${id} `);
}; };
/** /**
@ -482,10 +502,10 @@ export class Table<RowShape> {
*/ */
public deleteWhere(conditions: Partial<RowShape>): void { public deleteWhere(conditions: Partial<RowShape>): void {
const keys = Object.keys(conditions); const keys = Object.keys(conditions);
const whereParts = keys.map((key) => `"${key}" = $${key}`); const whereParts = keys.map((key) => `"${key}" = $${key} `);
const whereClause = whereParts.join(" AND "); const whereClause = whereParts.join(" AND ");
const query = this._db.prepare<void, SQLQueryBindings>( const query = this._db.prepare<void, SQLQueryBindings>(
`DELETE FROM ${this} WHERE ${whereClause};`, `DELETE FROM ${this} WHERE ${whereClause}; `,
); );
query.run(shapeForQuery(conditions)); query.run(shapeForQuery(conditions));

View file

@ -183,6 +183,39 @@ test(".findAll() returns the full table", () => {
expect(allUsers[2]).toEqual({ user_id: 3, name: "Sayid" }); expect(allUsers[2]).toEqual({ user_id: 3, name: "Sayid" });
}); });
test(".findAll() can set a limit on returned rows", () => {
const table = makeTestTable();
table.insertPartial({ name: "Jack" });
table.insertPartial({ name: "Kate" });
table.insertPartial({ name: "Sayid" });
const allUsers = table.findAll({ limit: 1 });
expect(allUsers).toHaveLength(1);
expect(allUsers[0]).toEqual({ user_id: 1, name: "Jack" });
});
test(".findAll() can set a skip and limit on returned rows", () => {
const table = makeTestTable();
table.insertPartial({ name: "Jack" });
table.insertPartial({ name: "Kate" });
table.insertPartial({ name: "Sayid" });
const allUsers = table.findAll({ limit: 1, skip: 1 });
expect(allUsers).toHaveLength(1);
expect(allUsers[0]).toEqual({ user_id: 2, name: "Kate" });
});
test(".findAll() can set an order for returned rows", () => {
const table = makeTestTable();
table.insertPartial({ name: "Jack" });
table.insertPartial({ name: "Kate" });
table.insertPartial({ name: "Sayid" });
const allUsers = table.findAll({ order: "user_id DESC" });
expect(allUsers).toHaveLength(3);
expect(allUsers[0]).toEqual({ user_id: 3, name: "Sayid" });
});
test(".query() returns a prepared statement for the table", () => { test(".query() returns a prepared statement for the table", () => {
const table = makeTestTable(); const table = makeTestTable();
const query = table.query("SELECT * FROM Users WHERE name = ?"); const query = table.query("SELECT * FROM Users WHERE name = ?");