UNPKG

@jakub.knejzlik/ts-query

Version:

TypeScript implementation of SQL builder

289 lines (208 loc) 5.07 kB
import { Meta } from "@storybook/addon-docs"; import { QueryPreview } from "./QueryPreview"; <Meta title="2. Conditions" /> # Condition Builder The Condition Builder provides a set of utilities to construct SQL conditions. It abstracts the raw SQL syntax, allowing developers to build conditions in a more readable and maintainable manner. ## Basic Usage To start building a condition, use the `Conditions` object: <QueryPreview code={` Cond.equal('columnName', 'foo'); `} /> ## Condition Types ### EQUAL To check if a column is equal to a value: <QueryPreview code={` Cond.equal('foo', 123); `} /> ### NOT EQUAL To check if a column is not equal to a value: <QueryPreview code={` Cond.notEqual('foo', '123'); `} /> ### GREATER THAN To check if a column's value is greater than a given value: <QueryPreview code={` Cond.greaterThan('foo', 123); `} /> ### LESS THAN To check if a column's value is less than a given value: <QueryPreview code={` Cond.lessThan('foo', '123'); `} /> ### GREATER THAN OR EQUAL To check if a column's value is greater than or equal to a given value: <QueryPreview code={` Cond.greaterThanOrEqual('foo', 123); `} /> ### LESS THAN OR EQUAL To check if a column's value is less than or equal to a given value: <QueryPreview code={` Cond.lessThanOrEqual('foo', '123'); `} /> ### BETWEEN To check if a column's value is between two values: <QueryPreview code={` Cond.between('foo', [1, 2]); `} /> You can also use dates: <QueryPreview code={` Cond.between('foo', [dayjs().startOf('year'), dayjs().endOf('day')]); `} /> Note: outputing SQL depends on [timezone of flavor](/docs/4-dates-and-timezones--docs). ### IN To check if a column's value is within a set of values: <QueryPreview code={` Cond.in('foo', [1, 2, 3]); `} /> #### IN with a subquery `Cond.in` also accepts a `SelectQuery` as its value, generating a `IN (SELECT …)` subquery. The subquery is fully serializable, so it survives a `serialize`/`deserialize` round-trip identically to its direct `toSQL` output: <QueryPreview code={` // id IN (SELECT user_id FROM orders WHERE active = 1) Cond.in('id', Q.select().field('user_id').from('orders').where(Cond.equal('active', 1))); `} /> #### Empty IN is fail-closed An empty (or \`null\`) value list renders \`IN (NULL)\` — a condition that never matches — instead of being dropped. This is intentional: an empty \`IN\` must never silently mean "no filter", which would expose every row. Because it is a real condition, it also survives serialization: <QueryPreview code={` // foo IN (NULL) — never matches, never silently dropped Cond.in('foo', []); `} /> ### NOT IN To check if a column's value is **not** within a set of values: <QueryPreview code={` Cond.notIn('foo', [1, 2, 3]); `} /> `Cond.notIn` mirrors `Cond.in`: it accepts a subquery and an empty list is fail-closed as `NOT IN (NULL)`. <QueryPreview code={` // id NOT IN (SELECT user_id FROM orders WHERE blocked = 1) Cond.notIn('id', Q.select().field('user_id').from('orders').where(Cond.equal('blocked', 1))); `} /> ### AND To combine multiple conditions with an AND operator: <QueryPreview code={` Cond.and([ Cond.equal('foo', 123), Cond.greaterThan('bar', 50), ]); `} /> ### OR To combine multiple conditions with an OR operator: <QueryPreview code={` Cond.or([Cond.equal('foo', 123), Cond.lessThan('bar', 50)]); `} /> ### Combining AND/OR To combine various AND/OR conditions together: <QueryPreview code={` Cond.and([ Cond.between('price', [10, 50]), Cond.or([ Cond.like('name', '%apple%'), Cond.notLike('description', '%refurbished%'), ]), ]) `} /> ### NULL To check if a column's value is NULL: <QueryPreview code={` Cond.null('foo'); `} /> ### NOT NULL To check if a column's value is NOT NULL: <QueryPreview code={` Cond.notNull('foo'); `} /> ### LIKE To check if a column's value matches a pattern: <QueryPreview code={` Cond.like('foo', 'He_lo wor%'); `} /> ### NOT LIKE To check if a column's value does not match a pattern: <QueryPreview code={` Cond.notLike('foo', 'He_lo wor%'); `} /> ### NOT To negate any condition: <QueryPreview code={` Cond.not(Cond.equal('foo', 123)); `} /> You can negate complex conditions: <QueryPreview code={` Cond.not( Cond.and([ Cond.equal('status', 'active'), Cond.greaterThan('age', 18) ]) ); `} /> Or negate other condition types: <QueryPreview code={` // NOT (foo IN (1, 2, 3)) Cond.not(Cond.in('foo', [1, 2, 3])); // NOT (price BETWEEN 10 AND 50) Cond.not(Cond.between('price', [10, 50])); // NOT (name LIKE '%test%') Cond.not(Cond.like('name', '%test%')); `} /> ## Conditions with functions To check if a column's value does not match a pattern: <QueryPreview code={` Cond.notLike(Fn.sum('foo'), 'He_lo wor%'); `} /> ## Conclusion The Condition Builder offers a powerful and flexible way to construct SQL conditions in a readable manner. By abstracting the raw SQL syntax, it helps in reducing errors and improving maintainability.