UNPKG

@jakub.knejzlik/ts-query

Version:

TypeScript implementation of SQL builder

112 lines (80 loc) 3.12 kB
import { Meta } from "@storybook/addon-docs"; import { CodePreview } from "./CodePreview"; <Meta title="6. Transformations" /> # 6. Transformations Transformations let you intercept and modify query structures at SQL generation time. This is useful for enforcing ACL rules, dynamic table routing, default filters, or modifying mutations without altering each query manually. ## Usage When calling `toSQL`, provide transformation functions: - `transformTable`: Alters table references. - `transformSelectQuery`: Modifies `SELECT` queries. - `transformInsertMutation`: Adjusts `INSERT` statements. - `transformUpdateMutation`: Modifies `UPDATE` operations. - `transformDeleteMutation`: Restricts `DELETE` queries. ## Transforming Table References This example replaces a table reference with a subquery: <CodePreview code={`const baseQuery = Q.select().from("foo", "f1"); const joinQuery = baseQuery.leftJoin(Q.table("foo2", "f2"), Cond.columnEqual("f1.id", "f2.id")); return joinQuery.toSQL(Q.flavors.mysql, { transformTable: (table) => { if (table === "foo") { return Q.select() .from(table, "f") .join(Q.table("bar", "b"), Cond.columnEqual("f.id", "b.id")); } return table; }, }); `}/> ## Modifying `SELECT` Queries You can modify fields in `SELECT` queries dynamically: <CodePreview code={`const baseQuery = Q.select().from("foo"); const unionQuery = baseQuery.union(Q.select().from("blah")); return unionQuery.toSQL(Q.flavors.mysql, { transformSelectQuery: (select) => { return select.addField("f1.name", "f1name"); }, }); `}/> ## Altering `INSERT` Statements Automatically add fields like `createdAt`: <CodePreview code={`const insertQuery = Q.insert("foo").values([{ id: 1, name: "foo" }]); return insertQuery.toSQL(Q.flavors.mysql, { transformInsertMutation: (q) => { const values = q.allValues().map((v) => ({ ...v, createdAt: "YYYY-MM-DD" })); return q.removeAllValues().values(values); }, }); `}/> ## Modifying `UPDATE` Operations Ensure updates meet specific conditions: <CodePreview code={`const updateQuery = Q.update("foo").set({ firstName: "john" }); return updateQuery.toSQL(Q.flavors.mysql, { transformUpdateMutation: (q) => { return q.set({ firstName: "jane" }).where(Cond.equal("lastName", "doe")); }, }); `}/> ## Restricting `DELETE` Queries Add automatic conditions to `DELETE` queries: <CodePreview code={`const deleteQuery = Q.delete("foo"); return deleteQuery.toSQL(Q.flavors.mysql, { transformDeleteMutation: (q) => { return q.where(Cond.equal("owner", "12345")); }, }); `}/> ## Common Use Cases 1. **ACL Enforcement** Automatically append conditions for access control. 2. **Sharding** Dynamically redirect queries to the appropriate database partition. 3. **Data Auditing** Add fields like `createdAt` to `INSERT` statements automatically. 4. **Soft Deletes** Transform `DELETE` into an `UPDATE` setting a `deletedAt` timestamp. By applying these transformations, query logic remains centralized and adaptable without needing individual query modifications.