pqb 0.16.0 → 0.16.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1507,379 +1507,664 @@ declare class OnQueryBuilder<S extends QueryBase = QueryBase, J extends QueryBas
1507
1507
  _onJsonPathEquals<T extends OnQueryBuilder>(this: T, ...args: OnJsonPathEqualsArgs<T>): T;
1508
1508
  }
1509
1509
 
1510
- declare module './aggregate' {
1511
- interface SelectAggMethods<T extends Query> {
1512
- /**
1513
- * Give the `as` alias for the search, and it becomes possible to select a text with highlights of the matching words or phrases:
1514
- *
1515
- * ```ts
1516
- * db.table
1517
- * .search({
1518
- * as: 'search',
1519
- * in: 'body',
1520
- * query: 'query',
1521
- * })
1522
- * .select({
1523
- * highlightedText: (q) => q.headline('search'),
1524
- * });
1525
- * ```
1526
- *
1527
- * When searching in the generated `tsvector` column, need to provide a text source to the `headline`:
1528
- *
1529
- * ```ts
1530
- * db.table
1531
- * .search({
1532
- * as: 'search',
1533
- * vector: 'textVector',
1534
- * query: 'query',
1535
- * })
1536
- * .select({
1537
- * // `body` is a column name
1538
- * highlightedText: (q) => q.headline('search', { text: 'body' }),
1539
- * });
1540
- * ```
1541
- *
1542
- * `text` can be a raw SQL, here we are joining multiple columns:
1543
- *
1544
- * ```ts
1545
- * import { raw } from 'orchid-orm';
1546
- *
1547
- * db.table
1548
- * .search({
1549
- * as: 'search',
1550
- * vector: 'titleAndBodyVector',
1551
- * query: 'query',
1552
- * })
1553
- * .select({
1554
- * highlightedText: (q) =>
1555
- * q.headline('search', { text: raw`concat_ws(' ', title, body)` }),
1556
- * });
1557
- * ```
1558
- *
1559
- * `headline` supports a string for `options`, see details [in Postgres doc](https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-HEADLINE).
1560
- *
1561
- * Provide a simple string or a raw SQL:
1562
- *
1563
- * ```ts
1564
- * db.table
1565
- * .search({
1566
- * as: 'search',
1567
- * in: 'body',
1568
- * query: 'query',
1569
- * })
1570
- * .select({
1571
- * highlightedText: (q) =>
1572
- * q.headline('search', {
1573
- * options:
1574
- * 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=<<, StopSel=>>',
1575
- * }),
1576
- * });
1577
- * ```
1578
- *
1579
- * @param search - name of the search to use the query from
1580
- * @param options - `text` for a text source, `options` for `ts_headline` options
1581
- */
1582
- headline(search: string | undefined extends T['meta']['tsQuery'] ? never : Exclude<T['meta']['tsQuery'], undefined>, options?: {
1583
- text?: SelectableOrExpressionOfType<T, TextColumn>;
1584
- options?: string | Expression;
1585
- }): ColumnExpression<TextColumn>;
1586
- }
1587
- }
1588
- type SearchArg<T extends QueryBase, As extends string> = {
1589
- as?: As;
1590
- order?: OrderTsQueryConfig;
1591
- } & ({
1592
- language?: string | Expression;
1593
- } | {
1594
- languageColumn?: keyof T['selectable'];
1595
- }) & ({
1596
- text: string | Expression;
1597
- } | {
1598
- in: MaybeArray<keyof T['selectable']> | {
1599
- [K in keyof T['selectable']]?: SearchWeight;
1600
- };
1601
- } | {
1602
- vector: {
1603
- [K in keyof T['selectable']]: T['selectable'][K]['column']['dataType'] extends 'tsvector' ? K : never;
1604
- }[keyof T['selectable']];
1605
- }) & ({
1606
- query: string | Expression;
1607
- } | {
1608
- plainQuery: string | Expression;
1609
- } | {
1610
- phraseQuery: string | Expression;
1611
- } | {
1612
- tsQuery: string | Expression;
1613
- });
1614
- type WhereSearchResult<T extends QueryBase, As extends string> = T & {
1510
+ type WhereArg<T extends QueryBase> = {
1511
+ [K in keyof T['selectable'] | 'NOT' | 'OR' | 'IN' | 'EXISTS']?: K extends 'NOT' ? MaybeArray<WhereArg<T>> : K extends 'OR' ? MaybeArray<WhereArg<T>>[] : K extends 'IN' ? MaybeArray<{
1512
+ columns: (keyof T['selectable'])[];
1513
+ values: unknown[][] | Query | Expression;
1514
+ }> : K extends keyof T['selectable'] ? T['selectable'][K]['column']['type'] | null | ColumnOperators<T['selectable'], K> | Expression | Query : never;
1515
+ } | QueryBase | Expression | ((q: WhereQueryBuilder<T>) => WhereQueryBuilder);
1516
+ type WhereArgs<T extends QueryBase> = WhereArg<T>[] | TemplateLiteralArgs;
1517
+ type WhereInColumn<T extends QueryBase> = keyof T['selectable'] | [keyof T['selectable'], ...(keyof T['selectable'])[]];
1518
+ type WhereInValues<T extends QueryBase, Column extends WhereInColumn<T>> = Column extends keyof T['selectable'] ? T['selectable'][Column]['column']['type'][] | Query | Expression : ({
1519
+ [I in keyof Column]: Column[I] extends keyof T['selectable'] ? T['selectable'][Column[I]]['column']['type'] : never;
1520
+ } & {
1521
+ length: Column extends {
1522
+ length: number;
1523
+ } ? Column['length'] : never;
1524
+ })[] | Query | Expression;
1525
+ type WhereInArg<T extends Pick<Query, 'selectable'>> = {
1526
+ [K in keyof T['selectable']]?: T['selectable'][K]['column']['type'][] | Query | Expression;
1527
+ };
1528
+ type WhereResult<T extends QueryBase> = T & {
1615
1529
  meta: {
1616
- tsQuery: string extends As ? never : As;
1530
+ hasWhere: true;
1617
1531
  };
1618
1532
  };
1619
- declare const saveSearchAlias: (q: QueryBase, as: string) => string;
1620
- declare class SearchMethods {
1533
+ /**
1534
+ * Adds `where` arguments to query data: SQL template string is added as `RawSQL` object, other arguments are added as is.
1535
+ *
1536
+ * @param q - query object to add the data to
1537
+ * @param args - `where` arguments, may be a template literal
1538
+ */
1539
+ declare const addWhere: <T extends QueryBase>(q: T, args: WhereArgs<T>) => WhereResult<T>;
1540
+ /**
1541
+ * Adds `where` arguments to query data with a `NOT` keyword: SQL template string is added as `RawSQL` object, other arguments are added as is.
1542
+ *
1543
+ * @param q - query object to add the data to
1544
+ * @param args - `where` arguments, may be a template literal
1545
+ */
1546
+ declare const addWhereNot: <T extends QueryBase>(q: T, args: WhereArgs<T>) => WhereResult<T>;
1547
+ /**
1548
+ * Adds `where` arguments to query data. Arguments will be separated from each other with `OR`.
1549
+ *
1550
+ * @param q - query object to add the data to
1551
+ * @param args - `where` arguments, may be a template literal
1552
+ */
1553
+ declare const addOr: <T extends QueryBase>(q: T, args: WhereArg<T>[]) => WhereResult<T>;
1554
+ /**
1555
+ * Adds `where` arguments to query data with a `NOT` keyword. Arguments will be separated from each other with `OR`.
1556
+ *
1557
+ * @param q - query object to add the data to
1558
+ * @param args - `where` arguments, may be a template literal
1559
+ */
1560
+ declare const addOrNot: <T extends QueryBase>(q: T, args: WhereArg<T>[]) => WhereResult<T>;
1561
+ /**
1562
+ * Process arguments of `whereIn` to add them to query data properly.
1563
+ *
1564
+ * @param q - query object to add the data to.
1565
+ * @param and - `true` to join arguments with `AND`, `false` to join them with `OR.
1566
+ * @param arg - `whereIn` argument: can be a single column name, tuple of column names, or object with column names and values.
1567
+ * @param values - if the `arg` is a column name or a tuple, `values` are the values for the column/columns. If `arg` is an object, `values` are `undefined`.
1568
+ * @param not - adds the `NOT` keyword.
1569
+ */
1570
+ declare const addWhereIn: <T extends QueryBase>(q: T, and: boolean, arg: unknown, values: unknown[] | unknown[][] | Query | Expression | undefined, not?: boolean) => WhereResult<T>;
1571
+ declare abstract class Where extends QueryBase {
1621
1572
  /**
1622
- * ## language
1573
+ * Constructing `WHERE` conditions:
1623
1574
  *
1624
- * By default, the search language is English.
1575
+ * ```ts
1576
+ * db.table.where({
1577
+ * // column of the current table
1578
+ * name: 'John',
1625
1579
  *
1626
- * You can set a different default language in the `createBaseTable` config:
1580
+ * // table name may be specified, it can be the name of a joined table
1581
+ * 'table.lastName': 'Johnsonuk',
1627
1582
  *
1628
- * ```ts
1629
- * import { createBaseTable } from 'orchid-orm';
1583
+ * // object with operators, see the "column operators" section to see a full list of them:
1584
+ * age: {
1585
+ * gt: 30,
1586
+ * lt: 70,
1587
+ * },
1630
1588
  *
1631
- * export const BaseTable = createBaseTable({
1632
- * language: 'swedish',
1589
+ * // where column equals to raw SQL
1590
+ * column: db.table.sql`raw expression`,
1633
1591
  * });
1634
1592
  * ```
1635
1593
  *
1636
- * See the list of supported language configs with the SQL:
1594
+ * `undefined` values are ignored, so you can supply a partial object with conditions:
1637
1595
  *
1638
- * ```sql
1639
- * SELECT cfgname FROM pg_ts_config;
1596
+ * ```ts
1597
+ * type Params = {
1598
+ * // allow providing exact age, or lower or greate than
1599
+ * age?: number | { lt?: number; gt?: number };
1600
+ * };
1601
+ *
1602
+ * const loadRecords = async (params: Params) => {
1603
+ * // this will load all records if params is an empty object
1604
+ * const records = await db.table.where(params);
1605
+ * };
1640
1606
  * ```
1641
1607
  *
1642
- * When performing a search, you can override the default language:
1608
+ * It supports a sub-query that is selecting a single value to compare it with a column:
1643
1609
  *
1644
1610
  * ```ts
1645
- * db.table.search({
1646
- * language: 'finnish',
1647
- * in: 'body',
1648
- * query: 'query',
1611
+ * db.table.where({
1612
+ * // compare `someColumn` in one table with the `column` value returned from another query.
1613
+ * someColumn: db.otherTable.where(...conditions).get('column'),
1649
1614
  * });
1650
1615
  * ```
1651
1616
  *
1652
- * `language` also accepts a raw SQL.
1653
- *
1654
- * The language can be stored in the column of this table, then you can use `languageColumn` to use this column for the search:
1617
+ * `where` can accept other queries and merge their conditions:
1655
1618
  *
1656
1619
  * ```ts
1657
- * db.table.search({
1658
- * // the table has `lang` column, use it for the search
1659
- * languageColumn: 'lang',
1660
- * in: 'body',
1661
- * query: 'query',
1662
- * });
1663
- * ```
1620
+ * const otherQuery = db.table.where({ name: 'John' });
1664
1621
  *
1665
- * ## text vector to search in
1622
+ * db.table.where({ id: 1 }, otherQuery);
1623
+ * // this will produce WHERE "table"."id" = 1 AND "table"."name' = 'John'
1624
+ * ```
1666
1625
  *
1667
- * The text to search in can be a simple string, or a raw SQL, or a text column, or multiple columns:
1626
+ * `where` supports raw SQL:
1668
1627
  *
1669
1628
  * ```ts
1670
- * db.table.search({
1671
- * // search in the given string
1672
- * text: 'simply a string to search in',
1673
- * query: 'query',
1674
- * });
1629
+ * db.table.where`a = b`;
1630
+ *
1631
+ * // or
1632
+ * db.table.where(db.table.sql`a = b`);
1675
1633
  *
1634
+ * // or
1676
1635
  * import { raw } from 'orchid-orm';
1677
1636
  *
1678
- * db.table.search({
1679
- * // raw SQL: join text columns with space
1680
- * text: raw`concat_ws(' ', title, body)`,
1681
- * query: 'query',
1682
- * });
1637
+ * db.table.where(raw`a = b`);
1638
+ * ```
1683
1639
  *
1684
- * db.table.search({
1685
- * // search in a single text column
1686
- * in: 'body',
1687
- * query: 'query',
1688
- * });
1640
+ * `where` can accept a callback with a specific query builder containing all "where" methods such as `where`, `or`, `whereNot`, `whereIn`, `whereExists`:
1689
1641
  *
1690
- * db.table.search({
1691
- * // search in multiple columns, they are concatenated with `concat_ws` as shown above
1692
- * in: ['title', 'body'],
1693
- * query: 'query',
1694
- * });
1642
+ * ```ts
1643
+ * db.table.where((q) =>
1644
+ * q
1645
+ * .where({ name: 'Name' })
1646
+ * .or({ id: 1 }, { id: 2 })
1647
+ * .whereIn('letter', ['a', 'b', 'c'])
1648
+ * .whereExists(Message, 'authorId', 'id'),
1649
+ * );
1650
+ * ```
1695
1651
  *
1696
- * db.table.search({
1697
- * // search in multiple columns with different weights. Weight can be A, B, C, or D
1698
- * in: {
1699
- * title: 'A',
1700
- * body: 'B',
1701
- * },
1702
- * query: 'query',
1703
- * });
1652
+ * `where` can accept multiple arguments, conditions are joined with `AND`:
1653
+ *
1654
+ * ```ts
1655
+ * db.table.where(
1656
+ * { id: 1 },
1657
+ * db.table.where({ name: 'John' }),
1658
+ * db.table.sql`a = b`,
1659
+ * );
1704
1660
  * ```
1705
1661
  *
1706
- * For better performance, define a [generated](/guide/migration-column-methods.html#generated) column of `tsvector` type, and use it in the search with `vector` keyword:
1662
+ * ### where special keys
1663
+ *
1664
+ * The object passed to `where` can contain special keys, each of the keys corresponds to its own method and takes the same value as the type of argument of the method.
1665
+ *
1666
+ * For example:
1707
1667
  *
1708
1668
  * ```ts
1709
- * db.table.search({
1710
- * vector: 'titleAndBodyVector',
1711
- * query: 'query',
1669
+ * db.table.where({
1670
+ * NOT: { key: 'value' },
1671
+ * OR: [{ name: 'a' }, { name: 'b' }],
1672
+ * IN: {
1673
+ * columns: ['id', 'name'],
1674
+ * values: [
1675
+ * [1, 'a'],
1676
+ * [2, 'b'],
1677
+ * ],
1678
+ * },
1712
1679
  * });
1713
1680
  * ```
1714
1681
  *
1715
- * ## search query
1682
+ * Using methods instead of this is a shorter and cleaner way, but in some cases, such object keys way may be more convenient.
1716
1683
  *
1717
- * Read about different search queries in [this Postgres doc](https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES).
1684
+ * ```ts
1685
+ * db.table.where({
1686
+ * // see .whereNot
1687
+ * NOT: { id: 1 },
1688
+ * // can be an array:
1689
+ * NOT: [{ id: 1 }, { id: 2 }],
1718
1690
  *
1719
- * `search` method can accept one of the following queries:
1691
+ * // see .or
1692
+ * OR: [{ name: 'a' }, { name: 'b' }],
1693
+ * // can be an array:
1694
+ * // this will give id = 1 AND id = 2 OR id = 3 AND id = 4
1695
+ * OR: [
1696
+ * [{ id: 1 }, { id: 2 }],
1697
+ * [{ id: 3 }, { id: 4 }],
1698
+ * ],
1720
1699
  *
1721
- * - `query`: corresponds to `websearch_to_tsquery` in Postgres, good to use by default
1722
- * - `plainQuery`: corresponds to `plainto_tsquery`
1723
- * - `phraseQuery`: corresponds to `phraseto_tsquery`
1724
- * - `tsQuery`: corresponds to `to_tsquery`
1700
+ * // see .in, the key syntax requires an object with columns and values
1701
+ * IN: {
1702
+ * columns: ['id', 'name'],
1703
+ * values: [
1704
+ * [1, 'a'],
1705
+ * [2, 'b'],
1706
+ * ],
1707
+ * },
1708
+ * // can be an array:
1709
+ * IN: [
1710
+ * {
1711
+ * columns: ['id', 'name'],
1712
+ * values: [
1713
+ * [1, 'a'],
1714
+ * [2, 'b'],
1715
+ * ],
1716
+ * },
1717
+ * { columns: ['someColumn'], values: [['foo', 'bar']] },
1718
+ * ],
1719
+ * });
1720
+ * ```
1725
1721
  *
1726
- * The `query` (`websearch_to_tsquery`) can work with any user input, while other query kinds require a specific format and will fail for invalid input.
1722
+ * ## column operators
1727
1723
  *
1728
- * Each query kind accepts a string or a raw SQL.
1724
+ * `where` argument can take an object where the key is the name of the operator and the value is its argument.
1725
+ *
1726
+ * Different types of columns support different sets of operators.
1727
+ *
1728
+ * All column operators can take a value of the same type as the column, a sub-query, or a raw SQL expression:
1729
1729
  *
1730
1730
  * ```ts
1731
- * import { raw } from 'orchid-orm';
1731
+ * db.table.where({
1732
+ * numericColumn: {
1733
+ * // lower than 5
1734
+ * lt: 5,
1732
1735
  *
1733
- * db.table.search({
1734
- * vector: 'titleAndBodyVector',
1735
- * // can accept raw SQL:
1736
- * phraseQuery: raw`'The Fat Rats'`,
1736
+ * // lower than the value returned by sub-query
1737
+ * lt: OtherTable.select('someNumber').take(),
1738
+ *
1739
+ * // raw SQL expression produces WHERE "numericColumn" < "otherColumn" + 10
1740
+ * lt: db.table.sql`"otherColumn" + 10`,
1741
+ * },
1737
1742
  * });
1738
1743
  * ```
1739
1744
  *
1740
- * ## order by search rank
1745
+ * ### Any type of column operators
1741
1746
  *
1742
- * Read about search ranking in [this Postgres doc](https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-RANKING).
1747
+ * `equals` is a simple `=` operator, it may be useful for comparing column value with JSON object:
1743
1748
  *
1744
- * Set `order: true` to order results by the search rank:
1749
+ * ```ts
1750
+ * db.table.where({
1751
+ * // this will fail because an object with operators is expected
1752
+ * jsonColumn: someObject,
1753
+ *
1754
+ * // use this instead:
1755
+ * jsonColumn: { equals: someObject },
1756
+ * });
1757
+ * ```
1758
+ *
1759
+ * `not` is `!=` (or `<>`) not equal operator:
1745
1760
  *
1746
1761
  * ```ts
1747
- * db.table.search({
1748
- * in: 'body',
1749
- * query: 'query',
1750
- * // will add ORDER BY ts_rank(to_tsvector('english', body)) DESC
1751
- * order: true,
1762
+ * db.table.where({
1763
+ * anyColumn: { not: value },
1752
1764
  * });
1753
1765
  * ```
1754
1766
  *
1755
- * To order with `ts_rank_cd` instead of `ts_rank`, set `coverDensity: true`:
1767
+ * `in` is for the `IN` operator to check if the column value is included in a list of values.
1768
+ *
1769
+ * Takes an array of the same type as a column, a sub-query that returns a list of values, or a raw SQL expression that returns a list.
1756
1770
  *
1757
1771
  * ```ts
1758
- * db.table.search({
1759
- * in: 'body',
1760
- * query: 'query',
1761
- * // will add ORDER BY ts_rank_cd(to_tsvector('english', body)) DESC
1762
- * order: {
1763
- * coverDensity: true,
1772
+ * db.table.where({
1773
+ * column: {
1774
+ * in: ['a', 'b', 'c'],
1775
+ *
1776
+ * // WHERE "column" IN (SELECT "column" FROM "otherTable")
1777
+ * in: OtherTable.select('column'),
1778
+ *
1779
+ * in: db.table.sql`('a', 'b')`,
1764
1780
  * },
1765
1781
  * });
1766
1782
  * ```
1767
1783
  *
1768
- * Other options are:
1784
+ * `notIn` is for the `NOT IN` operator, and takes the same arguments as `in`
1785
+ *
1786
+ * ### Numeric, Date, and Time column operators
1787
+ *
1788
+ * To compare numbers, dates, and times.
1789
+ *
1790
+ * `lt` is for `<` (lower than)
1791
+ *
1792
+ * `lte` is for `<=` (lower than or equal)
1793
+ *
1794
+ * `gt` is for `>` (greater than)
1795
+ *
1796
+ * `gte` is for `>=` (greater than or equal)
1769
1797
  *
1770
1798
  * ```ts
1771
- * db.table.search({
1772
- * in: 'body',
1773
- * query: 'query',
1774
- * order: {
1775
- * // weights for D, C, B, A:
1776
- * weights: [0.1, 0.2, 0.4, 1],
1777
- * // by default, rank ignores the document length
1778
- * // change rank behavior by providing here a special number
1779
- * normalization: 32,
1780
- * // it's possible to change the order direction:
1781
- * dir: 'ASC', // DESC by default
1799
+ * db.table.where({
1800
+ * numericColumn: {
1801
+ * gt: 5,
1802
+ * lt: 10,
1803
+ * },
1804
+ *
1805
+ * date: {
1806
+ * lte: new Date(),
1807
+ * },
1808
+ *
1809
+ * time: {
1810
+ * gte: new Date(),
1782
1811
  * },
1783
1812
  * });
1784
1813
  * ```
1785
1814
  *
1786
- * Giving the `as` alias for the search allows to set the ordering in the `order` method:
1815
+ * `between` also works with numeric, dates, and time columns, it takes an array of two elements.
1816
+ *
1817
+ * Both elements can be of the same type as a column, a sub-query, or a raw SQL expression.
1787
1818
  *
1788
1819
  * ```ts
1789
- * db.table
1790
- * .search({
1791
- * as: 'search',
1792
- * in: 'body',
1793
- * query: 'query',
1794
- * })
1795
- * .order({
1796
- * // can be `search: true` for defaults
1797
- * search: {
1798
- * // same options as above
1799
- * coverDensity: true,
1800
- * weights: [0.1, 0.2, 0.4, 1.0],
1801
- * normalization: 32,
1802
- * dir: 'ASC',
1803
- * },
1804
- * });
1820
+ * db.table.where({
1821
+ * column: {
1822
+ * // simple values
1823
+ * between: [1, 10],
1824
+ *
1825
+ * // sub-query and raw SQL expression
1826
+ * between: [OtherTable.select('column').take(), db.table.sql`2 + 2`],
1827
+ * },
1828
+ * });
1805
1829
  * ```
1806
1830
  *
1807
- * @param arg - search config
1831
+ * ### Text column operators
1832
+ *
1833
+ * For `text`, `char`, `varchar`, and `json` columns.
1834
+ *
1835
+ * `json` is stored as text, so it has text operators. Use the `jsonb` type for JSON operators.
1836
+ *
1837
+ * Takes a string, or sub-query returning string, or raw SQL expression as well as other operators.
1838
+ *
1839
+ * ```ts
1840
+ * db.table.where({
1841
+ * textColumn: {
1842
+ * // WHERE "textColumn" LIKE '%string%'
1843
+ * contains: 'string',
1844
+ * // WHERE "textColumn" ILIKE '%string%'
1845
+ * containsInsensitive: 'string',
1846
+ * // WHERE "textColumn" LIKE 'string%'
1847
+ * startsWith: 'string',
1848
+ * // WHERE "textColumn" ILIKE 'string%'
1849
+ * startsWithInsensitive: 'string',
1850
+ * // WHERE "textColumn" LIKE '%string'
1851
+ * endsWith: 'string',
1852
+ * // WHERE "textColumn" ILIKE '%string'
1853
+ * endsWithInsensitive: 'string',
1854
+ * },
1855
+ * });
1856
+ * ```
1857
+ *
1858
+ * ### JSONB column operators
1859
+ *
1860
+ * For the `jsonb` column, note that the `json` type has text operators instead.
1861
+ *
1862
+ * `jsonPath` operator: compare a column value under a given JSON path with the provided value.
1863
+ *
1864
+ * Value can be of any type to compare with JSON value, or it can be a sub-query or a raw SQL expression.
1865
+ *
1866
+ * ```ts
1867
+ * db.table.where({
1868
+ * jsonbColumn: {
1869
+ * jsonPath: [
1870
+ * '$.name', // first element is JSON path
1871
+ * '=', // second argument is comparison operator
1872
+ * 'value', // third argument is a value to compare with
1873
+ * ],
1874
+ * },
1875
+ * });
1876
+ * ```
1877
+ *
1878
+ * `jsonSupersetOf`: check if the column value is a superset of provided value.
1879
+ *
1880
+ * For instance, it is true if the column has JSON `{ "a": 1, "b": 2 }` and provided value is `{ "a": 1 }`.
1881
+ *
1882
+ * Takes the value of any type, or sub query which returns a single value, or a raw SQL expression.
1883
+ *
1884
+ * ```ts
1885
+ * db.table.where({
1886
+ * jsonbColumn: {
1887
+ * jsonSupersetOf: { a: 1 },
1888
+ * },
1889
+ * });
1890
+ * ```
1891
+ *
1892
+ * `jsonSubsetOf`: check if the column value is a subset of provided value.
1893
+ *
1894
+ * For instance, it is true if the column has JSON `{ "a": 1 }` and provided value is `{ "a": 1, "b": 2 }`.
1895
+ *
1896
+ * Takes the value of any type, or sub query which returns a single value, or a raw SQL expression.
1897
+ *
1898
+ * ```ts
1899
+ * db.table.where({
1900
+ * jsonbColumn: {
1901
+ * jsonSupersetOf: { a: 1 },
1902
+ * },
1903
+ * });
1904
+ * ```
1905
+ *
1906
+ * @param args - {@link WhereArgs}
1808
1907
  */
1809
- search<T extends Query, As extends string>(this: T, arg: SearchArg<T, As>): WhereSearchResult<T, As>;
1810
- _search<T extends Query, As extends string>(this: T, arg: SearchArg<T, As>): WhereSearchResult<T, As>;
1811
- }
1812
-
1813
- type WhereArg<T extends QueryBase> = {
1814
- [K in keyof T['selectable'] | 'NOT' | 'OR' | 'IN' | 'EXISTS' | 'SEARCH']?: K extends 'NOT' ? MaybeArray<WhereArg<T>> : K extends 'OR' ? MaybeArray<WhereArg<T>>[] : K extends 'IN' ? MaybeArray<{
1815
- columns: (keyof T['selectable'])[];
1816
- values: unknown[][] | Query | Expression;
1817
- }> : K extends 'SEARCH' ? MaybeArray<SearchArg<T, never>> : K extends keyof T['selectable'] ? T['selectable'][K]['column']['type'] | null | ColumnOperators<T['selectable'], K> | Expression : never;
1818
- } | QueryBase | Expression | ((q: WhereQueryBuilder<T>) => WhereQueryBuilder);
1819
- type WhereArgs<T extends QueryBase> = WhereArg<T>[] | TemplateLiteralArgs;
1820
- type WhereInColumn<T extends QueryBase> = keyof T['selectable'] | [keyof T['selectable'], ...(keyof T['selectable'])[]];
1821
- type WhereInValues<T extends QueryBase, Column extends WhereInColumn<T>> = Column extends keyof T['selectable'] ? T['selectable'][Column]['column']['type'][] | Query | Expression : ({
1822
- [I in keyof Column]: Column[I] extends keyof T['selectable'] ? T['selectable'][Column[I]]['column']['type'] : never;
1823
- } & {
1824
- length: Column extends {
1825
- length: number;
1826
- } ? Column['length'] : never;
1827
- })[] | Query | Expression;
1828
- type WhereResult<T extends QueryBase> = T & {
1829
- meta: {
1830
- hasWhere: true;
1831
- };
1832
- };
1833
- type WhereInArg<T extends Pick<Query, 'selectable'>> = {
1834
- [K in keyof T['selectable']]?: T['selectable'][K]['column']['type'][] | Query | Expression;
1835
- };
1836
- declare const addWhere: <T extends QueryBase>(q: T, args: WhereArgs<T>) => WhereResult<T>;
1837
- declare const addWhereNot: <T extends QueryBase>(q: T, args: WhereArgs<T>) => WhereResult<T>;
1838
- declare const addOr: <T extends QueryBase>(q: T, args: WhereArg<T>[]) => WhereResult<T>;
1839
- declare const addOrNot: <T extends QueryBase>(q: T, args: WhereArg<T>[]) => WhereResult<T>;
1840
- declare const addWhereIn: <T extends QueryBase>(q: T, and: boolean, arg: unknown, values: unknown[] | unknown[][] | Query | Expression | undefined, not?: boolean) => WhereResult<T>;
1841
- declare abstract class Where extends QueryBase {
1842
1908
  where<T extends Where>(this: T, ...args: WhereArgs<T>): WhereResult<T>;
1843
1909
  _where<T extends Where>(this: T, ...args: WhereArgs<T>): WhereResult<T>;
1910
+ /**
1911
+ * `whereNot` takes the same arguments as `where` and prepends them with `NOT` in SQL
1912
+ *
1913
+ * ```ts
1914
+ * // find records of different colors than red
1915
+ * db.table.whereNot({ color: 'red' });
1916
+ * ```
1917
+ *
1918
+ * @param args - {@link WhereArgs}
1919
+ */
1844
1920
  whereNot<T extends Where>(this: T, ...args: WhereArgs<T>): WhereResult<T>;
1845
1921
  _whereNot<T extends Where>(this: T, ...args: WhereArgs<T>): WhereResult<T>;
1922
+ /**
1923
+ * `and` is an alias for {@link where} to make it look closer to SQL:
1924
+ *
1925
+ * ```ts
1926
+ * db.table.where({ id: 1 }).and({ name: 'John' });
1927
+ * ```
1928
+ *
1929
+ * @param args - {@link WhereArgs}
1930
+ */
1846
1931
  and<T extends Where>(this: T, ...args: WhereArgs<T>): WhereResult<T>;
1847
1932
  _and<T extends Where>(this: T, ...args: WhereArgs<T>): WhereResult<T>;
1933
+ /**
1934
+ * `andNot` is an alias for `whereNot`.
1935
+ *
1936
+ * @param args - {@link WhereArgs}
1937
+ */
1848
1938
  andNot<T extends Where>(this: T, ...args: WhereArgs<T>): WhereResult<T>;
1849
1939
  _andNot<T extends Where>(this: T, ...args: WhereArgs<T>): WhereResult<T>;
1940
+ /**
1941
+ * `or` is accepting the same arguments as {@link where}, joining arguments with `OR`.
1942
+ *
1943
+ * Columns in single arguments are still joined with `AND`.
1944
+ *
1945
+ * The database is processing `AND` before `OR`, so this should be intuitively clear.
1946
+ *
1947
+ * ```ts
1948
+ * db.table.or({ id: 1, color: 'red' }, { id: 2, color: 'blue' });
1949
+ * ```
1950
+ *
1951
+ * This query will produce such SQL (simplified):
1952
+ *
1953
+ * ```sql
1954
+ * SELECT * FROM "table"
1955
+ * WHERE id = 1 AND color = 'red'
1956
+ * OR id = 2 AND color = 'blue'
1957
+ * ```
1958
+ *
1959
+ * @param args - {@link WhereArgs} will be joined with `OR`
1960
+ */
1850
1961
  or<T extends Where>(this: T, ...args: WhereArg<T>[]): WhereResult<T>;
1851
1962
  _or<T extends Where>(this: T, ...args: WhereArg<T>[]): WhereResult<T>;
1963
+ /**
1964
+ * `orNot` takes the same arguments as {@link or}, and prepends each condition with `NOT` just as {@link whereNot} does.
1965
+ *
1966
+ * @param args - {@link WhereArgs} will be prefixed with `NOT` and joined with `OR`
1967
+ */
1852
1968
  orNot<T extends Where>(this: T, ...args: WhereArg<T>[]): WhereResult<T>;
1853
1969
  _orNot<T extends Where>(this: T, ...args: WhereArg<T>[]): WhereResult<T>;
1970
+ /**
1971
+ * `whereIn` and related methods are for the `IN` operator to check for inclusion in a list of values.
1972
+ *
1973
+ * When used with a single column it works equivalent to the `in` column operator:
1974
+ *
1975
+ * ```ts
1976
+ * db.table.whereIn('column', [1, 2, 3]);
1977
+ * // the same as:
1978
+ * db.table.where({ column: [1, 2, 3] });
1979
+ * ```
1980
+ *
1981
+ * `whereIn` can support a tuple of columns, that's what the `in` operator cannot support:
1982
+ *
1983
+ * ```ts
1984
+ * db.table.whereIn(
1985
+ * ['id', 'name'],
1986
+ * [
1987
+ * [1, 'Alice'],
1988
+ * [2, 'Bob'],
1989
+ * ],
1990
+ * );
1991
+ * ```
1992
+ *
1993
+ * It supports sub query which should return records with columns of the same type:
1994
+ *
1995
+ * ```ts
1996
+ * db.table.whereIn(['id', 'name'], OtherTable.select('id', 'name'));
1997
+ * ```
1998
+ *
1999
+ * It supports raw SQL expression:
2000
+ *
2001
+ * ```ts
2002
+ * db.table.whereIn(['id', 'name'], db.table.sql`((1, 'one'), (2, 'two'))`);
2003
+ * ```
2004
+ *
2005
+ * @param column - one column name, or array of column names
2006
+ * @param values - array of values, or a query to load values, or a raw SQL. Tuple of such values in case of multiple columns.
2007
+ */
1854
2008
  whereIn<T extends Where, Column extends WhereInColumn<T>>(this: T, column: Column, values: WhereInValues<T, Column>): WhereResult<T>;
2009
+ /**
2010
+ * See {@link whereIn}.
2011
+ *
2012
+ * @param arg - object where keys are column names, and values are an array of column values, or a query returning column values, or a raw SQL.
2013
+ */
1855
2014
  whereIn<T extends Where>(this: T, arg: WhereInArg<T>): WhereResult<T>;
1856
2015
  _whereIn<T extends Where, Column extends WhereInColumn<T>>(this: T, column: Column, values: WhereInValues<T, Column>): WhereResult<T>;
1857
2016
  _whereIn<T extends Where>(this: T, arg: WhereInArg<T>): WhereResult<T>;
2017
+ /**
2018
+ * Takes the same arguments as {@link whereIn}.
2019
+ * Add a `WHERE IN` condition prefixed with `OR` to the query:
2020
+ *
2021
+ * ```ts
2022
+ * db.table.whereIn('a', [1, 2, 3]).orWhereIn('b', ['one', 'two']);
2023
+ * ```
2024
+ *
2025
+ * @param column - one column name, or array of column names
2026
+ * @param values - array of values, or a query to load values, or a raw SQL. Tuple of such values in case of multiple columns.
2027
+ */
1858
2028
  orWhereIn<T extends Where, Column extends WhereInColumn<T>>(this: T, column: Column, values: WhereInValues<T, Column>): WhereResult<T>;
2029
+ /**
2030
+ * See {@link orWhereIn}.
2031
+ *
2032
+ * @param arg - object where keys are column names, and values are an array of column values, or a query returning column values, or a raw SQL.
2033
+ */
1859
2034
  orWhereIn<T extends Where>(this: T, arg: WhereInArg<T>): WhereResult<T>;
1860
2035
  _orWhereIn<T extends Where, Column extends WhereInColumn<T>>(this: T, column: Column, values: WhereInValues<T, Column>): WhereResult<T>;
1861
2036
  _orWhereIn<T extends Where>(this: T, arg: WhereInArg<T>): WhereResult<T>;
2037
+ /**
2038
+ * Acts as `whereIn`, but negates the condition with `NOT`:
2039
+ *
2040
+ * ```ts
2041
+ * db.table.whereNotIn('color', ['red', 'green', 'blue']);
2042
+ * ```
2043
+ *
2044
+ * @param column - one column name, or array of column names
2045
+ * @param values - array of values, or a query to load values, or a raw SQL. Tuple of such values in case of multiple columns.
2046
+ */
1862
2047
  whereNotIn<T extends Where, Column extends WhereInColumn<T>>(this: T, column: Column, values: WhereInValues<T, Column>): WhereResult<T>;
2048
+ /**
2049
+ * See {@link whereNotIn}.
2050
+ *
2051
+ * @param arg - object where keys are column names, and values are an array of column values, or a query returning column values, or a raw SQL.
2052
+ */
1863
2053
  whereNotIn<T extends Where>(this: T, arg: WhereInArg<T>): WhereResult<T>;
1864
2054
  _whereNotIn<T extends Where, Column extends WhereInColumn<T>>(this: T, column: Column, values: WhereInValues<T, Column>): WhereResult<T>;
1865
2055
  _whereNotIn<T extends Where>(this: T, arg: WhereInArg<T>): WhereResult<T>;
2056
+ /**
2057
+ * Acts as `whereIn`, but prepends `OR` to the condition and negates it with `NOT`:
2058
+ *
2059
+ * ```ts
2060
+ * db.table.whereNotIn('a', [1, 2, 3]).orWhereNoIn('b', ['one', 'two']);
2061
+ * ```
2062
+ *
2063
+ * @param column - one column name, or array of column names
2064
+ * @param values - array of values, or a query to load values, or a raw SQL. Tuple of such values in case of multiple columns.
2065
+ */
1866
2066
  orWhereNotIn<T extends Where, Column extends WhereInColumn<T>>(this: T, column: Column, values: WhereInValues<T, Column>): WhereResult<T>;
2067
+ /**
2068
+ * See {@link orWhereNotIn}.
2069
+ *
2070
+ * @param arg - object where keys are column names, and values are an array of column values, or a query returning column values, or a raw SQL.
2071
+ */
1867
2072
  orWhereNotIn<T extends Where>(this: T, arg: WhereInArg<T>): WhereResult<T>;
1868
2073
  _orWhereNotIn<T extends Where, Column extends WhereInColumn<T>>(this: T, column: Column, values: WhereInValues<T, Column>): WhereResult<T>;
1869
2074
  _orWhereNotIn<T extends Where>(this: T, arg: WhereInArg<T>): WhereResult<T>;
2075
+ /**
2076
+ * `whereExists` is for support of the `WHERE EXISTS (query)` clause.
2077
+ *
2078
+ * This method is accepting the same arguments as `join`, see the {@link Join.join} section for more details.
2079
+ *
2080
+ * ```ts
2081
+ * // find users who have accounts
2082
+ * // find by a relation name if it's defined
2083
+ * db.user.whereExists('account');
2084
+ *
2085
+ * // find using a table and a join conditions
2086
+ * db.user.whereExists(db.account, 'account.id', 'user.id');
2087
+ *
2088
+ * // find using a query builder in a callback:
2089
+ * db.user.whereExists(db.account, (q) => q.on('account.id', '=', 'user.id'));
2090
+ * ```
2091
+ *
2092
+ * @param arg - relation name, or a query object, or a `with` table alias, or a callback returning a query object.
2093
+ * @param args - no arguments needed when the first argument is a relation name, or conditions to join the table with.
2094
+ */
1870
2095
  whereExists<T extends Where, Arg extends JoinFirstArg<T>>(this: T, arg: Arg, ...args: JoinArgs<T, Arg>): WhereResult<T>;
2096
+ /**
2097
+ * See {@link whereExists}.
2098
+ *
2099
+ * @param arg - relation name, or a query object, or a `with` table alias, or a callback returning a query object.
2100
+ * @param cb - callback with a query builder to join the table.
2101
+ */
1871
2102
  whereExists<T extends Where, Arg extends JoinFirstArg<T>>(this: T, arg: Arg, cb: JoinCallback<T, Arg>): WhereResult<T>;
1872
2103
  _whereExists<T extends Where, Arg extends JoinFirstArg<T>>(this: T, arg: Arg, ...args: JoinArgs<T, Arg>): WhereResult<T>;
1873
2104
  _whereExists<T extends Where, Arg extends JoinFirstArg<T>>(this: T, arg: Arg, cb: JoinCallback<T, Arg>): WhereResult<T>;
2105
+ /**
2106
+ * Acts as `whereExists`, but prepends the condition with `OR`:
2107
+ *
2108
+ * ```ts
2109
+ * // find users who have an account or a profile,
2110
+ * // imagine that the user has both `account` and `profile` relations defined.
2111
+ * db.user.whereExist('account').orWhereExists('profile');
2112
+ * ```
2113
+ *
2114
+ * @param arg - relation name, or a query object, or a `with` table alias, or a callback returning a query object.
2115
+ * @param args - no arguments needed when the first argument is a relation name, or conditions to join the table with.
2116
+ */
1874
2117
  orWhereExists<T extends Where, Arg extends JoinFirstArg<T>, Args extends JoinArgs<T, Arg>>(this: T, arg: Arg, ...args: Args): WhereResult<T>;
2118
+ /**
2119
+ * See {@link orWhereExists}.
2120
+ *
2121
+ * @param arg - relation name, or a query object, or a `with` table alias, or a callback returning a query object.
2122
+ * @param cb - callback with a query builder to join the table.
2123
+ */
1875
2124
  orWhereExists<T extends Where, Arg extends JoinFirstArg<T>>(this: T, arg: Arg, cb: JoinCallback<T, Arg>): WhereResult<T>;
1876
2125
  _orWhereExists<T extends Where, Arg extends JoinFirstArg<T>, Args extends JoinArgs<T, Arg>>(this: T, arg: Arg, ...args: Args): WhereResult<T>;
1877
2126
  _orWhereExists<T extends Where, Arg extends JoinFirstArg<T>>(this: T, arg: Arg, cb: JoinCallback<T, Arg>): WhereResult<T>;
2127
+ /**
2128
+ * Acts as `whereExists`, but negates the condition with `NOT`:
2129
+ *
2130
+ * ```ts
2131
+ * // find users who don't have an account,
2132
+ * // image that the user `belongsTo` or `hasOne` account.
2133
+ * db.user.whereNotExist('account');
2134
+ * ```
2135
+ *
2136
+ * @param arg - relation name, or a query object, or a `with` table alias, or a callback returning a query object.
2137
+ * @param args - no arguments needed when the first argument is a relation name, or conditions to join the table with.
2138
+ */
1878
2139
  whereNotExists<T extends Where, Arg extends JoinFirstArg<T>, Args extends JoinArgs<T, Arg>>(this: T, arg: Arg, ...args: Args): WhereResult<T>;
2140
+ /**
2141
+ * See {@link whereNotExists}.
2142
+ *
2143
+ * @param arg - relation name, or a query object, or a `with` table alias, or a callback returning a query object.
2144
+ * @param cb - callback with a query builder to join the table.
2145
+ */
1879
2146
  whereNotExists<T extends Where, Arg extends JoinFirstArg<T>>(this: T, arg: Arg, cb: JoinCallback<T, Arg>): WhereResult<T>;
1880
2147
  _whereNotExists<T extends Where, Arg extends JoinFirstArg<T>, Args extends JoinArgs<T, Arg>>(this: T, arg: Arg, ...args: Args): WhereResult<T>;
1881
2148
  _whereNotExists<T extends Where, Arg extends JoinFirstArg<T>>(this: T, arg: Arg, cb: JoinCallback<T, Arg>): WhereResult<T>;
2149
+ /**
2150
+ * Acts as `whereExists`, but prepends the condition with `OR` and negates it with `NOT`:
2151
+ *
2152
+ * ```ts
2153
+ * // find users who don't have an account OR who don't have a profile
2154
+ * // imagine that the user has both `account` and `profile` relations defined.
2155
+ * db.user.whereNotExists('account').orWhereNotExists('profile');
2156
+ * ```
2157
+ *
2158
+ * @param arg - relation name, or a query object, or a `with` table alias, or a callback returning a query object.
2159
+ * @param args - no arguments needed when the first argument is a relation name, or conditions to join the table with.
2160
+ */
1882
2161
  orWhereNotExists<T extends Where, Arg extends JoinFirstArg<T>, Args extends JoinArgs<T, Arg>>(this: T, arg: Arg, ...args: Args): WhereResult<T>;
2162
+ /**
2163
+ * See {@link orWhereNotExists}.
2164
+ *
2165
+ * @param arg - relation name, or a query object, or a `with` table alias, or a callback returning a query object.
2166
+ * @param cb - callback with a query builder to join the table.
2167
+ */
1883
2168
  orWhereNotExists<T extends Where, Arg extends JoinFirstArg<T>>(this: T, arg: Arg, cb: JoinCallback<T, Arg>): WhereResult<T>;
1884
2169
  _orWhereNotExists<T extends Where, Arg extends JoinFirstArg<T>, Args extends JoinArgs<T, Arg>>(this: T, arg: Arg, ...args: Args): WhereResult<T>;
1885
2170
  _orWhereNotExists<T extends Where, Arg extends JoinFirstArg<T>>(this: T, arg: Arg, cb: JoinCallback<T, Arg>): WhereResult<T>;
@@ -3325,169 +3610,472 @@ declare class Update {
3325
3610
  *
3326
3611
  * If `.select` and `.take`, `.find`, or similar were specified before the update it will return one updated record.
3327
3612
  *
3328
- * For a column value you can provide a specific value, raw SQL, a query object that returns a single value, or a callback with a sub-query.
3613
+ * For a column value you can provide a specific value, raw SQL, a query object that returns a single value, or a callback with a sub-query.
3614
+ *
3615
+ * ```ts
3616
+ * // returns number of updated records by default
3617
+ * const updatedCount = await db.table
3618
+ * .where({ name: 'old name' })
3619
+ * .update({ name: 'new name' });
3620
+ *
3621
+ * // returning only `id`
3622
+ * const id = await db.table.find(1).get('id').update({ name: 'new name' });
3623
+ *
3624
+ * // `selectAll` + `find` will return a full record
3625
+ * const oneFullRecord = await db.table
3626
+ * .selectAll()
3627
+ * .find(1)
3628
+ * .update({ name: 'new name' });
3629
+ *
3630
+ * // `selectAll` + `where` will return array of full records
3631
+ * const recordsArray = await db.table
3632
+ * .select('id', 'name')
3633
+ * .where({ id: 1 })
3634
+ * .update({ name: 'new name' });
3635
+ *
3636
+ * await db.table.where({ ...conditions }).update({
3637
+ * // set the column to a specific value
3638
+ * column1: 123,
3639
+ *
3640
+ * // use raw SQL to update the column
3641
+ * column2: db.table.sql`2 + 2`,
3642
+ *
3643
+ * // use query that returns a single value
3644
+ * // returning multiple values will result in Postgres error
3645
+ * column3: db.otherTable.get('someColumn'),
3646
+ *
3647
+ * // select a single value from a related record
3648
+ * fromRelation: (q) => q.relatedTable.get('someColumn'),
3649
+ *
3650
+ * // set a new value to the `.foo.bar` path into a JSON column
3651
+ * jsonColumn: (q) => q.jsonSet('jsonColumn', ['foo', 'bar'], 'new value'),
3652
+ * });
3653
+ * ```
3654
+ *
3655
+ * `null` value will set a column to `NULL`, but the `undefined` value will be ignored:
3656
+ *
3657
+ * ```ts
3658
+ * db.table.findBy({ id: 1 }).update({
3659
+ * name: null, // updates to null
3660
+ * age: undefined, // skipped, no effect
3661
+ * });
3662
+ * ```
3663
+ *
3664
+ * @param arg - data to update records with, may have specific values, raw SQL, queries, or callbacks with sub-queries.
3665
+ */
3666
+ update<T extends Query>(this: T, arg: UpdateArg<T>): UpdateResult<T>;
3667
+ _update<T extends Query>(this: T, arg: UpdateArg<T>): UpdateResult<T>;
3668
+ /**
3669
+ * `updateRaw` is for updating records with raw expression.
3670
+ *
3671
+ * The behavior is the same as a regular `update` method has:
3672
+ * `find` or `where` must precede calling this method,
3673
+ * it returns an updated count by default,
3674
+ * you can customize returning data by using `select`.
3675
+ *
3676
+ * ```ts
3677
+ * const value = 'new name';
3678
+ *
3679
+ * // update with SQL template string
3680
+ * const updatedCount = await db.table.find(1).updateRaw`name = ${value}`;
3681
+ *
3682
+ * // or update with `sql` function:
3683
+ * await db.table.find(1).updateRaw(db.table.sql`name = ${value}`);
3684
+ * ```
3685
+ * @param args - raw SQL via a template string or by using a `sql` method
3686
+ */
3687
+ updateRaw<T extends Query>(this: T, ...args: UpdateRawArgs<T>): UpdateResult<T>;
3688
+ _updateRaw<T extends Query>(this: T, ...args: UpdateRawArgs<T>): UpdateResult<T>;
3689
+ /**
3690
+ * To make sure that at least one row was updated use `updateOrThrow`:
3691
+ *
3692
+ * ```ts
3693
+ * import { NotFoundError } from 'pqb';
3694
+ *
3695
+ * try {
3696
+ * // updatedCount is guaranteed to be greater than 0
3697
+ * const updatedCount = await db.table
3698
+ * .where(conditions)
3699
+ * .updateOrThrow({ name: 'name' });
3700
+ *
3701
+ * // updatedRecords is guaranteed to be a non-empty array
3702
+ * const updatedRecords = await db.table
3703
+ * .where(conditions)
3704
+ * .select('id')
3705
+ * .updateOrThrow({ name: 'name' });
3706
+ * } catch (err) {
3707
+ * if (err instanceof NotFoundError) {
3708
+ * // handle error
3709
+ * }
3710
+ * }
3711
+ * ```
3712
+ *
3713
+ * @param arg - data to update records with, may have specific values, raw SQL, queries, or callbacks with sub-queries.
3714
+ */
3715
+ updateOrThrow<T extends Query>(this: T, arg: UpdateArg<T>): UpdateResult<T>;
3716
+ _updateOrThrow<T extends Query>(this: T, arg: UpdateArg<T>): UpdateResult<T>;
3717
+ /**
3718
+ * Increments a column value by the specified amount. Optionally takes `returning` argument.
3719
+ *
3720
+ * ```ts
3721
+ * // increment numericColumn column by 1, return updated records
3722
+ * const result = await db.table
3723
+ * .selectAll()
3724
+ * .where(...conditions)
3725
+ * .increment('numericColumn');
3726
+ *
3727
+ * // increment someColumn by 5 and otherColumn by 10, return updated records
3728
+ * const result2 = await db.table
3729
+ * .selectAll()
3730
+ * .where(...conditions)
3731
+ * .increment({
3732
+ * someColumn: 5,
3733
+ * otherColumn: 10,
3734
+ * });
3735
+ * ```
3736
+ *
3737
+ * @param data - name of the column to increment, or an object with columns and values to add
3738
+ */
3739
+ increment<T extends Query>(this: T, data: ChangeCountArg<T>): UpdateResult<T>;
3740
+ _increment<T extends Query>(this: T, data: ChangeCountArg<T>): UpdateResult<T>;
3741
+ /**
3742
+ * Decrements a column value by the specified amount. Optionally takes `returning` argument.
3743
+ *
3744
+ * ```ts
3745
+ * // decrement numericColumn column by 1, return updated records
3746
+ * const result = await db.table
3747
+ * .selectAll()
3748
+ * .where(...conditions)
3749
+ * .decrement('numericColumn');
3750
+ *
3751
+ * // decrement someColumn by 5 and otherColumn by 10, return updated records
3752
+ * const result2 = await db.table
3753
+ * .selectAll()
3754
+ * .where(...conditions)
3755
+ * .decrement({
3756
+ * someColumn: 5,
3757
+ * otherColumn: 10,
3758
+ * });
3759
+ * ```
3760
+ *
3761
+ * @param data - name of the column to decrement, or an object with columns and values to subtract
3762
+ */
3763
+ decrement<T extends Query>(this: T, data: ChangeCountArg<T>): UpdateResult<T>;
3764
+ _decrement<T extends Query>(this: T, data: ChangeCountArg<T>): UpdateResult<T>;
3765
+ }
3766
+
3767
+ type IsolationLevel = 'SERIALIZABLE' | 'REPEATABLE READ' | 'READ COMMITTED' | 'READ UNCOMMITTED';
3768
+ type TransactionOptions = {
3769
+ level: IsolationLevel;
3770
+ readOnly?: boolean;
3771
+ deferrable?: boolean;
3772
+ };
3773
+ declare class Transaction {
3774
+ transaction<T extends Query, Result>(this: T, cb: () => Promise<Result>): Promise<Result>;
3775
+ transaction<T extends Query, Result>(this: T, options: IsolationLevel | TransactionOptions, cb: () => Promise<Result>): Promise<Result>;
3776
+ }
3777
+
3778
+ declare module './aggregate' {
3779
+ interface SelectAggMethods<T extends Query> {
3780
+ /**
3781
+ * Give the `as` alias for the search, and it becomes possible to select a text with highlights of the matching words or phrases:
3782
+ *
3783
+ * ```ts
3784
+ * db.table
3785
+ * .search({
3786
+ * as: 'search',
3787
+ * in: 'body',
3788
+ * query: 'query',
3789
+ * })
3790
+ * .select({
3791
+ * highlightedText: (q) => q.headline('search'),
3792
+ * });
3793
+ * ```
3794
+ *
3795
+ * When searching in the generated `tsvector` column, need to provide a text source to the `headline`:
3796
+ *
3797
+ * ```ts
3798
+ * db.table
3799
+ * .search({
3800
+ * as: 'search',
3801
+ * vector: 'textVector',
3802
+ * query: 'query',
3803
+ * })
3804
+ * .select({
3805
+ * // `body` is a column name
3806
+ * highlightedText: (q) => q.headline('search', { text: 'body' }),
3807
+ * });
3808
+ * ```
3809
+ *
3810
+ * `text` can be a raw SQL, here we are joining multiple columns:
3811
+ *
3812
+ * ```ts
3813
+ * import { raw } from 'orchid-orm';
3814
+ *
3815
+ * db.table
3816
+ * .search({
3817
+ * as: 'search',
3818
+ * vector: 'titleAndBodyVector',
3819
+ * query: 'query',
3820
+ * })
3821
+ * .select({
3822
+ * highlightedText: (q) =>
3823
+ * q.headline('search', { text: raw`concat_ws(' ', title, body)` }),
3824
+ * });
3825
+ * ```
3826
+ *
3827
+ * `headline` supports a string for `options`, see details [in Postgres doc](https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-HEADLINE).
3828
+ *
3829
+ * Provide a simple string or a raw SQL:
3830
+ *
3831
+ * ```ts
3832
+ * db.table
3833
+ * .search({
3834
+ * as: 'search',
3835
+ * in: 'body',
3836
+ * query: 'query',
3837
+ * })
3838
+ * .select({
3839
+ * highlightedText: (q) =>
3840
+ * q.headline('search', {
3841
+ * options:
3842
+ * 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=<<, StopSel=>>',
3843
+ * }),
3844
+ * });
3845
+ * ```
3846
+ *
3847
+ * @param search - name of the search to use the query from
3848
+ * @param options - `text` for a text source, `options` for `ts_headline` options
3849
+ */
3850
+ headline(search: string | undefined extends T['meta']['tsQuery'] ? never : Exclude<T['meta']['tsQuery'], undefined>, options?: {
3851
+ text?: SelectableOrExpressionOfType<T, TextColumn>;
3852
+ options?: string | Expression;
3853
+ }): ColumnExpression<TextColumn>;
3854
+ }
3855
+ }
3856
+ type SearchArg<T extends QueryBase, As extends string> = {
3857
+ as?: As;
3858
+ order?: OrderTsQueryConfig;
3859
+ } & ({
3860
+ language?: string | Expression;
3861
+ } | {
3862
+ languageColumn?: keyof T['selectable'];
3863
+ }) & ({
3864
+ text: string | Expression;
3865
+ } | {
3866
+ in: MaybeArray<keyof T['selectable']> | {
3867
+ [K in keyof T['selectable']]?: SearchWeight;
3868
+ };
3869
+ } | {
3870
+ vector: {
3871
+ [K in keyof T['selectable']]: T['selectable'][K]['column']['dataType'] extends 'tsvector' ? K : never;
3872
+ }[keyof T['selectable']];
3873
+ }) & ({
3874
+ query: string | Expression;
3875
+ } | {
3876
+ plainQuery: string | Expression;
3877
+ } | {
3878
+ phraseQuery: string | Expression;
3879
+ } | {
3880
+ tsQuery: string | Expression;
3881
+ });
3882
+ type WhereSearchResult<T extends QueryBase, As extends string> = T & {
3883
+ meta: {
3884
+ tsQuery: string extends As ? never : As;
3885
+ };
3886
+ };
3887
+ declare const saveSearchAlias: (q: QueryBase, as: string) => string;
3888
+ declare class SearchMethods {
3889
+ /**
3890
+ * ## language
3891
+ *
3892
+ * By default, the search language is English.
3893
+ *
3894
+ * You can set a different default language in the `createBaseTable` config:
3895
+ *
3896
+ * ```ts
3897
+ * import { createBaseTable } from 'orchid-orm';
3898
+ *
3899
+ * export const BaseTable = createBaseTable({
3900
+ * language: 'swedish',
3901
+ * });
3902
+ * ```
3903
+ *
3904
+ * See the list of supported language configs with the SQL:
3905
+ *
3906
+ * ```sql
3907
+ * SELECT cfgname FROM pg_ts_config;
3908
+ * ```
3909
+ *
3910
+ * When performing a search, you can override the default language:
3911
+ *
3912
+ * ```ts
3913
+ * db.table.search({
3914
+ * language: 'finnish',
3915
+ * in: 'body',
3916
+ * query: 'query',
3917
+ * });
3918
+ * ```
3919
+ *
3920
+ * `language` also accepts a raw SQL.
3921
+ *
3922
+ * The language can be stored in the column of this table, then you can use `languageColumn` to use this column for the search:
3329
3923
  *
3330
3924
  * ```ts
3331
- * // returns number of updated records by default
3332
- * const updatedCount = await db.table
3333
- * .where({ name: 'old name' })
3334
- * .update({ name: 'new name' });
3925
+ * db.table.search({
3926
+ * // the table has `lang` column, use it for the search
3927
+ * languageColumn: 'lang',
3928
+ * in: 'body',
3929
+ * query: 'query',
3930
+ * });
3931
+ * ```
3335
3932
  *
3336
- * // returning only `id`
3337
- * const id = await db.table.find(1).get('id').update({ name: 'new name' });
3933
+ * ## text vector to search in
3338
3934
  *
3339
- * // `selectAll` + `find` will return a full record
3340
- * const oneFullRecord = await db.table
3341
- * .selectAll()
3342
- * .find(1)
3343
- * .update({ name: 'new name' });
3935
+ * The text to search in can be a simple string, or a raw SQL, or a text column, or multiple columns:
3344
3936
  *
3345
- * // `selectAll` + `where` will return array of full records
3346
- * const recordsArray = await db.table
3347
- * .select('id', 'name')
3348
- * .where({ id: 1 })
3349
- * .update({ name: 'new name' });
3937
+ * ```ts
3938
+ * db.table.search({
3939
+ * // search in the given string
3940
+ * text: 'simply a string to search in',
3941
+ * query: 'query',
3942
+ * });
3350
3943
  *
3351
- * await db.table.where({ ...conditions }).update({
3352
- * // set the column to a specific value
3353
- * column1: 123,
3944
+ * import { raw } from 'orchid-orm';
3354
3945
  *
3355
- * // use raw SQL to update the column
3356
- * column2: db.table.sql`2 + 2`,
3946
+ * db.table.search({
3947
+ * // raw SQL: join text columns with space
3948
+ * text: raw`concat_ws(' ', title, body)`,
3949
+ * query: 'query',
3950
+ * });
3357
3951
  *
3358
- * // use query that returns a single value
3359
- * // returning multiple values will result in Postgres error
3360
- * column3: db.otherTable.get('someColumn'),
3952
+ * db.table.search({
3953
+ * // search in a single text column
3954
+ * in: 'body',
3955
+ * query: 'query',
3956
+ * });
3361
3957
  *
3362
- * // select a single value from a related record
3363
- * fromRelation: (q) => q.relatedTable.get('someColumn'),
3958
+ * db.table.search({
3959
+ * // search in multiple columns, they are concatenated with `concat_ws` as shown above
3960
+ * in: ['title', 'body'],
3961
+ * query: 'query',
3962
+ * });
3364
3963
  *
3365
- * // set a new value to the `.foo.bar` path into a JSON column
3366
- * jsonColumn: (q) => q.jsonSet('jsonColumn', ['foo', 'bar'], 'new value'),
3964
+ * db.table.search({
3965
+ * // search in multiple columns with different weights. Weight can be A, B, C, or D
3966
+ * in: {
3967
+ * title: 'A',
3968
+ * body: 'B',
3969
+ * },
3970
+ * query: 'query',
3367
3971
  * });
3368
3972
  * ```
3369
3973
  *
3370
- * `null` value will set a column to `NULL`, but the `undefined` value will be ignored:
3974
+ * For better performance, define a [generated](/guide/migration-column-methods.html#generated) column of `tsvector` type, and use it in the search with `vector` keyword:
3371
3975
  *
3372
3976
  * ```ts
3373
- * db.table.findBy({ id: 1 }).update({
3374
- * name: null, // updates to null
3375
- * age: undefined, // skipped, no effect
3977
+ * db.table.search({
3978
+ * vector: 'titleAndBodyVector',
3979
+ * query: 'query',
3376
3980
  * });
3377
3981
  * ```
3378
3982
  *
3379
- * @param arg - data to update records with, may have specific values, raw SQL, queries, or callbacks with sub-queries.
3380
- */
3381
- update<T extends Query>(this: T, arg: UpdateArg<T>): UpdateResult<T>;
3382
- _update<T extends Query>(this: T, arg: UpdateArg<T>): UpdateResult<T>;
3383
- /**
3384
- * `updateRaw` is for updating records with raw expression.
3983
+ * ## search query
3385
3984
  *
3386
- * The behavior is the same as a regular `update` method has:
3387
- * `find` or `where` must precede calling this method,
3388
- * it returns an updated count by default,
3389
- * you can customize returning data by using `select`.
3985
+ * Read about different search queries in [this Postgres doc](https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES).
3390
3986
  *
3391
- * ```ts
3392
- * const value = 'new name';
3987
+ * `search` method can accept one of the following queries:
3393
3988
  *
3394
- * // update with SQL template string
3395
- * const updatedCount = await db.table.find(1).updateRaw`name = ${value}`;
3989
+ * - `query`: corresponds to `websearch_to_tsquery` in Postgres, good to use by default
3990
+ * - `plainQuery`: corresponds to `plainto_tsquery`
3991
+ * - `phraseQuery`: corresponds to `phraseto_tsquery`
3992
+ * - `tsQuery`: corresponds to `to_tsquery`
3396
3993
  *
3397
- * // or update with `sql` function:
3398
- * await db.table.find(1).updateRaw(db.table.sql`name = ${value}`);
3399
- * ```
3400
- * @param args - raw SQL via a template string or by using a `sql` method
3401
- */
3402
- updateRaw<T extends Query>(this: T, ...args: UpdateRawArgs<T>): UpdateResult<T>;
3403
- _updateRaw<T extends Query>(this: T, ...args: UpdateRawArgs<T>): UpdateResult<T>;
3404
- /**
3405
- * To make sure that at least one row was updated use `updateOrThrow`:
3994
+ * The `query` (`websearch_to_tsquery`) can work with any user input, while other query kinds require a specific format and will fail for invalid input.
3406
3995
  *
3407
- * ```ts
3408
- * import { NotFoundError } from 'pqb';
3996
+ * Each query kind accepts a string or a raw SQL.
3409
3997
  *
3410
- * try {
3411
- * // updatedCount is guaranteed to be greater than 0
3412
- * const updatedCount = await db.table
3413
- * .where(conditions)
3414
- * .updateOrThrow({ name: 'name' });
3998
+ * ```ts
3999
+ * import { raw } from 'orchid-orm';
3415
4000
  *
3416
- * // updatedRecords is guaranteed to be a non-empty array
3417
- * const updatedRecords = await db.table
3418
- * .where(conditions)
3419
- * .select('id')
3420
- * .updateOrThrow({ name: 'name' });
3421
- * } catch (err) {
3422
- * if (err instanceof NotFoundError) {
3423
- * // handle error
3424
- * }
3425
- * }
4001
+ * db.table.search({
4002
+ * vector: 'titleAndBodyVector',
4003
+ * // can accept raw SQL:
4004
+ * phraseQuery: raw`'The Fat Rats'`,
4005
+ * });
3426
4006
  * ```
3427
4007
  *
3428
- * @param arg - data to update records with, may have specific values, raw SQL, queries, or callbacks with sub-queries.
3429
- */
3430
- updateOrThrow<T extends Query>(this: T, arg: UpdateArg<T>): UpdateResult<T>;
3431
- _updateOrThrow<T extends Query>(this: T, arg: UpdateArg<T>): UpdateResult<T>;
3432
- /**
3433
- * Increments a column value by the specified amount. Optionally takes `returning` argument.
4008
+ * ## order by search rank
4009
+ *
4010
+ * Read about search ranking in [this Postgres doc](https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-RANKING).
4011
+ *
4012
+ * Set `order: true` to order results by the search rank:
3434
4013
  *
3435
4014
  * ```ts
3436
- * // increment numericColumn column by 1, return updated records
3437
- * const result = await db.table
3438
- * .selectAll()
3439
- * .where(...conditions)
3440
- * .increment('numericColumn');
4015
+ * db.table.search({
4016
+ * in: 'body',
4017
+ * query: 'query',
4018
+ * // will add ORDER BY ts_rank(to_tsvector('english', body)) DESC
4019
+ * order: true,
4020
+ * });
4021
+ * ```
3441
4022
  *
3442
- * // increment someColumn by 5 and otherColumn by 10, return updated records
3443
- * const result2 = await db.table
3444
- * .selectAll()
3445
- * .where(...conditions)
3446
- * .increment({
3447
- * someColumn: 5,
3448
- * otherColumn: 10,
3449
- * });
4023
+ * To order with `ts_rank_cd` instead of `ts_rank`, set `coverDensity: true`:
4024
+ *
4025
+ * ```ts
4026
+ * db.table.search({
4027
+ * in: 'body',
4028
+ * query: 'query',
4029
+ * // will add ORDER BY ts_rank_cd(to_tsvector('english', body)) DESC
4030
+ * order: {
4031
+ * coverDensity: true,
4032
+ * },
4033
+ * });
3450
4034
  * ```
3451
4035
  *
3452
- * @param data - name of the column to increment, or an object with columns and values to add
3453
- */
3454
- increment<T extends Query>(this: T, data: ChangeCountArg<T>): UpdateResult<T>;
3455
- _increment<T extends Query>(this: T, data: ChangeCountArg<T>): UpdateResult<T>;
3456
- /**
3457
- * Decrements a column value by the specified amount. Optionally takes `returning` argument.
4036
+ * Other options are:
3458
4037
  *
3459
4038
  * ```ts
3460
- * // decrement numericColumn column by 1, return updated records
3461
- * const result = await db.table
3462
- * .selectAll()
3463
- * .where(...conditions)
3464
- * .decrement('numericColumn');
4039
+ * db.table.search({
4040
+ * in: 'body',
4041
+ * query: 'query',
4042
+ * order: {
4043
+ * // weights for D, C, B, A:
4044
+ * weights: [0.1, 0.2, 0.4, 1],
4045
+ * // by default, rank ignores the document length
4046
+ * // change rank behavior by providing here a special number
4047
+ * normalization: 32,
4048
+ * // it's possible to change the order direction:
4049
+ * dir: 'ASC', // DESC by default
4050
+ * },
4051
+ * });
4052
+ * ```
3465
4053
  *
3466
- * // decrement someColumn by 5 and otherColumn by 10, return updated records
3467
- * const result2 = await db.table
3468
- * .selectAll()
3469
- * .where(...conditions)
3470
- * .decrement({
3471
- * someColumn: 5,
3472
- * otherColumn: 10,
4054
+ * Giving the `as` alias for the search allows to set the ordering in the `order` method:
4055
+ *
4056
+ * ```ts
4057
+ * db.table
4058
+ * .search({
4059
+ * as: 'search',
4060
+ * in: 'body',
4061
+ * query: 'query',
4062
+ * })
4063
+ * .order({
4064
+ * // can be `search: true` for defaults
4065
+ * search: {
4066
+ * // same options as above
4067
+ * coverDensity: true,
4068
+ * weights: [0.1, 0.2, 0.4, 1.0],
4069
+ * normalization: 32,
4070
+ * dir: 'ASC',
4071
+ * },
3473
4072
  * });
3474
4073
  * ```
3475
4074
  *
3476
- * @param data - name of the column to decrement, or an object with columns and values to subtract
4075
+ * @param arg - search config
3477
4076
  */
3478
- decrement<T extends Query>(this: T, data: ChangeCountArg<T>): UpdateResult<T>;
3479
- _decrement<T extends Query>(this: T, data: ChangeCountArg<T>): UpdateResult<T>;
3480
- }
3481
-
3482
- type IsolationLevel = 'SERIALIZABLE' | 'REPEATABLE READ' | 'READ COMMITTED' | 'READ UNCOMMITTED';
3483
- type TransactionOptions = {
3484
- level: IsolationLevel;
3485
- readOnly?: boolean;
3486
- deferrable?: boolean;
3487
- };
3488
- declare class Transaction {
3489
- transaction<T extends Query, Result>(this: T, cb: () => Promise<Result>): Promise<Result>;
3490
- transaction<T extends Query, Result>(this: T, options: IsolationLevel | TransactionOptions, cb: () => Promise<Result>): Promise<Result>;
4077
+ search<T extends Query, As extends string>(this: T, arg: SearchArg<T, As>): WhereSearchResult<T, As>;
4078
+ _search<T extends Query, As extends string>(this: T, arg: SearchArg<T, As>): WhereSearchResult<T, As>;
3491
4079
  }
3492
4080
 
3493
4081
  type UpsertCreateArg<T extends Query> = CreateData<T> | (() => CreateData<T>);
@@ -4086,37 +4674,46 @@ declare class QueryMethods<CT extends ColumnTypesBase> {
4086
4674
  distinct<T extends Query>(this: T, ...columns: SelectableOrExpression<T>[]): T;
4087
4675
  _distinct<T extends Query>(this: T, ...columns: SelectableOrExpression<T>[]): T;
4088
4676
  /**
4089
- * Find a single record by the primary key (id), adds `LIMIT 1`.
4090
- * Throws when not found.
4677
+ * The `find` method is available only for tables which has exactly one primary key.
4678
+ * And also it can accept raw SQL template literal, then the primary key is not required.
4679
+ *
4680
+ * Find record by id, throw [NotFoundError](/guide/error-handling.html) if not found:
4091
4681
  *
4092
4682
  * ```ts
4093
- * const result: TableType = await db.table.find(123);
4683
+ * await db.table.find(1);
4094
4684
  * ```
4095
4685
  *
4096
- * @param args - primary key value to find by
4686
+ * ```ts
4687
+ * await db.user.find`
4688
+ * age = ${age} AND
4689
+ * name = ${name}
4690
+ * `;
4691
+ * ```
4692
+ *
4693
+ * @param args - primary key value to find by, or a raw SQL
4097
4694
  */
4098
4695
  find<T extends Query>(this: T, ...args: FindArgs<T>): SetQueryReturnsOne<WhereResult<T>>;
4099
4696
  _find<T extends Query>(this: T, ...args: FindArgs<T>): SetQueryReturnsOne<WhereResult<T>>;
4100
4697
  /**
4101
- * Find a single record by the primary key (id), adds `LIMIT 1`.
4698
+ * Find a single record by the primary key (id), adds `LIMIT 1`, can accept a raw SQL.
4102
4699
  * Returns `undefined` when not found.
4103
4700
  *
4104
4701
  * ```ts
4105
4702
  * const result: TableType | undefined = await db.table.find(123);
4106
4703
  * ```
4107
4704
  *
4108
- * @param args - primary key value to find by
4705
+ * @param args - primary key value to find by, or a raw SQL
4109
4706
  */
4110
4707
  findOptional<T extends Query>(this: T, ...args: FindArgs<T>): SetQueryReturnsOneOptional<WhereResult<T>>;
4111
4708
  _findOptional<T extends Query>(this: T, ...args: FindArgs<T>): SetQueryReturnsOneOptional<WhereResult<T>>;
4112
4709
  /**
4113
4710
  * The same as `where(conditions).take()`, it will filter records and add a `LIMIT 1`.
4114
- * Throws when not found.
4711
+ * Throws `NotFoundError` if not found.
4115
4712
  *
4116
4713
  * ```ts
4117
- * const result: TableType = await db.table.findBy({
4118
- * key: 'value',
4119
- * });
4714
+ * const result: TableType = await db.table.findBy({ key: 'value' });
4715
+ * // is equivalent to:
4716
+ * db.table.where({ key: 'value' }).take()
4120
4717
  * ```
4121
4718
  *
4122
4719
  * @param args - `where` conditions
@@ -4267,6 +4864,15 @@ declare class QueryMethods<CT extends ColumnTypesBase> {
4267
4864
  */
4268
4865
  offset<T extends Query>(this: T, arg: number | undefined): T;
4269
4866
  _offset<T extends Query>(this: T, arg: number | undefined): T;
4867
+ /**
4868
+ * Use `exists()` to check if there is at least one record-matching condition.
4869
+ *
4870
+ * It will discard previous `select` statements if any. Returns a boolean.
4871
+ *
4872
+ * ```ts
4873
+ * const exists: boolean = await db.table.where(...conditions).exists();
4874
+ * ```
4875
+ */
4270
4876
  exists<T extends Query>(this: T): SetQueryReturnsColumn<T, BooleanColumn>;
4271
4877
  _exists<T extends Query>(this: T): SetQueryReturnsColumn<T, BooleanColumn>;
4272
4878
  /**