Add order/limit support to find queries
This commit is contained in:
parent
b4eeb2c296
commit
153725f785
4 changed files with 91 additions and 18 deletions
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@endeavorance/prequel",
|
||||
"version": "2.1.0",
|
||||
"version": "2.2.0",
|
||||
"exports": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"scripts": {
|
||||
|
|
|
@ -27,7 +27,10 @@ export class PrequelKVStore {
|
|||
primary: true,
|
||||
autoincrement: true,
|
||||
},
|
||||
key: "TEXT",
|
||||
key: {
|
||||
type: "TEXT",
|
||||
unique: true,
|
||||
},
|
||||
value: "TEXT",
|
||||
});
|
||||
}
|
||||
|
|
63
src/table.ts
63
src/table.ts
|
@ -136,27 +136,36 @@ export class Table<RowShape> {
|
|||
.map((colName) => `$${colName}`)
|
||||
.join(", ");
|
||||
|
||||
this._createTableSQL = `CREATE TABLE IF NOT EXISTS "${name}" (${columnSQL});`;
|
||||
const insertSql = `INSERT INTO "${name}" (${allCols}) VALUES (${allColVars}) RETURNING *;`;
|
||||
const updateSql = `UPDATE "${name}" SET ${updateColumnSQL} WHERE "${this._primaryColumnName}" = $${this._primaryColumnName} RETURNING *;`;
|
||||
const getByIdSql = `SELECT * FROM "${name}" WHERE "${this._primaryColumnName}" = ? LIMIT 1;`;
|
||||
const delByIdSql = `DELETE FROM "${name}" WHERE "${this._primaryColumnName}" = ?;`;
|
||||
const deleteRowSql = `DELETE FROM "${name}" WHERE "${this._primaryColumnName}" = $${this._primaryColumnName};`;
|
||||
const truncateQuery = `DELETE FROM "${name}";`;
|
||||
|
||||
// Ensure the table exists in the database
|
||||
this._createTableSQL = `CREATE TABLE IF NOT EXISTS "${name}" (${columnSQL});`;
|
||||
this.db.exec(this._createTableSQL);
|
||||
|
||||
// Prepare common queries
|
||||
this._insertQuery = this.db.query<RowShape, ArbitraryRow>(insertSql);
|
||||
this._updateQuery = this.db.query<RowShape, ArbitraryRow>(updateSql);
|
||||
this._findQuery = this.db.query<RowShape, string>(getByIdSql);
|
||||
this._deleteQuery = this.db.query<void, string>(delByIdSql);
|
||||
this._insertQuery = this.db.query<RowShape, ArbitraryRow>(
|
||||
`INSERT INTO "${name}" (${allCols}) VALUES (${allColVars}) RETURNING *;`,
|
||||
);
|
||||
|
||||
this._updateQuery = this.db.query<RowShape, ArbitraryRow>(
|
||||
`UPDATE "${name}" SET ${updateColumnSQL} WHERE "${this._primaryColumnName}" = $${this._primaryColumnName} RETURNING *;`,
|
||||
);
|
||||
|
||||
this._findQuery = this.db.query<RowShape, string>(
|
||||
`SELECT * FROM "${name}" WHERE "${this._primaryColumnName}" = ? LIMIT 1;`,
|
||||
);
|
||||
|
||||
this._deleteQuery = this.db.query<void, string>(
|
||||
`DELETE FROM "${name}" WHERE "${this._primaryColumnName}" = ?;`,
|
||||
);
|
||||
|
||||
this._sizeQuery = this.db.query<{ count: number }, []>(
|
||||
`SELECT count(*) as count FROM ${name}`,
|
||||
);
|
||||
this._deleteRowQuery = this.db.query<void, ArbitraryRow>(deleteRowSql);
|
||||
this._truncateQuery = this.db.query<void, []>(truncateQuery);
|
||||
|
||||
this._deleteRowQuery = this.db.query<void, ArbitraryRow>(
|
||||
`DELETE FROM "${name}" WHERE "${this._primaryColumnName}" = $${this._primaryColumnName};`,
|
||||
);
|
||||
|
||||
this._truncateQuery = this.db.query<void, []>(`DELETE FROM "${name}"`);
|
||||
|
||||
// If using with a Prequel instance, ensure the table is attached
|
||||
// This is only for when creating tables directly and passing in a Prequel instance
|
||||
|
@ -424,12 +433,34 @@ export class Table<RowShape> {
|
|||
* The keys are column names and the values are the values to match.
|
||||
* @returns An array of rows that match the specified conditions.
|
||||
*/
|
||||
public findAllWhere(conditions: Partial<RowShape>): RowShape[] {
|
||||
public findAllWhere(
|
||||
conditions: Partial<RowShape>,
|
||||
options?: {
|
||||
order?: string;
|
||||
limit?: number;
|
||||
skip?: number;
|
||||
},
|
||||
): RowShape[] {
|
||||
const keys = Object.keys(conditions);
|
||||
const whereParts = keys.map((key) => `"${key}" = $${key}`);
|
||||
const whereClause = whereParts.join(" AND ");
|
||||
|
||||
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}`);
|
||||
}
|
||||
}
|
||||
|
||||
const query = this._db.prepare<RowShape, ArbitraryRow>(
|
||||
`SELECT * FROM ${this} WHERE ${whereClause};`,
|
||||
`SELECT * FROM ${this} WHERE ${whereClause} ${optionParts.join(" ")};`,
|
||||
);
|
||||
|
||||
return query.all(shapeForQuery(conditions));
|
||||
|
|
|
@ -222,6 +222,45 @@ test(".findAllWhere() returns a row based on basic criteria", () => {
|
|||
expect(manyJacks[2]).toEqual({ user_id: 3, name: "Jack" });
|
||||
});
|
||||
|
||||
test(".findAllWhere() can set a limit on returned rows", () => {
|
||||
const table = makeTestTable();
|
||||
table.insertPartial({ name: "Jack" });
|
||||
table.insertPartial({ name: "Jack" });
|
||||
table.insertPartial({ name: "Jack" });
|
||||
|
||||
const manyJacks = table.findAllWhere({ name: "Jack" }, { limit: 1 });
|
||||
|
||||
expect(manyJacks).toHaveLength(1);
|
||||
expect(manyJacks[0]).toEqual({ user_id: 1, name: "Jack" });
|
||||
});
|
||||
|
||||
test(".findAllWhere() can set an offset on a limit", () => {
|
||||
const table = makeTestTable();
|
||||
table.insertPartial({ name: "Jack" });
|
||||
table.insertPartial({ name: "Jack" });
|
||||
table.insertPartial({ name: "Jack" });
|
||||
|
||||
const manyJacks = table.findAllWhere({ name: "Jack" }, { limit: 1, skip: 1 });
|
||||
|
||||
expect(manyJacks).toHaveLength(1);
|
||||
expect(manyJacks[0]).toEqual({ user_id: 2, name: "Jack" });
|
||||
});
|
||||
|
||||
test(".findAllWhere() can set an order on the results", () => {
|
||||
const table = makeTestTable();
|
||||
table.insertPartial({ name: "Jack" });
|
||||
table.insertPartial({ name: "Jack" });
|
||||
table.insertPartial({ name: "Jack" });
|
||||
|
||||
const manyJacks = table.findAllWhere(
|
||||
{ name: "Jack" },
|
||||
{ order: "user_id DESC" },
|
||||
);
|
||||
|
||||
expect(manyJacks).toHaveLength(3);
|
||||
expect(manyJacks[0]).toEqual({ user_id: 3, name: "Jack" });
|
||||
});
|
||||
|
||||
test(".findOneById() returns a single element by its primary column", () => {
|
||||
const table = makeTestTable();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue