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,920 @@
import { type SelectQueryBuilder } from '../query-builder/select-query-builder.js';
import { type TableExpressionOrList } from '../parser/table-parser.js';
import { type FunctionModule } from '../query-builder/function-module.js';
import { type ExtractTypeFromReferenceExpression, type ReferenceExpression, type SimpleReferenceExpression, type StringReference } from '../parser/reference-parser.js';
import type { QueryExecutor } from '../query-executor/query-executor.js';
import { type BinaryOperatorExpression, type FilterObject, type OperandValueExpression, type OperandValueExpressionOrList } from '../parser/binary-operation-parser.js';
import type { Expression } from './expression.js';
import { ExpressionWrapper } from './expression-wrapper.js';
import { type ComparisonOperator, type JSONOperatorWith$, type UnaryOperator } from '../operation-node/operator-node.js';
import type { IsNever, SqlBool } from '../util/type-utils.js';
import { type ExtractTypeFromValueExpression } from '../parser/value-parser.js';
import { CaseBuilder } from '../query-builder/case-builder.js';
import { JSONPathBuilder } from '../query-builder/json-path-builder.js';
import type { OperandExpression } from '../parser/expression-parser.js';
import type { RefTuple2, RefTuple3, RefTuple4, RefTuple5, ValTuple2, ValTuple3, ValTuple4, ValTuple5 } from '../parser/tuple-parser.js';
import type { Selectable } from '../util/column-type.js';
import type { KyselyTypeError } from '../util/type-error.js';
import { type DataTypeExpression } from '../parser/data-type-parser.js';
import type { SelectFrom } from '../parser/select-from-parser.js';
export interface ExpressionBuilder<DB, TB extends keyof DB> {
/**
* Creates a binary expression.
*
* This function returns an {@link Expression} and can be used pretty much anywhere.
* See the examples for a couple of possible use cases.
*
* ### Examples
*
* A simple comparison:
*
* ```ts
* const result = await db.selectFrom('person')
* .selectAll()
* .where((eb) => eb('first_name', '=', 'Jennifer'))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select *
* from "person"
* where "first_name" = $1
* ```
*
* By default the third argument is interpreted as a value. To pass in
* a column reference, you can use {@link ref}:
*
* ```ts
* const result = await db.selectFrom('person')
* .selectAll()
* .where((eb) => eb('first_name', '=', eb.ref('last_name')))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select *
* from "person"
* where "first_name" = "last_name"
* ```
*
* In the following example `eb` is used to increment an integer column:
*
* ```ts
* await db.updateTable('person')
* .set((eb) => ({
* age: eb('age', '+', 1)
* }))
* .where('id', '=', 3)
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* update "person"
* set "age" = "age" + $1
* where "id" = $2
* ```
*
* As always, expressions can be nested. Both the first and the third argument
* can be any expression:
*
* ```ts
* const result = await db.selectFrom('person')
* .selectAll()
* .where((eb) => eb(
* eb.fn<string>('lower', ['first_name']),
* 'in',
* eb.selectFrom('pet')
* .select('pet.name')
* .where('pet.species', '=', 'cat')
* ))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select *
* from "person"
* where lower("first_name") in (
* select "pet"."name"
* from "pet"
* where "pet"."species" = $1
* )
* ```
*/
<RE extends ReferenceExpression<DB, TB>, OP extends BinaryOperatorExpression, VE extends OperandValueExpressionOrList<DB, TB, RE>>(lhs: RE, op: OP, rhs: VE): ExpressionWrapper<DB, TB, OP extends ComparisonOperator ? SqlBool : OP extends Expression<infer T> ? unknown extends T ? SqlBool : T : ExtractTypeFromReferenceExpression<DB, TB, RE>>;
/**
* Returns a copy of `this` expression builder, for destructuring purposes.
*
* ### Examples
*
* ```ts
* const result = await db.selectFrom('person')
* .where(({ eb, exists, selectFrom }) =>
* eb('first_name', '=', 'Jennifer').and(exists(
* selectFrom('pet').whereRef('owner_id', '=', 'person.id').select('pet.id')
* ))
* )
* .selectAll()
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select * from "person" where "first_name" = $1 and exists (
* select "pet.id" from "pet" where "owner_id" = "person.id"
* )
* ```
*/
get eb(): ExpressionBuilder<DB, TB>;
/**
* Returns a {@link FunctionModule} that can be used to write type safe function
* calls.
*
* The difference between this and {@link Kysely.fn} is that this one is more
* type safe. You can only refer to columns visible to the part of the query
* you are building. {@link Kysely.fn} allows you to refer to columns in any
* table of the database even if it doesn't produce valid SQL.
*
* ```ts
* const result = await db.selectFrom('person')
* .innerJoin('pet', 'pet.owner_id', 'person.id')
* .select((eb) => [
* 'person.id',
* eb.fn.count('pet.id').as('pet_count')
* ])
* .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"
* from "person"
* inner join "pet" on "pet"."owner_id" = "person"."id"
* group by "person"."id"
* having count("pet"."id") > $1
* ```
*/
get fn(): FunctionModule<DB, TB>;
/**
* Creates a subquery.
*
* The query builder returned by this method is typed in a way that you can refer to
* all tables of the parent query in addition to the subquery's tables.
*
* This method accepts all the same inputs as {@link QueryCreator.selectFrom}.
*
* ### Examples
*
* This example shows that you can refer to both `pet.owner_id` and `person.id`
* columns from the subquery. This is needed to be able to create correlated
* subqueries:
*
* ```ts
* const result = await db.selectFrom('pet')
* .select((eb) => [
* 'pet.name',
* eb.selectFrom('person')
* .whereRef('person.id', '=', 'pet.owner_id')
* .select('person.first_name')
* .as('owner_name')
* ])
* .execute()
*
* console.log(result[0]?.owner_name)
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select
* "pet"."name",
* ( select "person"."first_name"
* from "person"
* where "person"."id" = "pet"."owner_id"
* ) as "owner_name"
* from "pet"
* ```
*
* You can use a normal query in place of `(qb) => qb.selectFrom(...)` but in
* that case Kysely typings wouldn't allow you to reference `pet.owner_id`
* because `pet` is not joined to that query.
*/
selectFrom<TE extends TableExpressionOrList<DB, TB>>(from: TE): SelectFrom<DB, TB, TE>;
/**
* Creates a `case` statement/operator.
*
* ### Examples
*
* Kitchen sink example with 2 flavors of `case` operator:
*
* ```ts
* const { title, name } = await db
* .selectFrom('person')
* .where('id', '=', 123)
* .select((eb) => [
* eb.fn.coalesce('last_name', 'first_name').as('name'),
* eb
* .case()
* .when('gender', '=', 'male')
* .then('Mr.')
* .when('gender', '=', 'female')
* .then(
* eb
* .case('marital_status')
* .when('single')
* .then('Ms.')
* .else('Mrs.')
* .end()
* )
* .end()
* .as('title'),
* ])
* .executeTakeFirstOrThrow()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select
* coalesce("last_name", "first_name") as "name",
* case
* when "gender" = $1 then $2
* when "gender" = $3 then
* case "marital_status"
* when $4 then $5
* else $6
* end
* end as "title"
* from "person"
* where "id" = $7
* ```
*/
case(): CaseBuilder<DB, TB>;
case<C extends SimpleReferenceExpression<DB, TB>>(column: C): CaseBuilder<DB, TB, ExtractTypeFromReferenceExpression<DB, TB, C>>;
case<E extends Expression<any>>(expression: E): CaseBuilder<DB, TB, ExtractTypeFromValueExpression<E>>;
/**
* This method can be used to reference columns within the query's context. For
* a non-type-safe version of this method see {@link sql}'s version.
*
* Additionally, this method can be used to reference nested JSON properties or
* array elements. See {@link JSONPathBuilder} for more information. For regular
* JSON path expressions you can use {@link jsonPath}.
*
* ### Examples
*
* By default the third argument of binary expressions is a value.
* This function can be used to pass in a column reference instead:
*
* ```ts
* const result = await db.selectFrom('person')
* .selectAll('person')
* .where((eb) => eb.or([
* eb('first_name', '=', eb.ref('last_name')),
* eb('first_name', '=', eb.ref('middle_name'))
* ]))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "person".*
* from "person"
* where "first_name" = "last_name" or "first_name" = "middle_name"
* ```
*
* 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
* await db.insertInto('person')
* .values({
* id: 3,
* first_name: 'Jennifer',
* last_name: 'Aniston',
* gender: 'female',
* })
* .onConflict((oc) => oc
* .column('id')
* .doUpdateSet(({ ref }) => ({
* first_name: ref('excluded.first_name'),
* last_name: ref('excluded.last_name'),
* gender: ref('excluded.gender'),
* }))
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* insert into "person" ("id", "first_name", "last_name", "gender")
* values ($1, $2, $3, $4)
* on conflict ("id") do update set
* "first_name" = "excluded"."first_name",
* "last_name" = "excluded"."last_name",
* "gender" = "excluded"."gender"
* ```
*
* In the next example we use `ref` in a raw sql expression. Unless you want
* to be as type-safe as possible, this is probably overkill:
*
* ```ts
* import { sql } from 'kysely'
*
* await db.updateTable('pet')
* .set((eb) => ({
* name: sql<string>`concat(${eb.ref('pet.name')}, ${' the animal'})`
* }))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* update "pet" set "name" = concat("pet"."name", $1)
* ```
*
* In the next example we use `ref` to reference a nested JSON property:
*
* ```ts
* const result = await db.selectFrom('person')
* .where(({ eb, ref }) => eb(
* ref('profile', '->').key('addresses').at(0).key('city'),
* '=',
* 'San Diego'
* ))
* .selectAll()
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select * from "person" where "profile"->'addresses'->0->'city' = $1
* ```
*
* You can also compile to a JSON path expression by using the `->$`or `->>$` operator:
*
* ```ts
* const result = await db.selectFrom('person')
* .select(({ ref }) =>
* ref('profile', '->$')
* .key('addresses')
* .at('last')
* .key('city')
* .as('current_city')
* )
* .execute()
* ```
*
* The generated SQL (MySQL):
*
* ```sql
* select `profile`->'$.addresses[last].city' as `current_city` from `person`
* ```
*/
ref<RE extends StringReference<DB, TB>>(reference: RE): ExpressionWrapper<DB, TB, ExtractTypeFromReferenceExpression<DB, TB, RE>>;
ref<RE extends StringReference<DB, TB>>(reference: RE, op: JSONOperatorWith$): JSONPathBuilder<ExtractTypeFromReferenceExpression<DB, TB, RE>>;
/**
* Creates a JSON path expression with provided column as root document (the $).
*
* For a JSON reference expression, see {@link ref}.
*
* ### Examples
*
* ```ts
* await db.updateTable('person')
* .set('profile', (eb) => eb.fn('json_set', [
* 'profile',
* eb.jsonPath<'profile'>().key('addresses').at('last').key('city'),
* eb.val('San Diego')
* ]))
* .where('id', '=', 3)
* .execute()
* ```
*
* The generated SQL (MySQL):
*
* ```sql
* update `person`
* set `profile` = json_set(`profile`, '$.addresses[last].city', $1)
* where `id` = $2
* ```
*/
jsonPath<$ extends StringReference<DB, TB> = never>(): IsNever<$> extends true ? KyselyTypeError<"You must provide a column reference as this method's $ generic"> : JSONPathBuilder<ExtractTypeFromReferenceExpression<DB, TB, $>>;
/**
* Creates a table reference.
*
* ### Examples
*
* ```ts
* import { sql } from 'kysely'
* import type { Pet } from 'type-editor' // imaginary module
*
* const result = await db.selectFrom('person')
* .innerJoin('pet', 'pet.owner_id', 'person.id')
* .select(eb => [
* 'person.id',
* sql<Pet[]>`jsonb_agg(${eb.table('pet')})`.as('pets')
* ])
* .groupBy('person.id')
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "person"."id", jsonb_agg("pet") as "pets"
* from "person"
* inner join "pet" on "pet"."owner_id" = "person"."id"
* group by "person"."id"
* ```
*
* If you need a column reference, use {@link ref}.
*/
table<T extends TB & string>(table: T): ExpressionWrapper<DB, TB, Selectable<DB[T]>>;
/**
* Returns a value expression.
*
* This can be used to pass in a value where a reference is taken by default.
*
* This function returns an {@link Expression} and can be used pretty much anywhere.
*
* ### Examples
*
* Binary expressions take a reference by default as the first argument. `val` could
* be used to pass in a value instead:
*
* ```ts
* const result = await db.selectFrom('person')
* .selectAll()
* .where((eb) => eb(
* eb.val('cat'),
* '=',
* eb.fn.any(
* eb.selectFrom('pet')
* .select('species')
* .whereRef('owner_id', '=', 'person.id')
* )
* ))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select *
* from "person"
* where $1 = any(
* select "species"
* from "pet"
* where "owner_id" = "person"."id"
* )
* ```
*/
val<VE>(value: VE): ExpressionWrapper<DB, TB, ExtractTypeFromValueExpression<VE>>;
/**
* Creates a tuple expression.
*
* This creates a tuple using column references by default. See {@link tuple}
* if you need to create value tuples.
*
* ### Examples
*
* ```ts
* const result = await db.selectFrom('person')
* .selectAll('person')
* .where(({ eb, refTuple, tuple }) => eb(
* refTuple('first_name', 'last_name'),
* 'in',
* [
* tuple('Jennifer', 'Aniston'),
* tuple('Sylvester', 'Stallone')
* ]
* ))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select
* "person".*
* from
* "person"
* where
* ("first_name", "last_name")
* in
* (
* ($1, $2),
* ($3, $4)
* )
* ```
*
* In the next example a reference tuple is compared to a subquery. Note that
* in this case you need to use the {@link @SelectQueryBuilder.$asTuple | $asTuple}
* function:
*
* ```ts
* const result = await db.selectFrom('person')
* .selectAll('person')
* .where(({ eb, refTuple, selectFrom }) => eb(
* refTuple('first_name', 'last_name'),
* 'in',
* selectFrom('pet')
* .select(['name', 'species'])
* .where('species', '!=', 'cat')
* .$asTuple('name', 'species')
* ))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select
* "person".*
* from
* "person"
* where
* ("first_name", "last_name")
* in
* (
* select "name", "species"
* from "pet"
* where "species" != $1
* )
* ```
*/
refTuple<R1 extends ReferenceExpression<DB, TB>, R2 extends ReferenceExpression<DB, TB>>(value1: R1, value2: R2): ExpressionWrapper<DB, TB, RefTuple2<DB, TB, R1, R2>>;
refTuple<R1 extends ReferenceExpression<DB, TB>, R2 extends ReferenceExpression<DB, TB>, R3 extends ReferenceExpression<DB, TB>>(value1: R1, value2: R2, value3: R3): ExpressionWrapper<DB, TB, RefTuple3<DB, TB, R1, R2, R3>>;
refTuple<R1 extends ReferenceExpression<DB, TB>, R2 extends ReferenceExpression<DB, TB>, R3 extends ReferenceExpression<DB, TB>, R4 extends ReferenceExpression<DB, TB>>(value1: R1, value2: R2, value3: R3, value4: R4): ExpressionWrapper<DB, TB, RefTuple4<DB, TB, R1, R2, R3, R4>>;
refTuple<R1 extends ReferenceExpression<DB, TB>, R2 extends ReferenceExpression<DB, TB>, R3 extends ReferenceExpression<DB, TB>, R4 extends ReferenceExpression<DB, TB>, R5 extends ReferenceExpression<DB, TB>>(value1: R1, value2: R2, value3: R3, value4: R4, value5: R5): ExpressionWrapper<DB, TB, RefTuple5<DB, TB, R1, R2, R3, R4, R5>>;
/**
* Creates a value tuple expression.
*
* This creates a tuple using values by default. See {@link refTuple} if you need to create
* tuples using column references.
*
* ### Examples
*
* ```ts
* const result = await db.selectFrom('person')
* .selectAll('person')
* .where(({ eb, refTuple, tuple }) => eb(
* refTuple('first_name', 'last_name'),
* 'in',
* [
* tuple('Jennifer', 'Aniston'),
* tuple('Sylvester', 'Stallone')
* ]
* ))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select
* "person".*
* from
* "person"
* where
* ("first_name", "last_name")
* in
* (
* ($1, $2),
* ($3, $4)
* )
* ```
*/
tuple<V1, V2>(value1: V1, value2: V2): ExpressionWrapper<DB, TB, ValTuple2<V1, V2>>;
tuple<V1, V2, V3>(value1: V1, value2: V2, value3: V3): ExpressionWrapper<DB, TB, ValTuple3<V1, V2, V3>>;
tuple<V1, V2, V3, V4>(value1: V1, value2: V2, value3: V3, value4: V4): ExpressionWrapper<DB, TB, ValTuple4<V1, V2, V3, V4>>;
tuple<V1, V2, V3, V4, V5>(value1: V1, value2: V2, value3: V3, value4: V4, value5: V5): ExpressionWrapper<DB, TB, ValTuple5<V1, V2, V3, V4, V5>>;
/**
* Returns a literal value expression.
*
* Just like `val` but creates a literal value that gets merged in the SQL.
* To prevent SQL injections, only `boolean`, `number` and `null` values
* are accepted. If you need `string` or other literals, use `sql.lit` instead.
*
* ### Examples
*
* ```ts
* const result = await db.selectFrom('person')
* .select((eb) => eb.lit(1).as('one'))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select 1 as "one" from "person"
* ```
*/
lit<VE extends number | boolean | null>(literal: VE): ExpressionWrapper<DB, TB, VE>;
/**
* Creates an unary expression.
*
* This function returns an {@link Expression} and can be used pretty much anywhere.
* See the examples for a couple of possible use cases.
*
* @see {@link not}, {@link exists} and {@link neg}.
*
* ### Examples
*
* ```ts
* const result = await db.selectFrom('person')
* .select((eb) => [
* 'first_name',
* eb.unary('-', 'age').as('negative_age')
* ])
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "first_name", -"age"
* from "person"
* ```
*/
unary<RE extends ReferenceExpression<DB, TB>>(op: UnaryOperator, expr: RE): ExpressionWrapper<DB, TB, ExtractTypeFromReferenceExpression<DB, TB, RE>>;
/**
* Creates a `not` operation.
*
* A shortcut for `unary('not', expr)`.
*
* @see {@link unary}
*/
not<RE extends ReferenceExpression<DB, TB>>(expr: RE): ExpressionWrapper<DB, TB, ExtractTypeFromReferenceExpression<DB, TB, RE>>;
/**
* Creates an `exists` operation.
*
* A shortcut for `unary('exists', expr)`.
*
* @see {@link unary}
*/
exists<RE extends ReferenceExpression<DB, TB>>(expr: RE): ExpressionWrapper<DB, TB, SqlBool>;
/**
* Creates a negation operation.
*
* A shortcut for `unary('-', expr)`.
*
* @see {@link unary}
*/
neg<RE extends ReferenceExpression<DB, TB>>(expr: RE): ExpressionWrapper<DB, TB, ExtractTypeFromReferenceExpression<DB, TB, RE>>;
/**
* Creates a `between` expression.
*
* ### Examples
*
* ```ts
* const result = await db.selectFrom('person')
* .selectAll()
* .where((eb) => eb.between('age', 40, 60))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select * from "person" where "age" between $1 and $2
* ```
*/
between<RE extends ReferenceExpression<DB, TB>, SE extends OperandValueExpression<DB, TB, RE>, EE extends OperandValueExpression<DB, TB, RE>>(expr: RE, start: SE, end: EE): ExpressionWrapper<DB, TB, SqlBool>;
/**
* Creates a `between symmetric` expression.
*
* ### Examples
*
* ```ts
* const result = await db.selectFrom('person')
* .selectAll()
* .where((eb) => eb.betweenSymmetric('age', 40, 60))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select * from "person" where "age" between symmetric $1 and $2
* ```
*/
betweenSymmetric<RE extends ReferenceExpression<DB, TB>, SE extends OperandValueExpression<DB, TB, RE>, EE extends OperandValueExpression<DB, TB, RE>>(expr: RE, start: SE, end: EE): ExpressionWrapper<DB, TB, SqlBool>;
/**
* Combines two or more expressions using the logical `and` operator.
*
* An empty array produces a `true` expression.
*
* This function returns an {@link Expression} and can be used pretty much anywhere.
* See the examples for a couple of possible use cases.
*
* ### Examples
*
* In this example we use `and` to create a `WHERE expr1 AND expr2 AND expr3`
* statement:
*
* ```ts
* const result = await db.selectFrom('person')
* .selectAll('person')
* .where((eb) => eb.and([
* eb('first_name', '=', 'Jennifer'),
* eb('first_name', '=', 'Arnold'),
* eb('first_name', '=', 'Sylvester')
* ]))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "person".*
* from "person"
* where (
* "first_name" = $1
* and "first_name" = $2
* and "first_name" = $3
* )
* ```
*
* Optionally you can use the simpler object notation if you only need
* equality comparisons:
*
* ```ts
* const result = await db.selectFrom('person')
* .selectAll('person')
* .where((eb) => eb.and({
* first_name: 'Jennifer',
* last_name: 'Aniston'
* }))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "person".*
* from "person"
* where (
* "first_name" = $1
* and "last_name" = $2
* )
* ```
*/
and<E extends OperandExpression<SqlBool>>(exprs: ReadonlyArray<E>): ExpressionWrapper<DB, TB, SqlBool>;
and<E extends Readonly<FilterObject<DB, TB>>>(exprs: E): ExpressionWrapper<DB, TB, SqlBool>;
/**
* Combines two or more expressions using the logical `or` operator.
*
* An empty array produces a `false` expression.
*
* This function returns an {@link Expression} and can be used pretty much anywhere.
* See the examples for a couple of possible use cases.
*
* ### Examples
*
* In this example we use `or` to create a `WHERE expr1 OR expr2 OR expr3`
* statement:
*
* ```ts
* const result = await db.selectFrom('person')
* .selectAll('person')
* .where((eb) => eb.or([
* eb('first_name', '=', 'Jennifer'),
* eb('first_name', '=', 'Arnold'),
* eb('first_name', '=', 'Sylvester')
* ]))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "person".*
* from "person"
* where (
* "first_name" = $1
* or "first_name" = $2
* or "first_name" = $3
* )
* ```
*
* Optionally you can use the simpler object notation if you only need
* equality comparisons:
*
* ```ts
* const result = await db.selectFrom('person')
* .selectAll('person')
* .where((eb) => eb.or({
* first_name: 'Jennifer',
* last_name: 'Aniston'
* }))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "person".*
* from "person"
* where (
* "first_name" = $1
* or "last_name" = $2
* )
* ```
*/
or<E extends OperandExpression<SqlBool>>(exprs: ReadonlyArray<E>): ExpressionWrapper<DB, TB, SqlBool>;
or<E extends Readonly<FilterObject<DB, TB>>>(exprs: E): ExpressionWrapper<DB, TB, SqlBool>;
/**
* Wraps the expression in parentheses.
*
* ### Examples
*
* ```ts
* const result = await db.selectFrom('person')
* .selectAll('person')
* .where((eb) => eb(eb.parens('age', '+', 1), '/', 100), '<', 0.1)
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "person".*
* from "person"
* where ("age" + $1) / $2 < $3
* ```
*
* You can also pass in any expression as the only argument:
*
* ```ts
* const result = await db.selectFrom('person')
* .selectAll('person')
* .where((eb) => eb.parens(
* eb('age', '=', 1).or('age', '=', 2)
* ).and(
* eb('first_name', '=', 'Jennifer').or('first_name', '=', 'Arnold')
* ))
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "person".*
* from "person"
* where ("age" = $1 or "age" = $2) and ("first_name" = $3 or "first_name" = $4)
* ```
*/
parens<RE extends ReferenceExpression<DB, TB>, OP extends BinaryOperatorExpression, VE extends OperandValueExpressionOrList<DB, TB, RE>>(lhs: RE, op: OP, rhs: VE): ExpressionWrapper<DB, TB, OP extends ComparisonOperator ? SqlBool : ExtractTypeFromReferenceExpression<DB, TB, RE>>;
parens<T>(expr: Expression<T>): ExpressionWrapper<DB, TB, T>;
/**
* Creates a `cast(expr as dataType)` expression.
*
* Since Kysely can't know the mapping between JavaScript and database types,
* you need to provide both explicitly.
*
* ### Examples
*
* ```ts
* const result = await db.selectFrom('person')
* .select((eb) => [
* 'id',
* 'first_name',
* eb.cast<number>('age', 'integer').as('age')
* ])
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select cast("age" as integer) as "age"
* from "person"
* ```
*/
cast<T, RE extends ReferenceExpression<DB, TB> = ReferenceExpression<DB, TB>>(expr: RE, dataType: DataTypeExpression): ExpressionWrapper<DB, TB, T>;
/**
* See {@link QueryCreator.withSchema}
*
* @deprecated Will be removed in kysely 0.25.0.
*/
withSchema(schema: string): ExpressionBuilder<DB, TB>;
}
export declare function createExpressionBuilder<DB, TB extends keyof DB>(executor?: QueryExecutor): ExpressionBuilder<DB, TB>;
export declare function expressionBuilder<DB, TB extends keyof DB>(_: SelectQueryBuilder<DB, TB, any>): ExpressionBuilder<DB, TB>;
export declare function expressionBuilder<DB, TB extends keyof DB = never>(): ExpressionBuilder<DB, TB>;

