Initial commit - Event Planner application

This commit is contained in:
mberlin
2026-03-18 14:55:56 -03:00
commit 86d779eb4d
7548 changed files with 1006324 additions and 0 deletions

View File

@@ -0,0 +1,379 @@
import { AggregateFunctionNode } from '../operation-node/aggregate-function-node.js';
import { AliasNode } from '../operation-node/alias-node.js';
import type { OverBuilder } from './over-builder.js';
import type { AliasableExpression, AliasedExpression, Expression } from '../expression/expression.js';
import type { ReferenceExpression } from '../parser/reference-parser.js';
import { type ComparisonOperatorExpression, type OperandValueExpressionOrList } from '../parser/binary-operation-parser.js';
import type { SqlBool } from '../util/type-utils.js';
import type { ExpressionOrFactory } from '../parser/expression-parser.js';
import { type DirectedOrderByStringReference, type OrderByExpression, type OrderByModifiers } from '../parser/order-by-parser.js';
import type { OrderByInterface } from './order-by-interface.js';
export declare class AggregateFunctionBuilder<DB, TB extends keyof DB, O = unknown> implements OrderByInterface<DB, TB, {}>, AliasableExpression<O> {
#private;
constructor(props: AggregateFunctionBuilderProps);
/** @private */
/**
* All expressions need to have this getter for complicated type-related reasons.
* Simply add this getter for your expression and always return `undefined` from it:
*
* ### Examples
*
* ```ts
* import { type Expression, type OperationNode, sql } from 'kysely'
*
* class SomeExpression<T> implements Expression<T> {
* get expressionType(): T | undefined {
* return undefined
* }
*
* toOperationNode(): OperationNode {
* return sql`some sql here`.toOperationNode()
* }
* }
* ```
*
* The getter is needed to make the expression assignable to another expression only
* if the types `T` are assignable. Without this property (or some other property
* that references `T`), you could assing `Expression<string>` to `Expression<number>`.
*/
get expressionType(): O | undefined;
/**
* Returns an aliased version of the function.
*
* In addition to slapping `as "the_alias"` to the end of the SQL,
* this method also provides strict typing:
*
* ```ts
* const result = await db
* .selectFrom('person')
* .select(
* (eb) => eb.fn.count<number>('id').as('person_count')
* )
* .executeTakeFirstOrThrow()
*
* // `person_count: number` field exists in the result type.
* console.log(result.person_count)
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select count("id") as "person_count"
* from "person"
* ```
*/
as<A extends string>(alias: A): AliasedAggregateFunctionBuilder<DB, TB, O, A>;
/**
* Adds a `distinct` clause inside the function.
*
* ### Examples
*
* ```ts
* const result = await db
* .selectFrom('person')
* .select((eb) =>
* eb.fn.count<number>('first_name').distinct().as('first_name_count')
* )
* .executeTakeFirstOrThrow()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select count(distinct "first_name") as "first_name_count"
* from "person"
* ```
*/
distinct(): AggregateFunctionBuilder<DB, TB, O>;
/**
* Adds an `order by` clause inside the aggregate function.
*
* ### Examples
*
* ```ts
* const result = await db
* .selectFrom('person')
* .innerJoin('pet', 'pet.owner_id', 'person.id')
* .select((eb) =>
* eb.fn.jsonAgg('pet').orderBy('pet.name').as('person_pets')
* )
* .executeTakeFirstOrThrow()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select json_agg("pet" order by "pet"."name") as "person_pets"
* from "person"
* inner join "pet" ON "pet"."owner_id" = "person"."id"
* ```
*/
orderBy<OE extends OrderByExpression<DB, TB, {}>>(expr: OE, modifiers?: OrderByModifiers): AggregateFunctionBuilder<DB, TB, O>;
/**
* @deprecated It does ~2-2.6x more compile-time instantiations compared to multiple chained `orderBy(expr, modifiers?)` calls (in `order by` clauses with reasonable item counts), and has broken autocompletion.
*/
orderBy<OE extends OrderByExpression<DB, TB, {}> | DirectedOrderByStringReference<DB, TB, {}>>(exprs: ReadonlyArray<OE>): AggregateFunctionBuilder<DB, TB, O>;
/**
* @deprecated It does ~2.9x more compile-time instantiations compared to a `orderBy(expr, direction)` call.
*/
orderBy<OE extends DirectedOrderByStringReference<DB, TB, {}>>(expr: OE): AggregateFunctionBuilder<DB, TB, O>;
/**
* @deprecated Use `orderBy(expr, (ob) => ...)` instead.
*/
orderBy<OE extends OrderByExpression<DB, TB, {}>>(expr: OE, modifiers: Expression<any>): AggregateFunctionBuilder<DB, TB, O>;
/**
* Clears the `order by` clause from the query.
*
* See {@link orderBy} for adding an `order by` clause or item to a query.
*
* ### Examples
*
* ```ts
* const query = db
* .selectFrom('person')
* .selectAll()
* .orderBy('id', 'desc')
*
* const results = await query
* .clearOrderBy()
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select * from "person"
* ```
*/
clearOrderBy(): AggregateFunctionBuilder<DB, TB, O>;
/**
* Adds a `withing group` clause with a nested `order by` clause after the function.
*
* This is only supported by some dialects like PostgreSQL or MS SQL Server.
*
* ### Examples
*
* Most frequent person name:
*
* ```ts
* const result = await db
* .selectFrom('person')
* .select((eb) => [
* eb.fn
* .agg<string>('mode')
* .withinGroupOrderBy('person.first_name')
* .as('most_frequent_name')
* ])
* .executeTakeFirstOrThrow()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select mode() within group (order by "person"."first_name") as "most_frequent_name"
* from "person"
* ```
*/
withinGroupOrderBy<OE extends OrderByExpression<DB, TB, {}>>(expr: OE, modifiers?: OrderByModifiers): AggregateFunctionBuilder<DB, TB, O>;
/**
* @deprecated It does ~2-2.6x more compile-time instantiations compared to multiple chained `withinGroupOrderBy(expr, modifiers?)` calls (in `order by` clauses with reasonable item counts), and has broken autocompletion.
*/
withinGroupOrderBy<OE extends OrderByExpression<DB, TB, {}> | DirectedOrderByStringReference<DB, TB, {}>>(exprs: ReadonlyArray<OE>): AggregateFunctionBuilder<DB, TB, O>;
/**
* @deprecated It does ~2.9x more compile-time instantiations compared to a `withinGroupOrderBy(expr, direction)` call.
*/
withinGroupOrderBy<OE extends DirectedOrderByStringReference<DB, TB, {}>>(expr: OE): AggregateFunctionBuilder<DB, TB, O>;
/**
* @deprecated Use `withinGroupOrderBy(expr, (ob) => ...)` instead.
*/
withinGroupOrderBy<OE extends OrderByExpression<DB, TB, {}>>(expr: OE, modifiers: Expression<any>): AggregateFunctionBuilder<DB, TB, O>;
/**
* Adds a `filter` clause with a nested `where` clause after the function.
*
* Similar to {@link WhereInterface}'s `where` method.
*
* Also see {@link filterWhereRef}.
*
* ### Examples
*
* Count by gender:
*
* ```ts
* const result = await db
* .selectFrom('person')
* .select((eb) => [
* eb.fn
* .count<number>('id')
* .filterWhere('gender', '=', 'female')
* .as('female_count'),
* eb.fn
* .count<number>('id')
* .filterWhere('gender', '=', 'male')
* .as('male_count'),
* eb.fn
* .count<number>('id')
* .filterWhere('gender', '=', 'other')
* .as('other_count'),
* ])
* .executeTakeFirstOrThrow()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select
* count("id") filter(where "gender" = $1) as "female_count",
* count("id") filter(where "gender" = $2) as "male_count",
* count("id") filter(where "gender" = $3) as "other_count"
* from "person"
* ```
*/
filterWhere<RE extends ReferenceExpression<DB, TB>, VE extends OperandValueExpressionOrList<DB, TB, RE>>(lhs: RE, op: ComparisonOperatorExpression, rhs: VE): AggregateFunctionBuilder<DB, TB, O>;
filterWhere<E extends ExpressionOrFactory<DB, TB, SqlBool>>(expression: E): AggregateFunctionBuilder<DB, TB, O>;
/**
* Adds a `filter` clause with a nested `where` clause after the function, where
* both sides of the operator are references to columns.
*
* Similar to {@link WhereInterface}'s `whereRef` method.
*
* ### Examples
*
* Count people with same first and last names versus general public:
*
* ```ts
* const result = await db
* .selectFrom('person')
* .select((eb) => [
* eb.fn
* .count<number>('id')
* .filterWhereRef('first_name', '=', 'last_name')
* .as('repeat_name_count'),
* eb.fn.count<number>('id').as('total_count'),
* ])
* .executeTakeFirstOrThrow()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select
* count("id") filter(where "first_name" = "last_name") as "repeat_name_count",
* count("id") as "total_count"
* from "person"
* ```
*/
filterWhereRef<LRE extends ReferenceExpression<DB, TB>, RRE extends ReferenceExpression<DB, TB>>(lhs: LRE, op: ComparisonOperatorExpression, rhs: RRE): AggregateFunctionBuilder<DB, TB, O>;
/**
* Adds an `over` clause (window functions) after the function.
*
* ### Examples
*
* ```ts
* const result = await db
* .selectFrom('person')
* .select(
* (eb) => eb.fn.avg<number>('age').over().as('average_age')
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select avg("age") over() as "average_age"
* from "person"
* ```
*
* Also supports passing a callback that returns an over builder,
* allowing to add partition by and sort by clauses inside over.
*
* ```ts
* const result = await db
* .selectFrom('person')
* .select(
* (eb) => eb.fn.avg<number>('age').over(
* ob => ob.partitionBy('last_name').orderBy('first_name', 'asc')
* ).as('average_age')
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select avg("age") over(partition by "last_name" order by "first_name" asc) as "average_age"
* from "person"
* ```
*/
over(over?: OverBuilderCallback<DB, TB>): AggregateFunctionBuilder<DB, TB, O>;
/**
* Simply calls the provided function passing `this` as the only argument. `$call` returns
* what the provided function returns.
*/
$call<T>(func: (qb: this) => T): T;
/**
* Casts the expression to the given type.
*
* This method call doesn't change the SQL in any way. This methods simply
* returns a copy of this `AggregateFunctionBuilder` with a new output type.
*/
$castTo<C>(): AggregateFunctionBuilder<DB, TB, C>;
/**
* Omit null from the expression's type.
*
* This function can be useful in cases where you know an expression can't be
* null, but Kysely is unable to infer it.
*
* This method call doesn't change the SQL in any way. This methods simply
* returns a copy of `this` with a new output type.
*/
$notNull(): AggregateFunctionBuilder<DB, TB, Exclude<O, null>>;
/**
* Creates the OperationNode that describes how to compile this expression into SQL.
*
* ### Examples
*
* If you are creating a custom expression, it's often easiest to use the {@link sql}
* template tag to build the node:
*
* ```ts
* import { type Expression, type OperationNode, sql } from 'kysely'
*
* class SomeExpression<T> implements Expression<T> {
* get expressionType(): T | undefined {
* return undefined
* }
*
* toOperationNode(): OperationNode {
* return sql`some sql here`.toOperationNode()
* }
* }
* ```
*/
toOperationNode(): AggregateFunctionNode;
}
/**
* {@link AggregateFunctionBuilder} with an alias. The result of calling {@link AggregateFunctionBuilder.as}.
*/
export declare class AliasedAggregateFunctionBuilder<DB, TB extends keyof DB, O = unknown, A extends string = never> implements AliasedExpression<O, A> {
#private;
constructor(aggregateFunctionBuilder: AggregateFunctionBuilder<DB, TB, O>, alias: A);
/** @private */
/**
* Returns the aliased expression.
*/
get expression(): Expression<O>;
/** @private */
/**
* Returns the alias.
*/
get alias(): A;
/**
* Creates the OperationNode that describes how to compile this expression into SQL.
*/
toOperationNode(): AliasNode;
}
export interface AggregateFunctionBuilderProps {
aggregateFunctionNode: AggregateFunctionNode;
}
export type OverBuilderCallback<DB, TB extends keyof DB> = (builder: OverBuilder<DB, TB>) => OverBuilder<any, any>;

View File

