import { Adapter, AdapterClass, AdapterConfigBase, AdapterParams, AdapterSchemaConfigOptions, AfterCommitStandaloneHook, AfterHook, ArrayColumn, ArrayColumnValue, ArrayData, AsyncState, AsyncStateStorage, BaseNumberData, BigIntColumn, BigSerialColumn, BitColumn, BitVaryingColumn, BooleanColumn, BoxColumn, BrandColumn, BrandColumnsShape, ByteaColumn, CidrColumn, CircleColumn, CitextColumn, Code, Codes, Column, ColumnFromDbParams, ColumnRefExpression, ColumnSchemaConfig, ColumnSchemaGetterColumns, ColumnSchemaGetterTableClass, ColumnToCodeCtx, ColumnTypeSchemaArg, ColumnsByType, ColumnsShape, ComputedColumnsFromOptions, ComputedOptionsConfig, ComputedOptionsFactory, CreateCtx, CreateData, CreateManyMethodsNames, CreateMethodsNames, CreateSelf, CustomTypeColumn, DateColumn, DateColumnData, DateColumnInput, DbDomainArg, DbExtension, DbOptions, DbResult, DbSharedOptions, DbSqlMethod, DbStructureDomainsMap, DbTableOptionScopes, DbTableOptions, DecimalColumn, DecimalColumnData, DefaultColumnTypes, DefaultPrivileges, DefaultSchemaConfig, DeleteMethodsNames, DomainColumn, DoublePrecisionColumn, DriverAdapter, DynamicRawSQL, EmptyObject, EmptyTuple, EnumColumn, Expression, ExpressionData, FromArg, FromResult, GeneratorIgnore, HookSelectValue, InetColumn, IntegerColumn, IntervalColumn, IsQuery, IsolationLevel, JSONColumn, JSONTextColumn, JoinedShapes, LineColumn, LsegColumn, MacAddr8Column, MacAddrColumn, MapTableScopesOption, MaybeArray, MaybePromise, MergeQuery, MoneyColumn, NoPrimaryKeyOption, NonUniqDataItem, NumberColumnData, Operators, OperatorsArray, OperatorsDate, OperatorsJson, OperatorsNumber, OperatorsOrdinalText, OperatorsText, Ord, PathColumn, PickQueryInputType, PickQueryInternal, PickQueryQ, PickQueryRelations, PickQuerySelectableRelations, PickQueryShape, PointColumn, PolygonColumn, PostgisGeographyPointColumn, QueryAfterHook, QueryBeforeActionHook, QueryBeforeHook, QueryCatch, QueryData, QueryHasWhere, QueryHookUtils, QueryHooks, QueryInternal, QueryLogObject, QueryLogOptions, QueryLogger, QueryManyTake, QueryManyTakeOptional, QueryOrExpression, QueryResult, QueryResultRow, QueryReturnType, QuerySchema, QueryScopes, QueryTake, QueryThenShallowSimplify, RawSql, RawSqlBase, RealColumn, RecordKeyTrue, RecordOptionalString, RecordString, RecordStringOrNumber, RecordUnknown, RelationConfigBase, RelationJoinQuery, RelationsBase, Rls, RlsPolicy, SchemaConfigFnWithOptions, SearchWeight, SelectAs, SelectAsFnReturnType, SelectResultObj, SelectSqlColumn, SelectableFromShape, SerialColumn, SerialColumnData, ShallowSimplify, ShapeUniqueColumns, SingleSql, SingleSqlItem, SmallIntColumn, SmallSerialColumn, Sql, SqlFn, SqlSessionState, StaticSQLArgs, StorageOptions, StringColumn, StringData, TableData, TableDataFn, TableDataInput, TableDataItem, TableDataItemsUniqueColumnTuples, TableDataItemsUniqueColumns, TableDataItemsUniqueConstraints, TableDataMethods, TemplateLiteralArgs, TextColumn, TimeColumn, TimestampColumn, TimestampTZColumn, Timestamps, ToSQLCtx, ToSqlValues, TransactionAdapter, TransactionAdapterClass, TransactionOptions, TsQueryColumn, TsVectorColumn, UUIDColumn, UniqueConstraints, UniqueTableDataItem, UnknownColumn, UpdateData, UpsertData, UpsertThis, ValExpression, VarCharColumn, VirtualColumn, WhereArg, XMLColumn, _appendQuery, _appendQueryOnUpsertCreate, _clone, _createDbSqlMethod, _hookSelectColumns, _initQueryBuilder, _onUpsertUpdate, _orCreate, _prependWith, _prependWithOnUpsertCreate, _queryCreate, _queryCreateMany, _queryCreateManyFrom, _queryDefaults, _queryDelete, _queryFindBy, _queryFindByOptional, _queryHookAfterCreate, _queryHookAfterUpdate, _queryInsert, _queryInsertForEachFrom, _queryInsertMany, _queryJoinOn, _queryRows, _querySelect, _queryTake, _queryTakeOptional, _queryUpdate, _queryUpdateOrThrow, _queryUpsert, _queryWhere, _queryWhereExists, _queryWhereIn, addCode, addTopCte, addTopCteSql, applyMixins, assignDbDataToColumn, backtickQuote, cloneQueryBaseUnscoped, codeToString, colors, columnsShapeToCode, constraintInnerToCode, constraintToCode, consumeColumnName, deepCompare, defaultSchemaConfig, emptyArray, emptyObject, escapeForMigration, escapeString, excludeInnerToCode, excludeToCode, exhaustive, getCallerFilePath, getClonedQueryData, getColumnBaseType, getColumnTypes, getDateAsDateFn, getDateAsNumberFn, getDriverErrorCode, getFreeAlias, getFreeSetAlias, getImportPath, getPrimaryKeys, getQueryAs, getQuerySchema, getShapeFromSelect, getSqlText, getStackTrace, getSupportedDefaultPrivileges, indexInnerToCode, indexToCode, internalSchemaConfig, isExpression, isQueryReturnsAll, isRawSQL, isRelationCondition, logColors, logParamToLogObject, makeColumnNullable, makeColumnTypes, makeColumnsByType, makeConnectRetryConfig, markRelationConditions, noop, objectHasValues, omit, parseTableData, parseTableDataInput, pathToLog, pick, pluralize, prepareSubQueryForSql, primaryKeyInnerToCode, pushQueryOnForOuter, pushQueryValueImmutable, pushTableDataCode, queryToSql, quoteIdentifier, quoteObjectKey, quoteTableWithSchema, raw, rawSqlToCode, rawSqlToSql, referencesArgsToCode, returnArg, setColumnData, setColumnEncode, setColumnParse, setColumnParseNull, setCurrentColumnName, setDataValue, setDefaultLanguage, setFreeAlias, setQueryObjectValueImmutable, singleQuote, sqlToRawSql, tableDataMethods, toArray, toCamelCase, toPascalCase, toSnakeCase, wrapAdapterFnWithConnectRetry } from "./index.d.ts"; import "node:util"; import "tagged-tag"; type UnionToIntersection = (U extends any ? (x: U) => void : never) extends ((x: infer I) => void) ? I : never; type MaybeArray$1 = T | T[]; type MaybePromise$1 = T | Promise; interface FnUnknownToUnknown { (a: unknown): unknown; } interface RecordString$1 { [K: string]: string; } interface RecordOptionalString$1 { [K: string]: string | undefined; } interface RecordUnknown$1 { [K: string]: unknown; } type ShallowSimplify$1 = T extends any ? { [K in keyof T]: T[K]; } : T; type EmptyObject$1 = {}; type EmptyTuple$1 = []; interface RelationJoinQuery$1 { (joiningQuery: IsQuery$1, baseQuery: IsQuery$1): IsQuery$1; } interface RelationConfigQuery extends PickQueryResult, PickQuerySelectable, PickQueryShape$1, PickQueryTable, PickQueryAs, PickQueryRelations$1, PickQueryReturnType {} interface RelationConfigBase$1 extends IsQuery$1 { returnsOne: boolean; required?: unknown; query: RelationConfigQuery; joinQuery: RelationJoinQuery$1; reverseJoin: RelationJoinQuery$1; params: unknown; queryRelated(params: unknown): unknown; modifyRelatedQuery?(relatedQuery: IsQuery$1): (query: IsQuery$1) => void; omitForeignKeyInCreate: PropertyKey; dataForUpdate: unknown; dataForUpdateOne: unknown; primaryKeys: string[]; } interface RelationConfigDataForCreate { columns: PropertyKey; nested: RecordUnknown$1; } interface RelationsBase$1 { [relationName: string]: RelationConfigBase$1; } interface RelationsDataForCreateBase { [relationName: string]: unknown; } interface RelationsDataForCreateOptionalBase { [relationName: string]: unknown; } type RelationQueryMaybeSingle = T['returnsOne'] extends true ? T['required'] extends true ? QueryManyTake$1 : QueryManyTakeOptional$1 : T['query']; interface SubQueryForSql extends ToSQLQuery { __forSql: true; } interface HasBeforeAndBeforeSet { before?: QueryBeforeHook$1[]; beforeSet?: QueryData$1['beforeSet']; } interface ColumnsShape$1 { [K: string]: Column$1; } declare namespace ColumnsShape$1 { export type DefaultSelectKeys = { [K in keyof S]: S[K]['data']['explicitSelect'] extends true | undefined ? never : K; }[keyof S]; export type DefaultOutput = { [K in DefaultSelectKeys]: Set[K]['__outputType']; }; export type Input = { [K in Exclude]: Shape[K]['__inputType']; } & { [K in Exclude]?: Shape[K]['__inputType']; }; export type InputPartial = { [K in keyof Shape]?: Shape[K]['__inputType']; }; export type Output = { [K in keyof Shape]: Shape[K]['__outputType']; }; export type DefaultSelectOutput = { [K in { [K in keyof Shape]: Shape[K]['data']['explicitSelect'] extends true | undefined ? never : K; }[keyof Shape]]: Shape[K]['__outputType']; }; export interface MapToObjectColumn { dataType: 'object'; __type: { [K in keyof Shape]: Shape[K]['__type']; }; __outputType: ShallowSimplify$1>; __queryType: { [K in keyof Shape]: Shape[K]['__queryType']; }; operators: OperatorsAny; } export interface MapToNullableObjectColumn { dataType: 'object'; __type: { [K in keyof Shape]: Shape[K]['__type']; }; __outputType: ShallowSimplify$1> | undefined; __queryType: { [K in keyof Shape]: Shape[K]['__queryType']; } | null; operators: OperatorsAny; } export interface MapToPluckColumn { dataType: 'array'; __type: Shape['pluck']['__type'][]; __outputType: Shape['pluck']['__outputType'][]; __queryType: Shape['pluck']['__queryType'][]; operators: OperatorsAny; } export interface MapToObjectArrayColumn { dataType: 'array'; __type: { [K in keyof Shape]: Shape[K]['__type']; }[]; __outputType: ShallowSimplify$1>[]; __queryType: { [K in keyof Shape]: Shape[K]['__queryType']; }[]; operators: OperatorsAny; } type ObjectOutput = { [K in keyof Shape]: Shape[K]['__outputType']; }; export {}; } declare abstract class OrchidOrmError extends Error {} declare class OrchidOrmInternalError extends Error { #private; data?: RecordUnknown$1 | undefined; constructor(query: IsQuery$1, message?: string, data?: RecordUnknown$1 | undefined); getQuery(): Query; } type QueryErrorName = 'parseComplete' | 'bindComplete' | 'closeComplete' | 'noData' | 'portalSuspended' | 'replicationStart' | 'emptyQuery' | 'copyDone' | 'copyData' | 'rowDescription' | 'parameterDescription' | 'parameterStatus' | 'backendKeyData' | 'notification' | 'readyForQuery' | 'commandComplete' | 'dataRow' | 'copyInResponse' | 'copyOutResponse' | 'authenticationOk' | 'authenticationMD5Password' | 'authenticationCleartextPassword' | 'authenticationSASL' | 'authenticationSASLContinue' | 'authenticationSASLFinal' | 'error' | 'notice'; declare abstract class QueryError extends OrchidOrmInternalError { #private; message: string; length?: number; name: QueryErrorName; stack: string | undefined; code: string | undefined; detail: string | undefined; severity: string | undefined; hint: string | undefined; position: string | undefined; internalPosition: string | undefined; internalQuery: string | undefined; where: string | undefined; schema: string | undefined; table: string | undefined; column: string | undefined; dataType: string | undefined; constraint: string | undefined; file: string | undefined; line: string | undefined; routine: string | undefined; get isUnique(): boolean; get columns(): { [K in keyof T["shape"]]?: true | undefined; }; } declare class CannotMutateReadOnlyTableError extends OrchidOrmInternalError { constructor(query: IsQuery$1); } type HookPurpose = 'Create' | 'Update' | 'Delete'; interface HasCteHooks { cteHooks?: CteHooks; } interface CteHooks { hasSelect?: boolean; tableHooks?: CteTableHooks; ensureCount?: EnsureCount; } interface EnsureCount { [cteName: string]: EnsureCountItem; } type EnsureCountItem = { count: number; message?: string; } | { jsonNotNull: string; message?: string; }; interface CteTableHooks { [K: string]: CteTableHook; } interface CteTableHook { table: string; shape: Column$1.Shape.Data; tableHook: TableHook; throwOnNotFound?: boolean; } interface TableHook { hookPurpose?: HookPurpose; select?: HookSelect; afterCreate?: QueryAfterHook$1[]; afterUpdate?: QueryAfterHook$1[]; afterSave?: QueryAfterHook$1[]; afterDelete?: QueryAfterHook$1[]; afterCreateCommit?: QueryAfterHook$1[]; afterUpdateCommit?: QueryAfterHook$1[]; afterSaveCommit?: QueryAfterHook$1[]; afterDeleteCommit?: QueryAfterHook$1[]; } type HookSelect = Map; interface HookSelectValue$1 { select: string | { sql: string; }; as?: string; temp?: string; onAs?: ((as: string) => void)[]; notLoaded?: boolean; } interface HasTableHook { tableHook?: TableHook; } interface HasHookSelect { hookSelect?: HookSelect; } interface SqlJoinExpression extends Expression$1, ExpressionTypeMethod {} declare class SqlJoinExpression extends Expression$1 { items: readonly unknown[]; separator?: RawSqlBase$1 | undefined; result: { value: T; }; q: ExpressionData$1; constructor(items: readonly unknown[], separator?: RawSqlBase$1 | undefined); makeSQL(ctx: ToSqlValues$1, quotedAs?: string): string; } /** * Expression for a SQL identifier reference. * Used to safely quote identifiers in raw SQL queries. */ declare class SqlRefExpression extends Expression$1 { name: string; result: { value: Column$1.Pick.QueryColumn; }; q: ExpressionData$1; constructor(name: string); makeSQL(): string; } declare class ValExpression$1 extends Expression$1 { value: unknown; result: { value: Column$1.Pick.QueryColumnOfType; }; q: ExpressionData$1; constructor(value: unknown); makeSQL(ctx: ToSqlValues$1): string; } interface PostgresInterval { years: number; months: number; days: number; hours: number; minutes: number; seconds: number; milliseconds: number; } interface ColumnSchemaGetterTableClass$1 { data?: { table: string | undefined; name: string | undefined; }; prototype: { columns: { shape: Column$1.Shape.ForValidation; }; }; inputSchema(): unknown; querySchema(): unknown; pkeySchema(): unknown; createSchema(): unknown; } interface ColumnTypeSchemaArg$1 { __schemaType: unknown; nullable: unknown; encode: unknown; parse: unknown; parseNull: unknown; asType: unknown; narrowType: unknown; narrowAllTypes: unknown; error?: unknown; } interface ColumnSchemaConfig$1 extends ColumnTypeSchemaArg$1 { intervalParse?(input: unknown): PostgresInterval; dateAsNumber: unknown; dateAsDate: unknown; enum: unknown; array: unknown; boolean(): unknown; buffer(): unknown; unknown(): unknown; never(): unknown; stringSchema(): unknown; stringMin(max: number): unknown; stringMax(max: number): unknown; stringMinMax(min: number, max: number): unknown; number(): unknown; int(): unknown; stringNumberDate(): unknown; timeInterval(): unknown; bit(max?: number): unknown; uuid(): unknown; json(): T; jsonText(): T; inputSchema(this: ColumnSchemaGetterTableClass$1): unknown; outputSchema(this: ColumnSchemaGetterTableClass$1): unknown; querySchema(this: ColumnSchemaGetterTableClass$1): unknown; createSchema(this: ColumnSchemaGetterTableClass$1): unknown; updateSchema(this: ColumnSchemaGetterTableClass$1): unknown; pkeySchema(this: ColumnSchemaGetterTableClass$1): unknown; smallint(): T; integer(): T; real(): T; smallSerial(): T; serial(): T; bigint(): T; decimal(precision?: number, scale?: number): T; doublePrecision(): T; bigSerial(): T; money(): T; varchar(limit?: number): T; text(): T; string(limit?: number): T; citext(): T; date(): T; timestampNoTZ(precision?: number): T; timestamp(precision?: number): T; geographyPointSchema(): unknown; } type SimpleJoinItemNonSubQueryArgs = [{ [K: string]: string | Expression$1; } | Expression$1 | true] | [leftColumn: string | Expression$1, rightColumn: string | Expression$1] | [leftColumn: string | Expression$1, op: string, rightColumn: string | Expression$1]; type JoinItemArgs = { u?: true; x: RawSql$1; } | { u?: true; c?: Column$1.QueryColumns; l: SubQueryForSql; a: string; i?: boolean; } | { u?: true; c?: Column$1.QueryColumns; j: IsQuery$1; s: boolean; r?: IsQuery$1; } | { u?: true; c?: Column$1.QueryColumns; w: string; r: IsQuery$1; s: boolean; } | { u?: true; c?: Column$1.QueryColumns; w: string; a: SimpleJoinItemNonSubQueryArgs; } | { u?: true; c?: Column$1.QueryColumns; q: IsQuery$1; s: boolean; } | { u?: true; c?: Column$1.QueryColumns; q: IsQuery$1; r: IsQuery$1; s: boolean; } | { u?: true; c?: Column$1.QueryColumns; q: IsQuery$1; a: SimpleJoinItemNonSubQueryArgs; s: boolean; } | { u?: true; c: Column$1.Shape.Data; a: string; d: RecordUnknown$1[]; }; interface JoinItem { type: string; args: JoinItemArgs; } type WithSelectable = keyof W['shape'] | `${W['table']}.${keyof W['shape'] & string}`; /** * The first argument of all `join` and `joinLateral` methods. * See argument of {@link join}. */ type JoinFirstArg = PickQueryResultAs | keyof T['relations'] | keyof T['withData'] | ((q: { [K in keyof T['relations']]: T['relations'][K]['query']; }) => PickQueryResultAs) | FnPickQueryResultAs; interface FnPickQueryResultAs { (): PickQueryResultAs; } /** * Arguments of `join` methods (not `joinLateral`). * See {@link join} */ type JoinArgs> = Arg extends PickQueryResultAs ? [conditions: { [K in JoinSelectable]: keyof T['__selectable'] | Expression$1; } | Expression$1] | [leftColumn: JoinSelectable | Expression$1, rightColumn: keyof T['__selectable'] | Expression$1] | [leftColumn: JoinSelectable | Expression$1, op: string, rightColumn: keyof T['__selectable'] | Expression$1] : Arg extends keyof T['withData'] ? JoinWithArgs : EmptyTuple$1; /** * Column names of the joined table that can be used to join. * Derived from 'result', not from 'shape', * because if the joined table has a specific selection, it will be wrapped like: * ```sql * JOIN (SELECT something FROM joined) joined ON joined.something = ... * ``` * And the selection becomes available to use in the `ON` and to select from the joined table. */ type JoinSelectable = keyof Q['result'] | `${Q['__as']}.${keyof Q['result'] & string}`; type JoinWithArgs = [conditions: { [K in WithSelectable]: keyof T['__selectable'] | Expression$1; } | Expression$1] | [leftColumn: WithSelectable | Expression$1, rightColumn: keyof T['__selectable'] | Expression$1] | [leftColumn: WithSelectable | Expression$1, op: string, rightColumn: keyof T['__selectable'] | Expression$1]; type JoinResultRequireMain = { [K in keyof T]: K extends '__selectable' ? T['__selectable'] & JoinedSelectable : T[K]; }; /** * Result of all `join` methods, not `joinLateral`. * Adds joined table columns from its 'result' to the '__selectable' of the query. */ type JoinResult = RequireMain extends true ? { [K in keyof T]: K extends '__selectable' ? T['__selectable'] & Joined['__selectable'] : K extends 'relations' ? { [K in keyof T['relations'] | keyof Joined['relations']]: K extends keyof Joined['relations'] ? Joined['relations'][K] : T['relations'][K]; } : T[K]; } : { [K in keyof T]: K extends '__selectable' ? { [K in keyof T['__selectable']]: { as: T['__selectable'][K]['as']; column: Column$1.QueryColumnToNullable; }; } & Joined['__selectable'] : K extends 'result' ? { [K in keyof T['result']]: Column$1.QueryColumnToNullable; } : K extends 'then' ? QueryThenByQuery; }> : K extends 'relations' ? { [K in keyof T['relations'] | keyof Joined['relations']]: K extends keyof Joined['relations'] ? Joined['relations'][K] : T['relations'][K]; } : T[K]; }; /** * Calls {@link JoinResult} with either callback result, if join has a callback, * or with a query derived from the first join argument. */ type JoinResultFromArgs = JoinResult['result'], ReturnType['__as'], ReturnType['relations'], RequireJoined> : Arg extends PickQueryHasSelectResultShapeAsRelations ? JoinResultSelectable : Arg extends keyof T['relations'] ? JoinResultSelectable : Arg extends FirstArgCallback ? JoinResultSelectable['shape'], ReturnType['__as'], ReturnType['relations'], RequireJoined> : Arg extends keyof T['withData'] ? T['withData'][Arg] extends WithDataItem ? JoinResultSelectable : never : never, RequireMain>; interface GenericJoinCallback { (...args: any[]): PickQueryResultAsRelations; } interface FirstArgCallback { (...args: any[]): PickQueryShapeAsRelations; } /** * Result of all `joinLateral` methods. * Adds joined table columns from its 'result' to the '__selectable' of the query. * * @param T - query type to join to * @param Arg - first arg of join, see {@link JoinFirstArg} * @param RequireJoined - when false, joined table shape will be mapped to make all columns optional */ type JoinLateralResult = JoinAddSelectable>; /** * Build `selectable` type for joined table. * * When `RequireJoined` parameter is false, * the result type of the joined table will be mapped to make all columns optional. * * Callback may override the joined table alias. * * The resulting selectable receives all joined table columns prefixed with the table name or alias, * and a star prefixed with the table name or alias to select all joined columns. */ type JoinResultSelectable = RequireJoined extends true ? { __selectable: { [K in '*' | (keyof Result & string) as `${As}.${K}`]: K extends '*' ? { as: As; column: ColumnsShape$1.MapToObjectColumn; } : { as: K; column: Result[K]; }; }; relations: { [K in keyof JoinedRelations & string as `${As}.${K}`]: JoinedRelations[K]; }; } : { __selectable: { [K in '*' | (keyof Result & string) as `${As}.${K}`]: K extends '*' ? { as: As; column: ColumnsShape$1.MapToNullableObjectColumn; } : { as: K; column: Column$1.QueryColumnToNullable; }; }; relations: { [K in keyof JoinedRelations & string as `${As}.${K}`]: JoinedRelations[K]; }; }; type JoinAddSelectable = { [K in keyof T]: K extends '__selectable' ? T['__selectable'] & Joined['__selectable'] : T[K]; }; /** * Map the first argument of `join` or `joinLateral` to a query type. * * `with` table arg is mapped into `QueryBase`, * query arg is returned as is, * relation name is replaced with a relation table. */ type JoinArgToQuery> = Arg extends keyof T['withData'] ? T['withData'][Arg] extends WithDataItem ? { [K in 'result' | '__as' | keyof T]: K extends '__as' ? T['withData'][Arg]['table'] : K extends '__selectable' ? { [K in keyof T['withData'][Arg]['shape'] & string as `${T['withData'][Arg]['table']}.${K}`]: { as: K; column: T['withData'][Arg]['shape'][K]; }; } : K extends 'result' ? T['withData'][Arg]['shape'] : K extends keyof T ? T[K] : never; } : never : Arg extends PickQuerySelectableResultAs ? Arg : Arg extends keyof T['relations'] ? T['relations'][Arg]['query'] : Arg extends JoinArgToQueryCallback ? ReturnType : never; interface JoinArgToQueryCallback { (...args: any[]): IsQuery$1; } /** * Type of the `join` callback (not `joinLateral`). * * Receives a query builder that can access columns of both the main and the joined table. * * The query builder is limited to `or` and `where` methods only. * * Callback must return a query builder. */ interface JoinCallback> { (q: JoinQueryBuilder>): IsQuery$1; } type JoinCallbackArgs> = [cb?: JoinCallback | true]; declare class QueryJoin { /** * ## Select relation * * Before joining a table, consider if selecting a relation is enough for your case: * * ```ts * // select users with profiles * // result type is Array<{ name: string, profile: Profile }> * await db.user.select('name', { * profile: (q) => q.profile, * }); * * // select posts with counts of comments, filter and order by comments count * // result type is Array * await db.post * .select('*', { * commentsCount: (q) => q.comments.count(), * }) * .where({ commentsCount: { gt: 10 } }) * .order({ commentsCount: 'DESC' }); * * // select authors with array of their book titles * // result type is Array * await db.author.select('*', { * books: (q) => q.books.pluck('title'), * }); * ``` * * Internally, such selects will use `LEFT JOIN LATERAL` to join a relation. * If you're loading users with profiles (one-to-one relation), and some users don't have a profile, `profile` property will have `NULL` for such users. * If you want to load only users that have profiles, and filter out the rest, add `.join()` method to the relation without arguments: * * ```ts * // load only users who have a profile * await db.user.select('*', { * profile: (q) => q.profile.join(), * }); * * // load only users who have a specific profile * await db.user.select('*', { * profile: (q) => q.profile.join().where({ age: { gt: 20 } }), * }); * ``` * * You can also use this `.join()` method on the one-to-many relations, and records with empty array will be filtered out: * * ```ts * // posts that have no tags won't be loaded * // result type is Array * db.post.select('*', { * tags: (q) => q.tags.join(), * }); * ``` * * # join * * `join` methods allows to join other tables, relations by name, [with](/guide/advanced-queries#with) statements, sub queries. * * All the `join` methods accept the same arguments, but returning type is different because with `join` it's guaranteed to load joined table, and with `leftJoin` the joined table columns may be `NULL` when no matching record was found. * * For the following examples, imagine you have a `User` table with `id` and `name`, and `Message` table with `id`, `text`, messages belongs to user via `userId` column: * * ```ts * export const UserTable = defineTable('user', (t) => ({ * id: t.identity().primaryKey(), * name: t.text(), * })).relations((user) => ({ * messages: user('id').hasMany(() => MessageTable('userId')), * })); * * export const MessageTable = defineTable('message', (t) => ({ * id: t.identity().primaryKey(), * userId: t.integer(), * text: t.text(), * ...t.timestamps(), * })).relations((message) => ({ * user: message('userId').belongsTo(() => UserTable('id')), * })); * ``` * * `join` is a method for SQL `JOIN`, which is equivalent to `INNER JOIN`, `LEFT INNERT JOIN`. * * When no matching record is found, it will skip records of the main table. * * ### join relation * * When relations are defined between the tables, you can join them by a relation name. * Joined table can be references from `where` and `select` by a relation name. * * ```ts * const result = await db.user * .join('messages') * // after joining a table, you can use it in `where` conditions: * .where({ 'messages.text': { startsWith: 'Hi' } }) * .select( * 'name', // name is User column, table name may be omitted * 'messages.text', // text is the Message column, and the table name is required * ); * * // result has the following type: * const ok: { name: string; text: string }[] = result; * ``` * * The first argument can also be a callback, where instead of relation name as a string you're picking it as a property of `q`. * In such a way, you can alias the relation with `as`, add `where` conditions, use other query methods. * * ```ts * const result = await db.user.join((q) => * q.messages.as('m').where({ text: 'some text' }), * ); * ``` * * Optionally, you can pass a second callback argument, it makes `on` and `orOn` methods available. * * But remember that when joining a relation, the relevant `ON` conditions are already handled automatically. * * ```ts * const result = await db.user.join( * (q) => q.messages.as('m'), * (q) => * q * .on('messages.text', 'user.name') // additionally, match message with user name * .where({ text: 'some text' }), // you can add `where` in a second callback as well. * ); * ``` * * ### join a relation of the joined * * After joining a relation or a table: * * ```ts * db.post.join('comments'); * * db.post.join(() => db.comment); * ``` * * You can join a relation of that joined table: * * ```ts * db.post.join('comments').join('comments.author'); * * db.post.join(() => db.comment).join('comment.author'); * ``` * * Note that in the first case it's `comments` - a relation name, while in the second case it is a table name. * * ### joins deduplication * * When joining the same table with the same condition more than once, duplicated joins will be ignored: * * ```ts * // joining a relation * db.post.join('comments').join('comments'); * * // joining a table with a condition * db.post * .join('comments', 'comments.postId', 'post.id') * .join('comments', 'comments.postId', 'post.id'); * ``` * * Both queries will produce SQL with only 1 join * * ```sql * SELECT * FROM post JOIN comments ON comments.postId = post.id * ``` * * However, this is only possible if the join has no dynamic values: * * ```ts * db.post * .join('comments', (q) => q.where({ rating: { gt: 5 } })) * .join('comments', (q) => q.where({ rating: { gt: 5 } })); * ``` * * Both joins above have the same `{ gt: 5 }`, but still, the `5` is a dynamic value and in this case joins will be duplicated, * resulting in a database error. * * ### select full joined records * * `select` supports selecting a full record of a previously joined table by passing a table name with `.*` at the end: * * ```ts * const result = await db.book.join('author').select('title', { * author: 'author.*', * }); * * // result has the following type: * const ok: { * // title of the book * title: string; * // a full author record is included: * author: { id: number; name: string; updatedAt: Date; createdAt: Date }; * }[] = result; * ``` * * It works fine for `1:1` (`belongsTo`, `hasOne`) relations, but it may have an unexpected result for `1:M` or `M:M` (`hasMany`, `hasAndBelongsToMany`) relations. * For any kind of relation, it results in one main table record with data of exactly one joined table record, i.e. when selecting in this way, the records **won't** be collected into arrays. * * ```ts * const result = await db.user * .join('messages') * .where({ 'messages.text': { startsWith: 'Hi' } }) * .select('name', { messages: 'messages.*' }); * * // result has the following type: * const ok: { * name: string; * // full message is included: * messages: { id: number; text: string; updatedAt: Date; createdAt: Date }; * }[] = result; * ``` * * Because it's a one-to-many relation, one user has many messages, the user data will be duplicated for different messages data: * * | name | msg | * | ------ | ------------------------------ | * | user 1 | `{ id: 1, text: 'message 1' }` | * | user 1 | `{ id: 2, text: 'message 2' }` | * | user 1 | `{ id: 3, text: 'message 3' }` | * * ### join table * * If relation wasn't defined, provide a `db.table` instance and specify columns for the join. * Joined table can be references from `where` and `select` by a table name. * * ```ts * db.user * .join(db.message, 'userId', 'user.id') * .where({ 'message.text': { startsWith: 'Hi' } }) * .select('name', 'message.text'); * ``` * * The name of the joining table can be omitted, but not the name of the main table: * * ```ts * db.user.join(db.message, 'userId', 'user.id'); * ``` * * Joined table can have an alias for referencing it further: * * ```ts * db.user * .join(db.message.as('m'), 'message.userId', 'user.id') * .where({ 'm.text': { startsWith: 'Hi' } }) * .select('name', 'm.text'); * ``` * * Joined table can be selected as an object as well as the relation join above: * * ```ts * const result = await db.user * .join(db.message.as('m'), 'message.userId', 'user.id') * .where({ 'm.text': { startsWith: 'Hi' } }) * .select('name', { msg: 'm.*' }); * * // result has the following type: * const ok: { * name: string; * // full message is included as msg: * msg: { id: number; text: string; updatedAt: Date; createdAt: Date }; * }[] = result; * ``` * * You can provide a custom comparison operator * * ```ts * db.user.join(db.message, 'userId', '!=', 'user.id'); * ``` * * Join can accept raw SQL for the `ON` part of join: * * ```ts * db.user.join( * db.message, * // `sql` can be imported from your table factory file * sql`lower("message"."text") = lower("user"."name")`, * ); * ``` * * Join can accept raw SQL instead of columns: * * ```ts * db.user.join( * db.message, * sql`lower("message"."text")`, * sql`lower("user"."name")`, * ); * * // with operator: * db.user.join( * db.message, * sql`lower("message"."text")`, * '!=', * sql`lower("user"."name")`, * ); * ``` * * To join based on multiple columns, you can provide an object where keys are joining table columns, and values are main table columns or a raw SQL: * * ```ts * db.user.join(db.message, { * 'message.userId': 'user.id', * * // joined table name may be omitted * userId: 'user.id', * * // value can be a raw SQL expression: * text: sql`lower("user"."name")`, * }); * ``` * * Join all records without conditions by providing `true`: * * ```ts * db.user.join(db.message, true); * ``` * * Join methods can accept a callback with a special query builder that has `on` and `orOn` methods for handling advanced cases: * * ```ts * db.user.join( * db.message, * (q) => * q * .on('message.userId', 'user.id') * // joined table name may be omitted * .on('userId', 'user.id') * // operator can be specified: * .on('userId', '!=', 'user.id') * // operator can be specified with table names as well: * .on('message.userId', '!=', 'user.id') * // `.orOn` takes the same arguments as `.on` and acts like `.or`: * .on('userId', 'user.id') // where message.userId = user.id * .orOn('text', 'user.name'), // or message.text = user.name * ); * ``` * * Column names in the where conditions are applied for the joined table, but you can specify a table name to add a condition for the main table. * * ```ts * db.user.join(db.message, (q) => * q * .on('userId', 'user.id') * .where({ * // not prefixed column name is for joined table: * text: { startsWith: 'hello' }, * // specify a table name to set condition on the main table: * 'user.name': 'Bob', * }) * // id is a column of a joined table Message * .whereIn('id', [1, 2, 3]) * // condition for id of a user * .whereIn('user.id', [4, 5, 6]), * ); * ``` * * The query above will generate the following SQL (simplified): * * ```sql * SELECT * FROM "user" * JOIN "message" * ON "message"."userId" = "user"."id" * AND "message"."text" ILIKE 'hello%' * AND "user"."name" = 'Bob' * AND "message"."id" IN (1, 2, 3) * AND "user"."id" IN (4, 5, 6) * ``` * * The join argument can be a query with `select`, `where`, and other methods. In such case, it will be handled as a sub query: * * ```ts * db.user.join( * db.message * .select('id', 'userId', 'text') * .where({ text: { startsWith: 'Hi' } }) * .as('t'), * 'userId', * 'user.id', * ); * ``` * * It will produce such SQL: * * ```sql * SELECT * FROM "user" * JOIN ( * SELECT "t"."id", "t"."userId", "t"."text" * FROM "message" AS "t" * ) "t" ON "t"."userId" = "user"."id" * ``` * * ## implicit join lateral * * `JOIN`'s source expression that comes before `ON` cannot access other tables, but in some cases this may be needed. * * For example, let's consider joining last 10 messages of a user: * * ```ts * await db.user.join('messages', (q) => q.order({ createdAt: 'DESC' }).limit(10)); * ``` * * When the `join`'s callback returns a more complex query than the one that simply applies certain conditions, * it will implicitly generate a `JOIN LATERAL` SQL query, as the following: * * ```sql * SELECT * * FROM "user" * JOIN LATERAL ( * SELECT * * FROM "message" AS "messages" * WHERE "message"."userId" = "user"."id" * ORDER BY "message"."createdAt" DESC * LIMIT 10 * ) "messages" ON true * ``` * * @param arg - {@link JoinFirstArg} * @param args - {@link JoinArgs} */ join, Cb extends JoinCallbackArgs>(this: T, arg: Arg, ...args: Cb | JoinArgs): JoinResultFromArgs; /** * `leftJoin` is a method for SQL `LEFT JOIN`, which is equivalent to `OUTER JOIN`, `LEFT OUTER JOIN`. * * When no matching record is found, it will fill joined table columns with `NULL` values in the result rows. * * Works just like `join`, except for result type that may have `null`: * * ```ts * const result = await db.user * .leftJoin('messages') * .select('name', 'messages.text'); * * // the same query, but joining table explicitly * const result2: typeof result = await db.user * .leftJoin(db.message, 'userId', 'user.id') * .select('name', 'message.text'); * * // result has the following type: * const ok: { name: string; text: string | null }[] = result; * ``` * * @param arg - {@link JoinFirstArg} * @param args - {@link JoinArgs} */ leftJoin, Cb extends JoinCallbackArgs>(this: T, arg: Arg, ...args: Cb | JoinArgs): JoinResultFromArgs; /** * `rightJoin` is a method for SQL `RIGHT JOIN`, which is equivalent to `RIGHT OUTER JOIN`. * * Takes the same arguments as `json`. * * It will load all records from the joining table, and fill the main table columns with `null` when no match is found. * * The columns of the table you're joining to are becoming nullable when using `rightJoin`. * * ```ts * const result = await db.user * .rightJoin('messages') * .select('name', 'messages.text'); * * // even though name is not a nullable column, it becomes nullable after using rightJoin * const ok: { name: string | null; text: string }[] = result; * ``` * * @param arg - {@link JoinFirstArg} * @param args - {@link JoinArgs} */ rightJoin, Cb extends JoinCallbackArgs>(this: T, arg: Arg, ...args: Cb | JoinArgs): JoinResultFromArgs; /** * `fullJoin` is a method for SQL `FULL JOIN`, which is equivalent to `FULL OUTER JOIN`. * * Takes the same arguments as `json`. * * It will load all records from the joining table, both sides of the join may result in `null` values when there is no match. * * All columns become nullable after using `fullJoin`. * * ```ts * const result = await db.user * .rightJoin('messages') * .select('name', 'messages.text'); * * // all columns can be null * const ok: { name: string | null; text: string | null }[] = result; * ``` * * @param arg - {@link JoinFirstArg} * @param args - {@link JoinArgs} */ fullJoin, Cb extends JoinCallbackArgs>(this: T, arg: Arg, ...args: Cb | JoinArgs): JoinResultFromArgs; /** * `joinLateral` allows joining a table with a sub-query that can reference the main table of current query and the other joined tables. * * First argument is the other table you want to join, or a name of relation, or a name of `with` defined table. * * Second argument is a callback where you can reference other tables using `on` and `orOn`, select columns, do `where` conditions, and use any other query methods to build a sub-query. * * Note that the regular `join` will also generate `JOIN LATERAL` SQL expression when the query returned from callback is complex enough (see the bottom of {@link join} description). * * ```ts * // joinLateral messages relation, alias it as `m` * // without aliasing you can refer to the message by a table name * db.user * .joinLateral(db.message.as('m'), (q) => * q * // select message columns * .select('text') * // join the message to the user, column names can be prefixed with table names * .on('authorId', 'user.id') * // message columns are available without prefixing, * // outer table columns are available with a table name * .where({ text: 'some text', 'user.name': 'name' }) * .order({ createdAt: 'DESC' }), * ) * // only selected message columns are available in select and where * .select('id', 'name', 'm.text') * .where({ 'm.text': messageData.text }); * ``` * * As well as simple `join`, `joinLateral` can select an object of full joined record: * * ```ts * // join by relation name * const result = await db.user * .joinLateral('messages', (q) => q.as('message')) // alias to 'message' * .select('name', { message: 'message.*' }); * * // result has the following type: * const ok: { * name: string; * // full message is included: * message: { id: number; text: string; updatedAt: Date; createdAt: Date }; * }[] = result; * ``` * * `message` can be aliased withing the `select` as well as in case of a simple `join`: * * ```ts * // join by relation name * const result = await db.user * .joinLateral('messages', (q) => q.as('message')) // alias to 'message' * .select('name', { msg: 'message.*' }); * * // result has the following type: * const ok: { * name: string; * // full message is included as msg: * msg: { id: number; text: string; updatedAt: Date; createdAt: Date }; * }[] = result; * ``` * * @param arg - {@link JoinFirstArg} * @param cb - callback for shaping the joined query */ joinLateral, As extends string, Result extends Column$1.QueryColumns, JoinedRelations extends RelationsBase$1>(this: T, arg: Arg, cb: (q: JoinQueryBuilder>) => { __as: As; result: Result; relations: JoinedRelations; }): JoinLateralResult; /** * The same as {@link joinLateral}, but when no records found for the join it will result in `null`: * * ```ts * const result = await db.user * .leftJoinLateral('messages', (q) => q.as('message')) * .select('name', 'message.text'); * * // result has the following type: * const ok: { name: string; text: string | null }[] = result; * ``` * * @param arg - {@link JoinFirstArg} * @param cb - callback for shaping the joined query */ leftJoinLateral, As extends string, Result extends Column$1.QueryColumns, JoinedRelations extends RelationsBase$1>(this: T, arg: Arg, cb: (q: JoinQueryBuilder>) => { __as: As; result: Result; relations: JoinedRelations; }): JoinLateralResult; /** * This method may be useful * for combining with [createForEachFrom](/guide/create-update-delete.html#createForEachFrom-insertForEachFrom). * * `createForEachFrom` creates multiple record based on a selecting query: * * ```sql * INSERT INTO t1(c1, c2) * SELECT c1, c2 FROM t2 * ``` * * Such a query inserts one record per one selected record. * * Use `joinData` to insert a multiplication of selected records and the provided data. * * ```ts * const data = [{ column2: 'one' }, { column2: 'two' }, { column2: 'three' }]; * * await db.table.createForEachFrom( * db.otherTable * .joinData('data', (t) => ({ column2: t.text() }), data) * .select('otherTable.column1', 'data.column2'), * ); * ``` * * If the query on the other table returns 2 records, * and the data array contains 3 records, then 2 \* 3 = 6 will be inserted - every combination. * * Joined data values are available in `where` just as usual. * * @param as - alias to reference joined columns * @param fn - declare column types * @param data - array of data to join */ joinData>(this: T, as: As, fn: (types: T['columnTypes']) => RecordType, data: Item[]): { [K in keyof T]: K extends '__selectable' ? T['__selectable'] & { [K in keyof RecordType & string as `${As}.${K}`]: { as: K; column: RecordType[K]; }; } : T[K]; }; } type OnArgs = [leftColumn: keyof S, rightColumn: keyof S] | [leftColumn: keyof S, op: string, rightColumn: keyof S]; type OnJsonPathEqualsArgs = [leftColumn: keyof S, leftPath: string, rightColumn: keyof S, rightPath: string]; /** * Argument of join callback. * It is a query object of table that you're joining, with ability to select main table's columns. * Adds {@link OnMethods.prototype.on} method and similar to the query. */ type JoinQueryBuilder = { [K in keyof J | keyof OnMethods]: K extends '__selectable' ? SelectableFromShape$1 & Omit : K extends keyof OnMethods ? OnMethods[K] : K extends keyof J ? J[K] : never; }; declare class OnMethods { /** * Use `on` to specify columns to join records. * * ```ts * q * .on('message.userId', 'user.id') * // joined table name may be omitted * .on('userId', 'user.id') * // operator can be specified: * .on('userId', '!=', 'user.id') * // operator can be specified with table names as well: * .on('message.userId', '!=', 'user.id') * ``` * * @param args - columns to join with */ on(this: T, ...args: OnArgs): T; /** * Works as {@link on}, but the added conditions will be separated from previous with `OR`. * * @param args - columns to join with */ orOn(this: T, ...args: OnArgs): T; /** * Use `onJsonPathEquals` to join record based on a field of their JSON column: * * ```ts * db.table.join(db.otherTable, (q) => * // '$.key' is a JSON path * q.onJsonPathEquals('otherTable.data', '$.key', 'table.data', '$.key'), * ); * ``` * * @param args - columns and JSON paths to join with. */ onJsonPathEquals(this: T, ...args: OnJsonPathEqualsArgs): T; } declare class ColumnRefExpression$1 extends Expression$1 { name: string; result: { value: T; }; q: ExpressionData$1; constructor(value: T, name: string); makeSQL(ctx: ToSQLCtx$1, quotedAs?: string): string; } declare class RefExpression extends Expression$1 { ref: string; result: { value: T; }; q: ExpressionData$1; table?: string; constructor(value: T, query: Query, ref: string); makeSQL(ctx: ToSQLCtx$1): string; } type SortDir = 'ASC' | 'DESC' | 'ASC NULLS FIRST' | 'DESC NULLS LAST'; type OrderItem = string | { [K: string]: SortDir; } | Expression$1; type OrderTsQueryConfig = true | OrderTsQueryConfigObject; interface OrderTsQueryConfigObject { coverDensity?: boolean; weights?: number[]; normalization?: number; dir?: SortDir; } type SearchWeight$1 = 'A' | 'B' | 'C' | 'D'; interface SearchWeightRecord { [K: string]: SearchWeight$1; } interface WhereSearchItem { as: string; vectorSQL: string; } type QuerySourceItem = { queryAs: string; as?: string; textSQL?: MaybeArray$1; langSQL?: string; vectorSQL?: string; order?: OrderTsQueryConfig; } & ({ language?: string; } | { languageColumn: string; }) & ({ text: string | Expression$1; } | { in: MaybeArray$1 | SearchWeightRecord; } | { vector: string; }) & ({ query: string | Expression$1; } | { plainQuery: string | Expression$1; } | { phraseQuery: string | Expression$1; } | { tsQuery: string | Expression$1; }); interface QueryDataSources { [K: string]: QuerySourceItem; } declare namespace Order { export interface ArgThis extends PickQuerySelectable, PickQueryResult, PickQueryTsQuery {} export type Arg = ArgKey | ArgTsQuery | { [K in ArgKey | ArgTsQuery]?: K extends ArgTsQuery ? OrderTsQueryConfig : SortDir; } | Expression$1; export type Args = Arg[]; type ArgTsQuery = string | undefined extends T['__tsQuery'] ? never : Exclude; type ArgKey = { [K in keyof T['__selectable']]: T['__selectable'][K]['column']['__queryType'] extends undefined ? never : K; }[keyof T['__selectable']] | { [K in keyof T['result']]: T['result'][K]['dataType'] extends 'array' | 'object' | 'runtimeComputed' ? never : K; }[keyof T['result']]; export {}; } declare class QueryOrder { /** * Adds an order by clause to the query. * * Takes one or more arguments, each argument can be a column name or an object. * * ```ts * db.table.order('id', 'name'); // ASC by default * * db.table.order({ * id: 'ASC', // or DESC * * // to set nulls order: * name: 'ASC NULLS FIRST', * age: 'DESC NULLS LAST', * }); * ``` * * `order` can refer to the values returned from `select` sub-queries (unlike `where` which cannot). * So you can select a count of related records and order by it. * * For example, `comment` has many `likes`. * We are selecting few columns of `comment`, selecting `likesCount` by a sub-query in a select, and ordering comments by likes count: * * ```ts * db.comment * .select('title', 'content', { * likesCount: (q) => q.likes.count(), * }) * .order({ * likesCount: 'DESC', * }); * ``` * * @param args - column name(s) or an object with column names and sort directions. */ order(this: T, ...args: Order.Args): T; /** * Order by SQL expression * * Order by raw SQL expression. * * ```ts * db.table.orderSql`raw sql`; * ``` * * @param args - SQL expression */ orderSql(this: T, ...args: SQLQueryArgs): T; } interface WindowArg { [K: string]: WindowArgDeclaration | Expression$1; } interface WindowArgDeclaration { partitionBy?: SelectableOrExpression | SelectableOrExpressions; order?: Order.Arg; } type WindowResult = T & { windows: { [K in keyof W]: true; }; }; declare class QueryWindow { /** * Add a window with `window` and use it later by its name for aggregate or window functions: * * ```ts * db.table * // define window `windowName` * .window({ * windowName: { * partitionBy: 'someColumn', * order: { * id: 'DESC', * }, * }, * }) * .select({ * avg: (q) => * // calculate average price over the window * q.avg('price', { * // use window by its name * over: 'windowName', * }), * }); * ``` * * @param arg - window config */ window>(this: T, arg: W): WindowResult; } interface AggregateOptions { distinct?: boolean; order?: Order.Arg | Order.Args; filter?: WhereArg$1; filterOr?: WhereArgs; withinGroup?: boolean; over?: Over; } type Over = keyof T['windows'] | WindowArgDeclaration; type HeadlineSearchArg = Exclude; interface HeadlineParams { text?: SelectableOrExpressionOfType>; options?: string | Expression$1; } interface SearchAggregateMethods { /** * Give the `as` alias for the search, and it becomes possible to select a text with highlights of the matching words or phrases: * * ```ts * db.table * .search({ * as: 'search', * in: 'body', * query: 'query', * }) * .select({ * highlightedText: (q) => q.headline('search'), * }); * ``` * * When searching in the generated `tsvector` column, need to provide a text source to the `headline`: * * ```ts * db.table * .search({ * as: 'search', * vector: 'textVector', * query: 'query', * }) * .select({ * // `body` is a column name * highlightedText: (q) => q.headline('search', { text: 'body' }), * }); * ``` * * `text` can be a raw SQL, here we are joining multiple columns: * * ```ts * import { raw } from 'orchid-orm'; * * db.table * .search({ * as: 'search', * vector: 'titleAndBodyVector', * query: 'query', * }) * .select({ * highlightedText: (q) => * q.headline('search', { text: raw`concat_ws(' ', title, body)` }), * }); * ``` * * `headline` supports a string for `options`, see details [in Postgres doc](https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-HEADLINE). * * Provide a simple string or a raw SQL: * * ```ts * db.table * .search({ * as: 'search', * in: 'body', * query: 'query', * }) * .select({ * highlightedText: (q) => * q.headline('search', { * options: * 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=<<, StopSel=>>', * }), * }); * ``` * * @param search - name of the search to use the query from * @param options - `text` for a text source, `options` for `ts_headline` options */ headline(this: T, search: HeadlineSearchArg, options?: HeadlineParams): SetQueryReturnsColumnOrThrow>; } type SearchArg = { as?: As; order?: OrderTsQueryConfig; } & ({ language?: string | Expression$1; } | { languageColumn?: keyof T['__selectable']; }) & ({ text: string | Expression$1; } | { in: MaybeArray$1 | { [K in keyof T['__selectable']]?: SearchWeight$1; }; } | { vector: { [K in keyof T['__selectable']]: T['__selectable'][K]['column']['dataType'] extends 'tsvector' ? K : never; }[keyof T['__selectable']]; }) & ({ query: string | Expression$1; } | { plainQuery: string | Expression$1; } | { phraseQuery: string | Expression$1; } | { tsQuery: string | Expression$1; }); type WhereSearchResult = T & { __tsQuery: string extends As ? never : As; }; declare class SearchMethods { /** * ## language * * By default, the search language is English. * * You can set a different default language in the `createTableFactory` config: * * ```ts * import { createTableFactory } from 'orchid-orm'; * * export const { defineTable, defineView, sql } = createTableFactory({ * language: 'swedish', * }); * ``` * * See the list of supported language configs with the SQL: * * ```sql * SELECT cfgname FROM pg_ts_config; * ``` * * When performing a search, you can override the default language: * * ```ts * db.table.search({ * language: 'finnish', * in: 'body', * query: 'query', * }); * ``` * * `language` also accepts a raw SQL. * * The language can be stored in the column of this table, then you can use `languageColumn` to use this column for the search: * * ```ts * db.table.search({ * // the table has `lang` column, use it for the search * languageColumn: 'lang', * in: 'body', * query: 'query', * }); * ``` * * ## text vector to search in * * The text to search in can be a simple string, or a raw SQL, or a text column, or multiple columns: * * ```ts * db.table.search({ * // search in the given string * text: 'simply a string to search in', * query: 'query', * }); * * import { raw } from 'orchid-orm'; * * db.table.search({ * // raw SQL: join text columns with space * text: raw`concat_ws(' ', title, body)`, * query: 'query', * }); * * db.table.search({ * // search in a single text column * in: 'body', * query: 'query', * }); * * db.table.search({ * // search in multiple columns, they are concatenated with `concat_ws` as shown above * in: ['title', 'body'], * query: 'query', * }); * * db.table.search({ * // search in multiple columns with different weights. Weight can be A, B, C, or D * in: { * title: 'A', * body: 'B', * }, * query: 'query', * }); * ``` * * 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: * * ```ts * db.table.search({ * vector: 'titleAndBodyVector', * query: 'query', * }); * ``` * * ## search query * * Read about different search queries in [this Postgres doc](https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES). * * `search` method can accept one of the following queries: * * - `query`: corresponds to `websearch_to_tsquery` in Postgres, good to use by default * - `plainQuery`: corresponds to `plainto_tsquery` * - `phraseQuery`: corresponds to `phraseto_tsquery` * - `tsQuery`: corresponds to `to_tsquery` * * 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. * * Each query kind accepts a string or a raw SQL. * * ```ts * import { raw } from 'orchid-orm'; * * db.table.search({ * vector: 'titleAndBodyVector', * // can accept raw SQL: * phraseQuery: raw`'The Fat Rats'`, * }); * ``` * * ## order by search rank * * Read about search ranking in [this Postgres doc](https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-RANKING). * * Set `order: true` to order results by the search rank: * * ```ts * db.table.search({ * in: 'body', * query: 'query', * // will add ORDER BY ts_rank(to_tsvector('english', body)) DESC * order: true, * }); * ``` * * To order with `ts_rank_cd` instead of `ts_rank`, set `coverDensity: true`: * * ```ts * db.table.search({ * in: 'body', * query: 'query', * // will add ORDER BY ts_rank_cd(to_tsvector('english', body)) DESC * order: { * coverDensity: true, * }, * }); * ``` * * Other options are: * * ```ts * db.table.search({ * in: 'body', * query: 'query', * order: { * // weights for D, C, B, A: * weights: [0.1, 0.2, 0.4, 1], * // by default, rank ignores the document length * // change rank behavior by providing here a special number * normalization: 32, * // it's possible to change the order direction: * dir: 'ASC', // DESC by default * }, * }); * ``` * * Giving the `as` alias for the search allows to set the ordering in the `order` method: * * ```ts * db.table * .search({ * as: 'search', * in: 'body', * query: 'query', * }) * .order({ * // can be `search: true` for defaults * search: { * // same options as above * coverDensity: true, * weights: [0.1, 0.2, 0.4, 1.0], * normalization: 32, * dir: 'ASC', * }, * }); * ``` * * @param arg - search config */ search(this: T, arg: SearchArg): WhereSearchResult; } interface OperatorsCount extends OperatorsNumber$1 { isCount: true; } type CountColumn = Column$1.Pick.QueryColumnOfTypeAndOps<'int8', number, OperatorsCount>; type CountReturn = SetQueryReturnsColumnOrThrow & OperatorsCount; type SelectableDataType = { [K in keyof T['__selectable']]: T['__selectable'][K]['column']['dataType'] extends DataType ? K : never; }[keyof T['__selectable']] | Expression$1>; type NumericReturn = Arg extends keyof T['__selectable'] ? SetQueryReturnsColumnOrThrow> & OperatorsNumber$1 : Arg extends Expression$1 ? SetQueryReturnsColumnOrThrow> & OperatorsNumber$1 : never; type NullableNumberReturn = SetQueryReturnsColumnOrThrow> & OperatorsNumber$1; type BooleanQueryColumn = Column$1.Pick.QueryColumnOfTypeAndOps<'bool', boolean, OperatorsBoolean>; type BooleanNullable = Column$1.Pick.QueryColumnOfTypeAndOps<'bool', boolean | null, OperatorsBoolean>; type NullableBooleanReturn = SetQueryReturnsColumnOrThrow & OperatorsBoolean; type NullableJSONAggReturn> = SetQueryReturnsColumnOrThrow['__type'] | null)[] | null; __outputType: (ExpressionOutput['__outputType'] | null)[] | null; __queryType: (ExpressionOutput['__queryType'] | null)[] | null; operators: OperatorsArray$1; }> & OperatorsArray$1; interface RecordSelectableOrExpression { [K: string]: SelectableOrExpression; } type NullableJSONObjectReturn> = SetQueryReturnsColumnOrThrow['__type']; } | null; __outputType: { [K in keyof Obj]: ExpressionOutput['__outputType']; } | null; __queryType: { [K in keyof Obj]: ExpressionOutput['__queryType']; } | null; operators: OperatorsAny; }> & OperatorsAny; type StringColumn$2 = Column$1.Pick.QueryColumnOfTypeAndOps; type StringNullable = Column$1.Pick.QueryColumnOfTypeAndOps; type NullableStringReturn = SetQueryReturnsColumnOrThrow & OperatorsText$1; interface AggregateArgTypes { minMax: 'citext' | 'date' | 'float4' | 'float8' | 'inet' | 'int2' | 'int4' | 'int8' | 'interval' | 'money' | 'numeric' | 'text' | 'time' | 'timestamp' | 'timestamptz'; sum: 'float4' | 'float8' | 'int2' | 'int4' | 'int8' | 'interval' | 'money' | 'numeric'; avg: // unlike sum, avg has no money 'float4' | 'float8' | 'int2' | 'int4' | 'int8' | 'interval' | 'numeric'; bit: 'bit' | 'int2' | 'int4' | 'int8'; bool: 'bool'; stringAgg: 'bytea' | 'text'; } interface AggregateMethods extends SearchAggregateMethods {} declare class AggregateMethods { /** * Count records with the `count` function: * * ```ts * // count all records: * const result: number = await db.table.count(); * * // count records where a column is not NULL: * db.table.count('name'); * * // see options above: * db.table.count('*', aggregateOptions); * * // select counts of people grouped by city * db.people * .select('city', { * population: (q) => q.count(), * }) * .group('city'); * ``` * * @param arg - optionally, provide a column or a raw SQL for the `count` argument * @param options - aggregation options */ count(this: T, arg?: SelectableOrExpression, options?: AggregateOptions): CountReturn; /** * Get the minimum value for the specified numeric column, returns number or `null` if there are no records. * * ```ts * const result: number | null = await db.table.min( * 'numericColumn', * aggregateOptions, * ); * * // select min product price grouped by product category * db.product * .select('category', { * minPrice: (q) => q.min('price'), * }) * .group('category') * .take(); * ``` * * @param arg - numeric column or raw SQL * @param options - aggregation options */ min>(this: T, arg: Arg, options?: AggregateOptions): NumericReturn; /** * Gets the maximum value for the specified numeric column, returns number or `null` if there are no records. * * ```ts * const result: number | null = await db.table.max( * 'numericColumn', * aggregateOptions, * ); * * // select max product price grouped by product category * db.product * .select('category', { * maxPrice: (q) => q.max('price'), * }) * .group('category') * .take(); * ``` * * @param arg - numeric column or raw SQL * @param options - aggregation options */ max>(this: T, arg: Arg, options?: AggregateOptions): NumericReturn; /** * Retrieve the sum of the values of a given numeric column, returns number or `null` if there are no records. * * ```ts * const result: number | null = await db.table.sum( * 'numericColumn', * aggregateOptions, * ); * * // select sum of employee salaries grouped by years * db.employee * .select('year', { * yearlySalaries: (q) => q.sum('salary'), * }) * .group('year'); * ``` * * @param arg - numeric column or raw SQL * @param options - aggregation options */ sum>(this: T, arg: Arg, options?: AggregateOptions): NumericReturn; /** * Retrieve the average value of a numeric column, it returns a number or `null` if there are no records. * * ```ts * const result: number | null = db.table.avg('numericColumn', aggregateOptions); * * // select average movies ratings * db.movie * .select('title', { * averageRating: (q) => q.avg('rating'), * }) * .group('title'); * ``` * * @param arg - numeric column or raw SQL * @param options - aggregation options */ avg>(this: T, arg: Arg, options?: AggregateOptions): NumericReturn; /** * Bitwise `and` aggregation, returns `number` or `null` if there are no records. * * ```ts * const result: number | null = db.table.bitAnd( * 'numericColumn', * aggregateOptions, * ); * * // select grouped `bitAnd` * db.table * .select('someColumn', { * bitAnd: (q) => q.bitAnd('numericColumn'), * }) * .group('someColumn'); * ``` * * @param arg - numeric column or raw SQL * @param options - aggregation options */ bitAnd>(this: T, arg: Arg, options?: AggregateOptions): NumericReturn; /** * Bitwise `or` aggregation, returns `number` or `null` if there are no records. * * ```ts * const result: number | null = db.table.bitOr('numericColumn', aggregateOptions); * * // select grouped `bitOr` * db.table * .select('someColumn', { * bitOr: (q) => q.bitOr('numericColumn'), * }) * .group('someColumn'); * ``` * * @param arg - numeric column or raw SQL * @param options - aggregation options */ bitOr>(this: T, arg: Arg, options?: AggregateOptions): NumericReturn; /** * Aggregate booleans with `and` logic, it returns `boolean` or `null` if there are no records. * * ```ts * const result: boolean | null = db.table.boolAnd( * 'booleanColumn', * aggregateOptions, * ); * * // select grouped `boolAnd` * db.table * .select('someColumn', { * boolAnd: (q) => q.boolAnd('booleanColumn'), * }) * .group('someColumn'); * ``` * * @param arg - boolean column or raw SQL * @param options - aggregation options */ boolAnd(this: T, arg: SelectableDataType, options?: AggregateOptions): NullableBooleanReturn; /** * Aggregate booleans with `or` logic, it returns `boolean` or `null` if there are no records. * * ```ts * const result: boolean | null = db.table.boolOr( * 'booleanColumn', * aggregateOptions, * ); * * // select grouped `boolOr` * db.table * .select('someColumn', { * boolOr: (q) => q.boolOr('booleanColumn'), * }) * .group('someColumn'); * ``` * * @param arg - boolean column or raw SQL * @param options - aggregation options */ boolOr(this: T, arg: SelectableDataType, options?: AggregateOptions): NullableBooleanReturn; /** * Equivalent to {@link boolAnd} */ every(this: T, arg: SelectableDataType, options?: AggregateOptions): NullableBooleanReturn; /** * Aggregate values into an array by using `json_agg`. Returns array of values or `null` if there are no records. * * `jsonAgg` is working a bit faster, `jsonbAgg` is better only when applying JSON operations in SQL. * * ```ts * const idsOrNull: number[] | null = db.table.jsonAgg('id', aggregateOptions); * * const namesOrNull: string[] | null = db.table.jsonbAgg( * 'name', * aggregateOptions, * ); * * // select grouped `jsonAgg` * db.table * .select('someColumn', { * jsonAgg: (q) => q.jsonAgg('anyColumn'), * }) * .group('someColumn'); * ``` * * @param arg - any column or raw SQL * @param options - aggregation options */ jsonAgg>(this: T, arg: Arg, options?: AggregateOptions): NullableJSONAggReturn; /** * See {@link jsonAgg} */ jsonbAgg>(this: T, arg: Arg, options?: AggregateOptions): NullableJSONAggReturn; /** * It does the construction of JSON objects, keys are provided strings and values can be table columns or raw SQL expressions, and returns `object` or `null` if no records. * * `jsonObjectAgg` is different from `jsonbObjectAgg` by internal representation in the database, `jsonObjectAgg` is a bit faster as it constructs a simple string. * * ```ts * import { TextColumn } from './string'; * * // object has type { nameAlias: string, foo: string } | null * const object = await db.table.jsonObjectAgg( * { * // select a column with alias * nameAlias: 'name', * // select raw SQL with alias * foo: sql`"bar" || "baz"`, * }, * aggregateOptions, * ); * * // select aggregated object * db.table.select('id', { * object: (q) => * q.jsonObjectAgg({ * nameAlias: 'name', * foo: sql`"bar" || "baz"`, * }), * }); * ``` * * @param arg - object where values are column names or SQL * @param options - aggregation options */ jsonObjectAgg>(this: T, arg: Obj, options?: AggregateOptions): NullableJSONObjectReturn; /** * See {@link jsonObjectAgg} */ jsonbObjectAgg>(this: T, arg: Obj, options?: AggregateOptions): NullableJSONObjectReturn; /** * Select joined strings, it returns a string or `null` if no records. * * ```ts * const result: string | null = db.table.stringAgg( * 'name', * ', ', * aggregateOptions, * ); * * // select joined strings grouped by some column * db.table * .select('someColumn', { * joinedNames: (q) => q.stringAgg('name', ', '), * }) * .group('someColumn'); * ``` * * @param arg - string column or SQL * @param delimiter - string to join with * @param options - aggration options */ stringAgg(this: T, arg: SelectableDataType, delimiter: string, options?: AggregateOptions): NullableStringReturn; /** * Concatenates `xml` columns, returns a `string` or `null` if no records. * * ```ts * const xml: string | null = await db.table.xmlAgg('xmlColumn', aggregateOptions); * * // select joined XMLs grouped by some column * db.table * .select('someColumn', { * joinedXMLs: (q) => q.xmlAgg('xml'), * }) * .group('someColumn'); * ``` * * @param arg - column or SQL with XML * @param options - aggregation options */ xmlAgg(this: T, arg: SelectableOrExpressionOfType, options?: AggregateOptions): NullableStringReturn; /** * Selects the` row_number` window function. * * Returns the number of the current row within its partition, counting from 1. * * ```ts * // result is of type Array<{ rowNumber: number }> * const result = await db.table.select({ * rowNumber: (q) => * q.rowNumber({ * partitionBy: 'someColumn', * order: { createdAt: 'ASC' }, * }), * }); * ``` * * @param over - OVER clause config */ rowNumber(this: T, over?: Over): NullableNumberReturn; /** * Selects the` rank` window function. * * Returns the rank of the current row, with gaps; that is, the row_number of the first row in its peer group. * * ```ts * // result is of type Array<{ rank: number }> * const result = await db.table.select({ * rank: (q) => * q.rank({ * partitionBy: 'someColumn', * order: { createdAt: 'ASC' }, * }), * }); * ``` * * @param over - OVER clause config */ rank(this: T, over?: Over): NullableNumberReturn; /** * Selects the` dense_rank` window function. * * Returns the rank of the current row, without gaps; this function effectively counts peer groups. * * ```ts * // result is of type Array<{ denseRank: number }> * const result = await db.table.select({ * denseRank: (q) => * q.denseRank({ * partitionBy: 'someColumn', * order: { createdAt: 'ASC' }, * }), * }); * ``` * * @param over - OVER clause config */ denseRank(this: T, over?: Over): NullableNumberReturn; /** * Selects the `percent_rank` window function. * * Returns the relative rank of the current row, that is (rank - 1) / (total partition rows - 1). The value thus ranges from 0 to 1 inclusive. * * ```ts * // result is of type Array<{ percentRank: number }> * const result = await db.table.select({ * percentRank: (q) => * q.percentRank({ * partitionBy: 'someColumn', * order: { createdAt: 'ASC' }, * }), * }); * ``` * * @param over - OVER clause config */ percentRank(this: T, over?: Over): NullableNumberReturn; /** * Selects the `cume_dist` window function. * * Returns the cumulative distribution, that is (number of partition rows preceding or peers with current row) / (total partition rows). The value thus ranges from 1/N to 1. * * ```ts * // result is of type Array<{ cumeDist: number }> * const result = await db.table.select({ * cumeDist: (q) => * q.cumeDist({ * partitionBy: 'someColumn', * order: { createdAt: 'ASC' }, * }), * }); * ``` * * @param over - OVER clause config */ cumeDist(this: T, over?: Over): NullableNumberReturn; } interface OrExpression extends Expression$1, OperatorsBoolean {} type OrExpressionArg = QueryOrExpressionBooleanOrNullResult | undefined; declare class OrExpression extends Expression$1 { args: [OrExpressionArg, ...OrExpressionArg[]]; result: { value: BooleanQueryColumn; }; q: ExpressionData$1; constructor(args: [OrExpressionArg, ...OrExpressionArg[]]); makeSQL(ctx: ToSQLCtx$1, quotedAs?: string): string; } interface QueryReturnsFnAdd extends PickQueryHasSelect { type(fn: (types: T['columnTypes']) => C): { [K in keyof T]: K extends 'result' ? { value: C; } : K extends 'returnType' ? 'valueOrThrow' : K extends 'then' ? QueryThen : T[K]; } & C['operators']; } type SetQueryReturnsFn = { [K in keyof T]: K extends 'result' ? { value: C; } : K extends 'returnType' ? 'valueOrThrow' : K extends 'then' ? QueryThen : T[K]; } & QueryReturnsFnAdd; declare class QueryExpressions { /** * `column` references a table column, this can be used in raw SQL or when building a column expression. * Only for referencing a column in the query's table. For referencing joined table's columns, see [ref](#ref). * * ```ts * import { sql } from './baseTable'; * * await db.table.select({ * // select `("table"."id" = 1 OR "table"."name" = 'name') AS "one"`, * // returns a boolean * one: (q) => * sql`${q.column('id')} = ${1} OR ${q.column('name')} = ${'name'}`, * * // selects the same as above, but by building a query * two: (q) => q.column('id').equals(1).or(q.column('name').equals('name')), * }); * ``` * * @param name - column name */ column(this: T, name: K): ColumnRefExpression$1 & T['shape'][K]['operators']; /** * `ref` is similar to [column](#column), but it also allows to reference a column of joined table, * and other dynamically defined columns. * * ```ts * import { sql } from './baseTable'; * * await db.table.join('otherTable').select({ * // select `("otherTable"."id" = 1 OR "otherTable"."name" = 'name') AS "one"`, * // returns a boolean * one: (q) => * sql`${q.ref('otherTable.id')} = ${1} OR ${q.ref( * 'otherTable.name', * )} = ${'name'}`, * * // selects the same as above, but by building a query * two: (q) => * q * .ref('otherTable.id') * .equals(1) * .or(q.ref('otherTable.name').equals('name')), * }); * ``` * * @param arg - any available column name, such as of a joined table */ ref(this: T, arg: K): RefExpression & T['__selectable'][K]['column']['operators']; /** * `fn` allows to call an arbitrary SQL function. * * For example, calling `sqrt` function to get a square root from some numeric column: * * ```ts * const q = await db.table.select({ * sqrt: (q) => q.fn('sqrt', ['numericColumn']), * }).take(); * * q.sqrt; // has type `number` just as provided * ``` * * If this is an aggregate function, you can specify aggregation options (see [Aggregate](/guide/aggregate.html)) via third parameter. * * Use `type` method to specify a column type so that its operators such as `lt` and `gt` become available: * * ```ts * const q = await db.table.select({ * // Produces `sqrt("numericColumn") > 5` * sqrtIsGreaterThan5: (q) => * q * .fn('sqrt', ['numericColumn']) * .type((t) => t.float()) * .gt(5), * }).take(); * * // Return type is boolean | null * // todo: it should be just boolean if the column is not nullable, but for now it's always nullable * q.sqrtIsGreaterThan5; * ``` * * @param fn * @param args * @param options */ fn>(this: T, fn: string, args: SelectableOrExpressions, options?: AggregateOptions): SetQueryReturnsFn; or(...args: [OrExpressionArg, ...OrExpressionArg[]]): OrExpression; } type WhereArg$1 = { [K in keyof T['__selectable'] | 'NOT' | 'OR' | 'IN']?: K extends 'NOT' ? WhereArg$1 | WhereArgs : K extends 'OR' ? (WhereArg$1 | WhereArgs)[] : K extends 'IN' ? MaybeArray$1<{ columns: (keyof T['__selectable'])[]; values: unknown[][] | IsQuery$1 | Expression$1; }> : T['__selectable'][K]['column']['__queryType'] | null | { [O in keyof T['__selectable'][K]['column']['operators']]?: T['__selectable'][K]['column']['operators'][O]['_opType']; } | { result: { value: { __queryType: T['__selectable'][K]['column']['__queryType'] | null; }; }; } | ((q: T) => { result: { value: { __queryType: T['__selectable'][K]['column']['__queryType'] | null; }; }; }); } | ((q: WhereQueryBuilder) => QueryOrExpressionBooleanOrNullResult | WhereQueryBuilder); /** * Callback argument of `where`. * It has `where` methods (`where`, `whereNot`, `whereExists`, etc.), * and it has relations that you can aggregate and use a boolean comparison with, such as: * ```ts * db.table.where((q) => q.relation.count().equals(10)) * ``` */ type WhereQueryBuilder = EmptyObject$1 extends T['relations'] ? { [K in keyof T]: K extends keyof Where | keyof QueryExpressions | 'table' | 'get' | 'columnTypes' | '__selectable' | 'relations' | 'useHelper' | 'modify' | 'result' | 'returnType' | 'withData' | 'windows' | 'then' | 'none' ? T[K] : never; } : { [K in keyof T['relations'] | keyof T]: K extends keyof T['relations'] ? T['relations'][K]['query'] : K extends keyof T & (keyof Where | keyof QueryExpressions | 'table' | 'get' | 'columnTypes' | '__selectable' | 'relations' | 'useHelper' | 'modify' | 'result' | 'returnType' | 'withData' | 'windows' | 'then' | 'none') ? T[K] : never; }; type WhereArgs = WhereArg$1[]; type WhereNotArgs = [WhereArg$1]; type WhereInColumn = keyof T['__selectable'] | [keyof T['__selectable'], ...(keyof T['__selectable'])[]]; type WhereInValues = Column extends keyof T['__selectable'] ? Iterable | IsQuery$1 | Expression$1 : ({ [I in keyof Column]: Column[I] extends keyof T['__selectable'] ? T['__selectable'][Column[I]]['column']['__queryType'] : never; } & { length: Column extends { length: number; } ? Column['length'] : never; })[] | IsQuery$1 | Expression$1; type WhereInArg = { [K in keyof T['__selectable']]?: Iterable | IsQuery$1 | Expression$1; }; interface QueryHasWhere$1 { __hasWhere: true; } interface QueryFnReturningSelect { (q: never): QueryHasSelect; } declare class Where { /** * Constructing `WHERE` conditions: * * ```ts * import { sql } from './table-factory'; * * db.table.where({ * // column of the current table * name: 'John', * * // table name may be specified, it can be the name of a joined table * 'table.lastName': 'Johnsonuk', * * // object with operators, see the "column operators" section to see a full list of them: * age: { * gt: 30, * lt: 70, * }, * * // where column equals to raw SQL * // import `sql` from your table factory * column: sql`sql expression`, * // or use `(q) => sql` for the same * column2: (q) => sql`sql expression`, * * // reference other columns in such a way: * firstName: (q) => q.ref('lastName'), * }); * ``` * * Multiple `where`s are joined with `AND`: * * ```ts * db.table.where({ foo: 'foo' }).where({ bar: 'bar' }); * ``` * * ```sql * SELECT * FROM table WHERE foo = 'foo' AND bar = 'bar' * ``` * * `undefined` values are ignored, so you can supply a partial object with conditions: * * ```ts * type Params = { * // allow providing exact age, or lower or greater than * age?: number | { lt?: number; gt?: number }; * }; * * const loadRecords = async (params: Params) => { * // this will load all records if params is an empty object * const records = await db.table.where(params); * }; * ``` * * It supports a sub-query that is selecting a single value to compare it with a column: * * ```ts * db.table.where({ * // compare `someColumn` in one table with the `column` value returned from another query. * someColumn: db.otherTable.where(...conditions).get('column'), * }); * ``` * * `where` can accept other queries and merge their conditions: * * ```ts * const otherQuery = db.table.where({ name: 'John' }); * * db.table.where({ id: 1 }, otherQuery); * // this will produce WHERE "table"."id" = 1 AND "table"."name' = 'John' * ``` * * `where` supports raw SQL: * * ```ts * db.table.where(sql`a = b`); * ``` * * `where` can accept a callback with a specific query builder containing all "where" methods such as `where`, `orWhere`, `whereNot`, `whereIn`, `whereExists`: * * ```ts * db.table.where((q) => * q * .where({ name: 'Name' }) * .orWhere({ id: 1 }, { id: 2 }) * .whereIn('letter', ['a', 'b', 'c']) * .whereExists(db.message, 'authorId', 'id'), * ); * ``` * * `where` can accept multiple arguments, conditions are joined with `AND`: * * ```ts * db.table.where( * { id: 1 }, * db.table.where({ name: 'John' }), * sql`a = b`, * ); * ``` * * ## where sub query * * `where` handles a special callback where you can query a relation to get some value and filter by that value. * * It is useful for a faceted search. For instance, posts have tags, and we want to find all posts that have all the given tags. * * ```ts * const givenTags = ['typescript', 'node.js']; * * const posts = await db.post.where( * (post) => * post.tags // query tags of the post * .whereIn('tagName', givenTags) // where name of the tag is inside array * .count() // count how many such tags were found * .equals(wantedTags.length), // the count must be exactly the length of array * // if the post has ony `typescript` tag but not the `node.js` it will be omitted * ); * ``` * * This will produce an efficient SQL query: * * ```sql * SELECT * FROM "post" * WHERE ( * SELECT count(*) = 3 * FROM "tag" AS "tags" * WHERE "tag"."tagName" IN ('typescript', 'node.js') * -- join tags to the post via "postTag" table * AND EXISTS ( * SELECT 1 FROM "postTag" * WHERE "postTag"."postId" = "post"."id" * AND "postTag"."tagId" = "tag"."id" * ) * ) * ``` * * In the example above we use `count()`, you can also use any other aggregate method instead, such as `min`, `max`, `avg`. * * The `count()` is chained with `equals` to check for a strict equality, any other operation is also allowed, such as `not`, `lt`, `gt`. * * ## where special keys * * 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. * * For example: * * ```ts * db.table.where({ * NOT: { key: 'value' }, * OR: [{ name: 'a' }, { name: 'b' }], * IN: { * columns: ['id', 'name'], * values: [ * [1, 'a'], * [2, 'b'], * ], * }, * }); * ``` * * Using methods `whereNot`, `orWhere`, `whereIn` instead of this is a shorter and cleaner way, but in some cases, such object keys way may be more convenient. * * ```ts * db.table.where({ * // see .whereNot * NOT: { id: 1 }, * // can be an array: * NOT: [{ id: 1 }, { id: 2 }], * * // see .orWhere * OR: [{ name: 'a' }, { name: 'b' }], * // can be an array: * // this will give id = 1 AND id = 2 OR id = 3 AND id = 4 * OR: [ * [{ id: 1 }, { id: 2 }], * [{ id: 3 }, { id: 4 }], * ], * * // see .in, the key syntax requires an object with columns and values * IN: { * columns: ['id', 'name'], * values: [ * [1, 'a'], * [2, 'b'], * ], * }, * // can be an array: * IN: [ * { * columns: ['id', 'name'], * values: [ * [1, 'a'], * [2, 'b'], * ], * }, * { columns: ['someColumn'], values: [['foo', 'bar']] }, * ], * }); * ``` * * ## column operators * * `where` argument can take an object where the key is the name of the operator and the value is its argument. * * Different types of columns support different sets of operators. * * All column operators can take a value of the same type as the column, a sub-query, or a raw SQL expression: * * ```ts * db.table.where({ * numericColumn: { * // lower than 5 * lt: 5, * * // lower than the value returned by sub-query * lt: db.otherTable.select('someNumber').take(), * * // raw SQL expression produces WHERE "numericColumn" < "otherColumn" + 10 * lt: sql`"otherColumn" + 10`, * }, * }); * ``` * * ### Any type of column operators * * `equals` is a simple `=` operator, it may be useful for comparing column value with JSON object: * * ```ts * db.table.where({ * // when searching for an exact same JSON value, this won't work: * jsonColumn: someObject, * * // use `{ equals: ... }` instead: * jsonColumn: { equals: someObject }, * }); * ``` * * `not` is `!=` (aka `<>`) not equal operator: * * ```ts * db.table.where({ * anyColumn: { not: value }, * }); * ``` * * `in` is for the `IN` operator to check if the column value is included in a list of values. * * 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. * * ```ts * db.table.where({ * column: { * in: ['a', 'b', 'c'], * * // WHERE "column" IN (SELECT "column" FROM "otherTable") * in: db.otherTable.select('column'), * * in: sql`('a', 'b')`, * }, * }); * ``` * * `notIn` is for the `NOT IN` operator, and takes the same arguments as `in` * * ### Numeric, Date, and Time column operators * * To compare numbers, dates, and times. * * `lt` is for `<` (lower than) * * `lte` is for `<=` (lower than or equal) * * `gt` is for `>` (greater than) * * `gte` is for `>=` (greater than or equal) * * ```ts * db.table.where({ * numericColumn: { * gt: 5, * lt: 10, * }, * * date: { * lte: new Date(), * }, * * time: { * gte: new Date(), * }, * }); * ``` * * `between` also works with numeric, dates, and time columns, it takes an array of two elements. * * Both elements can be of the same type as a column, a sub-query, or a raw SQL expression. * * ```ts * db.table.where({ * column: { * // simple values * between: [1, 10], * * // sub-query and raw SQL expression * between: [db.otherTable.select('column').take(), sql`2 + 2`], * }, * }); * ``` * * ### Text column operators * * For `text`, `varchar`, `string`, and `json` columns. * * `json` is stored as text, so it has text operators. Use the `jsonb` type for JSON operators. * * Takes a string, or sub-query returning string, or raw SQL expression as well as other operators. * * ```ts * db.table.where({ * textColumn: { * // WHERE "textColumn" LIKE '%string%' * contains: 'string', * // WHERE "textColumn" ILIKE '%string%' * containsInsensitive: 'string', * // WHERE "textColumn" LIKE 'string%' * startsWith: 'string', * // WHERE "textColumn" ILIKE 'string%' * startsWithInsensitive: 'string', * // WHERE "textColumn" LIKE '%string' * endsWith: 'string', * // WHERE "textColumn" ILIKE '%string' * endsWithInsensitive: 'string', * }, * }); * ``` * * ### JSONB column operators * * JSON functions are available only for the `jsonb` column, note that the `json` type has text operators instead. * * You can use [jsonPathQueryFirst](/guide/json.html#jsonpathqueryfirst) to filter by a JSON value, follow the link for details. * * The value can be of any type, it can also be returned from a sub-query, raw SQL expression. * * ```ts * db.table.where((q) => * q.get('jsonbColumn').jsonPathQueryFirst('$.name').equals(value), * ); * ``` * * `jsonSupersetOf`: check if the column value is a superset of provided value. * * For instance, it is true if the column has JSON `{ "a": 1, "b": 2 }` and provided value is `{ "a": 1 }`. * * Takes the value of any type, or sub query which returns a single value, or a raw SQL expression. * * ```ts * db.table.where({ * jsonbColumn: { * jsonSupersetOf: { a: 1 }, * }, * }); * ``` * * `jsonSubsetOf`: check if the column value is a subset of provided value. * * For instance, it is true if the column has JSON `{ "a": 1 }` and provided value is `{ "a": 1, "b": 2 }`. * * Takes the value of any type, or sub query which returns a single value, or a raw SQL expression. * * ```ts * db.table.where({ * jsonbColumn: { * jsonSubsetOf: { a: 1 }, * }, * }); * ``` * * @param args - {@link WhereArgs} */ where(this: T, ...args: WhereArgs): T & QueryHasWhere$1; /** * Use a custom SQL expression in `WHERE` statement: * * ```ts * db.table.whereSql`a = b`; * ``` * * @param args - SQL expression */ whereSql(this: T, ...args: SQLQueryArgs): T & QueryHasWhere$1; /** * `whereNot` takes the same argument as `where`, * multiple conditions are combined with `AND`, * the whole group of conditions is negated with `NOT`. * * ```ts * // find records of different colors than red * db.table.whereNot({ color: 'red' }); * // WHERE NOT color = 'red' * db.table.whereNot({ one: 1, two: 2 }); * // WHERE NOT (one = 1 AND two = 2) * ``` * * @param args - {@link WhereArgs} */ whereNot(this: T, ...args: WhereNotArgs): T & QueryHasWhere$1; /** * `whereNotSql` is a version of `whereNot` accepting SQL expression: * * ```ts * db.table.whereNotSql`sql expression` * ``` * * @param args - SQL expression */ whereNotSql(this: T, ...args: SQLQueryArgs): T; /** * `whereOneOf` stands for "...**and** where one of the given is true". * * Accepts the same arguments as `where`. * * ```ts * db.table.where({ id: 1 }).whereOneOf({ color: 'red' }, { color: 'blue' }); * ``` * * ```sql * SELECT * FROM table * WHERE id = 1 AND (color = 'red' OR color = 'blue') * ``` * * Note that columns inside every argument are joined with `AND`: * * ```ts * db.table.whereOneOf({ id: 1, color: 'red' }, { id: 2 }); * ``` * * ```sql * SELECT * FROM table * WHERE (id = 1 AND color = 'red') OR (id = 2) * ``` * * @param args - same arguments as in {@link where}, joined with `OR` */ whereOneOf(this: T, ...args: WhereArgs): T & QueryHasWhere$1; /** * Negative {@link whereOneOf}: * * ```ts * db.table.where({ id: 1 }).whereNotOneOf({ color: 'red' }, { color: 'blue' }); * ``` * * ```sql * SELECT * FROM table * WHERE id = 1 AND NOT (color = 'red' OR color = 'blue') * ``` * * @param args - same arguments as in {@link where}, joined with `OR` */ whereNotOneOf(this: T, ...args: WhereArgs): T; /** * `orWhere` stands for "...**or** where one of the given is true". * * Accepts the same arguments as `where`. * * ```ts * db.table.where({ id: 1, color: 'red' }).orWhere({ id: 2, color: 'blue' }); * // equivalent: * db.table.orWhere({ id: 1, color: 'red' }, { id: 2, color: 'blue' }); * ``` * * ```sql * SELECT * FROM table * WHERE (id = 1 AND color = 'red') OR (id = 2 AND color = 'blue') * ``` * * @param args - same arguments as in {@link where}, joined with `OR` */ orWhere(this: T, ...args: WhereArgs): T & QueryHasWhere$1; /** * `orWhereNot` takes the same arguments as {@link orWhere}, and prepends each condition with `NOT` just as {@link whereNot} does. * * @param args - {@link WhereArgs} will be prefixed with `NOT` and joined with `OR` */ orWhereNot(this: T, ...args: WhereArgs): T & QueryHasWhere$1; /** * `whereIn` and related methods are for the `IN` operator to check for inclusion in a list of values. * * When used with a single column it works equivalent to the `in` column operator: * * ```ts * db.table.whereIn('column', [1, 2, 3]); * db.table.whereIn('column', new Set([1, 2, 3])); * // the same as: * db.table.where({ column: { in: [1, 2, 3] } }); * db.table.where({ column: { in: new Set([1, 2, 3]) } }); * ``` * * `whereIn` can support a tuple of columns, that's what the `in` operator cannot support: * * ```ts * db.table.whereIn( * ['id', 'name'], * [ * [1, 'Alice'], * [2, 'Bob'], * ], * ); * ``` * * It supports sub query which should return records with columns of the same type: * * ```ts * db.table.whereIn(['id', 'name'], db.otherTable.select('id', 'name')); * ``` * * It supports raw SQL expression: * * ```ts * db.table.whereIn(['id', 'name'], sql`((1, 'one'), (2, 'two'))`); * ``` * * An empty list passed to `whereIn` or `orWhereIn` matches no records, and an empty list passed to `whereNotIn` or `orWhereNotIn` matches all records. * * An empty `whereIn` list, alone or with other `where` conditions, makes the query return an empty result without querying the database, the same as {@link QueryMethods.none}. * A query with `with` or `union` still queries the database. * * ```ts * // return an empty result without querying the database: * db.table.whereIn('id', []); * db.table.whereIn(['id', 'name'], []); * db.table.whereIn({ id: [] }); * db.table.where({ name: 'Ann' }).whereIn('id', []); * * // return records named Ann: * db.table.whereIn('id', []).orWhere({ name: 'Ann' }); * db.table.where({ name: 'Ann' }).orWhereIn('id', []); * db.table.where({ name: 'Ann' }).whereNotIn('id', []); * ``` * * `update` and `delete` throw when an empty `whereNotIn` or `orWhereNotIn` list makes them match all records, unless `all()` is called. */ whereIn>(this: T, ...args: [column: Column, values: WhereInValues] | [arg: WhereInArg]): T & QueryHasWhere$1; /** * Takes the same arguments as {@link whereIn}. * Add a `WHERE IN` condition prefixed with `OR` to the query: * * ```ts * db.table.whereIn('a', [1, 2, 3]).orWhereIn('b', ['one', 'two']); * ``` */ orWhereIn>(this: T, ...args: [column: Column, values: WhereInValues] | [WhereInArg]): T & QueryHasWhere$1; /** * Acts as `whereIn`, but negates the condition with `NOT`: * * ```ts * db.table.whereNotIn('color', ['red', 'green', 'blue']); * ``` */ whereNotIn>(this: T, ...args: [column: Column, values: WhereInValues] | [arg: WhereInArg]): T & QueryHasWhere$1; /** * Acts as `whereIn`, but prepends `OR` to the condition and negates it with `NOT`: * * ```ts * db.table.whereNotIn('a', [1, 2, 3]).orWhereNoIn('b', ['one', 'two']); * ``` */ orWhereNotIn>(this: T, ...args: [column: Column, values: WhereInValues] | [arg: WhereInArg]): T & QueryHasWhere$1; /** * `whereExists` is for support of the `WHERE EXISTS (query)` clause. * * This method is accepting the same arguments as `join`, see the {@link Join.join} section for more details. * * ```ts * // find users who have accounts * // find by a relation name if it's defined * db.user.whereExists('account'); * * // find users who have an account with positive balance * // `accounts` is a relation name * db.user.whereExists((q) => q.accounts.where({ balance: { gt: 0 } })); * * // find using a table and a join conditions * db.user.whereExists(db.account, 'account.id', 'user.id'); * * // find using a query builder in a callback: * db.user.whereExists(db.account, (q) => q.on('account.id', '=', 'user.id')); * ``` */ whereExists, Cb extends JoinCallbackArgs>(this: T, arg: Arg, ...args: Cb | JoinArgs): Arg extends QueryFnReturningSelect ? { error: 'Cannot select in whereExists'; } : Cb[0] extends QueryFnReturningSelect ? { error: 'Cannot select in whereExists'; } : T & QueryHasWhere$1; /** * Acts as `whereExists`, but prepends the condition with `OR`: * * ```ts * // find users who have an account or a profile, * // imagine that the user has both `account` and `profile` relations defined. * db.user.whereExist('account').orWhereExists('profile'); * ``` */ orWhereExists>(this: T, arg: Arg, ...args: JoinArgs): T & QueryHasWhere$1; /** * Acts as `whereExists`, but negates the condition with `NOT`: * * ```ts * // find users who don't have an account, * // image that the user `belongsTo` or `hasOne` account. * db.user.whereNotExist('account'); * ``` * * @param arg - relation name, or a query object, or a `with` table alias, or a callback returning a query object. * @param args - no arguments needed when the first argument is a relation name, or conditions to join the table with. */ whereNotExists>(this: T, arg: Arg, ...args: JoinArgs): T & QueryHasWhere$1; /** * Acts as `whereExists`, but prepends the condition with `OR` and negates it with `NOT`: * * ```ts * // find users who don't have an account OR who don't have a profile * // imagine that the user has both `account` and `profile` relations defined. * db.user.whereNotExists('account').orWhereNotExists('profile'); * ``` */ orWhereNotExists>(this: T, arg: Arg, ...args: JoinArgs): T & QueryHasWhere$1; } /** * This feature allows defining a set of query modifiers to use it later. * Only [where conditions](/guide/where.html) can be set in a scope. * If you define a scope with name `default`, it will be applied for all table queries by default. * * ```ts * import { defineTable } from './table-factory'; * * export const SomeTable = defineTable('some', (t) => ({ * id: t.identity().primaryKey(), * hidden: t.boolean(), * active: t.boolean(), * })).scopes({ * default: (q) => q.where({ hidden: false }), * active: (q) => q.where({ active: true }), * }); * * const db = orchidORM( * { databaseURL: '...' }, * { * some: SomeTable, * }, * ); * * // the default scope is applied for all queries: * const nonHiddenRecords = await db.some; * ``` */ declare class QueryScope { /** * See {@link QueryScope} * * Use the `scope` method to apply a pre-defined scope. * * ```ts * // use the `active` scope that is defined in the table: * await db.some.scope('active'); * ``` * * @param scope - name of the scope to apply */ scope(this: T, scope: keyof T['__scopes']): T & QueryHasWhere$1; /** * See {@link QueryScope} * * Remove conditions that were added by the scope from the query. * * ```ts * // SomeTable has a default scope, ignore it for this query: * await db.some.unscope('default'); * ``` * * @param scope - name of the scope to remove from the query */ unscope(this: T, scope: keyof T['__scopes']): T; } interface TableData$1 { primaryKey?: TableData$1.PrimaryKey; indexes?: TableData$1.Index[]; excludes?: TableData$1.Exclude[]; constraints?: TableData$1.Constraint[]; } declare namespace TableData$1 { export type DropMode = 'CASCADE' | 'RESTRICT'; export interface PrimaryKey { columns: string[]; name?: string; } export interface ColumnIndex { options: Index.ColumnOptionsData; } export interface ColumnExclude extends ColumnIndex { with: string; } export interface Index { columns: Index.ColumnOrExpressionOptions[]; options: Index.Options; } export interface Exclude { columns: Exclude.ColumnOrExpressionOptions[]; options: Exclude.Options; } export interface Constraint { name?: string; check?: Check; identity?: Identity; references?: References; dropMode?: TableData$1.DropMode; } export type Check = RawSqlBase$1; export interface ColumnReferences { fnOrTable: TableData$1.References.FnOrTable; foreignColumns: string[]; options?: References.Options; } export interface References extends ColumnReferences { columns: string[]; } export interface Identity extends SequenceBaseOptions { always?: boolean; } interface SequenceBaseOptions { increment?: number; start?: number; min?: number; max?: number; cache?: number; cycle?: boolean; } export interface SequenceOptions extends SequenceBaseOptions { dataType?: 'smallint' | 'integer' | 'bigint'; ownedBy?: string; } export namespace Index { export interface ColumnOptions { collate?: string; opclass?: string; order?: string; weight?: SearchWeight$1; } /** * Controls when Postgres checks a unique constraint. */ export type UniqueDeferrable = false | 'immediate' | 'deferred'; export interface BaseUniqueOptionsArg { name?: Name; nullsNotDistinct?: boolean; using?: string; include?: MaybeArray$1; with?: string; tablespace?: string; where?: string; dropMode?: DropMode; } export interface UniqueOptionsArg extends BaseUniqueOptionsArg { /** * Makes this unique definition a deferrable Postgres constraint. */ deferrable?: UniqueDeferrable; } export interface NonUniqueIndexOptionsArg extends BaseUniqueOptionsArg { unique?: false; deferrable?: never; } export interface UniqueIndexOptionsArg extends UniqueOptionsArg { unique: true; } export type OptionsArg = NonUniqueIndexOptionsArg | UniqueIndexOptionsArg; export type TsVectorArg = OptionsArg & TsVectorOptions; export interface Options extends UniqueOptionsArg, TsVectorOptions { unique?: boolean; } export interface UniqueColumnArg extends ColumnOptions, UniqueOptionsArg { expression?: string; } export interface NonUniqueColumnArg extends ColumnOptions, BaseUniqueOptionsArg { expression?: string; unique?: false; deferrable?: never; } export interface UniqueIndexColumnArg extends UniqueColumnArg { unique: true; } export interface ColumnOptionsData extends ColumnOptions, Options { expression?: string; } export type ColumnArg = NonUniqueColumnArg | UniqueIndexColumnArg; interface TsVectorOptions { language?: string; languageColumn?: string; tsVector?: boolean; } export type TsVectorColumnArg = ColumnArg & TsVectorOptions; export interface ExpressionOptions extends ColumnOptions { expression: string; } export interface ColumnOptionsForColumn extends ColumnOptions { column: Column; } export type ColumnOrExpressionOptions = ColumnOptionsForColumn | ExpressionOptions; export {}; } export namespace Exclude { export interface Options { name?: string; using?: string; include?: MaybeArray$1; with?: string; tablespace?: string; where?: string; dropMode?: DropMode; } export interface ArgColumnOptions { collate?: string; opclass?: string; order?: string; } export interface ColumnArg extends Options, ArgColumnOptions {} interface ColumnBaseOptions extends ArgColumnOptions { with: string; } interface ColumnOptions extends ColumnBaseOptions { column: Column; } interface ExpressionOptions extends ColumnBaseOptions { expression: string; } export type ColumnOrExpressionOptions = ColumnOptions | ExpressionOptions; export {}; } export namespace References { type FnOrTable = (() => Column.ForeignKey.TableParam) | string; /** * - MATCH FULL will not allow one column of a multicolumn foreign key to be null unless all foreign key columns are null; * if they are all null, the row is not required to have a match in the referenced table. * - MATCH SIMPLE (default) allows any of the foreign key columns to be null; if any of them are null, the row is not required to have a match in the referenced table. * - MATCH PARTIAL - PG docs say it's not implemented. */ type Match = 'FULL' | 'PARTIAL' | 'SIMPLE'; /** * - NO ACTION Produce an error indicating that the deletion or update would create a foreign key constraint violation. If the constraint is deferred, this error will be produced at constraint check time if there still exist any referencing rows. This is the default action. * - RESTRICT Produce an error indicating that the deletion or update would create a foreign key constraint violation. This is the same as NO ACTION except that the check is not deferrable. * - CASCADE Delete any rows referencing the deleted row, or update the values of the referencing column(s) to the new values of the referenced columns, respectively. * - SET NULL Set all the referencing columns, or a specified subset of the referencing columns, to null. A subset of columns can only be specified for ON DELETE actions. * - SET DEFAULT Set all the referencing columns, or a specified subset of the referencing columns, to their default values. A subset of columns can only be specified for ON DELETE actions. (There must be a row in the referenced table matching the default values, if they are not null, or the operation will fail.) */ type Action = 'NO ACTION' | 'RESTRICT' | 'CASCADE' | 'SET NULL' | 'SET DEFAULT'; interface BaseOptions { match?: Match; onUpdate?: Action; onDelete?: Action; dropMode?: TableData$1.DropMode; } interface Options extends BaseOptions { name?: string; } } export {}; } interface AdditionalNumberData { lt?: number; lte?: number; gt?: number; gte?: number; step?: number; int?: boolean; finite?: boolean; safe?: boolean; } interface BaseNumberData$1 extends Column$1.Data, AdditionalNumberData {} interface AdditionalStringData { min?: number; max?: number; length?: number; email?: boolean; url?: boolean; emoji?: boolean; uuid?: boolean; cuid?: boolean; cuid2?: boolean; ulid?: boolean; regex?: RegExp; includes?: string; startsWith?: string; endsWith?: string; datetime?: { offset?: boolean; precision?: number; }; ipv4?: true; ipv6?: true; nonEmpty?: boolean; trim?: boolean; toLowerCase?: boolean; toUpperCase?: boolean; } interface StringData$1 extends Column$1.Data, AdditionalStringData {} interface AdditionalDateData { min?: Date; max?: Date; } interface DateColumnData$1 extends Column$1.Data, AdditionalDateData {} interface ArrayMethodsData { min?: number; max?: number; length?: number; nonEmpty?: boolean; } type Code$1 = string | Codes$1; type Codes$1 = Code$1[]; interface ColumnToCodeCtx$1 { t: string; table: string; currentSchema: string; migration?: boolean; snakeCase?: boolean; sql?: string; isSqlUsed?: boolean; } type DateColumnInput$1 = string | number | Date; declare abstract class DateBaseColumn extends Column$1 { dateParsedByDriver?: boolean | undefined; __schema: Schema; __type: string; __inputType: DateColumnInput$1; inputSchema: ReturnType; data: DateColumnData$1; __outputType: string; outputSchema: ReturnType; __queryType: DateColumnInput$1; querySchema: ReturnType; operators: OperatorsDate$1; asNumber: Schema['dateAsNumber']; asDate: Schema['dateAsDate']; constructor(schema: Schema, dateParsedByDriver?: boolean | undefined); } declare class DateColumn$1 extends DateBaseColumn { dataType: 'date'; toCode(ctx: ColumnToCodeCtx$1, key: string): Code$1; } declare abstract class DateTimeBaseClass extends DateBaseColumn { data: DateColumnData$1 & { dateTimePrecision?: number; }; constructor(schema: Schema, dateTimePrecision?: number, dateParsedByDriver?: boolean); toSQL(): string; } declare abstract class DateTimeTzBaseClass extends DateTimeBaseClass { abstract baseDataType: string; toSQL(): string; } declare class TimestampColumn$1 extends DateTimeBaseClass { dataType: 'timestamp'; toCode(ctx: ColumnToCodeCtx$1, key: string): Code$1; } declare class TimestampTZColumn$1 extends DateTimeTzBaseClass { dataType: 'timestamptz'; baseDataType: 'timestamp'; toCode(ctx: ColumnToCodeCtx$1, key: string): Code$1; } declare class TimeColumn$1 extends Column$1 { __schema: Schema; __type: string; __inputType: ReturnType; inputSchema: ReturnType; data: DateColumnData$1 & { dateTimePrecision?: number; }; __outputType: string; outputSchema: ReturnType; __queryType: string; querySchema: ReturnType; dataType: 'time'; operators: OperatorsTime; constructor(schema: Schema, dateTimePrecision?: number); toCode(ctx: ColumnToCodeCtx$1, key: string): Code$1; } declare class IntervalColumn$1 extends Column$1 { __schema: Schema; __type: PostgresInterval; data: Column$1.Data & { fields?: string; precision?: number; }; __inputType: Partial; inputSchema: ReturnType; __outputType: PostgresInterval; outputSchema: ReturnType; __queryType: PostgresInterval; querySchema: ReturnType; dataType: 'interval'; operators: OperatorsDate$1; constructor(schema: Schema, fields?: string, precision?: number, parse?: (input: string) => PostgresInterval); toCode(ctx: ColumnToCodeCtx$1, key: string): Code$1; toSQL(): string; } declare class EnumColumn$1 extends Column$1 { enumName: string; options: T; __schema: Schema; operators: OperatorsOrdinalText$1; __type: T[number]; __inputType: T[number]; inputSchema: SchemaType; __outputType: T[number]; outputSchema: SchemaType; __queryType: T[number]; querySchema: SchemaType; dataType: string; constructor(schema: Schema, enumName: string, options: T, schemaType: SchemaType); toCode(ctx: ColumnToCodeCtx$1, key: string): Code$1; toSQL(): string; } interface ArrayColumnValue$1 { __type: unknown; inputSchema: any; __inputType: unknown; __outputType: unknown; outputSchema: any; __queryType: any; querySchema: any; toSQL(): string; toCode(ctx: ColumnToCodeCtx$1, key: string): Code$1; data: Column$1.Data; } interface ArrayData$1 extends Column$1.Data, ArrayMethodsData { item: Item; arrayDims: number; } declare class ArrayColumn$1 extends Column$1 { __schema: Schema; dataType: 'array'; operators: OperatorsArray$1; data: ArrayData$1; __type: Item['__type'][]; __inputType: Item['__type'][]; inputSchema: InputType; __outputType: Item['__outputType'][]; outputSchema: OutputType; __queryType: Item['__queryType'][]; querySchema: QueryType; constructor(schema: Schema, item: Item, __inputType: InputType, defaultEncode?: (input: unknown) => unknown, __outputType?: OutputType, __queryType?: QueryType); toSQL(): string; toCode(this: ArrayColumn$1, ctx: ColumnToCodeCtx$1, key: string): Code$1; } declare class JSONColumn$1 extends Column$1 { __schema: Schema; dataType: 'jsonb'; __type: T; __inputType: T; inputSchema: InputSchema; __outputType: T; outputSchema: InputSchema; __queryType: T; querySchema: InputSchema; operators: OperatorsJson$1; constructor(schema: Schema, __inputType: InputSchema, encodedByDriver?: boolean); toCode(ctx: ColumnToCodeCtx$1, key: string): Code$1; } declare class JSONTextColumn$1 extends Column$1 { __schema: Schema; dataType: 'json'; __type: T; __inputType: T; inputSchema: InputSchema; __outputType: T; outputSchema: InputSchema; __queryType: T; querySchema: InputSchema; operators: OperatorsText$1; private static _instance; static get instance(): JSONTextColumn$1; constructor(schema: Schema, __inputType: InputSchema); toCode(ctx: ColumnToCodeCtx$1, key: string): Code$1; } interface NumberColumnData$1 extends BaseNumberData$1, Column$1.Data { identity?: TableData$1.Identity; } interface SerialColumnData$1 extends NumberColumnData$1 { default: true; } declare abstract class NumberBaseColumn extends Column$1 { __schema: Schema; __type: number; __inputType: number; inputSchema: SchemaType; data: NumberColumnData$1; __outputType: number; outputSchema: SchemaType; __queryType: number; querySchema: SchemaType; operators: OperatorsNumber$1; } declare abstract class IntegerBaseColumn extends NumberBaseColumn> { data: NumberColumnData$1; querySchema: ReturnType; constructor(schema: Schema); } declare abstract class NumberAsStringBaseColumn extends Column$1 { __schema: Schema; __type: string; __inputType: InputType; inputSchema: ReturnType; operators: OperatorsNumber$1; __outputType: string; outputSchema: ReturnType; __queryType: InputType; querySchema: ReturnType; data: Column$1.Data; constructor(schema: Schema); } interface DecimalColumnData$1 extends Column$1.Data { numericPrecision?: number; numericScale?: number; } declare class DecimalColumn$1 extends NumberAsStringBaseColumn { data: DecimalColumnData$1; querySchema: ReturnType; operators: OperatorsNumber$1; dataType: 'numeric'; constructor(schema: Schema, numericPrecision?: number, numericScale?: number); toCode(ctx: ColumnToCodeCtx$1, key: string): Code$1; toSQL(): string; } declare class SmallIntColumn$1 extends IntegerBaseColumn { dataType: 'int2'; querySchema: ReturnType; constructor(schema: Schema); toCode(ctx: ColumnToCodeCtx$1, key: string): Code$1; identity(this: T, options?: TableData$1.Identity): Column$1.HasDefault; } declare class IntegerColumn$1 extends IntegerBaseColumn { dataType: 'int4'; querySchema: ReturnType; constructor(schema: Schema); toCode(ctx: ColumnToCodeCtx$1, key: string): Code$1; identity(this: T, options?: TableData$1.Identity): Column$1.HasDefault; } declare class BigIntColumn$1 extends NumberAsStringBaseColumn { dataType: 'int8'; querySchema: ReturnType; constructor(schema: Schema); toCode(ctx: ColumnToCodeCtx$1, key: string): Code$1; identity(this: T, options?: TableData$1.Identity): Column$1.HasDefault; } declare class RealColumn$1 extends NumberBaseColumn> { dataType: 'float4'; querySchema: ReturnType; constructor(schema: Schema); toCode(ctx: ColumnToCodeCtx$1, key: string): Code$1; } declare class DoublePrecisionColumn$1 extends NumberAsStringBaseColumn { dataType: 'float8'; querySchema: ReturnType; constructor(schema: Schema); toCode(ctx: ColumnToCodeCtx$1, key: string): Code$1; } declare class SmallSerialColumn$1 extends IntegerBaseColumn { dataType: 'int2'; data: SerialColumnData$1; querySchema: ReturnType; constructor(schema: Schema); toSQL(): string; toCode(ctx: ColumnToCodeCtx$1, key: string): Code$1; } declare class SerialColumn$1 extends IntegerBaseColumn { dataType: 'int4'; data: SerialColumnData$1; querySchema: ReturnType; constructor(schema: Schema); toSQL(): string; toCode(ctx: ColumnToCodeCtx$1, key: string): Code$1; } declare class BigSerialColumn$1 extends NumberAsStringBaseColumn { dataType: 'int8'; data: SerialColumnData$1; querySchema: ReturnType; constructor(schema: Schema); toSQL(): string; toCode(ctx: ColumnToCodeCtx$1, key: string): Code$1; } interface DefaultSchemaConfig$1 extends ColumnSchemaConfig$1 { nullable(this: T): Column$1.Nullable; parse(this: T, fn: (input: T['__type']) => Output): Column$1.Parse; parseNull(this: T, fn: () => Output): Column$1.ParseNull; encode(this: T, fn: (input: Input) => unknown): Column$1.Encode; /** * @deprecated use narrowType instead */ asType(this: T, _fn: (type: () => { type: Type; __inputType: Input; __outputType: Output; __queryType: Query; }) => Types): { [K in keyof T]: K extends '__type' ? Types['type'] : K extends keyof Types ? Types[K] : T[K]; }; narrowType(this: T, _fn: (type: () => { __inputType: T['__inputType'] extends never ? never : Type; __outputType: Type; __queryType: Type; }) => Types): { [K in keyof T]: K extends keyof Types ? Types[K] : T[K]; }; narrowAllTypes(this: T, _fn: (type: () => { __inputType: undefined extends Types['input'] ? T['__inputType'] : Types['input']; __outputType: undefined extends Types['output'] ? T['__outputType'] : Types['output']; __queryType: undefined extends Types['query'] ? T['__queryType'] : Types['query']; }) => Types): { [K in keyof T]: K extends keyof Types ? Types[K] : T[K]; }; dateAsNumber(this: T): Column$1.Parse; dateAsDate(this: T): Column$1.Parse; enum(dataType: string, type: T): EnumColumn$1; array(item: Item): ArrayColumn$1; json(): JSONColumn$1 : T, DefaultSchemaConfig$1>; jsonText(): JSONTextColumn$1 : T, DefaultSchemaConfig$1>; inputSchema(): undefined; outputSchema(): undefined; querySchema(): undefined; updateSchema(): undefined; pkeySchema(): undefined; smallint(): SmallIntColumn$1; integer(): IntegerColumn$1; real(): RealColumn$1; smallSerial(): SmallSerialColumn$1; serial(): SerialColumn$1; bigint(): BigIntColumn$1; decimal(precision?: number, scale?: number): DecimalColumn$1; doublePrecision(): DoublePrecisionColumn$1; bigSerial(): BigSerialColumn$1; money(): MoneyColumn$1; varchar(limit?: number): VarCharColumn$1; text(): TextColumn$1; string(limit?: number): StringColumn$1; citext(): CitextColumn$1; date(): DateColumn$1; timestampNoTZ(precision?: number): TimestampColumn$1; timestamp(precision?: number): TimestampTZColumn$1; } type DeleteArgs = T['__hasWhere'] extends true ? EmptyTuple$1 : [never]; type DeleteResult = T['__hasSelect'] extends true ? T : T['returnType'] extends undefined | 'all' ? SetQueryReturnsRowCountMany : SetQueryReturnsRowCount; interface DeleteSelf extends PickQueryHasSelectHasWhereResultReturnType, Query.Pick.IsNotReadOnly {} declare class QueryDelete { /** * This method deletes one or more rows, based on other conditions specified in the query. * * By default, `delete` will return a count of deleted records. * * Place `select`, `selectAll`, or `get` before `delete` to specify returning columns. * * Need to provide `where`, `findBy`, or `find` conditions before calling `delete`. * To prevent accidental deletion of all records, deleting without where will result in TypeScript and a runtime error. * * Use `all()` to delete ALL records without conditions: * * ```ts * await db.table.all().delete(); * ``` * * ```ts * // deletedCount is the number of deleted records * const deletedCount = await db.table.where(...conditions).delete(); * * // returns a single value, throws if not found * const id: number | undefined = await db.table * .findBy(...conditions) * .get('id') * .delete(); * * // returns an array of records with specified columns * const deletedRecord = await db.table * .select('id', 'name', 'age') * .where(...conditions) * .delete(); * * // returns an array of fully deleted records * const deletedUsersFull = await db.table * .selectAll() * .where(...conditions) * .delete(); * ``` * * `delete` supports joining, under the hood the join is transformed to `USING` and `WHERE` statements: * * ```ts * // delete all users who have corresponding profile records: * db.table.join(db.profile, 'profile.userId', 'user.id').all().delete(); * ``` * * `delete` can be used in {@link WithMethods.with} expressions: * * ```ts * db.$qb * // delete a record in one table * .with('a', db.table.find(1).select('id').delete()) * // delete a record in other table using the first table record id * .with('b', (q) => * db.otherTable.select('id').whereIn('aId', q.from('a').pluck('id')).delete(), * ) * .from('b'); * ``` */ delete(this: T, ..._args: DeleteArgs): DeleteResult; } interface QueryWithSoftDelete extends PickQueryResult, PickQueryReturnType, PickQueryHasSelect, PickQueryHasWhere, Query.Pick.IsNotReadOnly { __scopes: NonDeletedScope; } interface NonDeletedScope { nonDeleted: true; } /** * `softDelete` configures the table to set `deletedAt` to current time instead of deleting records. * All queries on such table will filter out deleted records by default. * * ```ts * import { defineTable } from './table-factory'; * * export const SomeTable = defineTable('some', (t) => ({ * id: t.identity().primaryKey(), * deletedAt: t.timestamp().nullable(), * })) * // true is for using `deletedAt` column * .softDelete(); * * // or provide a different column name * export const OtherTable = defineTable('other', (t) => ({ * id: t.identity().primaryKey(), * myDeletedAt: t.timestamp().nullable(), * })).softDelete('myDeletedAt'); * * const db = orchidORM( * { databaseURL: '...' }, * { * someTable: SomeTable, * }, * ); * * // deleted records are ignored by default * const onlyNonDeleted = await db.someTable; * ``` */ declare class SoftDeleteMethods { /** * `includeDeleted` disables the default `deletedAt` filter: * * ```ts * const allRecords = await db.someTable.includeDeleted(); * ``` */ includeDeleted(this: T): T; /** * `hardDelete` deletes records bypassing the `softDelete` behavior: * * ```ts * await db.someTable.find(1).hardDelete(); * ``` */ hardDelete(this: T, ..._args: DeleteArgs): DeleteResult; } interface QueryInternalColumnNameToKey { columnNameToKeyMap?: Map; } declare namespace RlsPolicy$1 { export type PolicyMode = 'PERMISSIVE' | 'RESTRICTIVE'; export type PolicyCommand = 'ALL' | 'SELECT' | 'INSERT' | 'UPDATE' | 'DELETE'; interface Base { name: string; to: string | string[]; } export interface ForSelectOrDelete extends Base { for: 'SELECT' | 'DELETE'; using: RawSqlBase$1; withCheck?: never; } export interface ForInsert extends Base { for: 'INSERT'; using?: never; withCheck: RawSqlBase$1; } export interface ForAllOrUpdate extends Base { for?: 'ALL' | 'UPDATE'; using: RawSqlBase$1; withCheck: RawSqlBase$1; } export type Policy = ForSelectOrDelete | ForInsert | ForAllOrUpdate; export {}; } declare namespace Rls$1 { interface TableConfigBase { enable?: boolean; force?: boolean; } interface TableConfig extends TableConfigBase { permit: [RlsPolicy$1.Policy, ...RlsPolicy$1.Policy[]]; restrict?: RlsPolicy$1.Policy[]; } interface TableDefaults { /** * Default RLS table flags for declarations that omit them. */ enable?: boolean; force?: boolean; } interface Options { tableRlsDefaults?: TableDefaults; } } declare namespace DefaultPrivileges$1 { export type ObjectType = (typeof DEFAULT_PRIVILEGE.OBJECT_TYPES)[number]; export interface Privilege { Table: (typeof DEFAULT_PRIVILEGE.PRIVILEGES.TABLE)[number]; Sequence: (typeof DEFAULT_PRIVILEGE.PRIVILEGES.SEQUENCE)[number]; Function: (typeof DEFAULT_PRIVILEGE.PRIVILEGES.FUNCTION)[number]; Type: (typeof DEFAULT_PRIVILEGE.PRIVILEGES.TYPE)[number]; Schema: (typeof DEFAULT_PRIVILEGE.PRIVILEGES.SCHEMA)[number]; LargeObject: (typeof DEFAULT_PRIVILEGE.PRIVILEGES.LARGE_OBJECT)[number]; } interface ObjectSetting { privileges?: T[]; grantablePrivileges?: T[]; } export interface SchemaTargetConfig { owner?: string; schema: string; all?: boolean; allGrantable?: boolean; tables?: ObjectSetting; sequences?: ObjectSetting; functions?: ObjectSetting; types?: ObjectSetting; } export interface GlobalTargetConfig { owner?: string; schema?: never; all?: boolean; allGrantable?: boolean; tables?: ObjectSetting; sequences?: ObjectSetting; functions?: ObjectSetting; types?: ObjectSetting; schemas?: ObjectSetting; largeObjects?: ObjectSetting; } export interface SupportedDefaultPrivileges { OBJECT_TYPES: string[]; PRIVILEGES: { TABLE: string[]; SEQUENCE: string[]; FUNCTION: string[]; TYPE: string[]; SCHEMA: string[]; LARGE_OBJECT?: string[]; }; } export type SchemaConfig = SchemaTargetConfig | GlobalTargetConfig; export {}; } declare const DEFAULT_PRIVILEGE: { OBJECT_TYPES: readonly ['TABLES', 'SEQUENCES', 'FUNCTIONS', 'TYPES', 'SCHEMAS', 'LARGE_OBJECTS']; PRIVILEGES: { TABLE: readonly ['ALL', 'SELECT', 'INSERT', 'UPDATE', 'DELETE', 'TRUNCATE', 'REFERENCES', 'TRIGGER', 'MAINTAIN']; SEQUENCE: readonly ['ALL', 'USAGE', 'SELECT', 'UPDATE']; FUNCTION: readonly ['ALL', 'EXECUTE']; TYPE: readonly ['ALL', 'USAGE']; SCHEMA: readonly ['ALL', 'USAGE', 'CREATE']; LARGE_OBJECT: readonly ['ALL', 'SELECT', 'UPDATE']; }; }; interface DbRole { name: string; super?: boolean; inherit?: boolean; createRole?: boolean; createDb?: boolean; canLogin?: boolean; replication?: boolean; connLimit?: number; validUntil?: Date; bypassRls?: boolean; config?: RecordOptionalString$1; defaultPrivileges?: DefaultPrivileges$1.SchemaConfig[]; } declare namespace Grant { type Role = string | [string, ...string[]]; type TablePrivilege = 'ALL' | 'SELECT' | 'INSERT' | 'UPDATE' | 'DELETE' | 'TRUNCATE' | 'REFERENCES' | 'TRIGGER' | 'MAINTAIN'; type SequencePrivilege = 'ALL' | 'USAGE' | 'SELECT' | 'UPDATE'; type RoutinePrivilege = 'ALL' | 'EXECUTE'; type TypePrivilege = 'ALL' | 'USAGE'; type DomainPrivilege = 'ALL' | 'USAGE'; type SchemaPrivilege = 'ALL' | 'USAGE' | 'CREATE'; type DatabasePrivilege = 'ALL' | 'CREATE' | 'CONNECT' | 'TEMPORARY' | 'TEMP'; interface SchemaGrant { to: Role; grantedBy?: string; schemas: string[]; privileges?: SchemaPrivilege[]; grantablePrivileges?: SchemaPrivilege[]; } interface TableGrant { to: Role; grantedBy?: string; tables: string[]; privileges?: TablePrivilege[]; grantablePrivileges?: TablePrivilege[]; } interface TableClassGrant { to: Role; grantedBy?: string; privileges?: TablePrivilege[]; grantablePrivileges?: TablePrivilege[]; } interface AllTablesInGrant { to: Role; grantedBy?: string; allTablesIn: string[]; privileges?: TablePrivilege[]; grantablePrivileges?: TablePrivilege[]; } interface SequenceGrant { to: Role; grantedBy?: string; sequences: string[]; privileges?: SequencePrivilege[]; grantablePrivileges?: SequencePrivilege[]; } interface AllSequencesInGrant { to: Role; grantedBy?: string; allSequencesIn: string[]; privileges?: SequencePrivilege[]; grantablePrivileges?: SequencePrivilege[]; } interface RoutineGrant { to: Role; grantedBy?: string; routines: string[]; privileges?: RoutinePrivilege[]; grantablePrivileges?: RoutinePrivilege[]; } interface AllRoutinesInGrant { to: Role; grantedBy?: string; allRoutinesIn: string[]; privileges?: RoutinePrivilege[]; grantablePrivileges?: RoutinePrivilege[]; } interface TypeGrant { to: Role; grantedBy?: string; types: string[]; privileges?: TypePrivilege[]; grantablePrivileges?: TypePrivilege[]; } interface DomainGrant { to: Role; grantedBy?: string; domains: string[]; privileges?: DomainPrivilege[]; grantablePrivileges?: DomainPrivilege[]; } interface DatabaseGrant { to: Role; grantedBy?: string; databases: string[]; privileges?: DatabasePrivilege[]; grantablePrivileges?: DatabasePrivilege[]; } type Privilege = SchemaGrant | TableGrant | AllTablesInGrant | SequenceGrant | AllSequencesInGrant | RoutineGrant | AllRoutinesInGrant | TypeGrant | DomainGrant | DatabaseGrant; interface InternalPrivilege { to: string[]; grantedBy?: string; schemas?: string[]; tables?: string[]; allTablesIn?: string[]; sequences?: string[]; allSequencesIn?: string[]; routines?: string[]; allRoutinesIn?: string[]; types?: string[]; domains?: string[]; databases?: string[]; privileges?: string[]; grantablePrivileges?: string[]; } type IgnoreSelector = string | RegExp | (string | RegExp)[]; interface Ignore { roles?: IgnoreSelector; schemas?: IgnoreSelector; tables?: IgnoreSelector; allTablesIn?: IgnoreSelector; sequences?: IgnoreSelector; allSequencesIn?: IgnoreSelector; routines?: IgnoreSelector; allRoutinesIn?: IgnoreSelector; types?: IgnoreSelector; domains?: IgnoreSelector; databases?: IgnoreSelector; } } interface QueryInternal$1 extends QueryInternalColumnNameToKey { runtimeDefaultColumns?: string[]; asyncStorage: AsyncStateStorage$1; scopes?: RecordUnknown$1; snakeCase?: boolean; noPrimaryKey: boolean; comment?: string; readOnly?: boolean; materialized?: boolean; generatorIgnored?: true; primaryKeys?: string[]; singlePrimaryKey: SinglePrimaryKey; uniqueColumns: UniqueColumns; uniqueColumnNames: UniqueColumnNames; uniqueColumnTuples: UniqueColumnTuples; uniqueConstraints: UniqueConstraints; extensions?: DbExtension$1[]; domains?: DbDomainArgRecord; generatorIgnore?: GeneratorIgnore$1; roles?: DbRole[]; rls?: Rls$1.Options; tableRls?: Rls$1.TableConfig; tableGrants?: Grant.TableClassGrant[]; viewData?: { query?: Query; sql?: string | RawSqlBase$1; recursive?: boolean; checkOption?: 'LOCAL' | 'CASCADED'; securityBarrier?: boolean; securityInvoker?: boolean; withData?: boolean; }; managedRolesSql?: string; defaultGrantedBy?: string; grants?: Grant.InternalPrivilege[]; tableData: TableData$1; nowSQL?: string; callbackArg?: Query; selectAllCount: number; /** * @see DbSharedOptions */ nestedCreateBatchMax: number; } type QuerySchema$1 = (() => string) | string; declare class QueryWithSchema { /** * Specifies the schema to be used as a prefix of a table name. * * Though this method can be used to set the schema right when building the query, * it's better to specify schema when calling `db(table, () => columns, { schema: string })` * * ```ts * db.table.withSchema('customSchema').select('id'); * ``` * * Resulting SQL: * * ```sql * SELECT "user"."id" FROM "customSchema"."user" * ``` * * You can set a **default** schema for all tables in a callback by using {@link $withOptions}. * * @param schema - a name of the database schema to use */ withSchema(this: T, schema: QuerySchema$1 | undefined): T; } interface QueryBuilder extends Query.NotReadOnlyQuery { returnType: undefined; } type SQLQueryArgs = TemplateLiteralArgs$1 | [RawSqlBase$1]; interface RawSqlBase$1 extends Expression$1 { _sql: string | TemplateLiteralArgs$1; _values?: RawSQLValues; } interface RawSql$1 extends Expression$1, RawSqlBase$1, ExpressionTypeMethod {} declare class RawSql$1> extends Expression$1 { result: { value: T; }; columnTypes: ColumnTypes; q: ExpressionData$1; _sql: string | TemplateLiteralArgs$1; _values?: RawSQLValues; constructor(sql: string | TemplateLiteralArgs$1, values?: RawSQLValues, type?: T); values(this: Self, values: RawSQLValues): Self; makeSQL(ctx: ToSqlValues$1, quotedAs?: string): string; } interface DynamicRawSQL$1 extends Expression$1, ExpressionTypeMethod {} declare class DynamicRawSQL$1> extends Expression$1 { fn: DynamicSQLArg; columnTypes: ColumnTypes; result: { value: T; }; q: ExpressionData$1; dynamicBefore: boolean; constructor(fn: DynamicSQLArg); makeSQL(ctx: ToSQLCtx$1, quotedAs?: string): string; } interface SqlFnMethods { /** * `sql.join` builds a SQL list from values and expressions. * Plain values are bound as query parameters, while SQL expressions render as SQL. * * Use it for SQL constructs such as `ARRAY[...]`, `IN (...)`, function arguments, * or tuple lists. The default separator is `, `. Provide a SQL expression as the * custom separator when a different separator is needed. * * ```ts * await db.user.whereSql`"id" IN (${sql.join([1, 2, 3])})`; * ``` * * ```ts * await db.user.whereSql` * (${sql.join([sql.ref('name'), sql.ref('age')])}) IN (${sql.join( * users.map((user) => sql`(${user.name}, ${user.age})`), * )}) * `; * ``` * * ```ts * await db.user.select({ * displayName: (q) => * sql`concat(${sql.join( * [q.column('firstName'), q.column('lastName')], * sql` || ' ' || `, * )})`, * }); * ``` */ join(items: readonly unknown[], separator?: RawSqlBase$1): SqlJoinExpression>; /** * `sql.ref` quotes a SQL identifier such as a table name, column name, or schema name. * Use it when you need to dynamically reference an identifier in raw SQL. * * ```ts * import { sql } from './baseTable'; * * const schema = 'my_schema'; * * // Produces: SET LOCAL search_path TO "my_schema" * await db.$query`SET LOCAL search_path TO ${sql.ref(schema)}` * ``` * * It handles dots to support qualified names: * * ```ts * // "my_schema"."my_table" * sql.ref('my_schema.my_table'); * ``` */ ref(name: string): SqlRefExpression; unsafe(sql: string | number | boolean): UnsafeSqlExpression; val(value: T): ValExpression$1; } interface SqlFn$1 extends SqlFnMethods { (this: T, ...args: Args): Args extends [RecordUnknown$1] ? (...sql: TemplateLiteralArgs$1) => RawSql$1 : RawSql$1; } declare class UnsafeSqlExpression extends Expression$1 { sql: string | number | boolean; result: { value: Column$1.Pick.QueryColumn; }; q: ExpressionData$1; constructor(sql: string | number | boolean); makeSQL(): string; } interface MutativeQueriesSelectRelationsQueryData { selectRelation?: true; } interface MutativeQueriesSelectRelationsSqlProp { mutativeQueriesSelectRelationsState?: MutativeQueriesSelectRelationsSqlState; } interface MutativeQueriesSelectRelationsSqlState { query: IsQuery$1; value?: MutativeQueriesSelectRelationsValue; } interface MutativeQueriesSelectRelationsValue { [K: string]: IsQuery$1; } interface SqlCommonOptions extends HasTableHook, HasCteHooks, MutativeQueriesSelectRelationsSqlProp {} interface SingleSqlItem$1 { text: string; values?: unknown[]; prepare?: true; runAfterQuery?: RunAfterQuery; } interface RunAfterQuery { (queryResult: QueryResult$1): void | Promise<{ result: unknown; }>; } interface SingleSql$1 extends SingleSqlItem$1, SqlCommonOptions {} interface BatchSql extends SqlCommonOptions { batch: SingleSql$1[]; } type Sql$1 = SingleSql$1 | BatchSql; declare class QuerySql { /** * @deprecated: use `sql` exported from the table factory file. * * When there is a need to use a piece of raw SQL, use the `sql` exported from the table factory file, it is also attached to query objects for convenience. * * When selecting a custom SQL, specify a resulting type with `` syntax: * * ```ts * import { sql } from './table-factory'; * * const result: { num: number }[] = await db.table.select({ * num: sql`random() * 100`, * }); * ``` * * In a situation when you want the result to be parsed, such as when returning a timestamp that you want to be parsed into a `Date` object, provide a column type in such a way: * * This example assumes that the `timestamp` column was overridden with `asDate` as shown in [Override column types](/guide/columns-overview#override-column-types). * * ```ts * import { sql } from './table-factory'; * * const result: { timestamp: Date }[] = await db.table.select({ * timestamp: sql`now()`.type((t) => t.timestamp()), * }); * ``` * * In some cases such as when using [from](/guide/orm-and-query-builder.html#from), setting column type via callback allows for special `where` operations: * * ```ts * const subQuery = db.someTable.select({ * sum: () => sql`$a + $b`.type((t) => t.decimal()).values({ a: 1, b: 2 }), * }); * * // `gt`, `gte`, `min`, `lt`, `lte`, `max` in `where` * // are allowed only for numeric columns: * const result = await db.$from(subQuery).where({ sum: { gte: 5 } }); * ``` * * Many query methods have a version suffixed with `Sql`, you can pass an SQL template literal directly to these methods. * These methods are: `whereSql`, `whereNotSql`, `orderSql`, `havingSql`, `fromSql`, `findBySql`. * * ```ts * await db.table.whereSql`"someValue" = random() * 100`; * ``` * * Interpolating values in template literals is completely safe: * * ```ts * // get value from user-provided params * const { value } = req.params; * * // SQL injection is prevented by a library, this is safe: * await db.table.whereSql`column = ${value}`; * ``` * * In the example above, TS cannot check if the table has `column` column, or if there are joined tables that have such column which will lead to error. * Instead, use the [column](/guide/sql-expressions#column) or [ref](/guide/sql-expressions#ref) to reference a column: * * ```ts * // ids will be prefixed with proper table names, no ambiguity: * db.table.join(db.otherTable, 'id', 'other.otherId').where` * ${db.table.column('id')} = 1 AND * ${db.otherTable.ref('id')} = 2 * `; * ``` * * SQL can be passed with a simple string, it's important to note that this is not safe to interpolate values in it. * * ```ts * import { sql } from './baseTable'; * * // no interpolation is okay * await db.table.where(sql({ raw: 'column = random() * 100' })); * * // get value from user-provided params * const { value } = req.params; * * // this is NOT safe, SQL injection is possible: * await db.table.where(sql({ raw: `column = random() * ${value}` })); * ``` * * To inject values into `sql({ raw: '...' })` SQL strings, denote it with `$` in the string and provide `values` object. * * Use `$$` to provide column or/and table name (`column` or `ref` are preferable). Column names will be quoted so don't quote them manually. * * ```ts * import { sql } from './baseTable'; * * // get value from user-provided params * const { value } = req.params; * * // this is SAFE, SQL injection are prevented: * await db.table.where( * sql({ * raw: '$$column = random() * $value', * values: { * column: 'someTable.someColumn', // or simply 'column' * one: value, * two: 123, * }, * }), * ); * ``` * * Summarizing: * * ```ts * import { sql } from './baseTable'; * * // simplest form: * sql`key = ${value}`; * * // with resulting type: * sql`key = ${value}`; * * // with column type for select: * sql`key = ${value}`.type((t) => t.boolean()); * * // with column name via `column` method: * sql`${db.table.column('column')} = ${value}`; * * // raw SQL string, not allowed to interpolate values: * sql({ raw: 'random()' }); * * // with resulting type and `raw` string: * sql({ raw: 'random()' }); * * // with column name and a value in a `raw` string: * sql({ * raw: `$$column = $value`, * values: { column: 'columnName', value: 123 }, * }); * * // combine template literal, column type, and values: * sql`($one + $two) / $one`.type((t) => t.numeric()).values({ one: 1, two: 2 }); * ``` * * @param args - template literal or an object { raw: string } * @return object that has `type` and `values` methods */ sql(this: PickQueryColumTypes, ...args: StaticSQLArgs$1): RawSql$1, ColumnTypes>; sql(this: PickQueryColumTypes, ...args: [DynamicSQLArg>]): DynamicRawSQL$1, ColumnTypes>; } interface QueryLogObject$1 { colors: boolean; beforeQuery(sql: SingleSql$1): unknown; afterQuery(sql: SingleSql$1, logData: unknown): void; onError(error: Error, sql: SingleSql$1, logData: unknown): void; } interface QueryLogger$1 { log(message: string): void; warn(message: string): void; error(message: string): void; } declare class QueryLog { /** * Override the `log` option, which can also be set in `createDb` or when creating a table instance: * * ```ts * // turn log on for this query: * await db.table.all().log(true); * await db.table.all().log(); // no argument for true * * // turn log off for this query: * await db.table.all().log(false); * ``` * * Use {@link $withOptions} to override `log` for a scope of a callback. */ log(this: T, log?: boolean): T; } interface SqlSessionState$1 { /** * Postgres role for SQL session context. * * `$withOptions` applies it around query execution; transaction options apply * it with transaction-local semantics. */ role?: string; /** * Postgres custom settings for SQL session context. * * `$withOptions` applies them around query execution; transaction options * apply them with transaction-local semantics. */ setConfig?: Record; } interface AsyncState$1 extends SqlSessionState$1 { transactionAdapter?: TransactionAdapter$1; transactionId?: number; afterCommit?: TransactionAfterCommitHook[]; log?: QueryLogObject$1; testTransactionCount?: number; schema?: QuerySchema$1; transactionRole?: SqlSessionState$1['role']; transactionSetConfig?: SqlSessionState$1['setConfig']; } /** * Async local storage of the query state that falls back to a state set for code running outside of its `run` callbacks. * * It wraps `AsyncLocalStorage` instead of extending it, because Node.js `run` restores the previous state read with `getStore`, * and an overridden `getStore` would leave the fallback state in the caller's context. */ declare class AsyncStateStorage$1 { /** * State of the innermost test transaction, for code running outside of `run` callbacks. */ fallback?: AsyncState$1; private storage; getStore(): AsyncState$1 | undefined; run(state: AsyncState$1, cb: () => Result): Result; } interface StorageOptions$1 extends SqlSessionState$1 { log?: boolean; schema?: QuerySchema$1; } interface ProcessedStorageOptions extends SqlSessionState$1 { log?: QueryLogObject$1; schema?: QuerySchema$1; } declare class QueryStorage { withOptions(this: PickQueryQAndInternal, options: StorageOptions$1, cb: () => Promise): Promise; } /** * Generic result returning from query methods. */ interface QueryResultRow$1 { [K: string]: any; } interface QueryResult$1 { rowCount: number; rows: T[]; /** * node-postgres and postgres-js: fields are present even for empty results. * Bun doesn't implement fields in the same way, fields are empty if no rows returned. */ fields: { name: string; }[]; } interface AdapterConfigBase$1 { databaseURL?: string; database?: string; user?: string; password?: string | (() => string | Promise); searchPath?: string; ssl?: any; /** * Postgres settings to apply when driver connections are configured. * * `searchPath` is normalized to `search_path` in this map. */ setConfig?: RecordString$1; schema?: QuerySchema$1; host?: string; /** * This option may be useful in CI when database container has started, CI starts performing next steps, * migrations begin to apply though database may be not fully ready for connections yet. * * Set `connectRetry: true` for the default backoff strategy. It performs 10 attempts starting with 50ms delay and increases delay exponentially according to this formula: * * ``` * (factor, defaults to 1.5) ** (currentAttempt - 1) * (delay, defaults to 50) * ``` * * So the 2nd attempt will happen in 50ms from start, 3rd attempt in 125ms, 3rd in 237ms, and so on. * * You can customize max attempts to be made, `factor` multiplier and the starting delay by passing: * * ```ts * const options = { * databaseURL: process.env.DATABASE_URL, * connectRetry: { * attempts: 15, // max attempts * strategy: { * delay: 100, // initial delay * factor: 2, // multiplier for the formula above * } * } * }; * * rakeDb(options, { ... }); * ``` * * You can pass a custom function to `strategy` to customize delay behavior: * * ```ts * import { setTimeout } from 'timers/promises'; * * const options = { * databaseURL: process.env.DATABASE_URL, * connectRetry: { * attempts: 5, * strategy(currentAttempt: number, maxAttempts: number) { * // linear: wait 100ms after 1st attempt, then 200m after 2nd, and so on. * return setTimeout(currentAttempt * 100); * }, * }, * }; * ``` */ connectRetry?: AdapterConfigConnectRetryParam | true; } interface AdapterConfigConnectRetryParam { attempts?: number; strategy?: AdapterConfigConnectRetryStrategyParam | AdapterConfigConnectRetryStrategy; } interface AdapterConfigConnectRetryStrategyParam { delay?: number; factor?: number; } interface AdapterConfigConnectRetryStrategy { (attempt: number, attempts: number): Promise | void; } interface AdapterTransactionOptions extends ProcessedStorageOptions { level?: IsolationLevel$1; readOnly?: boolean; deferrable?: boolean; } interface Adapter$1 { errorClass: new (...args: any[]) => Error; searchPath?: string; driverAdapter: DriverAdapter$1; isInTransaction(this: Adapter$1): this is TransactionAdapter$1; assignError(to: QueryError, from: Error): void; query(text: string, values?: unknown[], sqlSessionState?: SqlSessionState$1, prepare?: true): Promise>; arrays(text: string, values?: unknown[], sqlSessionState?: SqlSessionState$1, prepare?: true): Promise>; /** * Run a transaction * * `options` can be `undefined`. */ transaction(asyncStorage: AsyncStateStorage$1 | undefined, options: AdapterTransactionOptions | undefined, cb: (adapter: TransactionAdapter$1) => Promise): Promise; close(): Promise; getDatabase(): string; getUser(): string; getSearchPath(): string | undefined; getHost(): string; getSchema(): QuerySchema$1 | undefined; clone(params?: AdapterConfigBase$1): Adapter$1; } /** * Adapter interface for transaction contexts. */ interface TransactionAdapter$1 extends Adapter$1 { isInTransaction(this: Adapter$1): this is TransactionAdapter$1; savepoint(name: string, log: QueryLogObject$1 | undefined, cb: () => Promise): Promise; /** * This is a workaround for postgres-js savepoint limitations. * Postgres-js dictates this: * - must use its `savepoint` method over manual `SAVEPOINT` because when doing it manually there is no way to prevent transaction from being rolled back when a query in a savepoint fails. * - must use its `sql` client from inside the `savepoint` method for the lifetime of the savepoint because of the reason above. */ hackySavepoint(state: HackySavepointState, text: string, values?: unknown[], arraysMode?: boolean, prepare?: true, log?: QueryLogObject$1): Promise>; } type Pool = any; type Client = any; interface AdapterSchemaConfigOptions$1 { jsonEncodedByDriver?: boolean; dateParsedByDriver?: boolean; arrayEncode?(input: unknown): unknown; intervalParse?(input: string): PostgresInterval; } /** * Adapter class used by runtime orchestrator to create driver-specific adapters. */ interface DriverAdapter$1 { noFieldsForArrays?: boolean; schemaConfig?: AdapterSchemaConfigOptions$1; errorClass: new (...args: any[]) => Error; errorFields: RecordString$1; configure(config: AdapterConfigBase$1): Pool; manualPool: boolean; borrow(pool: Pool): Client; release(client: Client): void; queryClient(client: Client, text: string, values?: unknown[], arraysMode?: boolean, prepare?: true): Promise>; begin(pool: Pool, cb: (client: DriverClient) => Promise, options?: string): Promise; savepoint(client: Client, setClient: (client: Client) => void, name: string, cb: () => Promise, onSavepoint?: SavepointCallback, beforeRelease?: SavepointCallback, onRelease?: SavepointCallback, beforeRollback?: SavepointCallback, onRollback?: SavepointCallback): Promise; hackySavepoint(client: Client, setClient: (client: Client) => void, state: HackySavepointState, text: string, values?: unknown[], arraysMode?: boolean, prepare?: true, onSavepoint?: SavepointCallback, beforeRelease?: SavepointCallback, onRelease?: SavepointCallback, beforeRollback?: SavepointCallback, onRollback?: SavepointCallback): Promise>; close(pool: Pool): Promise; } type SavepointCallback = () => void; interface HackySavepointStateActiveSavepoint { release(): Promise; rollback(err: unknown): Promise; } interface HackySavepointState { name: string; activeSavepoint?: HackySavepointStateActiveSavepoint; } /** * Element of `afterCommit` transaction array. See {@link AsyncState.afterCommit}. */ type TransactionAfterCommitHook = unknown[] | Query | AfterCommitHook[] | AfterCommitStandaloneHook$1; interface AfterCommitHook { (data: unknown[], q: Query): unknown | Promise; } interface AfterCommitStandaloneHook$1 { (): unknown | Promise; } interface PickQueryDataParsers { defaultParsers?: ColumnsParsers; parsers?: ColumnsParsers; batchParsers?: BatchParsers; } type ColumnParser = FnUnknownToUnknown; interface BatchParserPathEntry { key: string; returnType: QueryReturnType$1; } interface BatchParser { path: BatchParserPathEntry[]; fn: (path: BatchParserPathEntry[], queryResult: { rows: unknown[]; }) => MaybePromise$1; } type ColumnsParsers = { [K in string]?: ColumnParser; }; type BatchParsers = BatchParser[]; interface QueryThen { (onfulfilled?: (value: T) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike): Promise; } type QueryThenShallowSimplify$1 = QueryThen>; type QueryThenShallowSimplifyArr = QueryThen[]>; type QueryThenShallowSimplifyOptional = QueryThen | undefined>; type QueryThenByQuery = T['returnType'] extends undefined | 'all' ? QueryThenShallowSimplifyArr> : T['returnType'] extends 'one' ? QueryThenShallowSimplifyOptional> : T['returnType'] extends 'oneOrThrow' ? QueryThenShallowSimplify$1> : T['returnType'] extends 'value' ? QueryThen : T['returnType'] extends 'valueOrThrow' ? QueryThen : T['returnType'] extends 'rows' ? QueryThen[keyof Result][][]> : T['returnType'] extends 'pluck' ? QueryThen : QueryThen; type QueryThenByReturnType = T extends undefined | 'all' ? QueryThenShallowSimplifyArr> : T extends 'one' ? QueryThenShallowSimplifyOptional> : T extends 'oneOrThrow' ? QueryThenShallowSimplify$1> : T extends 'value' ? QueryThen : T extends 'valueOrThrow' ? QueryThen : T extends 'rows' ? QueryThen[keyof Result][][]> : T extends 'pluck' ? QueryThen : QueryThen; interface QueryCatch$1 { (this: { then: (onfulfilled?: (value: Q) => any) => any; }, onrejected?: (reason: any) => TResult | PromiseLike): Promise; } interface QueryCatchers { catchUniqueError(this: { then: (onfulfilled?: (value: ThenResult) => any) => any; }, fn: (reason: QueryError) => CatchResult): Promise; } interface SelectSelf extends PickQuerySelectable, PickQueryHasSelect, PickQueryDefaultSelect, PickQueryShape$1, PickQueryRelations$1, PickQueryResult, PickQueryReturnType, PickQueryWithData {} type SelectArgs = ('*' | keyof T['__selectable'])[]; interface SubQueryAddition extends IsSubQuery { withData: T['withData']; } type SelectAsFnArg = EmptyObject$1 extends T['relations'] ? T : { [K in keyof T['relations'] | keyof T]: K extends keyof T['relations'] ? RelationQueryMaybeSingle & SubQueryAddition : K extends keyof T ? T[K] : never; }; interface SelectAsArg { [K: string]: keyof T['__selectable'] | Expression$1 | ((q: SelectAsFnArg) => unknown); } type SelectAsFnReturnType$1 = { result: Column$1.QueryColumns; returnType: Exclude; } | Expression$1; interface SelectAsCheckReturnTypes { [K: string]: PropertyKey | Expression$1 | ((q: never) => SelectAsFnReturnType$1); } type SelectReturnType = T['returnType'] extends 'valueOrThrow' ? 'oneOrThrow' : T extends 'value' ? 'one' : T['returnType'] extends 'pluck' ? 'all' : T['returnType']; type SelectResult = { [K in keyof T]: K extends '__hasSelect' ? true : K extends 'result' ? { [K in '*' extends Columns[number] ? Exclude | T['__defaultSelect'] : Columns[number] as T['__selectable'][K]['as']]: T['__selectable'][K]['column']; } & (T['__hasSelect'] extends (T['returnType'] extends 'value' | 'valueOrThrow' ? never : true) ? Omit : unknown) : K extends 'returnType' ? SelectReturnType : K extends 'then' ? QueryThenByReturnType, { [K in '*' extends Columns[number] ? Exclude | T['__defaultSelect'] : Columns[number] as T['__selectable'][K]['as']]: T['__selectable'][K]['column']; } & (T['__hasSelect'] extends (T['returnType'] extends 'value' | 'valueOrThrow' ? never : true) ? Omit : unknown)> : T[K]; }; type SelectResultObj$1 = Obj extends SelectAsCheckReturnTypes ? { [K in keyof T]: K extends '__hasSelect' ? true : K extends '__selectable' ? T['__selectable'] & SelectAsSelectable : K extends 'result' ? { [K in T['__hasSelect'] extends (T['returnType'] extends 'value' | 'valueOrThrow' ? never : true) ? keyof Obj | keyof T['result'] : keyof Obj]: K extends keyof Obj ? SelectAsValueResult : K extends keyof T['result'] ? T['result'][K] : never; } : K extends 'returnType' ? SelectReturnType : K extends 'then' ? QueryThenByReturnType, { [K in T['__hasSelect'] extends (T['returnType'] extends 'value' | 'valueOrThrow' ? never : true) ? keyof Obj | keyof T['result'] : keyof Obj]: K extends keyof Obj ? SelectAsValueResult : K extends keyof T['result'] ? T['result'][K] : never; }> : T[K]; } : `Invalid return type of ${{ [K in keyof Obj]: Obj[K] extends ((...args: any[]) => any) ? ReturnType extends SelectAsFnReturnType$1 ? never : K : never; }[keyof Obj] & string}`; type SelectResultColumnsAndObj = { [K in keyof T]: K extends '__hasSelect' ? true : K extends '__selectable' ? T['__selectable'] & SelectAsSelectable : K extends 'result' // Combine previously selected items, all columns if * was provided, ? { [K in ('*' extends Columns[number] ? Exclude | T['__defaultSelect'] : Columns[number]) | keyof Obj as K extends Columns[number] ? T['__selectable'][K]['as'] : K]: K extends keyof Obj ? SelectAsValueResult : T['__selectable'][K]['column']; } & (T['__hasSelect'] extends (T['returnType'] extends 'value' | 'valueOrThrow' ? never : true) ? Omit : unknown) : K extends 'returnType' ? SelectReturnType : K extends 'then' ? QueryThenByReturnType, { [K in ('*' extends Columns[number] ? Exclude | T['__defaultSelect'] : Columns[number]) | keyof Obj as K extends Columns[number] ? T['__selectable'][K]['as'] : K]: K extends keyof Obj ? SelectAsValueResult : T['__selectable'][K]['column']; } & (T['__hasSelect'] extends (T['returnType'] extends 'value' | 'valueOrThrow' ? never : true) ? Omit : unknown)> : T[K]; }; interface AllowedRelationOneQueryForSelectable extends IsSubQuery { result: Column$1.QueryColumns; returnType: 'value' | 'valueOrThrow' | 'one' | 'oneOrThrow'; } type SelectAsSelectable = UnionToIntersection<{ [K in keyof Obj]: Obj[K] extends ((q: never) => infer R extends AllowedRelationOneQueryForSelectable) ? { [C in R['returnType'] extends 'value' | 'valueOrThrow' ? K : keyof R['result'] as R['returnType'] extends 'value' | 'valueOrThrow' ? K : `${K & string}.${C & string}`]: { as: C; column: R['returnType'] extends 'value' | 'valueOrThrow' ? R['result']['value'] : R['result'][C & keyof R['result']]; }; } : never; }[keyof Obj]>; type SelectAsValueResult = Arg extends keyof T['__selectable'] ? T['__selectable'][Arg]['column'] : Arg extends Expression$1 ? Arg['result']['value'] : Arg extends ((q: never) => IsQuery$1) ? SelectSubQueryResult> : Arg extends ((q: never) => Expression$1) ? ReturnType['result']['value'] : Arg extends ((q: never) => IsQuery$1 | Expression$1) ? SelectSubQueryResult, Expression$1>> | Exclude, IsQuery$1>['result']['value'] : never; type SelectSubQueryResult = Arg['returnType'] extends undefined | 'all' ? ColumnsShape$1.MapToObjectArrayColumn : Arg['returnType'] extends 'value' | 'valueOrThrow' ? Arg['result']['value'] : Arg['returnType'] extends 'pluck' ? ColumnsShape$1.MapToPluckColumn : Arg['returnType'] extends 'one' ? ColumnsShape$1.MapToNullableObjectColumn : ColumnsShape$1.MapToObjectColumn; declare class Select { /** * Takes a list of columns to be selected, and by default, the query builder will select all columns of the table. * * The last argument can be an object. Keys of the object are column aliases, value can be a column name, sub-query, or raw SQL expression. * * ```ts * import { sql } from './baseTable' * * // select columns of the table: * db.table.select('id', 'name', { idAlias: 'id' }); * * // accepts columns with table names: * db.table.select('user.id', 'user.name', { nameAlias: 'user.name' }); * * // table name may refer to the current table or a joined table: * db.table * .join(db.message, 'authorId', 'user.id') * .select('user.name', 'message.text', { textAlias: 'message.text' }); * * // select value from the sub-query, * // this sub-query should return a single record and a single column: * db.table.select({ * subQueryResult: Otherdb.table.select('column').take(), * }); * * // select raw SQL value, specify the returning type via syntax: * db.table.select({ * raw: sql`1 + 2`, * }); * * // select raw SQL value, the resulting type can be set by providing a column type in such way: * db.table.select({ * raw: sql`1 + 2`.type((t) => t.integer()), * }); * * // same raw SQL query as above, but the sql is returned from a callback * db.table.select({ * raw: () => sql`1 + 2`.type((t) => t.integer()), * }); * ``` * * When you use the ORM and defined relations, `select` can also accept callbacks with related table queries: * * ```ts * await db.author.select({ * allBooks: (q) => q.books, * firstBook: (q) => q.books.order({ createdAt: 'ASC' }).take(), * booksCount: (q) => q.books.count(), * }); * ``` * * When you're selecting a relation that's connected via `belongsTo` or `hasOne`, it becomes available to use in `order` or in `where`: * * ```ts * // select books with their authors included, order by author name and filter by author column: * await db.books * .select({ * author: (q) => q.author, * }) * .order('author.name') * .where({ 'author.isPopular': true }); * ``` */ select>(this: T, ...args: Columns): SelectResult; select>(this: T, obj: Obj): SelectResultObj$1; select, Obj extends SelectAsArg>(this: T, ...args: [...columns: Columns, obj: Obj]): SelectResultColumnsAndObj; /** * When querying the table or creating records, all columns are selected by default, * but updating and deleting queries are returning affected row counts by default. * * Use `selectAll` to select all columns. If the `.select` method was applied before it will be discarded. * * ```ts * const selectFull = await db.table * .select('id', 'name') // discarded by `selectAll` * .selectAll(); * * const updatedFull = await db.table.selectAll().where(conditions).update(data); * * const deletedFull = await db.table.selectAll().where(conditions).delete(); * ``` */ selectAll(this: T): SelectResult; } type SelectItem = string | SelectAs$1 | Expression$1 | undefined; interface SelectAs$1 { selectAs: SelectAsValue; } interface SelectAsValue { [K: string]: string | Query | Expression$1 | undefined; } type QueryDataTransform = QueryDataTransformFn | { map: (record: unknown, index: number, array: unknown) => unknown; thisArg?: unknown; }; interface QueryDataTransformFn { (data: unknown, queryData: unknown): unknown; } declare class QueryTransform { /** * Transform the result of the query right after loading it. * * `transform` method should be called in the last order, other methods can't be chained after calling it. * * It is meant to transform the whole result of a query, for transforming individual records consider using {@link QueryMap.map}. * * The [hooks](/guide/hooks.html) that are going to run after the query will receive the query result **before** transferring. * * Consider the following example of a cursor-based pagination by `id`: * * ```ts * const lastId: number | undefined = req.query.cursor; * * type Result = { * nodes: { id: number; text: string }[]; * cursor?: number; * }; * * // result is only for demo, it will be inferred * const posts: Result = await db.post * .select('id', 'text') * .where({ id: { lt: lastId } }) * .order({ id: 'DESC' }) * .limit(100) * .transform((nodes) => ({ nodes, cursor: nodes.at(-1)?.id })); * ``` * * You can also use the `tranform` on nested sub-queries: * * ```ts * type Result = { * nodes: { * id: number; * text: string; * comments: { nodes: { id: number; text: string }[]; cursor?: number }; * }[]; * cursor?: number; * }; * * const postsWithComments: Result = await db.post * .select('id', 'text') * .select({ * comments: (q) => * q.comments * .select('id', 'text') * .transform((nodes) => ({ nodes, cursor: nodes.at(-1)?.id })), * }) * .transform((nodes) => ({ nodes, cursor: nodes.at(-1)?.id })); * ``` * * @param fn - function to transform query result with */ transform(this: T, fn: (input: T extends { then: QueryThen; } ? Data : never, queryData: QueryData$1) => Result): { [K in keyof T]: K extends 'returnType' ? 'valueOrThrow' : K extends 'result' ? { value: Column$1.Pick.QueryColumnOfType; } : K extends 'then' ? QueryThen : T[K]; }; } type SelectableOrExpression = '*' | keyof T['__selectable'] | Expression$1; type SelectableOrExpressions = ('*' | keyof T['__selectable'] | Expression$1)[]; type ExpressionOutput> = Expr extends keyof T['__selectable'] ? T['__selectable'][Expr]['column'] : Expr extends Expression$1 ? Expr['result']['value'] : never; type ExpressionChain = (OperatorToSQL | unknown)[]; interface ExpressionData$1 extends HasBeforeAndBeforeSet { chain?: ExpressionChain; expr?: Expression$1; before?: QueryBeforeHook$1[]; dynamicBefore?: boolean; getColumn?: Column$1; transform?: QueryDataTransform[]; } declare abstract class Expression$1 { abstract result: { value: T; }; abstract q: ExpressionData$1; meta: { kind: 'select'; }; toSQL(ctx: ToSqlValues$1, quotedAs?: string): string; /** * Transform the expression value after loading it. * * It is meant to transform expressions selected by a query. * * @param fn - function to transform expression value with */ transform(this: Self, fn: (input: Self['result']['value']['__type'], queryData: ExpressionData$1) => Result): Omit & { result: { value: Column$1.Pick.QueryColumnOfType; }; }; abstract makeSQL(ctx: ToSqlValues$1, quotedAs?: string): string; } type TemplateLiteralArgs$1 = [strings: TemplateStringsArray, ...values: unknown[]]; interface DynamicSQLArg { (sql: (...args: StaticSQLArgs$1) => Expression$1): Expression$1; } type StaticSQLArgs$1 = TemplateLiteralArgs$1 | [{ raw: string; values?: RawSQLValues; }]; type RawSQLValues = RecordUnknown$1; declare abstract class ExpressionTypeMethod { type(this: T, fn: (types: T['columnTypes']) => C): // Omit is optimal Omit & { result: { value: C; }; }; } interface WithDataItem { table: string; shape: Column$1.QueryColumns; } interface WithDataItems { [K: string]: WithDataItem; } interface CteItem { n: string | ((as: string) => void); o?: CteOptions; q?: SubQueryForSql; s?: Expression$1; p?: boolean; } interface CteOptions { columns?: string[]; recursive?: true; materialized?: true; notMaterialized?: true; } interface TopCTE { names: RecordUnknown$1; stack: string[][]; append: string[][]; } interface PickQueryTable { table?: string; } interface PickQueryThen { then: unknown; } interface PickQueryHasSelect { __hasSelect: boolean; } interface PickQueryHasWhere { __hasWhere: boolean; } interface PickQueryDefaults { __defaults: EmptyObject$1; } interface PickQueryTsQuery { __tsQuery?: string; } interface PickQueryScopes { __scopes: EmptyObject$1; } interface PickQueryDefaultSelect { __defaultSelect: PropertyKey; } interface PickQueryHasSelectResultReturnType extends PickQueryHasSelect, PickQueryResult, PickQueryReturnType {} interface PickQueryHasSelectResultShapeAsRelations extends PickQueryHasSelect, PickQueryResult, PickQueryShape$1, PickQueryAs, PickQueryRelations$1 {} interface PickQueryHasSelectHasWhereResultReturnType extends PickQueryHasSelect, PickQueryHasWhere, PickQueryResult, PickQueryReturnType {} interface PickQueryHasSelectResult extends PickQueryHasSelect, PickQueryResult {} interface PickQuerySelectable { __selectable: QuerySelectable; } interface PickQuerySelectableResult extends PickQuerySelectable, PickQueryResult {} interface PickQuerySelectableRelations$1 extends PickQuerySelectable, PickQueryRelations$1 {} interface PickQuerySelectableResultWindows extends PickQuerySelectable, PickQueryResult, PickQueryWindows {} interface PickQuerySelectableResultRelationsWindows extends PickQuerySelectableResult, PickQueryRelations$1, PickQueryWindows {} interface PickQueryMetaSelectableResultRelationsWindowsColumnTypes extends PickQuerySelectableResultRelationsWindows, PickQueryColumTypes {} interface PickQuerySelectableShapeAs extends PickQuerySelectable, PickQueryShape$1, PickQueryAs {} interface PickQueryTableMetaShapeTableAs extends PickQuerySelectableShapeAs, PickQueryTable {} interface PickQuerySelectableShapeRelationsWithData extends PickQuerySelectable, PickQueryShape$1, PickQueryRelations$1, PickQueryWithData {} interface PickQuerySelectableShapeRelationsWithDataAs extends PickQuerySelectableShapeRelationsWithData, PickQueryAs {} interface PickQuerySelectableShapeRelationsWithDataAsResultReturnType extends PickQuerySelectableShapeRelationsWithDataAs, PickQueryResult, PickQueryReturnType {} interface PickQuerySelectableRelationsResultReturnType extends PickQuerySelectableRelations$1, PickQueryResult, PickQueryReturnType {} interface PickQuerySelectableResultRelationsWithDataReturnType extends PickQuerySelectable, PickQueryResult, PickQueryRelations$1, PickQueryWithData, PickQueryReturnType {} interface PickQuerySelectableResultRelationsWithDataReturnTypeShapeAs extends PickQuerySelectableResultRelationsWithDataReturnType, PickQueryShape$1, PickQueryAs {} interface PickQuerySelectableShape extends PickQuerySelectable, PickQueryShape$1 {} interface PickQuerySelectableColumnTypes extends PickQuerySelectable, PickQueryColumTypes {} interface PickQuerySelectableShapeRelationsReturnTypeIsSubQuery extends PickQueryIsSubQuery, PickQuerySelectable, PickQueryShape$1, PickQueryRelations$1, PickQueryReturnType {} interface PickQuerySelectableResultInputTypeAs extends PickQuerySelectableResult, PickQueryInputType$1, PickQueryAs {} interface PickQuerySelectableResultAs extends PickQuerySelectable, PickQueryResult, PickQueryAs {} interface PickQueryIsSubQuery { __subQuery?: boolean; } interface PickQueryResult { result: Column$1.QueryColumns; } interface PickQueryShape$1 { shape: Column$1.QueryColumns; } interface PickQueryReturnType { returnType: QueryReturnType$1; } interface PickQueryResultReturnType extends PickQueryResult, PickQueryReturnType {} interface PickQueryResultUniqueColumns extends PickQueryResult { internal: { uniqueColumns: unknown; }; } interface PickQueryResultReturnTypeUniqueColumns extends PickQueryResultUniqueColumns, PickQueryReturnType {} interface PickQueryUniqueProperties { internal: { uniqueColumnNames: unknown; uniqueColumnTuples: unknown; uniqueConstraints: unknown; }; } interface PickQueryInputType$1 { __inputType: RecordUnknown$1; } interface PickQueryWithData { withData: WithDataItems; } interface PickQueryWindows { windows: EmptyObject$1; } interface PickQueryRelations$1 { relations: RelationsBase$1; } interface PickQueryRelationsDataForCreate { relationsDataForCreate: RelationsDataForCreateBase; } interface PickQueryRelationsDataForCreateOptional { relationsDataForCreateOptional: RelationsDataForCreateOptionalBase; } interface PickQueryColumTypes { columnTypes: unknown; } interface PickQueryWithDataColumnTypes extends PickQueryWithData, PickQueryColumTypes {} interface PickQueryResultColumnTypes extends PickQueryResult, PickQueryColumTypes {} interface PickQueryAs { __as: string; } interface PickQueryResultAs extends PickQueryResult, PickQueryAs {} interface PickQueryResultAsRelations extends PickQueryResultAs, PickQueryRelations$1 {} interface PickQueryShapeAsRelations extends PickQueryShape$1, PickQueryAs, PickQueryRelations$1 {} interface PickQueryRelationsWithData extends PickQueryWithData, PickQueryRelations$1 {} interface PickQuerySinglePrimaryKey { internal: { singlePrimaryKey: unknown; }; } interface PickQueryShapeSinglePrimaryKey extends PickQueryShape$1, PickQuerySinglePrimaryKey {} interface PickQueryShapeResultSinglePrimaryKey extends PickQueryShapeSinglePrimaryKey, PickQueryResult {} interface PickQueryShapeResultReturnTypeSinglePrimaryKey extends PickQueryShapeResultSinglePrimaryKey, PickQueryReturnType {} interface PickQueryQ$1 { q: QueryData$1; } interface PickQueryInternal$1 { internal: QueryInternal$1; } interface PickQueryQAndInternal extends IsQuery$1, PickQueryQ$1, PickQueryInternal$1 {} interface PickQueryDataAliases { aliases?: RecordString$1; } interface QueryDataAliases extends PickQueryDataAliases { as?: string; outerAliases?: RecordString$1; } type SetQueryTableAlias = { [K in keyof T]: K extends '__selectable' ? Omit & { [K in keyof T['shape'] & string as `${As}.${K}`]: { as: K; column: T['shape'][K]; }; } : K extends '__as' ? As : T[K]; }; type AsQueryArg = PickQuerySelectableShapeAs; declare abstract class QueryAsMethods { /** * Sets table alias: * * ```ts * db.table.as('u').select('u.name'); * * // Can be used in the join: * db.table.join(db.profile.as('p'), 'p.userId', 'user.id'); * ``` * * @param as - alias for the table of this query */ as(this: T, as: As): SetQueryTableAlias; } declare class QueryClone { /** * Clones the current query chain, useful for re-using partial query snippets in other queries without mutating the original. * * Used under the hood, and not really needed on the app side. */ clone(this: T): T; } interface CteArgsOptions { columns?: string[] | boolean; materialized?: true; notMaterialized?: true; } interface CteRecursiveOptions extends CteArgsOptions { union?: 'UNION' | 'UNION ALL' | 'INTERSECT' | 'INTERSECT ALL' | 'EXCEPT' | 'EXCEPT ALL'; } interface CteQueryBuilder extends Query { sql: QuerySql['sql']; relations: EmptyObject$1; withData: T['withData']; } type CteResult = { [K in keyof T]: K extends 'withData' ? { [K in keyof T['withData'] | Name]: K extends Name ? { table: Name; shape: Q['result']; } : K extends keyof T['withData'] ? T['withData'][K] : never; } : T[K]; }; type CteSqlResult = { [K in keyof T]: K extends 'withData' ? { [K in Name | keyof T['withData']]: K extends Name ? { table: Name; shape: Shape; } : K extends keyof T['withData'] ? T['withData'][K] : never; } : T[K]; }; declare class CteQuery { /** * Use `with` to add a Common Table Expression (CTE) to the query. * * `with` can be chained to any table on `db` instance, or to `db.$qb`, * note that in the latter case it won't have customized column types to use for typing SQL. * * ```ts * import { sql } from './baseTable'; * * // can access custom columns when using off a table * db.anyTable.with('x', (q) => * q.select({ column: (q) => sql`123`.type((t) => t.customColumn()) }), * ); * * // only default columns are available when using off `$qb` * db.$qb.with('x', (q) => * q.select({ column: (q) => sql`123`.type((t) => t.integer()) }), * ); * ``` * * `with` accepts query objects, callbacks returning query objects, and custom SQL expressions returned from callbacks. * * ```ts * import { sql } from './baseTable'; * * db.table * .with( * 'alias', * // define CTE by building a query * db.table.select('one', 'two', 'three').where({ x: 123 }), * ) * .from('alias') * .select('one') * .where({ two: 123 }); * * // 2nd argument can be a callback accepting a query builder * db.table * .with('alias', (q) => * // select a custom sql * q.select({ column: (q) => sql`123`.type((t) => t.integer()) }), * ) * .from('alias') * .select('column') * .where({ column: 123 }); * * // 2nd argument can be used for options * db.table * .with( * 'alias', * { * // all parameters are optional * materialized: true, * notMaterialized: true, * }, * db.table, * ) * .from('alias'); * ``` * * One `WITH` expression can reference the other: * * ```ts * db.$qb * .with('a', db.table.select('id', 'name')) * .with('b', (q) => q.from('a').where({ key: 'value' })) * .from('b'); * ``` * * Defined `WITH` expression can be used in `.from` or `.join` with all the type safeness: * * ```ts * db.table.with('alias', db.table).from('alias').select('alias.id'); * * db.firstTable * .with('secondTable', db.secondTable) * .join('secondTable', 'secondTable.someId', 'firstTable.id') * .select('firstTable.column', 'secondTable.column'); * ``` * * ## creating records using `with` values * * You can use values returned from `with` statements when creating records: * * ```ts * db.table * .with('created', () => db.someTable.create(data).select('one', 'two')) * .create({ * column: (q) => q.from('created').get('one'), * otherColumn: (q) => q.from('created').get('two'), * }); * * // A record in `with` is created once, its values are used to create two records * db.table * .with('created', () => db.someTable.create(data).select('one', 'two')) * .createMany([ * { * column: (q) => q.from('created').get('one'), * otherColumn: (q) => q.from('created').get('two'), * }, * { * column: (q) => q.from('created').get('one'), * otherColumn: (q) => q.from('created').get('two'), * }, * ]); * ``` */ with(this: T, name: Name, query: Q | ((q: CteQueryBuilder) => Q)): CteResult; with(this: T, name: Name, options: CteArgsOptions, query: Q | ((q: CteQueryBuilder) => Q)): CteResult; /** * It is priceless for fetching tree-like structures, or any other recursive cases. * * For example, it is useful for loading a tree of categories, where one category can include many other categories. * * Similarly to [with](#with), `withRecursive` can be chained to any table or `db.$qb`. * * For the first example, consider the employee table, an employee may or may not have a manager. * * ```ts * export const Employee = defineTable('employee', (t) => ({ * id: t.identity().primaryKey(), * name: t.string(), * managerId: t.integer().nullable(), * })); * ``` * * The task is to load all subordinates of the manager with the id 1. * * ```ts * db.$qb * .withRecursive( * 'subordinates', * // the base, anchor query: find the manager to begin recursion with * db.employee.select('id', 'name', 'managerId').find(1), * // recursive query: * // find employees whos managerId is id from the surrounding subordinates CTE * (q) => * q * .from(db.employee) * .select('id', 'name', 'managerId') * .join('subordinates', 'subordinates.id', 'profile.managerId'), * ) * .from('subordinates'); * ``` * * As being shown, `withRecursive` accepts one query to begin with, and a second query in a callback that can reference the surrounding table expression "subordinates". * * These two queries are joined with `UNION ALL` by default. * * You can customize it by passing options after the name. * * ```ts * db.$qb * .withRecursive( * 'subordinates', * { * // all parameters are optional * union: 'UNION', * materialized: true, * notMaterialized: true, * }, * // ...snip * ) * .from('subordinates'); * ``` * * Recursive query can be constructed with basic SQL instructions only, without referencing other tables. * In the following example, we recursively select numbers from 1 to 100, and additionally apply n > 10 filter in the end. * * ```ts * import { sql } from './baseTable'; * * db.$qb * .withRecursive( * 't', * // select `1 AS n` for the base query * (q) => q.select({ n: (q) => sql`1`.type((t) => t.integer()) }), * // select `n + 1 AS n` for the recursive part * (q) => * q * .from('t') * // type can be omitted here because it was defined in the base query * .select({ n: (q) => sql`n + 1` }) * .where({ n: { lt: 100 } }), * ) * .from('t') * .where({ n: { gt: 10 } }); * ``` */ withRecursive>(this: T, name: Name, base: Q | ((qb: CteQueryBuilder) => Q), recursive: (qb: { [K in keyof Result]: K extends 'result' ? Q['result'] : Result[K]; }) => PickQueryResult): Result; withRecursive>(this: T, name: Name, options: CteRecursiveOptions, base: Q | ((qb: CteQueryBuilder) => Q), recursive: (qb: { [K in keyof Result]: K extends 'result' ? Q['result'] : Result[K]; }) => PickQueryResult): Result; /** * Use `withSql` to add a Common Table Expression (CTE) based on a custom SQL. * * Similarly to [with](#with), `withRecursive` can be chained to any table or `db.$qb`. * * ```ts * import { sql } from './baseTable'; * * db.table * .withSql( * 'alias', * // define column types of the expression: * (t) => ({ * one: t.integer(), * two: t.string(), * }), * // define SQL expression: * (q) => sql`VALUES (1, 'two')`, * ) * // is not prefixed in the middle of a query chain * .withSql( * 'second', * (t) => ({ * x: t.integer(), * }), * (q) => sql`VALUES (1)`, * ) * .from('alias'); * ``` * * Options can be passed via a second argument: * * ```ts * import { sql } from './baseTable'; * * db.table * .withSql( * 'alias', * { * // all parameters are optional * recursive: true, * materialized: true, * notMaterialized: true, * }, * (t) => ({ * one: t.integer(), * two: t.string(), * }), * (q) => sql`VALUES (1, 'two')`, * ) * .from('alias'); * ``` */ withSql(this: T, name: Name, options: CteOptions, shape: (t: T['columnTypes']) => Shape, expr: (q: T) => Expression$1): CteSqlResult; withSql(this: T, name: Name, shape: (t: T['columnTypes']) => Shape, expr: (q: T) => Expression$1): CteSqlResult; } interface FromQuerySelf extends PickQuerySelectable, PickQueryShape$1, PickQueryReturnType, PickQueryWithData, PickQueryAs, PickQueryHasSelect {} type FromArg$1 = IsQuery$1 | Exclude; type FromResult$1>> = Arg extends string ? T['withData'] extends WithDataItems ? { [K in keyof T]: K extends '__selectable' ? SelectableFromShape$1 : K extends 'result' ? T['withData'][Arg]['shape'] : K extends 'then' ? QueryThenByQuery : T[K]; } : SetQueryTableAlias : Arg extends PickQuerySelectableResultInputTypeAs ? { [K in keyof T]: K extends '__defaultSelect' ? keyof Arg['result'] : K extends '__selectable' ? SelectableFromShape$1 : K extends '__as' ? Arg['__as'] : K extends 'result' ? Arg['result'] : K extends 'shape' ? Arg['result'] : K extends '__inputType' ? Arg['__inputType'] : K extends 'then' ? QueryThenByQuery : T[K]; } : Arg extends (infer A)[] ? { [K in keyof T]: K extends '__selectable' ? UnionToIntersection : T[K]; } : T; declare class FromMethods { /** * Set the `FROM` value, by default the table name is used. * * `from` determines a set of available tables and columns withing the query, * and thus it must not follow `select`, use `select` only after `from`. * * ```ts * // accepts sub-query: * db.table.from(db.otherTable.select('foo', 'bar')); * * // accepts alias of `WITH` expression: * q.with('withTable', db.table.select('id', 'name')) * .from('withTable') * // `select` is after `from` * .select('id', 'name'); * ``` * * `from` can accept multiple sources: * * ```ts * db.table * // add a `WITH` statement called `withTable * .with('withTable', db.table.select('one')) * // select from `withTable` and from `otherTable` * .from('withTable', db.otherTable.select('two')) * // source names and column names are properly typed when selecting * .select('withTable.one', 'otherTable.two'); * ``` * * @param arg - query or name of CTE table */ from>>(this: T, arg: T['__hasSelect'] extends true ? '`select` must be placed after `from`' : Arg): FromResult$1; /** * Set the `FROM` value with custom SQL: * * ```ts * const value = 123; * db.table.fromSql`value = ${value}`; * ``` * * @param args - SQL expression */ fromSql(this: T, ...args: SQLQueryArgs): T; /** * Adds `ONLY` SQL keyword to the `FROM`. * When selecting from a parent table that has a table inheritance, * setting `only` will make it to select rows only from the parent table. * * ```ts * db.table.only(); * * // disabling `only` after being enabled * db.table.only().only(false); * ``` * * @param only - can be disabled by passing `false` if was enabled previously. */ only(this: T, only?: boolean): T; } interface QueryGetSelf extends PickQuerySelectable, PickQueryRelationsWithData {} type GetArg = GetStringArg | Expression$1 | ((q: SelectAsFnArg) => Expression$1 | Query.Pick.SingleValueResult); type GetStringArg = keyof T['__selectable'] & string; type ResolveGetArgColumn = Arg extends Expression$1 ? Arg['result']['value'] : Arg extends ((q: never) => infer R) ? R extends Expression$1 ? R['result']['value'] : R extends Query.Pick.SingleValueResult ? R['result']['value'] : never : never; type GetResult> = Arg extends string ? SetQueryReturnsValueOrThrow : SetQueryReturnsColumnOrThrow>; type OptionalValueColumn = { [K in keyof C]: K extends '__outputType' ? C[K] | undefined : C[K]; }; type GetResultOptional> = Arg extends string ? SetQueryReturnsValueOptional : SetQueryReturnsColumnOptional>>; declare class QueryGet { /** * `.get` returns a single value, adds `LIMIT 1` to the query, and accepts a column name or a raw SQL expression. * * `get` throws a `NotFoundError` when not found, and `getOptional` returns `undefined`. * * ```ts * import { NumberColumn } from 'orchid-orm'; * import { sql } from './baseTable'; * * const firstName: string = await db.table.get('name'); * * const rawResult: number = await db.table.get(sql((t) => t.integer())`1 + 1`); * * const firstNameOptional: string | undefined = await db.table.getOptional( * 'name', * ); * ``` * * @param arg - string for a column to get, or a raw SQL */ get>(this: T, arg: Arg): GetResult; /** * `.getOptional` returns a single value or undefined when not found: * * ```ts * const firstName: string | undefined = await db.table.getOptional('name'); * ``` * * @param arg - string for a column to get, or a raw SQL */ getOptional>(this: T, arg: Arg): GetResultOptional; } type HavingItem = TemplateLiteralArgs$1 | Expression$1[]; interface QueryReturningOne extends IsQuery$1 { result: Column$1.QueryColumns; returnType: 'one' | 'oneOrThrow'; } type CreateRawOrFromResult = T extends { isCount: true; } ? T : T['returnType'] extends undefined | 'all' ? SetQueryReturnsOne : T['returnType'] extends 'pluck' ? SetQueryReturnsColumn : T; type InsertRawOrFromResult = T['__hasSelect'] extends true ? T['returnType'] extends undefined | 'all' ? SetQueryReturnsOne : T['returnType'] extends 'pluck' ? SetQueryReturnsColumn : T : SetQueryReturnsRowCount; type CreateManyFromResult = T extends { isCount: true; } ? T : T['returnType'] extends 'one' | 'oneOrThrow' ? SetQueryReturnsAll : T['returnType'] extends 'value' | 'valueOrThrow' ? SetValueQueryReturnsPluckColumn : T; type InsertManyFromResult = T['__hasSelect'] extends true ? T['returnType'] extends 'one' | 'oneOrThrow' ? SetQueryReturnsAll : T['returnType'] extends 'value' | 'valueOrThrow' ? SetValueQueryReturnsPluckColumn : T : SetQueryReturnsRowCountMany; declare const _queryInsertManyFrom: (q: T, query: Q, data: Omit, keyof Q['result']>[]) => InsertManyFromResult; declare class QueryCreateFrom { /** * Inserts a single record based on a query that selects a single record. * * Performs a single SQL query based on `INSERT ... SELECT ... FROM`. * * See {@link createManyFrom} to insert multiple records based on a single record query, * and {@link createForEachFrom} to insert a record per every one found by the query. * * The first argument is a query of a **single** record, it should have `find`, `take`, or similar. * * The second optional argument is a data which will be merged with columns returned by the query. * * The data for the second argument is the same as in {@link create}. * * Columns with runtime defaults (defined with a callback) are supported here. * The value for such a column will be injected unless selected from a related table or provided in a data object. * * ```ts * const oneRecord = await db.table.createOneFrom( * db.relatedTable * // use select to map columns from one table to another * .select({ * // relatedTable's id will be inserted as "relatedId" * relatedId: 'id', * }) * .findBy({ key: 'value' }), * // optional argument: * { * key: 'value', * // supports sql, nested select, create, update, delete queries * fromSql: () => sql`custom sql`, * fromQuery: () => db.otherTable.find(id).update(data).get('column'), * fromRelated: (q) => q.relatedTable.create(data).get('column'), * }, * ); * ``` * * The query above will produce such a SQL (omitting `from*` values): * * ```sql * INSERT INTO "table"("relatedId", "key") * SELECT "relatedTable"."id" AS "relatedId", 'value' * FROM "relatedTable" * WHERE "relatedTable"."key" = 'value' * LIMIT 1 * RETURNING * * ``` * * @param query - query to create new records from * @param data - additionally you can set some columns */ createOneFrom(this: T, query: Q, data?: CreateDataOmit): CreateRawOrFromResult; /** * Works exactly as {@link createOneFrom}, except that it returns inserted row count by default. * * @param query - query to create new records from * @param data - additionally you can set some columns */ insertOneFrom(this: T, query: Q, data?: CreateDataOmit): InsertRawOrFromResult; /** * Inserts multiple records based on a query that selects a single record. * * Performs a single SQL query based on `INSERT ... SELECT ... FROM`. * * See {@link createOneFrom} to insert a single record based on a single record query, * and {@link createForEachFrom} to insert a record per every one found by the query. * * The first argument is a query of a **single** record, it should have `find`, `take`, or similar. * * The second argument is array of objects to be merged with columns returned by the query. * * The data for the second argument is the same as in {@link createMany}. * * Columns with runtime defaults (defined with a callback) are supported here. * The value for such a column will be injected unless selected from a related table or provided in a data object. * * ```ts * const twoRecords = await db.table.createManyFrom( * db.relatedTable * // use select to map columns from one table to another * .select({ * // relatedTable's id will be inserted as "relatedId" * relatedId: 'id', * }) * .findBy({ key: 'value' }), * [ * { * key: 'value 1', * // supports sql, nested select, create, update, delete queries * fromSql: () => sql`custom sql`, * fromQuery: () => db.otherTable.find(id).update(data).get('column'), * fromRelated: (q) => q.relatedTable.create(data).get('column'), * }, * { * key: 'value 2', * }, * ], * ); * ``` * * The query above will produce such a SQL (omitting `from*` values): * * ```sql * WITH "relatedTable" AS ( * SELECT "relatedTable"."id" AS "relatedId", 'value' * FROM "relatedTable" * WHERE "relatedTable"."key" = 'value' * LIMIT 1 * ) * INSERT INTO "table"("relatedId", "key") * SELECT "relatedTable".*, v."key"::text * FROM "relatedTable", (VALUES ('value1'), ('value2')) v("key") * RETURNING * * ``` * * @param query - query to create new records from * @param data - array of records to create */ createManyFrom(this: T, query: Q, data: CreateDataOmit[]): CreateManyFromResult; /** * Works exactly as {@link createManyFrom}, except that it returns inserted row count by default. * * @param query - query to create new records from * @param data - array of records to create */ insertManyFrom(this: T, query: Q, data: CreateDataOmit[]): InsertManyFromResult; /** * Inserts a single record per every record found in a given query. * * Performs a single SQL query based on `INSERT ... SELECT ... FROM`. * * Unlike {@link createOneFrom}, it doesn't accept second argument with data. * * Runtime defaults cannot work with it. * * ```ts * const manyRecords = await db.table.createForEachFrom( * db.relatedTable.select({ relatedId: 'id' }).where({ key: 'value' }), * ); * ``` * * @param query - query to create new records from */ createForEachFrom(this: T, query: IsQuery$1): CreateManyFromResult; /** * Works exactly as {@link createForEachFrom}, except that it returns inserted row count by default. * * @param query - query to create new records from */ insertForEachFrom(this: T, query: IsQuery$1): InsertManyFromResult; } interface CreateSelf$1 extends PickQueryHasSelect, PickQueryDefaults, PickQueryResult, PickQueryRelations$1, PickQueryRelationsDataForCreate, PickQueryRelationsDataForCreateOptional, PickQueryWithData, PickQueryReturnType, PickQueryShape$1, PickQueryUniqueProperties, PickQueryInputType$1, Query.Pick.IsNotReadOnly {} type CreateData$1 = EmptyObject$1 extends T['relations'] ? CreateDataWithDefaults : CreateRelationsData; type CreateDataOmit = EmptyObject$1 extends T['relations'] ? CreateDataWithDefaultsOmit : CreateRelationsDataOmit; type CreateDataWithDefaults = { [K in keyof T['__inputType'] as K extends Defaults ? never : K]: K extends Defaults ? never : CreateColumn; } & { [K in Defaults]?: K extends keyof T['__inputType'] ? CreateColumn : never; }; type CreateDataWithDefaultsOmit = { [K in keyof T['__inputType'] as K extends Defaults | OmitKeys ? never : K]: K extends Defaults ? never : CreateColumn; } & { [K in Defaults as K extends OmitKeys ? never : K]?: K extends keyof T['__inputType'] ? CreateColumn : never; }; type WritableForeignKeys = AllFKeys extends (infer K) ? K extends keyof T['shape'] ? T['shape'][K] extends { data: { makeColumnWritable: true; }; } ? K : never : never : never; type CreateColumn = T['__inputType'][K] | ((q: T) => QueryOrExpression$1); type CreateRelationsData = CreateDataWithDefaultsOmit>> & CreateRelationsDataOmittingFKeys & CreateRelationsDataValidation & T['relationsDataForCreateOptional']; type CreateRelationsDataOmit = CreateDataWithDefaultsOmit> | OmitKeys> & CreateRelationsDataOmittingFKeys & CreateRelationsDataValidation & T['relationsDataForCreateOptional']; type CreateRelationsDataOmittingFKeys = EmptyObject$1 extends Data ? EmptyObject$1 : { [K in keyof Data]: CreateRelationDataOmittingFKeys; }[keyof Data] extends ((u: infer Obj) => void) ? Obj : never; type CreateRelationDataOmittingFKeys = (u: Union extends RelationConfigDataForCreate ? Union['columns'] extends keyof T['__defaults'] ? Pick, Union['columns']> & Partial : (Pick<{ [P in keyof T['__inputType']]: CreateColumn; }, Union['columns'] & keyof T['__inputType']> & { [K in keyof Union['nested']]?: never; }) | Union['nested'] : Union) => void; type RelationNestedNames = Data extends RelationConfigDataForCreate ? keyof Data['nested'] : never; type RelationNestedData = Data extends RelationConfigDataForCreate ? Name extends keyof Data['nested'] ? Data['nested'][Name] : never : never; type CreateRelationsDataValidation = { [K in RelationNestedNames]?: RelationNestedData; }; type CreateResult = T extends { isCount: true; } ? T : T['returnType'] extends undefined | 'all' ? SetQueryReturnsOneResult> : T['returnType'] extends 'pluck' ? SetQueryReturnsColumnResult> : SetQueryResult>; type InsertResult = T['__hasSelect'] extends true ? T['returnType'] extends undefined | 'all' ? SetQueryReturnsOneResult> : T['returnType'] extends 'pluck' ? SetQueryReturnsColumnResult> : SetQueryResult> : SetQueryReturnsRowCount; type CreateManyResult = T extends { isCount: true; } ? T : T['returnType'] extends 'one' | 'oneOrThrow' ? SetQueryReturnsAll : T['returnType'] extends 'value' | 'valueOrThrow' ? SetValueQueryReturnsPluckColumn : T; type InsertManyResult = T['__hasSelect'] extends true ? T['returnType'] extends 'one' | 'oneOrThrow' ? SetQueryReturnsAll : T['returnType'] extends 'value' | 'valueOrThrow' ? SetValueQueryReturnsPluckColumn : T : SetQueryReturnsRowCountMany; /** * When creating a record with a *belongs to* nested record, * un-nullify foreign key columns of the result. * * The same should work as well with any non-null columns passed to `create`, but it's to be implemented later. */ type NarrowCreateResult = EmptyObject$1 extends T['relations'] ? T['result'] : { [K in keyof T['result']]: true extends { [R in keyof T['relations']]: K extends T['relations'][R]['omitForeignKeyInCreate'] ? R extends keyof Data ? true : T['relations'][R]['omitForeignKeyInCreate'] extends keyof Data ? null | undefined extends Data[T['relations'][R]['omitForeignKeyInCreate']] ? never : true : never : never; }[keyof T['relations']] ? Column$1.Pick.QueryColumnOfTypeAndOps, T['result'][K]['operators']> : T['result'][K]; }; type IgnoreResult = T['returnType'] extends 'oneOrThrow' ? QueryTakeOptional : T['returnType'] extends 'valueOrThrow' ? SetQueryReturnsColumnOptional : T; type OnConflictArg = T['internal']['uniqueColumnNames'] | T['internal']['uniqueColumnTuples'] | Expression$1 | { constraint: T['internal']['uniqueConstraints']; }; type AddQueryDefaults = { [K in keyof T]: K extends '__defaults' ? { [K in keyof T['__defaults'] | DefaultKeys]: true; } : T[K]; }; type ExtraPropertiesAreNotAllowed = keyof Data extends keyof T['__inputType'] | keyof T['relations'] ? Data : `Extra properties are not allowed: ${Exclude & string}`; declare class QueryCreate { /** * `create` and `insert` create a single record. * * Use `select`, `selectAll`, `get`, or `pluck` alongside `create` or `insert` to * specify returning columns. * * Each column may accept a specific value, a raw SQL, or a query that returns a single value. * * ```ts * import { sql } from './baseTable'; * * const oneRecord = await db.table.create({ * name: 'John', * password: '1234', * }); * * // When using `.onConflictDoNothing()`, * // the record may be not created and the `createdCount` will be 0. * const createdCount = await db.table.insert(data).onConflictDoNothing(); * * await db.table.create({ * // raw SQL * column1: () => sql`'John' || ' ' || 'Doe'`, * * // query that returns a single value * // returning multiple values will result in Postgres error * column2: () => db.otherTable.get('someColumn'), * * // nesting creates, updates, deletes produces a single SQL * column4: () => db.otherTable.create(data).get('someColumn'), * column5: (q) => q.relatedTable.find(id).update(data).get('someColumn'), * }); * ``` * * Creational methods can be used in {@link WithMethods.with} expressions: * * ```ts * db.$qb * // create a record in one table * .with('a', db.table.select('id').create(data)) * // create a record in other table using the first table record id * .with('b', (q) => * db.otherTable.select('id').create({ * ...otherData, * aId: () => q.from('a').get('id'), * }), * ) * .from('b'); * ``` */ create>(this: T, data: ExtraPropertiesAreNotAllowed): CreateResult; /** * Works exactly as {@link create}, except that it returns inserted row count by default. */ insert>(this: T, data: ExtraPropertiesAreNotAllowed): InsertResult; /** * `createMany` and `insertMany` will create a batch of records. * * Each column may be set with a specific value, a raw SQL, or a query, the same as in {@link create}. * * In case one of the objects has fewer fields, the `DEFAULT` SQL keyword will be placed in its place in the `VALUES` statement. * * ```ts * const manyRecords = await db.table.createMany([ * { key: 'value', otherKey: 'other value' }, * { key: 'value' }, // default will be used for `otherKey` * ]); * * // `createdCount` will be 3. * const createdCount = await db.table.insertMany([data, data, data]); * ``` * * When nesting creates, a separate create query will be executed for every time it's used: * * ```ts * // will be performed twice, even though it is defined once * const nestedCreate = db.otherTable.create(data).get('column'); * * await db.table.createMany([{ column: nestedCreate }, { column: nestedCreate }]); * ``` * * Because of a limitation of Postgres protocol, queries having more than **65535** of values are going to fail in runtime. * To solve this seamlessly, `OrchidORM` will automatically batch such queries, and wrap them into a transaction, unless they are already in a transaction. * * ```ts * // OK: executes 2 inserts wrapped into a transaction * await db.table.createMany( * Array.from({ length: 65536 }, () => ({ text: 'text' })), * ); * ``` * * However, this only works in the case shown above. This **won't** work if you're using the `createMany` in `with` statement, * or if the insert is used as a sub-query in other query part. * * @param data - array of records data, may have values, raw SQL, queries, relation operations */ createMany(this: T, data: CreateData$1[]): CreateManyResult; /** * Works exactly as {@link createMany}, except that it returns inserted row count by default. * * @param data - array of records data, may have values, raw SQL, queries, relation operations */ insertMany(this: T, data: CreateData$1[]): InsertManyResult; /** * `defaults` allows setting values that will be used later in `create`. * * Columns provided in `defaults` are marked as optional in the following `create`. * * Default data is the same as in {@link create} and {@link createMany}, * so you can provide a raw SQL, or a query with a query. * * ```ts * // Will use firstName from defaults and lastName from create argument: * db.table * .defaults({ * firstName: 'first name', * lastName: 'last name', * }) * .create({ * lastName: 'override the last name', * }); * ``` * * @param data - default values for `create` and `createMany` which will follow `defaults` */ defaults>>(this: T, data: Data): AddQueryDefaults; /** * By default, violating unique constraint will cause the creative query to throw, * you can define what to do on a conflict: to ignore it, or to merge the existing record with a new data. * * A conflict occurs when a table has a primary key or a unique index on a column, * or a composite primary key unique index on a set of columns, * and a row being created has the same value as a row that already exists in the table in this column(s). * * Use {@link onConflictDoNothing} to suppress the error and continue without updating the record, * or the `merge` to update the record with new values automatically, * or the `set` to specify own values for the update. * * `onConflict` only accepts column names that are defined in `primaryKey` or `unique` in the table definition. * To specify a constraint, its name also must be explicitly set in `primaryKey` or `unique` in the table code. * * Postgres has a limitation that a single `INSERT` query can have only a single `ON CONFLICT` clause that can target only a single unique constraint * for updating the record. * * If your table has multiple potential reasons for unique constraint violation, such as username and email columns in a user table, * consider using `upsert` instead. * * ```ts * // leave `onConflict` without argument to ignore or merge on any conflict * db.table.create(data).onConflictDoNothing(); * * // single column: * // (this requires a composite primary key or unique index, see below) * db.table.create(data).onConflict('email').merge(); * * // array of columns: * db.table.create(data).onConflict(['email', 'name']).merge(); * * // constraint name * db.table.create(data).onConflict({ constraint: 'unique_index_name' }).merge(); * * // raw SQL expression: * db.table * .create(data) * .onConflict(sql`(email) where condition`) * .merge(); * ``` * * :::info * A primary key or a unique index for a **single** column can be fined on a column: * * ```ts * export const MyTable = defineTable('myTable', (t) => ({ * pkey: t.uuid().primaryKey(), * unique: t.string().unique(), * })); * ``` * * But for composite primary keys or indexes (having multiple columns), define it in a separate function: * * ```ts * export const MyTable = defineTable('myTable', (t) => ({ * one: t.integer(), * two: t.string(), * three: t.boolean(), * })) * .primaryKey(['one', 'two']) * .unique(['two', 'three']); * ``` * ::: * * You can use the `sql` function exported from your table factory file in onConflict. * It can be useful to specify a condition when you have a partial index: * * ```ts * db.table * .create({ * email: 'ignore@example.com', * name: 'John Doe', * active: true, * }) * // ignore only when having conflicting email and when active is true. * .onConflict(sql`(email) where active`) * .ignore(); * ``` * * For `merge` and `set`, you can append `where` to update data only for the matching rows: * * ```ts * const timestamp = Date.now(); * * db.table * .create(data) * .onConflict('email') * .set({ * name: 'John Doe', * updatedAt: timestamp, * }) * .where({ updatedAt: { lt: timestamp } }); * ``` * * @param arg - optionally provide an array of columns */ onConflict>(this: T, arg: Arg): OnConflictQueryBuilder; /** * Use `onConflictDoNothing` to suppress unique constraint violation error when creating a record. * * Adds `ON CONFLICT (columns) DO NOTHING` clause to the insert statement, columns are optional. * * Can also accept a constraint name. * * ```ts * db.table * .create({ * email: 'ignore@example.com', * name: 'John Doe', * }) * // on any conflict: * .onConflictDoNothing() * // or, for a specific column: * .onConflictDoNothing('email') * // or, for a specific constraint: * .onConflictDoNothing({ constraint: 'unique_index_name' }); * ``` * * When there is a conflict, nothing can be returned from the database, so `onConflictDoNothing` adds `| undefined` part to the response type. * * ```ts * const maybeRecord: RecordType | undefined = await db.table * .create(data) * .onConflictDoNothing(); * * const maybeId: number | undefined = await db.table * .get('id') * .create(data) * .onConflictDoNothing(); * ``` * * When creating multiple records, only created records will be returned. If no records were created, array will be empty: * * ```ts * // array can be empty * const arr = await db.table.createMany([data, data, data]).onConflictDoNothing(); * ``` */ onConflictDoNothing>(this: T, arg?: Arg): IgnoreResult; } type OnConflictSet$1 = { [K in keyof T['__inputType']]?: T['__inputType'][K] | (() => QueryOrExpression$1); }; declare class OnConflictQueryBuilder | undefined> { private query; private onConflict; constructor(query: T, onConflict: Arg); /** * Available only after `onConflict`. * * Updates the record with a given data when conflict occurs. * * ```ts * db.table * .create(data) * .onConflict('email') * .set({ * // supports plain values and SQL expressions * key: 'value', * fromSql: () => sql`custom sql`, * }) * // to update records only on certain conditions * .where({ ...certainConditions }); * ``` * * @param set - object containing new column values */ set(set: OnConflictSet$1): T; /** * Available only after `onConflict`. * * Use this method to merge all the data you have passed into `create` to update the existing record on conflict. * * If the table has columns with **dynamic** default values, such values will be applied as well. * * You can exclude certain columns from being merged by passing the `except` option. * * ```ts * // merge the full data * db.table.create(data).onConflict('email').merge(); * * // merge only a single column * db.table.create(data).onConflict('email').merge('name'); * * // merge multiple columns * db.table.create(data).onConflict('email').merge(['name', 'quantity']); * * // merge all columns except some * db.table * .create(data) * .onConflict('email') * .merge({ except: ['name', 'quantity'] }); * * // merge can be applied also for batch creates * db.table.createMany([data1, data2, data2]).onConflict('email').merge(); * * // update records only on certain conditions * db.table * .create(data) * .onConflict('email') * .merge() * .where({ ...certainConditions }); * ``` * * @param merge - no argument will merge all data, or provide a column(s) to merge, or provide `except` to update all except some. */ merge(merge?: keyof T['shape'] | (keyof T['shape'])[] | { except: keyof T['shape'] | (keyof T['shape'])[]; }): T; } type OnConflictTarget = string | string[] | Expression$1 | { constraint: string; }; type OnConflictSet = RecordUnknown$1; type OnConflictMerge = string | string[] | { except: string | string[]; }; interface UpdateSelf extends PickQuerySelectable, PickQueryResult, PickQueryRelations$1, PickQueryWithData, PickQueryReturnType, PickQueryShape$1, PickQueryInputType$1, PickQueryAs, PickQueryHasSelect, PickQueryHasWhere, Query.Pick.IsNotReadOnly {} type UpdateData$1 = { [K in keyof T['__inputType'] | keyof T['relations']]?: K extends keyof T['__inputType'] ? T['__inputType'][K] | ((q: { [K in keyof T['relations'] | keyof T]: K extends keyof T['relations'] ? T['relations'][K]['query'] : K extends keyof T ? T[K] : never; }) => QueryOrExpression$1) : T['returnType'] extends undefined | 'all' ? T['relations'][K]['dataForUpdate'] : T['relations'][K]['dataForUpdateOne']; }; type UpdateArg = T['__hasWhere'] extends true ? UpdateData$1 : 'Update statement must have where conditions. To update all prefix `update` with `all()`'; type UpdateResult = T['__hasSelect'] extends true ? T : T['returnType'] extends undefined | 'all' ? SetQueryReturnsRowCountMany : SetQueryReturnsRowCount; type NumericColumns = { [K in keyof T['__inputType']]: Exclude extends number | bigint | null ? K : never; }[keyof T['__inputType']]; type ChangeCountArg = NumericColumns | { [K in NumericColumns]?: T['shape'][K]['__type'] extends number | null ? number : number | string | bigint; }; interface UpdateManyBySelf extends UpdateSelf { internal: { uniqueColumns: unknown; uniqueColumnNames: unknown; uniqueColumnTuples: unknown; uniqueConstraints: unknown; }; } type UpdateManyData = ({ [K in keyof T['shape'] as T['shape'][K] extends Column$1.IsPrimaryKey ? K : never]: T['shape'][K]['__queryType'] | Expression$1; } & { [P in keyof T['__inputType']]?: T['__inputType'][P] | Expression$1; })[]; type UpdateManyByKeys = T['internal']['uniqueColumnNames'] | T['internal']['uniqueColumnTuples']; type UpdateManyByKeyColumns = K extends string[] ? K[number] : K; type UpdateManyByData = ({ [P in K & keyof T['__inputType']]: T['__inputType'][P]; } & { [P in keyof T['__inputType']]?: P extends K ? T['__inputType'][P] : T['__inputType'][P] | Expression$1; })[]; type UpdateManyResult = T['__hasSelect'] extends true ? T['returnType'] extends 'one' | 'oneOrThrow' ? SetQueryReturnsAllResult : T['returnType'] extends 'value' | 'valueOrThrow' ? SetQueryReturnsPluckColumnResult : SetQueryResult : SetQueryReturnsRowCountMany; declare class QueryUpdate { /** * `update` takes an object with columns and values to update records. * * By default, `update` will return a count of updated records. * * Use `select`, `selectAll`, `get`, or `pluck` alongside `update` to specify * returning columns. * * You need to provide `where`, `findBy`, or `find` conditions before calling `update`. * To ensure that the whole table won't be updated by accident, updating without where conditions will result in TypeScript and runtime errors. * * Use `all()` to update ALL records without conditions: * * ```ts * await db.table.all().update({ name: 'new name' }); * ``` * * If `select` and `where` were specified before the update it will return an array of updated records. * * If `select` and `take`, `find`, or similar were specified before the update it will return one updated record. * * 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. * * The callback is allowed to select a single value from a relation (see `fromRelation` column below), * or to use a [jsonSet](/guide/advanced-queries.html#jsonset), * [jsonInsert](/guide/advanced-queries.html#jsoninsert), * and [jsonRemove](/guide/advanced-queries.html#jsonremove) for a JSON column (see `jsonColumn` below). * * ```ts * import { sql } from './baseTable'; * * // returns number of updated records by default * const updatedCount = await db.table * .where({ name: 'old name' }) * .update({ name: 'new name' }); * * // returning only `id` * const id = await db.table.find(1).get('id').update({ name: 'new name' }); * * // `selectAll` + `find` will return a full record * const oneFullRecord = await db.table * .selectAll() * .find(1) * .update({ name: 'new name' }); * * // `selectAll` + `where` will return array of full records * const recordsArray = await db.table * .select('id', 'name') * .where({ id: 1 }) * .update({ name: 'new name' }); * * await db.table.where({ ...conditions }).update({ * // set the column to a specific value * value: 123, * * // use custom SQL to update the column * fromSql: () => sql`2 + 2`, * * // use query that returns a single value * // returning multiple values will result in Postgres error * fromQuery: () => db.otherTable.get('someColumn'), * * // select a single value from a related record * fromRelation: (q) => q.relatedTable.get('someColumn'), * * // set a new value to the `.foo.bar` path into a JSON column * jsonColumn: (q) => q.jsonSet('jsonColumn', ['foo', 'bar'], 'new value'), * }); * ``` * * `update` can be used in [with](/guide/advanced-queries#with) expressions: * * ```ts * db.$qb * // update record in one table * .with('a', db.table.find(1).select('id').update(data)) * // update record in other table using the first table record id * .with('b', (q) => * db.otherTable * .find(1) * .select('id') * .update({ * ...otherData, * aId: () => q.from('a').get('id'), * }), * ) * .from('b'); * * `update` can be used in {@link WithMethods.with} expressions: * * ```ts * db.$qb * // update record in one table * .with('a', db.table.find(1).select('id').update(data)) * // update record in other table using the first table record id * .with('b', (q) => * db.otherTable * .find(1) * .select('id') * .update({ * ...otherData, * aId: () => q.from('a').get('id'), * }), * ) * .from('b'); * ``` * * ### sub-queries * * In all `create`, `update`, `upsert` methods, * you can use sub queries that are either selecting a single value, * or creating/updating/deleting a record and return a single value. * * ```ts * await db.table.where({ ...conditions }).update({ * // `column` will be set to a value of the `otherColumn` of the created record. * column: () => db.otherTable.get('otherColumn').create({ ...data }), * * // `column2` will be set to a value of the `otherColumn` of the updated record. * column2: () => * db.otherTable * .get('otherColumn') * .findBy({ ...conditions }) * .update({ key: 'value' }), * * // `column3` will be set to a value of the `otherColumn` of the deleted record. * column3: () => * db.otherTable * .get('otherColumn') * .findBy({ ...conditions }) * .delete(), * }); * ``` * * This is achieved by defining a `WITH` clause under the hood, it produces such a query: * * ```sql * WITH q AS ( * INSERT INTO "otherTable"(col1, col2, col3) * VALUES ('val1', 'val2', 'val3') * RETURNING "otherTable"."selectedColumn" * ) * -- In a case of create * INSERT INTO "table"("column") VALUES ((SELECT * FROM "q")) * -- In a case of update * UPDATE "table" * SET "column" = (SELECT * FROM "q") * ``` * * The query is atomic. * No changes will persist in the database if the sub-query fails, or if the top-level query fails, or if multiple rows are returned from a sub-query. * * [//]: # 'not supported in create because cannot query related records for a thing that is not created yet' * [//]: # 'modificational sub queries are not allowed in update because it would be too hard to join a with statement to the update query' * * Only selective sub-queries are supported in `update` queries when the sub-query is using a relation: * * ```ts * db.book.update({ * authorName: (q) => q.author.get('name'), * }); * ``` * * ### null, undefined, unknown columns * * - `null` value will set a column to `NULL` * - `undefined` value will be ignored * - unknown columns will be ignored * * ```ts * db.table.findBy({ id: 1 }).update({ * name: null, // updates to null * age: undefined, // skipped, no effect * lalala: 123, // skipped * }); * ``` * * ### empty set * * When trying to query update with an empty object, it will be transformed seamlessly to a `SELECT` query: * * ```ts * // imagine the data is an empty object * const data = req.body; * * // query is transformed to `SELECT count(*) WHERE key = 'value'` * const count = await db.table.where({ key: 'value' }).update(data); * * // will select a full record by id * const record = await db.table.find(1).selectAll().update(data); * * // will select a single column by id * const name = await db.table.find(1).get('name').update(data); * ``` * * If the table has `updatedAt` [timestamp](/guide/common-column-methods.html#timestamps), it will be updated even for an empty data. * * @param arg - data to update records with, may have specific values, raw SQL, queries, or callbacks with sub-queries. */ update(this: T, arg: UpdateArg): UpdateResult; /** * To make sure that at least one row was updated use `updateOrThrow`: * * ```ts * import { NotFoundError } from 'orchid-orm'; * * try { * // updatedCount is guaranteed to be greater than 0 * const updatedCount = await db.table * .where(conditions) * .updateOrThrow({ name: 'name' }); * * // updatedRecords is guaranteed to be a non-empty array * const updatedRecords = await db.table * .where(conditions) * .select('id') * .updateOrThrow({ name: 'name' }); * } catch (err) { * if (err instanceof NotFoundError) { * // handle error * } * } * ``` * * @param arg - data to update records with, may have specific values, raw SQL, queries, or callbacks with sub-queries. */ updateOrThrow(this: T, arg: UpdateArg): UpdateResult; /** * Use `updateFrom` to update records in one table based on a query result from another table or CTE. * * `updateFrom` accepts the same arguments as {@link Query.join}. * * ```ts * // save all author names to their books by using a relation name: * db.books.updateFrom('author').set({ authorName: (q) => q.ref('author.name') }); * * // update from authors that match the condition: * db.books * .updateFrom((q) => q.author.where({ writingSkills: 'good' })) * .set({ authorName: (q) => q.ref('author.name') }); * * // update from any table using custom `on` conditions: * db.books * .updateFrom( * () => db.authors, * (q) => q.on('authors.id', 'books.authorId'), * ) * .set({ authorName: (q) => q.ref('author.name') }); * * // conditions after `updateFrom` can reference both tables: * db.books * .updateFrom(() => db.authors) * .where({ * 'authors.id': (q) => q.ref('books.authorId'), * }) * .set({ authorName: (q) => q.ref('author.name') }); * * // can join and use another table in between `updateFrom` and `set`: * db.books * .updateFrom('author') * .join('publisher') * .set({ * authorName: (q) => q.ref('author.name'), * publisherName: (q) => q.ref('publisher.name'), * }); * * // updating from a CTE * db.books * .with('a', () => * db.authors.where({ writingSkills: 'good' }).select('id', 'name').limit(10), * ) * .updateFrom('a', (q) => q.on('a.id', 'books.authorId')) * .set({ authorName: (q) => q.ref('author.name') }); * ``` */ updateFrom, Cb extends JoinCallbackArgs>(this: T, arg: Arg, ...args: Cb | JoinArgs): JoinResultFromArgs & QueryHasWhere$1; /** * Use after {@link updateFrom} */ set(this: T, arg: UpdateArg): UpdateResult; /** * Increments a column by `1`, returns a count of updated records by default. * * ```ts * const updatedCount = await db.table * .where(...conditions) * .increment('numericColumn'); * ``` * * When using `find` or `get` it will throw `NotFoundError` when no records found. * * ```ts * // throws when not found * const updatedCount = await db.table.find(1).increment('numericColumn'); * * // also throws when not found * const updatedCount2 = await db.table * .where(...conditions) * .get('columnName') * .increment('numericColumn'); * ``` * * Provide an object to increment multiple columns with different values. * Use `select` to specify columns to return. * * ```ts * // increment someColumn by 5 and otherColumn by 10, return updated records * const result = await db.table * .selectAll() * .where(...conditions) * .increment({ * someColumn: 5, * otherColumn: 10, * }); * ``` * * @param data - name of the column to increment, or an object with columns and values to add */ increment(this: T, data: ChangeCountArg): UpdateResult; /** * Decrements a column by `1`, returns a count of updated records by default. * * ```ts * const updatedCount = await db.table * .where(...conditions) * .decrement('numericColumn'); * ``` * * When using `find` or `get` it will throw `NotFoundError` when no records found. * * ```ts * // throws when not found * const updatedCount = await db.table.find(1).decrement('numericColumn'); * * // also throws when not found * const updatedCount2 = await db.table * .where(...conditions) * .get('columnName') * .decrement('numericColumn'); * ``` * * Provide an object to decrement multiple columns with different values. * Use `select` to specify columns to return. * * ```ts * // decrement someColumn by 5 and otherColumn by 10, return updated records * const result = await db.table * .selectAll() * .where(...conditions) * .decrement({ * someColumn: 5, * otherColumn: 10, * }); * ``` * * @param data - name of the column to decrement, or an object with columns and values to subtract */ decrement(this: T, data: ChangeCountArg): UpdateResult; /** * Updates multiple records with different per-row data in a single query. * * Each row must include the primary key and the columns to update. * All rows must have the same set of non-key columns. * * Returns a count of updated records by default. * Use `select`, `selectAll`, `get`, or `pluck` alongside `updateMany` to return * updated records. * * Throws {@link NotFoundError} if any record is not found. * Use {@link updateManyOptional} to skip missing records without throwing. * * ```ts * // returns count of updated records * const count = await db.table.updateMany([ * { id: 1, name: 'Alice', age: 30 }, * { id: 2, name: 'Bob', age: 25 }, * ]); * * // returns array of updated records * const records = await db.table.select('id', 'name').updateMany([ * { id: 1, name: 'Alice' }, * { id: 2, name: 'Bob' }, * ]); * ``` * * `.set()` applies shared values to all rows. * `.set()` values take precedence over per-row values for the same column. * * ```ts * await db.table * .updateMany([ * { id: 1, name: 'Alice' }, * { id: 2, name: 'Bob' }, * ]) * .set({ updatedBy: currentUser.id }); * ``` */ updateMany(this: T, data: UpdateManyData): UpdateManyResult & QueryHasWhere$1; /** * Same as {@link updateMany}, but skips missing records rather than throwing. * * ```ts * // updates what it can, doesn't throw for missing id: 999 * const count = await db.table.updateManyOptional([ * { id: 1, name: 'Alice' }, * { id: 999, name: 'Ghost' }, * ]); * ``` */ updateManyOptional(this: T, data: UpdateManyData): UpdateManyResult & QueryHasWhere$1; /** * Like {@link updateMany}, but matches rows by a unique column or a compound unique constraint instead of the primary key. * * Throws {@link NotFoundError} if any record is not found. * Use {@link updateManyByOptional} to skip records with no matching key without throwing. * * ```ts * // single unique column * await db.table.updateManyBy('email', [ * { email: 'alice@test.com', name: 'Alice' }, * { email: 'bob@test.com', name: 'Bob' }, * ]); * * // compound unique constraint * await db.table.updateManyBy(['firstName', 'lastName'], [ * { firstName: 'John', lastName: 'Doe', bio: 'updated' }, * ]); * ``` */ updateManyBy, K = UpdateManyByKeyColumns>(this: T, keys: Keys, data: UpdateManyByData): UpdateManyResult & QueryHasWhere$1; /** * Same as {@link updateManyBy}, but skips records with no matching key rather than throwing. * * ```ts * await db.table.updateManyByOptional('email', [ * { email: 'alice@test.com', name: 'Alice' }, * { email: 'unknown@test.com', name: 'Ghost' }, * ]); * ``` */ updateManyByOptional, K = UpdateManyByKeyColumns>(this: T, keys: Keys, data: UpdateManyByData): UpdateManyResult & QueryHasWhere$1; } type UpsertCreate = { [K in keyof CD as K extends DataKey ? never : K]: CD[K]; } & { [K in DataKey]?: K extends keyof CD ? CD[K] : never; }; type UpsertResult = T['__hasSelect'] extends true ? T['returnType'] extends 'value' | 'valueOrThrow' ? SetValueQueryReturnsValueOrThrow : SetQueryReturnsOne : SetQueryReturnsVoid; interface UpsertThis$1 extends UpdateSelf, CreateSelf$1 { __hasWhere: true; returnType: 'one' | 'oneOrThrow' | 'value' | 'valueOrThrow' | 'void'; } type UpsertData$1> = { update: Update; create: CreateData$1 | ((update: Update) => CreateData$1); } | { data: Update; create: UpsertCreate> | ((update: Update) => UpsertCreate>); }; declare class QueryUpsert { /** * `upsert` tries to update a single record, and then it creates the record if it doesn't yet exist. * * `find` or `findBy` must precede `upsert` because it does not work with multiple updates. * * In case more than one row was updated, it will throw `MoreThanOneRowError` and the transaction will be rolled back. * * It can take `update` and `create` objects, then they are used separately for update and create queries. * Or, it can take `data` and `create` objects, `data` will be used for update and be mixed to `create` object. * * `data` and `update` objects are of the same type that's expected by `update` method, `create` object is of type of `create` method argument. * * No values are returned by default, place `select` or `selectAll` before `upsert` to specify returning columns. * * ```ts * await db.user * .selectAll() * .findBy({ email: 'some@email.com' }) * .upsert({ * data: { * // update record's name * name: 'new name', * // supports sql and nested queries * fromSQL: () => sql`*SQL expression*`, * fromQuery: () => db.someTable.create(data).get('column'), * }, * create: { * // create a new record with this email and a name 'new name' * email: 'some@email.com', * // supports sql and nested queries as well * }, * create: { * // create a new record with this email and a name 'new name' * email: 'some@email.com', * }, * }); * * // the same as above but using `update` and `create` * await db.user * .selectAll() * .findBy({ email: 'some@email.com' }) * .upsert({ * update: { * name: 'updated user', * }, * create: { * email: 'some@email.com', * // here we use a different name when creating a record * name: 'created user', * }, * }); * ``` * * The data for `create` may be returned from a function, it won't be called if a record was updated: * * ```ts * await db.user * .selectAll() * .findBy({ email: 'some@email.com' }) * .upsert({ * update: { * name: 'updated user', * }, * create: () => ({ * email: 'some@email.com', * name: 'created user', * }), * }); * * // the same as above using `data` * await db.user * .selectAll() * .findBy({ email: 'some@email.com' }) * .upsert({ * data: { * name: 'updated user', * }, * create: () => ({ * email: 'some@email.com', * // name in `create` is overriding the name from `data` * name: 'created user', * }), * }); * ``` * * Data from `data` or `update` is passed to the `create` function and can be used: * * ```ts * const user = await db.user * .selectAll() * .findBy({ email: 'some@email.com' }) * .upsert({ * data: { * name: 'updated user', * }, * // `updateData` has the exact type of what is passed to `data` * create: (updateData) => ({ * email: `${updateData.name}@email.com`, * }), * }); * ``` * * `upsert` works in the exact same way as [orCreate](#orCreate), but with `UPDATE` statement instead of `SELECT`. * it also performs a single query if the record exists, and two queries if there is no record yet. * * @param data - `update` property for the data to update, `create` property for the data to create */ upsert>(this: T, data: UpsertData$1): UpsertResult; } type OrCreateArg = Data | (() => Data); declare class QueryOrCreate { /** * `orCreate` creates a record only if it was not found by conditions. * * `find` or `findBy` must precede `orCreate`. * * It is accepting the same argument as `create` commands. * * No result is returned by default, place `get`, `select`, or `selectAll` before `orCreate` to specify returning columns. * * ```ts * const user = await db.user * .selectAll() * .findBy({ email: 'some@email.com' }) * .orCreate({ * email: 'some@email.com', * name: 'created user', * // supports sql and nested queries * fromSQL: () => sql`*SQL expression*`, * fromQuery: () => db.someTable.create(data).get('column'), * fromRelated: (q) => q.relatedTable.update(data).get('column'), * }); * ``` * * The data can be returned from a function, it won't be called if the record was found: * * ```ts * const user = await db.user * .selectAll() * .findBy({ email: 'some@email.com' }) * .orCreate(() => ({ * email: 'some@email.com', * name: 'created user', * })); * ``` * * `orCreate` works by performing just a single query in the case if the record exists, and one additional query when the record does not exist. * * At first, it performs a "find" query, the query cost is exact same as if you didn't use `orCreate`. * * Then, if the record wasn't found, it performs a single query with CTE expressions to try finding it again, for the case it was already created just a moment before, * and then it creates the record if it's still not found. Using such CTE allows to skip using transactions, while still conforming to atomicity. * * ```sql * -- first query * SELECT * FROM "table" WHERE "key" = 'value' * * -- the record could have been created in between these two queries * * -- second query * WITH find_row AS ( * SELECT * FROM "table" WHERE "key" = 'value' * ) * WITH insert_row AS ( * INSERT INTO "table" ("key") * SELECT 'value' * -- skip the insert if the row already exists * WHERE NOT EXISTS (SELECT 1 FROM find_row) * RETURNING * * ) * SELECT * FROM find_row * UNION ALL * SELECT * FROM insert_row * ``` * * Called after [none](/guide/query-methods.html#none), `orCreate` performs only the second query. * * @param data - the same data as for `create`, it may be returned from a callback */ orCreate(this: T, data: OrCreateArg>): UpsertResult; } type IsolationLevel$1 = 'SERIALIZABLE' | 'REPEATABLE READ' | 'READ COMMITTED' | 'READ UNCOMMITTED'; interface TransactionOptions$1 extends SqlSessionState$1 { /** * Enable or disable logging for all queries in the transaction. */ log?: boolean; /** * Default schema to use for queries in the transaction. */ schema?: QuerySchema$1; /** * Postgres isolation level for the top-level transaction. */ level?: IsolationLevel$1; /** * Whether the top-level transaction should be read-only. */ readOnly?: boolean; /** * Whether the top-level transaction should be deferrable. */ deferrable?: boolean; /** * Postgres role to apply for the transaction callback. * * Nested transactions can temporarily replace the parent transaction role. */ role?: SqlSessionState$1['role']; /** * Postgres custom settings to apply for the transaction callback. * * Nested transaction settings are shallow-merged over the parent transaction * settings while the nested callback runs. */ setConfig?: SqlSessionState$1['setConfig']; } interface AfterCommitErrorFulfilledResult extends PromiseFulfilledResult { name?: string; } interface AfterCommitErrorRejectedResult extends PromiseRejectedResult { name?: string; } type AfterCommitErrorResult = AfterCommitErrorFulfilledResult | AfterCommitErrorRejectedResult; /** * `AfterCommitError` is thrown when one of after commit hooks throws. * * ```ts * interface AfterCommitError extends OrchidOrmError { * // the result of transaction functions * result: unknown; * * // Promise.allSettled result + optional function names * hookResults: ( * | { * status: 'fulfilled'; * value: unknown; * name?: string; * } * | { * status: 'rejected'; * reason: any; // the error object thrown by a hook * name?: string; * } * )[]; * } * ``` * * Use `function name() {}` function syntax for hooks to give them names, * so later they can be identified when handling after commit errors. * * ```ts * export const SomeTable = defineTable('someTable', (t) => ({ * ...someColumns, * })).init((orm: typeof db, hooks) => { * // anonymous funciton - has no name * hooks.afterCreateCommit([], async () => { * // ... * }); * * // named function * hooks.afterCreateCommit([], function myHook() { * // ... * }); * }); * ``` */ declare class AfterCommitError extends OrchidOrmError { result: unknown; hookResults: AfterCommitErrorResult[]; constructor(result: unknown, hookResults: AfterCommitErrorResult[]); } type AfterCommitErrorHandler = (error: AfterCommitError) => void | Promise; declare class QueryTransaction { /** * In Orchid ORM the method is `$transaction`, when using `pqb` on its own it is `transaction`. * * `COMMIT` happens automatically after the callback was successfully resolved, and `ROLLBACK` is done automatically if the callback fails. * * Let's consider the case of transferring money from one user to another: * * ```ts * export const transferMoney = async ( * fromId: number, * toId: number, * amount: number, * ) => { * try { * // db.$transaction returns data that is returned from the callback * // result here is senderRemainder * const result = await db.$transaction(async () => { * const sender = await db.user.find(fromId); * const senderRemainder = sender.balance - amount; * if (senderRemainder < 0) { * throw new Error('Sender does not have enough money'); * } * * await db.user.find(fromId).decrement({ * balance: amount, * }); * await db.user.find(toId).increment({ * balance: amount, * }); * * return senderRemainder; * }); * } catch (error) { * // handle transaction error * } * }; * ``` * * It performs 3 queries in a single transaction: load sender record, decrement sender's balance, increment receiver's balance. * * If sender or receiver record doesn't exist, it will throw `NotFound` error, and there is an error thrown when sender's balance is too low. * In such case, the transaction will be rolled back and no changes will be applied to the database. * * Internally, ORM relies on [AsyncLocalStorage](https://nodejs.org/api/async_context.html#class-asynclocalstorage) feature of node.js, * it allows passing the transaction object implicitly. So that any query that is done inside of callback, will run inside a transaction. * * ## nested transactions * * Transactions can be nested one in another. * The top level transaction is the real one, * and the nested ones are emulated with [savepoint](https://www.postgresql.org/docs/current/sql-savepoint.html) instead of `BEGIN` * and [release savepoint](https://www.postgresql.org/docs/current/sql-release-savepoint.html) instead of `COMMIT`. * * Use [ensureTransaction](#ensuretransaction) to run all queries in a single transaction. * * ```ts * const result = await db.$transaction(async () => { * await db.table.create(...one); * * const result = await db.$transaction(async () => { * await db.table.create(...two); * return 123; * }); * * await db.table.create(...three); * * return result; * }); * * // result is returned from the inner transaction * result === 123; * ``` * * If the inner transaction throws an error, and it is caught by `try/catch` of outer transaction, * it performs [rollback to savepoint](https://www.postgresql.org/docs/current/sql-rollback-to.html) * and the outer transaction can continue: * * ```ts * class CustomError extends Error {} * * await db.$transaction(async () => { * try { * await db.$transaction(async () => { * throw new CustomError(); * }); * } catch (err) { * if (err instanceof CustomError) { * // ignore this error * return; * } * throw err; * } * * // this transaction can continue * await db.table.create(...data); * }); * ``` * * If the error in the inner transaction is not caught, all nested transactions are rolled back and aborted. * * ## SQL session context in transactions * * Pass `role` and `setConfig` in transaction options to apply Postgres SQL session context for the whole transaction: * * ```ts * await db.$transaction( * { * role: 'app_user', * setConfig: { * 'app.tenant_id': tenantId, * 'app.user_id': userId, * }, * }, * async () => { * const project = await db.project.find(projectId); * * await db.project.find(projectId).update({ lastViewedAt: new Date() }); * * return project; * }, * ); * ``` * * This is different from `$withOptions({ role, setConfig }, cb)`. * `$withOptions` is query-scoped and reconciles SQL session state around each query. * Transaction options are applied once for the transaction and are useful for request-scoped RLS work that is already transaction-bound. * * Nested transactions can temporarily override the parent transaction role and config. * When the nested transaction finishes, Orchid restores the parent transaction context before the outer callback continues. */ transaction(this: PickQueryQAndInternal, cb: () => Promise): Promise; transaction(this: PickQueryQAndInternal, options: IsolationLevel$1 | TransactionOptions$1, cb: () => Promise): Promise; /** * Use the `$ensureTransaction` when you want to ensure the sequence of queries is running in a transaction, but there is no need for Postgres [savepoints](https://www.postgresql.org/docs/current/sql-savepoint.html). * * ```ts * async function updateUserBalance(userId: string, amount: number) { * await db.$ensureTransaction(async () => { * await db.transfer.create({ userId, amount }) * await db.user.find(userId).increment({ balance: amount }) * }) * } * * async function saveDeposit(userId: string, deposit: { ... }) { * await db.$ensureTransaction(async () => { * await db.deposit.create(deposit) * // transaction in updateUserBalance won't be started * await updateUserBalance(userId, deposit.amount) * }) * } * ``` */ ensureTransaction(this: PickQueryQAndInternal, cb: () => Promise): Promise; isInTransaction(): boolean; /** * Schedules a hook to run after the outermost transaction commits: * * ```ts * await db.$transaction(async () => { * await db.table.create(data) * await db.table.where({ ...conditions }).update({ key: 'value' }) * * db.$afterCommit(() => { // can be sync or async * console.log('after commit') * }) * }) * ``` * * If used outside the transaction, the hook will be executed almost immediately, on the next microtask: * * ```ts * db.$afterCommit(async () => { // can be sync or async * console.log('after commit') * }) * ``` * * If the callback has no `try/catch` and throws an error, * this will cause `uncaughtException` if the callback is sync and `unhandledRejection` if it is async. * * While a test transaction is open, a hook added outside of a transaction causes `unhandledRejection` when its returned promise rejects, even when that promise is handled elsewhere. */ afterCommit(this: Query, hook: AfterCommitStandaloneHook$1): void; /** * Whenever a query in a transaction fails, the transaction is transitioned to a failed state, no further queries are possible. * * Use [catchUniqueError](/guide/error-handling.html#catchuniqueerror) to handle uniqueness errors, * the following examples do not use it to illustrate error handling. * * ```ts * // This transaction is going to fail * db.$transaction(async () => { * try { * // imagine it fails because the username is already taken * await db.user.insert({ username: 'taken' }); * } catch (err) { * // even though the query is wrapped in a try-catch, the transaction fails anyway * } * }); * ``` * * You can use `catch` method on a query instead of `try-catch` to surpass the problem. * The following transaction won't fail: * * ```ts * // Transaction succeeds * db.$transaction(async () => { * const result = await db.user.insert({ username: 'taken' }).catch(() => 'failed'); * * if (result === 'failed') { * await db.user.insert({ username: 'another' }); * } * }); * ``` * * This is because when using `catch` method, `OrchidORM` will wrap the query with a savepoint. * * Alternatively, you can use the `recoverable()` method: * * ```ts * // Transaction succeeds * db.$transaction(async () => { * try { * await db.user.insert({ username: 'taken' }).recoverable(); * } catch (err) { * await db.user.insert({ username: 'another' }); * } * }); * ``` */ recoverable(this: T): T; } interface UnionItem { a: SubQueryForSql | Expression$1; k: UnionKind; p?: boolean; } type UnionKind = 'UNION' | 'UNION ALL' | 'INTERSECT' | 'INTERSECT ALL' | 'EXCEPT' | 'EXCEPT ALL'; interface QueryDataUnion { b: SubQueryForSql; u: UnionItem[]; p?: boolean; } /** * Condition that a relation adds to a query. * It is joined by `AND` with the whole condition of the query, so `orWhere` can't bypass it, and `clear('where')` keeps it. */ declare class RelationCondition { readonly condition: WhereItem; constructor(condition: WhereItem); } type WhereItem = { [K: string]: unknown | { [K: string]: unknown | SubQueryForSql | Expression$1; } | Expression$1; NOT?: MaybeArray$1; AND?: MaybeArray$1; OR?: MaybeArray$1[]; IN?: MaybeArray$1; EXISTS?: MaybeArray$1; ON?: WhereOnItem | WhereJsonPathEqualsItem; SEARCH?: MaybeArray$1; } | Query | Expression$1 | RelationCondition; interface WhereInItem { columns: string[]; values: unknown[][] | SubQueryForSql | Expression$1; } type WhereJsonPathEqualsItem = [leftColumn: string, leftPath: string, rightColumn: string, rightPath: string]; interface WhereOnItem { joinFrom: WhereOnJoinItem; from: string; joinTo: WhereOnJoinItem; to: string; useOuterAliases?: true; op?: string; } type WhereOnJoinItem = { table?: string; q: { as?: string; }; } | string; interface WindowItem { [K: string]: WindowDeclaration | Expression$1; } interface WindowDeclaration { partitionBy?: SelectableOrExpression | SelectableOrExpression[]; order?: OrderItem; } type WrapQueryArg = FromQuerySelf; declare class QueryWrap { wrap(this: T, query: Q, as?: As): SetQueryTableAlias; } type AfterHook$1