View File

@@ -0,0 +1,125 @@
/// <reference types="./expression-builder.d.ts" />
import { createSelectQueryBuilder, } from '../query-builder/select-query-builder.js';
import { SelectQueryNode } from '../operation-node/select-query-node.js';
import { parseTableExpressionOrList, parseTable, } from '../parser/table-parser.js';
import { WithSchemaPlugin } from '../plugin/with-schema/with-schema-plugin.js';
import { createQueryId } from '../util/query-id.js';
import { createFunctionModule, } from '../query-builder/function-module.js';
import { parseJSONReference, parseReferenceExpression, parseStringReference, } from '../parser/reference-parser.js';
import { parseFilterList, parseFilterObject, parseValueBinaryOperation, parseValueBinaryOperationOrExpression, } from '../parser/binary-operation-parser.js';
import { ParensNode } from '../operation-node/parens-node.js';
import { ExpressionWrapper } from './expression-wrapper.js';
import { OperatorNode, } from '../operation-node/operator-node.js';
import { parseUnaryOperation } from '../parser/unary-operation-parser.js';
import { parseSafeImmediateValue, parseValueExpression, } from '../parser/value-parser.js';
import { NOOP_QUERY_EXECUTOR } from '../query-executor/noop-query-executor.js';
import { CaseBuilder } from '../query-builder/case-builder.js';
import { CaseNode } from '../operation-node/case-node.js';
import { isReadonlyArray, isUndefined } from '../util/object-utils.js';
import { JSONPathBuilder } from '../query-builder/json-path-builder.js';
import { BinaryOperationNode } from '../operation-node/binary-operation-node.js';
import { AndNode } from '../operation-node/and-node.js';
import { TupleNode } from '../operation-node/tuple-node.js';
import { JSONPathNode } from '../operation-node/json-path-node.js';
import { parseDataTypeExpression, } from '../parser/data-type-parser.js';
import { CastNode } from '../operation-node/cast-node.js';
export function createExpressionBuilder(executor = NOOP_QUERY_EXECUTOR) {
function binary(lhs, op, rhs) {
return new ExpressionWrapper(parseValueBinaryOperation(lhs, op, rhs));
}
function unary(op, expr) {
return new ExpressionWrapper(parseUnaryOperation(op, expr));
}
const eb = Object.assign(binary, {
fn: undefined,
eb: undefined,
selectFrom(table) {
return createSelectQueryBuilder({
queryId: createQueryId(),
executor,
queryNode: SelectQueryNode.createFrom(parseTableExpressionOrList(table)),
});
},
case(reference) {
return new CaseBuilder({
node: CaseNode.create(isUndefined(reference)
? undefined
: parseReferenceExpression(reference)),
});
},
ref(reference, op) {
if (isUndefined(op)) {
return new ExpressionWrapper(parseStringReference(reference));
}
return new JSONPathBuilder(parseJSONReference(reference, op));
},
jsonPath() {
return new JSONPathBuilder(JSONPathNode.create());
},
table(table) {
return new ExpressionWrapper(parseTable(table));
},
val(value) {
return new ExpressionWrapper(parseValueExpression(value));
},
refTuple(...values) {
return new ExpressionWrapper(TupleNode.create(values.map(parseReferenceExpression)));
},
tuple(...values) {
return new ExpressionWrapper(TupleNode.create(values.map(parseValueExpression)));
},
lit(value) {
return new ExpressionWrapper(parseSafeImmediateValue(value));
},
unary,
not(expr) {
return unary('not', expr);
},
exists(expr) {
return unary('exists', expr);
},
neg(expr) {
return unary('-', expr);
},
between(expr, start, end) {
return new ExpressionWrapper(BinaryOperationNode.create(parseReferenceExpression(expr), OperatorNode.create('between'), AndNode.create(parseValueExpression(start), parseValueExpression(end))));
},
betweenSymmetric(expr, start, end) {
return new ExpressionWrapper(BinaryOperationNode.create(parseReferenceExpression(expr), OperatorNode.create('between symmetric'), AndNode.create(parseValueExpression(start), parseValueExpression(end))));
},
and(exprs) {
if (isReadonlyArray(exprs)) {
return new ExpressionWrapper(parseFilterList(exprs, 'and'));
}
return new ExpressionWrapper(parseFilterObject(exprs, 'and'));
},
or(exprs) {
if (isReadonlyArray(exprs)) {
return new ExpressionWrapper(parseFilterList(exprs, 'or'));
}
return new ExpressionWrapper(parseFilterObject(exprs, 'or'));
},
parens(...args) {
const node = parseValueBinaryOperationOrExpression(args);
if (ParensNode.is(node)) {
// No double wrapping.
return new ExpressionWrapper(node);
}
else {
return new ExpressionWrapper(ParensNode.create(node));
}
},
cast(expr, dataType) {
return new ExpressionWrapper(CastNode.create(parseReferenceExpression(expr), parseDataTypeExpression(dataType)));
},
withSchema(schema) {
return createExpressionBuilder(executor.withPluginAtFront(new WithSchemaPlugin(schema)));
},
});
eb.fn = createFunctionModule();
eb.eb = eb;
return eb;
}
export function expressionBuilder(_) {
return createExpressionBuilder();
}

View File

@@ -0,0 +1,631 @@
import { AliasNode } from '../operation-node/alias-node.js';
import { AndNode } from '../operation-node/and-node.js';
import type { OperationNode } from '../operation-node/operation-node.js';
import { OrNode } from '../operation-node/or-node.js';
import { ParensNode } from '../operation-node/parens-node.js';
import { type ComparisonOperatorExpression, type OperandValueExpressionOrList } from '../parser/binary-operation-parser.js';
import type { OperandExpression } from '../parser/expression-parser.js';
import type { ReferenceExpression } from '../parser/reference-parser.js';
import type { KyselyTypeError } from '../util/type-error.js';
import type { SqlBool } from '../util/type-utils.js';
import type { AliasableExpression, AliasedExpression, Expression } from './expression.js';
export declare class ExpressionWrapper<DB, TB extends keyof DB, T> implements AliasableExpression<T> {
#private;
constructor(node: OperationNode);
/** @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(): T | undefined;
/**
* Returns an aliased version of the expression.
*
* ### Examples
*
* 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<T, 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<T, A>;
/**
* Combines `this` and another expression using `OR`.
*
* Also see {@link ExpressionBuilder.or}
*
* ### Examples
*
* ```ts
* const result = await db.selectFrom('person')
* .selectAll()
* .where(eb => eb('first_name', '=', 'Jennifer')
* .or('first_name', '=', 'Arnold')
* .or('first_name', '=', 'Sylvester')
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select *
* from "person"
* where (
* "first_name" = $1
* or "first_name" = $2
* or "first_name" = $3
* )
* ```
*
* You can also pass any expression as the only argument to
* this method:
*
* ```ts
* const result = await db.selectFrom('person')
* .selectAll()
* .where(eb => eb('first_name', '=', 'Jennifer')
* .or(eb('first_name', '=', 'Sylvester').and('last_name', '=', 'Stallone'))
* .or(eb.exists(
* eb.selectFrom('pet')
* .select('id')
* .whereRef('pet.owner_id', '=', 'person.id')
* ))
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select *
* from "person"
* where (
* "first_name" = $1
* or ("first_name" = $2 and "last_name" = $3)
* or exists (
* select "id"
* from "pet"
* where "pet"."owner_id" = "person"."id"
* )
* )
* ```
*/
or<RE extends ReferenceExpression<DB, TB>, VE extends OperandValueExpressionOrList<DB, TB, RE>>(lhs: RE, op: ComparisonOperatorExpression, rhs: VE): T extends SqlBool ? OrWrapper<DB, TB, SqlBool> : KyselyTypeError<'or() method can only be called on boolean expressions'>;
or<E extends OperandExpression<SqlBool>>(expression: E): T extends SqlBool ? OrWrapper<DB, TB, SqlBool> : KyselyTypeError<'or() method can only be called on boolean expressions'>;
/**
* Combines `this` and another expression using `AND`.
*
* Also see {@link ExpressionBuilder.and}
*
* ### Examples
*
* ```ts
* const result = await db.selectFrom('person')
* .selectAll()
* .where(eb => eb('first_name', '=', 'Jennifer')
* .and('last_name', '=', 'Aniston')
* .and('age', '>', 40)
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select *
* from "person"
* where (
* "first_name" = $1
* and "last_name" = $2
* and "age" > $3
* )
* ```
*
* You can also pass any expression as the only argument to
* this method:
*
* ```ts
* const result = await db.selectFrom('person')
* .selectAll()
* .where(eb => eb('first_name', '=', 'Jennifer')
* .and(eb('first_name', '=', 'Sylvester').or('last_name', '=', 'Stallone'))
* .and(eb.exists(
* eb.selectFrom('pet')
* .select('id')
* .whereRef('pet.owner_id', '=', 'person.id')
* ))
* )
* .execute()
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select *
* from "person"
* where (
* "first_name" = $1
* and ("first_name" = $2 or "last_name" = $3)
* and exists (
* select "id"
* from "pet"
* where "pet"."owner_id" = "person"."id"
* )
* )
* ```
*/
and<RE extends ReferenceExpression<DB, TB>, VE extends OperandValueExpressionOrList<DB, TB, RE>>(lhs: RE, op: ComparisonOperatorExpression, rhs: VE): T extends SqlBool ? AndWrapper<DB, TB, SqlBool> : KyselyTypeError<'and() method can only be called on boolean expressions'>;
and<E extends OperandExpression<SqlBool>>(expression: E): T extends SqlBool ? AndWrapper<DB, TB, SqlBool> : KyselyTypeError<'and() method can only be called on boolean expressions'>;
/**
* Change the output type of the expression.
*
* This method call doesn't change the SQL in any way. This methods simply
* returns a copy of this `ExpressionWrapper` with a new output type.
*/
$castTo<C>(): ExpressionWrapper<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(): ExpressionWrapper<DB, TB, Exclude<T, 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 AliasedExpressionWrapper<T, A extends string> implements AliasedExpression<T, A> {
#private;
constructor(expr: Expression<T>, alias: A | Expression<unknown>);
/** @private */
/**
* Returns the aliased expression.
*/
get expression(): Expression<T>;
/** @private */
/**
* Returns the alias.
*/
get alias(): A | Expression<unknown>;
/**
* Creates the OperationNode that describes how to compile this expression into SQL.
*/
toOperationNode(): AliasNode;
}
export declare class OrWrapper<DB, TB extends keyof DB, T extends SqlBool> implements AliasableExpression<T> {
#private;
constructor(node: OrNode);
/** @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(): T | 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')
* .or('first_name', '=', 'Sylvester')
* .as('is_jennifer_or_sylvester')
* )
* .executeTakeFirstOrThrow()
*
* // `is_jennifer_or_sylvester: SqlBool` field exists in the result type.
* console.log(result.is_jennifer_or_sylvester)
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "first_name" = $1 or "first_name" = $2 as "is_jennifer_or_sylvester"
* from "person"
* ```
*/
as<A extends string>(alias: A): AliasedExpression<T, 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<T, A>;
/**
* Combines `this` and another expression using `OR`.
*
* See {@link ExpressionWrapper.or} for examples.
*/
or<RE extends ReferenceExpression<DB, TB>, VE extends OperandValueExpressionOrList<DB, TB, RE>>(lhs: RE, op: ComparisonOperatorExpression, rhs: VE): OrWrapper<DB, TB, T>;
or<E extends OperandExpression<SqlBool>>(expression: E): OrWrapper<DB, TB, T>;
/**
* Change the output type of the expression.
*
* This method call doesn't change the SQL in any way. This methods simply
* returns a copy of this `OrWrapper` with a new output type.
*/
$castTo<C extends SqlBool>(): OrWrapper<DB, TB, C>;
/**
* 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(): ParensNode;
}
export declare class AndWrapper<DB, TB extends keyof DB, T extends SqlBool> implements AliasableExpression<T> {
#private;
constructor(node: AndNode);
/** @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(): T | 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')
* .and('last_name', '=', 'Aniston')
* .as('is_jennifer_aniston')
* )
* .executeTakeFirstOrThrow()
*
* // `is_jennifer_aniston: SqlBool` field exists in the result type.
* console.log(result.is_jennifer_aniston)
* ```
*
* The generated SQL (PostgreSQL):
*
* ```sql
* select "first_name" = $1 and "first_name" = $2 as "is_jennifer_aniston"
* from "person"
* ```
*/
as<A extends string>(alias: A): AliasedExpression<T, 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<T, A>;
/**
* Combines `this` and another expression using `AND`.
*
* See {@link ExpressionWrapper.and} for examples.
*/
and<RE extends ReferenceExpression<DB, TB>, VE extends OperandValueExpressionOrList<DB, TB, RE>>(lhs: RE, op: ComparisonOperatorExpression, rhs: VE): AndWrapper<DB, TB, T>;
and<E extends OperandExpression<SqlBool>>(expression: E): AndWrapper<DB, TB, T>;
/**
* Change the output type of the expression.
*
* This method call doesn't change the SQL in any way. This methods simply
* returns a copy of this `AndWrapper` with a new output type.
*/
$castTo<C extends SqlBool>(): AndWrapper<DB, TB, C>;
/**
* 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(): ParensNode;
}

View File

@@ -0,0 +1,128 @@
/// <reference types="./expression-wrapper.d.ts" />
import { AliasNode } from '../operation-node/alias-node.js';
import { AndNode } from '../operation-node/and-node.js';
import { IdentifierNode } from '../operation-node/identifier-node.js';
import { isOperationNodeSource } from '../operation-node/operation-node-source.js';
import { OrNode } from '../operation-node/or-node.js';
import { ParensNode } from '../operation-node/parens-node.js';
import { parseValueBinaryOperationOrExpression, } from '../parser/binary-operation-parser.js';
export class ExpressionWrapper {
#node;
constructor(node) {
this.#node = node;
}
/** @private */
get expressionType() {
return undefined;
}
as(alias) {
return new AliasedExpressionWrapper(this, alias);
}
or(...args) {
return new OrWrapper(OrNode.create(this.#node, parseValueBinaryOperationOrExpression(args)));
}
and(...args) {
return new AndWrapper(AndNode.create(this.#node, parseValueBinaryOperationOrExpression(args)));
}
/**
* Change the output type of the expression.
*
* This method call doesn't change the SQL in any way. This methods simply
* returns a copy of this `ExpressionWrapper` with a new output type.
*/
$castTo() {
return new ExpressionWrapper(this.#node);
}
/**
* 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 ExpressionWrapper(this.#node);
}
toOperationNode() {
return this.#node;
}
}
export class AliasedExpressionWrapper {
#expr;
#alias;
constructor(expr, alias) {
this.#expr = expr;
this.#alias = alias;
}
/** @private */
get expression() {
return this.#expr;
}
/** @private */
get alias() {
return this.#alias;
}
toOperationNode() {
return AliasNode.create(this.#expr.toOperationNode(), isOperationNodeSource(this.#alias)
? this.#alias.toOperationNode()
: IdentifierNode.create(this.#alias));
}
}
export class OrWrapper {
#node;
constructor(node) {
this.#node = node;
}
/** @private */
get expressionType() {
return undefined;
}
as(alias) {
return new AliasedExpressionWrapper(this, alias);
}
or(...args) {
return new OrWrapper(OrNode.create(this.#node, parseValueBinaryOperationOrExpression(args)));
}
/**
* Change the output type of the expression.
*
* This method call doesn't change the SQL in any way. This methods simply
* returns a copy of this `OrWrapper` with a new output type.
*/
$castTo() {
return new OrWrapper(this.#node);
}
toOperationNode() {
return ParensNode.create(this.#node);
}
}
export class AndWrapper {
#node;
constructor(node) {
this.#node = node;
}
/** @private */
get expressionType() {
return undefined;
}
as(alias) {
return new AliasedExpressionWrapper(this, alias);
}
and(...args) {
return new AndWrapper(AndNode.create(this.#node, parseValueBinaryOperationOrExpression(args)));
}
/**
* Change the output type of the expression.
*
* This method call doesn't change the SQL in any way. This methods simply
* returns a copy of this `AndWrapper` with a new output type.
*/
$castTo() {
return new AndWrapper(this.#node);
}
toOperationNode() {
return ParensNode.create(this.#node);
}
}

198
node_modules/kysely/dist/esm/expression/expression.d.ts generated vendored Normal file
View File

@@ -0,0 +1,198 @@
import type { AliasNode } from '../operation-node/alias-node.js';
import { type OperationNodeSource } from '../operation-node/operation-node-source.js';
import type { OperationNode } from '../operation-node/operation-node.js';
/**
* `Expression` represents an arbitrary SQL expression with a type.
*
* Most Kysely methods accept instances of `Expression` and most classes like `SelectQueryBuilder`
* and the return value of the {@link sql} template tag implement it.
*
* ### Examples
*
* ```ts
* import { type Expression, sql } from 'kysely'
*
* const exp1: Expression<string> = sql<string>`CONCAT('hello', ' ', 'world')`
* const exp2: Expression<{ first_name: string }> = db.selectFrom('person').select('first_name')
* ```
*
* You can implement the `Expression` interface to create your own type-safe utilities for Kysely.
*/
export interface Expression<T> extends OperationNodeSource {
/**
* 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(): T | undefined;
/**
* 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;
}
/**
* An expression with an `as` method.
*/
export interface AliasableExpression<T> extends Expression<T> {
/**
* 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: A): AliasedExpression<T, A>;
as<A extends string>(alias: Expression<any>): AliasedExpression<T, A>;
}
/**
* A type that holds an expression and an alias for it.
*
* `AliasedExpression<T, A>` can be used in places where, in addition to the value type `T`, you
* also need a name `A` for that value. For example anything you can pass into the `select` method
* needs to implement an `AliasedExpression<T, A>`. `A` becomes the name of the selected expression
* in the result and `T` becomes its type.
*
* ### Examples
*
* ```ts
* import {
* AliasNode,
* type AliasedExpression,
* type Expression,
* IdentifierNode
* } from 'kysely'
*
* class SomeAliasedExpression<T, A extends string> implements AliasedExpression<T, A> {
* #expression: Expression<T>
* #alias: A
*
* constructor(expression: Expression<T>, alias: A) {
* this.#expression = expression
* this.#alias = alias
* }
*
* get expression(): Expression<T> {
* return this.#expression
* }
*
* get alias(): A {
* return this.#alias
* }
*
* toOperationNode(): AliasNode {
* return AliasNode.create(
* this.#expression.toOperationNode(),
* IdentifierNode.create(this.#alias)
* )
* }
* }
* ```
*/
export interface AliasedExpression<T, A extends string> extends OperationNodeSource {
/**
* Returns the aliased expression.
*/
get expression(): Expression<T>;
/**
* Returns the alias.
*/
get alias(): A | Expression<unknown>;
/**
* Creates the OperationNode that describes how to compile this expression into SQL.
*/
toOperationNode(): AliasNode;
}
export declare function isExpression(obj: unknown): obj is Expression<any>;
export declare function isAliasedExpression(obj: unknown): obj is AliasedExpression<any, any>;

12
node_modules/kysely/dist/esm/expression/expression.js generated vendored Normal file
View File

@@ -0,0 +1,12 @@
/// <reference types="./expression.d.ts" />
import { isOperationNodeSource, } from '../operation-node/operation-node-source.js';
import { isObject, isString } from '../util/object-utils.js';
export function isExpression(obj) {
return isObject(obj) && 'expressionType' in obj && isOperationNodeSource(obj);
}
export function isAliasedExpression(obj) {
return (isObject(obj) &&
'expression' in obj &&
isString(obj.alias) &&
isOperationNodeSource(obj));
}