@@ -0,0 +1,242 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AliasedAggregateFunctionBuilder = exports.AggregateFunctionBuilder = void 0;
const object_utils_js_1 = require("../util/object-utils.js");
const aggregate_function_node_js_1 = require("../operation-node/aggregate-function-node.js");
const alias_node_js_1 = require("../operation-node/alias-node.js");
const identifier_node_js_1 = require("../operation-node/identifier-node.js");
const parse_utils_js_1 = require("../parser/parse-utils.js");
const binary_operation_parser_js_1 = require("../parser/binary-operation-parser.js");
const order_by_parser_js_1 = require("../parser/order-by-parser.js");
const query_node_js_1 = require("../operation-node/query-node.js");
class AggregateFunctionBuilder {
#props;
constructor(props) {
this.#props = (0, object_utils_js_1.freeze)(props);
}
/** @private */
get expressionType() {
return undefined;
}
/**
* Returns an aliased version of the function.
*
* In addition to slapping `as "the_alias"` to the end of the SQL,
* this method also provides strict typing:
*
* ```ts
* const result = await db
* .selectFrom('person')
* .select(
* (eb) => eb.fn.count<number>('id').as('person_count')
* )
* .executeTakeFirstOrThrow()
*
* // `person_count: number` field exists in the result type.
* console.log(result.person_count)
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select count("id") as "person_count"
* from "person"
* ```
*/
as(alias) {
return new AliasedAggregateFunctionBuilder(this, alias);
}
/**
* Adds a `distinct` clause inside the function.
*
* ### Examples
*
* ```ts
* const result = await db
* .selectFrom('person')
* .select((eb) =>
* eb.fn.count<number>('first_name').distinct().as('first_name_count')
* )
* .executeTakeFirstOrThrow()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select count(distinct "first_name") as "first_name_count"
* from "person"
* ```
*/
distinct() {
return new AggregateFunctionBuilder({
...this.#props,
aggregateFunctionNode: aggregate_function_node_js_1.AggregateFunctionNode.cloneWithDistinct(this.#props.aggregateFunctionNode),
});
}
orderBy(...args) {
return new AggregateFunctionBuilder({
...this.#props,
aggregateFunctionNode: query_node_js_1.QueryNode.cloneWithOrderByItems(this.#props.aggregateFunctionNode, (0, order_by_parser_js_1.parseOrderBy)(args)),
});
}
clearOrderBy() {
return new AggregateFunctionBuilder({
...this.#props,
aggregateFunctionNode: query_node_js_1.QueryNode.cloneWithoutOrderBy(this.#props.aggregateFunctionNode),
});
}
withinGroupOrderBy(...args) {
return new AggregateFunctionBuilder({
...this.#props,
aggregateFunctionNode: aggregate_function_node_js_1.AggregateFunctionNode.cloneWithOrderBy(this.#props.aggregateFunctionNode, (0, order_by_parser_js_1.parseOrderBy)(args), true),
});
}
filterWhere(...args) {
return new AggregateFunctionBuilder({
...this.#props,
aggregateFunctionNode: aggregate_function_node_js_1.AggregateFunctionNode.cloneWithFilter(this.#props.aggregateFunctionNode, (0, binary_operation_parser_js_1.parseValueBinaryOperationOrExpression)(args)),
});
}
/**
* Adds a `filter` clause with a nested `where` clause after the function, where
* both sides of the operator are references to columns.
*
* Similar to {@link WhereInterface}'s `whereRef` method.
*
* ### Examples
*
* Count people with same first and last names versus general public:
*
* ```ts
* const result = await db
* .selectFrom('person')
* .select((eb) => [
* eb.fn
* .count<number>('id')
* .filterWhereRef('first_name', '=', 'last_name')
* .as('repeat_name_count'),
* eb.fn.count<number>('id').as('total_count'),
* ])
* .executeTakeFirstOrThrow()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select
* count("id") filter(where "first_name" = "last_name") as "repeat_name_count",
* count("id") as "total_count"
* from "person"
* ```
*/
filterWhereRef(lhs, op, rhs) {
return new AggregateFunctionBuilder({
...this.#props,
aggregateFunctionNode: aggregate_function_node_js_1.AggregateFunctionNode.cloneWithFilter(this.#props.aggregateFunctionNode, (0, binary_operation_parser_js_1.parseReferentialBinaryOperation)(lhs, op, rhs)),
});
}
/**
* Adds an `over` clause (window functions) after the function.
*
* ### Examples
*
* ```ts
* const result = await db
* .selectFrom('person')
* .select(
* (eb) => eb.fn.avg<number>('age').over().as('average_age')
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select avg("age") over() as "average_age"
* from "person"
* ```
*
* Also supports passing a callback that returns an over builder,
* allowing to add partition by and sort by clauses inside over.
*
* ```ts
* const result = await db
* .selectFrom('person')
* .select(
* (eb) => eb.fn.avg<number>('age').over(
* ob => ob.partitionBy('last_name').orderBy('first_name', 'asc')
* ).as('average_age')
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select avg("age") over(partition by "last_name" order by "first_name" asc) as "average_age"
* from "person"
* ```
*/
over(over) {
const builder = (0, parse_utils_js_1.createOverBuilder)();
return new AggregateFunctionBuilder({
...this.#props,
aggregateFunctionNode: aggregate_function_node_js_1.AggregateFunctionNode.cloneWithOver(this.#props.aggregateFunctionNode, (over ? over(builder) : builder).toOperationNode()),
});
}
/**
* Simply calls the provided function passing `this` as the only argument. `$call` returns
* what the provided function returns.
*/
$call(func) {
return func(this);
}
/**
* Casts the expression to the given type.
*
* This method call doesn't change the SQL in any way. This methods simply
* returns a copy of this `AggregateFunctionBuilder` with a new output type.
*/
$castTo() {
return new AggregateFunctionBuilder(this.#props);
}
/**
* Omit null from the expression's type.
*
* This function can be useful in cases where you know an expression can't be
* null, but Kysely is unable to infer it.
*
* This method call doesn't change the SQL in any way. This methods simply
* returns a copy of `this` with a new output type.
*/
$notNull() {
return new AggregateFunctionBuilder(this.#props);
}
toOperationNode() {
return this.#props.aggregateFunctionNode;
}
}
exports.AggregateFunctionBuilder = AggregateFunctionBuilder;
/**
* {@link AggregateFunctionBuilder} with an alias. The result of calling {@link AggregateFunctionBuilder.as}.
*/
class AliasedAggregateFunctionBuilder {
#aggregateFunctionBuilder;
#alias;
constructor(aggregateFunctionBuilder, alias) {
this.#aggregateFunctionBuilder = aggregateFunctionBuilder;
this.#alias = alias;
}
/** @private */
get expression() {
return this.#aggregateFunctionBuilder;
}
/** @private */
get alias() {
return this.#alias;
}
toOperationNode() {
return alias_node_js_1.AliasNode.create(this.#aggregateFunctionBuilder.toOperationNode(), identifier_node_js_1.IdentifierNode.create(this.#alias));
}
}
exports.AliasedAggregateFunctionBuilder = AliasedAggregateFunctionBuilder;

View File

@@ -0,0 +1,112 @@
import type { Expression } from '../expression/expression.js';
import { ExpressionWrapper } from '../expression/expression-wrapper.js';
import type { ReferenceExpression } from '../parser/reference-parser.js';
import { CaseNode } from '../operation-node/case-node.js';
import { type ComparisonOperatorExpression, type OperandValueExpressionOrList } from '../parser/binary-operation-parser.js';
import { type ExtractTypeFromValueExpression } from '../parser/value-parser.js';
import type { KyselyTypeError } from '../util/type-error.js';
export declare class CaseBuilder<DB, TB extends keyof DB, W = unknown, O = never> implements Whenable<DB, TB, W, O> {
#private;
constructor(props: CaseBuilderProps);
/**
* Adds a `when` clause to the case statement.
*
* A `when` call must be followed by a {@link CaseThenBuilder.then} call.
*/
when<RE extends ReferenceExpression<DB, TB>, VE extends OperandValueExpressionOrList<DB, TB, RE>>(lhs: unknown extends W ? RE : KyselyTypeError<'when(lhs, op, rhs) is not supported when using case(value)'>, op: ComparisonOperatorExpression, rhs: VE): CaseThenBuilder<DB, TB, W, O>;
when(expression: Expression<W>): CaseThenBuilder<DB, TB, W, O>;
when(value: unknown extends W ? KyselyTypeError<'when(value) is only supported when using case(value)'> : W): CaseThenBuilder<DB, TB, W, O>;
}
interface CaseBuilderProps {
readonly node: CaseNode;
}
export declare class CaseThenBuilder<DB, TB extends keyof DB, W, O> {
#private;
constructor(props: CaseBuilderProps);
/**
* Adds a `then` clause to the `case` statement.
*
* A `then` call can be followed by {@link Whenable.when}, {@link CaseWhenBuilder.else},
* {@link CaseWhenBuilder.end} or {@link CaseWhenBuilder.endCase} call.
*/
then<E extends Expression<unknown>>(expression: E): CaseWhenBuilder<DB, TB, W, O | ExtractTypeFromValueExpression<E>>;
then<V>(value: V): CaseWhenBuilder<DB, TB, W, O | V>;
}
export declare class CaseWhenBuilder<DB, TB extends keyof DB, W, O> implements Whenable<DB, TB, W, O>, Endable<DB, TB, O | null> {
#private;
constructor(props: CaseBuilderProps);
/**
* Adds a `when` clause to the case statement.
*
* A `when` call must be followed by a {@link CaseThenBuilder.then} call.
*/
when<RE extends ReferenceExpression<DB, TB>, VE extends OperandValueExpressionOrList<DB, TB, RE>>(lhs: unknown extends W ? RE : KyselyTypeError<'when(lhs, op, rhs) is not supported when using case(value)'>, op: ComparisonOperatorExpression, rhs: VE): CaseThenBuilder<DB, TB, W, O>;
when(expression: Expression<W>): CaseThenBuilder<DB, TB, W, O>;
when(value: unknown extends W ? KyselyTypeError<'when(value) is only supported when using case(value)'> : W): CaseThenBuilder<DB, TB, W, O>;
/**
* Adds an `else` clause to the `case` statement.
*
* An `else` call must be followed by an {@link Endable.end} or {@link Endable.endCase} call.
*/
else<E extends Expression<unknown>>(expression: E): CaseEndBuilder<DB, TB, O | ExtractTypeFromValueExpression<E>>;
else<V>(value: V): CaseEndBuilder<DB, TB, O | V>;
/**
* Adds an `end` keyword to the case operator.
*
* `case` operators can only be used as part of a query.
* For a `case` statement used as part of a stored program, use {@link endCase} instead.
*/
end(): ExpressionWrapper<DB, TB, O | null>;
/**
* Adds `end case` keywords to the case statement.
*
* `case` statements can only be used for flow control in stored programs.
* For a `case` operator used as part of a query, use {@link end} instead.
*/
endCase(): ExpressionWrapper<DB, TB, O | null>;
}
export declare class CaseEndBuilder<DB, TB extends keyof DB, O> implements Endable<DB, TB, O> {
#private;
constructor(props: CaseBuilderProps);
/**
* Adds an `end` keyword to the case operator.
*
* `case` operators can only be used as part of a query.
* For a `case` statement used as part of a stored program, use {@link endCase} instead.
*/
end(): ExpressionWrapper<DB, TB, O>;
/**
* Adds `end case` keywords to the case statement.
*
* `case` statements can only be used for flow control in stored programs.
* For a `case` operator used as part of a query, use {@link end} instead.
*/
endCase(): ExpressionWrapper<DB, TB, O>;
}
interface Whenable<DB, TB extends keyof DB, W, O> {
/**
* Adds a `when` clause to the case statement.
*
* A `when` call must be followed by a {@link CaseThenBuilder.then} call.
*/
when<RE extends ReferenceExpression<DB, TB>, VE extends OperandValueExpressionOrList<DB, TB, RE>>(lhs: unknown extends W ? RE : KyselyTypeError<'when(lhs, op, rhs) is not supported when using case(value)'>, op: ComparisonOperatorExpression, rhs: VE): CaseThenBuilder<DB, TB, W, O>;
when(expression: Expression<W>): CaseThenBuilder<DB, TB, W, O>;
when(value: unknown extends W ? KyselyTypeError<'when(value) is only supported when using case(value)'> : W): CaseThenBuilder<DB, TB, W, O>;
}
interface Endable<DB, TB extends keyof DB, O> {
/**
* Adds an `end` keyword to the case operator.
*
* `case` operators can only be used as part of a query.
* For a `case` statement used as part of a stored program, use {@link endCase} instead.
*/
end(): ExpressionWrapper<DB, TB, O>;
/**
* Adds `end case` keywords to the case statement.
*
* `case` statements can only be used for flow control in stored programs.
* For a `case` operator used as part of a query, use {@link end} instead.
*/
endCase(): ExpressionWrapper<DB, TB, O>;
}
export {};

View File

@@ -0,0 +1,79 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CaseEndBuilder = exports.CaseWhenBuilder = exports.CaseThenBuilder = exports.CaseBuilder = void 0;
const expression_wrapper_js_1 = require("../expression/expression-wrapper.js");
const object_utils_js_1 = require("../util/object-utils.js");
const case_node_js_1 = require("../operation-node/case-node.js");
const when_node_js_1 = require("../operation-node/when-node.js");
const binary_operation_parser_js_1 = require("../parser/binary-operation-parser.js");
const value_parser_js_1 = require("../parser/value-parser.js");
class CaseBuilder {
#props;
constructor(props) {
this.#props = (0, object_utils_js_1.freeze)(props);
}
when(...args) {
return new CaseThenBuilder({
...this.#props,
node: case_node_js_1.CaseNode.cloneWithWhen(this.#props.node, when_node_js_1.WhenNode.create((0, binary_operation_parser_js_1.parseValueBinaryOperationOrExpression)(args))),
});
}
}
exports.CaseBuilder = CaseBuilder;
class CaseThenBuilder {
#props;
constructor(props) {
this.#props = (0, object_utils_js_1.freeze)(props);
}
then(valueExpression) {
return new CaseWhenBuilder({
...this.#props,
node: case_node_js_1.CaseNode.cloneWithThen(this.#props.node, (0, value_parser_js_1.isSafeImmediateValue)(valueExpression)
? (0, value_parser_js_1.parseSafeImmediateValue)(valueExpression)
: (0, value_parser_js_1.parseValueExpression)(valueExpression)),
});
}
}
exports.CaseThenBuilder = CaseThenBuilder;
class CaseWhenBuilder {
#props;
constructor(props) {
this.#props = (0, object_utils_js_1.freeze)(props);
}
when(...args) {
return new CaseThenBuilder({
...this.#props,
node: case_node_js_1.CaseNode.cloneWithWhen(this.#props.node, when_node_js_1.WhenNode.create((0, binary_operation_parser_js_1.parseValueBinaryOperationOrExpression)(args))),
});
}
else(valueExpression) {
return new CaseEndBuilder({
...this.#props,
node: case_node_js_1.CaseNode.cloneWith(this.#props.node, {
else: (0, value_parser_js_1.isSafeImmediateValue)(valueExpression)
? (0, value_parser_js_1.parseSafeImmediateValue)(valueExpression)
: (0, value_parser_js_1.parseValueExpression)(valueExpression),
}),
});
}
end() {
return new expression_wrapper_js_1.ExpressionWrapper(case_node_js_1.CaseNode.cloneWith(this.#props.node, { isStatement: false }));
}
endCase() {
return new expression_wrapper_js_1.ExpressionWrapper(case_node_js_1.CaseNode.cloneWith(this.#props.node, { isStatement: true }));
}
}
exports.CaseWhenBuilder = CaseWhenBuilder;
class CaseEndBuilder {
#props;
constructor(props) {
this.#props = (0, object_utils_js_1.freeze)(props);
}
end() {
return new expression_wrapper_js_1.ExpressionWrapper(case_node_js_1.CaseNode.cloneWith(this.#props.node, { isStatement: false }));
}
endCase() {
return new expression_wrapper_js_1.ExpressionWrapper(case_node_js_1.CaseNode.cloneWith(this.#props.node, { isStatement: true }));
}
}
exports.CaseEndBuilder = CaseEndBuilder;

View File

@@ -0,0 +1,20 @@
import type { OperationNodeSource } from '../operation-node/operation-node-source.js';
import { CommonTableExpressionNode } from '../operation-node/common-table-expression-node.js';
export declare class CTEBuilder<N extends string> implements OperationNodeSource {
#private;
constructor(props: CTEBuilderProps);
/**
* Makes the common table expression materialized.
*/
materialized(): CTEBuilder<N>;
/**
* Makes the common table expression not materialized.
*/
notMaterialized(): CTEBuilder<N>;
toOperationNode(): CommonTableExpressionNode;
}
interface CTEBuilderProps {
readonly node: CommonTableExpressionNode;
}
export type CTEBuilderCallback<N extends string> = (cte: <N2 extends string>(name: N2) => CTEBuilder<N2>) => CTEBuilder<N>;
export {};

View File

@@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CTEBuilder = void 0;
const common_table_expression_node_js_1 = require("../operation-node/common-table-expression-node.js");
const object_utils_js_1 = require("../util/object-utils.js");
class CTEBuilder {
#props;
constructor(props) {
this.#props = (0, object_utils_js_1.freeze)(props);
}
/**
* Makes the common table expression materialized.
*/
materialized() {
return new CTEBuilder({
...this.#props,
node: common_table_expression_node_js_1.CommonTableExpressionNode.cloneWith(this.#props.node, {
materialized: true,
}),
});
}
/**
* Makes the common table expression not materialized.
*/
notMaterialized() {
return new CTEBuilder({
...this.#props,
node: common_table_expression_node_js_1.CommonTableExpressionNode.cloneWith(this.#props.node, {
materialized: false,
}),
});
}
toOperationNode() {
return this.#props.node;
}
}
exports.CTEBuilder = CTEBuilder;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,504 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DeleteQueryBuilder = void 0;
const join_parser_js_1 = require("../parser/join-parser.js");
const table_parser_js_1 = require("../parser/table-parser.js");
const select_parser_js_1 = require("../parser/select-parser.js");
const query_node_js_1 = require("../operation-node/query-node.js");
const object_utils_js_1 = require("../util/object-utils.js");
const no_result_error_js_1 = require("./no-result-error.js");
const delete_result_js_1 = require("./delete-result.js");
const delete_query_node_js_1 = require("../operation-node/delete-query-node.js");
const limit_node_js_1 = require("../operation-node/limit-node.js");
const order_by_parser_js_1 = require("../parser/order-by-parser.js");
const binary_operation_parser_js_1 = require("../parser/binary-operation-parser.js");
const value_parser_js_1 = require("../parser/value-parser.js");
const top_parser_js_1 = require("../parser/top-parser.js");
class DeleteQueryBuilder {
#props;
constructor(props) {
this.#props = (0, object_utils_js_1.freeze)(props);
}
where(...args) {
return new DeleteQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithWhere(this.#props.queryNode, (0, binary_operation_parser_js_1.parseValueBinaryOperationOrExpression)(args)),
});
}
whereRef(lhs, op, rhs) {
return new DeleteQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithWhere(this.#props.queryNode, (0, binary_operation_parser_js_1.parseReferentialBinaryOperation)(lhs, op, rhs)),
});
}
clearWhere() {
return new DeleteQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithoutWhere(this.#props.queryNode),
});
}
/**
* Changes a `delete from` query into a `delete top from` query.
*
* `top` clause is only supported by some dialects like MS SQL Server.
*
* ### Examples
*
* Delete the first 5 rows:
*
* ```ts
* await db
* .deleteFrom('person')
* .top(5)
* .where('age', '>', 18)
* .executeTakeFirstOrThrow()
* ```
*
* The generated SQL (MS SQL Server):
*
* ```sql
* delete top(5) from "person" where "age" > @1
* ```
*
* Delete the first 50% of rows:
*
* ```ts
* await db
* .deleteFrom('person')
* .top(50, 'percent')
* .where('age', '>', 18)
* .executeTakeFirstOrThrow()
* ```
*
* The generated SQL (MS SQL Server):
*
* ```sql
* delete top(50) percent from "person" where "age" > @1
* ```
*/
top(expression, modifiers) {
return new DeleteQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithTop(this.#props.queryNode, (0, top_parser_js_1.parseTop)(expression, modifiers)),
});
}
using(tables) {
return new DeleteQueryBuilder({
...this.#props,
queryNode: delete_query_node_js_1.DeleteQueryNode.cloneWithUsing(this.#props.queryNode, (0, table_parser_js_1.parseTableExpressionOrList)(tables)),
});
}
innerJoin(...args) {
return this.#join('InnerJoin', args);
}
leftJoin(...args) {
return this.#join('LeftJoin', args);
}
rightJoin(...args) {
return this.#join('RightJoin', args);
}
fullJoin(...args) {
return this.#join('FullJoin', args);
}
#join(joinType, args) {
return new DeleteQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithJoin(this.#props.queryNode, (0, join_parser_js_1.parseJoin)(joinType, args)),
});
}
returning(selection) {
return new DeleteQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithReturning(this.#props.queryNode, (0, select_parser_js_1.parseSelectArg)(selection)),
});
}
returningAll(table) {
return new DeleteQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithReturning(this.#props.queryNode, (0, select_parser_js_1.parseSelectAll)(table)),
});
}
output(args) {
return new DeleteQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithOutput(this.#props.queryNode, (0, select_parser_js_1.parseSelectArg)(args)),
});
}
outputAll(table) {
return new DeleteQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithOutput(this.#props.queryNode, (0, select_parser_js_1.parseSelectAll)(table)),
});
}
/**
* Clears all `returning` clauses from the query.
*
* ### Examples
*
* ```ts
* await db.deleteFrom('pet')
* .returningAll()
* .where('name', '=', 'Max')
* .clearReturning()
* .execute()
* ```
*
* The generated SQL(PostgreSQL):
*
* ```sql
* delete from "pet" where "name" = "Max"
* ```
*/
clearReturning() {
return new DeleteQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithoutReturning(this.#props.queryNode),
});
}
/**
* Clears the `limit` clause from the query.
*
* ### Examples
*
* ```ts
* await db.deleteFrom('pet')
* .returningAll()
* .where('name', '=', 'Max')
* .limit(5)
* .clearLimit()
* .execute()
* ```
*
* The generated SQL(PostgreSQL):
*
* ```sql
* delete from "pet" where "name" = "Max" returning *
* ```
*/
clearLimit() {
return new DeleteQueryBuilder({
...this.#props,
queryNode: delete_query_node_js_1.DeleteQueryNode.cloneWithoutLimit(this.#props.queryNode),
});
}
orderBy(...args) {
return new DeleteQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithOrderByItems(this.#props.queryNode, (0, order_by_parser_js_1.parseOrderBy)(args)),
});
}
clearOrderBy() {
return new DeleteQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithoutOrderBy(this.#props.queryNode),
});
}
/**
* Adds a limit clause to the query.
*
* A limit clause in a delete query is only supported by some dialects
* like MySQL.
*
* ### Examples
*
* Delete 5 oldest items in a table:
*
* ```ts
* await db
* .deleteFrom('pet')
* .orderBy('created_at')
* .limit(5)
* .execute()
* ```
*
* The generated SQL (MySQL):
*
* ```sql
* delete from `pet` order by `created_at` limit ?
* ```
*/
limit(limit) {
return new DeleteQueryBuilder({
...this.#props,
queryNode: delete_query_node_js_1.DeleteQueryNode.cloneWithLimit(this.#props.queryNode, limit_node_js_1.LimitNode.create((0, value_parser_js_1.parseValueExpression)(limit))),
});
}
/**
* This can be used to add any additional SQL to the end of the query.
*
* ### Examples
*
* ```ts
* import { sql } from 'kysely'
*
* await db.deleteFrom('person')
* .where('first_name', '=', 'John')
* .modifyEnd(sql`-- This is a comment`)
* .execute()
* ```
*
* The generated SQL (MySQL):
*
* ```sql
* delete from `person`
* where `first_name` = "John" -- This is a comment
* ```
*/
modifyEnd(modifier) {
return new DeleteQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithEndModifier(this.#props.queryNode, modifier.toOperationNode()),
});
}
/**
* Simply calls the provided function passing `this` as the only argument. `$call` returns
* what the provided function returns.
*
* If you want to conditionally call a method on `this`, see
* the {@link $if} method.
*
* ### Examples
*
* The next example uses a helper function `log` to log a query:
*
* ```ts
* import type { Compilable } from 'kysely'
*
* function log<T extends Compilable>(qb: T): T {
* console.log(qb.compile())
* return qb
* }
*
* await db.deleteFrom('person')
* .$call(log)
* .execute()
* ```
*/
$call(func) {
return func(this);
}
/**
* Call `func(this)` if `condition` is true.
*
* This method is especially handy with optional selects. Any `returning` or `returningAll`
* method calls add columns as optional fields to the output type when called inside
* the `func` callback. This is because we can't know if those selections were actually
* made before running the code.
*
* You can also call any other methods inside the callback.
*
* ### Examples
*
* ```ts
* async function deletePerson(id: number, returnLastName: boolean) {
* return await db
* .deleteFrom('person')
* .where('id', '=', id)
* .returning(['id', 'first_name'])
* .$if(returnLastName, (qb) => qb.returning('last_name'))
* .executeTakeFirstOrThrow()
* }
* ```
*
* Any selections added inside the `if` callback will be added as optional fields to the
* output type since we can't know if the selections were actually made before running
* the code. In the example above the return type of the `deletePerson` function is:
*
* ```ts
* Promise<{
* id: number
* first_name: string
* last_name?: string
* }>
* ```
*/
$if(condition, func) {
if (condition) {
return func(this);
}
return new DeleteQueryBuilder({
...this.#props,
});
}
/**
* Change the output type of the query.
*
* This method call doesn't change the SQL in any way. This methods simply
* returns a copy of this `DeleteQueryBuilder` with a new output type.
*/
$castTo() {
return new DeleteQueryBuilder(this.#props);
}
/**
* Narrows (parts of) the output type of the query.
*
* Kysely tries to be as type-safe as possible, but in some cases we have to make
* compromises for better maintainability and compilation performance. At present,
* Kysely doesn't narrow the output type of the query when using {@link where} and {@link returning} or {@link returningAll}.
*
* This utility method is very useful for these situations, as it removes unncessary
* runtime assertion/guard code. Its input type is limited to the output type
* of the query, so you can't add a column that doesn't exist, or change a column's
* type to something that doesn't exist in its union type.
*
* ### Examples
*
* Turn this code:
*
* ```ts
* import type { Person } from 'type-editor' // imaginary module
*
* const person = await db.deleteFrom('person')
* .where('id', '=', 3)
* .where('nullable_column', 'is not', null)
* .returningAll()
* .executeTakeFirstOrThrow()
*
* if (isWithNoNullValue(person)) {
* functionThatExpectsPersonWithNonNullValue(person)
* }
*
* function isWithNoNullValue(person: Person): person is Person & { nullable_column: string } {
* return person.nullable_column != null
* }
* ```
*
* Into this:
*
* ```ts
* import type { NotNull } from 'kysely'
*
* const person = await db.deleteFrom('person')
* .where('id', '=', 3)
* .where('nullable_column', 'is not', null)
* .returningAll()
* .$narrowType<{ nullable_column: NotNull }>()
* .executeTakeFirstOrThrow()
*
* functionThatExpectsPersonWithNonNullValue(person)
* ```
*/
$narrowType() {
return new DeleteQueryBuilder(this.#props);
}
/**
* Asserts that query's output row type equals the given type `T`.
*
* This method can be used to simplify excessively complex types to make TypeScript happy
* and much faster.
*
* Kysely uses complex type magic to achieve its type safety. This complexity is sometimes too much
* for TypeScript and you get errors like this:
*
* ```
* error TS2589: Type instantiation is excessively deep and possibly infinite.
* ```
*
* In these case you can often use this method to help TypeScript a little bit. When you use this
* method to assert the output type of a query, Kysely can drop the complex output type that
* consists of multiple nested helper types and replace it with the simple asserted type.
*
* Using this method doesn't reduce type safety at all. You have to pass in a type that is
* structurally equal to the current type.
*
* ### Examples
*
* ```ts
* import type { Species } from 'type-editor' // imaginary module
*
* async function deletePersonAndPets(personId: number) {
* return await db
* .with('deleted_person', (qb) => qb
* .deleteFrom('person')
* .where('id', '=', personId)
* .returning('first_name')
* .$assertType<{ first_name: string }>()
* )
* .with('deleted_pets', (qb) => qb
* .deleteFrom('pet')
* .where('owner_id', '=', personId)
* .returning(['name as pet_name', 'species'])
* .$assertType<{ pet_name: string, species: Species }>()
* )
* .selectFrom(['deleted_person', 'deleted_pets'])
* .selectAll()
* .execute()
* }
* ```
*/
$assertType() {
return new DeleteQueryBuilder(this.#props);
}
/**
* Returns a copy of this DeleteQueryBuilder instance with the given plugin installed.
*/
withPlugin(plugin) {
return new DeleteQueryBuilder({
...this.#props,
executor: this.#props.executor.withPlugin(plugin),
});
}
toOperationNode() {
return this.#props.executor.transformQuery(this.#props.queryNode, this.#props.queryId);
}
compile() {
return this.#props.executor.compileQuery(this.toOperationNode(), this.#props.queryId);
}
/**
* Executes the query and returns an array of rows.
*
* Also see the {@link executeTakeFirst} and {@link executeTakeFirstOrThrow} methods.
*/
async execute() {
const compiledQuery = this.compile();
const result = await this.#props.executor.executeQuery(compiledQuery);
const { adapter } = this.#props.executor;
const query = compiledQuery.query;
if ((query.returning && adapter.supportsReturning) ||
(query.output && adapter.supportsOutput)) {
return result.rows;
}
return [new delete_result_js_1.DeleteResult(result.numAffectedRows ?? BigInt(0))];
}
/**
* Executes the query and returns the first result or undefined if
* the query returned no result.
*/
async executeTakeFirst() {
const [result] = await this.execute();
return result;
}
/**
* Executes the query and returns the first result or throws if
* the query returned no result.
*
* By default an instance of {@link NoResultError} is thrown, but you can
* provide a custom error class, or callback as the only argument to throw a different
* error.
*/
async executeTakeFirstOrThrow(errorConstructor = no_result_error_js_1.NoResultError) {
const result = await this.executeTakeFirst();
if (result === undefined) {
const error = (0, no_result_error_js_1.isNoResultErrorConstructor)(errorConstructor)
? new errorConstructor(this.toOperationNode())
: errorConstructor(this.toOperationNode());
throw error;
}
return result;
}
async *stream(chunkSize = 100) {
const compiledQuery = this.compile();
const stream = this.#props.executor.stream(compiledQuery, chunkSize);
for await (const item of stream) {
yield* item.rows;
}
}
async explain(format, options) {
const builder = new DeleteQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithExplain(this.#props.queryNode, format, options),
});
return await builder.execute();
}
}
exports.DeleteQueryBuilder = DeleteQueryBuilder;

View File

@@ -0,0 +1,4 @@
export declare class DeleteResult {
readonly numDeletedRows: bigint;
constructor(numDeletedRows: bigint);
}

View File

@@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DeleteResult = void 0;
class DeleteResult {
numDeletedRows;
constructor(numDeletedRows) {
this.numDeletedRows = numDeletedRows;
}
}
exports.DeleteResult = DeleteResult;

View File

@@ -0,0 +1,592 @@
import { ExpressionWrapper } from '../expression/expression-wrapper.js';
import type { Expression } from '../expression/expression.js';
import type { ExtractTypeFromCoalesce1, ExtractTypeFromCoalesce3, ExtractTypeFromCoalesce2, ExtractTypeFromCoalesce4, ExtractTypeFromCoalesce5 } from '../parser/coalesce-parser.js';
import { type ExtractTypeFromReferenceExpression, type ReferenceExpression, type StringReference, type ExtractTypeFromStringReference } from '../parser/reference-parser.js';
import type { KyselyTypeError } from '../util/type-error.js';
import type { IsNever, ShallowDehydrateObject, ShallowDehydrateValue, Simplify } from '../util/type-utils.js';
import { AggregateFunctionBuilder } from './aggregate-function-builder.js';
import type { SelectQueryBuilderExpression } from '../query-builder/select-query-builder-expression.js';
import type { Selectable, SelectType } from '../util/column-type.js';
/**
* Helpers for type safe SQL function calls.
*
* You can always use the {@link sql} tag to call functions and build arbitrary
* expressions. This module simply has shortcuts for most common function calls.
*
* ### Examples
*
* <!-- siteExample("select", "Function calls", 60) -->
*
* This example shows how to create function calls. These examples also work in any
* other place (`where` calls, updates, inserts etc.). The only difference is that you
* leave out the alias (the `as` call) if you use these in any other place than `select`.
*
* ```ts
* import { sql } from 'kysely'
*
* const result = await db.selectFrom('person')
* .innerJoin('pet', 'pet.owner_id', 'person.id')
* .select(({ fn, val, ref }) => [
* 'person.id',
*
* // The `fn` module contains the most common
* // functions.
* fn.count<number>('pet.id').as('pet_count'),
*
* // You can call any function by calling `fn`
* // directly. The arguments are treated as column
* // references by default. If you want to pass in
* // values, use the `val` function.
* fn<string>('concat', [
* val('Ms. '),
* 'first_name',
* val(' '),
* 'last_name'
* ]).as('full_name_with_title'),
*
* // You can call any aggregate function using the
* // `fn.agg` function.
* fn.agg<string[]>('array_agg', ['pet.name']).as('pet_names'),
*
* // And once again, you can use the `sql`
* // template tag. The template tag substitutions
* // are treated as values by default. If you want
* // to reference columns, you can use the `ref`
* // function.
* sql<string>`concat(
* ${ref('first_name')},
* ' ',
* ${ref('last_name')}
* )`.as('full_name')
* ])
* .groupBy('person.id')
* .having((eb) => eb.fn.count('pet.id'), '>', 10)
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select
* "person"."id",
* count("pet"."id") as "pet_count",
* concat($1, "first_name", $2, "last_name") as "full_name_with_title",
* array_agg("pet"."name") as "pet_names",
* concat("first_name", ' ', "last_name") as "full_name"
* from "person"
* inner join "pet" on "pet"."owner_id" = "person"."id"
* group by "person"."id"
* having count("pet"."id") > $3
* ```
*/
export interface FunctionModule<DB, TB extends keyof DB> {
/**
* Creates a function call.
*
* To create an aggregate function call, use {@link FunctionModule.agg}.
*
* ### Examples
*
* ```ts
* await db.selectFrom('person')
* .selectAll('person')
* .where(db.fn('upper', ['first_name']), '=', 'JENNIFER')
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "person".*
* from "person"
* where upper("first_name") = $1
* ```
*
* If you prefer readability over type-safety, you can always use raw `sql`:
*
* ```ts
* import { sql } from 'kysely'
*
* await db.selectFrom('person')
* .selectAll('person')
* .where(sql<string>`upper(first_name)`, '=', 'JENNIFER')
* .execute()
* ```
*/
<O, RE extends ReferenceExpression<DB, TB> = ReferenceExpression<DB, TB>>(name: string, args?: ReadonlyArray<RE>): ExpressionWrapper<DB, TB, O>;
/**
* Creates an aggregate function call.
*
* This is a specialized version of the `fn` method, that returns an {@link AggregateFunctionBuilder}
* instance. A builder that allows you to chain additional methods such as `distinct`,
* `filterWhere` and `over`.
*
* See {@link avg}, {@link count}, {@link countAll}, {@link max}, {@link min}, {@link sum}
* shortcuts of common aggregate functions.
*
* ### Examples
*
* ```ts
* await db.selectFrom('person')
* .select(({ fn }) => [
* fn.agg<number>('rank').over().as('rank'),
* fn.agg<string>('group_concat', ['first_name']).distinct().as('first_names')
* ])
* .execute()
* ```
*
* The generated SQL (MySQL):
*
* ```sql
* select rank() over() as "rank",
* group_concat(distinct "first_name") as "first_names"
* from "person"
* ```
*/
agg<O, RE extends ReferenceExpression<DB, TB> = ReferenceExpression<DB, TB>>(name: string, args?: ReadonlyArray<RE>): AggregateFunctionBuilder<DB, TB, O>;
/**
* Calls the `avg` function for the column or expression given as the argument.
*
* This sql function calculates the average value for a given column.
*
* For additional functionality such as distinct, filtering and window functions,
* refer to {@link AggregateFunctionBuilder}. An instance of this builder is
* returned when calling this function.
*
* ### Examples
*
* ```ts
* await db.selectFrom('toy')
* .select((eb) => eb.fn.avg('price').as('avg_price'))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select avg("price") as "avg_price" from "toy"
* ```
*
* If this function is used in a `select` statement, the type of the selected
* expression will be `number | string` by default. This is because Kysely can't know the
* type the db driver outputs. Sometimes the output can be larger than the largest
* JavaScript number and a string is returned instead. Most drivers allow you
* to configure the output type of large numbers and Kysely can't know if you've
* done so.
*
* You can specify the output type of the expression by providing the type as
* the first type argument:
*
* ```ts
* await db.selectFrom('toy')
* .select((eb) => eb.fn.avg<number>('price').as('avg_price'))
* .execute()
* ```
*
* Sometimes a null is returned, e.g. when row count is 0, and no `group by`
* was used. It is highly recommended to include null in the output type union
* and handle null values in post-execute code, or wrap the function with a {@link coalesce}
* function.
*
* ```ts
* await db.selectFrom('toy')
* .select((eb) => eb.fn.avg<number | null>('price').as('avg_price'))
* .execute()
* ```
*/
avg<O extends number | string | null = number | string, RE extends ReferenceExpression<DB, TB> = ReferenceExpression<DB, TB>>(expr: RE): AggregateFunctionBuilder<DB, TB, O>;
/**
* Calls the `coalesce` function for given arguments.
*
* This sql function returns the first non-null value from left to right, commonly
* used to provide a default scalar for nullable columns or functions.
*
* If this function is used in a `select` statement, the type of the selected
* expression is inferred in the same manner that the sql function computes.
* A union of arguments' types - if a non-nullable argument exists, it stops
* there (ignoring any further arguments' types) and exludes null from the final
* union type.
*
* `(string | null, number | null)` is inferred as `string | number | null`.
*
* `(string | null, number, Date | null)` is inferred as `string | number`.
*
* `(number, string | null)` is inferred as `number`.
*
* ### Examples
*
* ```ts
* import { sql } from 'kysely'
*
* await db.selectFrom('person')
* .select((eb) => eb.fn.coalesce('nullable_column', sql.lit('<unknown>')).as('column'))
* .where('first_name', '=', 'Jessie')
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select coalesce("nullable_column", '<unknown>') as "column" from "person" where "first_name" = $1
* ```
*
* You can combine this function with other helpers in this module:
*
* ```ts
* await db.selectFrom('person')
* .select((eb) => eb.fn.coalesce(eb.fn.avg<number | null>('age'), eb.lit(0)).as('avg_age'))
* .where('first_name', '=', 'Jennifer')
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select coalesce(avg("age"), 0) as "avg_age" from "person" where "first_name" = $1
* ```
*/
coalesce<V1 extends ReferenceExpression<DB, TB>>(v1: V1): ExpressionWrapper<DB, TB, ExtractTypeFromCoalesce1<DB, TB, V1>>;
coalesce<V1 extends ReferenceExpression<DB, TB>, V2 extends ReferenceExpression<DB, TB>>(v1: V1, v2: V2): ExpressionWrapper<DB, TB, ExtractTypeFromCoalesce2<DB, TB, V1, V2>>;
coalesce<V1 extends ReferenceExpression<DB, TB>, V2 extends ReferenceExpression<DB, TB>, V3 extends ReferenceExpression<DB, TB>>(v1: V1, v2: V2, v3: V3): ExpressionWrapper<DB, TB, ExtractTypeFromCoalesce3<DB, TB, V1, V2, V3>>;
coalesce<V1 extends ReferenceExpression<DB, TB>, V2 extends ReferenceExpression<DB, TB>, V3 extends ReferenceExpression<DB, TB>, V4 extends ReferenceExpression<DB, TB>>(v1: V1, v2: V2, v3: V3, v4: V4): ExpressionWrapper<DB, TB, ExtractTypeFromCoalesce4<DB, TB, V1, V2, V3, V4>>;
coalesce<V1 extends ReferenceExpression<DB, TB>, V2 extends ReferenceExpression<DB, TB>, V3 extends ReferenceExpression<DB, TB>, V4 extends ReferenceExpression<DB, TB>, V5 extends ReferenceExpression<DB, TB>>(v1: V1, v2: V2, v3: V3, v4: V4, v5: V5): ExpressionWrapper<DB, TB, ExtractTypeFromCoalesce5<DB, TB, V1, V2, V3, V4, V5>>;
/**
* Calls the `count` function for the column or expression given as the argument.
*
* When called with a column as argument, this sql function counts the number of rows where there
* is a non-null value in that column.
*
* For counting all rows nulls included (`count(*)`), see {@link countAll}.
*
* For additional functionality such as distinct, filtering and window functions,
* refer to {@link AggregateFunctionBuilder}. An instance of this builder is
* returned when calling this function.
*
* ### Examples
*
* ```ts
* await db.selectFrom('toy')
* .select((eb) => eb.fn.count('id').as('num_toys'))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select count("id") as "num_toys" from "toy"
* ```
*
* If this function is used in a `select` statement, the type of the selected
* expression will be `number | string | bigint` by default. This is because
* Kysely can't know the type the db driver outputs. Sometimes the output can
* be larger than the largest JavaScript number and a string is returned instead.
* Most drivers allow you to configure the output type of large numbers and Kysely
* can't know if you've done so.
*
* You can specify the output type of the expression by providing
* the type as the first type argument:
*
* ```ts
* await db.selectFrom('toy')
* .select((eb) => eb.fn.count<number>('id').as('num_toys'))
* .execute()
* ```
*/
count<O extends number | string | bigint, RE extends ReferenceExpression<DB, TB> = ReferenceExpression<DB, TB>>(expr: RE): AggregateFunctionBuilder<DB, TB, O>;
/**
* Calls the `count` function with `*` or `table.*` as argument.
*
* When called with `*` as argument, this sql function counts the number of rows,
* nulls included.
*
* For counting rows with non-null values in a given column (`count(column)`),
* see {@link count}.
*
* For additional functionality such as filtering and window functions, refer
* to {@link AggregateFunctionBuilder}. An instance of this builder is returned
* when calling this function.
*
* ### Examples
*
* ```ts
* await db.selectFrom('toy')
* .select((eb) => eb.fn.countAll().as('num_toys'))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select count(*) as "num_toys" from "toy"
* ```
*
* If this is used in a `select` statement, the type of the selected expression
* will be `number | string | bigint` by default. This is because Kysely
* can't know the type the db driver outputs. Sometimes the output can be larger
* than the largest JavaScript number and a string is returned instead. Most
* drivers allow you to configure the output type of large numbers and Kysely
* can't know if you've done so.
*
* You can specify the output type of the expression by providing
* the type as the first type argument:
*
* ```ts
* await db.selectFrom('toy')
* .select((eb) => eb.fn.countAll<number>().as('num_toys'))
* .execute()
* ```
*
* Some databases, such as PostgreSQL, support scoping the function to a specific
* table:
*
* ```ts
* await db.selectFrom('toy')
* .innerJoin('pet', 'pet.id', 'toy.pet_id')
* .select((eb) => eb.fn.countAll('toy').as('num_toys'))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select count("toy".*) as "num_toys"
* from "toy" inner join "pet" on "pet"."id" = "toy"."pet_id"
* ```
*/
countAll<O extends number | string | bigint, T extends TB = TB>(table: T): AggregateFunctionBuilder<DB, TB, O>;
countAll<O extends number | string | bigint>(): AggregateFunctionBuilder<DB, TB, O>;
/**
* Calls the `max` function for the column or expression given as the argument.
*
* This sql function calculates the maximum value for a given column.
*
* For additional functionality such as distinct, filtering and window functions,
* refer to {@link AggregateFunctionBuilder}. An instance of this builder is
* returned when calling this function.
*
* If this function is used in a `select` statement, the type of the selected
* expression will be the referenced column's type. This is because the result
* is within the column's value range.
*
* ### Examples
*
* ```ts
* await db.selectFrom('toy')
* .select((eb) => eb.fn.max('price').as('max_price'))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select max("price") as "max_price" from "toy"
* ```
*
* Sometimes a null is returned, e.g. when row count is 0, and no `group by`
* was used. It is highly recommended to include null in the output type union
* and handle null values in post-execute code, or wrap the function with a {@link coalesce}
* function.
*
* ```ts
* await db.selectFrom('toy')
* .select((eb) => eb.fn.max<number | null>('price').as('max_price'))
* .execute()
* ```
*/
max<O extends number | string | Date | bigint | null = never, RE extends ReferenceExpression<DB, TB> = ReferenceExpression<DB, TB>>(expr: RE): AggregateFunctionBuilder<DB, TB, IsNever<O> extends true ? ExtractTypeFromReferenceExpression<DB, TB, RE, number | string | Date | bigint> : O>;
/**
* Calls the `min` function for the column or expression given as the argument.
*
* This sql function calculates the minimum value for a given column.
*
* For additional functionality such as distinct, filtering and window functions,
* refer to {@link AggregateFunctionBuilder}. An instance of this builder is
* returned when calling this function.
*
* If this function is used in a `select` statement, the type of the selected
* expression will be the referenced column's type. This is because the result
* is within the column's value range.
*
* ### Examples
*
* ```ts
* await db.selectFrom('toy')
* .select((eb) => eb.fn.min('price').as('min_price'))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select min("price") as "min_price" from "toy"
* ```
*
* Sometimes a null is returned, e.g. when row count is 0, and no `group by`
* was used. It is highly recommended to include null in the output type union
* and handle null values in post-execute code, or wrap the function with a {@link coalesce}
* function.
*
* ```ts
* await db.selectFrom('toy')
* .select((eb) => eb.fn.min<number | null>('price').as('min_price'))
* .execute()
* ```
*/
min<O extends number | string | Date | bigint | null = never, RE extends ReferenceExpression<DB, TB> = ReferenceExpression<DB, TB>>(expr: RE): AggregateFunctionBuilder<DB, TB, IsNever<O> extends true ? ExtractTypeFromReferenceExpression<DB, TB, RE, number | string | Date | bigint> : O>;
/**
* Calls the `sum` function for the column or expression given as the argument.
*
* This sql function sums the values of a given column.
*
* For additional functionality such as distinct, filtering and window functions,
* refer to {@link AggregateFunctionBuilder}. An instance of this builder is
* returned when calling this function.
*
* ### Examples
*
* ```ts
* await db.selectFrom('toy')
* .select((eb) => eb.fn.sum('price').as('total_price'))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select sum("price") as "total_price" from "toy"
* ```
*
* If this function is used in a `select` statement, the type of the selected
* expression will be `number | string` by default. This is because Kysely can't know the
* type the db driver outputs. Sometimes the output can be larger than the largest
* JavaScript number and a string is returned instead. Most drivers allow you
* to configure the output type of large numbers and Kysely can't know if you've
* done so.
*
* You can specify the output type of the expression by providing the type as
* the first type argument:
*
* ```ts
* await db.selectFrom('toy')
* .select((eb) => eb.fn.sum<number>('price').as('total_price'))
* .execute()
* ```
*
* Sometimes a null is returned, e.g. when row count is 0, and no `group by`
* was used. It is highly recommended to include null in the output type union
* and handle null values in post-execute code, or wrap the function with a {@link coalesce}
* function.
*
* ```ts
* await db.selectFrom('toy')
* .select((eb) => eb.fn.sum<number | null>('price').as('total_price'))
* .execute()
* ```
*/
sum<O extends number | string | bigint | null = number | string | bigint, RE extends ReferenceExpression<DB, TB> = ReferenceExpression<DB, TB>>(expr: RE): AggregateFunctionBuilder<DB, TB, O>;
/**
* Calls the `any` function for the column or expression given as the argument.
*
* The argument must be a subquery or evaluate to an array.
*
* ### Examples
*
* In the following example, `nicknames` is assumed to be a column of type `string[]`:
*
* ```ts
* await db.selectFrom('person')
* .selectAll('person')
* .where((eb) => eb(
* eb.val('Jen'), '=', eb.fn.any('person.nicknames')
* ))
* .execute()
* ```
*
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select
* "person".*
* from
* "person"
* where
* $1 = any("person"."nicknames")
* ```
*/
any<RE extends StringReference<DB, TB>>(expr: RE): Exclude<ExtractTypeFromReferenceExpression<DB, TB, RE>, null> extends ReadonlyArray<infer I> ? ExpressionWrapper<DB, TB, I> : KyselyTypeError<'any(expr) call failed: expr must be an array'>;
any<T>(subquery: SelectQueryBuilderExpression<Record<string, T>>): ExpressionWrapper<DB, TB, T>;
any<T>(expr: Expression<ReadonlyArray<T>>): ExpressionWrapper<DB, TB, T>;
/**
* Creates a `json_agg` function call.
*
* This is only supported by some dialects like PostgreSQL.
*
* ### Examples
*
* You can use it on table expressions:
*
* ```ts
* await db.selectFrom('person')
* .innerJoin('pet', 'pet.owner_id', 'person.id')
* .select((eb) => ['first_name', eb.fn.jsonAgg('pet').as('pets')])
* .groupBy('person.first_name')
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "first_name", json_agg("pet") as "pets"
* from "person"
* inner join "pet" on "pet"."owner_id" = "person"."id"
* group by "person"."first_name"
* ```
*
* or on columns:
*
* ```ts
* await db.selectFrom('person')
* .innerJoin('pet', 'pet.owner_id', 'person.id')
* .select((eb) => [
* 'first_name',
* eb.fn.jsonAgg('pet.name').as('pet_names'),
* ])
* .groupBy('person.first_name')
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "first_name", json_agg("pet"."name") AS "pet_names"
* from "person"
* inner join "pet" ON "pet"."owner_id" = "person"."id"
* group by "person"."first_name"
* ```
*/
jsonAgg<T extends (TB & string) | Expression<unknown>>(table: T): AggregateFunctionBuilder<DB, TB, T extends TB ? Simplify<ShallowDehydrateObject<Selectable<DB[T]>>>[] : T extends Expression<infer O> ? Simplify<ShallowDehydrateObject<O>>[] : never>;
jsonAgg<RE extends StringReference<DB, TB>>(column: RE): AggregateFunctionBuilder<DB, TB, ShallowDehydrateValue<SelectType<ExtractTypeFromStringReference<DB, TB, RE>>>[] | null>;
/**
* Creates a to_json function call.
*
* This function is only available on PostgreSQL.
*
* ```ts
* await db.selectFrom('person')
* .innerJoin('pet', 'pet.owner_id', 'person.id')
* .select((eb) => ['first_name', eb.fn.toJson('pet').as('pet')])
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "first_name", to_json("pet") as "pet"
* from "person"
* inner join "pet" on "pet"."owner_id" = "person"."id"
* ```
*/
toJson<T extends (TB & string) | Expression<unknown>>(table: T): ExpressionWrapper<DB, TB, T extends TB ? Simplify<ShallowDehydrateObject<Selectable<DB[T]>>> : T extends Expression<infer O> ? Simplify<ShallowDehydrateObject<O>> : never>;
}
export declare function createFunctionModule<DB, TB extends keyof DB>(): FunctionModule<DB, TB>;

View File

@@ -0,0 +1,62 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createFunctionModule = createFunctionModule;
const expression_wrapper_js_1 = require("../expression/expression-wrapper.js");
const aggregate_function_node_js_1 = require("../operation-node/aggregate-function-node.js");
const function_node_js_1 = require("../operation-node/function-node.js");
const reference_parser_js_1 = require("../parser/reference-parser.js");
const select_parser_js_1 = require("../parser/select-parser.js");
const aggregate_function_builder_js_1 = require("./aggregate-function-builder.js");
const object_utils_js_1 = require("../util/object-utils.js");
const table_parser_js_1 = require("../parser/table-parser.js");
function createFunctionModule() {
const fn = (name, args) => {
return new expression_wrapper_js_1.ExpressionWrapper(function_node_js_1.FunctionNode.create(name, (0, reference_parser_js_1.parseReferenceExpressionOrList)(args ?? [])));
};
const agg = (name, args) => {
return new aggregate_function_builder_js_1.AggregateFunctionBuilder({
aggregateFunctionNode: aggregate_function_node_js_1.AggregateFunctionNode.create(name, args ? (0, reference_parser_js_1.parseReferenceExpressionOrList)(args) : undefined),
});
};
return Object.assign(fn, {
agg,
avg(column) {
return agg('avg', [column]);
},
coalesce(...values) {
return fn('coalesce', values);
},
count(column) {
return agg('count', [column]);
},
countAll(table) {
return new aggregate_function_builder_js_1.AggregateFunctionBuilder({
aggregateFunctionNode: aggregate_function_node_js_1.AggregateFunctionNode.create('count', (0, select_parser_js_1.parseSelectAll)(table)),
});
},
max(column) {
return agg('max', [column]);
},
min(column) {
return agg('min', [column]);
},
sum(column) {
return agg('sum', [column]);
},
any(column) {
return fn('any', [column]);
},
jsonAgg(table) {
return new aggregate_function_builder_js_1.AggregateFunctionBuilder({
aggregateFunctionNode: aggregate_function_node_js_1.AggregateFunctionNode.create('json_agg', [
(0, object_utils_js_1.isString)(table) ? (0, table_parser_js_1.parseTable)(table) : table.toOperationNode(),
]),
});
},
toJson(table) {
return new expression_wrapper_js_1.ExpressionWrapper(function_node_js_1.FunctionNode.create('to_json', [
(0, object_utils_js_1.isString)(table) ? (0, table_parser_js_1.parseTable)(table) : table.toOperationNode(),
]));
},
});
}

View File

@@ -0,0 +1,15 @@
import type { ComparisonOperatorExpression, OperandValueExpressionOrList } from '../parser/binary-operation-parser.js';
import type { ReferenceExpression } from '../parser/reference-parser.js';
export interface HavingInterface<DB, TB extends keyof DB> {
/**
* Just like {@link WhereInterface.where | where} but adds a `having` statement
* instead of a `where` statement.
*/
having<RE extends ReferenceExpression<DB, TB>, VE extends OperandValueExpressionOrList<DB, TB, RE>>(lhs: RE, op: ComparisonOperatorExpression, rhs: VE): HavingInterface<DB, TB>;
having<E>(expression: E): HavingInterface<DB, TB>;
/**
* Just like {@link WhereInterface.whereRef | whereRef} but adds a `having` statement
* instead of a `where` statement.
*/
havingRef<LRE extends ReferenceExpression<DB, TB>, RRE extends ReferenceExpression<DB, TB>>(lhs: LRE, op: ComparisonOperatorExpression, rhs: RRE): HavingInterface<DB, TB>;
}

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,46 @@
/**
* The result of an insert query.
*
* If the table has an auto incrementing primary key {@link insertId} will hold
* the generated id on dialects that support it. For example PostgreSQL doesn't
* return the id by default and {@link insertId} is undefined. On PostgreSQL you
* need to use {@link ReturningInterface.returning} or {@link ReturningInterface.returningAll}
* to get out the inserted id.
*
* {@link numInsertedOrUpdatedRows} holds the number of (actually) inserted rows.
* On MySQL, updated rows are counted twice when using `on duplicate key update`.
*
* ### Examples
*
* ```ts
* import type { NewPerson } from 'type-editor' // imaginary module
*
* async function insertPerson(person: NewPerson) {
* const result = await db
* .insertInto('person')
* .values(person)
* .executeTakeFirstOrThrow()
*
* console.log(result.insertId) // relevant on MySQL
* console.log(result.numInsertedOrUpdatedRows) // always relevant
* }
* ```
*/
export declare class InsertResult {
/**
* The auto incrementing primary key of the inserted row.
*
* This property can be undefined when the query contains an `on conflict`
* clause that makes the query succeed even when nothing gets inserted.
*
* This property is always undefined on dialects like PostgreSQL that
* don't return the inserted id by default. On those dialects you need
* to use the {@link ReturningInterface.returning | returning} method.
*/
readonly insertId: bigint | undefined;
/**
* Affected rows count.
*/
readonly numInsertedOrUpdatedRows: bigint | undefined;
constructor(insertId: bigint | undefined, numInsertedOrUpdatedRows: bigint | undefined);
}

View File

@@ -0,0 +1,53 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.InsertResult = void 0;
/**
* The result of an insert query.
*
* If the table has an auto incrementing primary key {@link insertId} will hold
* the generated id on dialects that support it. For example PostgreSQL doesn't
* return the id by default and {@link insertId} is undefined. On PostgreSQL you
* need to use {@link ReturningInterface.returning} or {@link ReturningInterface.returningAll}
* to get out the inserted id.
*
* {@link numInsertedOrUpdatedRows} holds the number of (actually) inserted rows.
* On MySQL, updated rows are counted twice when using `on duplicate key update`.
*
* ### Examples
*
* ```ts
* import type { NewPerson } from 'type-editor' // imaginary module
*
* async function insertPerson(person: NewPerson) {
* const result = await db
* .insertInto('person')
* .values(person)
* .executeTakeFirstOrThrow()
*
* console.log(result.insertId) // relevant on MySQL
* console.log(result.numInsertedOrUpdatedRows) // always relevant
* }
* ```
*/
class InsertResult {
/**
* The auto incrementing primary key of the inserted row.
*
* This property can be undefined when the query contains an `on conflict`
* clause that makes the query succeed even when nothing gets inserted.
*
* This property is always undefined on dialects like PostgreSQL that
* don't return the inserted id by default. On those dialects you need
* to use the {@link ReturningInterface.returning | returning} method.
*/
insertId;
/**
* Affected rows count.
*/
numInsertedOrUpdatedRows;
constructor(insertId, numInsertedOrUpdatedRows) {
this.insertId = insertId;
this.numInsertedOrUpdatedRows = numInsertedOrUpdatedRows;
}
}
exports.InsertResult = InsertResult;

View File

@@ -0,0 +1,38 @@
import { JoinNode } from '../operation-node/join-node.js';
import type { OperationNodeSource } from '../operation-node/operation-node-source.js';
import { type ComparisonOperatorExpression, type OperandValueExpressionOrList } from '../parser/binary-operation-parser.js';
import type { ExpressionOrFactory } from '../parser/expression-parser.js';
import type { ReferenceExpression } from '../parser/reference-parser.js';
import type { SqlBool } from '../util/type-utils.js';
export declare class JoinBuilder<DB, TB extends keyof DB> implements OperationNodeSource {
#private;
constructor(props: JoinBuilderProps);
/**
* Just like {@link WhereInterface.where} but adds an item to the join's
* `on` clause instead.
*
* See {@link WhereInterface.where} for documentation and examples.
*/
on<RE extends ReferenceExpression<DB, TB>>(lhs: RE, op: ComparisonOperatorExpression, rhs: OperandValueExpressionOrList<DB, TB, RE>): JoinBuilder<DB, TB>;
on(expression: ExpressionOrFactory<DB, TB, SqlBool>): JoinBuilder<DB, TB>;
/**
* Just like {@link WhereInterface.whereRef} but adds an item to the join's
* `on` clause instead.
*
* See {@link WhereInterface.whereRef} for documentation and examples.
*/
onRef(lhs: ReferenceExpression<DB, TB>, op: ComparisonOperatorExpression, rhs: ReferenceExpression<DB, TB>): JoinBuilder<DB, TB>;
/**
* Adds `on true`.
*/
onTrue(): JoinBuilder<DB, TB>;
/**
* Simply calls the provided function passing `this` as the only argument. `$call` returns
* what the provided function returns.
*/
$call<T>(func: (qb: this) => T): T;
toOperationNode(): JoinNode;
}
export interface JoinBuilderProps {
readonly joinNode: JoinNode;
}

View File

@@ -0,0 +1,51 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.JoinBuilder = void 0;
const join_node_js_1 = require("../operation-node/join-node.js");
const raw_node_js_1 = require("../operation-node/raw-node.js");
const binary_operation_parser_js_1 = require("../parser/binary-operation-parser.js");
const object_utils_js_1 = require("../util/object-utils.js");
class JoinBuilder {
#props;
constructor(props) {
this.#props = (0, object_utils_js_1.freeze)(props);
}
on(...args) {
return new JoinBuilder({
...this.#props,
joinNode: join_node_js_1.JoinNode.cloneWithOn(this.#props.joinNode, (0, binary_operation_parser_js_1.parseValueBinaryOperationOrExpression)(args)),
});
}
/**
* Just like {@link WhereInterface.whereRef} but adds an item to the join's
* `on` clause instead.
*
* See {@link WhereInterface.whereRef} for documentation and examples.
*/
onRef(lhs, op, rhs) {
return new JoinBuilder({
...this.#props,
joinNode: join_node_js_1.JoinNode.cloneWithOn(this.#props.joinNode, (0, binary_operation_parser_js_1.parseReferentialBinaryOperation)(lhs, op, rhs)),
});
}
/**
* Adds `on true`.
*/
onTrue() {
return new JoinBuilder({
...this.#props,
joinNode: join_node_js_1.JoinNode.cloneWithOn(this.#props.joinNode, raw_node_js_1.RawNode.createWithSql('true')),
});
}
/**
* Simply calls the provided function passing `this` as the only argument. `$call` returns
* what the provided function returns.
*/
$call(func) {
return func(this);
}
toOperationNode() {
return this.#props.joinNode;
}
}
exports.JoinBuilder = JoinBuilder;

View File

@@ -0,0 +1,294 @@
import type { AliasableExpression, AliasedExpression, Expression } from '../expression/expression.js';
import { AliasNode } from '../operation-node/alias-node.js';
import { JSONPathNode } from '../operation-node/json-path-node.js';
import { JSONReferenceNode } from '../operation-node/json-reference-node.js';
import type { OperationNode } from '../operation-node/operation-node.js';
export declare class JSONPathBuilder<S, O = S> {
#private;
constructor(node: JSONReferenceNode | JSONPathNode);
/**
* Access an element of a JSON array in a specific location.
*
* Since there's no guarantee an element exists in the given array location, the
* resulting type is always nullable. If you're sure the element exists, you
* should use {@link SelectQueryBuilder.$assertType} to narrow the type safely.
*
* See also {@link key} to access properties of JSON objects.
*
* ### Examples
*
* ```ts
* await db.selectFrom('person')
* .select(eb =>
* eb.ref('nicknames', '->').at(0).as('primary_nickname')
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "nicknames"->0 as "primary_nickname" from "person"
*```
*
* Combined with {@link key}:
*
* ```ts
* db.selectFrom('person').select(eb =>
* eb.ref('experience', '->').at(0).key('role').as('first_role')
* )
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "experience"->0->'role' as "first_role" from "person"
* ```
*
* You can use `'last'` to access the last element of the array in MySQL:
*
* ```ts
* db.selectFrom('person').select(eb =>
* eb.ref('nicknames', '->$').at('last').as('last_nickname')
* )
* ```
*
* The generated SQL (MySQL):
*
* ```sql
* select `nicknames`->'$[last]' as `last_nickname` from `person`
* ```
*
* Or `'#-1'` in SQLite:
*
* ```ts
* db.selectFrom('person').select(eb =>
* eb.ref('nicknames', '->>$').at('#-1').as('last_nickname')
* )
* ```
*
* The generated SQL (SQLite):
*
* ```sql
* select "nicknames"->>'$[#-1]' as `last_nickname` from `person`
* ```
*/
at<I extends any[] extends O ? number | 'last' | `#-${number}` : never, O2 = null | NonNullable<NonNullable<O>[keyof NonNullable<O> & number]>>(index: `${I}` extends `${any}.${any}` | `#--${any}` ? never : I): TraversedJSONPathBuilder<S, O2>;
/**
* Access a property of a JSON object.
*
* If a field is optional, the resulting type will be nullable.
*
* See also {@link at} to access elements of JSON arrays.
*
* ### Examples
*
* ```ts
* db.selectFrom('person').select(eb =>
* eb.ref('address', '->').key('city').as('city')
* )
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "address"->'city' as "city" from "person"
* ```
*
* Going deeper:
*
* ```ts
* db.selectFrom('person').select(eb =>
* eb.ref('profile', '->$').key('website').key('url').as('website_url')
* )
* ```
*
* The generated SQL (MySQL):
*
* ```sql
* select `profile`->'$.website.url' as `website_url` from `person`
* ```
*
* Combined with {@link at}:
*
* ```ts
* db.selectFrom('person').select(eb =>
* eb.ref('profile', '->').key('addresses').at(0).key('city').as('city')
* )
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "profile"->'addresses'->0->'city' as "city" from "person"
* ```
*/
key<K extends any[] extends O ? never : O extends object ? keyof NonNullable<O> & string : never, O2 = undefined extends O ? null | NonNullable<NonNullable<O>[K]> : null extends O ? null | NonNullable<NonNullable<O>[K]> : string extends keyof NonNullable<O> ? null | NonNullable<NonNullable<O>[K]> : NonNullable<O>[K]>(key: K): TraversedJSONPathBuilder<S, O2>;
}
export declare class TraversedJSONPathBuilder<S, O> extends JSONPathBuilder<S, O> implements AliasableExpression<O> {
#private;
constructor(node: JSONReferenceNode | JSONPathNode);
/** @private */
/**
* All expressions need to have this getter for complicated type-related reasons.
* Simply add this getter for your expression and always return `undefined` from it:
*
* ### Examples
*
* ```ts
* import { type Expression, type OperationNode, sql } from 'kysely'
*
* class SomeExpression<T> implements Expression<T> {
* get expressionType(): T | undefined {
* return undefined
* }
*
* toOperationNode(): OperationNode {
* return sql`some sql here`.toOperationNode()
* }
* }
* ```
*
* The getter is needed to make the expression assignable to another expression only
* if the types `T` are assignable. Without this property (or some other property
* that references `T`), you could assing `Expression<string>` to `Expression<number>`.
*/
get expressionType(): O | undefined;
/**
* Returns an aliased version of the expression.
*
* In addition to slapping `as "the_alias"` to the end of the SQL,
* this method also provides strict typing:
*
* ```ts
* const result = await db
* .selectFrom('person')
* .select(eb =>
* eb('first_name', '=', 'Jennifer').as('is_jennifer')
* )
* .executeTakeFirstOrThrow()
*
* // `is_jennifer: SqlBool` field exists in the result type.
* console.log(result.is_jennifer)
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "first_name" = $1 as "is_jennifer"
* from "person"
* ```
*/
as<A extends string>(alias: A): AliasedExpression<O, A>;
/**
* Returns an aliased version of the expression.
*
* ### Examples
*
* In addition to slapping `as "the_alias"` at the end of the expression,
* this method also provides strict typing:
*
* ```ts
* const result = await db
* .selectFrom('person')
* .select((eb) =>
* // `eb.fn<string>` returns an AliasableExpression<string>
* eb.fn<string>('concat', ['first_name', eb.val(' '), 'last_name']).as('full_name')
* )
* .executeTakeFirstOrThrow()
*
* // `full_name: string` field exists in the result type.
* console.log(result.full_name)
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select
* concat("first_name", $1, "last_name") as "full_name"
* from
* "person"
* ```
*
* You can also pass in a raw SQL snippet (or any expression) but in that case you must
* provide the alias as the only type argument:
*
* ```ts
* import { sql } from 'kysely'
*
* const values = sql<{ a: number, b: string }>`(values (1, 'foo'))`
*
* // The alias is `t(a, b)` which specifies the column names
* // in addition to the table name. We must tell kysely that
* // columns of the table can be referenced through `t`
* // by providing an explicit type argument.
* const aliasedValues = values.as<'t'>(sql`t(a, b)`)
*
* await db
* .insertInto('person')
* .columns(['first_name', 'last_name'])
* .expression(
* db.selectFrom(aliasedValues).select(['t.a', 't.b'])
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* insert into "person" ("first_name", "last_name")
* from (values (1, 'foo')) as t(a, b)
* select "t"."a", "t"."b"
* ```
*/
as<A extends string>(alias: Expression<unknown>): AliasedExpression<O, A>;
/**
* Change the output type of the json path.
*
* This method call doesn't change the SQL in any way. This methods simply
* returns a copy of this `JSONPathBuilder` with a new output type.
*/
$castTo<O2>(): TraversedJSONPathBuilder<S, O2>;
$notNull(): TraversedJSONPathBuilder<S, Exclude<O, null>>;
/**
* Creates the OperationNode that describes how to compile this expression into SQL.
*
* ### Examples
*
* If you are creating a custom expression, it's often easiest to use the {@link sql}
* template tag to build the node:
*
* ```ts
* import { type Expression, type OperationNode, sql } from 'kysely'
*
* class SomeExpression<T> implements Expression<T> {
* get expressionType(): T | undefined {
* return undefined
* }
*
* toOperationNode(): OperationNode {
* return sql`some sql here`.toOperationNode()
* }
* }
* ```
*/
toOperationNode(): OperationNode;
}
export declare class AliasedJSONPathBuilder<O, A extends string> implements AliasedExpression<O, A> {
#private;
constructor(jsonPath: TraversedJSONPathBuilder<any, O>, alias: A | Expression<unknown>);
/** @private */
/**
* Returns the aliased expression.
*/
get expression(): Expression<O>;
/** @private */
/**
* Returns the alias.
*/
get alias(): A | Expression<unknown>;
/**
* Creates the OperationNode that describes how to compile this expression into SQL.
*/
toOperationNode(): AliasNode;
}

View File

@@ -0,0 +1,200 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AliasedJSONPathBuilder = exports.TraversedJSONPathBuilder = exports.JSONPathBuilder = void 0;
const alias_node_js_1 = require("../operation-node/alias-node.js");
const identifier_node_js_1 = require("../operation-node/identifier-node.js");
const json_operator_chain_node_js_1 = require("../operation-node/json-operator-chain-node.js");
const json_path_leg_node_js_1 = require("../operation-node/json-path-leg-node.js");
const json_path_node_js_1 = require("../operation-node/json-path-node.js");
const json_reference_node_js_1 = require("../operation-node/json-reference-node.js");
const operation_node_source_js_1 = require("../operation-node/operation-node-source.js");
const value_node_js_1 = require("../operation-node/value-node.js");
class JSONPathBuilder {
#node;
constructor(node) {
this.#node = node;
}
/**
* Access an element of a JSON array in a specific location.
*
* Since there's no guarantee an element exists in the given array location, the
* resulting type is always nullable. If you're sure the element exists, you
* should use {@link SelectQueryBuilder.$assertType} to narrow the type safely.
*
* See also {@link key} to access properties of JSON objects.
*
* ### Examples
*
* ```ts
* await db.selectFrom('person')
* .select(eb =>
* eb.ref('nicknames', '->').at(0).as('primary_nickname')
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "nicknames"->0 as "primary_nickname" from "person"
*```
*
* Combined with {@link key}:
*
* ```ts
* db.selectFrom('person').select(eb =>
* eb.ref('experience', '->').at(0).key('role').as('first_role')
* )
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "experience"->0->'role' as "first_role" from "person"
* ```
*
* You can use `'last'` to access the last element of the array in MySQL:
*
* ```ts
* db.selectFrom('person').select(eb =>
* eb.ref('nicknames', '->$').at('last').as('last_nickname')
* )
* ```
*
* The generated SQL (MySQL):
*
* ```sql
* select `nicknames`->'$[last]' as `last_nickname` from `person`
* ```
*
* Or `'#-1'` in SQLite:
*
* ```ts
* db.selectFrom('person').select(eb =>
* eb.ref('nicknames', '->>$').at('#-1').as('last_nickname')
* )
* ```
*
* The generated SQL (SQLite):
*
* ```sql
* select "nicknames"->>'$[#-1]' as `last_nickname` from `person`
* ```
*/
at(index) {
return this.#createBuilderWithPathLeg('ArrayLocation', index);
}
/**
* Access a property of a JSON object.
*
* If a field is optional, the resulting type will be nullable.
*
* See also {@link at} to access elements of JSON arrays.
*
* ### Examples
*
* ```ts
* db.selectFrom('person').select(eb =>
* eb.ref('address', '->').key('city').as('city')
* )
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "address"->'city' as "city" from "person"
* ```
*
* Going deeper:
*
* ```ts
* db.selectFrom('person').select(eb =>
* eb.ref('profile', '->$').key('website').key('url').as('website_url')
* )
* ```
*
* The generated SQL (MySQL):
*
* ```sql
* select `profile`->'$.website.url' as `website_url` from `person`
* ```
*
* Combined with {@link at}:
*
* ```ts
* db.selectFrom('person').select(eb =>
* eb.ref('profile', '->').key('addresses').at(0).key('city').as('city')
* )
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "profile"->'addresses'->0->'city' as "city" from "person"
* ```
*/
key(key) {
return this.#createBuilderWithPathLeg('Member', key);
}
#createBuilderWithPathLeg(legType, value) {
if (json_reference_node_js_1.JSONReferenceNode.is(this.#node)) {
return new TraversedJSONPathBuilder(json_reference_node_js_1.JSONReferenceNode.cloneWithTraversal(this.#node, json_path_node_js_1.JSONPathNode.is(this.#node.traversal)
? json_path_node_js_1.JSONPathNode.cloneWithLeg(this.#node.traversal, json_path_leg_node_js_1.JSONPathLegNode.create(legType, value))
: json_operator_chain_node_js_1.JSONOperatorChainNode.cloneWithValue(this.#node.traversal, value_node_js_1.ValueNode.createImmediate(value))));
}
return new TraversedJSONPathBuilder(json_path_node_js_1.JSONPathNode.cloneWithLeg(this.#node, json_path_leg_node_js_1.JSONPathLegNode.create(legType, value)));
}
}
exports.JSONPathBuilder = JSONPathBuilder;
class TraversedJSONPathBuilder extends JSONPathBuilder {
#node;
constructor(node) {
super(node);
this.#node = node;
}
/** @private */
get expressionType() {
return undefined;
}
as(alias) {
return new AliasedJSONPathBuilder(this, alias);
}
/**
* Change the output type of the json path.
*
* This method call doesn't change the SQL in any way. This methods simply
* returns a copy of this `JSONPathBuilder` with a new output type.
*/
$castTo() {
return new TraversedJSONPathBuilder(this.#node);
}
$notNull() {
return new TraversedJSONPathBuilder(this.#node);
}
toOperationNode() {
return this.#node;
}
}
exports.TraversedJSONPathBuilder = TraversedJSONPathBuilder;
class AliasedJSONPathBuilder {
#jsonPath;
#alias;
constructor(jsonPath, alias) {
this.#jsonPath = jsonPath;
this.#alias = alias;
}
/** @private */
get expression() {
return this.#jsonPath;
}
/** @private */
get alias() {
return this.#alias;
}
toOperationNode() {
return alias_node_js_1.AliasNode.create(this.#jsonPath.toOperationNode(), (0, operation_node_source_js_1.isOperationNodeSource)(this.#alias)
? this.#alias.toOperationNode()
: identifier_node_js_1.IdentifierNode.create(this.#alias));
}
}
exports.AliasedJSONPathBuilder = AliasedJSONPathBuilder;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,630 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NotMatchedThenableMergeQueryBuilder = exports.MatchedThenableMergeQueryBuilder = exports.WheneableMergeQueryBuilder = exports.MergeQueryBuilder = void 0;
const insert_query_node_js_1 = require("../operation-node/insert-query-node.js");
const merge_query_node_js_1 = require("../operation-node/merge-query-node.js");
const query_node_js_1 = require("../operation-node/query-node.js");
const update_query_node_js_1 = require("../operation-node/update-query-node.js");
const insert_values_parser_js_1 = require("../parser/insert-values-parser.js");
const join_parser_js_1 = require("../parser/join-parser.js");
const merge_parser_js_1 = require("../parser/merge-parser.js");
const select_parser_js_1 = require("../parser/select-parser.js");
const top_parser_js_1 = require("../parser/top-parser.js");
const noop_query_executor_js_1 = require("../query-executor/noop-query-executor.js");
const object_utils_js_1 = require("../util/object-utils.js");
const merge_result_js_1 = require("./merge-result.js");
const no_result_error_js_1 = require("./no-result-error.js");
const update_query_builder_js_1 = require("./update-query-builder.js");
class MergeQueryBuilder {
#props;
constructor(props) {
this.#props = (0, object_utils_js_1.freeze)(props);
}
/**
* This can be used to add any additional SQL to the end of the query.
*
* ### Examples
*
* ```ts
* import { sql } from 'kysely'
*
* await db
* .mergeInto('person')
* .using('pet', 'pet.owner_id', 'person.id')
* .whenMatched()
* .thenDelete()
* .modifyEnd(sql.raw('-- this is a comment'))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched then delete -- this is a comment
* ```
*/
modifyEnd(modifier) {
return new MergeQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithEndModifier(this.#props.queryNode, modifier.toOperationNode()),
});
}
/**
* Changes a `merge into` query to an `merge top into` query.
*
* `top` clause is only supported by some dialects like MS SQL Server.
*
* ### Examples
*
* Affect 5 matched rows at most:
*
* ```ts
* await db.mergeInto('person')
* .top(5)
* .using('pet', 'person.id', 'pet.owner_id')
* .whenMatched()
* .thenDelete()
* .execute()
* ```
*
* The generated SQL (MS SQL Server):
*
* ```sql
* merge top(5) into "person"
* using "pet" on "person"."id" = "pet"."owner_id"
* when matched then
* delete
* ```
*
* Affect 50% of matched rows:
*
* ```ts
* await db.mergeInto('person')
* .top(50, 'percent')
* .using('pet', 'person.id', 'pet.owner_id')
* .whenMatched()
* .thenDelete()
* .execute()
* ```
*
* The generated SQL (MS SQL Server):
*
* ```sql
* merge top(50) percent into "person"
* using "pet" on "person"."id" = "pet"."owner_id"
* when matched then
* delete
* ```
*/
top(expression, modifiers) {
return new MergeQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithTop(this.#props.queryNode, (0, top_parser_js_1.parseTop)(expression, modifiers)),
});
}
using(...args) {
return new WheneableMergeQueryBuilder({
...this.#props,
queryNode: merge_query_node_js_1.MergeQueryNode.cloneWithUsing(this.#props.queryNode, (0, join_parser_js_1.parseJoin)('Using', args)),
});
}
returning(args) {
return new MergeQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithReturning(this.#props.queryNode, (0, select_parser_js_1.parseSelectArg)(args)),
});
}
returningAll(table) {
return new MergeQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithReturning(this.#props.queryNode, (0, select_parser_js_1.parseSelectAll)(table)),
});
}
output(args) {
return new MergeQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithOutput(this.#props.queryNode, (0, select_parser_js_1.parseSelectArg)(args)),
});
}
outputAll(table) {
return new MergeQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithOutput(this.#props.queryNode, (0, select_parser_js_1.parseSelectAll)(table)),
});
}
}
exports.MergeQueryBuilder = MergeQueryBuilder;
class WheneableMergeQueryBuilder {
#props;
constructor(props) {
this.#props = (0, object_utils_js_1.freeze)(props);
}
/**
* This can be used to add any additional SQL to the end of the query.
*
* ### Examples
*
* ```ts
* import { sql } from 'kysely'
*
* await db
* .mergeInto('person')
* .using('pet', 'pet.owner_id', 'person.id')
* .whenMatched()
* .thenDelete()
* .modifyEnd(sql.raw('-- this is a comment'))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched then delete -- this is a comment
* ```
*/
modifyEnd(modifier) {
return new WheneableMergeQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithEndModifier(this.#props.queryNode, modifier.toOperationNode()),
});
}
/**
* See {@link MergeQueryBuilder.top}.
*/
top(expression, modifiers) {
return new WheneableMergeQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithTop(this.#props.queryNode, (0, top_parser_js_1.parseTop)(expression, modifiers)),
});
}
/**
* Adds a simple `when matched` clause to the query.
*
* For a `when matched` clause with an `and` condition, see {@link whenMatchedAnd}.
*
* For a simple `when not matched` clause, see {@link whenNotMatched}.
*
* For a `when not matched` clause with an `and` condition, see {@link whenNotMatchedAnd}.
*
* ### Examples
*
* ```ts
* const result = await db.mergeInto('person')
* .using('pet', 'person.id', 'pet.owner_id')
* .whenMatched()
* .thenDelete()
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* merge into "person"
* using "pet" on "person"."id" = "pet"."owner_id"
* when matched then
* delete
* ```
*/
whenMatched() {
return this.#whenMatched([]);
}
whenMatchedAnd(...args) {
return this.#whenMatched(args);
}
/**
* Adds the `when matched` clause to the query with an `and` condition. But unlike
* {@link whenMatchedAnd}, this method accepts a column reference as the 3rd argument.
*
* This method is similar to {@link SelectQueryBuilder.whereRef}, so see the documentation
* for that method for more examples.
*/
whenMatchedAndRef(lhs, op, rhs) {
return this.#whenMatched([lhs, op, rhs], true);
}
#whenMatched(args, refRight) {
return new MatchedThenableMergeQueryBuilder({
...this.#props,
queryNode: merge_query_node_js_1.MergeQueryNode.cloneWithWhen(this.#props.queryNode, (0, merge_parser_js_1.parseMergeWhen)({ isMatched: true }, args, refRight)),
});
}
/**
* Adds a simple `when not matched` clause to the query.
*
* For a `when not matched` clause with an `and` condition, see {@link whenNotMatchedAnd}.
*
* For a simple `when matched` clause, see {@link whenMatched}.
*
* For a `when matched` clause with an `and` condition, see {@link whenMatchedAnd}.
*
* ### Examples
*
* ```ts
* const result = await db.mergeInto('person')
* .using('pet', 'person.id', 'pet.owner_id')
* .whenNotMatched()
* .thenInsertValues({
* first_name: 'John',
* last_name: 'Doe',
* })
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* merge into "person"
* using "pet" on "person"."id" = "pet"."owner_id"
* when not matched then
* insert ("first_name", "last_name") values ($1, $2)
* ```
*/
whenNotMatched() {
return this.#whenNotMatched([]);
}
whenNotMatchedAnd(...args) {
return this.#whenNotMatched(args);
}
/**
* Adds the `when not matched` clause to the query with an `and` condition. But unlike
* {@link whenNotMatchedAnd}, this method accepts a column reference as the 3rd argument.
*
* Unlike {@link whenMatchedAndRef}, you cannot reference columns from the target table.
*
* This method is similar to {@link SelectQueryBuilder.whereRef}, so see the documentation
* for that method for more examples.
*/
whenNotMatchedAndRef(lhs, op, rhs) {
return this.#whenNotMatched([lhs, op, rhs], true);
}
/**
* Adds a simple `when not matched by source` clause to the query.
*
* Supported in MS SQL Server.
*
* Similar to {@link whenNotMatched}, but returns a {@link MatchedThenableMergeQueryBuilder}.
*/
whenNotMatchedBySource() {
return this.#whenNotMatched([], false, true);
}
whenNotMatchedBySourceAnd(...args) {
return this.#whenNotMatched(args, false, true);
}
/**
* Adds the `when not matched by source` clause to the query with an `and` condition.
*
* Similar to {@link whenNotMatchedAndRef}, but you can reference columns from
* the target table, and not from source table and returns a {@link MatchedThenableMergeQueryBuilder}.
*/
whenNotMatchedBySourceAndRef(lhs, op, rhs) {
return this.#whenNotMatched([lhs, op, rhs], true, true);
}
returning(args) {
return new WheneableMergeQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithReturning(this.#props.queryNode, (0, select_parser_js_1.parseSelectArg)(args)),
});
}
returningAll(table) {
return new WheneableMergeQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithReturning(this.#props.queryNode, (0, select_parser_js_1.parseSelectAll)(table)),
});
}
output(args) {
return new WheneableMergeQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithOutput(this.#props.queryNode, (0, select_parser_js_1.parseSelectArg)(args)),
});
}
outputAll(table) {
return new WheneableMergeQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithOutput(this.#props.queryNode, (0, select_parser_js_1.parseSelectAll)(table)),
});
}
#whenNotMatched(args, refRight = false, bySource = false) {
const props = {
...this.#props,
queryNode: merge_query_node_js_1.MergeQueryNode.cloneWithWhen(this.#props.queryNode, (0, merge_parser_js_1.parseMergeWhen)({ isMatched: false, bySource }, args, refRight)),
};
const Builder = bySource
? MatchedThenableMergeQueryBuilder
: NotMatchedThenableMergeQueryBuilder;
return new Builder(props);
}
/**
* Simply calls the provided function passing `this` as the only argument. `$call` returns
* what the provided function returns.
*
* If you want to conditionally call a method on `this`, see
* the {@link $if} method.
*
* ### Examples
*
* The next example uses a helper function `log` to log a query:
*
* ```ts
* import type { Compilable } from 'kysely'
*
* function log<T extends Compilable>(qb: T): T {
* console.log(qb.compile())
* return qb
* }
*
* await db.updateTable('person')
* .set({ first_name: 'John' })
* .$call(log)
* .execute()
* ```
*/
$call(func) {
return func(this);
}
/**
* Call `func(this)` if `condition` is true.
*
* This method is especially handy with optional selects. Any `returning` or `returningAll`
* method calls add columns as optional fields to the output type when called inside
* the `func` callback. This is because we can't know if those selections were actually
* made before running the code.
*
* You can also call any other methods inside the callback.
*
* ### Examples
*
* ```ts
* import type { PersonUpdate } from 'type-editor' // imaginary module
*
* async function updatePerson(id: number, updates: PersonUpdate, returnLastName: boolean) {
* return await db
* .updateTable('person')
* .set(updates)
* .where('id', '=', id)
* .returning(['id', 'first_name'])
* .$if(returnLastName, (qb) => qb.returning('last_name'))
* .executeTakeFirstOrThrow()
* }
* ```
*
* Any selections added inside the `if` callback will be added as optional fields to the
* output type since we can't know if the selections were actually made before running
* the code. In the example above the return type of the `updatePerson` function is:
*
* ```ts
* Promise<{
* id: number
* first_name: string
* last_name?: string
* }>
* ```
*/
$if(condition, func) {
if (condition) {
return func(this);
}
return new WheneableMergeQueryBuilder({
...this.#props,
});
}
toOperationNode() {
return this.#props.executor.transformQuery(this.#props.queryNode, this.#props.queryId);
}
compile() {
return this.#props.executor.compileQuery(this.toOperationNode(), this.#props.queryId);
}
/**
* Executes the query and returns an array of rows.
*
* Also see the {@link executeTakeFirst} and {@link executeTakeFirstOrThrow} methods.
*/
async execute() {
const compiledQuery = this.compile();
const result = await this.#props.executor.executeQuery(compiledQuery);
const { adapter } = this.#props.executor;
const query = compiledQuery.query;
if ((query.returning && adapter.supportsReturning) ||
(query.output && adapter.supportsOutput)) {
return result.rows;
}
return [new merge_result_js_1.MergeResult(result.numAffectedRows)];
}
/**
* Executes the query and returns the first result or undefined if
* the query returned no result.
*/
async executeTakeFirst() {
const [result] = await this.execute();
return result;
}
/**
* Executes the query and returns the first result or throws if
* the query returned no result.
*
* By default an instance of {@link NoResultError} is thrown, but you can
* provide a custom error class, or callback as the only argument to throw a different
* error.
*/
async executeTakeFirstOrThrow(errorConstructor = no_result_error_js_1.NoResultError) {
const result = await this.executeTakeFirst();
if (result === undefined) {
const error = (0, no_result_error_js_1.isNoResultErrorConstructor)(errorConstructor)
? new errorConstructor(this.toOperationNode())
: errorConstructor(this.toOperationNode());
throw error;
}
return result;
}
}
exports.WheneableMergeQueryBuilder = WheneableMergeQueryBuilder;
class MatchedThenableMergeQueryBuilder {
#props;
constructor(props) {
this.#props = (0, object_utils_js_1.freeze)(props);
}
/**
* Performs the `delete` action.
*
* To perform the `do nothing` action, see {@link thenDoNothing}.
*
* To perform the `update` action, see {@link thenUpdate} or {@link thenUpdateSet}.
*
* ### Examples
*
* ```ts
* const result = await db.mergeInto('person')
* .using('pet', 'person.id', 'pet.owner_id')
* .whenMatched()
* .thenDelete()
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* merge into "person"
* using "pet" on "person"."id" = "pet"."owner_id"
* when matched then
* delete
* ```
*/
thenDelete() {
return new WheneableMergeQueryBuilder({
...this.#props,
queryNode: merge_query_node_js_1.MergeQueryNode.cloneWithThen(this.#props.queryNode, (0, merge_parser_js_1.parseMergeThen)('delete')),
});
}
/**
* Performs the `do nothing` action.
*
* This is supported in PostgreSQL.
*
* To perform the `delete` action, see {@link thenDelete}.
*
* To perform the `update` action, see {@link thenUpdate} or {@link thenUpdateSet}.
*
* ### Examples
*
* ```ts
* const result = await db.mergeInto('person')
* .using('pet', 'person.id', 'pet.owner_id')
* .whenMatched()
* .thenDoNothing()
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* merge into "person"
* using "pet" on "person"."id" = "pet"."owner_id"
* when matched then
* do nothing
* ```
*/
thenDoNothing() {
return new WheneableMergeQueryBuilder({
...this.#props,
queryNode: merge_query_node_js_1.MergeQueryNode.cloneWithThen(this.#props.queryNode, (0, merge_parser_js_1.parseMergeThen)('do nothing')),
});
}
/**
* Perform an `update` operation with a full-fledged {@link UpdateQueryBuilder}.
* This is handy when multiple `set` invocations are needed.
*
* For a shorthand version of this method, see {@link thenUpdateSet}.
*
* To perform the `delete` action, see {@link thenDelete}.
*
* To perform the `do nothing` action, see {@link thenDoNothing}.
*
* ### Examples
*
* ```ts
* import { sql } from 'kysely'
*
* const result = await db.mergeInto('person')
* .using('pet', 'person.id', 'pet.owner_id')
* .whenMatched()
* .thenUpdate((ub) => ub
* .set(sql`metadata['has_pets']`, 'Y')
* .set({
* updated_at: new Date().toISOString(),
* })
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* merge into "person"
* using "pet" on "person"."id" = "pet"."owner_id"
* when matched then
* update set metadata['has_pets'] = $1, "updated_at" = $2
* ```
*/
thenUpdate(set) {
return new WheneableMergeQueryBuilder({
...this.#props,
queryNode: merge_query_node_js_1.MergeQueryNode.cloneWithThen(this.#props.queryNode, (0, merge_parser_js_1.parseMergeThen)(set(new update_query_builder_js_1.UpdateQueryBuilder({
queryId: this.#props.queryId,
executor: noop_query_executor_js_1.NOOP_QUERY_EXECUTOR,
queryNode: update_query_node_js_1.UpdateQueryNode.createWithoutTable(),
})))),
});
}
thenUpdateSet(...args) {
// @ts-ignore not sure how to type this so it won't complain about set(...args).
return this.thenUpdate((ub) => ub.set(...args));
}
}
exports.MatchedThenableMergeQueryBuilder = MatchedThenableMergeQueryBuilder;
class NotMatchedThenableMergeQueryBuilder {
#props;
constructor(props) {
this.#props = (0, object_utils_js_1.freeze)(props);
}
/**
* Performs the `do nothing` action.
*
* This is supported in PostgreSQL.
*
* To perform the `insert` action, see {@link thenInsertValues}.
*
* ### Examples
*
* ```ts
* const result = await db.mergeInto('person')
* .using('pet', 'person.id', 'pet.owner_id')
* .whenNotMatched()
* .thenDoNothing()
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* merge into "person"
* using "pet" on "person"."id" = "pet"."owner_id"
* when not matched then
* do nothing
* ```
*/
thenDoNothing() {
return new WheneableMergeQueryBuilder({
...this.#props,
queryNode: merge_query_node_js_1.MergeQueryNode.cloneWithThen(this.#props.queryNode, (0, merge_parser_js_1.parseMergeThen)('do nothing')),
});
}
thenInsertValues(insert) {
const [columns, values] = (0, insert_values_parser_js_1.parseInsertExpression)(insert);
return new WheneableMergeQueryBuilder({
...this.#props,
queryNode: merge_query_node_js_1.MergeQueryNode.cloneWithThen(this.#props.queryNode, (0, merge_parser_js_1.parseMergeThen)(insert_query_node_js_1.InsertQueryNode.cloneWith(insert_query_node_js_1.InsertQueryNode.createWithoutInto(), {
columns,
values,
}))),
});
}
}
exports.NotMatchedThenableMergeQueryBuilder = NotMatchedThenableMergeQueryBuilder;

View File

@@ -0,0 +1,4 @@
export declare class MergeResult {
readonly numChangedRows: bigint | undefined;
constructor(numChangedRows: bigint | undefined);
}

View File

@@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MergeResult = void 0;
class MergeResult {
numChangedRows;
constructor(numChangedRows) {
this.numChangedRows = numChangedRows;
}
}
exports.MergeResult = MergeResult;

View File

@@ -0,0 +1,10 @@
import type { QueryNode } from '../operation-node/query-node.js';
export type NoResultErrorConstructor = new (node: QueryNode) => Error;
export declare class NoResultError extends Error {
/**
* The operation node tree of the query that was executed.
*/
readonly node: QueryNode;
constructor(node: QueryNode);
}
export declare function isNoResultErrorConstructor(fn: NoResultErrorConstructor | ((node: QueryNode) => Error)): fn is NoResultErrorConstructor;

View File

@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NoResultError = void 0;
exports.isNoResultErrorConstructor = isNoResultErrorConstructor;
class NoResultError extends Error {
/**
* The operation node tree of the query that was executed.
*/
node;
constructor(node) {
super('no result');
this.node = node;
}
}
exports.NoResultError = NoResultError;
function isNoResultErrorConstructor(fn) {
return Object.prototype.hasOwnProperty.call(fn, 'prototype');
}

View File

@@ -0,0 +1,872 @@
import type { Expression } from '../expression/expression.js';
import { OnConflictNode } from '../operation-node/on-conflict-node.js';
import type { OperationNodeSource } from '../operation-node/operation-node-source.js';
import { type ComparisonOperatorExpression, type OperandValueExpressionOrList } from '../parser/binary-operation-parser.js';
import type { ExpressionOrFactory } from '../parser/expression-parser.js';
import type { ReferenceExpression } from '../parser/reference-parser.js';
import { type UpdateObjectExpression } from '../parser/update-set-parser.js';
import type { Updateable } from '../util/column-type.js';
import type { AnyColumn, SqlBool } from '../util/type-utils.js';
import type { WhereInterface } from './where-interface.js';
export declare class OnConflictBuilder<DB, TB extends keyof DB> implements WhereInterface<DB, TB> {
#private;
constructor(props: OnConflictBuilderProps);
/**
* Specify a single column as the conflict target.
*
* Also see the {@link columns}, {@link constraint} and {@link expression}
* methods for alternative ways to specify the conflict target.
*/
column(column: AnyColumn<DB, TB>): OnConflictBuilder<DB, TB>;
/**
* Specify a list of columns as the conflict target.
*
* Also see the {@link column}, {@link constraint} and {@link expression}
* methods for alternative ways to specify the conflict target.
*/
columns(columns: ReadonlyArray<AnyColumn<DB, TB>>): OnConflictBuilder<DB, TB>;
/**
* Specify a specific constraint by name as the conflict target.
*
* Also see the {@link column}, {@link columns} and {@link expression}
* methods for alternative ways to specify the conflict target.
*/
constraint(constraintName: string): OnConflictBuilder<DB, TB>;
/**
* Specify an expression as the conflict target.
*
* This can be used if the unique index is an expression index.
*
* Also see the {@link column}, {@link columns} and {@link constraint}
* methods for alternative ways to specify the conflict target.
*/
expression(expression: Expression<any>): OnConflictBuilder<DB, TB>;
/**
* Adds a `where` expression to the query.
*
* Calling this method multiple times will combine the expressions using `and`.
*
* Also see {@link whereRef}
*
* ### Examples
*
* <!-- siteExample("where", "Simple where clause", 10) -->
*
* `where` method calls are combined with `AND`:
*
* ```ts
* const person = await db
* .selectFrom('person')
* .selectAll()
* .where('first_name', '=', 'Jennifer')
* .where('age', '>', 40)
* .executeTakeFirst()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select * from "person" where "first_name" = $1 and "age" > $2
* ```
*
* Operator can be any supported operator or if the typings don't support it
* you can always use:
*
* ```ts
* import { sql } from 'kysely'
*
* sql`your operator`
* ```
*
* <!-- siteExample("where", "Where in", 20) -->
*
* Find multiple items using a list of identifiers:
*
* ```ts
* const persons = await db
* .selectFrom('person')
* .selectAll()
* .where('id', 'in', [1, 2, 3])
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select * from "person" where "id" in ($1, $2, $3)
* ```
*
* <!-- siteExample("where", "Object filter", 30) -->
*
* You can use the `and` function to create a simple equality
* filter using an object
*
* ```ts
* const persons = await db
* .selectFrom('person')
* .selectAll()
* .where((eb) => eb.and({
* first_name: 'Jennifer',
* last_name: eb.ref('first_name')
* }))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select *
* from "person"
* where (
* "first_name" = $1
* and "last_name" = "first_name"
* )
* ```
*
* <!-- siteExample("where", "OR where", 40) -->
*
* To combine conditions using `OR`, you can use the expression builder.
* There are two ways to create `OR` expressions. Both are shown in this
* example:
*
* ```ts
* const persons = await db
* .selectFrom('person')
* .selectAll()
* // 1. Using the `or` method on the expression builder:
* .where((eb) => eb.or([
* eb('first_name', '=', 'Jennifer'),
* eb('first_name', '=', 'Sylvester')
* ]))
* // 2. Chaining expressions using the `or` method on the
* // created expressions:
* .where((eb) =>
* eb('last_name', '=', 'Aniston').or('last_name', '=', 'Stallone')
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select *
* from "person"
* where (
* ("first_name" = $1 or "first_name" = $2)
* and
* ("last_name" = $3 or "last_name" = $4)
* )
* ```
*
* <!-- siteExample("where", "Conditional where calls", 50) -->
*
* You can add expressions conditionally like this:
*
* ```ts
* import { Expression, SqlBool } from 'kysely'
*
* const firstName: string | undefined = 'Jennifer'
* const lastName: string | undefined = 'Aniston'
* const under18 = true
* const over60 = true
*
* let query = db
* .selectFrom('person')
* .selectAll()
*
* if (firstName) {
* // The query builder is immutable. Remember to reassign
* // the result back to the query variable.
* query = query.where('first_name', '=', firstName)
* }
*
* if (lastName) {
* query = query.where('last_name', '=', lastName)
* }
*
* if (under18 || over60) {
* // Conditional OR expressions can be added like this.
* query = query.where((eb) => {
* const ors: Expression<SqlBool>[] = []
*
* if (under18) {
* ors.push(eb('age', '<', 18))
* }
*
* if (over60) {
* ors.push(eb('age', '>', 60))
* }
*
* return eb.or(ors)
* })
* }
*
* const persons = await query.execute()
* ```
*
* Both the first and third argument can also be arbitrary expressions like
* subqueries. An expression can defined by passing a function and calling
* the methods of the {@link ExpressionBuilder} passed to the callback:
*
* ```ts
* const persons = await db
* .selectFrom('person')
* .selectAll()
* .where(
* (qb) => qb.selectFrom('pet')
* .select('pet.name')
* .whereRef('pet.owner_id', '=', 'person.id')
* .limit(1),
* '=',
* 'Fluffy'
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select *
* from "person"
* where (
* select "pet"."name"
* from "pet"
* where "pet"."owner_id" = "person"."id"
* limit $1
* ) = $2
* ```
*
* A `where in` query can be built by using the `in` operator and an array
* of values. The values in the array can also be expressions:
*
* ```ts
* const persons = await db
* .selectFrom('person')
* .selectAll()
* .where('person.id', 'in', [100, 200, 300])
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select * from "person" where "id" in ($1, $2, $3)
* ```
*
* <!-- siteExample("where", "Complex where clause", 60) -->
*
* For complex `where` expressions you can pass in a single callback and
* use the `ExpressionBuilder` to build your expression:
*
* ```ts
* const firstName = 'Jennifer'
* const maxAge = 60
*
* const persons = await db
* .selectFrom('person')
* .selectAll('person')
* .where(({ eb, or, and, not, exists, selectFrom }) => and([
* or([
* eb('first_name', '=', firstName),
* eb('age', '<', maxAge)
* ]),
* not(exists(
* selectFrom('pet')
* .select('pet.id')
* .whereRef('pet.owner_id', '=', 'person.id')
* ))
* ]))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "person".*
* from "person"
* where (
* (
* "first_name" = $1
* or "age" < $2
* )
* and not exists (
* select "pet"."id" from "pet" where "pet"."owner_id" = "person"."id"
* )
* )
* ```
*
* If everything else fails, you can always use the {@link sql} tag
* as any of the arguments, including the operator:
*
* ```ts
* import { sql } from 'kysely'
*
* const persons = await db
* .selectFrom('person')
* .selectAll()
* .where(
* sql<string>`coalesce(first_name, last_name)`,
* 'like',
* '%' + name + '%',
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select * from "person"
* where coalesce(first_name, last_name) like $1
* ```
*
* In all examples above the columns were known at compile time
* (except for the raw {@link sql} expressions). By default kysely only
* allows you to refer to columns that exist in the database **and**
* can be referred to in the current query and context.
*
* Sometimes you may want to refer to columns that come from the user
* input and thus are not available at compile time.
*
* You have two options, the {@link sql} tag or `db.dynamic`. The example below
* uses both:
*
* ```ts
* import { sql } from 'kysely'
* const { ref } = db.dynamic
*
* const columnFromUserInput: string = 'id'
*
* const persons = await db
* .selectFrom('person')
* .selectAll()
* .where(ref(columnFromUserInput), '=', 1)
* .where(sql.id(columnFromUserInput), '=', 2)
* .execute()
* ```
*/
where<RE extends ReferenceExpression<DB, TB>, VE extends OperandValueExpressionOrList<DB, TB, RE>>(lhs: RE, op: ComparisonOperatorExpression, rhs: VE): OnConflictBuilder<DB, TB>;
where<E extends ExpressionOrFactory<DB, TB, SqlBool>>(expression: E): OnConflictBuilder<DB, TB>;
/**
* Adds a `where` clause where both sides of the operator are references
* to columns.
*
* The normal `where` method treats the right hand side argument as a
* value by default. `whereRef` treats it as a column reference. This method is
* expecially useful with joins and correlated subqueries.
*
* ### Examples
*
* Usage with a join:
*
* ```ts
* db.selectFrom(['person', 'pet'])
* .selectAll()
* .whereRef('person.first_name', '=', 'pet.name')
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select * from "person", "pet" where "person"."first_name" = "pet"."name"
* ```
*
* Usage in a subquery:
*
* ```ts
* const persons = await db
* .selectFrom('person')
* .selectAll('person')
* .select((eb) => eb
* .selectFrom('pet')
* .select('name')
* .whereRef('pet.owner_id', '=', 'person.id')
* .limit(1)
* .as('pet_name')
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "person".*, (
* select "name"
* from "pet"
* where "pet"."owner_id" = "person"."id"
* limit $1
* ) as "pet_name"
* from "person"
*/
whereRef<LRE extends ReferenceExpression<DB, TB>, RRE extends ReferenceExpression<DB, TB>>(lhs: LRE, op: ComparisonOperatorExpression, rhs: RRE): OnConflictBuilder<DB, TB>;
/**
* Clears all where expressions from the query.
*
* ### Examples
*
* ```ts
* db.selectFrom('person')
* .selectAll()
* .where('id','=',42)
* .clearWhere()
* ```
*
* The generated SQL(PostgreSQL):
*
* ```sql
* select * from "person"
* ```
*/
clearWhere(): OnConflictBuilder<DB, TB>;
/**
* Adds the "do nothing" conflict action.
*
* ### Examples
*
* ```ts
* const id = 1
* const first_name = 'John'
*
* await db
* .insertInto('person')
* .values({ first_name, id })
* .onConflict((oc) => oc
* .column('id')
* .doNothing()
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* insert into "person" ("first_name", "id")
* values ($1, $2)
* on conflict ("id") do nothing
* ```
*/
doNothing(): OnConflictDoNothingBuilder<DB, TB>;
/**
* Adds the "do update set" conflict action.
*
* ### Examples
*
* ```ts
* const id = 1
* const first_name = 'John'
*
* await db
* .insertInto('person')
* .values({ first_name, id })
* .onConflict((oc) => oc
* .column('id')
* .doUpdateSet({ first_name })
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* insert into "person" ("first_name", "id")
* values ($1, $2)
* on conflict ("id")
* do update set "first_name" = $3
* ```
*
* In the next example we use the `ref` method to reference
* columns of the virtual table `excluded` in a type-safe way
* to create an upsert operation:
*
* ```ts
* import type { NewPerson } from 'type-editor' // imaginary module
*
* async function upsertPerson(person: NewPerson): Promise<void> {
* await db.insertInto('person')
* .values(person)
* .onConflict((oc) => oc
* .column('id')
* .doUpdateSet((eb) => ({
* first_name: eb.ref('excluded.first_name'),
* last_name: eb.ref('excluded.last_name')
* })
* )
* )
* .execute()
* }
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* insert into "person" ("first_name", "last_name")
* values ($1, $2)
* on conflict ("id")
* do update set
* "first_name" = excluded."first_name",
* "last_name" = excluded."last_name"
* ```
*/
doUpdateSet(update: UpdateObjectExpression<OnConflictDatabase<DB, TB>, OnConflictTables<TB>, OnConflictTables<TB>>): OnConflictUpdateBuilder<OnConflictDatabase<DB, TB>, OnConflictTables<TB>>;
/**
* Simply calls the provided function passing `this` as the only argument. `$call` returns
* what the provided function returns.
*/
$call<T>(func: (qb: this) => T): T;
}
export interface OnConflictBuilderProps {
readonly onConflictNode: OnConflictNode;
}
export type OnConflictDatabase<DB, TB extends keyof DB> = {
[K in keyof DB | 'excluded']: Updateable<K extends keyof DB ? DB[K] : DB[TB]>;
};
export type OnConflictTables<TB> = TB | 'excluded';
export declare class OnConflictDoNothingBuilder<DB, TB extends keyof DB> implements OperationNodeSource {
#private;
constructor(props: OnConflictBuilderProps);
toOperationNode(): OnConflictNode;
}
export declare class OnConflictUpdateBuilder<DB, TB extends keyof DB> implements WhereInterface<DB, TB>, OperationNodeSource {
#private;
constructor(props: OnConflictBuilderProps);
/**
* Specify a where condition for the update operation.
*
* See {@link WhereInterface.where} for more info.
*/
where<RE extends ReferenceExpression<DB, TB>, VE extends OperandValueExpressionOrList<DB, TB, RE>>(lhs: RE, op: ComparisonOperatorExpression, rhs: VE): OnConflictUpdateBuilder<DB, TB>;
/**
* Adds a `where` expression to the query.
*
* Calling this method multiple times will combine the expressions using `and`.
*
* Also see {@link whereRef}
*
* ### Examples
*
* <!-- siteExample("where", "Simple where clause", 10) -->
*
* `where` method calls are combined with `AND`:
*
* ```ts
* const person = await db
* .selectFrom('person')
* .selectAll()
* .where('first_name', '=', 'Jennifer')
* .where('age', '>', 40)
* .executeTakeFirst()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select * from "person" where "first_name" = $1 and "age" > $2
* ```
*
* Operator can be any supported operator or if the typings don't support it
* you can always use:
*
* ```ts
* import { sql } from 'kysely'
*
* sql`your operator`
* ```
*
* <!-- siteExample("where", "Where in", 20) -->
*
* Find multiple items using a list of identifiers:
*
* ```ts
* const persons = await db
* .selectFrom('person')
* .selectAll()
* .where('id', 'in', [1, 2, 3])
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select * from "person" where "id" in ($1, $2, $3)
* ```
*
* <!-- siteExample("where", "Object filter", 30) -->
*
* You can use the `and` function to create a simple equality
* filter using an object
*
* ```ts
* const persons = await db
* .selectFrom('person')
* .selectAll()
* .where((eb) => eb.and({
* first_name: 'Jennifer',
* last_name: eb.ref('first_name')
* }))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select *
* from "person"
* where (
* "first_name" = $1
* and "last_name" = "first_name"
* )
* ```
*
* <!-- siteExample("where", "OR where", 40) -->
*
* To combine conditions using `OR`, you can use the expression builder.
* There are two ways to create `OR` expressions. Both are shown in this
* example:
*
* ```ts
* const persons = await db
* .selectFrom('person')
* .selectAll()
* // 1. Using the `or` method on the expression builder:
* .where((eb) => eb.or([
* eb('first_name', '=', 'Jennifer'),
* eb('first_name', '=', 'Sylvester')
* ]))
* // 2. Chaining expressions using the `or` method on the
* // created expressions:
* .where((eb) =>
* eb('last_name', '=', 'Aniston').or('last_name', '=', 'Stallone')
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select *
* from "person"
* where (
* ("first_name" = $1 or "first_name" = $2)
* and
* ("last_name" = $3 or "last_name" = $4)
* )
* ```
*
* <!-- siteExample("where", "Conditional where calls", 50) -->
*
* You can add expressions conditionally like this:
*
* ```ts
* import { Expression, SqlBool } from 'kysely'
*
* const firstName: string | undefined = 'Jennifer'
* const lastName: string | undefined = 'Aniston'
* const under18 = true
* const over60 = true
*
* let query = db
* .selectFrom('person')
* .selectAll()
*
* if (firstName) {
* // The query builder is immutable. Remember to reassign
* // the result back to the query variable.
* query = query.where('first_name', '=', firstName)
* }
*
* if (lastName) {
* query = query.where('last_name', '=', lastName)
* }
*
* if (under18 || over60) {
* // Conditional OR expressions can be added like this.
* query = query.where((eb) => {
* const ors: Expression<SqlBool>[] = []
*
* if (under18) {
* ors.push(eb('age', '<', 18))
* }
*
* if (over60) {
* ors.push(eb('age', '>', 60))
* }
*
* return eb.or(ors)
* })
* }
*
* const persons = await query.execute()
* ```
*
* Both the first and third argument can also be arbitrary expressions like
* subqueries. An expression can defined by passing a function and calling
* the methods of the {@link ExpressionBuilder} passed to the callback:
*
* ```ts
* const persons = await db
* .selectFrom('person')
* .selectAll()
* .where(
* (qb) => qb.selectFrom('pet')
* .select('pet.name')
* .whereRef('pet.owner_id', '=', 'person.id')
* .limit(1),
* '=',
* 'Fluffy'
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select *
* from "person"
* where (
* select "pet"."name"
* from "pet"
* where "pet"."owner_id" = "person"."id"
* limit $1
* ) = $2
* ```
*
* A `where in` query can be built by using the `in` operator and an array
* of values. The values in the array can also be expressions:
*
* ```ts
* const persons = await db
* .selectFrom('person')
* .selectAll()
* .where('person.id', 'in', [100, 200, 300])
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select * from "person" where "id" in ($1, $2, $3)
* ```
*
* <!-- siteExample("where", "Complex where clause", 60) -->
*
* For complex `where` expressions you can pass in a single callback and
* use the `ExpressionBuilder` to build your expression:
*
* ```ts
* const firstName = 'Jennifer'
* const maxAge = 60
*
* const persons = await db
* .selectFrom('person')
* .selectAll('person')
* .where(({ eb, or, and, not, exists, selectFrom }) => and([
* or([
* eb('first_name', '=', firstName),
* eb('age', '<', maxAge)
* ]),
* not(exists(
* selectFrom('pet')
* .select('pet.id')
* .whereRef('pet.owner_id', '=', 'person.id')
* ))
* ]))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "person".*
* from "person"
* where (
* (
* "first_name" = $1
* or "age" < $2
* )
* and not exists (
* select "pet"."id" from "pet" where "pet"."owner_id" = "person"."id"
* )
* )
* ```
*
* If everything else fails, you can always use the {@link sql} tag
* as any of the arguments, including the operator:
*
* ```ts
* import { sql } from 'kysely'
*
* const persons = await db
* .selectFrom('person')
* .selectAll()
* .where(
* sql<string>`coalesce(first_name, last_name)`,
* 'like',
* '%' + name + '%',
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select * from "person"
* where coalesce(first_name, last_name) like $1
* ```
*
* In all examples above the columns were known at compile time
* (except for the raw {@link sql} expressions). By default kysely only
* allows you to refer to columns that exist in the database **and**
* can be referred to in the current query and context.
*
* Sometimes you may want to refer to columns that come from the user
* input and thus are not available at compile time.
*
* You have two options, the {@link sql} tag or `db.dynamic`. The example below
* uses both:
*
* ```ts
* import { sql } from 'kysely'
* const { ref } = db.dynamic
*
* const columnFromUserInput: string = 'id'
*
* const persons = await db
* .selectFrom('person')
* .selectAll()
* .where(ref(columnFromUserInput), '=', 1)
* .where(sql.id(columnFromUserInput), '=', 2)
* .execute()
* ```
*/
where<E extends ExpressionOrFactory<DB, TB, SqlBool>>(expression: E): OnConflictUpdateBuilder<DB, TB>;
/**
* Specify a where condition for the update operation.
*
* See {@link WhereInterface.whereRef} for more info.
*/
whereRef<LRE extends ReferenceExpression<DB, TB>, RRE extends ReferenceExpression<DB, TB>>(lhs: LRE, op: ComparisonOperatorExpression, rhs: RRE): OnConflictUpdateBuilder<DB, TB>;
/**
* Clears all where expressions from the query.
*
* ### Examples
*
* ```ts
* db.selectFrom('person')
* .selectAll()
* .where('id','=',42)
* .clearWhere()
* ```
*
* The generated SQL(PostgreSQL):
*
* ```sql
* select * from "person"
* ```
*/
clearWhere(): OnConflictUpdateBuilder<DB, TB>;
/**
* Simply calls the provided function passing `this` as the only argument. `$call` returns
* what the provided function returns.
*/
$call<T>(func: (qb: this) => T): T;
toOperationNode(): OnConflictNode;
}

View File

@@ -0,0 +1,259 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OnConflictUpdateBuilder = exports.OnConflictDoNothingBuilder = exports.OnConflictBuilder = void 0;
const column_node_js_1 = require("../operation-node/column-node.js");
const identifier_node_js_1 = require("../operation-node/identifier-node.js");
const on_conflict_node_js_1 = require("../operation-node/on-conflict-node.js");
const binary_operation_parser_js_1 = require("../parser/binary-operation-parser.js");
const update_set_parser_js_1 = require("../parser/update-set-parser.js");
const object_utils_js_1 = require("../util/object-utils.js");
class OnConflictBuilder {
#props;
constructor(props) {
this.#props = (0, object_utils_js_1.freeze)(props);
}
/**
* Specify a single column as the conflict target.
*
* Also see the {@link columns}, {@link constraint} and {@link expression}
* methods for alternative ways to specify the conflict target.
*/
column(column) {
const columnNode = column_node_js_1.ColumnNode.create(column);
return new OnConflictBuilder({
...this.#props,
onConflictNode: on_conflict_node_js_1.OnConflictNode.cloneWith(this.#props.onConflictNode, {
columns: this.#props.onConflictNode.columns
? (0, object_utils_js_1.freeze)([...this.#props.onConflictNode.columns, columnNode])
: (0, object_utils_js_1.freeze)([columnNode]),
}),
});
}
/**
* Specify a list of columns as the conflict target.
*
* Also see the {@link column}, {@link constraint} and {@link expression}
* methods for alternative ways to specify the conflict target.
*/
columns(columns) {
const columnNodes = columns.map(column_node_js_1.ColumnNode.create);
return new OnConflictBuilder({
...this.#props,
onConflictNode: on_conflict_node_js_1.OnConflictNode.cloneWith(this.#props.onConflictNode, {
columns: this.#props.onConflictNode.columns
? (0, object_utils_js_1.freeze)([...this.#props.onConflictNode.columns, ...columnNodes])
: (0, object_utils_js_1.freeze)(columnNodes),
}),
});
}
/**
* Specify a specific constraint by name as the conflict target.
*
* Also see the {@link column}, {@link columns} and {@link expression}
* methods for alternative ways to specify the conflict target.
*/
constraint(constraintName) {
return new OnConflictBuilder({
...this.#props,
onConflictNode: on_conflict_node_js_1.OnConflictNode.cloneWith(this.#props.onConflictNode, {
constraint: identifier_node_js_1.IdentifierNode.create(constraintName),
}),
});
}
/**
* Specify an expression as the conflict target.
*
* This can be used if the unique index is an expression index.
*
* Also see the {@link column}, {@link columns} and {@link constraint}
* methods for alternative ways to specify the conflict target.
*/
expression(expression) {
return new OnConflictBuilder({
...this.#props,
onConflictNode: on_conflict_node_js_1.OnConflictNode.cloneWith(this.#props.onConflictNode, {
indexExpression: expression.toOperationNode(),
}),
});
}
where(...args) {
return new OnConflictBuilder({
...this.#props,
onConflictNode: on_conflict_node_js_1.OnConflictNode.cloneWithIndexWhere(this.#props.onConflictNode, (0, binary_operation_parser_js_1.parseValueBinaryOperationOrExpression)(args)),
});
}
whereRef(lhs, op, rhs) {
return new OnConflictBuilder({
...this.#props,
onConflictNode: on_conflict_node_js_1.OnConflictNode.cloneWithIndexWhere(this.#props.onConflictNode, (0, binary_operation_parser_js_1.parseReferentialBinaryOperation)(lhs, op, rhs)),
});
}
clearWhere() {
return new OnConflictBuilder({
...this.#props,
onConflictNode: on_conflict_node_js_1.OnConflictNode.cloneWithoutIndexWhere(this.#props.onConflictNode),
});
}
/**
* Adds the "do nothing" conflict action.
*
* ### Examples
*
* ```ts
* const id = 1
* const first_name = 'John'
*
* await db
* .insertInto('person')
* .values({ first_name, id })
* .onConflict((oc) => oc
* .column('id')
* .doNothing()
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* insert into "person" ("first_name", "id")
* values ($1, $2)
* on conflict ("id") do nothing
* ```
*/
doNothing() {
return new OnConflictDoNothingBuilder({
...this.#props,
onConflictNode: on_conflict_node_js_1.OnConflictNode.cloneWith(this.#props.onConflictNode, {
doNothing: true,
}),
});
}
/**
* Adds the "do update set" conflict action.
*
* ### Examples
*
* ```ts
* const id = 1
* const first_name = 'John'
*
* await db
* .insertInto('person')
* .values({ first_name, id })
* .onConflict((oc) => oc
* .column('id')
* .doUpdateSet({ first_name })
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* insert into "person" ("first_name", "id")
* values ($1, $2)
* on conflict ("id")
* do update set "first_name" = $3
* ```
*
* In the next example we use the `ref` method to reference
* columns of the virtual table `excluded` in a type-safe way
* to create an upsert operation:
*
* ```ts
* import type { NewPerson } from 'type-editor' // imaginary module
*
* async function upsertPerson(person: NewPerson): Promise<void> {
* await db.insertInto('person')
* .values(person)
* .onConflict((oc) => oc
* .column('id')
* .doUpdateSet((eb) => ({
* first_name: eb.ref('excluded.first_name'),
* last_name: eb.ref('excluded.last_name')
* })
* )
* )
* .execute()
* }
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* insert into "person" ("first_name", "last_name")
* values ($1, $2)
* on conflict ("id")
* do update set
* "first_name" = excluded."first_name",
* "last_name" = excluded."last_name"
* ```
*/
doUpdateSet(update) {
return new OnConflictUpdateBuilder({
...this.#props,
onConflictNode: on_conflict_node_js_1.OnConflictNode.cloneWith(this.#props.onConflictNode, {
updates: (0, update_set_parser_js_1.parseUpdateObjectExpression)(update),
}),
});
}
/**
* Simply calls the provided function passing `this` as the only argument. `$call` returns
* what the provided function returns.
*/
$call(func) {
return func(this);
}
}
exports.OnConflictBuilder = OnConflictBuilder;
class OnConflictDoNothingBuilder {
#props;
constructor(props) {
this.#props = (0, object_utils_js_1.freeze)(props);
}
toOperationNode() {
return this.#props.onConflictNode;
}
}
exports.OnConflictDoNothingBuilder = OnConflictDoNothingBuilder;
class OnConflictUpdateBuilder {
#props;
constructor(props) {
this.#props = (0, object_utils_js_1.freeze)(props);
}
where(...args) {
return new OnConflictUpdateBuilder({
...this.#props,
onConflictNode: on_conflict_node_js_1.OnConflictNode.cloneWithUpdateWhere(this.#props.onConflictNode, (0, binary_operation_parser_js_1.parseValueBinaryOperationOrExpression)(args)),
});
}
/**
* Specify a where condition for the update operation.
*
* See {@link WhereInterface.whereRef} for more info.
*/
whereRef(lhs, op, rhs) {
return new OnConflictUpdateBuilder({
...this.#props,
onConflictNode: on_conflict_node_js_1.OnConflictNode.cloneWithUpdateWhere(this.#props.onConflictNode, (0, binary_operation_parser_js_1.parseReferentialBinaryOperation)(lhs, op, rhs)),
});
}
clearWhere() {
return new OnConflictUpdateBuilder({
...this.#props,
onConflictNode: on_conflict_node_js_1.OnConflictNode.cloneWithoutUpdateWhere(this.#props.onConflictNode),
});
}
/**
* Simply calls the provided function passing `this` as the only argument. `$call` returns
* what the provided function returns.
*/
$call(func) {
return func(this);
}
toOperationNode() {
return this.#props.onConflictNode;
}
}
exports.OnConflictUpdateBuilder = OnConflictUpdateBuilder;

View File

@@ -0,0 +1,158 @@
import type { Expression } from '../expression/expression.js';
import type { OrderByExpression, DirectedOrderByStringReference, OrderByModifiers } from '../parser/order-by-parser.js';
export interface OrderByInterface<DB, TB extends keyof DB, O> {
/**
* Adds an `order by` clause to the query.
*
* `orderBy` calls are additive. Meaning, additional `orderBy` calls append to
* the existing order by clause.
*
* `orderBy` is supported in select queries on all dialects. In MySQL, you can
* also use `orderBy` in update and delete queries.
*
* In a single call you can add a single column/expression or multiple columns/expressions.
*
* Single column/expression calls can have 1-2 arguments. The first argument is
* the expression to order by, while the second optional argument is the direction
* (`asc` or `desc`), a callback that accepts and returns an {@link OrderByItemBuilder}
* or an expression.
*
* See {@link clearOrderBy} to remove the `order by` clause from a query.
*
* ### Examples
*
* Single column/expression per call:
*
* ```ts
* await db
* .selectFrom('person')
* .select('person.first_name as fn')
* .orderBy('id')
* .orderBy('fn', 'desc')
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "person"."first_name" as "fn"
* from "person"
* order by "id", "fn" desc
* ```
*
* Building advanced modifiers:
*
* ```ts
* await db
* .selectFrom('person')
* .select('person.first_name as fn')
* .orderBy('id', (ob) => ob.desc().nullsFirst())
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "person"."first_name" as "fn"
* from "person"
* order by "id" desc nulls first
* ```
*
* The order by expression can also be a raw sql expression or a subquery
* in addition to column references:
*
* ```ts
* import { sql } from 'kysely'
*
* await db
* .selectFrom('person')
* .selectAll()
* .orderBy((eb) => eb.selectFrom('pet')
* .select('pet.name')
* .whereRef('pet.owner_id', '=', 'person.id')
* .limit(1)
* )
* .orderBy(
* sql<string>`concat(first_name, last_name) asc`
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select *
* from "person"
* order by
* ( select "pet"."name"
* from "pet"
* where "pet"."owner_id" = "person"."id"
* limit $1
* ) asc,
* concat(first_name, last_name) asc
* ```
*
* `dynamic.ref` can be used to refer to columns not known at
* compile time:
*
* ```ts
* async function someQuery(orderBy: string) {
* const { ref } = db.dynamic
*
* return await db
* .selectFrom('person')
* .select('person.first_name as fn')
* .orderBy(ref(orderBy))
* .execute()
* }
*
* someQuery('fn')
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "person"."first_name" as "fn"
* from "person"
* order by "fn"
* ```
*/
orderBy<OE extends OrderByExpression<DB, TB, O>>(expr: OE, modifiers?: OrderByModifiers): OrderByInterface<DB, TB, O>;
/**
* @deprecated It does ~2-2.6x more compile-time instantiations compared to multiple chained `orderBy(expr, modifiers?)` calls (in `order by` clauses with reasonable item counts), and has broken autocompletion.
*/
orderBy<OE extends OrderByExpression<DB, TB, O> | DirectedOrderByStringReference<DB, TB, O>>(exprs: ReadonlyArray<OE>): OrderByInterface<DB, TB, O>;
/**
* @deprecated It does ~2.9x more compile-time instantiations compared to a `orderBy(expr, direction)` call.
*/
orderBy<OE extends DirectedOrderByStringReference<DB, TB, O>>(expr: OE): OrderByInterface<DB, TB, O>;
/**
* @deprecated Use `orderBy(expr, (ob) => ...)` instead.
*/
orderBy<OE extends OrderByExpression<DB, TB, O>>(expr: OE, modifiers: Expression<any>): OrderByInterface<DB, TB, O>;
/**
* Clears the `order by` clause from the query.
*
* See {@link orderBy} for adding an `order by` clause or item to a query.
*
* ### Examples
*
* ```ts
* const query = db
* .selectFrom('person')
* .selectAll()
* .orderBy('id', 'desc')
*
* const results = await query
* .clearOrderBy()
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select * from "person"
* ```
*/
clearOrderBy(): OrderByInterface<DB, TB, O>;
}

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,43 @@
import type { OperationNodeSource } from '../operation-node/operation-node-source.js';
import { OrderByItemNode } from '../operation-node/order-by-item-node.js';
import type { Collation } from '../parser/collate-parser.js';
export declare class OrderByItemBuilder implements OperationNodeSource {
#private;
constructor(props: OrderByItemBuilderProps);
/**
* Adds `desc` to the `order by` item.
*
* See {@link asc} for the opposite.
*/
desc(): OrderByItemBuilder;
/**
* Adds `asc` to the `order by` item.
*
* See {@link desc} for the opposite.
*/
asc(): OrderByItemBuilder;
/**
* Adds `nulls last` to the `order by` item.
*
* This is only supported by some dialects like PostgreSQL and SQLite.
*
* See {@link nullsFirst} for the opposite.
*/
nullsLast(): OrderByItemBuilder;
/**
* Adds `nulls first` to the `order by` item.
*
* This is only supported by some dialects like PostgreSQL and SQLite.
*
* See {@link nullsLast} for the opposite.
*/
nullsFirst(): OrderByItemBuilder;
/**
* Adds `collate <collationName>` to the `order by` item.
*/
collate(collation: Collation): OrderByItemBuilder;
toOperationNode(): OrderByItemNode;
}
export interface OrderByItemBuilderProps {
readonly node: OrderByItemNode;
}

View File

@@ -0,0 +1,75 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OrderByItemBuilder = void 0;
const collate_node_js_1 = require("../operation-node/collate-node.js");
const order_by_item_node_js_1 = require("../operation-node/order-by-item-node.js");
const raw_node_js_1 = require("../operation-node/raw-node.js");
const object_utils_js_1 = require("../util/object-utils.js");
class OrderByItemBuilder {
#props;
constructor(props) {
this.#props = (0, object_utils_js_1.freeze)(props);
}
/**
* Adds `desc` to the `order by` item.
*
* See {@link asc} for the opposite.
*/
desc() {
return new OrderByItemBuilder({
node: order_by_item_node_js_1.OrderByItemNode.cloneWith(this.#props.node, {
direction: raw_node_js_1.RawNode.createWithSql('desc'),
}),
});
}
/**
* Adds `asc` to the `order by` item.
*
* See {@link desc} for the opposite.
*/
asc() {
return new OrderByItemBuilder({
node: order_by_item_node_js_1.OrderByItemNode.cloneWith(this.#props.node, {
direction: raw_node_js_1.RawNode.createWithSql('asc'),
}),
});
}
/**
* Adds `nulls last` to the `order by` item.
*
* This is only supported by some dialects like PostgreSQL and SQLite.
*
* See {@link nullsFirst} for the opposite.
*/
nullsLast() {
return new OrderByItemBuilder({
node: order_by_item_node_js_1.OrderByItemNode.cloneWith(this.#props.node, { nulls: 'last' }),
});
}
/**
* Adds `nulls first` to the `order by` item.
*
* This is only supported by some dialects like PostgreSQL and SQLite.
*
* See {@link nullsLast} for the opposite.
*/
nullsFirst() {
return new OrderByItemBuilder({
node: order_by_item_node_js_1.OrderByItemNode.cloneWith(this.#props.node, { nulls: 'first' }),
});
}
/**
* Adds `collate <collationName>` to the `order by` item.
*/
collate(collation) {
return new OrderByItemBuilder({
node: order_by_item_node_js_1.OrderByItemNode.cloneWith(this.#props.node, {
collation: collate_node_js_1.CollateNode.create(collation),
}),
});
}
toOperationNode() {
return this.#props.node;
}
}
exports.OrderByItemBuilder = OrderByItemBuilder;

View File

@@ -0,0 +1,138 @@
import type { ExpressionBuilder } from '../expression/expression-builder.js';
import type { AliasedExpressionOrFactory } from '../parser/expression-parser.js';
import type { ReturningAllRow, ReturningRow } from '../parser/returning-parser.js';
import type { AnyAliasedColumnWithTable, AnyColumnWithTable } from '../util/type-utils.js';
export interface OutputInterface<DB, TB extends keyof DB, O, OP extends OutputPrefix = OutputPrefix> {
/**
* Allows you to return data from modified rows.
*
* On supported databases like MS SQL Server (MSSQL), this method can be chained
* to `insert`, `update`, `delete` and `merge` queries to return data.
*
* Also see the {@link outputAll} method.
*
* ### Examples
*
* Return one column:
*
* ```ts
* const { id } = await db
* .insertInto('person')
* .output('inserted.id')
* .values({
* first_name: 'Jennifer',
* last_name: 'Aniston',
* gender: 'female',
* })
* .executeTakeFirstOrThrow()
* ```
*
* The generated SQL (MSSQL):
*
* ```sql
* insert into "person" ("first_name", "last_name", "gender")
* output "inserted"."id"
* values (@1, @2, @3)
* ```
*
* Return multiple columns:
*
* ```ts
* const { old_first_name, old_last_name, new_first_name, new_last_name } = await db
* .updateTable('person')
* .set({ first_name: 'John', last_name: 'Doe' })
* .output([
* 'deleted.first_name as old_first_name',
* 'deleted.last_name as old_last_name',
* 'inserted.first_name as new_first_name',
* 'inserted.last_name as new_last_name',
* ])
* .where('created_at', '<', new Date())
* .executeTakeFirstOrThrow()
* ```
*
* The generated SQL (MSSQL):
*
* ```sql
* update "person"
* set "first_name" = @1, "last_name" = @2
* output "deleted"."first_name" as "old_first_name",
* "deleted"."last_name" as "old_last_name",
* "inserted"."first_name" as "new_first_name",
* "inserted"."last_name" as "new_last_name"
* where "created_at" < @3
* ```
*
* Return arbitrary expressions:
*
* ```ts
* import { sql } from 'kysely'
*
* const { full_name } = await db
* .deleteFrom('person')
* .output((eb) => sql<string>`concat(${eb.ref('deleted.first_name')}, ' ', ${eb.ref('deleted.last_name')})`.as('full_name'))
* .where('created_at', '<', new Date())
* .executeTakeFirstOrThrow()
* ```
*
* The generated SQL (MSSQL):
*
* ```sql
* delete from "person"
* output concat("deleted"."first_name", ' ', "deleted"."last_name") as "full_name"
* where "created_at" < @1
* ```
*
* Return the action performed on the row:
*
* ```ts
* await db
* .mergeInto('person')
* .using('pet', 'pet.owner_id', 'person.id')
* .whenMatched()
* .thenDelete()
* .whenNotMatched()
* .thenInsertValues({
* first_name: 'John',
* last_name: 'Doe',
* gender: 'male'
* })
* .output([
* 'inserted.id as inserted_id',
* 'deleted.id as deleted_id',
* ])
* .execute()
* ```
*
* The generated SQL (MSSQL):
*
* ```sql
* merge into "person"
* using "pet" on "pet"."owner_id" = "person"."id"
* when matched then delete
* when not matched then
* insert ("first_name", "last_name", "gender")
* values (@1, @2, @3)
* output "inserted"."id" as "inserted_id", "deleted"."id" as "deleted_id"
* ```
*
*/
output<OE extends OutputExpression<DB, TB, OP>>(selections: ReadonlyArray<OE>): OutputInterface<DB, TB, ReturningRow<DB, TB, O, SelectExpressionFromOutputExpression<OE>>, OP>;
output<CB extends OutputCallback<DB, TB, OP>>(callback: CB): OutputInterface<DB, TB, ReturningRow<DB, TB, O, SelectExpressionFromOutputCallback<CB>>, OP>;
output<OE extends OutputExpression<DB, TB, OP>>(selection: OE): OutputInterface<DB, TB, ReturningRow<DB, TB, O, SelectExpressionFromOutputExpression<OE>>, OP>;
/**
* Adds an `output {prefix}.*` to an `insert`/`update`/`delete`/`merge` query on databases
* that support `output` such as MS SQL Server (MSSQL).
*
* Also see the {@link output} method.
*/
outputAll(table: OP): OutputInterface<DB, TB, ReturningAllRow<DB, TB, O>, OP>;
}
export type OutputPrefix = 'deleted' | 'inserted';
export type OutputDatabase<DB, TB extends keyof DB, OP extends OutputPrefix = OutputPrefix> = {
[K in OP]: DB[TB];
};
export type OutputExpression<DB, TB extends keyof DB, OP extends OutputPrefix = OutputPrefix, ODB = OutputDatabase<DB, TB, OP>, OTB extends keyof ODB = keyof ODB> = AnyAliasedColumnWithTable<ODB, OTB> | AnyColumnWithTable<ODB, OTB> | AliasedExpressionOrFactory<ODB, OTB>;
export type OutputCallback<DB, TB extends keyof DB, OP extends OutputPrefix = OutputPrefix> = (eb: ExpressionBuilder<OutputDatabase<DB, TB, OP>, OP>) => ReadonlyArray<OutputExpression<DB, TB, OP>>;
export type SelectExpressionFromOutputExpression<OE> = OE extends `${OutputPrefix}.${infer C}` ? C : OE;
export type SelectExpressionFromOutputCallback<CB> = CB extends (eb: ExpressionBuilder<any, any>) => ReadonlyArray<infer OE> ? SelectExpressionFromOutputExpression<OE> : never;

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,101 @@
import type { Expression } from '../expression/expression.js';
import type { OperationNodeSource } from '../operation-node/operation-node-source.js';
import { OverNode } from '../operation-node/over-node.js';
import { type DirectedOrderByStringReference, type OrderByExpression, type OrderByModifiers } from '../parser/order-by-parser.js';
import { type PartitionByExpression } from '../parser/partition-by-parser.js';
import type { OrderByInterface } from './order-by-interface.js';
export declare class OverBuilder<DB, TB extends keyof DB> implements OrderByInterface<DB, TB, {}>, OperationNodeSource {
#private;
constructor(props: OverBuilderProps);
/**
* Adds an `order by` clause or item inside the `over` function.
*
* ```ts
* const result = await db
* .selectFrom('person')
* .select(
* (eb) => eb.fn.avg<number>('age').over(
* ob => ob.orderBy('first_name', 'asc').orderBy('last_name', 'asc')
* ).as('average_age')
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select avg("age") over(order by "first_name" asc, "last_name" asc) as "average_age"
* from "person"
* ```
*/
orderBy<OE extends OrderByExpression<DB, TB, {}>>(expr: OE, modifiers?: OrderByModifiers): OverBuilder<DB, TB>;
/**
* @deprecated It does ~2-2.6x more compile-time instantiations compared to multiple chained `orderBy(expr, modifiers?)` calls (in `order by` clauses with reasonable item counts), and has broken autocompletion.
*/
orderBy<OE extends OrderByExpression<DB, TB, {}> | DirectedOrderByStringReference<DB, TB, {}>>(exprs: ReadonlyArray<OE>): OverBuilder<DB, TB>;
/**
* @deprecated It does ~2.9x more compile-time instantiations compared to a `orderBy(expr, direction)` call.
*/
orderBy<OE extends DirectedOrderByStringReference<DB, TB, {}>>(expr: OE): OverBuilder<DB, TB>;
/**
* @deprecated Use `orderBy(expr, (ob) => ...)` instead.
*/
orderBy<OE extends OrderByExpression<DB, TB, {}>>(expr: OE, modifiers: Expression<any>): OverBuilder<DB, TB>;
/**
* Clears the `order by` clause from the query.
*
* See {@link orderBy} for adding an `order by` clause or item to a query.
*
* ### Examples
*
* ```ts
* const query = db
* .selectFrom('person')
* .selectAll()
* .orderBy('id', 'desc')
*
* const results = await query
* .clearOrderBy()
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select * from "person"
* ```
*/
clearOrderBy(): OverBuilder<DB, TB>;
/**
* Adds partition by clause item/s inside the over function.
*
* ```ts
* const result = await db
* .selectFrom('person')
* .select(
* (eb) => eb.fn.avg<number>('age').over(
* ob => ob.partitionBy(['last_name', 'first_name'])
* ).as('average_age')
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select avg("age") over(partition by "last_name", "first_name") as "average_age"
* from "person"
* ```
*/
partitionBy(partitionBy: ReadonlyArray<PartitionByExpression<DB, TB>>): OverBuilder<DB, TB>;
partitionBy<PE extends PartitionByExpression<DB, TB>>(partitionBy: PE): OverBuilder<DB, TB>;
/**
* Simply calls the provided function passing `this` as the only argument. `$call` returns
* what the provided function returns.
*/
$call<T>(func: (qb: this) => T): T;
toOperationNode(): OverNode;
}
export interface OverBuilderProps {
readonly overNode: OverNode;
}

View File

@@ -0,0 +1,40 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OverBuilder = void 0;
const over_node_js_1 = require("../operation-node/over-node.js");
const query_node_js_1 = require("../operation-node/query-node.js");
const order_by_parser_js_1 = require("../parser/order-by-parser.js");
const partition_by_parser_js_1 = require("../parser/partition-by-parser.js");
const object_utils_js_1 = require("../util/object-utils.js");
class OverBuilder {
#props;
constructor(props) {
this.#props = (0, object_utils_js_1.freeze)(props);
}
orderBy(...args) {
return new OverBuilder({
overNode: over_node_js_1.OverNode.cloneWithOrderByItems(this.#props.overNode, (0, order_by_parser_js_1.parseOrderBy)(args)),
});
}
clearOrderBy() {
return new OverBuilder({
overNode: query_node_js_1.QueryNode.cloneWithoutOrderBy(this.#props.overNode),
});
}
partitionBy(partitionBy) {
return new OverBuilder({
overNode: over_node_js_1.OverNode.cloneWithPartitionByItems(this.#props.overNode, (0, partition_by_parser_js_1.parsePartitionBy)(partitionBy)),
});
}
/**
* Simply calls the provided function passing `this` as the only argument. `$call` returns
* what the provided function returns.
*/
$call(func) {
return func(this);
}
toOperationNode() {
return this.#props.overNode;
}
}
exports.OverBuilder = OverBuilder;

View File

@@ -0,0 +1,91 @@
import type { ReturningAllRow, ReturningCallbackRow, ReturningRow } from '../parser/returning-parser.js';
import type { SelectCallback, SelectExpression } from '../parser/select-parser.js';
import type { Selectable } from '../util/column-type.js';
export interface ReturningInterface<DB, TB extends keyof DB, O> {
/**
* Allows you to return data from modified rows.
*
* On supported databases like PostgreSQL, this method can be chained to
* `insert`, `update`, `delete` and `merge` queries to return data.
*
* Note that on SQLite you need to give aliases for the expressions to avoid
* [this bug](https://sqlite.org/forum/forumpost/033daf0b32) in SQLite.
* For example `.returning('id as id')`.
*
* Also see the {@link returningAll} method.
*
* ### Examples
*
* Return one column:
*
* ```ts
* const { id } = await db
* .insertInto('person')
* .values({
* first_name: 'Jennifer',
* last_name: 'Aniston'
* })
* .returning('id')
* .executeTakeFirstOrThrow()
* ```
*
* Return multiple columns:
*
* ```ts
* const { id, last_name } = await db
* .insertInto('person')
* .values({
* first_name: 'Jennifer',
* last_name: 'Aniston'
* })
* .returning(['id', 'last_name'])
* .executeTakeFirstOrThrow()
* ```
*
* Return arbitrary expressions:
*
* ```ts
* import { sql } from 'kysely'
*
* const { id, full_name, first_pet_id } = await db
* .insertInto('person')
* .values({
* first_name: 'Jennifer',
* last_name: 'Aniston'
* })
* .returning((eb) => [
* 'id as id',
* sql<string>`concat(first_name, ' ', last_name)`.as('full_name'),
* eb.selectFrom('pet').select('pet.id').limit(1).as('first_pet_id')
* ])
* .executeTakeFirstOrThrow()
* ```
*/
returning<SE extends SelectExpression<DB, TB>>(selections: ReadonlyArray<SE>): ReturningInterface<DB, TB, ReturningRow<DB, TB, O, SE>>;
returning<CB extends SelectCallback<DB, TB>>(callback: CB): ReturningInterface<DB, TB, ReturningCallbackRow<DB, TB, O, CB>>;
returning<SE extends SelectExpression<DB, TB>>(selection: SE): ReturningInterface<DB, TB, ReturningRow<DB, TB, O, SE>>;
/**
* Adds a `returning *` to an insert/update/delete/merge query on databases
* that support `returning` such as PostgreSQL.
*
* Also see the {@link returning} method.
*/
returningAll(): ReturningInterface<DB, TB, Selectable<DB[TB]>>;
}
export interface MultiTableReturningInterface<DB, TB extends keyof DB, O> extends ReturningInterface<DB, TB, O> {
/**
* Adds a `returning *` or `returning table.*` to an insert/update/delete/merge
* query on databases that support `returning` such as PostgreSQL.
*
* Also see the {@link returning} method.
*/
returningAll<T extends TB>(tables: ReadonlyArray<T>): MultiTableReturningInterface<DB, TB, ReturningAllRow<DB, T, O>>;
/**
* Adds a `returning *` to an insert/update/delete/merge query on databases
* that support `returning` such as PostgreSQL.
*
* Also see the {@link returning} method.
*/
returningAll<T extends TB>(table: T): MultiTableReturningInterface<DB, TB, ReturningAllRow<DB, T, O>>;
returningAll(): ReturningInterface<DB, TB, Selectable<DB[TB]>>;
}

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,28 @@
import type { AliasableExpression } from '../expression/expression.js';
import type { SelectQueryNode } from '../operation-node/select-query-node.js';
export interface SelectQueryBuilderExpression<O> extends AliasableExpression<O> {
get isSelectQueryBuilder(): true;
/**
* Creates the OperationNode that describes how to compile this expression into SQL.
*
* ### Examples
*
* If you are creating a custom expression, it's often easiest to use the {@link sql}
* template tag to build the node:
*
* ```ts
* import { type Expression, type OperationNode, sql } from 'kysely'
*
* class SomeExpression<T> implements Expression<T> {
* get expressionType(): T | undefined {
* return undefined
* }
*
* toOperationNode(): OperationNode {
* return sql`some sql here`.toOperationNode()
* }
* }
* ```
*/
toOperationNode(): SelectQueryNode;
}

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,376 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createSelectQueryBuilder = createSelectQueryBuilder;
const alias_node_js_1 = require("../operation-node/alias-node.js");
const select_modifier_node_js_1 = require("../operation-node/select-modifier-node.js");
const join_parser_js_1 = require("../parser/join-parser.js");
const table_parser_js_1 = require("../parser/table-parser.js");
const select_parser_js_1 = require("../parser/select-parser.js");
const reference_parser_js_1 = require("../parser/reference-parser.js");
const select_query_node_js_1 = require("../operation-node/select-query-node.js");
const query_node_js_1 = require("../operation-node/query-node.js");
const order_by_parser_js_1 = require("../parser/order-by-parser.js");
const limit_node_js_1 = require("../operation-node/limit-node.js");
const offset_node_js_1 = require("../operation-node/offset-node.js");
const object_utils_js_1 = require("../util/object-utils.js");
const group_by_parser_js_1 = require("../parser/group-by-parser.js");
const no_result_error_js_1 = require("./no-result-error.js");
const identifier_node_js_1 = require("../operation-node/identifier-node.js");
const set_operation_parser_js_1 = require("../parser/set-operation-parser.js");
const binary_operation_parser_js_1 = require("../parser/binary-operation-parser.js");
const expression_wrapper_js_1 = require("../expression/expression-wrapper.js");
const value_parser_js_1 = require("../parser/value-parser.js");
const fetch_parser_js_1 = require("../parser/fetch-parser.js");
const top_parser_js_1 = require("../parser/top-parser.js");
class SelectQueryBuilderImpl {
#props;
constructor(props) {
this.#props = (0, object_utils_js_1.freeze)(props);
}
get expressionType() {
return undefined;
}
get isSelectQueryBuilder() {
return true;
}
where(...args) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithWhere(this.#props.queryNode, (0, binary_operation_parser_js_1.parseValueBinaryOperationOrExpression)(args)),
});
}
whereRef(lhs, op, rhs) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithWhere(this.#props.queryNode, (0, binary_operation_parser_js_1.parseReferentialBinaryOperation)(lhs, op, rhs)),
});
}
having(...args) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: select_query_node_js_1.SelectQueryNode.cloneWithHaving(this.#props.queryNode, (0, binary_operation_parser_js_1.parseValueBinaryOperationOrExpression)(args)),
});
}
havingRef(lhs, op, rhs) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: select_query_node_js_1.SelectQueryNode.cloneWithHaving(this.#props.queryNode, (0, binary_operation_parser_js_1.parseReferentialBinaryOperation)(lhs, op, rhs)),
});
}
select(selection) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: select_query_node_js_1.SelectQueryNode.cloneWithSelections(this.#props.queryNode, (0, select_parser_js_1.parseSelectArg)(selection)),
});
}
distinctOn(selection) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: select_query_node_js_1.SelectQueryNode.cloneWithDistinctOn(this.#props.queryNode, (0, reference_parser_js_1.parseReferenceExpressionOrList)(selection)),
});
}
modifyFront(modifier) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: select_query_node_js_1.SelectQueryNode.cloneWithFrontModifier(this.#props.queryNode, select_modifier_node_js_1.SelectModifierNode.createWithExpression(modifier.toOperationNode())),
});
}
modifyEnd(modifier) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithEndModifier(this.#props.queryNode, select_modifier_node_js_1.SelectModifierNode.createWithExpression(modifier.toOperationNode())),
});
}
distinct() {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: select_query_node_js_1.SelectQueryNode.cloneWithFrontModifier(this.#props.queryNode, select_modifier_node_js_1.SelectModifierNode.create('Distinct')),
});
}
forUpdate(of) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithEndModifier(this.#props.queryNode, select_modifier_node_js_1.SelectModifierNode.create('ForUpdate', of ? (0, object_utils_js_1.asArray)(of).map(table_parser_js_1.parseTable) : undefined)),
});
}
forShare(of) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithEndModifier(this.#props.queryNode, select_modifier_node_js_1.SelectModifierNode.create('ForShare', of ? (0, object_utils_js_1.asArray)(of).map(table_parser_js_1.parseTable) : undefined)),
});
}
forKeyShare(of) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithEndModifier(this.#props.queryNode, select_modifier_node_js_1.SelectModifierNode.create('ForKeyShare', of ? (0, object_utils_js_1.asArray)(of).map(table_parser_js_1.parseTable) : undefined)),
});
}
forNoKeyUpdate(of) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithEndModifier(this.#props.queryNode, select_modifier_node_js_1.SelectModifierNode.create('ForNoKeyUpdate', of ? (0, object_utils_js_1.asArray)(of).map(table_parser_js_1.parseTable) : undefined)),
});
}
skipLocked() {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithEndModifier(this.#props.queryNode, select_modifier_node_js_1.SelectModifierNode.create('SkipLocked')),
});
}
noWait() {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithEndModifier(this.#props.queryNode, select_modifier_node_js_1.SelectModifierNode.create('NoWait')),
});
}
selectAll(table) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: select_query_node_js_1.SelectQueryNode.cloneWithSelections(this.#props.queryNode, (0, select_parser_js_1.parseSelectAll)(table)),
});
}
innerJoin(...args) {
return this.#join('InnerJoin', args);
}
leftJoin(...args) {
return this.#join('LeftJoin', args);
}
rightJoin(...args) {
return this.#join('RightJoin', args);
}
fullJoin(...args) {
return this.#join('FullJoin', args);
}
crossJoin(...args) {
return this.#join('CrossJoin', args);
}
innerJoinLateral(...args) {
return this.#join('LateralInnerJoin', args);
}
leftJoinLateral(...args) {
return this.#join('LateralLeftJoin', args);
}
crossJoinLateral(...args) {
return this.#join('LateralCrossJoin', args);
}
crossApply(...args) {
return this.#join('CrossApply', args);
}
outerApply(...args) {
return this.#join('OuterApply', args);
}
#join(joinType, args) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithJoin(this.#props.queryNode, (0, join_parser_js_1.parseJoin)(joinType, args)),
});
}
orderBy(...args) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithOrderByItems(this.#props.queryNode, (0, order_by_parser_js_1.parseOrderBy)(args)),
});
}
groupBy(groupBy) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: select_query_node_js_1.SelectQueryNode.cloneWithGroupByItems(this.#props.queryNode, (0, group_by_parser_js_1.parseGroupBy)(groupBy)),
});
}
limit(limit) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: select_query_node_js_1.SelectQueryNode.cloneWithLimit(this.#props.queryNode, limit_node_js_1.LimitNode.create((0, value_parser_js_1.parseValueExpression)(limit))),
});
}
offset(offset) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: select_query_node_js_1.SelectQueryNode.cloneWithOffset(this.#props.queryNode, offset_node_js_1.OffsetNode.create((0, value_parser_js_1.parseValueExpression)(offset))),
});
}
fetch(rowCount, modifier = 'only') {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: select_query_node_js_1.SelectQueryNode.cloneWithFetch(this.#props.queryNode, (0, fetch_parser_js_1.parseFetch)(rowCount, modifier)),
});
}
top(expression, modifiers) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithTop(this.#props.queryNode, (0, top_parser_js_1.parseTop)(expression, modifiers)),
});
}
union(expression) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: select_query_node_js_1.SelectQueryNode.cloneWithSetOperations(this.#props.queryNode, (0, set_operation_parser_js_1.parseSetOperations)('union', expression, false)),
});
}
unionAll(expression) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: select_query_node_js_1.SelectQueryNode.cloneWithSetOperations(this.#props.queryNode, (0, set_operation_parser_js_1.parseSetOperations)('union', expression, true)),
});
}
intersect(expression) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: select_query_node_js_1.SelectQueryNode.cloneWithSetOperations(this.#props.queryNode, (0, set_operation_parser_js_1.parseSetOperations)('intersect', expression, false)),
});
}
intersectAll(expression) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: select_query_node_js_1.SelectQueryNode.cloneWithSetOperations(this.#props.queryNode, (0, set_operation_parser_js_1.parseSetOperations)('intersect', expression, true)),
});
}
except(expression) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: select_query_node_js_1.SelectQueryNode.cloneWithSetOperations(this.#props.queryNode, (0, set_operation_parser_js_1.parseSetOperations)('except', expression, false)),
});
}
exceptAll(expression) {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: select_query_node_js_1.SelectQueryNode.cloneWithSetOperations(this.#props.queryNode, (0, set_operation_parser_js_1.parseSetOperations)('except', expression, true)),
});
}
as(alias) {
return new AliasedSelectQueryBuilderImpl(this, alias);
}
clearSelect() {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: select_query_node_js_1.SelectQueryNode.cloneWithoutSelections(this.#props.queryNode),
});
}
clearWhere() {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithoutWhere(this.#props.queryNode),
});
}
clearLimit() {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: select_query_node_js_1.SelectQueryNode.cloneWithoutLimit(this.#props.queryNode),
});
}
clearOffset() {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: select_query_node_js_1.SelectQueryNode.cloneWithoutOffset(this.#props.queryNode),
});
}
clearOrderBy() {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithoutOrderBy(this.#props.queryNode),
});
}
clearGroupBy() {
return new SelectQueryBuilderImpl({
...this.#props,
queryNode: select_query_node_js_1.SelectQueryNode.cloneWithoutGroupBy(this.#props.queryNode),
});
}
$call(func) {
return func(this);
}
$if(condition, func) {
if (condition) {
return func(this);
}
return new SelectQueryBuilderImpl({
...this.#props,
});
}
$castTo() {
return new SelectQueryBuilderImpl(this.#props);
}
$narrowType() {
return new SelectQueryBuilderImpl(this.#props);
}
$assertType() {
return new SelectQueryBuilderImpl(this.#props);
}
$asTuple() {
return new expression_wrapper_js_1.ExpressionWrapper(this.toOperationNode());
}
$asScalar() {
return new expression_wrapper_js_1.ExpressionWrapper(this.toOperationNode());
}
withPlugin(plugin) {
return new SelectQueryBuilderImpl({
...this.#props,
executor: this.#props.executor.withPlugin(plugin),
});
}
toOperationNode() {
return this.#props.executor.transformQuery(this.#props.queryNode, this.#props.queryId);
}
compile() {
return this.#props.executor.compileQuery(this.toOperationNode(), this.#props.queryId);
}
async execute() {
const compiledQuery = this.compile();
const result = await this.#props.executor.executeQuery(compiledQuery);
return result.rows;
}
async executeTakeFirst() {
const [result] = await this.execute();
return result;
}
async executeTakeFirstOrThrow(errorConstructor = no_result_error_js_1.NoResultError) {
const result = await this.executeTakeFirst();
if (result === undefined) {
const error = (0, no_result_error_js_1.isNoResultErrorConstructor)(errorConstructor)
? new errorConstructor(this.toOperationNode())
: errorConstructor(this.toOperationNode());
throw error;
}
return result;
}
async *stream(chunkSize = 100) {
const compiledQuery = this.compile();
const stream = this.#props.executor.stream(compiledQuery, chunkSize);
for await (const item of stream) {
yield* item.rows;
}
}
async explain(format, options) {
const builder = new SelectQueryBuilderImpl({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithExplain(this.#props.queryNode, format, options),
});
return await builder.execute();
}
}
function createSelectQueryBuilder(props) {
return new SelectQueryBuilderImpl(props);
}
/**
* {@link SelectQueryBuilder} with an alias. The result of calling {@link SelectQueryBuilder.as}.
*/
class AliasedSelectQueryBuilderImpl {
#queryBuilder;
#alias;
constructor(queryBuilder, alias) {
this.#queryBuilder = queryBuilder;
this.#alias = alias;
}
get expression() {
return this.#queryBuilder;
}
get alias() {
return this.#alias;
}
get isAliasedSelectQueryBuilder() {
return true;
}
toOperationNode() {
return alias_node_js_1.AliasNode.create(this.#queryBuilder.toOperationNode(), identifier_node_js_1.IdentifierNode.create(this.#alias));
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,513 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UpdateQueryBuilder = void 0;
const join_parser_js_1 = require("../parser/join-parser.js");
const table_parser_js_1 = require("../parser/table-parser.js");
const select_parser_js_1 = require("../parser/select-parser.js");
const query_node_js_1 = require("../operation-node/query-node.js");
const update_query_node_js_1 = require("../operation-node/update-query-node.js");
const update_set_parser_js_1 = require("../parser/update-set-parser.js");
const object_utils_js_1 = require("../util/object-utils.js");
const update_result_js_1 = require("./update-result.js");
const no_result_error_js_1 = require("./no-result-error.js");
const binary_operation_parser_js_1 = require("../parser/binary-operation-parser.js");
const value_parser_js_1 = require("../parser/value-parser.js");
const limit_node_js_1 = require("../operation-node/limit-node.js");
const top_parser_js_1 = require("../parser/top-parser.js");
const order_by_parser_js_1 = require("../parser/order-by-parser.js");
class UpdateQueryBuilder {
#props;
constructor(props) {
this.#props = (0, object_utils_js_1.freeze)(props);
}
where(...args) {
return new UpdateQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithWhere(this.#props.queryNode, (0, binary_operation_parser_js_1.parseValueBinaryOperationOrExpression)(args)),
});
}
whereRef(lhs, op, rhs) {
return new UpdateQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithWhere(this.#props.queryNode, (0, binary_operation_parser_js_1.parseReferentialBinaryOperation)(lhs, op, rhs)),
});
}
clearWhere() {
return new UpdateQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithoutWhere(this.#props.queryNode),
});
}
/**
* Changes an `update` query into a `update top` query.
*
* `top` clause is only supported by some dialects like MS SQL Server.
*
* ### Examples
*
* Update the first row:
*
* ```ts
* await db.updateTable('person')
* .top(1)
* .set({ first_name: 'Foo' })
* .where('age', '>', 18)
* .executeTakeFirstOrThrow()
* ```
*
* The generated SQL (MS SQL Server):
*
* ```sql
* update top(1) "person" set "first_name" = @1 where "age" > @2
* ```
*
* Update the 50% first rows:
*
* ```ts
* await db.updateTable('person')
* .top(50, 'percent')
* .set({ first_name: 'Foo' })
* .where('age', '>', 18)
* .executeTakeFirstOrThrow()
* ```
*
* The generated SQL (MS SQL Server):
*
* ```sql
* update top(50) percent "person" set "first_name" = @1 where "age" > @2
* ```
*/
top(expression, modifiers) {
return new UpdateQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithTop(this.#props.queryNode, (0, top_parser_js_1.parseTop)(expression, modifiers)),
});
}
from(from) {
return new UpdateQueryBuilder({
...this.#props,
queryNode: update_query_node_js_1.UpdateQueryNode.cloneWithFromItems(this.#props.queryNode, (0, table_parser_js_1.parseTableExpressionOrList)(from)),
});
}
innerJoin(...args) {
return this.#join('InnerJoin', args);
}
leftJoin(...args) {
return this.#join('LeftJoin', args);
}
rightJoin(...args) {
return this.#join('RightJoin', args);
}
fullJoin(...args) {
return this.#join('FullJoin', args);
}
#join(joinType, args) {
return new UpdateQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithJoin(this.#props.queryNode, (0, join_parser_js_1.parseJoin)(joinType, args)),
});
}
orderBy(...args) {
return new UpdateQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithOrderByItems(this.#props.queryNode, (0, order_by_parser_js_1.parseOrderBy)(args)),
});
}
clearOrderBy() {
return new UpdateQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithoutOrderBy(this.#props.queryNode),
});
}
/**
* Adds a limit clause to the update query for supported databases, such as MySQL.
*
* ### Examples
*
* Update the first 2 rows in the 'person' table:
*
* ```ts
* await db
* .updateTable('person')
* .set({ first_name: 'Foo' })
* .limit(2)
* .execute()
* ```
*
* The generated SQL (MySQL):
*
* ```sql
* update `person` set `first_name` = ? limit ?
* ```
*/
limit(limit) {
return new UpdateQueryBuilder({
...this.#props,
queryNode: update_query_node_js_1.UpdateQueryNode.cloneWithLimit(this.#props.queryNode, limit_node_js_1.LimitNode.create((0, value_parser_js_1.parseValueExpression)(limit))),
});
}
set(...args) {
return new UpdateQueryBuilder({
...this.#props,
queryNode: update_query_node_js_1.UpdateQueryNode.cloneWithUpdates(this.#props.queryNode, (0, update_set_parser_js_1.parseUpdate)(...args)),
});
}
returning(selection) {
return new UpdateQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithReturning(this.#props.queryNode, (0, select_parser_js_1.parseSelectArg)(selection)),
});
}
returningAll(table) {
return new UpdateQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithReturning(this.#props.queryNode, (0, select_parser_js_1.parseSelectAll)(table)),
});
}
output(args) {
return new UpdateQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithOutput(this.#props.queryNode, (0, select_parser_js_1.parseSelectArg)(args)),
});
}
outputAll(table) {
return new UpdateQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithOutput(this.#props.queryNode, (0, select_parser_js_1.parseSelectAll)(table)),
});
}
/**
* This can be used to add any additional SQL to the end of the query.
*
* ### Examples
*
* ```ts
* import { sql } from 'kysely'
*
* await db.updateTable('person')
* .set({ age: 39 })
* .where('first_name', '=', 'John')
* .modifyEnd(sql.raw('-- This is a comment'))
* .execute()
* ```
*
* The generated SQL (MySQL):
*
* ```sql
* update `person`
* set `age` = 39
* where `first_name` = "John" -- This is a comment
* ```
*/
modifyEnd(modifier) {
return new UpdateQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithEndModifier(this.#props.queryNode, modifier.toOperationNode()),
});
}
/**
* Clears all `returning` clauses from the query.
*
* ### Examples
*
* ```ts
* db.updateTable('person')
* .returningAll()
* .set({ age: 39 })
* .where('first_name', '=', 'John')
* .clearReturning()
* ```
*
* The generated SQL(PostgreSQL):
*
* ```sql
* update "person" set "age" = 39 where "first_name" = "John"
* ```
*/
clearReturning() {
return new UpdateQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithoutReturning(this.#props.queryNode),
});
}
/**
* Simply calls the provided function passing `this` as the only argument. `$call` returns
* what the provided function returns.
*
* If you want to conditionally call a method on `this`, see
* the {@link $if} method.
*
* ### Examples
*
* The next example uses a helper function `log` to log a query:
*
* ```ts
* import type { Compilable } from 'kysely'
* import type { PersonUpdate } from 'type-editor' // imaginary module
*
* function log<T extends Compilable>(qb: T): T {
* console.log(qb.compile())
* return qb
* }
*
* const values = {
* first_name: 'John',
* } satisfies PersonUpdate
*
* db.updateTable('person')
* .set(values)
* .$call(log)
* .execute()
* ```
*/
$call(func) {
return func(this);
}
/**
* Call `func(this)` if `condition` is true.
*
* This method is especially handy with optional selects. Any `returning` or `returningAll`
* method calls add columns as optional fields to the output type when called inside
* the `func` callback. This is because we can't know if those selections were actually
* made before running the code.
*
* You can also call any other methods inside the callback.
*
* ### Examples
*
* ```ts
* import type { PersonUpdate } from 'type-editor' // imaginary module
*
* async function updatePerson(id: number, updates: PersonUpdate, returnLastName: boolean) {
* return await db
* .updateTable('person')
* .set(updates)
* .where('id', '=', id)
* .returning(['id', 'first_name'])
* .$if(returnLastName, (qb) => qb.returning('last_name'))
* .executeTakeFirstOrThrow()
* }
* ```
*
* Any selections added inside the `if` callback will be added as optional fields to the
* output type since we can't know if the selections were actually made before running
* the code. In the example above the return type of the `updatePerson` function is:
*
* ```ts
* Promise<{
* id: number
* first_name: string
* last_name?: string
* }>
* ```
*/
$if(condition, func) {
if (condition) {
return func(this);
}
return new UpdateQueryBuilder({
...this.#props,
});
}
/**
* Change the output type of the query.
*
* This method call doesn't change the SQL in any way. This methods simply
* returns a copy of this `UpdateQueryBuilder` with a new output type.
*/
$castTo() {
return new UpdateQueryBuilder(this.#props);
}
/**
* Narrows (parts of) the output type of the query.
*
* Kysely tries to be as type-safe as possible, but in some cases we have to make
* compromises for better maintainability and compilation performance. At present,
* Kysely doesn't narrow the output type of the query based on {@link set} input
* when using {@link where} and/or {@link returning} or {@link returningAll}.
*
* This utility method is very useful for these situations, as it removes unncessary
* runtime assertion/guard code. Its input type is limited to the output type
* of the query, so you can't add a column that doesn't exist, or change a column's
* type to something that doesn't exist in its union type.
*
* ### Examples
*
* Turn this code:
*
* ```ts
* import type { Person } from 'type-editor' // imaginary module
*
* const id = 1
* const now = new Date().toISOString()
*
* const person = await db.updateTable('person')
* .set({ deleted_at: now })
* .where('id', '=', id)
* .where('nullable_column', 'is not', null)
* .returningAll()
* .executeTakeFirstOrThrow()
*
* if (isWithNoNullValue(person)) {
* functionThatExpectsPersonWithNonNullValue(person)
* }
*
* function isWithNoNullValue(person: Person): person is Person & { nullable_column: string } {
* return person.nullable_column != null
* }
* ```
*
* Into this:
*
* ```ts
* import type { NotNull } from 'kysely'
*
* const id = 1
* const now = new Date().toISOString()
*
* const person = await db.updateTable('person')
* .set({ deleted_at: now })
* .where('id', '=', id)
* .where('nullable_column', 'is not', null)
* .returningAll()
* .$narrowType<{ deleted_at: Date; nullable_column: NotNull }>()
* .executeTakeFirstOrThrow()
*
* functionThatExpectsPersonWithNonNullValue(person)
* ```
*/
$narrowType() {
return new UpdateQueryBuilder(this.#props);
}
/**
* Asserts that query's output row type equals the given type `T`.
*
* This method can be used to simplify excessively complex types to make TypeScript happy
* and much faster.
*
* Kysely uses complex type magic to achieve its type safety. This complexity is sometimes too much
* for TypeScript and you get errors like this:
*
* ```
* error TS2589: Type instantiation is excessively deep and possibly infinite.
* ```
*
* In these case you can often use this method to help TypeScript a little bit. When you use this
* method to assert the output type of a query, Kysely can drop the complex output type that
* consists of multiple nested helper types and replace it with the simple asserted type.
*
* Using this method doesn't reduce type safety at all. You have to pass in a type that is
* structurally equal to the current type.
*
* ### Examples
*
* ```ts
* import type { PersonUpdate, PetUpdate, Species } from 'type-editor' // imaginary module
*
* const person = {
* id: 1,
* gender: 'other',
* } satisfies PersonUpdate
*
* const pet = {
* name: 'Fluffy',
* } satisfies PetUpdate
*
* const result = await db
* .with('updated_person', (qb) => qb
* .updateTable('person')
* .set(person)
* .where('id', '=', person.id)
* .returning('first_name')
* .$assertType<{ first_name: string }>()
* )
* .with('updated_pet', (qb) => qb
* .updateTable('pet')
* .set(pet)
* .where('owner_id', '=', person.id)
* .returning(['name as pet_name', 'species'])
* .$assertType<{ pet_name: string, species: Species }>()
* )
* .selectFrom(['updated_person', 'updated_pet'])
* .selectAll()
* .executeTakeFirstOrThrow()
* ```
*/
$assertType() {
return new UpdateQueryBuilder(this.#props);
}
/**
* Returns a copy of this UpdateQueryBuilder instance with the given plugin installed.
*/
withPlugin(plugin) {
return new UpdateQueryBuilder({
...this.#props,
executor: this.#props.executor.withPlugin(plugin),
});
}
toOperationNode() {
return this.#props.executor.transformQuery(this.#props.queryNode, this.#props.queryId);
}
compile() {
return this.#props.executor.compileQuery(this.toOperationNode(), this.#props.queryId);
}
/**
* Executes the query and returns an array of rows.
*
* Also see the {@link executeTakeFirst} and {@link executeTakeFirstOrThrow} methods.
*/
async execute() {
const compiledQuery = this.compile();
const result = await this.#props.executor.executeQuery(compiledQuery);
const { adapter } = this.#props.executor;
const query = compiledQuery.query;
if ((query.returning && adapter.supportsReturning) ||
(query.output && adapter.supportsOutput)) {
return result.rows;
}
return [
new update_result_js_1.UpdateResult(result.numAffectedRows ?? BigInt(0), result.numChangedRows),
];
}
/**
* Executes the query and returns the first result or undefined if
* the query returned no result.
*/
async executeTakeFirst() {
const [result] = await this.execute();
return result;
}
/**
* Executes the query and returns the first result or throws if
* the query returned no result.
*
* By default an instance of {@link NoResultError} is thrown, but you can
* provide a custom error class, or callback as the only argument to throw a different
* error.
*/
async executeTakeFirstOrThrow(errorConstructor = no_result_error_js_1.NoResultError) {
const result = await this.executeTakeFirst();
if (result === undefined) {
const error = (0, no_result_error_js_1.isNoResultErrorConstructor)(errorConstructor)
? new errorConstructor(this.toOperationNode())
: errorConstructor(this.toOperationNode());
throw error;
}
return result;
}
async *stream(chunkSize = 100) {
const compiledQuery = this.compile();
const stream = this.#props.executor.stream(compiledQuery, chunkSize);
for await (const item of stream) {
yield* item.rows;
}
}
async explain(format, options) {
const builder = new UpdateQueryBuilder({
...this.#props,
queryNode: query_node_js_1.QueryNode.cloneWithExplain(this.#props.queryNode, format, options),
});
return await builder.execute();
}
}
exports.UpdateQueryBuilder = UpdateQueryBuilder;

View File

@@ -0,0 +1,14 @@
export declare class UpdateResult {
/**
* The number of rows the update query updated (even if not changed).
*/
readonly numUpdatedRows: bigint;
/**
* The number of rows the update query changed.
*
* This is **optional** and only supported in dialects such as MySQL.
* You would probably use {@link numUpdatedRows} in most cases.
*/
readonly numChangedRows?: bigint;
constructor(numUpdatedRows: bigint, numChangedRows: bigint | undefined);
}

View File

@@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UpdateResult = void 0;
class UpdateResult {
/**
* The number of rows the update query updated (even if not changed).
*/
numUpdatedRows;
/**
* The number of rows the update query changed.
*
* This is **optional** and only supported in dialects such as MySQL.
* You would probably use {@link numUpdatedRows} in most cases.
*/
numChangedRows;
constructor(numUpdatedRows, numChangedRows) {
this.numUpdatedRows = numUpdatedRows;
this.numChangedRows = numChangedRows;
}
}
exports.UpdateResult = UpdateResult;

View File

@@ -0,0 +1,382 @@
import type { ComparisonOperatorExpression, OperandValueExpressionOrList } from '../parser/binary-operation-parser.js';
import type { ReferenceExpression } from '../parser/reference-parser.js';
import type { SqlBool } from '../util/type-utils.js';
import type { ExpressionOrFactory } from '../parser/expression-parser.js';
export interface WhereInterface<DB, TB extends keyof DB> {
/**
* Adds a `where` expression to the query.
*
* Calling this method multiple times will combine the expressions using `and`.
*
* Also see {@link whereRef}
*
* ### Examples
*
* <!-- siteExample("where", "Simple where clause", 10) -->
*
* `where` method calls are combined with `AND`:
*
* ```ts
* const person = await db
* .selectFrom('person')
* .selectAll()
* .where('first_name', '=', 'Jennifer')
* .where('age', '>', 40)
* .executeTakeFirst()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select * from "person" where "first_name" = $1 and "age" > $2
* ```
*
* Operator can be any supported operator or if the typings don't support it
* you can always use:
*
* ```ts
* import { sql } from 'kysely'
*
* sql`your operator`
* ```
*
* <!-- siteExample("where", "Where in", 20) -->
*
* Find multiple items using a list of identifiers:
*
* ```ts
* const persons = await db
* .selectFrom('person')
* .selectAll()
* .where('id', 'in', [1, 2, 3])
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select * from "person" where "id" in ($1, $2, $3)
* ```
*
* <!-- siteExample("where", "Object filter", 30) -->
*
* You can use the `and` function to create a simple equality
* filter using an object
*
* ```ts
* const persons = await db
* .selectFrom('person')
* .selectAll()
* .where((eb) => eb.and({
* first_name: 'Jennifer',
* last_name: eb.ref('first_name')
* }))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select *
* from "person"
* where (
* "first_name" = $1
* and "last_name" = "first_name"
* )
* ```
*
* <!-- siteExample("where", "OR where", 40) -->
*
* To combine conditions using `OR`, you can use the expression builder.
* There are two ways to create `OR` expressions. Both are shown in this
* example:
*
* ```ts
* const persons = await db
* .selectFrom('person')
* .selectAll()
* // 1. Using the `or` method on the expression builder:
* .where((eb) => eb.or([
* eb('first_name', '=', 'Jennifer'),
* eb('first_name', '=', 'Sylvester')
* ]))
* // 2. Chaining expressions using the `or` method on the
* // created expressions:
* .where((eb) =>
* eb('last_name', '=', 'Aniston').or('last_name', '=', 'Stallone')
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select *
* from "person"
* where (
* ("first_name" = $1 or "first_name" = $2)
* and
* ("last_name" = $3 or "last_name" = $4)
* )
* ```
*
* <!-- siteExample("where", "Conditional where calls", 50) -->
*
* You can add expressions conditionally like this:
*
* ```ts
* import { Expression, SqlBool } from 'kysely'
*
* const firstName: string | undefined = 'Jennifer'
* const lastName: string | undefined = 'Aniston'
* const under18 = true
* const over60 = true
*
* let query = db
* .selectFrom('person')
* .selectAll()
*
* if (firstName) {
* // The query builder is immutable. Remember to reassign
* // the result back to the query variable.
* query = query.where('first_name', '=', firstName)
* }
*
* if (lastName) {
* query = query.where('last_name', '=', lastName)
* }
*
* if (under18 || over60) {
* // Conditional OR expressions can be added like this.
* query = query.where((eb) => {
* const ors: Expression<SqlBool>[] = []
*
* if (under18) {
* ors.push(eb('age', '<', 18))
* }
*
* if (over60) {
* ors.push(eb('age', '>', 60))
* }
*
* return eb.or(ors)
* })
* }
*
* const persons = await query.execute()
* ```
*
* Both the first and third argument can also be arbitrary expressions like
* subqueries. An expression can defined by passing a function and calling
* the methods of the {@link ExpressionBuilder} passed to the callback:
*
* ```ts
* const persons = await db
* .selectFrom('person')
* .selectAll()
* .where(
* (qb) => qb.selectFrom('pet')
* .select('pet.name')
* .whereRef('pet.owner_id', '=', 'person.id')
* .limit(1),
* '=',
* 'Fluffy'
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select *
* from "person"
* where (
* select "pet"."name"
* from "pet"
* where "pet"."owner_id" = "person"."id"
* limit $1
* ) = $2
* ```
*
* A `where in` query can be built by using the `in` operator and an array
* of values. The values in the array can also be expressions:
*
* ```ts
* const persons = await db
* .selectFrom('person')
* .selectAll()
* .where('person.id', 'in', [100, 200, 300])
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select * from "person" where "id" in ($1, $2, $3)
* ```
*
* <!-- siteExample("where", "Complex where clause", 60) -->
*
* For complex `where` expressions you can pass in a single callback and
* use the `ExpressionBuilder` to build your expression:
*
* ```ts
* const firstName = 'Jennifer'
* const maxAge = 60
*
* const persons = await db
* .selectFrom('person')
* .selectAll('person')
* .where(({ eb, or, and, not, exists, selectFrom }) => and([
* or([
* eb('first_name', '=', firstName),
* eb('age', '<', maxAge)
* ]),
* not(exists(
* selectFrom('pet')
* .select('pet.id')
* .whereRef('pet.owner_id', '=', 'person.id')
* ))
* ]))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "person".*
* from "person"
* where (
* (
* "first_name" = $1
* or "age" < $2
* )
* and not exists (
* select "pet"."id" from "pet" where "pet"."owner_id" = "person"."id"
* )
* )
* ```
*
* If everything else fails, you can always use the {@link sql} tag
* as any of the arguments, including the operator:
*
* ```ts
* import { sql } from 'kysely'
*
* const persons = await db
* .selectFrom('person')
* .selectAll()
* .where(
* sql<string>`coalesce(first_name, last_name)`,
* 'like',
* '%' + name + '%',
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select * from "person"
* where coalesce(first_name, last_name) like $1
* ```
*
* In all examples above the columns were known at compile time
* (except for the raw {@link sql} expressions). By default kysely only
* allows you to refer to columns that exist in the database **and**
* can be referred to in the current query and context.
*
* Sometimes you may want to refer to columns that come from the user
* input and thus are not available at compile time.
*
* You have two options, the {@link sql} tag or `db.dynamic`. The example below
* uses both:
*
* ```ts
* import { sql } from 'kysely'
* const { ref } = db.dynamic
*
* const columnFromUserInput: string = 'id'
*
* const persons = await db
* .selectFrom('person')
* .selectAll()
* .where(ref(columnFromUserInput), '=', 1)
* .where(sql.id(columnFromUserInput), '=', 2)
* .execute()
* ```
*/
where<RE extends ReferenceExpression<DB, TB>, VE extends OperandValueExpressionOrList<DB, TB, RE>>(lhs: RE, op: ComparisonOperatorExpression, rhs: VE): WhereInterface<DB, TB>;
where<E extends ExpressionOrFactory<DB, TB, SqlBool>>(expression: E): WhereInterface<DB, TB>;
/**
* Adds a `where` clause where both sides of the operator are references
* to columns.
*
* The normal `where` method treats the right hand side argument as a
* value by default. `whereRef` treats it as a column reference. This method is
* expecially useful with joins and correlated subqueries.
*
* ### Examples
*
* Usage with a join:
*
* ```ts
* db.selectFrom(['person', 'pet'])
* .selectAll()
* .whereRef('person.first_name', '=', 'pet.name')
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select * from "person", "pet" where "person"."first_name" = "pet"."name"
* ```
*
* Usage in a subquery:
*
* ```ts
* const persons = await db
* .selectFrom('person')
* .selectAll('person')
* .select((eb) => eb
* .selectFrom('pet')
* .select('name')
* .whereRef('pet.owner_id', '=', 'person.id')
* .limit(1)
* .as('pet_name')
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "person".*, (
* select "name"
* from "pet"
* where "pet"."owner_id" = "person"."id"
* limit $1
* ) as "pet_name"
* from "person"
*/
whereRef<LRE extends ReferenceExpression<DB, TB>, RRE extends ReferenceExpression<DB, TB>>(lhs: LRE, op: ComparisonOperatorExpression, rhs: RRE): WhereInterface<DB, TB>;
/**
* Clears all where expressions from the query.
*
* ### Examples
*
* ```ts
* db.selectFrom('person')
* .selectAll()
* .where('id','=',42)
* .clearWhere()
* ```
*
* The generated SQL(PostgreSQL):
*
* ```sql
* select * from "person"
* ```
*/
clearWhere(): WhereInterface<DB, TB>;
}

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });